From 3249c6c9e183704bdc0d00b5bc2e0761569f159f Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 13 Aug 2019 03:57:56 -0700 Subject: [PATCH] MLK-22437-2 spi: fsl_qspi: Use driver data for different SOCs Add the driver data for each compatible string of different SOC. So we can remove the SOC config and use driver data instead. Signed-off-by: Ye Li Reviewed-by: Peng Fan --- drivers/spi/fsl_qspi.c | 159 +++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 53 deletions(-) diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 547c030062..2fe32903a4 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -19,14 +19,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define RX_BUFFER_SIZE 0x80 -#if defined(CONFIG_MX6SX) || defined(CONFIG_MX6UL) || \ - defined(CONFIG_MX6ULL) || defined(CONFIG_MX7D) || defined(CONFIG_IMX8M) -#define TX_BUFFER_SIZE 0x200 -#else -#define TX_BUFFER_SIZE 0x40 -#endif - #define OFFSET_BITS_MASK GENMASK(23, 0) #define FLASH_STATUS_WEL 0x02 @@ -88,6 +80,28 @@ DECLARE_GLOBAL_DATA_PTR; /* QSPI max chipselect signals number */ #define FSL_QSPI_MAX_CHIPSELECT_NUM 4 +/* Controller needs driver to swap endian */ +#define QUADSPI_QUIRK_SWAP_ENDIAN BIT(0) + +#define QUADSPI_QUIRK_BYTE_ORDER_LE BIT(1) + + +enum fsl_qspi_devtype { + FSL_QUADSPI_VYBRID, + FSL_QUADSPI_IMX6SX, + FSL_QUADSPI_IMX7D, + FSL_QUADSPI_IMX6UL, + FSL_QUADSPI_IMX7ULP, +}; + +struct fsl_qspi_devtype_data { + enum fsl_qspi_devtype devtype; + u32 rxfifo; + u32 txfifo; + u32 ahb_buf_size; + u32 driver_data; +}; + /** * struct fsl_qspi_platdata - platform data for Freescale QSPI * @@ -136,8 +150,48 @@ struct fsl_qspi_priv { u32 flash_num; u32 num_chipselect; struct fsl_qspi_regs *regs; + struct fsl_qspi_devtype_data *devtype_data; +}; + +static const struct fsl_qspi_devtype_data vybrid_data = { + .devtype = FSL_QUADSPI_VYBRID, + .rxfifo = 128, + .txfifo = 64, + .ahb_buf_size = 1024, + .driver_data = QUADSPI_QUIRK_SWAP_ENDIAN, +}; + +static const struct fsl_qspi_devtype_data imx6sx_data = { + .devtype = FSL_QUADSPI_IMX6SX, + .rxfifo = 128, + .txfifo = 512, + .ahb_buf_size = 1024, + .driver_data = QUADSPI_QUIRK_BYTE_ORDER_LE, +}; + +static const struct fsl_qspi_devtype_data imx7d_data = { + .devtype = FSL_QUADSPI_IMX7D, + .rxfifo = 128, + .txfifo = 512, + .ahb_buf_size = 1024, + .driver_data = QUADSPI_QUIRK_BYTE_ORDER_LE, +}; + +static const struct fsl_qspi_devtype_data imx6ul_data = { + .devtype = FSL_QUADSPI_IMX6UL, + .rxfifo = 128, + .txfifo = 512, + .ahb_buf_size = 1024, + .driver_data = QUADSPI_QUIRK_BYTE_ORDER_LE, }; +static const struct fsl_qspi_devtype_data imx7ulp_data = { + .devtype = FSL_QUADSPI_IMX7ULP, + .rxfifo = 64, + .txfifo = 64, + .ahb_buf_size = 128, + .driver_data = QUADSPI_QUIRK_BYTE_ORDER_LE, +}; static u32 qspi_read32(u32 flags, u32 *addr) { @@ -176,13 +230,12 @@ static inline int is_controller_busy(const struct fsl_qspi_priv *priv) /* QSPI support swapping the flash read/write data * in hardware for LS102xA, but not for VF610 */ -static inline u32 qspi_endian_xchg(u32 data) +static inline u32 qspi_endian_xchg(struct fsl_qspi_priv *priv, u32 data) { -#ifdef CONFIG_VF610 - return swab32(data); -#else - return data; -#endif + if (priv->devtype_data->driver_data & QUADSPI_QUIRK_SWAP_ENDIAN) + return swab32(data); + else + return data; } static void qspi_set_lut(struct fsl_qspi_priv *priv) @@ -224,7 +277,7 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv) #endif qspi_write32(priv->flags, ®s->lut[lut_base + 1], OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) | - OPRND1(RX_BUFFER_SIZE) | PAD1(LUT_PAD1) | + OPRND1(priv->devtype_data->rxfifo) | PAD1(LUT_PAD1) | INSTR1(LUT_READ)); qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); @@ -296,19 +349,11 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv) INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #endif -#if defined(CONFIG_MX6SX) || defined(CONFIG_MX6UL) || \ - defined(CONFIG_MX6ULL) || defined(CONFIG_MX7D) || defined(CONFIG_IMX8M) /* - * To MX6SX, OPRND0(TX_BUFFER_SIZE) can not work correctly. - * So, Use IDATSZ in IPCR to determine the size and here set 0. + * Use IDATSZ in IPCR to determine the size and here set 0. */ qspi_write32(priv->flags, ®s->lut[lut_base + 1], OPRND0(0) | PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); -#else - qspi_write32(priv->flags, ®s->lut[lut_base + 1], - OPRND0(TX_BUFFER_SIZE) | - PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); -#endif qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); @@ -450,7 +495,6 @@ static void qspi_enable_ddr_mode(struct fsl_qspi_priv *priv) reg |= QSPI_MCR_DDR_EN_MASK; /* Enable bit 29 for imx6sx */ reg |= BIT(29); - qspi_write32(priv->flags, ®s->mcr, reg); /* Enable the TDH to 1 for i.mx6ul and mx7d, it is reserved on other platforms */ @@ -481,13 +525,8 @@ static void qspi_init_ahb_read(struct fsl_qspi_priv *priv) qspi_write32(priv->flags, ®s->buf0cr, QSPI_BUFXCR_INVALID_MSTRID); qspi_write32(priv->flags, ®s->buf1cr, QSPI_BUFXCR_INVALID_MSTRID); qspi_write32(priv->flags, ®s->buf2cr, QSPI_BUFXCR_INVALID_MSTRID); -#ifdef CONFIG_MX7ULP - qspi_write32(priv->flags, ®s->buf3cr, QSPI_BUF3CR_ALLMST_MASK | - (0x10 << QSPI_BUF3CR_ADATSZ_SHIFT)); -#else qspi_write32(priv->flags, ®s->buf3cr, QSPI_BUF3CR_ALLMST_MASK | - (0x80 << QSPI_BUF3CR_ADATSZ_SHIFT)); -#endif + ((priv->devtype_data->ahb_buf_size >> 3) << QSPI_BUF3CR_ADATSZ_SHIFT)); /* We only use the buffer3 */ qspi_write32(priv->flags, ®s->buf0ind, 0); @@ -539,7 +578,7 @@ static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len) reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[0]); - data = qspi_endian_xchg(data); + data = qspi_endian_xchg(priv, data); memcpy(rxbuf, &data, len); qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | @@ -572,13 +611,13 @@ static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) ; i = 0; - while ((RX_BUFFER_SIZE >= len) && (len > 0)) { + while ((priv->devtype_data->rxfifo >= len) && (len > 0)) { WATCHDOG_RESET(); rbsr_reg = qspi_read32(priv->flags, ®s->rbsr); if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[i]); - data = qspi_endian_xchg(data); + data = qspi_endian_xchg(priv, data); size = (len < 4) ? len : 4; memcpy(rxbuf, &data, size); len -= size; @@ -617,8 +656,8 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) qspi_write32(priv->flags, ®s->sfar, to_or_from); - size = (len > RX_BUFFER_SIZE) ? - RX_BUFFER_SIZE : len; + size = (len > priv->devtype_data->rxfifo) ? + priv->devtype_data->rxfifo : len; qspi_write32(priv->flags, ®s->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | @@ -630,9 +669,9 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) len -= size; i = 0; - while ((RX_BUFFER_SIZE >= size) && (size > 0)) { + while ((priv->devtype_data->rxfifo >= size) && (size > 0)) { data = qspi_read32(priv->flags, ®s->rbdr[i]); - data = qspi_endian_xchg(data); + data = qspi_endian_xchg(priv, data); if (size < 4) memcpy(rxbuf, &data, size); else @@ -662,7 +701,7 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); - if (TX_BUFFER_SIZE <= 256) { + if (priv->devtype_data->txfifo <= 256) { status_reg = 0; do { WATCHDOG_RESET(); @@ -675,7 +714,7 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { status_reg = qspi_read32(priv->flags, ®s->rbdr[0]); - status_reg = qspi_endian_xchg(status_reg); + status_reg = qspi_endian_xchg(priv, status_reg); } qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | @@ -700,7 +739,7 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { status_reg = qspi_read32(priv->flags, ®s->rbdr[0]); - status_reg = qspi_endian_xchg(status_reg); + status_reg = qspi_endian_xchg(priv, status_reg); } qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | @@ -722,8 +761,8 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) qspi_write32(priv->flags, ®s->sfar, to_or_from); - tx_size = (len > TX_BUFFER_SIZE) ? - TX_BUFFER_SIZE : len; + tx_size = (len > priv->devtype_data->txfifo) ? + priv->devtype_data->txfifo : len; size = tx_size / 16; /* @@ -734,7 +773,7 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) size++; for (i = 0; i < size * 4; i++) { memcpy(&data, txbuf, 4); - data = qspi_endian_xchg(data); + data = qspi_endian_xchg(priv, data); qspi_write32(priv->flags, ®s->tbdr, data); txbuf += 4; } @@ -771,7 +810,7 @@ static void qspi_op_rdsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len) reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[0]); - data = qspi_endian_xchg(data); + data = qspi_endian_xchg(priv, data); memcpy(rxbuf, &data, len); qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | @@ -807,7 +846,7 @@ static void qspi_op_rdfsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len) reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[0]); - data = qspi_endian_xchg(data); + data = qspi_endian_xchg(priv, data); memcpy(rxbuf, &data, len); qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | @@ -961,8 +1000,9 @@ void qspi_cfg_smpr(struct fsl_qspi_priv *priv, u32 clear_bits, u32 set_bits) static int fsl_qspi_child_pre_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); + struct fsl_qspi_priv *priv = dev_get_priv(dev_get_parent(dev)); - slave->max_write_size = TX_BUFFER_SIZE; + slave->max_write_size = priv->devtype_data->txfifo; return 0; } @@ -1001,6 +1041,19 @@ static int fsl_qspi_probe(struct udevice *bus) priv->flash_num = plat->flash_num; priv->num_chipselect = plat->num_chipselect; + priv->devtype_data = (struct fsl_qspi_devtype_data *)dev_get_driver_data(bus); + if (!priv->devtype_data) { + printf("ERROR : No devtype_data found\n"); + return -ENODEV; + } + + debug("devtype=%d, txfifo=%d, rxfifo=%d, ahb=%d, data=0x%x\n", + priv->devtype_data->devtype, + priv->devtype_data->txfifo, + priv->devtype_data->rxfifo, + priv->devtype_data->ahb_buf_size, + priv->devtype_data->driver_data); + /* make sure controller is not busy anywhere */ ret = is_controller_busy(priv); @@ -1012,7 +1065,7 @@ static int fsl_qspi_probe(struct udevice *bus) mcr_val = qspi_read32(priv->flags, &priv->regs->mcr); /* Set endianness to LE for i.mx */ - if (IS_ENABLED(CONFIG_MX6) || IS_ENABLED(CONFIG_MX7) || IS_ENABLED(CONFIG_MX7ULP)) + if (priv->devtype_data->driver_data & QUADSPI_QUIRK_BYTE_ORDER_LE) mcr_val = QSPI_MCR_END_CFD_LE; qspi_write32(priv->flags, &priv->regs->mcr, @@ -1213,11 +1266,11 @@ static const struct dm_spi_ops fsl_qspi_ops = { }; static const struct udevice_id fsl_qspi_ids[] = { - { .compatible = "fsl,vf610-qspi" }, - { .compatible = "fsl,imx6sx-qspi" }, - { .compatible = "fsl,imx6ul-qspi" }, - { .compatible = "fsl,imx7d-qspi" }, - { .compatible = "fsl,imx7ulp-qspi" }, + { .compatible = "fsl,vf610-qspi", .data = (ulong)&vybrid_data }, + { .compatible = "fsl,imx6sx-qspi", .data = (ulong)&imx6sx_data }, + { .compatible = "fsl,imx6ul-qspi", .data = (ulong)&imx6ul_data }, + { .compatible = "fsl,imx7d-qspi", .data = (ulong)&imx7d_data }, + { .compatible = "fsl,imx7ulp-qspi", .data = (ulong)&imx7ulp_data }, { } }; -- 2.17.1