[U-Boot] [PATCH v4 0/5] qspi: qspi support for mx6sxsabresd

This patch set is to support qspi for mx6sxsabresd board.
To mx6sxsabresd Revb board, 32M flash is used, but in header file, CONFIG_SPI_FLASH_BAR is not defined, and we still use SZ_16M. The LUT initialization qspi_set_lut function uses 32BIT addr, however CONFIG_SPI_FLASH_BAR and 24BIT addr should be used to access bigger than 16MB size flash, and BRRD/BRWR should also be supported. Future patches will fix this.
Since flash opcodes are not recommended to use in driver level, use QSPI_CMD_xx to replace OPCODE_xx. It is qspi controller's feature to program LUT with QSPI_CMD_xx which same value with OPCODE_xx.
Since Revb board's qspi flash support 4K erase, 4K erase is added in driver.
Peng Fan (5): QuadSPI: use QSPI_CMD_xx instead of flash opcodes QuadSPI: use correct amba_base arm:mx6sx add QSPI support imx:qspi add 4K erase support imx:mx6sxsabresd add qspi support
arch/arm/cpu/armv7/mx6/clock.c | 50 ++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 1 + arch/arm/include/asm/arch-mx6/imx-regs.h | 12 +-- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 ++++++++ drivers/spi/fsl_qspi.c | 137 +++++++++++++++++++--------- include/configs/mx6sxsabresd.h | 12 +++ 6 files changed, 205 insertions(+), 47 deletions(-)

