[U-Boot] [PATCH] driver/spi: Add FSPI driver for NXP FlexSPI controller

Ashish Kumar Ashish.Kumar at nxp.com
Tue Sep 25 08:41:34 UTC 2018


Add nxp_fspi driver for NXP FlexSPI controller.
This driver supports both IP Mode read/write and
AHB mode READ.

It supports Single Bit mode read along with Fast Read cmd support.
Octal bit mode is supported for read.
Multi CS are supported tested until 4.

Signed-off-by: Suresh Gupta <suresh.gupta at nxp.com>
Signed-off-by: Yogesh Gaur <yogeshnarayan.gaur at nxp.com>
Signed-off-by: Rajat Srivastava <Rajat.srivastava at nxp.com>
Signed-off-by: Ashish Kumar <Ashish.Kumar at nxp.com>
---
 arch/arm/cpu/armv8/fsl-layerscape/Kconfig |   10 +
 drivers/spi/Kconfig                       |    7 +
 drivers/spi/Makefile                      |    1 +
 drivers/spi/nxp_fspi.c                    | 1088 +++++++++++++++++++++
 drivers/spi/nxp_fspi.h                    |  422 ++++++++
 5 files changed, 1528 insertions(+)
 create mode 100644 drivers/spi/nxp_fspi.c
 create mode 100644 drivers/spi/nxp_fspi.h

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index f2111fadc0..5280d33ec8 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -317,6 +317,16 @@ config QSPI_AHB_INIT
 	  But some QSPI flash size up to 64MBytes, so initialize the QSPI AHB
 	  bus for those flashes to support the full QSPI flash size.
 
+config SYS_FSPI_AHB_INIT
+	bool "Initialize the FlexSPI controller for AHB mode"
+	depends on NXP_FSPI
+	default n
+	help
+	  Initialize the FlexSPI controller for AHB mode and mark default
+	  read mode as AHB mode. In AHB mode, direct memory copying is
+	  performed. Default LUT programmed in AHB mode is Fast Read command
+	  with 4-byte addressing enabled.
+
 config SYS_CCI400_OFFSET
 	hex "Offset for CCI400 base"
 	depends on SYS_FSL_HAS_CCI400
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index dcd719ff0a..7c2ccfa6bc 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -242,6 +242,13 @@ config ZYNQMP_GQSPI
 	  This option is used to enable ZynqMP QSPI controller driver which
 	  is used to communicate with qspi flash devices.
 
+config NXP_FSPI
+	bool "NXP FLEXSPI driver"
+	help
+	  Enable the NXP Flex-SPI (FSPI) driver. This driver can be used to
+	  access SPI NOR flash on platforms embedding this NXP IP code.
+	  This driver support SPI flash read, write and erase.
+
 endif # if DM_SPI
 
 config SOFT_SPI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 728e30c538..71f914543c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
 obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
 obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
 obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
+obj-$(CONFIG_NXP_FSPI) += nxp_fspi.o
 obj-$(CONFIG_ICH_SPI) +=  ich.o
 obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c
