[U-Boot] [PATCH] spi: add NXP FlexSPI driver

Add NXP Flexspi driver for i.MX8 Family usage. Flexible Serial Peripheral Interface (FlexSPI) host controller supports two SPI channels and up to 4 external devices. Each channel supports Single/Dual/Quad/Octal mode data transfer (1/2/4/8 bidirectional data lines).
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/spi/Kconfig | 19 + drivers/spi/Makefile | 1 + drivers/spi/fsl_fspi.c | 1291 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/spi/fsl_fspi.h | 170 +++++++ 4 files changed, 1481 insertions(+) create mode 100644 drivers/spi/fsl_fspi.c create mode 100644 drivers/spi/fsl_fspi.h
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f459c0a411..b71f289fb7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -372,6 +372,25 @@ config FSL_ESPI access the SPI interface and SPI NOR flash on platforms embedding this Freescale eSPI IP core.
+config FSL_FSPI + bool "NXP FlexSPI driver" + help + Enable the NXP FlexSPI (FSPI) driver. This driver can be + used to access the SPI NOR flash on platforms embedding this + NXP IP core. + +if FSL_FSPI +config FSPI_QUAD_SUPPORT + bool "FlexSPI QUAD support" + help + Enable Quad Read/write + +config FSPI_AHB + bool "FlexSPI AHB support" + help + Enable AHB buffer read +endif + config FSL_QSPI bool "Freescale QSPI driver" imply SPI_FLASH_BAR diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index ae4f2958f8..867feb994b 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o obj-$(CONFIG_FSL_ESPI) += fsl_espi.o +obj-$(CONFIG_FSL_FSPI) += fsl_fspi.o obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o obj-$(CONFIG_ICH_SPI) += ich.o obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o diff --git a/drivers/spi/fsl_fspi.c b/drivers/spi/fsl_fspi.c new file mode 100644 index 0000000000..7f9d2f0b45 --- /dev/null +++ b/drivers/spi/fsl_fspi.c @@ -0,0 +1,1291 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include <common.h> +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <errno.h> +#include <linux/sizes.h> +#include <malloc.h> +#include <spi.h> +#include <watchdog.h> + +#include "fsl_fspi.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define RX_BUFFER_SIZE 0x200 +#define TX_BUFFER_SIZE 0x400 +#define AHB_BUFFER_SIZE 0x800 + +/* SEQID */ +#define SEQID_READ 0 +#define SEQID_WREN 1 +#define SEQID_FAST_READ 2 +#define SEQID_RDSR 3 +#define SEQID_SE 4 +#define SEQID_CHIP_ERASE 5 +#define SEQID_PP 6 +#define SEQID_RDID 7 +#define SEQID_BE_4K 8 +#ifdef CONFIG_SPI_FLASH_BAR +#define SEQID_BRRD 9 +#define SEQID_BRWR 10 +#define SEQID_RDEAR 11 +#define SEQID_WREAR 12 +#endif +#define SEQID_RDEVCR 13 +#define SEQID_WREVCR 14 +#define SEQID_QUAD_OUTPUT 15 +#define SEQID_RDFSR 16 +#define SEQID_EN4B 17 +#define SEQID_CRFSR 18 + +/* FSPI CMD */ +#define FSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */ +#define FSPI_CMD_RDSR 0x05 /* Read status register */ +#define FSPI_CMD_WREN 0x06 /* Write enable */ +#define FSPI_CMD_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define FSPI_CMD_READ 0x03 /* Read data bytes */ +#define FSPI_CMD_BE_4K 0x20 /* 4K erase */ +#define FSPI_CMD_CHIP_ERASE 0xc7 /* Erase whole flash chip */ +#define FSPI_CMD_SE 0xd8 /* Sector erase (usually 64KiB) */ +#define FSPI_CMD_RDID 0x9f /* Read JEDEC ID */ + +/* Used for Micron, winbond and Macronix flashes */ +#define FSPI_CMD_WREAR 0xc5 /* EAR register write */ +#define FSPI_CMD_RDEAR 0xc8 /* EAR reigster read */ + +/* Used for Spansion flashes only. */ +#define FSPI_CMD_BRRD 0x16 /* Bank register read */ +#define FSPI_CMD_BRWR 0x17 /* Bank register write */ + +/* 4-byte address FSPI CMD - used on Spansion and some Macronix flashes */ +#define FSPI_CMD_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ +#define FSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */ +#define FSPI_CMD_SE_4B 0xdc /* Sector erase (usually 64KiB) */ +#define FSPI_CMD_BE_4K_4B 0x21 /* 4K erase */ + +#define FSPI_CMD_RD_EVCR 0x65 /* Read EVCR register */ +#define FSPI_CMD_WR_EVCR 0x61 /* Write EVCR register */ + +#define FSPI_CMD_EN4B 0xB7 + +/* 1-1-4 READ CMD */ +#define FSPI_CMD_QUAD_OUTPUT 0x6b +#define FSPI_CMD_DDR_QUAD_OUTPUT 0x6d + +/* read flag status register */ +#define FSPI_CMD_RDFSR 0x70 +#define FSPI_CMD_CRFSR 0x50 + +/* fsl_fspi_platdata flags */ +#define FSPI_FLAG_REGMAP_ENDIAN_BIG BIT(0) + +/* default SCK frequency, unit: HZ */ +#define FSL_FSPI_DEFAULT_SCK_FREQ 50000000 + +/* FSPI max chipselect signals number */ +#define FSL_FSPI_MAX_CHIPSELECT_NUM 4 + +#define FSPI_AHB_BASE_ADDR 0x08000000 + +/** + * struct fsl_fspi_platdata - platform data for NXP FSPI + * + * @flags: Flags for FSPI FSPI_FLAG_... + * @speed_hz: Default SCK frequency + * @reg_base: Base address of FSPI registers + * @amba_base: Base address of FSPI memory mapping + * @amba_total_size: size of FSPI memory mapping + * @flash_num: Number of active slave devices + * @num_chipselect: Number of FSPI chipselect signals + */ +struct fsl_fspi_platdata { + u32 flags; + u32 speed_hz; + u32 reg_base; + u32 amba_base; + u32 amba_total_size; + u32 flash_num; + u32 num_chipselect; +}; + +/** + * struct fsl_fspi_priv - private data for NXP FSPI + * + * @flags: Flags for FSPI FSPI_FLAG_... + * @bus_clk: FSPI 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 FSPI memory mapping of every CS + * @amba_total_size: size of FSPI memory mapping + * @cur_amba_base: Base address of FSPI memory mapping of current CS + * @flash_num: Number of active slave devices + * @num_chipselect: Number of FSPI chipselect signals + * @regs: Point to FSPI register structure for I/O access + */ +struct fsl_fspi_priv { + u32 flags; + u32 bus_clk; + u32 speed_hz; + u32 cur_seqid; + u32 sf_addr; + u32 amba_base[FSL_FSPI_MAX_CHIPSELECT_NUM]; + u32 amba_total_size; + u32 cur_amba_base; + u32 flash_num; + u32 num_chipselect; + struct fsl_fspi_regs *regs; +}; + +static u32 fspi_read32(u32 flags, u32 *addr) +{ + return flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ? + in_be32(addr) : in_le32(addr); +} + +static void fspi_write32(u32 flags, u32 *addr, u32 val) +{ + flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ? + out_be32(addr, val) : out_le32(addr, val); +} + +static void fspi_set_lut(struct fsl_fspi_priv *priv) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 lut_base; + + /* Unlock the LUT */ + fspi_write32(priv->flags, ®s->lutkey, FLEXSPI_LUTKEY_VALUE); + fspi_write32(priv->flags, ®s->lutcr, FLEXSPI_LCKER_UNLOCK); + + /* READ */ + lut_base = SEQID_READ * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_READ) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], + OPRND0(0) | PAD0(LUT_PAD1) | + INSTR0(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Write Enable */ + lut_base = SEQID_WREN * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_WREN) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Fast Read */ + lut_base = SEQID_FAST_READ * 4; +#ifdef CONFIG_SPI_FLASH_BAR + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#else + if (FSL_FSPI_FLASH_SIZE <= SZ_16M) + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + else + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_FAST_READ_4B) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | + OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) | + INSTR1(LUT_ADDR)); +#endif + fspi_write32(priv->flags, ®s->lut[lut_base + 1], + OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) | + OPRND1(0) | PAD1(LUT_PAD1) | + INSTR1(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Read Status */ + lut_base = SEQID_RDSR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_RDSR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | + INSTR1(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Erase a sector */ + lut_base = SEQID_SE * 4; +#ifdef CONFIG_SPI_FLASH_BAR + fspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(FSPI_CMD_SE) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#else + if (FSL_FSPI_FLASH_SIZE <= SZ_16M) + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_SE) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + else + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_SE_4B) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#endif + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Erase the whole chip */ + lut_base = SEQID_CHIP_ERASE * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_CHIP_ERASE) | + PAD0(LUT_PAD1) | INSTR0(LUT_CMD)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Page Program */ + lut_base = SEQID_PP * 4; +#ifdef CONFIG_SPI_FLASH_BAR + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_PP) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | + INSTR1(LUT_ADDR)); +#else + if (FSL_FSPI_FLASH_SIZE <= SZ_16M) + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_PP) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + else + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_PP_4B) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#endif + fspi_write32(priv->flags, ®s->lut[lut_base + 1], + OPRND0(0) | + PAD0(LUT_PAD1) | INSTR0(LUT_WRITE)); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* READ ID */ + lut_base = SEQID_RDID * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_RDID) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(8) | PAD1(LUT_PAD1) | + INSTR1(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* SUB SECTOR 4K ERASE */ + lut_base = SEQID_BE_4K * 4; +#ifdef CONFIG_SPI_FLASH_BAR + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_BE_4K) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) | + INSTR1(LUT_ADDR)); +#else + if (FSL_FSPI_FLASH_SIZE <= SZ_16M) + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_BE_4K) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); + else + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_BE_4K_4B) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); +#endif + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + +#ifdef CONFIG_SPI_FLASH_BAR + /* + * BRRD BRWR RDEAR WREAR are all supported, because it is hard to + * dynamically check whether to set BRRD BRWR or RDEAR WREAR during + * initialization. + */ + lut_base = SEQID_BRRD * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_BRRD) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | + INSTR1(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + lut_base = SEQID_BRWR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_BRWR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | + INSTR1(LUT_WRITE)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + lut_base = SEQID_RDEAR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_RDEAR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | + INSTR1(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + lut_base = SEQID_WREAR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_WREAR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | + INSTR1(LUT_WRITE)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); +#endif + lut_base = SEQID_RDEVCR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_RD_EVCR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + lut_base = SEQID_WREVCR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_WR_EVCR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + +#ifdef CONFIG_FSPI_QUAD_SUPPORT + /* QUAD OUTPUT READ */ + lut_base = SEQID_QUAD_OUTPUT * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_DDR_QUAD_OUTPUT) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | + PAD1(LUT_PAD1) | INSTR1(LUT_ADDR_DDR)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], + OPRND0(0xc) | PAD0(LUT_PAD4) | + INSTR0(LUT_DUMMY_DDR) | OPRND1(0) | + PAD1(LUT_PAD4) | INSTR1(LUT_READ_DDR)); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); +#endif + + /* Read Flag Status */ + lut_base = SEQID_RDFSR * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_RDFSR) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) | + INSTR1(LUT_READ)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Enter 4 bytes address mode */ + lut_base = SEQID_EN4B * 4; + fspi_write32(priv->flags, ®s->lut[lut_base], + OPRND0(FSPI_CMD_EN4B) | PAD0(LUT_PAD1) | + INSTR0(LUT_CMD)); + fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0); + fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); + + /* Lock the LUT */ + fspi_write32(priv->flags, ®s->lutkey, FLEXSPI_LUTKEY_VALUE); + fspi_write32(priv->flags, ®s->lutcr, FLEXSPI_LCKER_LOCK); +} + +#if defined(CONFIG_FSI_AHB) +/* + * If we have changed the content of the flash by writing or erasing, + * we need to invalidate the AHB buffer. If we do not do so, we may read out + * the wrong data. The spec tells us reset the AHB domain and Serial Flash + * domain at the same time. + */ +static inline void fspi_ahb_invalid(struct fsl_fspi_priv *priv) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 reg; + + reg = fspi_read32(priv->flags, ®s->mcr0); + reg |= FLEXSPI_MCR0_SWRST_MASK; + fspi_write32(priv->flags, ®s->mcr0, reg); + + while ((fspi_read32(priv->flags, ®s->mcr0) & 1)) + ; +} + +/* Read out the data from the AHB buffer. */ +static inline void fspi_ahb_read(struct fsl_fspi_priv *priv, u8 *rxbuf, + int len) +{ + /* Read out the data directly from the AHB buffer. */ + memcpy(rxbuf, (u8 *)(FSPI_AHB_BASE_ADDR + + (uintptr_t)priv->sf_addr), len); +} + +/* + * There are two different ways to read out the data from the flash: + * the "IP Command Read" and the "AHB Command Read". + * + * The IC guy suggests we use the "AHB Command Read" which is faster + * then the "IP Command Read". (What's more is that there is a bug in + * the "IP Command Read" in the Vybrid.) + * + * After we set up the registers for the "AHB Command Read", we can use + * the memcpy to read the data directly. A "missed" access to the buffer + * causes the controller to clear the buffer, and use the sequence pointed + * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. + */ +static void fspi_init_ahb_read(struct fsl_fspi_priv *priv) +{ + struct fsl_fspi_regs *regs = priv->regs; + int i; + + /* AHB configuration for access buffer 0~7 .*/ + for (i = 0; i < 7; i++) + fspi_write32(priv->flags, ®s->ahbrxbuf0cr0 + i, 0); + + /* + * Set ADATSZ with the maximum AHB buffer size to improve the read + * performance + */ + fspi_write32(priv->flags, ®s->ahbrxbuf7cr0, AHB_BUFFER_SIZE / 8 | + FLEXSPI_AHBRXBUF0CR7_PREF_MASK); + + fspi_write32(priv->flags, ®s->ahbcr, FLEXSPI_AHBCR_PREF_EN_MASK); + /* + * Set the default lut sequence for AHB Read. + * Parallel mode is disabled. + */ +#ifdef CONFIG_FSPI_QUAD_SUPPORT + fspi_write32(priv->flags, ®s->flsha1cr2, SEQID_QUAD_OUTPUT); +#else + fspi_write32(priv->flags, ®s->flsha1cr2, SEQID_FAST_READ); +#endif +} +#endif + +#ifdef CONFIG_SPI_FLASH_BAR +/* Bank register read/write, EAR register read/write */ +static void fspi_op_rdbank(struct fsl_fspi_priv *priv, u8 *rxbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 data, seqid; + + /* invalid the RXFIFO first */ + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + if (priv->cur_seqid == FSPI_CMD_BRRD) + seqid = SEQID_BRRD; + else + seqid = SEQID_RDEAR; + + fspi_write32(priv->flags, ®s->ipcr1, + (seqid << FLEXSPI_IPCR1_SEQID_SHIFT) | len); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) & + FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + while (1) { + data = fspi_read32(priv->flags, ®s->rfdr[0]); + memcpy(rxbuf, &data, len); + break; + } + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK); + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} +#endif + +static void fspi_op_rdevcr(struct fsl_fspi_priv *priv, u8 *rxbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 data; + + /* invalid the RXFIFO first */ + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_RDEVCR << FLEXSPI_IPCR1_SEQID_SHIFT) | len); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + while (1) { + data = fspi_read32(priv->flags, ®s->rfdr[0]); + memcpy(rxbuf, &data, len); + break; + } + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK); + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +static void fspi_op_wrevcr(struct fsl_fspi_priv *priv, u8 *txbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + /* Wait for TXFIFO empty*/ + while (!(fspi_read32(priv->flags, ®s->intr) & + FLEXSPI_INTR_IPTXWE_MASK)) + ; + + /* write the data to TXFIFO */ + memcpy(®s->tfdr, txbuf, len); + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPTXWE_MASK); + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_WREVCR << FLEXSPI_IPCR1_SEQID_SHIFT) | len); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) & + FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +static void fspi_op_rdid(struct fsl_fspi_priv *priv, u32 *rxbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 data, size; + int i; + + /* invalid the RXFIFO first */ + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_RDID << FLEXSPI_IPCR1_SEQID_SHIFT) | len); + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) & + FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + i = 0; + while ((len <= RX_BUFFER_SIZE) && (len > 0)) { + data = fspi_read32(priv->flags, ®s->rfdr[i]); + size = (len < 4) ? len : 4; + memcpy(rxbuf, &data, size); + len -= size; + rxbuf++; + i++; + } + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK); + + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +#ifndef CONFIG_FSI_AHB +/* If not use AHB read, read data from ip interface */ +static void fspi_op_read(struct fsl_fspi_priv *priv, u32 *rxbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + int i, size, rx_size; + u32 to_or_from; + + to_or_from = priv->sf_addr + priv->cur_amba_base; + + /* invalid the RXFIFO */ + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + + while (len > 0) { + WATCHDOG_RESET(); + + fspi_write32(priv->flags, ®s->ipcr0, to_or_from); + + rx_size = (len > RX_BUFFER_SIZE) ? + RX_BUFFER_SIZE : len; + +#ifdef CONFIG_FSPI_QUAD_SUPPORT + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_QUAD_OUTPUT << FLEXSPI_IPCR1_SEQID_SHIFT) | + rx_size); +#else + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_FAST_READ << FLEXSPI_IPCR1_SEQID_SHIFT) | + rx_size); +#endif + + to_or_from += rx_size; + len -= rx_size; + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + size = rx_size / 8; + for (i = 0; i < size; ++i) { + /* Wait for RXFIFO available*/ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPRXWA_MASK)) + ; + + memcpy(rxbuf, ®s->rfdr, 8); + rxbuf += 2; + + /* move the FIFO pointer */ + fspi_write32(priv->flags, ®s->intr, + FLEXSPI_INTR_IPRXWA_MASK); + } + + size = rx_size % 8; + + if (size) { + /* Wait for data filled*/ + while (!(fspi_read32(priv->flags, ®s->iprxfsts) + & FLEXSPI_IPRXFSTS_FILL_MASK)) + ; + memcpy(rxbuf, ®s->rfdr, size); + } + + /* invalid the RXFIFO */ + fspi_write32(priv->flags, ®s->iprxfcr, + FLEXSPI_IPRXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, + FLEXSPI_INTR_IPCMDDONE_MASK); + } +} +#endif + +static void fspi_op_write(struct fsl_fspi_priv *priv, u8 *txbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 seqid; + int i, size, tx_size; + u32 to_or_from = 0; + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_WREN << FLEXSPI_IPCR1_SEQID_SHIFT) | 0); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK); + + to_or_from = priv->sf_addr + priv->cur_amba_base; + + while (len > 0) { + /* Default is page programming */ + seqid = SEQID_PP; +#ifdef CONFIG_SPI_FLASH_BAR + if (priv->cur_seqid == FSPI_CMD_BRWR) + seqid = SEQID_BRWR; + else if (priv->cur_seqid == FSPI_CMD_WREAR) + seqid = SEQID_WREAR; +#endif + + fspi_write32(priv->flags, ®s->ipcr0, to_or_from); + + tx_size = (len > TX_BUFFER_SIZE) ? + TX_BUFFER_SIZE : len; + + to_or_from += tx_size; + len -= tx_size; + + size = tx_size / 8; + for (i = 0; i < size; i++) { + /* Wait for TXFIFO empty*/ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPTXWE_MASK)) + ; + + memcpy(®s->tfdr, txbuf, 8); + txbuf += 8; + fspi_write32(priv->flags, ®s->intr, + FLEXSPI_INTR_IPTXWE_MASK); + } + + size = tx_size % 8; + if (size) { + /* Wait for TXFIFO empty*/ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPTXWE_MASK)) + ; + + memcpy(®s->tfdr, txbuf, size); + fspi_write32(priv->flags, ®s->intr, + FLEXSPI_INTR_IPTXWE_MASK); + } + + fspi_write32(priv->flags, ®s->ipcr1, + (seqid << FLEXSPI_IPCR1_SEQID_SHIFT) | tx_size); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) & + FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, + FLEXSPI_IPTXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, + FLEXSPI_INTR_IPCMDDONE_MASK); + } +} + +static void fspi_op_rdsr(struct fsl_fspi_priv *priv, void *rxbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 data; + + /* invalid the RXFIFO first */ + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_RDSR << FLEXSPI_IPCR1_SEQID_SHIFT) | len); + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + data = fspi_read32(priv->flags, ®s->rfdr[0]); + memcpy(rxbuf, &data, len); + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK); + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +static void fspi_op_rdfsr(struct fsl_fspi_priv *priv, void *rxbuf, u32 len) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 data; + + /* invalid the RXFIFO first */ + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_RDFSR << FLEXSPI_IPCR1_SEQID_SHIFT) | len); + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + data = fspi_read32(priv->flags, ®s->rfdr[0]); + memcpy(rxbuf, &data, len); + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK); + fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK); + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +static void fspi_op_erase(struct fsl_fspi_priv *priv) +{ + struct fsl_fspi_regs *regs = priv->regs; + u32 to_or_from = 0; + + to_or_from = priv->sf_addr + priv->cur_amba_base; + + fspi_write32(priv->flags, ®s->ipcr0, to_or_from); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_WREN << FLEXSPI_IPCR1_SEQID_SHIFT) | 0); + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); + + if (priv->cur_seqid == FSPI_CMD_SE || + priv->cur_seqid == FSPI_CMD_SE_4B) { + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_SE << FLEXSPI_IPCR1_SEQID_SHIFT) | 0); + } else if (priv->cur_seqid == FSPI_CMD_BE_4K || + priv->cur_seqid == FSPI_CMD_BE_4K_4B) { + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_BE_4K << FLEXSPI_IPCR1_SEQID_SHIFT) | 0); + } + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +static void fspi_op_crfsr(struct fsl_fspi_priv *priv) +{ + struct fsl_fspi_regs *regs = priv->regs; + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_CRFSR << FLEXSPI_IPCR1_SEQID_SHIFT) | 0); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +static void fspi_op_enter_4bytes(struct fsl_fspi_priv *priv) +{ + struct fsl_fspi_regs *regs = priv->regs; + + /* invalid the TXFIFO first */ + fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK); + + fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base); + + fspi_write32(priv->flags, ®s->ipcr1, + (SEQID_EN4B << FLEXSPI_IPCR1_SEQID_SHIFT) | 0); + + /* Trigger the command */ + fspi_write32(priv->flags, ®s->ipcmd, 1); + + /* Wait for command done */ + while (!(fspi_read32(priv->flags, ®s->intr) + & FLEXSPI_INTR_IPCMDDONE_MASK)) + ; + + fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPCMDDONE_MASK); +} + +int fspi_xfer(struct fsl_fspi_priv *priv, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + u32 bytes = DIV_ROUND_UP(bitlen, 8); + static u32 wr_sfaddr; + u32 txbuf = 0; + + if (dout) { + if (flags & SPI_XFER_BEGIN) { + priv->cur_seqid = *(u8 *)dout; + if (bytes > 1) { + int i, addr_bytes; + + if (FSL_FSPI_FLASH_SIZE <= SZ_16M) + addr_bytes = 3; + else +#ifdef CONFIG_SPI_FLASH_BAR + addr_bytes = 3; +#else + addr_bytes = 4; +#endif + + dout = (u8 *)dout + 1; + txbuf = *(u8 *)dout; + for (i = 1; i < addr_bytes; i++) { + txbuf <<= 8; + txbuf |= *(((u8 *)dout) + i); + } + + debug("seqid 0x%x addr 0x%x\n", + priv->cur_seqid, txbuf); + } + } + + if (flags == SPI_XFER_END) { + if (priv->cur_seqid == FSPI_CMD_WR_EVCR) { + fspi_op_wrevcr(priv, (u8 *)dout, bytes); + return 0; + } else if ((priv->cur_seqid == FSPI_CMD_SE) || + (priv->cur_seqid == FSPI_CMD_BE_4K) || + (priv->cur_seqid == FSPI_CMD_SE_4B) || + (priv->cur_seqid == FSPI_CMD_BE_4K_4B)) { + int i; + + txbuf = *(u8 *)dout; + for (i = 1; i < bytes; i++) { + txbuf <<= 8; + txbuf |= *(((u8 *)dout) + i); + } + + priv->sf_addr = txbuf; + fspi_op_erase(priv); +#ifdef CONFIG_FSI_AHB + fspi_ahb_invalid(priv); +#endif + return 0; + } + priv->sf_addr = wr_sfaddr; + fspi_op_write(priv, (u8 *)dout, bytes); + return 0; + } + + if (priv->cur_seqid == FSPI_CMD_QUAD_OUTPUT || + priv->cur_seqid == FSPI_CMD_FAST_READ || + priv->cur_seqid == FSPI_CMD_FAST_READ_4B) { + priv->sf_addr = txbuf; + } else if (priv->cur_seqid == FSPI_CMD_PP || + priv->cur_seqid == FSPI_CMD_PP_4B) { + wr_sfaddr = txbuf; + } else if (priv->cur_seqid == FSPI_CMD_WR_EVCR) { + wr_sfaddr = 0; + } else if ((priv->cur_seqid == FSPI_CMD_BRWR) || + (priv->cur_seqid == FSPI_CMD_WREAR)) { +#ifdef CONFIG_SPI_FLASH_BAR + wr_sfaddr = 0; +#endif + } else if (priv->cur_seqid == FSPI_CMD_EN4B) { + fspi_op_enter_4bytes(priv); + } else if (priv->cur_seqid == FSPI_CMD_CRFSR) { + fspi_op_crfsr(priv); + } + } + + if (din) { + if (priv->cur_seqid == FSPI_CMD_QUAD_OUTPUT || + priv->cur_seqid == FSPI_CMD_FAST_READ || + priv->cur_seqid == FSPI_CMD_FAST_READ_4B) { +#ifdef CONFIG_FSI_AHB + fspi_ahb_read(priv, din, bytes); +#else + fspi_op_read(priv, din, bytes); +#endif + } else if (priv->cur_seqid == FSPI_CMD_RDID) + fspi_op_rdid(priv, din, bytes); + else if (priv->cur_seqid == FSPI_CMD_RDSR) + fspi_op_rdsr(priv, din, bytes); + else if (priv->cur_seqid == FSPI_CMD_RDFSR) + fspi_op_rdfsr(priv, din, bytes); + else if (priv->cur_seqid == FSPI_CMD_RD_EVCR) + fspi_op_rdevcr(priv, din, bytes); +#ifdef CONFIG_SPI_FLASH_BAR + else if (priv->cur_seqid == FSPI_CMD_BRRD || + priv->cur_seqid == FSPI_CMD_RDEAR) { + priv->sf_addr = 0; + fspi_op_rdbank(priv, din, bytes); + } +#endif + } + +#ifdef CONFIG_FSI_AHB + if (priv->cur_seqid == FSPI_CMD_SE || + priv->cur_seqid == FSPI_CMD_SE_4B || + priv->cur_seqid == FSPI_CMD_PP || + priv->cur_seqid == FSPI_CMD_PP_4B || + priv->cur_seqid == FSPI_CMD_BE_4K || + priv->cur_seqid == FSPI_CMD_BE_4K_4B || + priv->cur_seqid == FSPI_CMD_WREAR || + priv->cur_seqid == FSPI_CMD_BRWR) + fspi_ahb_invalid(priv); +#endif + + return 0; +} + +void fspi_module_disable(struct fsl_fspi_priv *priv, u8 disable) +{ + u32 mcr_val; + + mcr_val = fspi_read32(priv->flags, &priv->regs->mcr0); + if (disable) + mcr_val |= FLEXSPI_MCR0_MDIS_MASK; + else + mcr_val &= ~FLEXSPI_MCR0_MDIS_MASK; + fspi_write32(priv->flags, &priv->regs->mcr0, mcr_val); +} + +__weak void init_clk_fspi(int index) +{ +} + +static int fsl_fspi_child_pre_probe(struct udevice *dev) +{ + struct spi_slave *slave = dev_get_parent_priv(dev); + + slave->max_write_size = TX_BUFFER_SIZE; + +#ifdef CONFIG_FSPI_QUAD_SUPPORT + slave->mode |= SPI_RX_QUAD; +#endif + + return 0; +} + +static int fsl_fspi_probe(struct udevice *bus) +{ + u32 total_size; + struct fsl_fspi_platdata *plat = dev_get_platdata(bus); + struct fsl_fspi_priv *priv = dev_get_priv(bus); + struct dm_spi_bus *dm_spi_bus; + + if (CONFIG_IS_ENABLED(CLK)) { + /* Assigned clock already set clock */ + struct clk fspi_clk; + int ret; + + ret = clk_get_by_name(bus, "fspi", &fspi_clk); + if (ret < 0) { + printf("Can't get fspi clk: %d\n", ret); + return ret; + } + + ret = clk_enable(&fspi_clk); + if (ret < 0) { + printf("Can't enable fspi clk: %d\n", ret); + return ret; + } + } else { + init_clk_fspi(bus->seq); + } + dm_spi_bus = bus->uclass_priv; + + dm_spi_bus->max_hz = plat->speed_hz; + + priv->regs = (struct fsl_fspi_regs *)(uintptr_t)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; + + fspi_write32(priv->flags, &priv->regs->mcr0, FLEXSPI_MCR0_SWRST_MASK); + do { + udelay(1); + } while (0x1 & fspi_read32(priv->flags, &priv->regs->mcr0)); + + /* Disable the module */ + fspi_module_disable(priv, 1); + + /* Enable the module and set to proper value*/ +#ifdef CONFIG_FSPI_DQS_LOOPBACK + fspi_write32(priv->flags, &priv->regs->mcr0, 0xFFFF0010); +#else + fspi_write32(priv->flags, &priv->regs->mcr0, 0xFFFF0000); +#endif + + /* Reset the DLL register to default value */ + fspi_write32(priv->flags, &priv->regs->dllacr, 0x0100); + fspi_write32(priv->flags, &priv->regs->dllbcr, 0x0100); + + /* Flash Size in KByte */ + total_size = FSL_FSPI_FLASH_SIZE * FSL_FSPI_FLASH_NUM >> 10; + + /* + * 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. + */ + + fspi_write32(priv->flags, &priv->regs->flsha1cr0, + total_size); + fspi_write32(priv->flags, &priv->regs->flsha2cr0, + 0); + fspi_write32(priv->flags, &priv->regs->flshb1cr0, + 0); + fspi_write32(priv->flags, &priv->regs->flshb2cr0, + 0); + + fspi_set_lut(priv); + +#ifdef CONFIG_FSI_AHB + fspi_init_ahb_read(priv); +#endif + + fspi_module_disable(priv, 0); + + return 0; +} + +static int fsl_fspi_ofdata_to_platdata(struct udevice *bus) +{ + struct fdt_resource res_regs, res_mem; + struct fsl_fspi_platdata *plat = bus->platdata; + const void *blob = gd->fdt_blob; + int node = ofnode_to_offset(bus->node); + int ret, flash_num = 0, subnode; + + if (fdtdec_get_bool(blob, node, "big-endian")) + plat->flags |= FSPI_FLAG_REGMAP_ENDIAN_BIG; + + ret = fdt_get_named_resource(blob, node, "reg", "reg-names", + "FlexSPI", &res_regs); + if (ret) { + debug("Error: can't get regs base addresses(ret = %d)!\n", ret); + return -ENOMEM; + } + ret = fdt_get_named_resource(blob, node, "reg", "reg-names", + "FlexSPI-memory", &res_mem); + if (ret) { + debug("Error: can't get AMBA base addresses(ret = %d)!\n", ret); + return -ENOMEM; + } + + /* Count flash numbers */ + fdt_for_each_subnode(subnode, blob, 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_FSPI_DEFAULT_SCK_FREQ); + plat->num_chipselect = fdtdec_get_int(blob, node, "num-cs", + FSL_FSPI_MAX_CHIPSELECT_NUM); + + plat->reg_base = res_regs.start; + plat->amba_base = 0; + plat->amba_total_size = res_mem.end - res_mem.start + 1; + plat->flash_num = flash_num; + + debug("%s: regs=<0x%x> <0x%x, 0x%x>, max-frequency=%d, endianness=%s\n", + __func__, plat->reg_base, plat->amba_base, + plat->amba_total_size, plat->speed_hz, + plat->flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le"); + + return 0; +} + +static int fsl_fspi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct fsl_fspi_priv *priv; + + priv = dev_get_priv(dev->parent); + + return fspi_xfer(priv, bitlen, dout, din, flags); +} + +static int fsl_fspi_claim_bus(struct udevice *dev) +{ + struct fsl_fspi_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_FSPI_FLASH_SIZE * slave_plat->cs; + + return 0; +} + +static int fsl_fspi_release_bus(struct udevice *dev) +{ + return 0; +} + +static int fsl_fspi_set_speed(struct udevice *bus, uint speed) +{ + /* Nothing to do */ + return 0; +} + +static int fsl_fspi_set_mode(struct udevice *bus, uint mode) +{ + /* Nothing to do */ + return 0; +} + +static const struct dm_spi_ops fsl_fspi_ops = { + .claim_bus = fsl_fspi_claim_bus, + .release_bus = fsl_fspi_release_bus, + .xfer = fsl_fspi_xfer, + .set_speed = fsl_fspi_set_speed, + .set_mode = fsl_fspi_set_mode, +}; + +static const struct udevice_id fsl_fspi_ids[] = { + { .compatible = "fsl,imx8qm-flexspi" }, + { .compatible = "fsl,imx8qxp-flexspi" }, + { .compatible = "fsl,imx8mm-flexspi" }, + { } +}; + +U_BOOT_DRIVER(fsl_fspi) = { + .name = "fsl_fspi", + .id = UCLASS_SPI, + .of_match = fsl_fspi_ids, + .ops = &fsl_fspi_ops, + .ofdata_to_platdata = fsl_fspi_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct fsl_fspi_platdata), + .priv_auto_alloc_size = sizeof(struct fsl_fspi_priv), + .probe = fsl_fspi_probe, + .child_pre_probe = fsl_fspi_child_pre_probe, +}; diff --git a/drivers/spi/fsl_fspi.h b/drivers/spi/fsl_fspi.h new file mode 100644 index 0000000000..bff13b9bd8 --- /dev/null +++ b/drivers/spi/fsl_fspi.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 NXP + * + * Register definitions for NXP FLEXSPI + */ + +#ifndef _FSL_FSPI_H_ +#define _FSL_FSPI_H_ + +#include <linux/bitops.h> + +struct fsl_fspi_regs { + u32 mcr0; + u32 mcr1; + u32 mcr2; + u32 ahbcr; + u32 inten; + u32 intr; + u32 lutkey; + u32 lutcr; + u32 ahbrxbuf0cr0; + u32 ahbrxbuf1cr0; + u32 ahbrxbuf2cr0; + u32 ahbrxbuf3cr0; + u32 ahbrxbuf4cr0; + u32 ahbrxbuf5cr0; + u32 ahbrxbuf6cr0; + u32 ahbrxbuf7cr0; + u32 ahbrxbuf0cr1; + u32 ahbrxbuf1cr1; + u32 ahbrxbuf2cr1; + u32 ahbrxbuf3cr1; + u32 ahbrxbuf4cr1; + u32 ahbrxbuf5cr1; + u32 ahbrxbuf6cr1; + u32 ahbrxbuf7cr1; + u32 flsha1cr0; + u32 flsha2cr0; + u32 flshb1cr0; + u32 flshb2cr0; + u32 flsha1cr1; + u32 flsha2cr1; + u32 flshb1cr1; + u32 flshb2cr1; + u32 flsha1cr2; + u32 flsha2cr2; + u32 flshb1cr2; + u32 flshb2cr2; + u32 flshcr3; + u32 flshcr4; + u32 flshcr5; + u32 flshcr6; + u32 ipcr0; + u32 ipcr1; + u32 ipcr2; + u32 ipcr3; + u32 ipcmd; + u32 dlpr; + u32 iprxfcr; + u32 iptxfcr; + u32 dllacr; + u32 dllbcr; + u32 soccr; + u32 misccr2; + u32 misccr3; + u32 misccr4; + u32 misccr5; + u32 misccr6; + u32 sts0; + u32 sts1; + u32 sts2; + u32 ahbspndsts; + u32 iprxfsts; + u32 iptxfsts; + u32 rsvd[2]; + u32 rfdr[32]; + u32 tfdr[32]; + u32 lut[128]; +}; + +/* The registers */ +#define FLEXSPI_MCR0_MDIS_SHIFT 1 +#define FLEXSPI_MCR0_MDIS_MASK BIT(1) +#define FLEXSPI_MCR0_SWRST_SHIFT 0 +#define FLEXSPI_MCR0_SWRST_MASK BIT(0) + +#define FLEXSPI_AHBCR_PREF_EN_SHIFT 5 +#define FLEXSPI_AHBCR_PREF_EN_MASK BIT(5) + +#define FLEXSPI_INTR_IPTXWE_SHIFT 6 +#define FLEXSPI_INTR_IPTXWE_MASK BIT(6) +#define FLEXSPI_INTR_IPRXWA_SHIFT 5 +#define FLEXSPI_INTR_IPRXWA_MASK BIT(5) +#define FLEXSPI_INTR_IPCMDDONE_SHIFT 0 +#define FLEXSPI_INTR_IPCMDDONE_MASK BIT(0) + +#define FLEXSPI_LUTKEY_VALUE 0x5AF05AF0 + +#define FLEXSPI_LCKER_LOCK 0x1 +#define FLEXSPI_LCKER_UNLOCK 0x2 + +#define FLEXSPI_BUFXCR_INVALID_MSTRID 0xe +#define FLEXSPI_AHBRXBUF0CR7_PREF_SHIFT 31 +#define FLEXSPI_AHBRXBUF0CR7_PREF_MASK BIT(31) + +#define FLEXSPI_IPCR1_SEQID_SHIFT 16 + +#define FLEXSPI_IPRXFCR_CLR_SHIFT 0 +#define FLEXSPI_IPRXFCR_CLR_MASK BIT(0) + +#define FLEXSPI_IPTXFCR_CLR_SHIFT 0 +#define FLEXSPI_IPTXFCR_CLR_MASK BIT(0) + +#define FLEXSPI_IPRXFSTS_FILL_SHIFT 0 +#define FLEXSPI_IPRXFSTS_FILL_MASK (0xFF << FLEXSPI_IPRXFSTS_FILL_SHIFT) + +/* register map end */ + +#define OPRND0_SHIFT 0 +#define OPRND0(x) ((x) << OPRND0_SHIFT) +#define PAD0_SHIFT 8 +#define PAD0(x) ((x) << PAD0_SHIFT) +#define INSTR0_SHIFT 10 +#define INSTR0(x) ((x) << INSTR0_SHIFT) +#define OPRND1_SHIFT 16 +#define OPRND1(x) ((x) << OPRND1_SHIFT) +#define PAD1_SHIFT 24 +#define PAD1(x) ((x) << PAD1_SHIFT) +#define INSTR1_SHIFT 26 +#define INSTR1(x) ((x) << INSTR1_SHIFT) + +#define LUT_STOP 0x00 +#define LUT_CMD 0x01 +#define LUT_ADDR 0x02 +#define LUT_CADDR_SDR 0x03 +#define LUT_MODE 0x04 +#define LUT_MODE2 0x05 +#define LUT_MODE4 0x06 +#define LUT_MODE8 0x07 +#define LUT_WRITE 0x08 +#define LUT_READ 0x09 +#define LUT_LEARN_SDR 0x0A +#define LUT_DATSZ_SDR 0x0B +#define LUT_DUMMY 0x0C +#define LUT_DUMMY_RWDS_SDR 0x0D +#define LUT_JMP_ON_CS 0x1F +#define LUT_CMD_DDR 0x21 +#define LUT_ADDR_DDR 0x22 +#define LUT_CADDR_DDR 0x23 +#define LUT_MODE_DDR 0x24 +#define LUT_MODE2_DDR 0x25 +#define LUT_MODE4_DDR 0x26 +#define LUT_MODE8_DDR 0x27 +#define LUT_WRITE_DDR 0x28 +#define LUT_READ_DDR 0x29 +#define LUT_LEARN_DDR 0x2A +#define LUT_DATSZ_DDR 0x2B +#define LUT_DUMMY_DDR 0x2C +#define LUT_DUMMY_RWDS_DDR 0x2D + +#define LUT_PAD1 0 +#define LUT_PAD2 1 +#define LUT_PAD4 2 +#define LUT_PAD8 3 + +#define ADDR24BIT 0x18 +#define ADDR32BIT 0x20 + +#endif /* _FSL_FSPI_H_ */

