
Hi Haikun,
On 4/1/2015 11:10 AM, Haikun Wang wrote:
Move the Freescale QSPI driver over to driver model.
Signed-off-by: Haikun Wang Haikun.Wang@freescale.com Signed-off-by: Peng Fan Peng.Fan@freescale.com
Changes in v2:
- Fix build fail on mx6sxsabresd_spl issue
- Add configure regmap endian in NO-DM model
Changes in v1: None.
drivers/spi/fsl_qspi.c | 985 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 656 insertions(+), 329 deletions(-)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 5e0b069..868df5f 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -1,5 +1,5 @@ /*
- Copyright 2013-2014 Freescale Semiconductor, Inc.
- Copyright 2013-2015 Freescale Semiconductor, Inc.
- Freescale Quad Serial Peripheral Interface (QSPI) driver
@@ -11,8 +11,12 @@ #include <spi.h> #include <asm/io.h> #include <linux/sizes.h> +#include <dm.h> +#include <errno.h> #include "fsl_qspi.h"
+DECLARE_GLOBAL_DATA_PTR;
- #define RX_BUFFER_SIZE 0x80 #ifdef CONFIG_MX6SX #define TX_BUFFER_SIZE 0x200
@@ -63,35 +67,85 @@ #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 -#define qspi_write32 out_le32 -#elif defined(CONFIG_SYS_FSL_QSPI_BE) -#define qspi_read32 in_be32 -#define qspi_write32 out_be32 -#endif +/* fsl_qspi_platdata flags */ +#define QSPI_FLAG_REGMAP_ENDIAN_BIG (1 << 0)
-static unsigned long spi_bases[] = {
- QSPI0_BASE_ADDR,
-#ifdef CONFIG_MX6SX
- QSPI1_BASE_ADDR,
-#endif -}; +/* default SCK frequency, unit: HZ */ +#define FSL_QSPI_DEFAULT_SCK_FREQ 50000000
-static unsigned long amba_bases[] = {
- QSPI0_AMBA_BASE,
-#ifdef CONFIG_MX6SX
- QSPI1_AMBA_BASE,
+/* QSPI max chipselect signals number */ +#define FSL_QSPI_MAX_CHIPSELECT_NUM 4
+#ifdef CONFIG_DM_SPI +/**
- struct fsl_qspi_platdata - platform data for Freescale QSPI
- @flags: Flags for QSPI QSPI_FLAG_...
- @speed_hz: Default SCK frequency
- @reg_base: Base address of QSPI registers
- @amba_base: Base address of QSPI memory mapping
- @amba_total_size: size of QSPI memory mapping
- @flash_num: Number of active slave devices
- @num_chipselect: Number of QSPI chipselect signals
- */
+struct fsl_qspi_platdata {
- u32 flags;
- u32 speed_hz;
- u32 reg_base;
- u32 amba_base;
- u32 amba_total_size;
- u32 flash_num;
- u32 num_chipselect;
+}; #endif
+/**
- struct fsl_qspi_priv - private data for Freescale QSPI
- @flags: Flags for QSPI QSPI_FLAG_...
- @bus_clk: QSPI input clk frequency
- @speed_hz: Default SCK frequency
- @cur_seqid: current LUT table sequence id
- @sf_addr: flash access offset
- @amba_base: Base address of QSPI memory mapping of every CS
- @amba_total_size: size of QSPI memory mapping
- @cur_amba_base: Base address of QSPI memory mapping of current CS
- @flash_num: Number of active slave devices
- @num_chipselect: Number of QSPI chipselect signals
- @regs: Point to QSPI register structure for I/O access
- */
+struct fsl_qspi_priv {
- u32 flags;
- u32 bus_clk;
- u32 speed_hz;
- u32 cur_seqid;
- u32 sf_addr;
- u32 amba_base[FSL_QSPI_MAX_CHIPSELECT_NUM];
- u32 amba_total_size;
- u32 cur_amba_base;
- u32 flash_num;
- u32 num_chipselect;
- struct fsl_qspi_regs *regs; };
+#ifndef CONFIG_DM_SPI struct fsl_qspi { struct spi_slave slave;
- unsigned long reg_base;
- unsigned long amba_base;
- u32 sf_addr;
- u8 cur_seqid;
- struct fsl_qspi_priv priv; };
+#endif
+static u32 qspi_read32(u32 flags, u32 *addr) +{
- return flags & QSPI_FLAG_REGMAP_ENDIAN_BIG ?
in_be32(addr) : in_le32(addr);
+}
+static void qspi_write32(u32 flags, u32 *addr, u32 val) +{
- flags & QSPI_FLAG_REGMAP_ENDIAN_BIG ?
out_be32(addr, val) : out_le32(addr, val);
+}
/* QSPI support swapping the flash read/write data
- in hardware for LS102xA, but not for VF610 */
@@ -104,131 +158,135 @@ static inline u32 qspi_endian_xchg(u32 data) #endif }
-static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave) -{
- return container_of(slave, struct fsl_qspi, slave);
-}
-static void qspi_set_lut(struct fsl_qspi *qspi) +static void qspi_set_lut(struct fsl_qspi_priv *priv) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
struct fsl_qspi_regs *regs = priv->regs; u32 lut_base;
/* Unlock the LUT */
- qspi_write32(®s->lutkey, LUT_KEY_VALUE);
- qspi_write32(®s->lckcr, QSPI_LCKCR_UNLOCK);
qspi_write32(priv->flags, ®s->lutkey, LUT_KEY_VALUE);
qspi_write32(priv->flags, ®s->lckcr, QSPI_LCKCR_UNLOCK);
/* Write Enable */ lut_base = SEQID_WREN * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_WREN) |
- qspi_write32(priv->flags, ®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);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
/* Fast Read */ lut_base = SEQID_FAST_READ * 4; #ifdef CONFIG_SPI_FLASH_BAR
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_FAST_READ) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
- qspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) |
#else if (FSL_QSPI_FLASH_SIZE <= SZ_16M)INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
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));
qspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
elsePAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
qspi_write32(®s->lut[lut_base],
#endifqspi_write32(priv->flags, ®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));
- qspi_write32(®s->lut[lut_base + 2], 0);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 1],
OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) |
OPRND1(RX_BUFFER_SIZE) | 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);
/* Read Status */ lut_base = SEQID_RDSR * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_RDSR) |
- qspi_write32(priv->flags, ®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);
- qspi_write32(®s->lut[lut_base + 2], 0);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
/* Erase a sector */ lut_base = SEQID_SE * 4; #ifdef CONFIG_SPI_FLASH_BAR
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_SE) |
- qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_SE) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_SE) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
qspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_SE) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
elsePAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
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(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_SE_4B) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
#endifPAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
- qspi_write32(®s->lut[lut_base + 1], 0);
- qspi_write32(®s->lut[lut_base + 2], 0);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
/* Erase the whole chip */ lut_base = SEQID_CHIP_ERASE * 4;
- 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);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_CHIP_ERASE) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
qspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
/* Page Program */ lut_base = SEQID_PP * 4; #ifdef CONFIG_SPI_FLASH_BAR
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_PP) |
- qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_PP) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else if (FSL_QSPI_FLASH_SIZE <= SZ_16M)
qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_PP) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
qspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_PP) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
elsePAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
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(priv->flags, ®s->lut[lut_base],
OPRND0(QSPI_CMD_PP_4B) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
#endif #ifdef CONFIG_MX6SX /*PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
*/
- 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) |
- qspi_write32(priv->flags, ®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));
- qspi_write32(priv->flags, ®s->lut[lut_base + 1],
OPRND0(TX_BUFFER_SIZE) |
#endifPAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
- qspi_write32(®s->lut[lut_base + 2], 0);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
/* READ ID */ lut_base = SEQID_RDID * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_RDID) |
- qspi_write32(priv->flags, ®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);
- qspi_write32(®s->lut[lut_base + 2], 0);
- qspi_write32(®s->lut[lut_base + 3], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
qspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
qspi_write32(priv->flags, ®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) |
- qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_BE_4K) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
@@ -239,28 +297,28 @@ static void qspi_set_lut(struct fsl_qspi *qspi) * initialization. */ lut_base = SEQID_BRRD * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_BRRD) |
qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_BRRD) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | INSTR1(LUT_READ));
lut_base = SEQID_BRWR * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_BRWR) |
qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_BRWR) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | INSTR1(LUT_WRITE));
lut_base = SEQID_RDEAR * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_RDEAR) |
qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_RDEAR) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | INSTR1(LUT_READ));
lut_base = SEQID_WREAR * 4;
- qspi_write32(®s->lut[lut_base], OPRND0(QSPI_CMD_WREAR) |
- qspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(QSPI_CMD_WREAR) | PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | INSTR1(LUT_WRITE)); #endif /* Lock the LUT */
- qspi_write32(®s->lutkey, LUT_KEY_VALUE);
- qspi_write32(®s->lckcr, QSPI_LCKCR_LOCK);
qspi_write32(priv->flags, ®s->lutkey, LUT_KEY_VALUE);
qspi_write32(priv->flags, ®s->lckcr, QSPI_LCKCR_LOCK); }
#if defined(CONFIG_SYS_FSL_QSPI_AHB)
@@ -270,14 +328,14 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
- the wrong data. The spec tells us reset the AHB domain and Serial Flash
- domain at the same time.
*/ -static inline void qspi_ahb_invalid(struct fsl_qspi *q) +static inline void qspi_ahb_invalid(struct fsl_qspi_priv *priv) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)q->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 reg;
- reg = qspi_read32(®s->mcr);
- reg = qspi_read32(priv->flags, ®s->mcr); reg |= QSPI_MCR_SWRSTHD_MASK | QSPI_MCR_SWRSTSD_MASK;
- qspi_write32(®s->mcr, reg);
qspi_write32(priv->flags, ®s->mcr, reg);
/*
- The minimum delay : 1 AHB + 2 SFCK clocks.
@@ -286,46 +344,48 @@ static inline void qspi_ahb_invalid(struct fsl_qspi *q) udelay(1);
reg &= ~(QSPI_MCR_SWRSTHD_MASK | QSPI_MCR_SWRSTSD_MASK);
- qspi_write32(®s->mcr, reg);
qspi_write32(priv->flags, ®s->mcr, reg); }
/* Read out the data from the AHB buffer. */
-static inline void qspi_ahb_read(struct fsl_qspi *q, u8 *rxbuf, int len) +static inline void qspi_ahb_read(struct fsl_qspi_priv *priv, u8 *rxbuf, int len) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)q->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg;
- mcr_reg = qspi_read32(®s->mcr);
- mcr_reg = qspi_read32(priv->flags, ®s->mcr);
- qspi_write32(®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
qspi_write32(priv->flags, ®s->mcr,
QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
/* Read out the data directly from the AHB buffer. */
- memcpy(rxbuf, (u8 *)(q->amba_base + q->sf_addr), len);
- memcpy(rxbuf, (u8 *)(priv->cur_amba_base + priv->sf_addr), len);
- qspi_write32(®s->mcr, mcr_reg);
- qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
-static void qspi_enable_ddr_mode(struct fsl_qspi_regs *regs) +static void qspi_enable_ddr_mode(struct fsl_qspi_priv *priv) { u32 reg, reg2;
- struct fsl_qspi_regs *regs = priv->regs;
- reg = qspi_read32(®s->mcr);
- reg = qspi_read32(priv->flags, ®s->mcr); /* Disable the module */
- qspi_write32(®s->mcr, reg | QSPI_MCR_MDIS_MASK);
qspi_write32(priv->flags, ®s->mcr, reg | QSPI_MCR_MDIS_MASK);
/* Set the Sampling Register for DDR */
- reg2 = qspi_read32(®s->smpr);
- reg2 = qspi_read32(priv->flags, ®s->smpr); reg2 &= ~QSPI_SMPR_DDRSMP_MASK; reg2 |= (2 << QSPI_SMPR_DDRSMP_SHIFT);
- qspi_write32(®s->smpr, reg2);
qspi_write32(priv->flags, ®s->smpr, reg2);
/* Enable the module again (enable the DDR too) */ reg |= QSPI_MCR_DDR_EN_MASK; /* Enable bit 29 for imx6sx */ reg |= (1 << 29);
- qspi_write32(®s->mcr, reg);
qspi_write32(priv->flags, ®s->mcr, reg); }
/*
@@ -341,180 +401,103 @@ static void qspi_enable_ddr_mode(struct fsl_qspi_regs *regs)
- causes the controller to clear the buffer, and use the sequence pointed
- by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
*/ -static void qspi_init_ahb_read(struct fsl_qspi_regs *regs) +static void qspi_init_ahb_read(struct fsl_qspi_priv *priv) {
- struct fsl_qspi_regs *regs = priv->regs;
- /* 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 |
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);
qspi_write32(priv->flags, ®s->buf3cr, QSPI_BUF3CR_ALLMST_MASK | (0x80 << QSPI_BUF3CR_ADATSZ_SHIFT));
/* We only use the buffer3 */
- qspi_write32(®s->buf0ind, 0);
- qspi_write32(®s->buf1ind, 0);
- qspi_write32(®s->buf2ind, 0);
qspi_write32(priv->flags, ®s->buf0ind, 0);
qspi_write32(priv->flags, ®s->buf1ind, 0);
qspi_write32(priv->flags, ®s->buf2ind, 0);
/*
- Set the default lut sequence for AHB Read.
- Parallel mode is disabled.
*/
- qspi_write32(®s->bfgencr,
qspi_write32(priv->flags, ®s->bfgencr, SEQID_FAST_READ << QSPI_BFGENCR_SEQID_SHIFT);
/*Enable DDR Mode*/
- qspi_enable_ddr_mode(regs);
- qspi_enable_ddr_mode(priv); } #endif
-void spi_init() -{
- /* do nothing */
-}
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int mode)
-{
- struct fsl_qspi *qspi;
- struct fsl_qspi_regs *regs;
- u32 smpr_val;
- u32 total_size;
- 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];
- /*
* 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;
- regs = (struct fsl_qspi_regs *)qspi->reg_base;
- qspi_write32(®s->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
- smpr_val = qspi_read32(®s->smpr);
- qspi_write32(®s->smpr, smpr_val & ~(QSPI_SMPR_FSDLY_MASK |
QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK));
- qspi_write32(®s->mcr, QSPI_MCR_RESERVED_MASK);
- total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
- /*
* 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);
- smpr_val = qspi_read32(®s->smpr);
- smpr_val &= ~QSPI_SMPR_DDRSMP_MASK;
- qspi_write32(®s->smpr, smpr_val);
- qspi_write32(®s->mcr, QSPI_MCR_RESERVED_MASK);
-#ifdef CONFIG_SYS_FSL_QSPI_AHB
- qspi_init_ahb_read(regs);
-#endif
- return &qspi->slave;
-}
-void spi_free_slave(struct spi_slave *slave) -{
- struct fsl_qspi *qspi = to_qspi_spi(slave);
- free(qspi);
-}
-int spi_claim_bus(struct spi_slave *slave) -{
- return 0;
-}
- #ifdef CONFIG_SPI_FLASH_BAR /* Bank register read/write, EAR register read/write */
-static void qspi_op_rdbank(struct fsl_qspi *qspi, u8 *rxbuf, u32 len) +static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 reg, mcr_reg, data, seqid;
- mcr_reg = qspi_read32(®s->mcr);
- qspi_write32(®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
- mcr_reg = qspi_read32(priv->flags, ®s->mcr);
- qspi_write32(priv->flags, ®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);
- qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS);
- qspi_write32(®s->sfar, qspi->amba_base);
- qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base);
- if (qspi->cur_seqid == QSPI_CMD_BRRD)
- if (priv->cur_seqid == QSPI_CMD_BRRD) seqid = SEQID_BRRD; else seqid = SEQID_RDEAR;
- qspi_write32(®s->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | len);
qspi_write32(priv->flags, ®s->ipcr,
(seqid << QSPI_IPCR_SEQID_SHIFT) | len);
/* Wait previous command complete */
- while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
while (1) {
reg = qspi_read32(®s->rbsr);
if (reg & QSPI_RBSR_RDBFL_MASK) {reg = qspi_read32(priv->flags, ®s->rbsr);
data = qspi_read32(®s->rbdr[0]);
data = qspi_read32(priv->flags, ®s->rbdr[0]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, len);
qspi_write32(®s->mcr, qspi_read32(®s->mcr) |
qspi_write32(priv->flags, ®s->mcr,
} }qspi_read32(priv->flags, ®s->mcr) | QSPI_MCR_CLR_RXF_MASK); break;
- qspi_write32(®s->mcr, mcr_reg);
- qspi_write32(priv->flags, ®s->mcr, mcr_reg); } #endif
-static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len) +static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, rbsr_reg, data; int i, size;
- 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);
- mcr_reg = qspi_read32(priv->flags, ®s->mcr);
- qspi_write32(priv->flags, ®s->mcr,
QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
- qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS);
- qspi_write32(®s->sfar, qspi->amba_base);
- qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base);
- qspi_write32(®s->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
- while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
qspi_write32(priv->flags, ®s->ipcr,
(SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
i = 0; size = len; while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
rbsr_reg = qspi_read32(®s->rbsr);
if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {rbsr_reg = qspi_read32(priv->flags, ®s->rbsr);
data = qspi_read32(®s->rbdr[i]);
data = qspi_read32(priv->flags, ®s->rbdr[i]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, 4); rxbuf++;
@@ -523,34 +506,36 @@ static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len) } }
- qspi_write32(®s->mcr, mcr_reg);
qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
#ifndef CONFIG_SYS_FSL_QSPI_AHB /* If not use AHB read, read data from ip interface */
-static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len) +static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, data; int i, size; 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);
- mcr_reg = qspi_read32(priv->flags, ®s->mcr);
- qspi_write32(priv->flags, ®s->mcr,
QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
- qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS);
- to_or_from = qspi->sf_addr + qspi->amba_base;
to_or_from = priv->sf_addr + priv->cur_amba_base;
while (len > 0) {
qspi_write32(®s->sfar, to_or_from);
qspi_write32(priv->flags, ®s->sfar, to_or_from);
size = (len > RX_BUFFER_SIZE) ? RX_BUFFER_SIZE : len;
qspi_write32(®s->ipcr,
(SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size);
while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
qspi_write32(priv->flags, ®s->ipcr,
(SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) |
size);
while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
to_or_from += size;
@@ -558,66 +543,69 @@ static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
i = 0; while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
data = qspi_read32(®s->rbdr[i]);
}data = qspi_read32(priv->flags, ®s->rbdr[i]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, 4); rxbuf++; size -= 4; i++;
qspi_write32(®s->mcr, qspi_read32(®s->mcr) |
QSPI_MCR_CLR_RXF_MASK);
qspi_write32(priv->flags, ®s->mcr,
qspi_read32(priv->flags, ®s->mcr) |
}QSPI_MCR_CLR_RXF_MASK);
- qspi_write32(®s->mcr, mcr_reg);
- qspi_write32(priv->flags, ®s->mcr, mcr_reg); } #endif
-static void qspi_op_write(struct fsl_qspi *qspi, u8 *txbuf, u32 len) +static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, data, reg, status_reg, seqid; int i, size, tx_size; u32 to_or_from = 0;
- 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);
mcr_reg = qspi_read32(priv->flags, ®s->mcr);
qspi_write32(priv->flags, ®s->mcr,
QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
qspi_write32(priv->flags, ®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(priv->flags, ®s->ipcr,
(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
while (qspi_read32(priv->flags, ®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)
qspi_write32(priv->flags, ®s->ipcr,
(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
reg = qspi_read32(®s->rbsr);
if (reg & QSPI_RBSR_RDBFL_MASK) {reg = qspi_read32(priv->flags, ®s->rbsr);
status_reg = qspi_read32(®s->rbdr[0]);
}status_reg = qspi_read32(priv->flags, ®s->rbdr[0]); status_reg = qspi_endian_xchg(status_reg);
qspi_write32(®s->mcr,
qspi_read32(®s->mcr) | QSPI_MCR_CLR_RXF_MASK);
qspi_write32(priv->flags, ®s->mcr,
qspi_read32(priv->flags, ®s->mcr) |
QSPI_MCR_CLR_RXF_MASK);
}
/* Default is page programming */ seqid = SEQID_PP; #ifdef CONFIG_SPI_FLASH_BAR
- if (qspi->cur_seqid == QSPI_CMD_BRWR)
- if (priv->cur_seqid == QSPI_CMD_BRWR) seqid = SEQID_BRWR;
- else if (qspi->cur_seqid == QSPI_CMD_WREAR)
- else if (priv->cur_seqid == QSPI_CMD_WREAR) seqid = SEQID_WREAR; #endif
- to_or_from = qspi->sf_addr + qspi->amba_base;
- to_or_from = priv->sf_addr + priv->cur_amba_base;
- qspi_write32(®s->sfar, to_or_from);
qspi_write32(priv->flags, ®s->sfar, to_or_from);
tx_size = (len > TX_BUFFER_SIZE) ? TX_BUFFER_SIZE : len;
@@ -626,7 +614,7 @@ static void qspi_op_write(struct fsl_qspi *qspi, u8 *txbuf, u32 len) for (i = 0; i < size; i++) { memcpy(&data, txbuf, 4); data = qspi_endian_xchg(data);
qspi_write32(®s->tbdr, data);
txbuf += 4; }qspi_write32(priv->flags, ®s->tbdr, data);
@@ -635,146 +623,273 @@ static void qspi_op_write(struct fsl_qspi *qspi, u8 *txbuf, u32 len) data = 0; memcpy(&data, txbuf, size); data = qspi_endian_xchg(data);
qspi_write32(®s->tbdr, data);
}qspi_write32(priv->flags, ®s->tbdr, data);
- qspi_write32(®s->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size);
- while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
- qspi_write32(priv->flags, ®s->ipcr,
(seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size);
- while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
- qspi_write32(®s->mcr, mcr_reg);
- qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
-static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf) +static void qspi_op_rdsr(struct fsl_qspi_priv *priv, u32 *rxbuf) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, reg, data;
- 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);
- mcr_reg = qspi_read32(priv->flags, ®s->mcr);
- qspi_write32(priv->flags, ®s->mcr,
QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
- qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS);
- qspi_write32(®s->sfar, qspi->amba_base);
- qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base);
- qspi_write32(®s->ipcr,
(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
- while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
qspi_write32(priv->flags, ®s->ipcr,
(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
while (1) {
reg = qspi_read32(®s->rbsr);
if (reg & QSPI_RBSR_RDBFL_MASK) {reg = qspi_read32(priv->flags, ®s->rbsr);
data = qspi_read32(®s->rbdr[0]);
data = qspi_read32(priv->flags, ®s->rbdr[0]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, 4);
qspi_write32(®s->mcr, qspi_read32(®s->mcr) |
QSPI_MCR_CLR_RXF_MASK);
qspi_write32(priv->flags, ®s->mcr,
qspi_read32(priv->flags, ®s->mcr) |
} }QSPI_MCR_CLR_RXF_MASK); break;
- qspi_write32(®s->mcr, mcr_reg);
- qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
-static void qspi_op_erase(struct fsl_qspi *qspi) +static void qspi_op_erase(struct fsl_qspi_priv *priv) {
- struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
- struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg; u32 to_or_from = 0;
- 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);
- mcr_reg = qspi_read32(priv->flags, ®s->mcr);
- qspi_write32(priv->flags, ®s->mcr,
QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
- qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS);
- to_or_from = qspi->sf_addr + qspi->amba_base;
- qspi_write32(®s->sfar, to_or_from);
- to_or_from = priv->sf_addr + priv->cur_amba_base;
- qspi_write32(priv->flags, ®s->sfar, to_or_from);
- qspi_write32(®s->ipcr,
(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
- while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
- qspi_write32(priv->flags, ®s->ipcr,
(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
- while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
- if (qspi->cur_seqid == QSPI_CMD_SE) {
qspi_write32(®s->ipcr,
- if (priv->cur_seqid == QSPI_CMD_SE) {
qspi_write32(priv->flags, ®s->ipcr, (SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0);
- } else if (qspi->cur_seqid == QSPI_CMD_BE_4K) {
qspi_write32(®s->ipcr,
- } else if (priv->cur_seqid == QSPI_CMD_BE_4K) {
}qspi_write32(priv->flags, ®s->ipcr, (SEQID_BE_4K << QSPI_IPCR_SEQID_SHIFT) | 0);
- while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK)
- while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ;
- qspi_write32(®s->mcr, mcr_reg);
- qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, +int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen, const void *dout, void *din, unsigned long flags) {
struct fsl_qspi *qspi = to_qspi_spi(slave); u32 bytes = DIV_ROUND_UP(bitlen, 8); static u32 wr_sfaddr; u32 txbuf;
if (dout) { if (flags & SPI_XFER_BEGIN) {
qspi->cur_seqid = *(u8 *)dout;
priv->cur_seqid = *(u8 *)dout; memcpy(&txbuf, dout, 4);
}
if (flags == SPI_XFER_END) {
qspi->sf_addr = wr_sfaddr;
qspi_op_write(qspi, (u8 *)dout, bytes);
priv->sf_addr = wr_sfaddr;
}qspi_op_write(priv, (u8 *)dout, bytes); return 0;
if (qspi->cur_seqid == QSPI_CMD_FAST_READ) {
qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
} 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_erase(qspi);
} else if (qspi->cur_seqid == QSPI_CMD_PP)
if (priv->cur_seqid == QSPI_CMD_FAST_READ) {
priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
} else if ((priv->cur_seqid == QSPI_CMD_SE) ||
(priv->cur_seqid == QSPI_CMD_BE_4K)) {
priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
qspi_op_erase(priv);
} else if (priv->cur_seqid == QSPI_CMD_PP) { wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
} else if ((priv->cur_seqid == QSPI_CMD_BRWR) ||
#ifdef CONFIG_SPI_FLASH_BAR(priv->cur_seqid == QSPI_CMD_WREAR)) {
else if ((qspi->cur_seqid == QSPI_CMD_BRWR) ||
(qspi->cur_seqid == QSPI_CMD_WREAR)) { wr_sfaddr = 0;
#endif}
}
}
if (din) {
if (qspi->cur_seqid == QSPI_CMD_FAST_READ) {
#ifdef CONFIG_SYS_FSL_QSPI_AHBif (priv->cur_seqid == QSPI_CMD_FAST_READ) {
qspi_ahb_read(qspi, din, bytes);
#elseqspi_ahb_read(priv, din, bytes);
qspi_op_read(qspi, din, bytes);
#endifqspi_op_read(priv, din, bytes);
}
else if (qspi->cur_seqid == QSPI_CMD_RDID)
qspi_op_rdid(qspi, din, bytes);
else if (qspi->cur_seqid == QSPI_CMD_RDSR)
qspi_op_rdsr(qspi, din);
} else if (priv->cur_seqid == QSPI_CMD_RDID)
qspi_op_rdid(priv, din, bytes);
else if (priv->cur_seqid == QSPI_CMD_RDSR)
#ifdef CONFIG_SPI_FLASH_BARqspi_op_rdsr(priv, din);
else if ((qspi->cur_seqid == QSPI_CMD_BRRD) ||
(qspi->cur_seqid == QSPI_CMD_RDEAR)) {
qspi->sf_addr = 0;
qspi_op_rdbank(qspi, din, bytes);
else if ((priv->cur_seqid == QSPI_CMD_BRRD) ||
(priv->cur_seqid == QSPI_CMD_RDEAR)) {
priv->sf_addr = 0;
qspi_op_rdbank(priv, din, bytes);
} #endif }
#ifdef CONFIG_SYS_FSL_QSPI_AHB
- if ((qspi->cur_seqid == QSPI_CMD_SE) ||
(qspi->cur_seqid == QSPI_CMD_PP) ||
(qspi->cur_seqid == QSPI_CMD_BE_4K) ||
(qspi->cur_seqid == QSPI_CMD_WREAR) ||
(qspi->cur_seqid == QSPI_CMD_BRWR))
qspi_ahb_invalid(qspi);
- if ((priv->cur_seqid == QSPI_CMD_SE) ||
(priv->cur_seqid == QSPI_CMD_PP) ||
(priv->cur_seqid == QSPI_CMD_BE_4K) ||
(priv->cur_seqid == QSPI_CMD_WREAR) ||
(priv->cur_seqid == QSPI_CMD_BRWR))
qspi_ahb_invalid(priv);
+#endif
- return 0;
+}
+void qspi_module_disable(struct fsl_qspi_priv *priv, u8 disable) +{
- u32 mcr_val;
- mcr_val = qspi_read32(priv->flags, &priv->regs->mcr);
- if (disable)
mcr_val |= QSPI_MCR_MDIS_MASK;
- else
mcr_val &= ~QSPI_MCR_MDIS_MASK;
- qspi_write32(priv->flags, &priv->regs->mcr, mcr_val);
+}
+void qspi_cfg_smpr(struct fsl_qspi_priv *priv, u32 clear_bits, u32 set_bits) +{
- u32 smpr_val;
- smpr_val = qspi_read32(priv->flags, &priv->regs->smpr);
- smpr_val &= ~clear_bits;
- smpr_val |= set_bits;
- qspi_write32(priv->flags, &priv->regs->smpr, smpr_val);
+} +#ifndef CONFIG_DM_SPI +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 +};
+static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave) +{
- return container_of(slave, struct fsl_qspi, slave);
+}
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int mode)
+{
- struct fsl_qspi *qspi;
- struct fsl_qspi_regs *regs;
- u32 total_size;
- 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;
+#ifdef CONFIG_SYS_FSL_QSPI_BE
- qspi->priv.flags |= QSPI_FLAG_REGMAP_ENDIAN_BIG;
+#endif
- regs = (struct fsl_qspi_regs *)spi_bases[bus];
- qspi->priv.regs = regs;
- /*
* 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->priv.cur_amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE;
- qspi->slave.max_write_size = TX_BUFFER_SIZE;
- qspi_write32(qspi->priv.flags, ®s->mcr,
QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
- qspi_cfg_smpr(&qspi->priv,
~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK |
QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0);
- total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
- /*
* 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(qspi->priv.flags, ®s->sfa1ad,
FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
- qspi_write32(qspi->priv.flags, ®s->sfa2ad,
FSL_QSPI_FLASH_SIZE | amba_bases[bus]);
- qspi_write32(qspi->priv.flags, ®s->sfb1ad,
total_size | amba_bases[bus]);
- qspi_write32(qspi->priv.flags, ®s->sfb2ad,
total_size | amba_bases[bus]);
- qspi_set_lut(&qspi->priv);
+#ifdef CONFIG_SYS_FSL_QSPI_AHB
qspi_init_ahb_read(&qspi->priv); #endif
qspi_module_disable(&qspi->priv, 0);
return &qspi->slave;
+}
+void spi_free_slave(struct spi_slave *slave) +{
- struct fsl_qspi *qspi = to_qspi_spi(slave);
- free(qspi);
+}
+int spi_claim_bus(struct spi_slave *slave) +{ return 0; }
@@ -782,3 +897,215 @@ void spi_release_bus(struct spi_slave *slave) { /* Nothing to do */ }
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+{
- struct fsl_qspi *qspi = to_qspi_spi(slave);
- return qspi_xfer(&qspi->priv, bitlen, dout, din, flags);
+}
+void spi_init(void) +{
- /* Nothing to do */
+} +#else +static int fsl_qspi_child_pre_probe(struct udevice *dev) +{
- struct spi_slave *slave = dev_get_parentdata(dev);
- slave->max_write_size = TX_BUFFER_SIZE;
- return 0;
+}
+static int fsl_qspi_probe(struct udevice *bus) +{
- u32 total_size;
- struct fsl_qspi_platdata *plat = dev_get_platdata(bus);
- struct fsl_qspi_priv *priv = dev_get_priv(bus);
- struct dm_spi_bus *dm_spi_bus;
- dm_spi_bus = bus->uclass_priv;
- dm_spi_bus->max_hz = plat->speed_hz;
- priv->regs = (struct fsl_qspi_regs *)plat->reg_base;
- priv->flags = plat->flags;
- priv->speed_hz = plat->speed_hz;
- priv->amba_base[0] = plat->amba_base;
- priv->amba_total_size = plat->amba_total_size;
- priv->flash_num = plat->flash_num;
- priv->num_chipselect = plat->num_chipselect;
- qspi_write32(priv->flags, &priv->regs->mcr,
QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
- qspi_cfg_smpr(priv, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK |
QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0);
- total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
- /*
* 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(priv->flags, &priv->regs->sfa1ad,
FSL_QSPI_FLASH_SIZE | priv->amba_base[0]);
- qspi_write32(priv->flags, &priv->regs->sfa2ad,
FSL_QSPI_FLASH_SIZE | priv->amba_base[0]);
- qspi_write32(priv->flags, &priv->regs->sfb1ad,
total_size | priv->amba_base[0]);
- qspi_write32(priv->flags, &priv->regs->sfb2ad,
total_size | priv->amba_base[0]);
- qspi_set_lut(priv);
+#ifdef CONFIG_SYS_FSL_QSPI_AHB
- qspi_init_ahb_read(priv);
+#endif
- qspi_module_disable(priv, 0);
- return 0;
+}
+static int fsl_qspi_ofdata_to_platdata(struct udevice *bus) +{
- struct reg_data {
u32 addr;
u32 size;
- } regs_data[2];
- struct fsl_qspi_platdata *plat = bus->platdata;
- const void *blob = gd->fdt_blob;
- int node = bus->of_offset;
- int ret, flash_num = 0, subnode;
- if (fdtdec_get_bool(blob, node, "big-endian"))
plat->flags |= QSPI_FLAG_REGMAP_ENDIAN_BIG;
- ret = fdtdec_get_int_array(blob, node, "reg", (u32 *)regs_data,
sizeof(regs_data)/sizeof(u32));
- if (ret) {
debug("Error: can't get base addresses (ret = %d)!\n", ret);
return -ENOMEM;
- }
- /* Count flash numbers */
- fdt_for_each_subnode(blob, subnode, node)
++flash_num;
- if (flash_num == 0) {
debug("Error: Missing flashes!\n");
return -ENODEV;
- }
- plat->speed_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
FSL_QSPI_DEFAULT_SCK_FREQ);
- plat->num_chipselect = fdtdec_get_int(blob, node, "num-cs",
FSL_QSPI_MAX_CHIPSELECT_NUM);
- plat->reg_base = regs_data[0].addr;
- plat->amba_base = regs_data[1].addr;
- plat->amba_total_size = regs_data[1].size;
- plat->flash_num = flash_num;
- debug("%s: regs=<0x%x> <0x%x, 0x%x>, max-frequency=%d, endianess=%s\n",
__func__,
plat->reg_base,
plat->amba_base,
plat->amba_total_size,
plat->speed_hz,
plat->flags & QSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le"
);
- return 0;
+}
+static int fsl_qspi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+{
- struct fsl_qspi_priv *priv;
- struct udevice *bus;
- bus = dev->parent;
- priv = dev_get_priv(bus);
- return qspi_xfer(priv, bitlen, dout, din, flags);
+}
+static int fsl_qspi_claim_bus(struct udevice *dev) +{
- struct fsl_qspi_priv *priv;
- struct udevice *bus;
- struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
- bus = dev->parent;
- priv = dev_get_priv(bus);
- priv->cur_amba_base =
priv->amba_base[0] + FSL_QSPI_FLASH_SIZE * slave_plat->cs;
- qspi_module_disable(priv, 0);
- return 0;
+}
+static int fsl_qspi_release_bus(struct udevice *dev) +{
- struct fsl_qspi_priv *priv;
- struct udevice *bus;
- bus = dev->parent;
- priv = dev_get_priv(bus);
- qspi_module_disable(priv, 1);
- return 0;
+}
+static int fsl_qspi_set_speed(struct udevice *bus, uint speed) +{
- /* Nothing to do */
- return 0;
+}
+static int fsl_qspi_set_mode(struct udevice *bus, uint mode) +{
- /* Nothing to do */
- return 0;
+}
+static const struct dm_spi_ops fsl_qspi_ops = {
- .claim_bus = fsl_qspi_claim_bus,
- .release_bus = fsl_qspi_release_bus,
- .xfer = fsl_qspi_xfer,
- .set_speed = fsl_qspi_set_speed,
- .set_mode = fsl_qspi_set_mode,
+};
+static const struct udevice_id fsl_qspi_ids[] = {
- { .compatible = "fsl,vf610-qspi" },
- { .compatible = "fsl,imx6sx-qspi" },
- { }
+};
+U_BOOT_DRIVER(fsl_qspi) = {
- .name = "fsl_qspi",
- .id = UCLASS_SPI,
- .of_match = fsl_qspi_ids,
- .ops = &fsl_qspi_ops,
- .ofdata_to_platdata = fsl_qspi_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct fsl_qspi_platdata),
- .priv_auto_alloc_size = sizeof(struct fsl_qspi_priv),
- .probe = fsl_qspi_probe,
- .child_pre_probe = fsl_qspi_child_pre_probe,
+}; +#endif
Testey-by: Peng Fan Peng.Fan@freescale.com
Regards, Peng.