]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
spi: zynq: Move qspi MIO detection code into slcr
authorJagannadha Sutradharudu Teki <jagannadha.sutradharudu-teki@xilinx.com>
Thu, 14 Mar 2013 12:29:13 +0000 (17:59 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 14 Mar 2013 14:23:48 +0000 (15:23 +0100)
This patch provides a support for the qspi MIO runtime
detection code through slcr driver.

Now, slcr driver is capable to get the status of specific MIO
pins by taking an @periph name as an argument.

Currently added qspi0, qspi1_cs and qspi1 as @periph names.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
arch/arm/cpu/armv7/zynq/slcr.c
arch/arm/include/asm/arch-zynq/hardware.h
arch/arm/include/asm/arch-zynq/sys_proto.h
drivers/spi/zynq_qspips.c

index a940067c3f101bd8a4b2965f07a2f1afcd017653..0cee614d84f49ff3711ea664dbe7af6da1af01a5 100644 (file)
 #define SLCR_LOCK_MAGIC                0x767B
 #define SLCR_UNLOCK_MAGIC      0xDF0D
 
+#define SLCR_QSPI_ENABLE               0x02
+#define SLCR_QSPI_ENABLE_MASK          0x03
+
+/*
+ * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
+ *
+ * @peri_name: Name of the peripheral for checking MIO status
+ * @get_pins: Pointer to array of get pin for this peripheral
+ * @num_pins: Number of pins for this peripheral
+ * @mask: Mask value
+ * @check_val: Required check value to get the status of  periph
+ */
+struct zynq_slcr_mio_get_status {
+       const char *peri_name;
+       const int *get_pins;
+       int num_pins;
+       u32 mask;
+       u32 check_val;
+};
+
+static const int qspi0_pins[] = {
+       1, 2, 3, 4, 5, 6
+};
+
+static const int qspi1_cs_pin[] = {
+       0
+};
+
+static const int qspi1_pins[] = {
+       9, 10, 11, 12, 13
+};
+
+static const struct zynq_slcr_mio_get_status mio_periphs[] = {
+       {
+               "qspi0",
+               qspi0_pins,
+               ARRAY_SIZE(qspi0_pins),
+               SLCR_QSPI_ENABLE_MASK,
+               SLCR_QSPI_ENABLE,
+       },
+       {
+               "qspi1_cs",
+               qspi1_cs_pin,
+               ARRAY_SIZE(qspi1_cs_pin),
+               SLCR_QSPI_ENABLE_MASK,
+               SLCR_QSPI_ENABLE,
+       },
+       {
+               "qspi1",
+               qspi1_pins,
+               ARRAY_SIZE(qspi1_pins),
+               SLCR_QSPI_ENABLE_MASK,
+               SLCR_QSPI_ENABLE,
+       },
+};
+
 static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
 
 void zynq_slcr_lock(void)
@@ -119,3 +175,33 @@ u32 zynq_slcr_get_boot_mode(void)
        /* Get the bootmode register value */
        return readl(&slcr_base->boot_mode);
 }
+
+/*
+ * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
+ *
+ * @periph: Name of the peripheral
+ *
+ * Returns count to indicate the number of pins configured for the
+ * given @periph.
+ */
+int zynq_slcr_get_mio_pin_status(const char *periph)
+{
+       const struct zynq_slcr_mio_get_status *mio_ptr;
+       int val, i, j;
+       int mio = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
+               if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
+                       mio_ptr = &mio_periphs[i];
+                       for (j = 0; j < mio_ptr->num_pins; j++) {
+                               val = readl(&slcr_base->mio_pin
+                                               [mio_ptr->get_pins[j]]);
+                               if ((val & mio_ptr->mask) == mio_ptr->check_val)
+                                       mio++;
+                       }
+                       break;
+               }
+       }
+
+       return mio;
+}
index d0b6476bc28b41ab2d03729f10f568686804812d..0e8f71740db5936dc5b714a8980175b3a4987b5a 100644 (file)
@@ -50,9 +50,11 @@ struct slcr_regs {
        u32 ddr_urgent; /* 0x600 */
        u32 reserved6[6];
        u32 ddr_urgent_sel; /* 0x61c */
-       u32 reserved7[184];
+       u32 reserved7[56];
+       u32 mio_pin[54]; /* 0x700 - 0x7D4 */
+       u32 reserved8[74];
        u32 lvl_shftr_en; /* 0x900 */
-       u32 reserved8[3];
+       u32 reserved9[3];
        u32 ocm_cfg; /* 0x910 */
 };
 
index 2e3f034381c03b668c6991c83f608dcdcef306b4..fd2ecc5ee0fa1ba385cc9b6bfeec1cf09b294ab1 100644 (file)
@@ -30,5 +30,6 @@ extern void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk);
 extern void zynq_slcr_devcfg_disable(void);
 extern void zynq_slcr_devcfg_enable(void);
 extern u32 zynq_slcr_get_boot_mode(void);