Subject: [PATCH] spi: add NXP FlexSPI driver
Please ignore this patch.
Thanks, Peng.
Add NXP Flexspi driver for i.MX8 Family usage. Flexible Serial Peripheral Interface (FlexSPI) host controller supports two SPI channels and up to 4 external devices. Each channel supports Single/Dual/Quad/Octal mode data transfer (1/2/4/8 bidirectional data lines).
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/spi/Kconfig | 19 + drivers/spi/Makefile | 1 + drivers/spi/fsl_fspi.c | 1291 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/spi/fsl_fspi.h | 170 +++++++ 4 files changed, 1481 insertions(+) create mode 100644 drivers/spi/fsl_fspi.c create mode 100644 drivers/spi/fsl_fspi.h
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f459c0a411..b71f289fb7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -372,6 +372,25 @@ config FSL_ESPI access the SPI interface and SPI NOR flash on platforms embedding this Freescale eSPI IP core.
+config FSL_FSPI
- bool "NXP FlexSPI driver"
- help
Enable the NXP FlexSPI (FSPI) driver. This driver can be
used to access the SPI NOR flash on platforms embedding this
NXP IP core.
+if FSL_FSPI +config FSPI_QUAD_SUPPORT
- bool "FlexSPI QUAD support"
- help
Enable Quad Read/write
+config FSPI_AHB
- bool "FlexSPI AHB support"
- help
Enable AHB buffer read
+endif
config FSL_QSPI bool "Freescale QSPI driver" imply SPI_FLASH_BAR diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index ae4f2958f8..867feb994b 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o obj-$(CONFIG_FSL_ESPI) += fsl_espi.o +obj-$(CONFIG_FSL_FSPI) += fsl_fspi.o obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o obj-$(CONFIG_ICH_SPI) += ich.o obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o diff --git a/drivers/spi/fsl_fspi.c b/drivers/spi/fsl_fspi.c new file mode 100644 index 0000000000..7f9d2f0b45 --- /dev/null +++ b/drivers/spi/fsl_fspi.c @@ -0,0 +1,1291 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2019 NXP
- */
+#include <common.h> +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <errno.h> +#include <linux/sizes.h> +#include <malloc.h> +#include <spi.h> +#include <watchdog.h>
+#include "fsl_fspi.h"
+DECLARE_GLOBAL_DATA_PTR;
+#define RX_BUFFER_SIZE 0x200 +#define TX_BUFFER_SIZE 0x400 +#define AHB_BUFFER_SIZE 0x800
+/* SEQID */ +#define SEQID_READ 0 +#define SEQID_WREN 1 +#define SEQID_FAST_READ 2 +#define SEQID_RDSR 3 +#define SEQID_SE 4 +#define SEQID_CHIP_ERASE 5 +#define SEQID_PP 6 +#define SEQID_RDID 7 +#define SEQID_BE_4K 8 +#ifdef CONFIG_SPI_FLASH_BAR +#define SEQID_BRRD 9 +#define SEQID_BRWR 10 +#define SEQID_RDEAR 11 +#define SEQID_WREAR 12 +#endif +#define SEQID_RDEVCR 13 +#define SEQID_WREVCR 14 +#define SEQID_QUAD_OUTPUT 15 +#define SEQID_RDFSR 16 +#define SEQID_EN4B 17 +#define SEQID_CRFSR 18
+/* FSPI CMD */ +#define FSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */ +#define FSPI_CMD_RDSR 0x05 /* Read status register */ +#define FSPI_CMD_WREN 0x06 /* Write enable */ +#define FSPI_CMD_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define FSPI_CMD_READ 0x03 /* Read data bytes */ +#define FSPI_CMD_BE_4K 0x20 /* 4K erase */ +#define FSPI_CMD_CHIP_ERASE 0xc7 /* Erase whole flash chip */ +#define FSPI_CMD_SE 0xd8 /* Sector erase (usually 64KiB) */ +#define FSPI_CMD_RDID 0x9f /* Read JEDEC ID */
+/* Used for Micron, winbond and Macronix flashes */ +#define FSPI_CMD_WREAR 0xc5 /* EAR register write */ +#define FSPI_CMD_RDEAR 0xc8 /* EAR reigster read */
+/* Used for Spansion flashes only. */ +#define FSPI_CMD_BRRD 0x16 /* Bank register read */ +#define FSPI_CMD_BRWR 0x17 /* Bank register write */
+/* 4-byte address FSPI CMD - used on Spansion and some Macronix flashes */ +#define FSPI_CMD_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ +#define FSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */ +#define FSPI_CMD_SE_4B 0xdc /* Sector erase (usually 64KiB) */ +#define FSPI_CMD_BE_4K_4B 0x21 /* 4K erase */
+#define FSPI_CMD_RD_EVCR 0x65 /* Read EVCR register */ +#define FSPI_CMD_WR_EVCR 0x61 /* Write EVCR register */
+#define FSPI_CMD_EN4B 0xB7
+/* 1-1-4 READ CMD */ +#define FSPI_CMD_QUAD_OUTPUT 0x6b +#define FSPI_CMD_DDR_QUAD_OUTPUT 0x6d
+/* read flag status register */ +#define FSPI_CMD_RDFSR 0x70 +#define FSPI_CMD_CRFSR 0x50
+/* fsl_fspi_platdata flags */ +#define FSPI_FLAG_REGMAP_ENDIAN_BIG BIT(0)
+/* default SCK frequency, unit: HZ */ +#define FSL_FSPI_DEFAULT_SCK_FREQ 50000000
+/* FSPI max chipselect signals number */ +#define FSL_FSPI_MAX_CHIPSELECT_NUM 4
+#define FSPI_AHB_BASE_ADDR 0x08000000
+/**
- struct fsl_fspi_platdata - platform data for NXP FSPI
- @flags: Flags for FSPI FSPI_FLAG_...
- @speed_hz: Default SCK frequency
- @reg_base: Base address of FSPI registers
- @amba_base: Base address of FSPI memory mapping
- @amba_total_size: size of FSPI memory mapping
- @flash_num: Number of active slave devices
- @num_chipselect: Number of FSPI chipselect signals */ struct
+fsl_fspi_platdata {
- u32 flags;
- u32 speed_hz;
- u32 reg_base;
- u32 amba_base;
- u32 amba_total_size;
- u32 flash_num;
- u32 num_chipselect;
+};
+/**
- struct fsl_fspi_priv - private data for NXP FSPI
- @flags: Flags for FSPI FSPI_FLAG_...
- @bus_clk: FSPI 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 FSPI memory mapping of every CS
- @amba_total_size: size of FSPI memory mapping
- @cur_amba_base: Base address of FSPI memory mapping of current CS
- @flash_num: Number of active slave devices
- @num_chipselect: Number of FSPI chipselect signals
- @regs: Point to FSPI register structure for I/O access */ struct
+fsl_fspi_priv {
- u32 flags;
- u32 bus_clk;
- u32 speed_hz;
- u32 cur_seqid;
- u32 sf_addr;
- u32 amba_base[FSL_FSPI_MAX_CHIPSELECT_NUM];
- u32 amba_total_size;
- u32 cur_amba_base;
- u32 flash_num;
- u32 num_chipselect;
- struct fsl_fspi_regs *regs;
+};
+static u32 fspi_read32(u32 flags, u32 *addr) {
- return flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ?
in_be32(addr) : in_le32(addr);
+}
+static void fspi_write32(u32 flags, u32 *addr, u32 val) {
- flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ?
out_be32(addr, val) : out_le32(addr, val); }
+static void fspi_set_lut(struct fsl_fspi_priv *priv) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 lut_base;
- /* Unlock the LUT */
- fspi_write32(priv->flags, ®s->lutkey, FLEXSPI_LUTKEY_VALUE);
- fspi_write32(priv->flags, ®s->lutcr, FLEXSPI_LCKER_UNLOCK);
- /* READ */
- lut_base = SEQID_READ * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_READ) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1],
OPRND0(0) | PAD0(LUT_PAD1) |
INSTR0(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Write Enable */
- lut_base = SEQID_WREN * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_WREN) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Fast Read */
- lut_base = SEQID_FAST_READ * 4;
+#ifdef CONFIG_SPI_FLASH_BAR
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else
- if (FSL_FSPI_FLASH_SIZE <= SZ_16M)
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_FAST_READ) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
- else
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_FAST_READ_4B) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD) |
OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) |
INSTR1(LUT_ADDR));
+#endif
- fspi_write32(priv->flags, ®s->lut[lut_base + 1],
OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) |
OPRND1(0) | PAD1(LUT_PAD1) |
INSTR1(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Read Status */
- lut_base = SEQID_RDSR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_RDSR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) |
INSTR1(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Erase a sector */
- lut_base = SEQID_SE * 4;
+#ifdef CONFIG_SPI_FLASH_BAR
- fspi_write32(priv->flags, ®s->lut[lut_base], OPRND0(FSPI_CMD_SE) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT)
|
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #else
- if (FSL_FSPI_FLASH_SIZE <= SZ_16M)
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_SE) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
- else
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_SE_4B) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #endif
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Erase the whole chip */
- lut_base = SEQID_CHIP_ERASE * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_CHIP_ERASE) |
PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Page Program */
- lut_base = SEQID_PP * 4;
+#ifdef CONFIG_SPI_FLASH_BAR
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_PP) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1)
|
INSTR1(LUT_ADDR));
+#else
- if (FSL_FSPI_FLASH_SIZE <= SZ_16M)
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_PP) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
- else
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_PP_4B) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #endif
- fspi_write32(priv->flags, ®s->lut[lut_base + 1],
OPRND0(0) |
PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* READ ID */
- lut_base = SEQID_RDID * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_RDID) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(8) | PAD1(LUT_PAD1) |
INSTR1(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* SUB SECTOR 4K ERASE */
- lut_base = SEQID_BE_4K * 4;
+#ifdef CONFIG_SPI_FLASH_BAR
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_BE_4K) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) | PAD1(LUT_PAD1)
|
INSTR1(LUT_ADDR));
+#else
- if (FSL_FSPI_FLASH_SIZE <= SZ_16M)
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_BE_4K) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
- else
fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_BE_4K_4B) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR)); #endif
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
+#ifdef CONFIG_SPI_FLASH_BAR
- /*
* BRRD BRWR RDEAR WREAR are all supported, because it is hard to
* dynamically check whether to set BRRD BRWR or RDEAR WREAR
during
* initialization.
*/
- lut_base = SEQID_BRRD * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_BRRD) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) |
INSTR1(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- lut_base = SEQID_BRWR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_BRWR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) |
INSTR1(LUT_WRITE));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- lut_base = SEQID_RDEAR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_RDEAR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) |
INSTR1(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- lut_base = SEQID_WREAR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_WREAR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) |
INSTR1(LUT_WRITE));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); #endif
- lut_base = SEQID_RDEVCR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_RD_EVCR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- lut_base = SEQID_WREVCR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_WR_EVCR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
+#ifdef CONFIG_FSPI_QUAD_SUPPORT
- /* QUAD OUTPUT READ */
- lut_base = SEQID_QUAD_OUTPUT * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_DDR_QUAD_OUTPUT) |
PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
PAD1(LUT_PAD1) | INSTR1(LUT_ADDR_DDR));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1],
OPRND0(0xc) | PAD0(LUT_PAD4) |
INSTR0(LUT_DUMMY_DDR) | OPRND1(0) |
PAD1(LUT_PAD4) | INSTR1(LUT_READ_DDR));
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0); #endif
- /* Read Flag Status */
- lut_base = SEQID_RDFSR * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_RDFSR) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD) | OPRND1(1) | PAD1(LUT_PAD1) |
INSTR1(LUT_READ));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Enter 4 bytes address mode */
- lut_base = SEQID_EN4B * 4;
- fspi_write32(priv->flags, ®s->lut[lut_base],
OPRND0(FSPI_CMD_EN4B) | PAD0(LUT_PAD1) |
INSTR0(LUT_CMD));
- fspi_write32(priv->flags, ®s->lut[lut_base + 1], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 2], 0);
- fspi_write32(priv->flags, ®s->lut[lut_base + 3], 0);
- /* Lock the LUT */
- fspi_write32(priv->flags, ®s->lutkey, FLEXSPI_LUTKEY_VALUE);
- fspi_write32(priv->flags, ®s->lutcr, FLEXSPI_LCKER_LOCK); }
+#if defined(CONFIG_FSI_AHB) +/*
- If we have changed the content of the flash by writing or erasing,
- we need to invalidate the AHB buffer. If we do not do so, we may
+read out
- the wrong data. The spec tells us reset the AHB domain and Serial
+Flash
- domain at the same time.
- */
+static inline void fspi_ahb_invalid(struct fsl_fspi_priv *priv) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 reg;
- reg = fspi_read32(priv->flags, ®s->mcr0);
- reg |= FLEXSPI_MCR0_SWRST_MASK;
- fspi_write32(priv->flags, ®s->mcr0, reg);
- while ((fspi_read32(priv->flags, ®s->mcr0) & 1))
;
+}
+/* Read out the data from the AHB buffer. */ static inline void +fspi_ahb_read(struct fsl_fspi_priv *priv, u8 *rxbuf,
int len)
+{
- /* Read out the data directly from the AHB buffer. */
- memcpy(rxbuf, (u8 *)(FSPI_AHB_BASE_ADDR +
(uintptr_t)priv->sf_addr), len); }
+/*
- There are two different ways to read out the data from the flash:
- the "IP Command Read" and the "AHB Command Read".
- The IC guy suggests we use the "AHB Command Read" which is faster
- then the "IP Command Read". (What's more is that there is a bug in
- the "IP Command Read" in the Vybrid.)
- After we set up the registers for the "AHB Command Read", we can use
- the memcpy to read the data directly. A "missed" access to the
+buffer
- causes the controller to clear the buffer, and use the sequence
+pointed
- by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
- */
+static void fspi_init_ahb_read(struct fsl_fspi_priv *priv) {
- struct fsl_fspi_regs *regs = priv->regs;
- int i;
- /* AHB configuration for access buffer 0~7 .*/
- for (i = 0; i < 7; i++)
fspi_write32(priv->flags, ®s->ahbrxbuf0cr0 + i, 0);
- /*
* Set ADATSZ with the maximum AHB buffer size to improve the read
* performance
*/
- fspi_write32(priv->flags, ®s->ahbrxbuf7cr0, AHB_BUFFER_SIZE / 8 |
FLEXSPI_AHBRXBUF0CR7_PREF_MASK);
- fspi_write32(priv->flags, ®s->ahbcr,
FLEXSPI_AHBCR_PREF_EN_MASK);
- /*
* Set the default lut sequence for AHB Read.
* Parallel mode is disabled.
*/
+#ifdef CONFIG_FSPI_QUAD_SUPPORT
- fspi_write32(priv->flags, ®s->flsha1cr2, SEQID_QUAD_OUTPUT);
#else
- fspi_write32(priv->flags, ®s->flsha1cr2, SEQID_FAST_READ); #endif }
+#endif
+#ifdef CONFIG_SPI_FLASH_BAR +/* Bank register read/write, EAR register read/write */ static void +fspi_op_rdbank(struct fsl_fspi_priv *priv, u8 *rxbuf, u32 len) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 data, seqid;
- /* invalid the RXFIFO first */
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- if (priv->cur_seqid == FSPI_CMD_BRRD)
seqid = SEQID_BRRD;
- else
seqid = SEQID_RDEAR;
- fspi_write32(priv->flags, ®s->ipcr1,
(seqid << FLEXSPI_IPCR1_SEQID_SHIFT) | len);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr) &
FLEXSPI_INTR_IPCMDDONE_MASK))
;
- while (1) {
data = fspi_read32(priv->flags, ®s->rfdr[0]);
memcpy(rxbuf, &data, len);
break;
- }
- fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK);
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); } +#endif
+static void fspi_op_rdevcr(struct fsl_fspi_priv *priv, u8 *rxbuf, u32 +len) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 data;
- /* invalid the RXFIFO first */
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_RDEVCR << FLEXSPI_IPCR1_SEQID_SHIFT) | len);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- while (1) {
data = fspi_read32(priv->flags, ®s->rfdr[0]);
memcpy(rxbuf, &data, len);
break;
- }
- fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK);
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+static void fspi_op_wrevcr(struct fsl_fspi_priv *priv, u8 *txbuf, u32 +len) {
- struct fsl_fspi_regs *regs = priv->regs;
- /* invalid the TXFIFO first */
- fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- /* Wait for TXFIFO empty*/
- while (!(fspi_read32(priv->flags, ®s->intr) &
FLEXSPI_INTR_IPTXWE_MASK))
;
- /* write the data to TXFIFO */
- memcpy(®s->tfdr, txbuf, len);
- fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPTXWE_MASK);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_WREVCR << FLEXSPI_IPCR1_SEQID_SHIFT) | len);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr) &
FLEXSPI_INTR_IPCMDDONE_MASK))
;
- /* invalid the TXFIFO first */
- fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+static void fspi_op_rdid(struct fsl_fspi_priv *priv, u32 *rxbuf, u32 +len) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 data, size;
- int i;
- /* invalid the RXFIFO first */
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_RDID << FLEXSPI_IPCR1_SEQID_SHIFT) | len);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr) &
FLEXSPI_INTR_IPCMDDONE_MASK))
;
- i = 0;
- while ((len <= RX_BUFFER_SIZE) && (len > 0)) {
data = fspi_read32(priv->flags, ®s->rfdr[i]);
size = (len < 4) ? len : 4;
memcpy(rxbuf, &data, size);
len -= size;
rxbuf++;
i++;
- }
- fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK);
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+#ifndef CONFIG_FSI_AHB +/* If not use AHB read, read data from ip interface */ static void +fspi_op_read(struct fsl_fspi_priv *priv, u32 *rxbuf, u32 len) {
- struct fsl_fspi_regs *regs = priv->regs;
- int i, size, rx_size;
- u32 to_or_from;
- to_or_from = priv->sf_addr + priv->cur_amba_base;
- /* invalid the RXFIFO */
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- while (len > 0) {
WATCHDOG_RESET();
fspi_write32(priv->flags, ®s->ipcr0, to_or_from);
rx_size = (len > RX_BUFFER_SIZE) ?
RX_BUFFER_SIZE : len;
+#ifdef CONFIG_FSPI_QUAD_SUPPORT
fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_QUAD_OUTPUT <<
FLEXSPI_IPCR1_SEQID_SHIFT) |
rx_size);
+#else
fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_FAST_READ << FLEXSPI_IPCR1_SEQID_SHIFT) |
rx_size);
+#endif
to_or_from += rx_size;
len -= rx_size;
/* Trigger the command */
fspi_write32(priv->flags, ®s->ipcmd, 1);
size = rx_size / 8;
for (i = 0; i < size; ++i) {
/* Wait for RXFIFO available*/
while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPRXWA_MASK))
;
memcpy(rxbuf, ®s->rfdr, 8);
rxbuf += 2;
/* move the FIFO pointer */
fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPRXWA_MASK);
}
size = rx_size % 8;
if (size) {
/* Wait for data filled*/
while (!(fspi_read32(priv->flags, ®s->iprxfsts)
& FLEXSPI_IPRXFSTS_FILL_MASK))
;
memcpy(rxbuf, ®s->rfdr, size);
}
/* invalid the RXFIFO */
fspi_write32(priv->flags, ®s->iprxfcr,
FLEXSPI_IPRXFCR_CLR_MASK);
fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK);
- }
+} +#endif
+static void fspi_op_write(struct fsl_fspi_priv *priv, u8 *txbuf, u32 +len) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 seqid;
- int i, size, tx_size;
- u32 to_or_from = 0;
- /* invalid the TXFIFO first */
- fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_WREN << FLEXSPI_IPCR1_SEQID_SHIFT) | 0);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK);
- /* invalid the TXFIFO first */
- fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK);
- to_or_from = priv->sf_addr + priv->cur_amba_base;
- while (len > 0) {
/* Default is page programming */
seqid = SEQID_PP;
+#ifdef CONFIG_SPI_FLASH_BAR
if (priv->cur_seqid == FSPI_CMD_BRWR)
seqid = SEQID_BRWR;
else if (priv->cur_seqid == FSPI_CMD_WREAR)
seqid = SEQID_WREAR;
+#endif
fspi_write32(priv->flags, ®s->ipcr0, to_or_from);
tx_size = (len > TX_BUFFER_SIZE) ?
TX_BUFFER_SIZE : len;
to_or_from += tx_size;
len -= tx_size;
size = tx_size / 8;
for (i = 0; i < size; i++) {
/* Wait for TXFIFO empty*/
while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPTXWE_MASK))
;
memcpy(®s->tfdr, txbuf, 8);
txbuf += 8;
fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPTXWE_MASK);
}
size = tx_size % 8;
if (size) {
/* Wait for TXFIFO empty*/
while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPTXWE_MASK))
;
memcpy(®s->tfdr, txbuf, size);
fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPTXWE_MASK);
}
fspi_write32(priv->flags, ®s->ipcr1,
(seqid << FLEXSPI_IPCR1_SEQID_SHIFT) | tx_size);
/* Trigger the command */
fspi_write32(priv->flags, ®s->ipcmd, 1);
/* Wait for command done */
while (!(fspi_read32(priv->flags, ®s->intr) &
FLEXSPI_INTR_IPCMDDONE_MASK))
;
/* invalid the TXFIFO first */
fspi_write32(priv->flags, ®s->iptxfcr,
FLEXSPI_IPTXFCR_CLR_MASK);
fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK);
- }
+}
+static void fspi_op_rdsr(struct fsl_fspi_priv *priv, void *rxbuf, u32 +len) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 data;
- /* invalid the RXFIFO first */
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_RDSR << FLEXSPI_IPCR1_SEQID_SHIFT) | len);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- data = fspi_read32(priv->flags, ®s->rfdr[0]);
- memcpy(rxbuf, &data, len);
- fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK);
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+static void fspi_op_rdfsr(struct fsl_fspi_priv *priv, void *rxbuf, u32 +len) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 data;
- /* invalid the RXFIFO first */
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_RDFSR << FLEXSPI_IPCR1_SEQID_SHIFT) | len);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- data = fspi_read32(priv->flags, ®s->rfdr[0]);
- memcpy(rxbuf, &data, len);
- fspi_write32(priv->flags, ®s->intr, FLEXSPI_INTR_IPRXWA_MASK);
- fspi_write32(priv->flags, ®s->iprxfcr, FLEXSPI_IPRXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+static void fspi_op_erase(struct fsl_fspi_priv *priv) {
- struct fsl_fspi_regs *regs = priv->regs;
- u32 to_or_from = 0;
- to_or_from = priv->sf_addr + priv->cur_amba_base;
- fspi_write32(priv->flags, ®s->ipcr0, to_or_from);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_WREN << FLEXSPI_IPCR1_SEQID_SHIFT) | 0);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK);
- if (priv->cur_seqid == FSPI_CMD_SE ||
priv->cur_seqid == FSPI_CMD_SE_4B) {
fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_SE << FLEXSPI_IPCR1_SEQID_SHIFT) | 0);
- } else if (priv->cur_seqid == FSPI_CMD_BE_4K ||
priv->cur_seqid == FSPI_CMD_BE_4K_4B) {
fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_BE_4K << FLEXSPI_IPCR1_SEQID_SHIFT) | 0);
- }
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+static void fspi_op_crfsr(struct fsl_fspi_priv *priv) {
- struct fsl_fspi_regs *regs = priv->regs;
- /* invalid the TXFIFO first */
- fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_CRFSR << FLEXSPI_IPCR1_SEQID_SHIFT) | 0);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+static void fspi_op_enter_4bytes(struct fsl_fspi_priv *priv) {
- struct fsl_fspi_regs *regs = priv->regs;
- /* invalid the TXFIFO first */
- fspi_write32(priv->flags, ®s->iptxfcr, FLEXSPI_IPTXFCR_CLR_MASK);
- fspi_write32(priv->flags, ®s->ipcr0, priv->cur_amba_base);
- fspi_write32(priv->flags, ®s->ipcr1,
(SEQID_EN4B << FLEXSPI_IPCR1_SEQID_SHIFT) | 0);
- /* Trigger the command */
- fspi_write32(priv->flags, ®s->ipcmd, 1);
- /* Wait for command done */
- while (!(fspi_read32(priv->flags, ®s->intr)
& FLEXSPI_INTR_IPCMDDONE_MASK))
;
- fspi_write32(priv->flags, ®s->intr,
FLEXSPI_INTR_IPCMDDONE_MASK); }
+int fspi_xfer(struct fsl_fspi_priv *priv, unsigned int bitlen,
const void *dout, void *din, unsigned long flags) {
- u32 bytes = DIV_ROUND_UP(bitlen, 8);
- static u32 wr_sfaddr;
- u32 txbuf = 0;
- if (dout) {
if (flags & SPI_XFER_BEGIN) {
priv->cur_seqid = *(u8 *)dout;
if (bytes > 1) {
int i, addr_bytes;
if (FSL_FSPI_FLASH_SIZE <= SZ_16M)
addr_bytes = 3;
else
+#ifdef CONFIG_SPI_FLASH_BAR
addr_bytes = 3;
+#else
addr_bytes = 4;
+#endif
dout = (u8 *)dout + 1;
txbuf = *(u8 *)dout;
for (i = 1; i < addr_bytes; i++) {
txbuf <<= 8;
txbuf |= *(((u8 *)dout) + i);
}
debug("seqid 0x%x addr 0x%x\n",
priv->cur_seqid, txbuf);
}
}
if (flags == SPI_XFER_END) {
if (priv->cur_seqid == FSPI_CMD_WR_EVCR) {
fspi_op_wrevcr(priv, (u8 *)dout, bytes);
return 0;
} else if ((priv->cur_seqid == FSPI_CMD_SE) ||
(priv->cur_seqid == FSPI_CMD_BE_4K) ||
(priv->cur_seqid == FSPI_CMD_SE_4B) ||
(priv->cur_seqid == FSPI_CMD_BE_4K_4B)) {
int i;
txbuf = *(u8 *)dout;
for (i = 1; i < bytes; i++) {
txbuf <<= 8;
txbuf |= *(((u8 *)dout) + i);
}
priv->sf_addr = txbuf;
fspi_op_erase(priv);
+#ifdef CONFIG_FSI_AHB
fspi_ahb_invalid(priv);
+#endif
return 0;
}
priv->sf_addr = wr_sfaddr;
fspi_op_write(priv, (u8 *)dout, bytes);
return 0;
}
if (priv->cur_seqid == FSPI_CMD_QUAD_OUTPUT ||
priv->cur_seqid == FSPI_CMD_FAST_READ ||
priv->cur_seqid == FSPI_CMD_FAST_READ_4B) {
priv->sf_addr = txbuf;
} else if (priv->cur_seqid == FSPI_CMD_PP ||
priv->cur_seqid == FSPI_CMD_PP_4B) {
wr_sfaddr = txbuf;
} else if (priv->cur_seqid == FSPI_CMD_WR_EVCR) {
wr_sfaddr = 0;
} else if ((priv->cur_seqid == FSPI_CMD_BRWR) ||
(priv->cur_seqid == FSPI_CMD_WREAR)) { #ifdef
CONFIG_SPI_FLASH_BAR
wr_sfaddr = 0;
+#endif
} else if (priv->cur_seqid == FSPI_CMD_EN4B) {
fspi_op_enter_4bytes(priv);
} else if (priv->cur_seqid == FSPI_CMD_CRFSR) {
fspi_op_crfsr(priv);
}
- }
- if (din) {
if (priv->cur_seqid == FSPI_CMD_QUAD_OUTPUT ||
priv->cur_seqid == FSPI_CMD_FAST_READ ||
priv->cur_seqid == FSPI_CMD_FAST_READ_4B) { #ifdef
CONFIG_FSI_AHB
fspi_ahb_read(priv, din, bytes);
+#else
fspi_op_read(priv, din, bytes);
+#endif
} else if (priv->cur_seqid == FSPI_CMD_RDID)
fspi_op_rdid(priv, din, bytes);
else if (priv->cur_seqid == FSPI_CMD_RDSR)
fspi_op_rdsr(priv, din, bytes);
else if (priv->cur_seqid == FSPI_CMD_RDFSR)
fspi_op_rdfsr(priv, din, bytes);
else if (priv->cur_seqid == FSPI_CMD_RD_EVCR)
fspi_op_rdevcr(priv, din, bytes);
+#ifdef CONFIG_SPI_FLASH_BAR
else if (priv->cur_seqid == FSPI_CMD_BRRD ||
priv->cur_seqid == FSPI_CMD_RDEAR) {
priv->sf_addr = 0;
fspi_op_rdbank(priv, din, bytes);
}
+#endif
- }
+#ifdef CONFIG_FSI_AHB
- if (priv->cur_seqid == FSPI_CMD_SE ||
priv->cur_seqid == FSPI_CMD_SE_4B ||
priv->cur_seqid == FSPI_CMD_PP ||
priv->cur_seqid == FSPI_CMD_PP_4B ||
priv->cur_seqid == FSPI_CMD_BE_4K ||
priv->cur_seqid == FSPI_CMD_BE_4K_4B ||
priv->cur_seqid == FSPI_CMD_WREAR ||
priv->cur_seqid == FSPI_CMD_BRWR)
fspi_ahb_invalid(priv);
+#endif
- return 0;
+}
+void fspi_module_disable(struct fsl_fspi_priv *priv, u8 disable) {
- u32 mcr_val;
- mcr_val = fspi_read32(priv->flags, &priv->regs->mcr0);
- if (disable)
mcr_val |= FLEXSPI_MCR0_MDIS_MASK;
- else
mcr_val &= ~FLEXSPI_MCR0_MDIS_MASK;
- fspi_write32(priv->flags, &priv->regs->mcr0, mcr_val); }
+__weak void init_clk_fspi(int index) +{ +}
+static int fsl_fspi_child_pre_probe(struct udevice *dev) {
- struct spi_slave *slave = dev_get_parent_priv(dev);
- slave->max_write_size = TX_BUFFER_SIZE;
+#ifdef CONFIG_FSPI_QUAD_SUPPORT
- slave->mode |= SPI_RX_QUAD;
+#endif
- return 0;
+}
+static int fsl_fspi_probe(struct udevice *bus) {
- u32 total_size;
- struct fsl_fspi_platdata *plat = dev_get_platdata(bus);
- struct fsl_fspi_priv *priv = dev_get_priv(bus);
- struct dm_spi_bus *dm_spi_bus;
- if (CONFIG_IS_ENABLED(CLK)) {
/* Assigned clock already set clock */
struct clk fspi_clk;
int ret;
ret = clk_get_by_name(bus, "fspi", &fspi_clk);
if (ret < 0) {
printf("Can't get fspi clk: %d\n", ret);
return ret;
}
ret = clk_enable(&fspi_clk);
if (ret < 0) {
printf("Can't enable fspi clk: %d\n", ret);
return ret;
}
- } else {
init_clk_fspi(bus->seq);
- }
- dm_spi_bus = bus->uclass_priv;
- dm_spi_bus->max_hz = plat->speed_hz;
- priv->regs = (struct fsl_fspi_regs *)(uintptr_t)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;
- fspi_write32(priv->flags, &priv->regs->mcr0,
FLEXSPI_MCR0_SWRST_MASK);
- do {
udelay(1);
- } while (0x1 & fspi_read32(priv->flags, &priv->regs->mcr0));
- /* Disable the module */
- fspi_module_disable(priv, 1);
- /* Enable the module and set to proper value*/ #ifdef
+CONFIG_FSPI_DQS_LOOPBACK
- fspi_write32(priv->flags, &priv->regs->mcr0, 0xFFFF0010); #else
- fspi_write32(priv->flags, &priv->regs->mcr0, 0xFFFF0000); #endif
- /* Reset the DLL register to default value */
- fspi_write32(priv->flags, &priv->regs->dllacr, 0x0100);
- fspi_write32(priv->flags, &priv->regs->dllbcr, 0x0100);
- /* Flash Size in KByte */
- total_size = FSL_FSPI_FLASH_SIZE * FSL_FSPI_FLASH_NUM >> 10;
- /*
* 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.
*/
- fspi_write32(priv->flags, &priv->regs->flsha1cr0,
total_size);
- fspi_write32(priv->flags, &priv->regs->flsha2cr0,
0);
- fspi_write32(priv->flags, &priv->regs->flshb1cr0,
0);
- fspi_write32(priv->flags, &priv->regs->flshb2cr0,
0);
- fspi_set_lut(priv);
+#ifdef CONFIG_FSI_AHB
- fspi_init_ahb_read(priv);
+#endif
- fspi_module_disable(priv, 0);
- return 0;
+}
+static int fsl_fspi_ofdata_to_platdata(struct udevice *bus) {
- struct fdt_resource res_regs, res_mem;
- struct fsl_fspi_platdata *plat = bus->platdata;
- const void *blob = gd->fdt_blob;
- int node = ofnode_to_offset(bus->node);
- int ret, flash_num = 0, subnode;
- if (fdtdec_get_bool(blob, node, "big-endian"))
plat->flags |= FSPI_FLAG_REGMAP_ENDIAN_BIG;
- ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
"FlexSPI", &res_regs);
- if (ret) {
debug("Error: can't get regs base addresses(ret = %d)!\n", ret);
return -ENOMEM;
- }
- ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
"FlexSPI-memory", &res_mem);
- if (ret) {
debug("Error: can't get AMBA base addresses(ret = %d)!\n", ret);
return -ENOMEM;
- }
- /* Count flash numbers */
- fdt_for_each_subnode(subnode, blob, 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_FSPI_DEFAULT_SCK_FREQ);
- plat->num_chipselect = fdtdec_get_int(blob, node, "num-cs",
FSL_FSPI_MAX_CHIPSELECT_NUM);
- plat->reg_base = res_regs.start;
- plat->amba_base = 0;
- plat->amba_total_size = res_mem.end - res_mem.start + 1;
- plat->flash_num = flash_num;
- debug("%s: regs=<0x%x> <0x%x, 0x%x>, max-frequency=%d,
endianness=%s\n",
__func__, plat->reg_base, plat->amba_base,
plat->amba_total_size, plat->speed_hz,
plat->flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le");
- return 0;
+}
+static int fsl_fspi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags) {
- struct fsl_fspi_priv *priv;
- priv = dev_get_priv(dev->parent);
- return fspi_xfer(priv, bitlen, dout, din, flags); }
+static int fsl_fspi_claim_bus(struct udevice *dev) {
- struct fsl_fspi_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_FSPI_FLASH_SIZE * slave_plat->cs;
- return 0;
+}
+static int fsl_fspi_release_bus(struct udevice *dev) {
- return 0;
+}
+static int fsl_fspi_set_speed(struct udevice *bus, uint speed) {
- /* Nothing to do */
- return 0;
+}
+static int fsl_fspi_set_mode(struct udevice *bus, uint mode) {
- /* Nothing to do */
- return 0;
+}
+static const struct dm_spi_ops fsl_fspi_ops = {
- .claim_bus = fsl_fspi_claim_bus,
- .release_bus = fsl_fspi_release_bus,
- .xfer = fsl_fspi_xfer,
- .set_speed = fsl_fspi_set_speed,
- .set_mode = fsl_fspi_set_mode,
+};
+static const struct udevice_id fsl_fspi_ids[] = {
- { .compatible = "fsl,imx8qm-flexspi" },
- { .compatible = "fsl,imx8qxp-flexspi" },
- { .compatible = "fsl,imx8mm-flexspi" },
- { }
+};
+U_BOOT_DRIVER(fsl_fspi) = {
- .name = "fsl_fspi",
- .id = UCLASS_SPI,
- .of_match = fsl_fspi_ids,
- .ops = &fsl_fspi_ops,
- .ofdata_to_platdata = fsl_fspi_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct fsl_fspi_platdata),
- .priv_auto_alloc_size = sizeof(struct fsl_fspi_priv),
- .probe = fsl_fspi_probe,
- .child_pre_probe = fsl_fspi_child_pre_probe, };
diff --git a/drivers/spi/fsl_fspi.h b/drivers/spi/fsl_fspi.h new file mode 100644 index 0000000000..bff13b9bd8 --- /dev/null +++ b/drivers/spi/fsl_fspi.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright 2019 NXP
- Register definitions for NXP FLEXSPI */
+#ifndef _FSL_FSPI_H_ +#define _FSL_FSPI_H_
+#include <linux/bitops.h>
+struct fsl_fspi_regs {
- u32 mcr0;
- u32 mcr1;
- u32 mcr2;
- u32 ahbcr;
- u32 inten;
- u32 intr;
- u32 lutkey;
- u32 lutcr;
- u32 ahbrxbuf0cr0;
- u32 ahbrxbuf1cr0;
- u32 ahbrxbuf2cr0;
- u32 ahbrxbuf3cr0;
- u32 ahbrxbuf4cr0;
- u32 ahbrxbuf5cr0;
- u32 ahbrxbuf6cr0;
- u32 ahbrxbuf7cr0;
- u32 ahbrxbuf0cr1;
- u32 ahbrxbuf1cr1;
- u32 ahbrxbuf2cr1;
- u32 ahbrxbuf3cr1;
- u32 ahbrxbuf4cr1;
- u32 ahbrxbuf5cr1;
- u32 ahbrxbuf6cr1;
- u32 ahbrxbuf7cr1;
- u32 flsha1cr0;
- u32 flsha2cr0;
- u32 flshb1cr0;
- u32 flshb2cr0;
- u32 flsha1cr1;
- u32 flsha2cr1;
- u32 flshb1cr1;
- u32 flshb2cr1;
- u32 flsha1cr2;
- u32 flsha2cr2;
- u32 flshb1cr2;
- u32 flshb2cr2;
- u32 flshcr3;
- u32 flshcr4;
- u32 flshcr5;
- u32 flshcr6;
- u32 ipcr0;
- u32 ipcr1;
- u32 ipcr2;
- u32 ipcr3;
- u32 ipcmd;
- u32 dlpr;
- u32 iprxfcr;
- u32 iptxfcr;
- u32 dllacr;
- u32 dllbcr;
- u32 soccr;
- u32 misccr2;
- u32 misccr3;
- u32 misccr4;
- u32 misccr5;
- u32 misccr6;
- u32 sts0;
- u32 sts1;
- u32 sts2;
- u32 ahbspndsts;
- u32 iprxfsts;
- u32 iptxfsts;
- u32 rsvd[2];
- u32 rfdr[32];
- u32 tfdr[32];
- u32 lut[128];
+};
+/* The registers */ +#define FLEXSPI_MCR0_MDIS_SHIFT 1 +#define FLEXSPI_MCR0_MDIS_MASK BIT(1) +#define FLEXSPI_MCR0_SWRST_SHIFT 0 +#define FLEXSPI_MCR0_SWRST_MASK BIT(0)
+#define FLEXSPI_AHBCR_PREF_EN_SHIFT 5 +#define FLEXSPI_AHBCR_PREF_EN_MASK BIT(5)
+#define FLEXSPI_INTR_IPTXWE_SHIFT 6 +#define FLEXSPI_INTR_IPTXWE_MASK BIT(6) +#define FLEXSPI_INTR_IPRXWA_SHIFT 5 +#define FLEXSPI_INTR_IPRXWA_MASK BIT(5) +#define FLEXSPI_INTR_IPCMDDONE_SHIFT 0 +#define FLEXSPI_INTR_IPCMDDONE_MASK BIT(0)
+#define FLEXSPI_LUTKEY_VALUE 0x5AF05AF0
+#define FLEXSPI_LCKER_LOCK 0x1 +#define FLEXSPI_LCKER_UNLOCK 0x2
+#define FLEXSPI_BUFXCR_INVALID_MSTRID 0xe +#define FLEXSPI_AHBRXBUF0CR7_PREF_SHIFT 31 +#define FLEXSPI_AHBRXBUF0CR7_PREF_MASK BIT(31)
+#define FLEXSPI_IPCR1_SEQID_SHIFT 16
+#define FLEXSPI_IPRXFCR_CLR_SHIFT 0 +#define FLEXSPI_IPRXFCR_CLR_MASK BIT(0)
+#define FLEXSPI_IPTXFCR_CLR_SHIFT 0 +#define FLEXSPI_IPTXFCR_CLR_MASK BIT(0)
+#define FLEXSPI_IPRXFSTS_FILL_SHIFT 0 +#define FLEXSPI_IPRXFSTS_FILL_MASK (0xFF << FLEXSPI_IPRXFSTS_FILL_SHIFT)
+/* register map end */
+#define OPRND0_SHIFT 0 +#define OPRND0(x) ((x) << OPRND0_SHIFT) +#define PAD0_SHIFT 8 +#define PAD0(x) ((x) << PAD0_SHIFT) +#define INSTR0_SHIFT 10 +#define INSTR0(x) ((x) << INSTR0_SHIFT) +#define OPRND1_SHIFT 16 +#define OPRND1(x) ((x) << OPRND1_SHIFT) +#define PAD1_SHIFT 24 +#define PAD1(x) ((x) << PAD1_SHIFT) +#define INSTR1_SHIFT 26 +#define INSTR1(x) ((x) << INSTR1_SHIFT)
+#define LUT_STOP 0x00 +#define LUT_CMD 0x01 +#define LUT_ADDR 0x02 +#define LUT_CADDR_SDR 0x03 +#define LUT_MODE 0x04 +#define LUT_MODE2 0x05 +#define LUT_MODE4 0x06 +#define LUT_MODE8 0x07 +#define LUT_WRITE 0x08 +#define LUT_READ 0x09 +#define LUT_LEARN_SDR 0x0A +#define LUT_DATSZ_SDR 0x0B +#define LUT_DUMMY 0x0C +#define LUT_DUMMY_RWDS_SDR 0x0D +#define LUT_JMP_ON_CS 0x1F +#define LUT_CMD_DDR 0x21 +#define LUT_ADDR_DDR 0x22 +#define LUT_CADDR_DDR 0x23 +#define LUT_MODE_DDR 0x24 +#define LUT_MODE2_DDR 0x25 +#define LUT_MODE4_DDR 0x26 +#define LUT_MODE8_DDR 0x27 +#define LUT_WRITE_DDR 0x28 +#define LUT_READ_DDR 0x29 +#define LUT_LEARN_DDR 0x2A +#define LUT_DATSZ_DDR 0x2B +#define LUT_DUMMY_DDR 0x2C +#define LUT_DUMMY_RWDS_DDR 0x2D
+#define LUT_PAD1 0 +#define LUT_PAD2 1 +#define LUT_PAD4 2 +#define LUT_PAD8 3
+#define ADDR24BIT 0x18 +#define ADDR32BIT 0x20
+#endif /* _FSL_FSPI_H_ */
2.16.4
participants (1)
-
Peng Fan