[U-Boot] [PATCH 0/3] Add QSPI support for mx6sxsabresd board

From: Peng Fan van.freenix@gmail.com
This patch set is to support QSPI for mx6sxsabresd board. And register read/write is implmented. AHB read is also supported to improve flash read performance.
All the three patches have been tested on mx6sxsabresd board.
Peng Fan (3): ARM:MX6SX Add QuadSPI support for mx6sxsabresd QSPI: Enable write device registers QSPI: Enable QSPI AHB read for MX6SX
arch/arm/cpu/armv7/mx6/clock.c | 50 ++++++++ arch/arm/include/asm/arch-mx6/clock.h | 3 + board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 ++++++ drivers/spi/fsl_qspi.c | 188 +++++++++++++++++++++++++++- drivers/spi/fsl_qspi.h | 11 ++ include/configs/mx6sxsabresd.h | 14 +++ 6 files changed, 303 insertions(+), 3 deletions(-)

From: Peng Fan van.freenix@gmail.com
Add QuadSPI support for mx6sxsabresd board.
There are two 16MB S25FL128S flashes on board. They are connected to QSPI2 interface. i.MX6SX supports two QuadSPI interfaces, QSPI1/2. The two flash devices are connected to A1/B1 of QSPI2.
Signed-off-by: Peng Fan van.freenix@gmail.com --- arch/arm/cpu/armv7/mx6/clock.c | 50 +++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 3 ++ board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 +++++++++++++++++++++++ drivers/spi/fsl_qspi.c | 30 +++++++++++++++++ include/configs/mx6sxsabresd.h | 14 ++++++++ 5 files changed, 137 insertions(+)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 820b8d5..8caa61d 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -340,6 +340,56 @@ static u32 get_mmdc_ch0_clk(void) } #endif
+#ifdef CONFIG_MX6SX +/* qspi_num can be from 0 - 1 */ +void enable_qspi_clk(int qspi_num) +{ + u32 reg = 0; + /* Enable QuadSPI clock */ + switch (qspi_num) { + case 0: + /* disable the clock gate */ + clrbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_QSPI1_MASK); + + /* set 50M : (50 = 396 / 2 / 4) */ + reg = readl(&imx_ccm->cscmr1); + reg &= ~(MXC_CCM_CSCMR1_QSPI1_PODF_MASK | + MXC_CCM_CSCMR1_QSPI1_CLK_SEL_MASK); + reg |= ((1 << MXC_CCM_CSCMR1_QSPI1_PODF_OFFSET) | + (2 << MXC_CCM_CSCMR1_QSPI1_CLK_SEL_OFFSET)); + writel(reg, &imx_ccm->cscmr1); + + /* enable the clock gate */ + setbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_QSPI1_MASK); + break; + case 1: + /* + * disable the clock gate + * QSPI2 and GPMI_BCH_INPUT_GPMI_IO share the same clock gate, + * disable both of them. + */ + clrbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK | + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK); + + /* set 50M : (50 = 396 / 2 / 4) */ + reg = readl(&imx_ccm->cs2cdr); + reg &= ~(MXC_CCM_CS2CDR_QSPI2_CLK_PODF_MASK | + MXC_CCM_CS2CDR_QSPI2_CLK_PRED_MASK | + MXC_CCM_CS2CDR_QSPI2_CLK_SEL_MASK); + reg |= (MXC_CCM_CS2CDR_QSPI2_CLK_PRED(0x1) | + MXC_CCM_CS2CDR_QSPI2_CLK_SEL(0x3)); + writel(reg, &imx_ccm->cs2cdr); + + /*enable the clock gate*/ + setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK | + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK); + break; + default: + break; + } +} +#endif + #ifdef CONFIG_FEC_MXC int enable_fec_anatop_clock(enum enet_freq freq) { diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 339c789..9d0ba7a 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -60,4 +60,7 @@ int enable_i2c_clk(unsigned char enable, unsigned i2c_num); int enable_spi_clk(unsigned char enable, unsigned spi_num); void enable_ipu_clock(void); int enable_fec_anatop_clock(enum enet_freq freq); +#ifdef CONFIG_MX6SX +void enable_qspi_clk(int qspi_num); +#endif #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index 5eaec1b..f9cad5a 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -272,11 +272,51 @@ int board_mmc_init(bd_t *bis) return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); }
+#ifdef CONFIG_FSL_QSPI + +#define QSPI_PAD_CTRL1 \ + (PAD_CTL_SRE_FAST | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_40ohm) + +static iomux_v3_cfg_t const quadspi_pads[] = { + MX6_PAD_NAND_WP_B__QSPI2_A_DATA_0 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_READY_B__QSPI2_A_DATA_1 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_CE0_B__QSPI2_A_DATA_2 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_CE1_B__QSPI2_A_DATA_3 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_ALE__QSPI2_A_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_CLE__QSPI2_A_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_DATA07__QSPI2_A_DQS | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_DATA01__QSPI2_B_DATA_0 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_DATA00__QSPI2_B_DATA_1 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_WE_B__QSPI2_B_DATA_2 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_RE_B__QSPI2_B_DATA_3 | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_DATA03__QSPI2_B_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_DATA02__QSPI2_B_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL1), + MX6_PAD_NAND_DATA05__QSPI2_B_DQS | MUX_PAD_CTRL(QSPI_PAD_CTRL1), +}; + +int board_qspi_init(void) +{ + /* Set the iomux */ + imx_iomux_v3_setup_multiple_pads(quadspi_pads, + ARRAY_SIZE(quadspi_pads)); + + /* Set the clock */ + enable_qspi_clk(1); + + return 0; +} +#endif + int board_init(void) { /* Address of boot parameters */ gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+#ifdef CONFIG_FSL_QSPI + board_qspi_init(); +#endif + return 0; }
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index ba20bef..7e8d07e 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -14,7 +14,11 @@ #include "fsl_qspi.h"
#define RX_BUFFER_SIZE 0x80 +#ifdef CONFIG_MX6SX +#define TX_BUFFER_SIZE 0x200 +#else #define TX_BUFFER_SIZE 0x40 +#endif
#define OFFSET_BITS_MASK 0x00ffffff
@@ -52,11 +56,19 @@ #endif
static unsigned long spi_bases[] = { +#ifdef CONFIG_MX6SX + CONFIG_QSPI_BASE, +#else QSPI0_BASE_ADDR, +#endif };
static unsigned long amba_bases[] = { +#ifdef CONFIG_MX6SX + CONFIG_QSPI_MEMMAP_BASE, +#else QSPI0_AMBA_BASE, +#endif };
struct fsl_qspi { @@ -157,8 +169,14 @@ static void qspi_set_lut(struct fsl_qspi *qspi) qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_PP_4B) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#ifdef CONFIG_MX6SX + /* Use IDATSZ in IPCR to determine the size */ + qspi_write32(®s->lut[lut_base + 1], OPRND0(0) | + PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); +#else qspi_write32(®s->lut[lut_base + 1], OPRND0(TX_BUFFER_SIZE) | PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); +#endif qspi_write32(®s->lut[lut_base + 2], 0); qspi_write32(®s->lut[lut_base + 3], 0);
@@ -191,6 +209,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (bus >= ARRAY_SIZE(spi_bases)) return NULL; +#ifdef CONFIG_MX6SX + if (cs > 1) + return NULL; +#endif
qspi = spi_alloc_slave(struct fsl_qspi, bus, cs); if (!qspi) @@ -215,6 +237,14 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, qspi_write32(®s->sfb1ad, total_size | qspi->amba_base); qspi_write32(®s->sfb2ad, total_size | qspi->amba_base);
+#ifdef CONFIG_MX6SX + /* + * According to cs, change the amba_base to choose the flashes + * bus:cs 0:0--A1, 0:1--B1 + */ + qspi->amba_base = qspi->amba_base + cs * FSL_QSPI_FLASH_SIZE; +#endif + qspi_set_lut(qspi);
smpr_val = qspi_read32(®s->smpr); diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h index 1eda65e..00031ec 100644 --- a/include/configs/mx6sxsabresd.h +++ b/include/configs/mx6sxsabresd.h @@ -201,6 +201,20 @@ /* FLASH and environment organization */ #define CONFIG_SYS_NO_FLASH
+#define CONFIG_FSL_QSPI + +#ifdef CONFIG_FSL_QSPI +#define CONFIG_CMD_SF +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_SPANSION +#define CONFIG_SPI_FLASH_STMICRO +#define CONFIG_SYS_FSL_QSPI_LE +#define CONFIG_QSPI_BASE QSPI2_BASE_ADDR +#define CONFIG_QSPI_MEMMAP_BASE QSPI2_ARB_BASE_ADDR +#define FSL_QSPI_FLASH_SIZE SZ_16M +#define FSL_QSPI_FLASH_NUM 2 +#endif + #define CONFIG_ENV_OFFSET (6 * SZ_64K) #define CONFIG_ENV_SIZE SZ_8K #define CONFIG_ENV_IS_IN_MMC

On Wed, Sep 10, 2014 at 3:16 AM, Peng Fan Peng.Fan@freescale.com wrote:
From: Peng Fan van.freenix@gmail.com
Add QuadSPI support for mx6sxsabresd board.
There are two 16MB S25FL128S flashes on board. They are connected to QSPI2 interface. i.MX6SX supports two QuadSPI interfaces, QSPI1/2. The two flash devices are connected to A1/B1 of QSPI2.
Signed-off-by: Peng Fan van.freenix@gmail.com
arch/arm/cpu/armv7/mx6/clock.c | 50 +++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 3 ++ board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 +++++++++++++++++++++++ drivers/spi/fsl_qspi.c | 30 +++++++++++++++++ include/configs/mx6sxsabresd.h | 14 ++++++++
I would split this in two patches: one that adds qspi support for the mx6solox SoC and another one that adds qspi support to the mx6sxsabresd board.

On 09/10/2014 08:40 PM, Fabio Estevam wrote:
On Wed, Sep 10, 2014 at 3:16 AM, Peng Fan Peng.Fan@freescale.com wrote:
From: Peng Fan van.freenix@gmail.com
Add QuadSPI support for mx6sxsabresd board.
There are two 16MB S25FL128S flashes on board. They are connected to QSPI2 interface. i.MX6SX supports two QuadSPI interfaces, QSPI1/2. The two flash devices are connected to A1/B1 of QSPI2.
Signed-off-by: Peng Fan van.freenix@gmail.com
arch/arm/cpu/armv7/mx6/clock.c | 50 +++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 3 ++ board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 +++++++++++++++++++++++ drivers/spi/fsl_qspi.c | 30 +++++++++++++++++ include/configs/mx6sxsabresd.h | 14 ++++++++
I would split this in two patches: one that adds qspi support for the mx6solox SoC and another one that adds qspi support to the mx6sxsabresd board.
ok. I'll correct this. Thanks for reviewing.
Regards, Peng.
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

From: Peng Fan van.freenix@gmail.com
Add qspi_op_wrr to support status and configuration register write in flash devices.
Signed-off-by: Peng Fan van.freenix@gmail.com --- drivers/spi/fsl_qspi.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 7e8d07e..b1d75e7 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -32,12 +32,16 @@ #define SEQID_CHIP_ERASE 5 #define SEQID_PP 6 #define SEQID_RDID 7 +#define SEQID_WRR 8 +#define SEQID_RDCR 9
/* Flash opcodes */ +#define OPCODE_WRR 0x01 /* Write status/config register */ #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ #define OPCODE_RDSR 0x05 /* Read status register */ #define OPCODE_WREN 0x06 /* Write enable */ #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define OPCODE_RDCR 0x35 /* Read configuration register */ #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ #define OPCODE_RDID 0x9f /* Read JEDEC ID */ @@ -189,6 +193,18 @@ static void qspi_set_lut(struct fsl_qspi *qspi) qspi_write32(®s->lut[lut_base + 2], 0); qspi_write32(®s->lut[lut_base + 3], 0);
+ /* Write Register */ + lut_base = SEQID_WRR * 4; + qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_WRR) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(LUT_WRITE) | + PAD1(LUT_PAD1) | INSTR1(0x2)); + + /* Read Configuration Register */ + lut_base = SEQID_RDCR * 4; + qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_RDCR) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(LUT_READ) | + PAD1(LUT_PAD1) | INSTR1(0x1)); + /* Lock the LUT */ qspi_write32(®s->lutkey, LUT_KEY_VALUE); qspi_write32(®s->lckcr, QSPI_LCKCR_LOCK); @@ -352,6 +368,55 @@ static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len) qspi_write32(®s->mcr, mcr_reg); }
+static void qspi_op_wrr(struct fsl_qspi *qspi, u8 *txbuf, u32 len) +{ + struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base; + u32 mcr_reg, data, reg, status_reg; + u32 to_or_from; + + mcr_reg = qspi_read32(®s->mcr); + qspi_write32(®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | + QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + qspi_write32(®s->rbct, QSPI_RBCT_RXBRD_USEIPS); + + status_reg = 0; + while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) { + qspi_write32(®s->ipcr, + (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0); + while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) + ; + + qspi_write32(®s->ipcr, + (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1); + while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) + ; + + reg = qspi_read32(®s->rbsr); + if (reg & QSPI_RBSR_RDBFL_MASK) { + status_reg = qspi_read32(®s->rbdr[0]); + status_reg = qspi_endian_xchg(status_reg); + } + qspi_write32(®s->mcr, + qspi_read32(®s->mcr) | QSPI_MCR_CLR_RXF_MASK); + } + + to_or_from = qspi->amba_base; + qspi_write32(®s->sfar, to_or_from); + + /* The max len is 2 for OPCODE_WRR */ + data = 0; + memcpy(&data, txbuf, len); + data = qspi_endian_xchg(data); + qspi_write32(®s->tbdr, data); + + qspi_write32(®s->ipcr, + (SEQID_WRR << QSPI_IPCR_SEQID_SHIFT) | len); + while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) + ; + + qspi_write32(®s->mcr, mcr_reg); +} + static void qspi_op_pp(struct fsl_qspi *qspi, u32 *txbuf, u32 len) { struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base; @@ -476,11 +541,17 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
if (dout) { memcpy(&txbuf, dout, 4); - qspi->cur_seqid = *(u8 *)dout; + /* extract cmd when SPI_XFER_BEGIN is set */ + if (flags & SPI_XFER_BEGIN) + qspi->cur_seqid = *(u8 *)dout;
if (flags == SPI_XFER_END) { - qspi->sf_addr = pp_sfaddr; - qspi_op_pp(qspi, (u32 *)dout, bytes); + if (qspi->cur_seqid == OPCODE_WRR) { + qspi_op_wrr(qspi, (u8 *)dout, bytes); + } else if (qspi->cur_seqid == OPCODE_PP) { + qspi->sf_addr = pp_sfaddr; + qspi_op_pp(qspi, (u32 *)dout, bytes); + } return 0; }

From: Peng Fan van.freenix@gmail.com
There are two different ways to read out the data from the flash: the "IP Command Read" and the "AHB Command Read".
The IC guy suggests we use the "AHB Command Read" which is faster then the "IP Command Read". (What's more is that there is a bug in the "IP Command Read" in the Vybrid.)
After we set up the registers for the "AHB Command Read", we can use the memcpy to read the data directly. A "missed" access to the buffer causes the controller to clear the buffer, and use the sequence pointed by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
Signed-off-by: Peng Fan van.freenix@gmail.com --- drivers/spi/fsl_qspi.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/spi/fsl_qspi.h | 11 +++++++ 2 files changed, 92 insertions(+)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index b1d75e7..95b36f0 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -215,6 +215,52 @@ void spi_init() /* do nothing */ }
+#ifdef CONFIG_MX6SX +static void qspi_ahb_read(struct fsl_qspi *qspi, u8 *rxbuf, u32 len) +{ + struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base; + u32 mcr_reg; + u32 to_or_from; + + to_or_from = qspi->sf_addr + qspi->amba_base; + + mcr_reg = qspi_read32(®s->mcr); + qspi_write32(®s->mcr, QSPI_MCR_CLR_RXF_MASK | + QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | + QSPI_MCR_END_CFD_LE_64); + + /* Read out the data directly from the AHB buffer.*/ + memcpy(rxbuf, (u8 *)to_or_from, len); + + qspi_write32(®s->mcr, mcr_reg); +} + +/* + * If we have changed the content of the flash by writing or erasing, + * we need to invalidate the AHB buffer. If we do not do so, we may read out + * the wrong data. The spec tells us reset the AHB domain and Serial Flash + * domain at the same time. + */ +static inline void qspi_invalid_buf(struct fsl_qspi *qspi) +{ + struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base; + u32 mcr_reg; + + mcr_reg = qspi_read32(®s->mcr); + mcr_reg |= QSPI_MCR_SWRSTHD_MASK | QSPI_MCR_SWRSTSD_MASK; + qspi_write32(®s->mcr, mcr_reg); + + /* + * The minimum delay : 1 AHB + 2 SFCK clocks. + * Delay 1 us is enough. + */ + udelay(1); + + mcr_reg &= ~(QSPI_MCR_SWRSTHD_MASK | QSPI_MCR_SWRSTSD_MASK); + qspi_write32(®s->mcr, mcr_reg); +} +#endif + struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { @@ -266,9 +312,30 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, smpr_val = qspi_read32(®s->smpr); smpr_val &= ~QSPI_SMPR_DDRSMP_MASK; qspi_write32(®s->smpr, smpr_val); + +#ifdef CONFIG_MX6SX + qspi_write32(®s->mcr, QSPI_MCR_RESERVED_MASK | + QSPI_MCR_END_CFD_LE << QSPI_MCR_END_CFD_SHIFT); +#else qspi_write32(®s->mcr, QSPI_MCR_RESERVED_MASK); +#endif
+#ifdef CONFIG_MX6SX + /* AHB configuration for access buffer 0/1/2 */ + qspi_write32(®s->buf0cr, QSPI_BUFXCR_INVALID_MSTRID); + qspi_write32(®s->buf1cr, QSPI_BUFXCR_INVALID_MSTRID); + qspi_write32(®s->buf2cr, QSPI_BUFXCR_INVALID_MSTRID); + qspi_write32(®s->buf3cr, QSPI_BUF3CR_ALLMST_MASK | + (0x80 << QSPI_BUF3CR_ADATSZ_SHIFT)); + + qspi_write32(®s->buf0ind, 0); + qspi_write32(®s->buf1ind, 0); + qspi_write32(®s->buf2ind, 0); + + seq_id = SEQID_FAST_READ; +#else seq_id = 0; +#endif reg_val = qspi_read32(®s->bfgencr); reg_val &= ~QSPI_BFGENCR_SEQID_MASK; reg_val |= (seq_id << QSPI_BFGENCR_SEQID_SHIFT); @@ -324,6 +391,7 @@ static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len) qspi_write32(®s->mcr, mcr_reg); }
+#ifndef CONFIG_MX6SX static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len) { struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base; @@ -367,6 +435,7 @@ static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
qspi_write32(®s->mcr, mcr_reg); } +#endif
static void qspi_op_wrr(struct fsl_qspi *qspi, u8 *txbuf, u32 len) { @@ -470,6 +539,10 @@ static void qspi_op_pp(struct fsl_qspi *qspi, u32 *txbuf, u32 len) ;
qspi_write32(®s->mcr, mcr_reg); + +#ifdef CONFIG_MX6SX + qspi_invalid_buf(qspi); +#endif }
static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf) @@ -529,6 +602,10 @@ static void qspi_op_se(struct fsl_qspi *qspi) ;
qspi_write32(®s->mcr, mcr_reg); + +#ifdef CONFIG_MX6SX + qspi_invalid_buf(qspi); +#endif }
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, @@ -567,7 +644,11 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
if (din) { if (qspi->cur_seqid == OPCODE_FAST_READ) +#ifdef CONFIG_MX6SX + qspi_ahb_read(qspi, din, bytes); +#else qspi_op_read(qspi, din, bytes); +#endif else if (qspi->cur_seqid == OPCODE_RDID) qspi_op_rdid(qspi, din, bytes); else if (qspi->cur_seqid == OPCODE_RDSR) diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h index db400e6..80c5ac9 100644 --- a/drivers/spi/fsl_qspi.h +++ b/drivers/spi/fsl_qspi.h @@ -56,9 +56,14 @@ struct fsl_qspi_regs { #define QSPI_IPCR_SEQID_SHIFT 24 #define QSPI_IPCR_SEQID_MASK (0xf << QSPI_IPCR_SEQID_SHIFT)
+#define QSPI_MCR_SWRSTSD_SHIFT 0 +#define QSPI_MCR_SWRSTSD_MASK (1 << QSPI_MCR_SWRSTSD_SHIFT) +#define QSPI_MCR_SWRSTHD_SHIFT 1 +#define QSPI_MCR_SWRSTHD_MASK (1 << QSPI_MCR_SWRSTHD_SHIFT) #define QSPI_MCR_END_CFD_SHIFT 2 #define QSPI_MCR_END_CFD_MASK (3 << QSPI_MCR_END_CFD_SHIFT) #define QSPI_MCR_END_CFD_LE (1 << QSPI_MCR_END_CFD_SHIFT) +#define QSPI_MCR_END_CFD_LE_64 (3 << QSPI_MCR_END_CFD_SHIFT) #define QSPI_MCR_DDR_EN_SHIFT 7 #define QSPI_MCR_DDR_EN_MASK (1 << QSPI_MCR_DDR_EN_SHIFT) #define QSPI_MCR_CLR_RXF_SHIFT 10 @@ -79,6 +84,12 @@ struct fsl_qspi_regs { #define QSPI_SMPR_DDRSMP_SHIFT 16 #define QSPI_SMPR_DDRSMP_MASK (7 << QSPI_SMPR_DDRSMP_SHIFT)
+#define QSPI_BUFXCR_INVALID_MSTRID 0xe +#define QSPI_BUF3CR_ALLMST_SHIFT 31 +#define QSPI_BUF3CR_ALLMST_MASK (1 << QSPI_BUF3CR_ALLMST_SHIFT) +#define QSPI_BUF3CR_ADATSZ_SHIFT 8 +#define QSPI_BUF3CR_ADATSZ_MASK (0xff << QSPI_BUF3CR_ADATSZ_SHIFT) + #define QSPI_BFGENCR_SEQID_SHIFT 12 #define QSPI_BFGENCR_SEQID_MASK (0xf << QSPI_BFGENCR_SEQID_SHIFT) #define QSPI_BFGENCR_PAR_EN_SHIFT 16
participants (3)
-
Fabio Estevam
-
Peng Fan
-
Peng Fan