diff options
Diffstat (limited to 'drivers/spi/fsl_qspi.c')
-rw-r--r-- | drivers/spi/fsl_qspi.c | 985 |
1 files changed, 656 insertions, 329 deletions
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 5e0b069274..868df5f121 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) | + 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_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) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); else - qspi_write32(®s->lut[lut_base], + qspi_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)); #endif - 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) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); else - 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) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #endif - 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) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); else - 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) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #endif #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) | + 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) | + PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); #endif - 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); + reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { - 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); + rbsr_reg = qspi_read32(priv->flags, ®s->rbsr); if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) { - 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); + reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { - 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); + qspi_write32(priv->flags, ®s->tbdr, data); txbuf += 4; } @@ -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); + reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { - 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) || + (priv->cur_seqid == QSPI_CMD_WREAR)) { #ifdef CONFIG_SPI_FLASH_BAR - 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) { + if (priv->cur_seqid == QSPI_CMD_FAST_READ) { #ifdef CONFIG_SYS_FSL_QSPI_AHB - qspi_ahb_read(qspi, din, bytes); + qspi_ahb_read(priv, din, bytes); #else - qspi_op_read(qspi, din, bytes); + qspi_op_read(priv, din, bytes); #endif - } - 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) + qspi_op_rdsr(priv, din); #ifdef CONFIG_SPI_FLASH_BAR - 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 |