+extern int zynq_slcr_get_mio_pin_status(const char *periph);
 
 #endif /* _SYS_PROTO_H_ */
index 7db501fe6cf99902855947c1d9e37dfd35aeb62f..689793a7c91c7c198d82a63508a913de5eb9c794 100644 (file)
@@ -19,7 +19,7 @@
 #include <ubi_uboot.h>
 #include <spi.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 
 /* QSPI Transmit Data Register */
 #define XQSPIPS_TXD_00_00_OFFSET       0x1C /* Transmit 4-byte inst, WO */
 #define XQSPIPS_QUEUE_RUNNING          1
 
 /* QSPI MIO's count for different connection topologies */
-#define XQSPIPS_MIO_SINGLE             6
-#define XQSPIPS_MIO_DUAL_PARALLEL      6
-#define XQSPIPS_MIO_DUAL_STACKED       7
+#define XQSPIPS_MIO_NUM_QSPI0          6
+#define XQSPIPS_MIO_NUM_QSPI1          5
+#define XQSPIPS_MIO_NUM_QSPI1_CS       1
 
 /* QSPI connections topology */
 enum xqspips_con_topology {
-       MODE_SINGLE = 0,
-       MODE_DUAL_PARALLEL = 1,
-       MODE_DUAL_STACKED = 2,
+       MODE_UNKNOWN = -1,
+       MODE_SINGLE,
+       MODE_DUAL_PARALLEL,
+       MODE_DUAL_STACKED,
 };
 
 /* Definitions of the flash commands - Flash opcodes in ascending order */
@@ -805,45 +806,25 @@ static int xqspips_transfer(struct spi_device *qspi,
  * @regs_base: base address of SLCR
  */
 
-static int xqspips_check_is_dual_flash(void __iomem *regs_base)
+static int xqspips_check_is_dual_flash(void)
 {
-       int is_dual = -1, lower_mio = 0, upper_mio = 0, val;
-       u16 mask = 3, type = 2;
-       u32 mio_pin_index;
-       void *mio_base;
-
-       mio_base = regs_base + 0x700;
-
-       /* checking single QSPI MIO's */
-       val = (u32) readl(mio_base + 4 * 1);
-       if ((val & mask) == type) {
-               lower_mio++;
-               for (mio_pin_index = 2; mio_pin_index < 7; mio_pin_index++) {
-                       val = (u32) readl(mio_base + 4 * mio_pin_index);
-                       if ((val & mask) == type)
-                               lower_mio++;
-               }
-       }
+       int is_dual = MODE_UNKNOWN;
+       int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0;
 
-       /* checking dual QSPI MIO's */
-       val = (u32) readl(mio_base + 4 * 0);
-       if ((val & mask) == type) {
-               lower_mio++;
-               upper_mio++;
-               for (mio_pin_index = 9; mio_pin_index < 14; mio_pin_index++) {
-                       val = (u32) readl(mio_base + 4 * mio_pin_index);
-                       if ((val & mask) == type)
-                               upper_mio++;
-               }
-       }
+       lower_mio =  zynq_slcr_get_mio_pin_status("qspi0");
+       if (lower_mio == XQSPIPS_MIO_NUM_QSPI0)
+               is_dual = MODE_SINGLE;
 
-       if ((lower_mio == XQSPIPS_MIO_DUAL_STACKED) &&
-                       (upper_mio == XQSPIPS_MIO_DUAL_PARALLEL))
-               is_dual = MODE_DUAL_PARALLEL;
-       else if (lower_mio == XQSPIPS_MIO_DUAL_STACKED)
+       upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs");
+       if ((lower_mio == XQSPIPS_MIO_NUM_QSPI0) &&
+                       (upper_mio_cs1 == XQSPIPS_MIO_NUM_QSPI1_CS))
                is_dual = MODE_DUAL_STACKED;
-       else if (lower_mio == XQSPIPS_MIO_SINGLE)
-               is_dual = MODE_SINGLE;
+
+       upper_mio =  zynq_slcr_get_mio_pin_status("qspi1");
+       if ((lower_mio == XQSPIPS_MIO_NUM_QSPI0) &&
+                       (upper_mio_cs1 == XQSPIPS_MIO_NUM_QSPI1_CS) &&
+                       (upper_mio == XQSPIPS_MIO_NUM_QSPI1))
+               is_dual = MODE_DUAL_PARALLEL;
 
        return is_dual;
 }
@@ -985,9 +966,9 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        if (!spi_cs_is_valid(bus, cs))
                return NULL;
 
-       is_dual = xqspips_check_is_dual_flash((void *)XPSS_SYS_CTRL_BASEADDR);
+       is_dual = xqspips_check_is_dual_flash();
 
-       if (is_dual == -1) {
+       if (is_dual == MODE_UNKNOWN) {
                printf("SPI error: No QSPI device detected based"
                                " on MIO settings\n");
                return NULL;