From: Jagannadha Sutradharudu Teki Date: Thu, 14 Mar 2013 12:29:13 +0000 (+0530) Subject: spi: zynq: Move qspi MIO detection code into slcr X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=feac0114fa2783aaaa3b5513a47262e461e354d1;p=thirdparty%2Fu-boot.git spi: zynq: Move qspi MIO detection code into slcr 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 Signed-off-by: Michal Simek --- diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c index a940067c3f1..0cee614d84f 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/cpu/armv7/zynq/slcr.c @@ -28,6 +28,62 @@ #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; +} diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h index d0b6476bc28..0e8f71740db 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -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 */ }; diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/include/asm/arch-zynq/sys_proto.h index 2e3f034381c..fd2ecc5ee0f 100644 --- a/arch/arm/include/asm/arch-zynq/sys_proto.h +++ b/arch/arm/include/asm/arch-zynq/sys_proto.h @@ -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_ */ diff --git a/drivers/spi/zynq_qspips.c b/drivers/spi/zynq_qspips.c index 7db501fe6cf..689793a7c91 100644 --- a/drivers/spi/zynq_qspips.c +++ b/drivers/spi/zynq_qspips.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include /* QSPI Transmit Data Register */ #define XQSPIPS_TXD_00_00_OFFSET 0x1C /* Transmit 4-byte inst, WO */ @@ -82,15 +82,16 @@ #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;