Use QSPI_CMD_xx instead of flash opcodes
Signed-off-by: Peng Fan Peng.Fan@freescale.com ---
Changes v4: None
Changes v3: Use QSPI_CMD_XX instead of flash opcodes. To fsl qspi controller, the LUT should be pre programmed with QSPI CMD.
Changes v2: None
drivers/spi/fsl_qspi.c | 64 ++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index ba20bef..61490c9 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -29,19 +29,19 @@ #define SEQID_PP 6 #define SEQID_RDID 7
-/* Flash opcodes */ -#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_CHIP_ERASE 0xc7 /* Erase whole flash chip */ -#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ -#define OPCODE_RDID 0x9f /* Read JEDEC ID */ - -/* 4-byte address opcodes - used on Spansion and some Macronix flashes */ -#define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ -#define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ -#define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ +/* QSPI CMD */ +#define QSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */ +#define QSPI_CMD_RDSR 0x05 /* Read status register */ +#define QSPI_CMD_WREN 0x06 /* Write enable */ +#define QSPI_CMD_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define QSPI_CMD_CHIP_ERASE 0xc7 /* Erase whole flash chip */ +#define QSPI_CMD_SE 0xd8 /* Sector erase (usually 64KiB) */ +#define QSPI_CMD_RDID 0x9f /* Read JEDEC ID */ + +/* 4-byte address QSPI CMD - used on Spansion and some Macronix flashes */ +#define QSPI_CMD_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ +#define QSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */ +#define QSPI_CMD_SE_4B 0xdc /* Sector erase (usually 64KiB) */
#ifdef CONFIG_SYS_FSL_QSPI_LE #define qspi_read32 in_le32 @@ -94,7 +94,7 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
/* Write Enable */ lut_base = SEQID_WREN * 4; - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_WREN) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_WREN) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD)); qspi_write32(®s->lut[lut_base + 1], 0); qspi_write32(®s->lut[lut_base + 2], 0); @@ -103,13 +103,15 @@ static void qspi_set_lut(struct fsl_qspi *qspi) /* Fast Read */ lut_base = SEQID_FAST_READ * 4; if (FSL_QSPI_FLASH_SIZE <= SZ_16M) - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_FAST_READ) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); else - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_FAST_READ_4B) | - PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | - PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + qspi_write32(®s->lut[lut_base], + OPRND0(QSPI_CMD_FAST_READ_4B) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | + OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | + INSTR1(LUT_ADDR)); qspi_write32(®s->lut[lut_base + 1], OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) | OPRND1(RX_BUFFER_SIZE) | PAD1(LUT_PAD1) | INSTR1(LUT_READ)); @@ -118,7 +120,7 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
/* Read Status */ lut_base = SEQID_RDSR * 4; - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_RDSR) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_RDSR) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | INSTR1(LUT_READ)); qspi_write32(®s->lut[lut_base + 1], 0); @@ -128,11 +130,11 @@ static void qspi_set_lut(struct fsl_qspi *qspi) /* Erase a sector */ lut_base = SEQID_SE * 4; if (FSL_QSPI_FLASH_SIZE <= SZ_16M) - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_SE) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_SE) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); else - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_SE_4B) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_SE_4B) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); qspi_write32(®s->lut[lut_base + 1], 0); @@ -141,7 +143,7 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
/* Erase the whole chip */ lut_base = SEQID_CHIP_ERASE * 4; - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_CHIP_ERASE) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_CHIP_ERASE) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD)); qspi_write32(®s->lut[lut_base + 1], 0); qspi_write32(®s->lut[lut_base + 2], 0); @@ -150,11 +152,11 @@ static void qspi_set_lut(struct fsl_qspi *qspi) /* Page Program */ lut_base = SEQID_PP * 4; if (FSL_QSPI_FLASH_SIZE <= SZ_16M) - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_PP) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_PP) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); else - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_PP_4B) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_PP_4B) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); qspi_write32(®s->lut[lut_base + 1], OPRND0(TX_BUFFER_SIZE) | @@ -164,7 +166,7 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
/* READ ID */ lut_base = SEQID_RDID * 4; - qspi_write32(®s->lut[lut_base], OPRND0(OPCODE_RDID) | + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_RDID) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(8) | PAD1(LUT_PAD1) | INSTR1(LUT_READ)); qspi_write32(®s->lut[lut_base + 1], 0); @@ -454,22 +456,22 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, return 0; }
- if (qspi->cur_seqid == OPCODE_FAST_READ) { + if (qspi->cur_seqid == QSPI_CMD_FAST_READ) { qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK; - } else if (qspi->cur_seqid == OPCODE_SE) { + } else if (qspi->cur_seqid == QSPI_CMD_SE) { qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK; qspi_op_se(qspi); - } else if (qspi->cur_seqid == OPCODE_PP) { + } else if (qspi->cur_seqid == QSPI_CMD_PP) { pp_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK; } }
if (din) { - if (qspi->cur_seqid == OPCODE_FAST_READ) + if (qspi->cur_seqid == QSPI_CMD_FAST_READ) qspi_op_read(qspi, din, bytes); - else if (qspi->cur_seqid == OPCODE_RDID) + else if (qspi->cur_seqid == QSPI_CMD_RDID) qspi_op_rdid(qspi, din, bytes); - else if (qspi->cur_seqid == OPCODE_RDSR) + else if (qspi->cur_seqid == QSPI_CMD_RDSR) qspi_op_rdsr(qspi, din); }

