dm: spi: Convert Freescale QSPI driver to driver model
PATCH v2 1/1 dm: spi: Convert Freescale QSPI driver to driver model
Move the Freescale QSPI driver over to driver model.
---
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(-)
drivers/spi/fsl_qspi.c +656 -329
@@ -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
Signature · 1 line
2.1.0.27.g96db324
PATCH v2 1/1 dm: spi: Convert Freescale QSPI driver to driver model
Hi Haikun,
Quoted 1,381 lines · Haikun Wang
Move the Freescale QSPI driver over to driver model.
Signed-off-by Haikun Wang <[email protected]>Signed-off-by Peng Fan <[email protected]>---
Changes in v2:
- Fix build fail onmx6sxsabresd_splissue
- Add configure regmap endian in NO-DM modelChanges in v1: None.
drivers/spi/fsl_qspi.c | 985 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 656 insertions(+), 329 deletions(-)drivers/spi/fsl_qspi.c +646
-329@@ -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",
drivers/spi/fsl_qspi.c void spi_release_bus(struct spi_slave *slave) · line 1111
Quoted 10 lines
drivers/spi/fsl_qspi.c +10
-0+ .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
Regards,
Peng.
PATCH v2 1/1 dm: spi: Convert Freescale QSPI driver to driver model
Quoted 17 lines · Peng Fan
Hi Haikun,
Quoted 13 lines · Haikun Wang
Move the Freescale QSPI driver over to driver model.
Signed-off-by Haikun Wang <[email protected]>Signed-off-by Peng Fan <[email protected]>---
Changes in v2:
- Fix build fail onmx6sxsabresd_splissue
- Add configure regmap endian in NO-DM modelChanges in v1: None.
[snip]
Quoted 2 lines
Testey-by Peng Fan <[email protected]>
PATCH v2 1/1 dm: spi: Convert Freescale QSPI driver to driver model
Quoted 16 lines · Simon Glass
Quoted 15 lines · Peng Fan
Hi Haikun,
Quoted 11 lines · Haikun Wang
Move the Freescale QSPI driver over to driver model.
Signed-off-by Haikun Wang <[email protected]>Signed-off-by Peng Fan <[email protected]>---
Changes in v2:
- Fix build fail onmx6sxsabresd_splissue
- Add configure regmap endian in NO-DM model
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines
Changes in v1: None.
[snip]
Quoted 2 lines
Testey-by Peng Fan <[email protected]>Acked-by Simon Glass <[email protected]>
Corrected the Tested-by tag.
Applied to u-boot-dm/next, thanks!
- Simon