new file mode 100644
index 0000000000..9a9e6371c8
--- /dev/null
+++ b/drivers/spi/nxp_fspi.c
@@ -0,0 +1,1088 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ *
+ * NXP Flex Serial Peripheral Interface (FSPI) driver
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+#include <dm.h>
+#include <errno.h>
+#include "nxp_fspi.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* default SCK frequency, unit: HZ */
+#define NXP_FSPI_DEFAULT_SCK_FREQ	50000000
+
+/* FSPI max chipselect signals number */
+#define NXP_FSPI_MAX_CHIPSELECT_NUM     4
+
+#define NXP_FSPI_MAX_TIMEOUT_AHBCMD	0xFF
+#define NXP_FSPI_MAX_TIMEOUT_IPCMD	0xFF
+#define NXP_FSPI_SER_CLK_DIV		0x00
+
+#define FSPI_FLAG_REGMAP_ENDIAN_BIG	BIT(0)
+
+#define FSPI_RX_MAX_IPBUF_SIZE		0x200 /* 64 * 64bits  */
+#define FSPI_TX_MAX_IPBUF_SIZE		0x400 /* 128 * 64bits */
+#define FSPI_RX_MAX_AHBBUF_SIZE		0x800 /* 256 * 64bits */
+#define FSPI_TX_MAX_AHBBUF_SIZE		0x40  /* 8 * 64bits   */
+
+#define TX_IPBUF_SIZE		FSPI_TX_MAX_IPBUF_SIZE
+#define RX_IPBUF_SIZE		FSPI_RX_MAX_IPBUF_SIZE
+#define RX_AHBBUF_SIZE		FSPI_RX_MAX_AHBBUF_SIZE
+#define TX_AHBBUF_SIZE		FSPI_TX_MAX_AHBBUF_SIZE
+
+/* 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
+#define SEQID_RDFSR		9
+#define SEQID_ENTR4BYTE		10
+#define SEQID_OCTAL_READ	11
+
+/* FSPI CMD */
+#define FSPI_CMD_PP		0x02	/* Page program (up to 256 bytes) */
+#define FSPI_CMD_RDSR		0x05	/* Read status register */
+#define FSPI_CMD_RDFSR		0x70	/* Read flag status register */
+#define FSPI_CMD_WREN		0x06	/* Write enable */
+#define FSPI_CMD_READ		0x03	/* Read data bytes */
+#define FSPI_CMD_FAST_READ	0x0b	/* Read data bytes (high frequency) */
+#define FSPI_CMD_OCTAL_READ	0x8b	/* Octal Read (CMD-ADDR-DATA : 1-1-8) */
+#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 */
+
+#define FSPI_CMD_ENTR4BYTE	0xb7	/* Enter 4-Byte Address Mode */
+#define FSPI_CMD_EXIT4BYTE	0xe9	/* Exit 4-Byte Address Mode */
+
+/* 4-byte address QSPI CMD - used on Spansion and some Macronix flashes */
+#define FSPI_CMD_FAST_READ_4B	0x0c    /* Read data bytes (high frequency) */
+#define FSPI_CMD_OCTAL_READ_4B	0x7c	/* Octal Read (CMD-ADDR-DATA : 1-1-8) */
+#define FSPI_CMD_PP_4B		0x12    /* Page program (up to 256 bytes) */
+#define FSPI_CMD_BE_4K_4B	0x21    /* 4K erase */
+#define FSPI_CMD_SE_4B		0xdc    /* Sector erase (usually 64KiB) */
+
+/* Number of SPI lines supported for Rx and Tx lines */
+#define FSPI_SINGLE_MODE	0x1
+#define FSPI_DUAL_MODE		0x2
+#define FSPI_QUAD_MODE		0x4
+#define FSPI_OCTAL_MODE		0x8
+
+/* Default SPI Rx bus width and SPI Tx bus width */
+#define NXP_FSPI_DEFAULT_SPI_RX_BUS_WIDTH	FSPI_SINGLE_MODE
+#define NXP_FSPI_DEFAULT_SPI_TX_BUS_WIDTH	FSPI_SINGLE_MODE
+
+#ifdef CONFIG_DM_SPI
+
+/**
+ * struct nxp_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
+ * @memmap_phy: Physical base address of FSPI memory mapping
+ * @flash_num: Number of active slave devices
+ * @num_chipselect: Number of FSPI chipselect signals
+ * @fspi_rx_bus_width: Number of SPI lines the flash supports for Rx
+ * @fspi_tx_bus_width: Number of SPI lines the flash supports for Tx
+ * @fspi_has_second_chip: Flash device connected on CS1
+ */
+struct nxp_fspi_platdata {
+	u32 flags; /*future use*/
+	u32 speed_hz;
+	fdt_addr_t reg_base;
+	fdt_addr_t amba_base;
+	fdt_size_t amba_total_size;
+	fdt_size_t memmap_phy;
+	u32 flash_num;
+	u32 num_chipselect;
+	u32 fspi_rx_bus_width;
+	u32 fspi_tx_bus_width;
+	bool fspi_has_second_chip;
+};
+
+/**
+ * struct nxp_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
+ * @memmap_phy: Physical base address of FSPI memory mapping
+ * @regs: Point to FSPI register structure for I/O access
+ * @fspi_rx_bus_width: Number of SPI lines the flash supports for Rx
+ * @fspi_tx_bus_width: Number of SPI lines the flash supports for Tx
+ * @fspi_has_second_chip: Flash device connected on CS1
+ */
+struct nxp_fspi_priv {
+	u32 flags; /*future use*/
+	u32 bus_clk;
+	u32 speed_hz;
+	u32 cur_seqid;
+	u32 sf_addr;
+	u32 amba_base[NXP_FSPI_MAX_CHIPSELECT_NUM];
+	u32 amba_total_size;
+	u32 cur_amba_base;
+	u32 flash_num;
+	u32 num_chipselect;
+	u32 memmap_phy;
+	u32 fspi_rx_bus_width;
+	u32 fspi_tx_bus_width;
+	bool fspi_has_second_chip;
+	struct nxp_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);
+}
+
+void fspi_lut_lock(struct nxp_fspi_priv *priv, u8 lock)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+
+	fspi_write32(priv->flags, &regs->lutkey, FSPI_LUTKEY_VALUE);
+
+	if (lock)
+		fspi_write32(priv->flags, &regs->lutcr, FSPI_LUTCR_LOCK);
+	else
+		fspi_write32(priv->flags, &regs->lutcr, FSPI_LUTCR_UNLOCK);
+}
+
+static void fspi_set_lut(struct nxp_fspi_priv *priv)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	u32 lut_base;
+
+	/* Unlock the LUT */
+	fspi_lut_lock(priv, 0);
+
+	/* READ */
+	lut_base = SEQID_READ * 4;
+	fspi_write32(priv->flags, &regs->lut[lut_base],
+		     OPRND0(FSPI_CMD_READ) | PAD0(LUT_PAD1) |
+		     INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+		     PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1],
+		     OPRND0(0) | PAD0(LUT_PAD1) |
+		     INSTR0(LUT_READ));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Write Enable */
+	lut_base = SEQID_WREN * 4;
+	fspi_write32(priv->flags, &regs->lut[lut_base], OPRND0(FSPI_CMD_WREN) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Fast Read */
+	lut_base = SEQID_FAST_READ * 4;
+	if (NXP_FSPI_FLASH_SIZE <= SZ_16M)
+		fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base],
+			     OPRND0(FSPI_CMD_FAST_READ_4B) |
+			     PAD0(LUT_PAD1) | INSTR0(LUT_CMD) |
+			     OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) |
+			     INSTR1(LUT_ADDR));
+
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1],
+		     OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) |
+		     OPRND1(0) | PAD1(LUT_PAD1) |
+		     INSTR1(LUT_READ));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Read Status */
+	lut_base = SEQID_RDSR * 4;
+	fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Erase a sector */
+	lut_base = SEQID_SE * 4;
+	if (NXP_FSPI_FLASH_SIZE <= SZ_16M)
+		fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base],
+			     OPRND0(FSPI_CMD_SE_4B) | PAD0(LUT_PAD1) |
+			     INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
+			     PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Erase the whole chip */
+	lut_base = SEQID_CHIP_ERASE * 4;
+	fspi_write32(priv->flags, &regs->lut[lut_base],
+		     OPRND0(FSPI_CMD_CHIP_ERASE) |
+		     PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Page Program */
+	lut_base = SEQID_PP * 4;
+	if (NXP_FSPI_FLASH_SIZE <= SZ_16M)
+		fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base],
+			     OPRND0(FSPI_CMD_PP_4B) | PAD0(LUT_PAD1) |
+			     INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
+			     PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1],
+		     OPRND0(0) |
+		     PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* READ ID */
+	lut_base = SEQID_RDID * 4;
+	fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* SUB SECTOR 4K ERASE */
+	lut_base = SEQID_BE_4K * 4;
+	if (NXP_FSPI_FLASH_SIZE <= SZ_16M)
+		fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base],
+			     OPRND0(FSPI_CMD_BE_4K_4B) | PAD0(LUT_PAD1) |
+			     INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
+			     PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+
+	/* Read Flag Status */
+	lut_base = SEQID_RDFSR * 4;
+	fspi_write32(priv->flags, &regs->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, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Enter 4-Byte Address Mode */
+	lut_base = SEQID_ENTR4BYTE * 4;
+	fspi_write32(priv->flags, &regs->lut[lut_base],
+		     OPRND0(FSPI_CMD_ENTR4BYTE) |
+		     PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* 8-Bit Read */
+	lut_base = SEQID_OCTAL_READ * 4;
+	if (NXP_FSPI_FLASH_SIZE <= SZ_16M)
+		fspi_write32(priv->flags, &regs->lut[lut_base],
+			     OPRND0(FSPI_CMD_OCTAL_READ) |
+			     PAD0(LUT_PAD1) | INSTR0(LUT_CMD) |
+			     OPRND1(ADDR24BIT) | PAD1(LUT_PAD1) |
+			     INSTR1(LUT_ADDR));
+	else
+		fspi_write32(priv->flags, &regs->lut[lut_base],
+			     OPRND0(FSPI_CMD_OCTAL_READ_4B) |
+			     PAD0(LUT_PAD1) | INSTR0(LUT_CMD) |
+			     OPRND1(ADDR32BIT) | PAD1(LUT_PAD1) |
+			     INSTR1(LUT_ADDR));
+
+	fspi_write32(priv->flags, &regs->lut[lut_base + 1],
+		     OPRND0(8) | PAD0(LUT_PAD8) | INSTR0(LUT_DUMMY) |
+		     OPRND1(0) | PAD1(LUT_PAD8) |
+		     INSTR1(LUT_READ));
+	fspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	fspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
+	/* Lock the LUT */
+	fspi_lut_lock(priv, 1);
+}
+
+void fspi_module_disable(struct nxp_fspi_priv *priv, u8 disable)
+{
+	u32 mcr0;
+
+	mcr0 = fspi_read32(priv->flags, &priv->regs->mcr0);
+	if (disable)
+		mcr0 |= FSPI_MCR0_MDIS_MASK;
+	else
+		mcr0 &= ~FSPI_MCR0_MDIS_MASK;
+	fspi_write32(priv->flags, &priv->regs->mcr0, mcr0);
+}
+
+static void fspi_op_write_cmd(struct nxp_fspi_priv *priv)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	u32 seqid;
+
+	/*
+	 * Increase write cmds list as required.
+	 * For now below write cmds support is there:
+	 * 'Write Enable' and 'Enter 4 Byte'
+	 */
+	if (priv->cur_seqid == FSPI_CMD_WREN)
+		seqid = SEQID_WREN;
+	else if (priv->cur_seqid == FSPI_CMD_ENTR4BYTE)
+		seqid = SEQID_ENTR4BYTE;
+	else
+		return;
+
+	/* invalid the TXFIFO first */
+	fspi_write32(priv->flags, &regs->iptxfcr, FSPI_IPTXFCR_CLRIPTXF_MASK);
+
+	/* set address value in IPCR0 register. */
+	fspi_write32(priv->flags, &regs->ipcr0, priv->cur_amba_base);
+
+	/*Push SEQID in IPCR1 */
+	fspi_write32(priv->flags, &regs->ipcr1,
+		     (seqid << FSPI_IPCR1_ISEQID_SHIFT) | 0);
+
+	/* Trigger the command */
+	fspi_write32(priv->flags, &regs->ipcmd, FSPI_IPCMD_TRG_MASK);
+
+	/* Wait for command done */
+	while (!(fspi_read32(priv->flags, &regs->intr)
+		 & FSPI_INTR_IPCMDDONE_MASK))
+		;
+
+	fspi_write32(priv->flags, &regs->intr, FSPI_INTR_IPCMDDONE_MASK);
+}
+
+#if defined(CONFIG_SYS_FSPI_AHB_INIT)
+
+/*
+ * 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 to reset the AHB domain and Serial Flash
+ * domain at the same time.
+ */
+static inline void fspi_ahb_invalid(struct nxp_fspi_priv *priv)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	u32 reg;
+
+	reg = fspi_read32(priv->flags, &regs->mcr0);
+	reg |= FSPI_MCR0_SWRESET_MASK;
+	fspi_write32(priv->flags, &regs->mcr0, reg);
+
+	/*
+	 * The minimum delay : 1 AHB + 2 SFCK clocks.
+	 * Delay 1 us is enough.
+	 */
+	while ((fspi_read32(priv->flags, &regs->mcr0) & 1))
+		;
+}
+
+/* Read out the data from the AHB buffer. */
+static inline void fspi_ahb_read(struct nxp_fspi_priv *priv, u8 *rxbuf, int len)
+{
+	void *rx_addr = NULL;
+
+	debug("FSPI AHB Read Invoked from:[0x%02x] len:[0x%02x]\n",
+	      (priv->memmap_phy + priv->cur_amba_base + priv->sf_addr), len);
+	rx_addr = (void *)(uintptr_t)(priv->memmap_phy +
+				      priv->cur_amba_base +
+				      priv->sf_addr);
+
+	/* Read out the data directly from the AHB buffer. */
+	memcpy(rxbuf, rx_addr, len);
+}
+
+/*
+ * There are two different ways to read out the data from the flash:
+ * the "IP Command Read" and the "AHB Command Read".
+ * "AHB Command Read" is faster then the "IP Command Read".
+ *
+ * After we set up the registers for the "AHB Command Read", we can use
+ * the memcpy to read the data directly.
+ */
+static void fspi_init_ahb_read(struct nxp_fspi_priv *priv)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	int i;
+
+	/* AHB configuration for access buffer 0~7. */
+	for (i = 0; i < 7; i++)
+		fspi_write32(priv->flags, &regs->ahbrxbuf0cr0 + i, 0);
+
+	/*
+	 * Set ADATSZ with the maximum AHB buffer size to improve the read
+	 * performance
+	 */
+	fspi_write32(priv->flags, &regs->ahbrxbuf7cr0,
+		     FSPI_RX_MAX_AHBBUF_SIZE / 8 |
+		     FSPI_AHBBUFXCR0_PREFETCHEN_MASK);
+
+	fspi_write32(priv->flags, &regs->ahbcr,
+		     FSPI_AHBCR_PREFETCHEN_MASK |
+		     FSPI_AHBCR_READADDROPT_MASK);
+
+	/*
+	 * Set default lut sequence for AHB Read, bit[4-0] in flsha1cr2 reg.
+	 * Parallel mode is disabled.
+	 */
+
+	if (priv->fspi_rx_bus_width == FSPI_OCTAL_MODE) {
+		/* Flash supports octal read */
+		fspi_write32(priv->flags, &regs->flsha1cr2, SEQID_OCTAL_READ);
+	} else {
+		/* Flash supports single bit read */
+		fspi_write32(priv->flags, &regs->flsha1cr2, SEQID_FAST_READ);
+	}
+}
+#endif
+
+static void fspi_op_rdxx(struct nxp_fspi_priv *priv, u32 *rxbuf, u32 len)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	u32 iprxfcr = 0;
+	u32 data, size;
+	int i;
+
+	iprxfcr = fspi_read32(priv->flags, &regs->iprxfcr);
+	/* IP RX FIFO would be read by processor */
+	iprxfcr &= ~FSPI_IPRXFCR_RXDMAEN_MASK;
+	/* Invalid data entries in IP RX FIFO */
+	iprxfcr = iprxfcr | FSPI_IPRXFCR_CLRIPRXF_MASK;
+	fspi_write32(priv->flags, &regs->iprxfcr, iprxfcr);
+
+	fspi_write32(priv->flags, &regs->ipcr0, priv->cur_amba_base);
+
+	if (priv->cur_seqid == FSPI_CMD_RDID)
+		fspi_write32(priv->flags, &regs->ipcr1,
+			     (SEQID_RDID << FSPI_IPCR1_ISEQID_SHIFT) |
+			     (u16)len);
+	else if (priv->cur_seqid == FSPI_CMD_RDSR)
+		fspi_write32(priv->flags, &regs->ipcr1,
+			     (SEQID_RDSR << FSPI_IPCR1_ISEQID_SHIFT) |
+			     (u16)len);
+	else if (priv->cur_seqid == FSPI_CMD_RDFSR)
+		fspi_write32(priv->flags, &regs->ipcr1,
+			     (SEQID_RDFSR << FSPI_IPCR1_ISEQID_SHIFT) |
+			     (u16)len);
+
+	/* Trigger the IP command */
+	fspi_write32(priv->flags, &regs->ipcmd, FSPI_IPCMD_TRG_MASK);
+
+	/* Wait for command done */
+	while (!(fspi_read32(priv->flags, &regs->intr)
+		 & FSPI_INTR_IPCMDDONE_MASK))
+		;
+
+	i = 0;
+	while ((len <= RX_IPBUF_SIZE) && (len > 0)) {
+		data = fspi_read32(priv->flags, &regs->rfdr[i]);
+		size = (len < 4) ? len : 4;
+		memcpy(rxbuf, &data, size);
+		len -= size;
+		rxbuf++;
+		i++;
+	}
+
+	/* Rx FIFO invalidation needs to be done prior w1c of INTR.IPRXWA bit */
+	fspi_write32(priv->flags, &regs->iprxfcr, FSPI_IPRXFCR_CLRIPRXF_MASK);
+	fspi_write32(priv->flags, &regs->intr, FSPI_INTR_IPRXWA_MASK);
+	fspi_write32(priv->flags, &regs->intr, FSPI_INTR_IPCMDDONE_MASK);
+}
+
+#ifndef CONFIG_SYS_FSPI_AHB_INIT
+/* If AHB read interface not defined, read data from ip interface. */
+static void fspi_op_read(struct nxp_fspi_priv *priv, u32 *rxbuf, u32 len)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	int i, j;
+	int size, rx_size, wm_size, temp_size;
+	u32 to_or_from, data = 0;
+
+	to_or_from = priv->sf_addr + priv->cur_amba_base;
+
+	debug("Read [to_or_frm:0x%02x]\n", to_or_from);
+	/* invalid the RXFIFO */
+	fspi_write32(priv->flags, &regs->iprxfcr, FSPI_IPRXFCR_CLRIPRXF_MASK);
+
+	while (len > 0) {
+		fspi_write32(priv->flags, &regs->ipcr0, to_or_from);
+
+		rx_size = (len > RX_IPBUF_SIZE) ? RX_IPBUF_SIZE : len;
+
+		if (priv->fspi_rx_bus_width == FSPI_OCTAL_MODE) {
+			/* Flash supports octal read */
+			fspi_write32(priv->flags, &regs->ipcr1,
+				     (SEQID_OCTAL_READ <<
+				      FSPI_IPCR1_ISEQID_SHIFT) | (u16)rx_size);
+		} else {
+			/* Flash supports single bit read */
+			fspi_write32(priv->flags, &regs->ipcr1,
+				     (SEQID_FAST_READ <<
+				      FSPI_IPCR1_ISEQID_SHIFT) | (u16)rx_size);
+		}
+
+		to_or_from += rx_size;
+		len -= rx_size;
+
+		/* Trigger the command */
+		fspi_write32(priv->flags, &regs->ipcmd, FSPI_IPCMD_TRG_MASK);
+
+		/* Default value of water mark level is 8 bytes. */
+		wm_size = 8;
+
+		size = rx_size / wm_size;
+		for (i = 0; i < size; ++i) {
+			/* Wait for RXFIFO available*/
+			while (!(fspi_read32(priv->flags, &regs->intr)
+				 & FSPI_INTR_IPRXWA_MASK))
+				;
+
+			temp_size = wm_size;
+			j = 0;
+			while (temp_size > 0) {
+				data = 0;
+				data = fspi_read32(priv->flags,
+						   &regs->rfdr[j++]);
+				temp_size = wm_size - 4 * j;
+				memcpy(rxbuf, &data, 4);
+				rxbuf++;
+			}
+
+			/* move the FIFO pointer */
+			fspi_write32(priv->flags, &regs->intr,
+				     FSPI_INTR_IPRXWA_MASK);
+		}
+
+		size = rx_size % 8;
+
+		if (size) {
+			/* Wait for data filled*/
+			while (!(fspi_read32(priv->flags, &regs->iprxfsts)
+				 & FSPI_IPRXFSTS_FILL_MASK))
+				;
+
+			temp_size = 0;
+			data = 0;
+			j = 0;
+			while (size > 0) {
+				data = 0;
+				data = fspi_read32(priv->flags,
+						   &regs->rfdr[j++]);
+				temp_size = (size < 4) ? size : 4;
+				memcpy(rxbuf, &data, temp_size);
+				size -= temp_size;
+				rxbuf++;
+			}
+		}
+
+		/* invalid the RXFIFO */
+		fspi_write32(priv->flags, &regs->iprxfcr,
+			     FSPI_IPRXFCR_CLRIPRXF_MASK);
+		/* move the FIFO pointer */
+		fspi_write32(priv->flags, &regs->intr,
+			     FSPI_INTR_IPRXWA_MASK);
+		fspi_write32(priv->flags, &regs->intr,
+			     FSPI_INTR_IPCMDDONE_MASK);
+	}
+}
+#endif
+
+static void fspi_op_erase(struct nxp_fspi_priv *priv)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	u32 to_or_from = 0;
+
+	to_or_from = priv->sf_addr + priv->cur_amba_base;
+	fspi_write32(priv->flags, &regs->ipcr0, to_or_from);
+
+	if (priv->cur_seqid == FSPI_CMD_SE) {
+		fspi_write32(priv->flags, &regs->ipcr1,
+			     (SEQID_SE << FSPI_IPCR1_ISEQID_SHIFT) | 0);
+	} else if (priv->cur_seqid == FSPI_CMD_BE_4K) {
+		fspi_write32(priv->flags, &regs->ipcr1,
+			     (SEQID_BE_4K << FSPI_IPCR1_ISEQID_SHIFT) | 0);
+	}
+	/* Trigger the command */
+	fspi_write32(priv->flags, &regs->ipcmd, FSPI_IPCMD_TRG_MASK);
+
+	while (!(fspi_read32(priv->flags, &regs->intr)
+		 & FSPI_INTR_IPCMDDONE_MASK))
+		;
+
+	fspi_write32(priv->flags, &regs->intr, FSPI_INTR_IPCMDDONE_MASK);
+}
+
+static void fspi_op_write(struct nxp_fspi_priv *priv, u8 *txbuf, u32 len)
+{
+	struct nxp_fspi_regs *regs = priv->regs;
+	u32 seqid;
+	int i, j;
+	int size = 0, tx_size = 0, wm_size = 0, temp_size = 0;
+	u32 to_or_from = 0, data = 0;
+
+	/* invalid the TXFIFO first */
+	fspi_write32(priv->flags, &regs->iptxfcr, FSPI_IPTXFCR_CLRIPTXF_MASK);
+
+	to_or_from = priv->sf_addr + priv->cur_amba_base;
+
+	debug("Write [to_or_frm:0x%02x]\n", to_or_from);
+	while (len > 0) {
+		/* Default is page programming */
+		seqid = SEQID_PP;
+		fspi_write32(priv->flags, &regs->ipcr0, to_or_from);
+
+		tx_size = (len > TX_IPBUF_SIZE) ? TX_IPBUF_SIZE : len;
+
+		to_or_from += tx_size;
+		len -= tx_size;
+
+		/* Default value of water mark level is 8 bytes. */
+		wm_size = 8;
+
+		size = tx_size / wm_size;
+		for (i = 0; i < size; i++) {
+			/* Wait for TXFIFO empty*/
+			while (!(fspi_read32(priv->flags, &regs->intr)
+				 & FSPI_INTR_IPTXWE_MASK))
+				;
+
+			temp_size = wm_size;
+			j = 0;
+			while (temp_size > 0) {
+				data = 0;
+				memcpy(&data, txbuf, 4);
+				fspi_write32(priv->flags, &regs->tfdr[j++],
+					     data);
+				temp_size = wm_size - 4 * j;
+				txbuf += 4;
+			}
+
+			fspi_write32(priv->flags, &regs->intr,
+				     FSPI_INTR_IPTXWE_MASK);
+		}
+
+		size = tx_size % 8;
+		if (size) {
+			/* Wait for TXFIFO empty*/
+			while (!(fspi_read32(priv->flags, &regs->intr)
+				 & FSPI_INTR_IPTXWE_MASK))
+				;
+
+			temp_size = 0;
+			j = 0;
+			while (size > 0) {
+				data = 0;
+				temp_size = (size < 4) ? size : 4;
+				memcpy(&data, txbuf, temp_size);
+				fspi_write32(priv->flags, &regs->tfdr[j++],
+					     data);
+				size -= temp_size;
+				txbuf += temp_size;
+			}
+			fspi_write32(priv->flags, &regs->intr,
+				     FSPI_INTR_IPTXWE_MASK);
+		}
+
+		fspi_write32(priv->flags, &regs->ipcr1,
+			     (seqid << FSPI_IPCR1_ISEQID_SHIFT) | tx_size);
+
+		/* Trigger the command */
+		fspi_write32(priv->flags, &regs->ipcmd, FSPI_IPCMD_TRG_MASK);
+
+		/* Wait for command done */
+		while (!(fspi_read32(priv->flags, &regs->intr)
+			 & FSPI_INTR_IPCMDDONE_MASK))
+			;
+
+		fspi_write32(priv->flags, &regs->iptxfcr,
+			     FSPI_IPTXFCR_CLRIPTXF_MASK);
+		fspi_write32(priv->flags, &regs->intr,
+			     FSPI_INTR_IPCMDDONE_MASK);
+	}
+}
+
+static int fspi_xfer(struct nxp_fspi_priv *priv, unsigned int bitlen,
+		     const void *dout, void *din, unsigned long flags)
+{
+	u32 bytes = DIV_ROUND_UP(bitlen, 8);
+	u32 txbuf;
+	u8  *tempbuf;
+
+	if (dout) {
+		if (flags & SPI_XFER_BEGIN) {
+			priv->cur_seqid = *(u8 *)dout;
+			/*
+			 * For 4-byte support address, received bytes are 5.
+			 * SEQID in 1st byte and then address in rest 4 bytes.
+			 */
+			if ((NXP_FSPI_FLASH_SIZE > SZ_16M) && (bytes > 4)) {
+				memcpy(&txbuf, dout + 1, 4);
+				priv->sf_addr = swab32(txbuf) & GENMASK(27, 0);
+			} else {
+				memcpy(&txbuf, dout, 4);
+				priv->sf_addr = swab32(txbuf) & GENMASK(23, 0);
+			}
+
+			tempbuf = (u8 *)&txbuf;
+			debug("txbuf: 0x%02x  0x%02x  0x%02x  0x%02x\n",
+			      tempbuf[0], tempbuf[1], tempbuf[2], tempbuf[3]);
+		}
+
+		if (flags == SPI_XFER_END) {
+			debug("sf_addr:[0x%02x]\n", priv->sf_addr);
+			fspi_op_write(priv, (u8 *)dout, bytes);
+			return 0;
+		}
+
+		if ((priv->cur_seqid == FSPI_CMD_WREN) ||
+		    (priv->cur_seqid == FSPI_CMD_ENTR4BYTE)) {
+			debug("FSPI Write [%x] cmd Invoked\n", priv->cur_seqid);
+			fspi_op_write_cmd(priv);
+			return 0;
+		}
+
+		if ((priv->cur_seqid == FSPI_CMD_SE) ||
+		    (priv->cur_seqid == FSPI_CMD_SE_4B) ||
+		    (priv->cur_seqid == FSPI_CMD_BE_4K) ||
+		    (priv->cur_seqid == FSPI_CMD_BE_4K_4B)) {
+			debug("FSPI Erase Invoked\n");
+			fspi_op_erase(priv);
+		}
+
+		debug("FSPI [%x] Cmd\n", priv->cur_seqid);
+	}
+
+	if (din) {
+		if ((priv->cur_seqid == FSPI_CMD_RDID) ||
+		    (priv->cur_seqid == FSPI_CMD_RDSR) ||
+		    (priv->cur_seqid == FSPI_CMD_RDFSR))
+			fspi_op_rdxx(priv, din, bytes);
+		else if (priv->cur_seqid == FSPI_CMD_FAST_READ ||
+			 priv->cur_seqid == FSPI_CMD_FAST_READ_4B)
+#ifdef CONFIG_SYS_FSPI_AHB_INIT
+			fspi_ahb_read(priv, din, bytes);
+#else
+			fspi_op_read(priv, din, bytes);
+#endif
+		else
+			debug("FSPI [%x] Cmd not supported\n",
+			      priv->cur_seqid);
+	}
+
+#ifdef CONFIG_SYS_FSPI_AHB_INIT
+	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))
+		fspi_ahb_invalid(priv);
+#endif
+
+	return 0;
+}
+
+static int nxp_fspi_child_pre_probe(struct udevice *dev)
+{
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+
+	slave->max_write_size = TX_IPBUF_SIZE;
+	debug("FSPI Child Pre Probe set Max write to 0x%x\n",
+	      slave->max_write_size);
+
+	return 0;
+}
+
+static int nxp_fspi_probe(struct udevice *bus)
+{
+	struct nxp_fspi_platdata *plat = dev_get_platdata(bus);
+	struct nxp_fspi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_bus *dm_spi_bus;
+	u32 flash_size;
+	u32 mcrx;
+
+	dm_spi_bus = bus->uclass_priv;
+
+	dm_spi_bus->max_hz = plat->speed_hz;
+	priv->regs = (struct nxp_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->memmap_phy = plat->memmap_phy;
+	priv->flash_num = plat->flash_num;
+	priv->num_chipselect = plat->num_chipselect;
+	priv->fspi_rx_bus_width = plat->fspi_rx_bus_width;
+	priv->fspi_tx_bus_width = plat->fspi_tx_bus_width;
+	priv->fspi_has_second_chip = plat->fspi_has_second_chip;
+
+	debug("%s: regs=<0x%llx> <0x%llx, 0x%llx>\n",
+	      __func__,
+	      (u64)priv->regs,
+	      (u64)priv->amba_base[0],
+	      (u64)priv->amba_total_size);
+
+	debug("max-frequency=%d, flags=0x%x, rx_width=0x%x, tx_width=0x%x\n",
+	      priv->speed_hz,
+	      plat->flags,
+	      priv->fspi_rx_bus_width,
+	      priv->fspi_tx_bus_width);
+
+	/*Send Software Reset to controller*/
+	fspi_write32(priv->flags, &priv->regs->mcr0,
+		     FSPI_MCR0_SWRESET_MASK);
+	/*Wait till controller come out of reset*/
+	while (FSPI_MCR0_SWRESET_MASK & fspi_read32(priv->flags,
+						    &priv->regs->mcr0))
+		;
+
+	/* configure controller in stop mode */
+	fspi_module_disable(priv, 1);
+
+	mcrx = fspi_read32(priv->flags, &priv->regs->mcr0);
+	/*Timeout wait cycle for AHB command grant*/
+	mcrx |= (NXP_FSPI_MAX_TIMEOUT_AHBCMD << FSPI_MCR0_AHBGRANTWAIT_SHIFT) &
+						(FSPI_MCR0_AHBGRANTWAIT_MASK);
+	/*Time out wait cycle for IP command grant*/
+	mcrx |= (NXP_FSPI_MAX_TIMEOUT_IPCMD << FSPI_MCR0_IPGRANTWAIT_SHIFT) &
+						(FSPI_MCR0_IPGRANTWAIT_MASK);
+	/* Default set to IP mode */
+	mcrx &= ~FSPI_MCR0_ARDFEN_MASK;
+
+	/* Enable the module and set to IP mode. */
+	mcrx = 0xFFFF0000;
+
+	fspi_write32(priv->flags, &priv->regs->mcr0, mcrx);
+
+	/* Reset the DLL register to default value */
+	fspi_write32(priv->flags, &priv->regs->dllacr, 0x0100);
+	fspi_write32(priv->flags, &priv->regs->dllbcr, 0x0100);
+
+	/*
+	 * Supporting same flash device as slaves on different chip-select.
+	 * As SAMEDEVICEEN bit set, by default, in mcr2 reg then need not to
+	 * configure FLSHA2CRx/FLSHB1CRx/FLSHB2CRx register as setting for
+	 * these would be ignored.
+	 * Need to Reset SAMEDEVICEEN bit in mcr2 reg, when require to add
+	 * support for different flashes.
+	 */
+
+	/* Flash Size in KByte */
+	flash_size = (NXP_FSPI_FLASH_SIZE * NXP_FSPI_FLASH_NUM) / SZ_1K;
+
+	fspi_write32(priv->flags, &priv->regs->flsha1cr0,
+		     flash_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_SYS_FSPI_AHB_INIT
+	fspi_init_ahb_read(priv);
+#endif
+
+	/*Clear Module Disable mode*/
+	fspi_module_disable(priv, 0);
+
+	return 0;
+}
+
+static int nxp_fspi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct fdt_resource res_regs, res_mem;
+	struct nxp_fspi_platdata *plat = bus->platdata;
+	const void *blob = gd->fdt_blob;
+	int node = dev_of_offset(bus);
+	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",
+				     "FSPI", &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",
+				     "FSPI-memory", &res_mem);
+	if (ret) {
+		debug("Error: can't get AMBA base addresses(ret = %d)!\n", ret);
+		return -ENOMEM;
+	}
+
+	plat->num_chipselect = fdtdec_get_int(blob, node, "num-cs",
+					      NXP_FSPI_MAX_CHIPSELECT_NUM);
+	if (fdt_get_property(blob, node, "fspi-has-second-chip", NULL))
+		plat->fspi_has_second_chip = true;
+
+	/* Count flash numbers */
+	fdt_for_each_subnode(subnode, blob, node) {
+		plat->speed_hz = fdtdec_get_int(blob, subnode,
+						"spi-max-frequency",
+						NXP_FSPI_DEFAULT_SCK_FREQ);
+		/*
+		 * MCR2[SAMEDEVICEEN] is enabled.
+		 * Add code to set individual flash settings to
+		 * different flashes if SAMEDEVICEEN bit is disabled.
+		 */
+		plat->fspi_rx_bus_width = fdtdec_get_int(blob, subnode,
+							 "fspi-rx-bus-width",
+					NXP_FSPI_DEFAULT_SPI_RX_BUS_WIDTH);
+		plat->fspi_tx_bus_width = fdtdec_get_int(blob, subnode,
+							 "fspi-tx-bus-width",
+					NXP_FSPI_DEFAULT_SPI_TX_BUS_WIDTH);
+		++flash_num;
+	}
+
+	if (flash_num == 0) {
+		debug("Error: Missing flashes!\n");
+		return -ENODEV;
+	}
+
+	plat->reg_base = res_regs.start;
+	plat->amba_base = 0;
+	plat->memmap_phy = res_mem.start;
+	plat->amba_total_size = res_mem.end - res_mem.start + 1;
+	plat->flash_num = flash_num;
+
+	debug("%s: regs=<0x%llx> <0x%llx, 0x%llx>\n",
+	      __func__,
+	      (u64)plat->reg_base,
+	      (u64)plat->amba_base,
+	      (u64)plat->amba_total_size);
+
+	debug("max-frequency=%d, endianness=%s\n",
+	      plat->speed_hz,
+	      plat->flags & FSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le");
+
+	return 0;
+}
+
+static int nxp_fspi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev->parent;
+	struct nxp_fspi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+
+	debug("FSPI Bus Claim for CS [%x]\n", slave_plat->cs);
+
+	if ((slave_plat->cs != 0) && (!priv->fspi_has_second_chip)) {
+		printf("FSPI Only CS 0 is supported\n");
+		return -1;
+	}
+
+	if (slave_plat->cs > (priv->num_chipselect - 1)) {
+		printf("ERR: Given CS [%x] is larger than supported CS [%x]\n",
+		       slave_plat->cs, (priv->num_chipselect - 1));
+		return -1;
+	}
+
+	priv->cur_amba_base = priv->amba_base[0] +
+			      NXP_FSPI_FLASH_SIZE * slave_plat->cs;
+
+	debug("FSPI CS [%x] cur_amba_base[0x%x]\n",
+	      slave_plat->cs, priv->cur_amba_base);
+	return 0;
+}
+
+static int nxp_fspi_release_bus(struct udevice *dev)
+{
+	debug("FSPI release bus\n");
+	return 0;
+}
+
+static int nxp_fspi_xfer(struct udevice *dev, unsigned int bitlen,
+			 const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct nxp_fspi_priv *priv = dev_get_priv(bus);
+
+	return fspi_xfer(priv, bitlen, dout, din, flags);
+}
+
+static int nxp_fspi_set_speed(struct udevice *bus, uint speed)
+{
+	debug("FSPI speed change is not supported\n");
+	return 0;
+}
+
+static int nxp_fspi_set_mode(struct udevice *bus, uint mode)
+{
+	debug("FSPI Mode change is not supported\n");
+	return 0;
+}
+
+static const struct dm_spi_ops nxp_fspi_ops = {
+	.claim_bus	= nxp_fspi_claim_bus,
+	.release_bus	= nxp_fspi_release_bus,
+	.xfer		= nxp_fspi_xfer,
+	.set_speed	= nxp_fspi_set_speed,
+	.set_mode	= nxp_fspi_set_mode,
+};
+
+static const struct udevice_id nxp_fspi_ids[] = {
+	{ .compatible = "nxp,lx2160a-fspi" },
+	{ }
+};
+
+U_BOOT_DRIVER(nxp_fspi) = {
+	.name				= "nxp_fspi",
+	.id				= UCLASS_SPI,
+	.of_match			= nxp_fspi_ids,
+	.ops				= &nxp_fspi_ops,
+	.ofdata_to_platdata		= nxp_fspi_ofdata_to_platdata,
+	.platdata_auto_alloc_size	= sizeof(struct nxp_fspi_platdata),
+	.priv_auto_alloc_size		= sizeof(struct nxp_fspi_priv),
+	.probe				= nxp_fspi_probe,
+	.child_pre_probe		= nxp_fspi_child_pre_probe,
+};
+#endif
diff --git a/drivers/spi/nxp_fspi.h b/drivers/spi/nxp_fspi.h
new file mode 100644
index 0000000000..f001102448
--- /dev/null
+++ b/drivers/spi/nxp_fspi.h
@@ -0,0 +1,422 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ *
+ * Register definitions for NXP Flex Serial Peripheral Interface (FSPI)
+ */
+
+#ifndef _NXP_FSPI_H_
+#define _NXP_FSPI_H_
+
+struct nxp_fspi_regs {
+	u32 mcr0;		/* 0h */
+	u32 mcr1;
+	u32 mcr2;
+	u32 ahbcr;
+	u32 inten;
+	u32 intr;
+	u32 lutkey;
+	u32 lutcr;
+	u32 ahbrxbuf0cr0;
+	u32 ahbrxbuf1cr0;
+	u32 ahbrxbuf2cr0;
+	u32 ahbrxbuf3cr0;
+	u32 ahbrxbuf4cr0;	/* 30h */
+	u32 ahbrxbuf5cr0;
+	u32 ahbrxbuf6cr0;
+	u32 ahbrxbuf7cr0;
+	u32 ahbrxbuf0cr1;
+	u32 ahbrxbuf1cr1;
+	u32 ahbrxbuf2cr1;
+	u32 ahbrxbuf3cr1;
+	u32 ahbrxbuf4cr1;
+	u32 ahbrxbuf5cr1;
+	u32 ahbrxbuf6cr1;
+	u32 ahbrxbuf7cr1;
+	u32 flsha1cr0;		/* 60h */
+	u32 flsha2cr0;
+	u32 flshb1cr0;
+	u32 flshb2cr0;
+	u32 flsha1cr1;
+	u32 flsha2cr1;
+	u32 flshb1cr1;
+	u32 flshb2cr1;
+	u32 flsha1cr2;
+	u32 flsha2cr2;
+	u32 flshb1cr2;
+	u32 flshb2cr2;
+	u32 flshcr3;		/* 90h */
+	u32 flshcr4;
+	u32 flshcr5;
+	u32 flshcr6;
+	u32 ipcr0;
+	u32 ipcr1;
+	u32 ipcr2;
+	u32 ipcr3;
+	u32 ipcmd;
+	u32 dlpr;
+	u32 iprxfcr;
+	u32 iptxfcr;
+	u32 dllacr;		/* C0h */
+	u32 dllbcr;
+	u32 misccr2;
+	u32 misccr3;
+	u32 misccr4;
+	u32 misccr5;
+	u32 misccr6;
+	u32 misccr7;
+	u32 sts0;		/* E0h */
+	u32 sts1;
+	u32 sts2;
+	u32 ahbspndsts;
+	u32 iprxfsts;
+	u32 iptxfsts;
+	u32 rsvd[2];
+	u32 rfdr[32];		/* 100h */
+	u32 tfdr[32];
+	u32 lut[128];
+};
+
+/* The registers */
+/* Module Control Register 0 */
+#define FSPI_MCR0_AHBGRANTWAIT_SHIFT	24
+#define FSPI_MCR0_AHBGRANTWAIT_MASK	(0xFF << FSPI_MCR0_AHBGRANTWAIT_SHIFT)
+#define FSPI_MCR0_IPGRANTWAIT_SHIFT	16
+#define FSPI_MCR0_IPGRANTWAIT_MASK	(0xFF << FSPI_MCR0_IPGRANTWAIT_SHIFT)
+#define FSPI_MCR0_LEARNEN_SHIFT		15
+#define FSPI_MCR0_LEARNEN_MASK		BIT(FSPI_MCR0_LEARNEN_SHIFT)
+#define FSPI_MCR0_SCKFREERUNEN_SHIFT	14
+#define FSPI_MCR0_SCKFREERUNEN_MASK	BIT(FSPI_MCR0_SCKFREERUNEN_SHIFT)
+#define FSPI_MCR0_COMBINATIONEN_SHIFT	13
+#define FSPI_MCR0_COMBINATION_MASK	BIT(FSPI_MCR0_COMBINATION_SHIFT)
+#define FSPI_MCR0_DOZEEN_SHIFT		12
+#define FSPI_MCR0_DOZEEN_MASK		BIT(FSPI_MCR0_DOZEEN_SHIFT)
+#define FSPI_MCR0_HSEN_SHIFT		11
+#define FSPI_MCR0_HSEN_MASK		BIT(FSPI_HSEN_SHIFT)
+#define FSPI_MCR0_SERCLKDIV_SHIFT	8
+#define FSPI_MCR0_SERCLKDIV_MASK	(7 << FSPI_MCR0_SERCLKDIV_SHIFT)
+#define FSPI_MCR0_ATDFEN_SHIFT		7
+#define FSPI_MCR0_ATDFEN_MASK		BIT(FSPI_MCR0_ATDFEN_SHIFT)
+#define FSPI_MCR0_ARDFEN_SHIFT		6
+#define FSPI_MCR0_ARDFEN_MASK		BIT(FSPI_MCR0_ARDFEN_SHIFT)
+#define FSPI_MCR0_RXCLKSRC_SHIFT	4
+#define FSPI_MCR0_RXCLKSRC_MASK		(3 << FSPI_MCR0_RXCLKSRC_SHIFT)
+#define FSPI_MCR0_ENDCFG_SHIFT		2
+#define FSPI_MCR0_ENDCFG_MASK		(3 << FSPI_MCR0_ENDCFG_SHIFT)
+#define FSPI_MCR0_MDIS_SHIFT		1
+#define FSPI_MCR0_MDIS_MASK		BIT(FSPI_MCR0_MDIS_SHIFT)
+#define FSPI_MCR0_SWRESET_SHIFT		0
+#define FSPI_MCR0_SWRESET_MASK		BIT(FSPI_MCR0_SWRESET_SHIFT)
+
+/* Module Control Register 1 */
+#define FSPI_MCR1_SEQWAIT_SHIFT		16
+#define FSPI_MCR1_SEQWAIT_MASK		(0xFFFF << FSPI_MCR1_SEQWAIT_SHIFT)
+#define FSPI_MCR1_AHBBUSWAIT_SHIFT	0
+#define FSPI_MCR1_AHBBUSWAIT_MASK	(0xFFFF << FSPI_MCR1_AHBBUSWAIT_SHIFT)
+
+/* Module Control Register 2 */
+#define FSPI_MCR2_RESUMEWAIT_SHIFT	24
+#define FSPI_MCR2_RESUMEWAIT_MASK	(0xFF << FSPI_MCR2_RESUMEWAIT_SHIFT)
+#define FSPI_MCR2_CLKPHASERST_SHIFT	20
+#define FSPI_MCR2_CLKPHASERST_MASK	BIT(FSPI_MCR2_CLKPHASERST_SHIFT)
+#define FSPI_MCR2_SCKBDIFFOPT_SHIFT	19
+#define FSPI_MC2_SCKBDIFFOPT_MASK	BIT(FSPI_MCR2_SCKBDIFFOPT_SHIFT)
+#define FSPI_MCR2_RXDELAYOPT_SHIFT	17
+#define FSPI_MCR2_RXDELAYOPT_MASK	(3 << FSPI_MCR2_RXDELAYOPT_SHIFT)
+#define FSPI_MCR2_FLASHDQSOPT_SHIFT	16
+#define FSPI_MCR2_FLASHDQSOPT_MASK	BIT(FSPI_MCR2_FLASHDQSOPT_SHIFT)
+#define FSPI_MCR2_SAMEDEVICEEN_SHIFT	15
+#define FSPI_MCR2_SAMEDEVICEEN_MASK	BIT(FSPI_MCR2_SAMEDEVICEEN_SHIFT)
+#define FSPI_MCR2_CLRLEARNPHASE_SHIFT	14
+#define FSPI_MCR2_CLRLEARNPHASE_MASK	BIT(FSPI_MCR2_CLRLEARNPHASE_SHIFT)
+#define FSPI_MCR2_TSTMD_SHIFT		13
+#define FSPI_MCR2_TSTMD_MASK		BIT(FSPI_MCR2_TSTMD_SHIFT)
+#define FSPI_MCR2_SCK2OPT_SHIFT		12
+#define FSPI_MCR2_SCK2OPT_MASK		BIT(FSPI_MCR2_SCK2OPT_SHIFT)
+#define FSPI_MCR2_CLRAHBBUFOPT_SHIFT	11
+#define FSPI_MCR2_CLRAHBBUFOPT_MASK	BIT(FSPI_MCR2_CLRAHBBUFOPT_SHIFT)
+#define FSPI_MCR2_ABORTONDATSZEN_SHIFT	8
+#define FSPI_MCR2_ABORTONDATSZEN_MASK	BIT(FSPI_MCR2_ABORTONDATSZEN_SHIFT)
+#define FSPI_MCR2_ABORTONLEARNEN_SHIFT	7
+#define FSPI_MCR2_ABORTONLEARNEN_MASK	BIT(FSPI_MCR2_ABORTONLEARNEN_SHIFT)
+#define FSPI_MCR2_ABORTONREADEN_SHIFT	6
+#define FSPI_MCR2_ABORTONREADEN_MASK	BIT(FSPI_MCR2_ABORTONREADEN_SHIFT)
+#define FSPI_MCR2_ABORTONWRITEEN_SHIFT	5
+#define FSPI_MCR2_ABORTONWRITEEN_MASK	BIT(FSPI_MCR2_ABORTONWRITEEN_SHIFT)
+#define FSPI_MCR2_ABORTONDUMMYEN_SHIFT	4
+#define FSPI_MCR2_ABORTONDUMMYEN_MASK	BIT(FSPI_MCR2_ABORTONDUMMYEN_SHIFT)
+#define FSPI_MCR2_ABORTONMODEEN_SHIFT	3
+#define FSPI_MCR2_ABORTONMODEEN_MASK	BIT(FSPI_MCR2_ABORTONMODEEN_SHIFT)
+#define FSPI_MCR2_ABORTONCADDREN_SHIFT	2
+#define FSPI_MCR2_ABORTONCADDREN_MASK	BIT(FSPI_MCR2_ABORTONCADDREN_SHIFT)
+#define FSPI_MCR2_ABORTONRADDREN_SHIFT	1
+#define FSPI_MCR2_ABORTONRADDREN_MASK	BIT(FSPI_MCR2_ABORTONRADDREN_SHIFT)
+#define FSPI_MCR2_ABORTONCMDEN_SHIFT	0
+#define FSPI_MCR2_ABORTONCMDEN_MASK	BIT(FSPI_MCR2_ABORTONCMDEN_SHIFT)
+
+/* AHB Bus Control Register */
+#define FSPI_AHBCR_AFLASHBASE_SHIFT	28
+#define FSPI_AHBCR_AFLASHBASE_MASK	(0xF << FSPI_AHBCR_AFLASHBASE_SHIFT)
+#define FSPI_AHBCR_READADDROPT_SHIFT	6
+#define FSPI_AHBCR_READADDROPT_MASK	BIT(FSPI_AHBCR_READADDROPT_SHIFT)
+#define FSPI_AHBCR_PREFETCHEN_SHIFT	5
+#define FSPI_AHBCR_PREFETCHEN_MASK	BIT(FSPI_AHBCR_PREFETCHEN_SHIFT)
+#define FSPI_AHBCR_BUFFERABLEEN_SHIFT	4
+#define FSPI_AHBCR_BUFFERABLEEN_MASK	BIT(FSPI_AHBCR_BUFFERABLEEN_SHIFT)
+#define FSPI_AHBCR_CACHABLEEN_SHIFT	3
+#define FSPI_AHBCR_CACHABLEEN_MASK	BIT(FSPI_AHBCR_CACHABLEEN_SHIFT)
+#define FSPI_AHBCR_CLRAHBTXBUF_SHIFT	2
+#define FSPI_AHBCR_CLRAHBTXBUF_MASK	BIT(FSPI_AHBCR_CLRAHBTXBUF_SHIFT)
+#define FSPI_AHBCR_CLRAHBRXBUF_SHIFT	1
+#define FSPI_AHBCR_CLRAHBRXBUF_MASK	BIT(FSPI_AHBCR_CLRAHBRXBUF_SHIFT)
+#define FSPI_AHBCR_APAREN_SHIFT		0
+#define FSPI_AHBCR_APAREN_MASK		BIT(FSPI_AHBCR_APAREN_SHIFT)
+
+/* Interrupt Enable Register */
+#define FSPI_INTEN_SEQTIMEOUTEN_SHIFT	11
+#define FSPI_INTEN_SEQTIMEOUTEN_MASK	BIT(FSPI_INTEN_SEQTIMEOUTEN_SHIFT)
+#define FSPI_INTEN_AHBBUSTIMEOUTEN_SHIFT 10
+#define FSPI_INTEN_AHBBUSTIMEOUTEN_MASK BIT(FSPI_INTEN_AHBBUSTIMEOUTEN_SHIFT)
+#define FSPI_INTEN_SCKSTOPBYWREN_SHIFT 9
+#define FSPI_INTEN_SCKSTOPBYWREN_MASK	BIT(FSPI_INTEN_SCKSTOPBYWREN_SHIFT)
+#define FSPI_INTEN_SCKSTOPBYRDEN_SHIFT	8
+#define FSPI_INTEN_SCKSTOPBYRDEN_MASK	BIT(FSPI_INTEN_SCKSTOPBYRDEN_SHIFT)
+#define FSPI_INTEN_DATALEARNFAILEN_SHIFT 7
+#define FSPI_INTEN_DATALEARNFAILEN_MASK	BIT(FSPI_INTEN_DATALEARNFAILEN_SHIFT)
+#define FSPI_INTEN_IPTXWEEN_SHIFT	6
+#define FSPI_INTEN_IPTXWEEN_MASK	BIT(FSPI_INTEN_IPTXWEEN_SHIFT)
+#define FSPI_INTEN_IPRXWAEN_SHIFT	5
+#define FSPI_INTEN_IPRXWAEN_MASK	BIT(FSPI_INTEN_IPRXWAEN_SHIFT)
+#define FSPI_INTEN_AHBCMDERREN_SHIFT	4
+#define FSPI_INTEN_AHBCMDERREN_MASK	BIT(FSPI_INTEN_AHBCMDERREN_SHIFT)
+#define FSPI_INTEN_IPCMDERREN_SHIFT	3
+#define FSPI_INTEN_IPCMDERREN_MASK	BIT(FSPI_INTEN_IPCMDERREN_SHIFT)
+#define FSPI_INTEN_AHBCMDGEEN_SHIFT	2
+#define FSPI_INTEN_AHBCMDGEEN_MASK	BIT(FSPI_INTEN_AHBCMDGEEN_SHIFT)
+#define FSPI_INTEN_IPCMDGEEN_SHIFT	1
+#define FSPI_INTEN_IPCMDGEEN_MASK	BIT(FSPI_INTEN_IPCMDGEEN_SHIFT)
+#define FSPI_INTEN_IPCMDDONEEN_SHIFT	0
+#define FSPI_INTEN_IPCMDDONEEN_MASK	BIT(FSPI_INTEN_IPCMDDONEEN_SHIFT)
+
+/* Interrupt Register */
+#define FSPI_INTR_SEQTIMEOUT_SHIFT	11
+#define FSPI_INTR_SEQTIMEOUT_MASK	BIT(FSPI_INTR_SEQTIMEOUT_SHIFT)
+#define FSPI_INTR_AHBBUSTIMEOUT_SHIFT	10
+#define FSPI_INTR_AHBBUSTIMEOUT_MASK	BIT(FSPI_INTR_AHBBUSTIMEOUT_SHIFT)
+#define FSPI_INTR_SCKSTOPBYWR_SHIFT	9
+#define FSPI_INTR_SCKSTOPBYWR_MASK	BIT(FSPI_INTR_SCKSTOPBYWR_SHIFT)
+#define FSPI_INTR_SCKSTOPBYRD_SHIFT	8
+#define FSPI_INTR_SCKSTOPBYRD_MASK	BIT(FSPI_INTR_SCKSTOPBYRD_SHIFT)
+#define FSPI_INTR_DATALEARNFAIL_SHIFT	7
+#define FSPI_INTR_DATALEARNFAIL_MASK	BIT(FSPI_INTR_DATALEARNFAIL_SHIFT)
+#define FSPI_INTR_IPTXWE_SHIFT		6
+#define FSPI_INTR_IPTXWE_MASK		BIT(FSPI_INTR_IPTXWE_SHIFT)
+#define FSPI_INTR_IPRXWA_SHIFT		5
+#define FSPI_INTR_IPRXWA_MASK		BIT(FSPI_INTR_IPRXWA_SHIFT)
+#define FSPI_INTR_AHBCMDERR_SHIFT	4
+#define FSPI_INTR_AHBCMDERR_MASK	BIT(FSPI_INTR_AHBCMDERR_SHIFT)
+#define FSPI_INTR_IPCMDERR_SHIFT	3
+#define FSPI_INTR_IPCMDERR_MASK		BIT(FSPI_INTR_IPCMDERR_SHIFT)
+#define FSPI_INTR_AHBCMDGE_SHIFT	2
+#define FSPI_INTR_AHBCMDGE_MASK		BIT(FSPI_INTR_AHBCMDGE_SHIFT)
+#define FSPI_INTR_IPCMDGE_SHIFT		1
+#define FSPI_INTR_IPCMDGE_MASK		BIT(FSPI_INTR_IPCMDGE_SHIFT)
+#define FSPI_INTR_IPCMDDONE_SHIFT	0
+#define FSPI_INTR_IPCMDDONE_MASK	BIT(FSPI_INTR_IPCMDDONE_SHIFT)
+
+/* AHB RX Buffer 0-7 Control Register 0 */
+#define FSPI_AHBBUFXCR0_PREFETCHEN_SHIFT 31
+#define FSPI_AHBBUFXCR0_PREFETCHEN_MASK BIT(FSPI_AHBBUFXCR0_PREFETCHEN_SHIFT)
+#define FSPI_AHBBUFXCR0_PRIORITY_SHIFT	24
+#define FSPI_AHBBUFXCR0_PRIORITY_MASK	(7 << FSPI_AHBBUFXCR0_PRIORITY_SHIFT)
+#define FSPI_AHBBUFXCR0_MSTRID_SHIFT	16
+#define FSPI_AHBBUFXCR0_MSTRID_MASK	(0xF << FSPI_AHBBUFXCR0_MSTRID_SHIFT)
+#define FSPI_AHBBUFXCR0_BUFSZ_SHIFT	0
+#define FSPI_AHBBUFXCR0_BUFSZ_MASK	(0xFF << FSPI_AHBBUFXCR0_BUFSZ_SHIFT)
+
+/* Flash A1/A2/B1/B2 Control 0 */
+#define FSPI_FLSHXCR0_FLSHSZ_SHIFT	0
+#define FSPI_FLSHXCR0_FLSHSZ_MASK	(0x7FFFFF << FSPI_FLSHXCR0_SZ_SHIFT)
+
+/* Flash A1/A2/B1/B2 Control 1 */
+#define FSPI_FLSHXCR1_CSINTERVAL_SHIFT	16
+#define FSPI_FLSHXCR1_CSINTERVAL_MASK \
+	(0xFFFF << FSPI_FLSHXCR1_CSINTERVAL_SHIFT)
+#define FSPI_FLSHXCR1_CSINTERVALUNIT_SHIFT 15
+#define FSPI_FLSHXCR1_CSINTERVALUNIT_MASK \
+	(1 << FSPI_FLSHXCR1_CSINTERVALUNIT_SHIFT)
+#define FSPI_FLSHXCR1_CAS_SHIFT		11
+#define FSPI_FLSHXCR1_CAS_MASK		(0xF << FSPI_FLSHXCR0_CAS_SHIFT)
+#define FSPI_FLSHXCR1_WA_SHIFT		10
+#define FSPI_FLSHXCR1_WA_MASK		BIT(FSPI_FLSHXCR0_WA_SHIFT)
+#define FSPI_FLSHXCR1_TCSH_SHIFT	5
+#define FSPI_FLSHXCR1_TCSH_MASK		(0x1F << FSPI_FLSHXCR0_TCSH_SHIFT)
+#define FSPI_FLSHXCR1_TCSS_SHIFT	0
+#define FSPI_FLSHXCR1_TCSS_MASK		(0x1F << FSPI_FLSHXCR0_TCSS_SHIFT)
+
+/* Flash A1/A2/B1/B2 Control 2 */
+#define FSPI_FLSHXCR2_CLRINSTRPTR_SHIFT	31
+#define FSPI_FLSHXCR2_CLRINSTRPTR_MASK	BIT(FSPI_FLSHXCR2_CLRINSTRPTR_SHIFT)
+#define FSPI_FLSHXCR2_AWRWAITUNIT_SHIFT	30
+#define FSPI_FLSHXCR2_AWRWAITUNIT_MASK	(0x7 << FSPI_FLSHXCR2_AWRWAITUNIT_SHIFT)
+#define FSPI_FLSHXCR2_AWRWAIT_SHIFT	16
+#define FSPI_FLSHXCR2_AWRWAIT_MASK	(0xFFF << FSPI_FLSHXCR2_AWRWAIT_SHIFT)
+#define FSPI_FLSHXCR2_AWRSEQNUM_SHIFT	13
+#define FSPI_FLSHXCR2_AWRSEQNUM_MASK	(0x7 << FSPI_FLSHXCR2_AWRSEQNUM_SHIFT)
+#define FSPI_FLSHXCR2_AWRSEQID_SHIFT	8
+#define FSPI_FLSHXCR2_AWRSEQID_MASK	(0xF << FSPI_FLSHXCR2_AWRSEQID_SHIFT)
+#define FSPI_FLSHXCR2_ARDSEQNUM_SHIFT	5
+#define FSPI_FLSHXCR2_ARDSEQNUM_MASK	(0x7 << FSPI_FLSHXCR2_ARDSEQN_SHIFT)
+#define FSPI_FLSHXCR2_ARDSEQID_SHIFT	0
+#define FSPI_FLSHXCR2_ARDSEQID_MASK	(0xFFFF << FSPI_FLSHXCR2_ARDSEQID_SHIFT)
+
+/* Flash Control Register 3 */
+#define FSPI_FLSHCR3_SIOOENONIDLE_SHIFT 24
+#define FSPI_FLSHCR3_SIOOENONIDLE_MASK (0xff << FSPI_FLSHCR3_SIOOENONIDLE_SHIFT)
+#define FSPI_FLSHCR3_SIOOEIDLE_SHIFT	16
+#define FSPI_FLSHCR3_SIOOEIDLE_MASK	(0xff << FSPI_FLSHCR3_SIOOEIDLE_SHIFT)
+#define FSPI_FLSHCR3_SIODONONIDLE_SHIFT	8
+#define FSPI_FLSHCR3_SIODONONIDLE_MASK \
+	(0xff << FSPI_FLSHCR3_SIODONONIDLE_SHIFT)
+#define FSPI_FLSHCR3_SIODOIDLE_SHIFT	0
+#define FSPI_FLSHCR3_SIODOIDLE_MASK	(0xff << FSPI_FLSHCR3_SIODOIDLE_SHIFT)
+
+/* Flash Control Register 4  */
+#define FSPI_FLSHCR4_WMOPT_SHIFT	0
+#define FSPI_FLSHCR4_WMOPT_MASK		BIT(FSPI_FLSHCR4_WMOPT_SHIFT)
+
+/* IP Control Register 0 */
+
+/* IP Control Register 1 */
+#define FSPI_IPCR1_IPAREN_SHIFT		31
+#define FSPI_IPCR1_IPAREN_MASK		BIT(FSPI_IPCR1_IPAREN_SHIFT)
+#define FSPI_IPCR1_ISEQNUM_SHIFT	24
+#define FSPI_IPCR1_ISEQNUM_MASK		(0x7 << FSPI_IPCR1_ISEQNUM_SHIFT)
+#define FSPI_IPCR1_ISEQID_SHIFT		16
+#define FSPI_IPCR1_ISEQID_MASK		(0x1F << FSPI_IPCR1_ISEQID_SHIFT)
+#define FSPI_IPCR1_IDATSZ_SHIFT		0
+#define FSPI_IPCR1_IDATSZ_MASK		(0xFFFF << FSPI_IPCR1_IDATSZ_SHIFT)
+
+/* IP Command Register */
+#define FSPI_IPCMD_TRG_SHIFT		0
+#define FSPI_IPCMD_TRG_MASK		BIT(FSPI_IPCMD_TRG_SHIFT)
+
+/* IP RX FIFO Control Register */
+#define FSPI_IPRXFCR_RXWMRK_SHIFT	2
+#define FSPI_IPRXFCR_RXWMRK_MASK	(0x3F << FSPI_IPRXFCR_RXWMRK_SHIFT)
+#define FSPI_IPRXFCR_RXDMAEN_SHIFT	1
+#define FSPI_IPRXFCR_RXDMAEN_MASK	BIT(FSPI_IPRXFCR_RXDMAEN_SHIFT)
+#define FSPI_IPRXFCR_CLRIPRXF_SHIFT	0
+#define FSPI_IPRXFCR_CLRIPRXF_MASK	BIT(FSPI_IPRXFCR_CLRIPRXF_SHIFT)
+
+/* IP TX FIFO Control Register */
+#define FSPI_IPTXFCR_TXWMRK_SHIFT	2
+#define FSPI_IPTXFCR_TXWMRK_MASK	(0x7F << FSPI_IPTXFCR_TXWMRK_SHIFT)
+#define FSPI_IPTXFCR_TXDMAEN_SHIFT	1
+#define FSPI_IPTXFCR_TXDMAEN_MASK	BIT(FSPI_IPTXFCR_TXDMAEN_SHIFT)
+#define FSPI_IPTXFCR_CLRIPTXF_SHIFT	0
+#define FSPI_IPTXFCR_CLRIPTXF_MASK	BIT(FSPI_IPTXFCR_CLRIPTXF_SHIFT)
+
+/*Status Register 0*/
+#define FSPI_STS0_DATALEARNPHASEB_SHIFT	8
+#define FSPI_STS0_DATALEARNPHASEB_MASK	(0xF << FSPI_STS0_DATALEARNPHASEB_SHIFT)
+#define FSPI_STS0_DATALEARNPHASEA_SHIFT	4
+#define FSPI_STS0_DATALEARNPHASEA_MASK	(0xF << FSPI_STS0_DATALEARNPHASEA_SHIFT)
+#define FSPI_STS0_ARBCMDSRC_SHIFT	2
+#define FSPI_STS0_ARBCMDSRC_MASK	(3 << FSPI_STS0_ARBCMDSRC_SHIFT)
+#define FSPI_STS0_ARBIDLE_SHIFT		1
+#define FSPI_STS0_ARBIDLE_MASK		BIT(FSPI_STS0_ARBIDLE_SHIFT)
+#define FSPI_STS0_SEQIDLE_SHIFT		0
+#define FSPI_STS0_SEQIDLE_MASK		BIT(FSPI_STS0_SEQIDLE_SHIFT)
+
+/* Status Register 1 */
+#define FSPI_STS1_IPCMDERRCODE_SHIFT	24
+#define FSPI_STS1_IPCMDERRCODE_MASK	(0xF << FSPI_STS1_IP_ERRCD_SHIFT)
+#define FSPI_STS1_IPCMDERRID_SHIFT	16
+#define FSPI_STS1_IPCMDERRID_MASK	(0x1F << FSPI_STS1_IPCMDERRID_SHIFT)
+#define FSPI_STS1_AHBCMDERRCODE_SHIFT	8
+#define FSPI_STS1_AHBCMDERRCODE_MASK	(0xF << FSPI_STS1_AHBCMDERRCODE_SHIFT)
+#define FSPI_STS1_AHBCMDERRID_SHIFT	0
+#define FSPI_STS1_AHBCMDERRID_MASK	(0x1F << FSPI_STS1_AHBCMDERRID_SHIFT)
+
+/* AHB Suspend Status Register */
+#define FSPI_AHBSPNST_DATLFT_SHIFT	16
+#define FSPI_AHBSPNST_DATLFT_MASK	(0xFFFF << FSPI_AHBSPNST_DATLFT_SHIFT)
+#define FSPI_AHBSPNST_BUFID_SHIFT	1
+#define FSPI_AHBSPNST_BUFID_MASK	(7 << FSPI_AHBSPNST_BUFID_SHIFT)
+#define FSPI_AHBSPNST_ACTIVE_SHIFT	0
+#define FSPI_AHBSPNST_ACTIVE_MASK	BIT(FSPI_AHBSPNST_ACTIVE_SHIFT)
+
+/* IP RX FIFO Status Register */
+#define FSPI_IPRXFSTS_RDCNTR_SHIFT	16
+#define FSPI_IPRXFSTS_RDCNTR_MASK	(0xFFFF << FSPI_IPRXFSTS_RDCNTR_SHIFT)
+#define FSPI_IPRXFSTS_FILL_SHIFT	0
+#define FSPI_IPRXFSTS_FILL_MASK		(0xFF << FSPI_IPRXFSTS_FILL_SHIFT)
+
+/* IP TX FIFO Status Register */
+#define FSPI_IPTXFSTS_WRCNTR_SHIFT	16
+#define FSPI_IPTXFSTS_WRCNTR_MASK	(0xFFFF << FSPI_IPTXFSTS_WRCNTR_SHIFT)
+#define FSPI_IPTXFSTS_FILL_SHIFT	0
+#define FSPI_IPTXFSTS_FILL_MASK		(0xFF << FSPI_IPTXFSTS_FILL_SHIFT)
+
+/*LUT Keys*/
+
+#define FSPI_LUTKEY_VALUE		0x5AF05AF0
+
+/* LUT Control Register */
+#define FSPI_LUTCR_LOCK			0x1
+#define FSPI_LUTCR_UNLOCK		0x2
+
+/* 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 /* _NXP_FSPI_H_ */
-- 
2.17.1



More information about the U-Boot mailing list