According cs, use different amba_base to choose the corresponding flash devices. If not, `sf probe 1:0` and `sf probe 1:1` will choose the same flash device, but not different flash devices.
Signed-off-by: Peng Fan Peng.Fan@freescale.com ---
Changes v4: None
Changes v3: None
Changes v2: None
drivers/spi/fsl_qspi.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 61490c9..eae2f3a 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -194,12 +194,22 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (bus >= ARRAY_SIZE(spi_bases)) return NULL;
+ if (cs >= FSL_QSPI_FLASH_NUM) + return NULL; + qspi = spi_alloc_slave(struct fsl_qspi, bus, cs); if (!qspi) return NULL;
qspi->reg_base = spi_bases[bus]; - qspi->amba_base = amba_bases[bus]; + /* + * According cs, use different amba_base to choose the + * corresponding flash devices. + * + * If not, only one flash device is used even if passing + * different cs using `sf probe` + */ + qspi->amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE;
qspi->slave.max_write_size = TX_BUFFER_SIZE;
@@ -212,10 +222,20 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, qspi_write32(®s->mcr, QSPI_MCR_RESERVED_MASK);
total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM; - qspi_write32(®s->sfa1ad, FSL_QSPI_FLASH_SIZE | qspi->amba_base); - qspi_write32(®s->sfa2ad, FSL_QSPI_FLASH_SIZE | qspi->amba_base); - qspi_write32(®s->sfb1ad, total_size | qspi->amba_base); - qspi_write32(®s->sfb2ad, total_size | qspi->amba_base); + /* + * Any read access to non-implemented addresses will provide + * undefined results. + * + * In case single die flash devices, TOP_ADDR_MEMA2 and + * TOP_ADDR_MEMB2 should be initialized/programmed to + * TOP_ADDR_MEMA1 and TOP_ADDR_MEMB1 respectively - in effect, + * setting the size of these devices to 0. This would ensure + * that the complete memory map is assigned to only one flash device. + */ + qspi_write32(®s->sfa1ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]); + qspi_write32(®s->sfa2ad, FSL_QSPI_FLASH_SIZE | amba_bases[bus]); + qspi_write32(®s->sfb1ad, total_size | amba_bases[bus]); + qspi_write32(®s->sfb2ad, total_size | amba_bases[bus]);
qspi_set_lut(qspi);

Add QSPI support for mx6solox.
Signed-off-by: Peng Fan Peng.Fan@freescale.com ---
Changes v4: None
Changes v3: None
Changes v2: Take Fabio's suggestion, split soc code and board code into two patches.
arch/arm/cpu/armv7/mx6/clock.c | 50 ++++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 1 + arch/arm/include/asm/arch-mx6/imx-regs.h | 12 ++++---- drivers/spi/fsl_qspi.c | 19 ++++++++++++ 4 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 93a02ad..a05dca3 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -434,6 +434,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 226a4cd..a6de5ee 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -67,5 +67,6 @@ int enable_spi_clk(unsigned char enable, unsigned spi_num); void enable_ipu_clock(void); int enable_fec_anatop_clock(enum enet_freq freq); void enable_enet_clk(unsigned char enable); +void enable_qspi_clk(int qspi_num); void enable_thermal_clk(void); #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index 5314298..c968600 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -92,10 +92,10 @@ #define AIPS3_END_ADDR 0x022FFFFF #define WEIM_ARB_BASE_ADDR 0x50000000 #define WEIM_ARB_END_ADDR 0x57FFFFFF -#define QSPI1_ARB_BASE_ADDR 0x60000000 -#define QSPI1_ARB_END_ADDR 0x6FFFFFFF -#define QSPI2_ARB_BASE_ADDR 0x70000000 -#define QSPI2_ARB_END_ADDR 0x7FFFFFFF +#define QSPI0_AMBA_BASE 0x60000000 +#define QSPI0_AMBA_END 0x6FFFFFFF +#define QSPI1_AMBA_BASE 0x70000000 +#define QSPI1_AMBA_END 0x7FFFFFFF #else #define SATA_ARB_BASE_ADDR 0x02200000 #define SATA_ARB_END_ADDR 0x02203FFF @@ -262,8 +262,8 @@ #define AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000) #ifdef CONFIG_MX6SX #define SAI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000) -#define QSPI1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000) -#define QSPI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000) +#define QSPI0_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000) +#define QSPI1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000) #else #define MIPI_CSI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000) #define MIPI_DSI_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000) diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index eae2f3a..e9c45de 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
@@ -53,10 +57,16 @@
static unsigned long spi_bases[] = { QSPI0_BASE_ADDR, +#ifdef CONFIG_MX6SX + QSPI1_BASE_ADDR, +#endif };
static unsigned long amba_bases[] = { QSPI0_AMBA_BASE, +#ifdef CONFIG_MX6SX + QSPI1_AMBA_BASE, +#endif };
struct fsl_qspi { @@ -159,8 +169,17 @@ static void qspi_set_lut(struct fsl_qspi *qspi) qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_PP_4B) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#ifdef CONFIG_MX6SX + /* + * To MX6SX, OPRND0(TX_BUFFER_SIZE) can not work correctly. + * So, Use IDATSZ in IPCR to determine the size and here set 0. + */ + 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);

Add 4k erase command support for qspi driver. reuse the 64k erase function, but change the function name from qspi_op_se to qspi_op_erase, since it supports 64k and 4k erase.
Signed-off-by: Peng Fan Peng.Fan@freescale.com ---
Changes v4: New patch in v4. This patch is to support 4k erase.
drivers/spi/fsl_qspi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index e9c45de..d12f420 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -32,12 +32,14 @@ #define SEQID_CHIP_ERASE 5 #define SEQID_PP 6 #define SEQID_RDID 7 +#define SEQID_BE_4K 8
/* QSPI CMD */ #define QSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */ #define QSPI_CMD_RDSR 0x05 /* Read status register */ #define QSPI_CMD_WREN 0x06 /* Write enable */ #define QSPI_CMD_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define QSPI_CMD_BE_4K 0x20 /* 4K erase */ #define QSPI_CMD_CHIP_ERASE 0xc7 /* Erase whole flash chip */ #define QSPI_CMD_SE 0xd8 /* Sector erase (usually 64KiB) */ #define QSPI_CMD_RDID 0x9f /* Read JEDEC ID */ @@ -192,6 +194,12 @@ 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);
+ /* SUB SECTOR 4K ERASE */ + lut_base = SEQID_BE_4K * 4; + qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_BE_4K) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + /* Lock the LUT */ qspi_write32(®s->lutkey, LUT_KEY_VALUE); qspi_write32(®s->lckcr, QSPI_LCKCR_LOCK); @@ -450,7 +458,7 @@ static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf) qspi_write32(®s->mcr, mcr_reg); }
-static void qspi_op_se(struct fsl_qspi *qspi) +static void qspi_op_erase(struct fsl_qspi *qspi) { struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base; u32 mcr_reg; @@ -469,8 +477,13 @@ static void qspi_op_se(struct fsl_qspi *qspi) while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) ;
- qspi_write32(®s->ipcr, - (SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0); + if (qspi->cur_seqid == QSPI_CMD_SE) { + qspi_write32(®s->ipcr, + (SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0); + } else if (qspi->cur_seqid == QSPI_CMD_BE_4K) { + qspi_write32(®s->ipcr, + (SEQID_BE_4K << QSPI_IPCR_SEQID_SHIFT) | 0); + } while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) ;
@@ -497,9 +510,10 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
if (qspi->cur_seqid == QSPI_CMD_FAST_READ) { qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK; - } else if (qspi->cur_seqid == QSPI_CMD_SE) { + } else if ((qspi->cur_seqid == QSPI_CMD_SE) || + (qspi->cur_seqid == QSPI_CMD_BE_4K)) { qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK; - qspi_op_se(qspi); + qspi_op_erase(qspi); } else if (qspi->cur_seqid == QSPI_CMD_PP) { pp_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK; }

Configure the pad setting and enable qspi clock to support qspi flashes access.
Add QSPI related macro in configuration header file.
Signed-off-by: Peng Fan Peng.Fan@freescale.com ---
Changes v4: None
Changes v3: None
Changes v2: Take Fabio's suggestion, split soc code and board code into two patches.
board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 +++++++++++++++++++++++++++++ include/configs/mx6sxsabresd.h | 12 +++++++++ 2 files changed, 52 insertions(+)
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index fd8bc72..5cc58ac 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -371,6 +371,42 @@ int board_mmc_init(bd_t *bis) return 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 */ @@ -380,6 +416,10 @@ int board_init(void) setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); #endif
+#ifdef CONFIG_FSL_QSPI + board_qspi_init(); +#endif + return 0; }
diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h index 61a7a7a..469d250 100644 --- a/include/configs/mx6sxsabresd.h +++ b/include/configs/mx6sxsabresd.h @@ -235,6 +235,18 @@ /* 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 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 31 December 2014 at 08:31, Peng Fan Peng.Fan@freescale.com wrote:
This patch set is to support qspi for mx6sxsabresd board.
To mx6sxsabresd Revb board, 32M flash is used, but in header file, CONFIG_SPI_FLASH_BAR is not defined, and we still use SZ_16M. The LUT initialization qspi_set_lut function uses 32BIT addr, however CONFIG_SPI_FLASH_BAR and 24BIT addr should be used to access bigger than 16MB size flash, and BRRD/BRWR should also be supported. Future patches will fix this.
Please do remember your self, for next patches. of-course I have added this note on "[U-Boot,v4,5/5] imx:mx6sxsabresd add qspi support" commit body.
Since flash opcodes are not recommended to use in driver level, use QSPI_CMD_xx to replace OPCODE_xx. It is qspi controller's feature to program LUT with QSPI_CMD_xx which same value with OPCODE_xx.
Since Revb board's qspi flash support 4K erase, 4K erase is added in driver.
Peng Fan (5): QuadSPI: use QSPI_CMD_xx instead of flash opcodes QuadSPI: use correct amba_base arm:mx6sx add QSPI support imx:qspi add 4K erase support imx:mx6sxsabresd add qspi support
arch/arm/cpu/armv7/mx6/clock.c | 50 ++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 1 + arch/arm/include/asm/arch-mx6/imx-regs.h | 12 +-- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 ++++++++ drivers/spi/fsl_qspi.c | 137 +++++++++++++++++++--------- include/configs/mx6sxsabresd.h | 12 +++ 6 files changed, 205 insertions(+), 47 deletions(-)
-- 1.8.4
Applied to u-boot-spi/master
thanks!

On 12/31/2014 5:35 PM, Jagan Teki wrote:
On 31 December 2014 at 08:31, Peng Fan Peng.Fan@freescale.com wrote:
This patch set is to support qspi for mx6sxsabresd board.
To mx6sxsabresd Revb board, 32M flash is used, but in header file, CONFIG_SPI_FLASH_BAR is not defined, and we still use SZ_16M. The LUT initialization qspi_set_lut function uses 32BIT addr, however CONFIG_SPI_FLASH_BAR and 24BIT addr should be used to access bigger than 16MB size flash, and BRRD/BRWR should also be supported. Future patches will fix this.
Please do remember your self, for next patches. of-course I have added this note on "[U-Boot,v4,5/5] imx:mx6sxsabresd add qspi support" commit body.
Thanks. Actually I am doing the work.
Since flash opcodes are not recommended to use in driver level, use QSPI_CMD_xx to replace OPCODE_xx. It is qspi controller's feature to program LUT with QSPI_CMD_xx which same value with OPCODE_xx.
Since Revb board's qspi flash support 4K erase, 4K erase is added in driver.
Peng Fan (5): QuadSPI: use QSPI_CMD_xx instead of flash opcodes QuadSPI: use correct amba_base arm:mx6sx add QSPI support imx:qspi add 4K erase support imx:mx6sxsabresd add qspi support
arch/arm/cpu/armv7/mx6/clock.c | 50 ++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 1 + arch/arm/include/asm/arch-mx6/imx-regs.h | 12 +-- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 40 ++++++++ drivers/spi/fsl_qspi.c | 137 +++++++++++++++++++--------- include/configs/mx6sxsabresd.h | 12 +++ 6 files changed, 205 insertions(+), 47 deletions(-)
-- 1.8.4
Applied to u-boot-spi/master
thanks!
Regards, Peng.
participants (3)
-
Jagan Teki
-
Peng Fan
-
Peng Fan