Contributors: 1
Author Tokens Token Proportion Commits Commit Proportion
Haibo Chen 5971 100.00% 1 100.00%
Total 5971 1


// SPDX-License-Identifier: GPL-2.0+

/*
 * NXP xSPI controller driver.
 *
 * Copyright 2025 NXP
 *
 * xSPI is a flexible SPI host controller which supports single
 * external devices. This device can have up to eight bidirectional
 * data lines, this means xSPI support Single/Dual/Quad/Octal mode
 * data transfer (1/2/4/8 bidirectional data lines).
 *
 * xSPI controller is driven by the LUT(Look-up Table) registers
 * LUT registers are a look-up-table for sequences of instructions.
 * A valid sequence consists of five LUT registers.
 * Maximum 16 LUT sequences can be programmed simultaneously.
 *
 * LUTs are being created at run-time based on the commands passed
 * from the spi-mem framework, thus using single LUT index.
 *
 * Software triggered Flash read/write access by IP Bus.
 *
 * Memory mapped read access by AHB Bus.
 *
 * Based on SPI MEM interface and spi-nxp-fspi.c driver.
 *
 * Author:
 *     Haibo Chen <haibo.chen@nxp.com>
 * Co-author:
 *     Han Xu <han.xu@nxp.com>
 */

#include <linux/bitops.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>

/* Runtime pm timeout */
#define XSPI_RPM_TIMEOUT_MS 50	/* 50ms */
/*
 * The driver only uses one single LUT entry, that is updated on
 * each call of exec_op(). Index 0 is preset at boot with a basic
 * read operation, so let's use the last entry (15).
 */
#define	XSPI_SEQID_LUT			15

#define XSPI_MCR			0x0
#define XSPI_MCR_CKN_FA_EN		BIT(26)
#define XSPI_MCR_DQS_FA_SEL_MASK	GENMASK(25, 24)
#define XSPI_MCR_ISD3FA			BIT(17)
#define XSPI_MCR_ISD2FA			BIT(16)
#define XSPI_MCR_DOZE			BIT(15)
#define XSPI_MCR_MDIS			BIT(14)
#define XSPI_MCR_DLPEN			BIT(12)
#define XSPI_MCR_CLR_TXF		BIT(11)
#define XSPI_MCR_CLR_RXF		BIT(10)
#define XSPI_MCR_IPS_TG_RST		BIT(9)
#define XSPI_MCR_VAR_LAT_EN		BIT(8)
#define XSPI_MCR_DDR_EN			BIT(7)
#define XSPI_MCR_DQS_EN			BIT(6)
#define XSPI_MCR_DQS_LAT_EN		BIT(5)
#define XSPI_MCR_DQS_OUT_EN		BIT(4)
#define XSPI_MCR_SWRSTHD		BIT(1)
#define XSPI_MCR_SWRSTSD		BIT(0)

#define XSPI_IPCR			0x8

#define XSPI_FLSHCR			0xC
#define XSPI_FLSHCR_TDH_MASK		GENMASK(17, 16)
#define XSPI_FLSHCR_TCSH_MASK		GENMASK(11, 8)
#define XSPI_FLSHCR_TCSS_MASK		GENMASK(3, 0)

#define XSPI_BUF0CR			0x10
#define XSPI_BUF1CR			0x14
#define XSPI_BUF2CR			0x18
#define XSPI_BUF3CR			0x1C
#define XSPI_BUF3CR_ALLMST		BIT(31)
#define XSPI_BUF3CR_ADATSZ_MASK		GENMASK(17, 8)
#define XSPI_BUF3CR_MSTRID_MASK		GENMASK(3, 0)

#define XSPI_BFGENCR			0x20
#define XSPI_BFGENCR_SEQID_WR_MASK	GENMASK(31, 28)
#define XSPI_BFGENCR_ALIGN_MASK		GENMASK(24, 22)
#define XSPI_BFGENCR_PPWF_CLR		BIT(20)
#define XSPI_BFGENCR_WR_FLUSH_EN	BIT(21)
#define XSPI_BFGENCR_SEQID_WR_EN	BIT(17)
#define XSPI_BFGENCR_SEQID_MASK		GENMASK(15, 12)

#define XSPI_BUF0IND			0x30
#define XSPI_BUF1IND			0x34
#define XSPI_BUF2IND			0x38

#define XSPI_DLLCRA			0x60
#define XSPI_DLLCRA_DLLEN		BIT(31)
#define XSPI_DLLCRA_FREQEN		BIT(30)
#define XSPI_DLLCRA_DLL_REFCNTR_MASK	GENMASK(27, 24)
#define XSPI_DLLCRA_DLLRES_MASK		GENMASK(23, 20)
#define XSPI_DLLCRA_SLV_FINE_MASK	GENMASK(19, 16)
#define XSPI_DLLCRA_SLV_DLY_MASK	GENMASK(14, 12)
#define XSPI_DLLCRA_SLV_DLY_COARSE_MASK	GENMASK(11,  8)
#define XSPI_DLLCRA_SLV_DLY_FINE_MASK	GENMASK(7, 5)
#define XSPI_DLLCRA_DLL_CDL8		BIT(4)
#define XSPI_DLLCRA_SLAVE_AUTO_UPDT	BIT(3)
#define XSPI_DLLCRA_SLV_EN		BIT(2)
#define XSPI_DLLCRA_SLV_DLL_BYPASS	BIT(1)
#define XSPI_DLLCRA_SLV_UPD		BIT(0)

#define XSPI_SFAR			0x100

#define XSPI_SFACR			0x104
#define XSPI_SFACR_FORCE_A10		BIT(22)
#define XSPI_SFACR_WA_4B_EN		BIT(21)
#define XSPI_SFACR_CAS_INTRLVD		BIT(20)
#define XSPI_SFACR_RX_BP_EN		BIT(18)
#define XSPI_SFACR_BYTE_SWAP		BIT(17)
#define XSPI_SFACR_WA			BIT(16)
#define XSPI_SFACR_CAS_MASK		GENMASK(3, 0)

#define XSPI_SMPR			0x108
#define XSPI_SMPR_DLLFSMPFA_MASK	GENMASK(26, 24)
#define XSPI_SMPR_FSDLY			BIT(6)
#define XSPI_SMPR_FSPHS			BIT(5)

#define XSPI_RBSR			0x10C

#define XSPI_RBCT			0x110
#define XSPI_RBCT_WMRK_MASK		GENMASK(6, 0)

#define XSPI_DLLSR			0x12C
#define XSPI_DLLSR_DLLA_LOCK		BIT(15)
#define XSPI_DLLSR_SLVA_LOCK		BIT(14)
#define XSPI_DLLSR_DLLA_RANGE_ERR	BIT(13)
#define XSPI_DLLSR_DLLA_FINE_UNDERFLOW	BIT(12)

#define XSPI_TBSR			0x150

#define XSPI_TBDR			0x154

#define XSPI_TBCT			0x158
#define XSPI_TBCT_WMRK_MASK		GENMASK(7, 0)

#define XSPI_SR				0x15C
#define XSPI_SR_TXFULL			BIT(27)
#define XSPI_SR_TXDMA			BIT(26)
#define XSPI_SR_TXWA			BIT(25)
#define XSPI_SR_TXNE			BIT(24)
#define XSPI_SR_RXDMA			BIT(23)
#define XSPI_SR_ARB_STATE_MASK		GENMASK(23, 20)
#define XSPI_SR_RXFULL			BIT(19)
#define XSPI_SR_RXWE			BIT(16)
#define XSPI_SR_ARB_LCK			BIT(15)
#define XSPI_SR_AHBnFUL			BIT(11)
#define XSPI_SR_AHBnNE			BIT(7)
#define XSPI_SR_AHBTRN			BIT(6)
#define XSPI_SR_AWRACC			BIT(4)
#define XSPI_SR_AHB_ACC			BIT(2)
#define XSPI_SR_IP_ACC			BIT(1)
#define XSPI_SR_BUSY			BIT(0)

#define XSPI_FR				0x160
#define XSPI_FR_DLPFF			BIT(31)
#define XSPI_FR_DLLABRT			BIT(28)
#define XSPI_FR_TBFF			BIT(27)
#define XSPI_FR_TBUF			BIT(26)
#define XSPI_FR_DLLUNLCK		BIT(24)
#define XSPI_FR_ILLINE			BIT(23)
#define XSPI_FR_RBOF			BIT(17)
#define XSPI_FR_RBDF			BIT(16)
#define XSPI_FR_AAEF			BIT(15)
#define XSPI_FR_AITEF			BIT(14)
#define XSPI_FR_AIBSEF			BIT(13)
#define XSPI_FR_ABOF			BIT(12)
#define XSPI_FR_CRCAEF			BIT(10)
#define XSPI_FR_PPWF			BIT(8)
#define XSPI_FR_IPIEF			BIT(6)
#define XSPI_FR_IPEDERR			BIT(5)
#define XSPI_FR_PERFOVF			BIT(2)
#define XSPI_FR_RDADDR			BIT(1)
#define XSPI_FR_TFF			BIT(0)

#define XSPI_RSER			0x164
#define XSPI_RSER_TFIE			BIT(0)

#define XSPI_SFA1AD			0x180

#define XSPI_SFA2AD			0x184

#define XSPI_RBDR0			0x200

#define XSPI_LUTKEY			0x300
#define XSPI_LUT_KEY_VAL		(0x5AF05AF0UL)

#define XSPI_LCKCR			0x304
#define XSPI_LOKCR_LOCK			BIT(0)
#define XSPI_LOKCR_UNLOCK		BIT(1)

#define XSPI_LUT			0x310
#define XSPI_LUT_OFFSET			(XSPI_SEQID_LUT * 5 * 4)
#define XSPI_LUT_REG(idx) \
	(XSPI_LUT + XSPI_LUT_OFFSET + (idx) * 4)

#define XSPI_MCREXT			0x4FC
#define XSPI_MCREXT_RST_MASK		GENMASK(3, 0)


#define XSPI_FRAD0_WORD2		0x808
#define XSPI_FRAD0_WORD2_MD0ACP_MASK	GENMASK(2, 0)

#define XSPI_FRAD0_WORD3		0x80C
#define XSPI_FRAD0_WORD3_VLD		BIT(31)

#define XSPI_TG0MDAD			0x900
#define XSPI_TG0MDAD_VLD		BIT(31)

#define XSPI_TG1MDAD			0x910

#define XSPI_MGC			0x920
#define XSPI_MGC_GVLD			BIT(31)
#define XSPI_MGC_GVLDMDAD		BIT(29)
#define XSPI_MGC_GVLDFRAD		BIT(27)

#define XSPI_MTO			0x928

#define XSPI_ERRSTAT			0x938
#define XSPI_INT_EN			0x93C

#define XSPI_SFP_TG_IPCR		0x958
#define XSPI_SFP_TG_IPCR_SEQID_MASK	GENMASK(27, 24)
#define XSPI_SFP_TG_IPCR_ARB_UNLOCK	BIT(23)
#define XSPI_SFP_TG_IPCR_ARB_LOCK	BIT(22)
#define XSPI_SFP_TG_IPCR_IDATSZ_MASK	GENMASK(15, 0)

#define XSPI_SFP_TG_SFAR 0x95C

/* Register map end */

/********* XSPI CMD definitions ***************************/
#define LUT_STOP	0x00
#define LUT_CMD_SDR	0x01
#define LUT_ADDR_SDR	0x02
#define LUT_DUMMY	0x03
#define LUT_MODE8_SDR	0x04
#define LUT_MODE2_SDR	0x05
#define LUT_MODE4_SDR	0x06
#define LUT_READ_SDR	0x07
#define LUT_WRITE_SDR	0x08
#define LUT_JMP_ON_CS	0x09
#define LUT_ADDR_DDR	0x0A
#define LUT_MODE8_DDR	0x0B
#define LUT_MODE2_DDR	0x0C
#define LUT_MODE4_DDR	0x0D
#define LUT_READ_DDR	0x0E
#define LUT_WRITE_DDR	0x0F
#define LUT_DATA_LEARN	0x10
#define LUT_CMD_DDR	0x11
#define LUT_CADDR_SDR	0x12
#define LUT_CADDR_DDR	0x13
#define JMP_TO_SEQ	0x14

#define XSPI_64BIT_LE	0x3
/*
 * Calculate number of required PAD bits for LUT register.
 *
 * The pad stands for the number of IO lines [0:7].
 * For example, the octal read needs eight IO lines,
 * so you should use LUT_PAD(8). This macro
 * returns 3 i.e. use eight (2^3) IP lines for read.
 */
#define LUT_PAD(x) (fls(x) - 1)

/*
 * Macro for constructing the LUT entries with the following
 * register layout:
 *
 *  ---------------------------------------------------
 *  | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
 *  ---------------------------------------------------
 */
#define PAD_SHIFT		8
#define INSTR_SHIFT		10
#define OPRND_SHIFT		16

/* Macros for constructing the LUT register. */
#define LUT_DEF(idx, ins, pad, opr)			  \
	((((ins) << INSTR_SHIFT) | ((pad) << PAD_SHIFT) | \
	(opr)) << (((idx) % 2) * OPRND_SHIFT))

#define NXP_XSPI_MIN_IOMAP	SZ_4M
#define NXP_XSPI_MAX_CHIPSELECT		2
#define POLL_TOUT_US		5000

/* Access flash memory using IP bus only */
#define XSPI_QUIRK_USE_IP_ONLY	BIT(0)

struct nxp_xspi_devtype_data {
	unsigned int rxfifo;
	unsigned int txfifo;
	unsigned int ahb_buf_size;
	unsigned int quirks;
};

static struct nxp_xspi_devtype_data imx94_data = {
	.rxfifo = SZ_512,       /* (128 * 4 bytes)  */
	.txfifo = SZ_1K,        /* (256 * 4 bytes)  */
	.ahb_buf_size = SZ_4K,  /* (1024 * 4 bytes)  */
};

struct nxp_xspi {
	void __iomem *iobase;
	void __iomem *ahb_addr;
	u32 memmap_phy;
	u32 memmap_phy_size;
	u32 memmap_start;
	u32 memmap_len;
	struct clk *clk;
	struct device *dev;
	struct completion c;
	const struct nxp_xspi_devtype_data *devtype_data;
	/* mutex lock for each operation */
	struct mutex lock;
	int selected;
#define XSPI_DTR_PROTO		BIT(0)
	int flags;
	/* Save the previous operation clock rate */
	unsigned long pre_op_rate;
	/* The max clock rate xspi supported output to device */
	unsigned long support_max_rate;
};

static inline int needs_ip_only(struct nxp_xspi *xspi)
{
	return xspi->devtype_data->quirks & XSPI_QUIRK_USE_IP_ONLY;
}

static irqreturn_t nxp_xspi_irq_handler(int irq, void *dev_id)
{
	struct nxp_xspi *xspi = dev_id;
	u32 reg;

	reg = readl(xspi->iobase + XSPI_FR);
	if (reg & XSPI_FR_TFF) {
		/* Clear interrupt */
		writel(XSPI_FR_TFF, xspi->iobase + XSPI_FR);
		complete(&xspi->c);
		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}

static int nxp_xspi_check_buswidth(struct nxp_xspi *xspi, u8 width)
{
	return (is_power_of_2(width) && width <= 8) ? 0 : -EOPNOTSUPP;
}

static bool nxp_xspi_supports_op(struct spi_mem *mem,
				 const struct spi_mem_op *op)
{
	struct nxp_xspi *xspi = spi_controller_get_devdata(mem->spi->controller);
	int ret;

	ret = nxp_xspi_check_buswidth(xspi, op->cmd.buswidth);

	if (op->addr.nbytes)
		ret |= nxp_xspi_check_buswidth(xspi, op->addr.buswidth);

	if (op->dummy.nbytes)
		ret |= nxp_xspi_check_buswidth(xspi, op->dummy.buswidth);

	if (op->data.nbytes)
		ret |= nxp_xspi_check_buswidth(xspi, op->data.buswidth);

	if (ret)
		return false;

	/*
	 * The number of address bytes should be equal to or less than 4 bytes.
	 */
	if (op->addr.nbytes > 4)
		return false;

	/* Max 32 dummy clock cycles supported */
	if (op->dummy.buswidth &&
	    (op->dummy.nbytes * 8 / op->dummy.buswidth > 64))
		return false;

	if (needs_ip_only(xspi) && op->data.dir == SPI_MEM_DATA_IN &&
	    op->data.nbytes > xspi->devtype_data->rxfifo)
		return false;

	if (op->data.dir == SPI_MEM_DATA_OUT &&
			op->data.nbytes > xspi->devtype_data->txfifo)
		return false;

	return spi_mem_default_supports_op(mem, op);
}

static void nxp_xspi_prepare_lut(struct nxp_xspi *xspi,
				 const struct spi_mem_op *op)
{
	void __iomem *base = xspi->iobase;
	u32 lutval[5] = {};
	int lutidx = 1, i;

	/* cmd */
	if (op->cmd.dtr) {
		lutval[0] |= LUT_DEF(0, LUT_CMD_DDR, LUT_PAD(op->cmd.buswidth),
				     op->cmd.opcode >> 8);
		lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_CMD_DDR,
					      LUT_PAD(op->cmd.buswidth),
					      op->cmd.opcode & 0x00ff);
		lutidx++;
	} else {
		lutval[0] |= LUT_DEF(0, LUT_CMD_SDR, LUT_PAD(op->cmd.buswidth),
				     op->cmd.opcode);
	}

	/* Addr bytes */
	if (op->addr.nbytes) {
		lutval[lutidx / 2] |= LUT_DEF(lutidx, op->addr.dtr ?
					      LUT_ADDR_DDR : LUT_ADDR_SDR,
					      LUT_PAD(op->addr.buswidth),
					      op->addr.nbytes * 8);
		lutidx++;
	}

	/* Dummy bytes, if needed */
	if (op->dummy.nbytes) {
		lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
					      LUT_PAD(op->data.buswidth),
					      op->dummy.nbytes * 8 /
						/* need distinguish ddr mode */
					      op->dummy.buswidth / (op->dummy.dtr ? 2 : 1));
		lutidx++;
	}

	/* Read/Write data bytes */
	if (op->data.nbytes) {
		lutval[lutidx / 2] |= LUT_DEF(lutidx,
					      op->data.dir == SPI_MEM_DATA_IN ?
					      (op->data.dtr ? LUT_READ_DDR : LUT_READ_SDR) :
					      (op->data.dtr ? LUT_WRITE_DDR : LUT_WRITE_SDR),
					      LUT_PAD(op->data.buswidth),
					      0);
		lutidx++;
	}

	/* Stop condition. */
	lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_STOP, 0, 0);

	/* Unlock LUT */
	writel(XSPI_LUT_KEY_VAL, xspi->iobase + XSPI_LUTKEY);
	writel(XSPI_LOKCR_UNLOCK, xspi->iobase + XSPI_LCKCR);

	/* Fill LUT */
	for (i = 0; i < ARRAY_SIZE(lutval); i++)
		writel(lutval[i], base + XSPI_LUT_REG(i));

	dev_dbg(xspi->dev, "CMD[%02x] lutval[0:%08x 1:%08x 2:%08x 3:%08x 4:%08x], size: 0x%08x\n",
		op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], lutval[4],
		op->data.nbytes);

	/* Lock LUT */
	writel(XSPI_LUT_KEY_VAL, xspi->iobase + XSPI_LUTKEY);
	writel(XSPI_LOKCR_LOCK, xspi->iobase + XSPI_LCKCR);
}

static void nxp_xspi_disable_ddr(struct nxp_xspi *xspi)
{
	void __iomem *base = xspi->iobase;
	u32 reg;

	/* Disable module */
	reg = readl(base + XSPI_MCR);
	reg |= XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);

	reg &= ~XSPI_MCR_DDR_EN;
	reg &= ~XSPI_MCR_DQS_FA_SEL_MASK;
	/* Use dummy pad loopback mode to sample data */
	reg |= FIELD_PREP(XSPI_MCR_DQS_FA_SEL_MASK, 0x01);
	writel(reg, base + XSPI_MCR);
	xspi->support_max_rate = 133000000;

	reg = readl(base + XSPI_FLSHCR);
	reg &= ~XSPI_FLSHCR_TDH_MASK;
	writel(reg, base + XSPI_FLSHCR);

	/* Select sampling at inverted clock */
	reg = FIELD_PREP(XSPI_SMPR_DLLFSMPFA_MASK, 0) | XSPI_SMPR_FSPHS;
	writel(reg, base + XSPI_SMPR);

	/* Enable module */
	reg = readl(base + XSPI_MCR);
	reg &= ~XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);
}

static void nxp_xspi_enable_ddr(struct nxp_xspi *xspi)
{
	void __iomem *base = xspi->iobase;
	u32 reg;

	/* Disable module */
	reg = readl(base + XSPI_MCR);
	reg |= XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);

	reg |= XSPI_MCR_DDR_EN;
	reg &= ~XSPI_MCR_DQS_FA_SEL_MASK;
	/* Use external dqs to sample data */
	reg |= FIELD_PREP(XSPI_MCR_DQS_FA_SEL_MASK, 0x03);
	writel(reg, base + XSPI_MCR);
	xspi->support_max_rate = 200000000;

	reg = readl(base + XSPI_FLSHCR);
	reg &= ~XSPI_FLSHCR_TDH_MASK;
	reg |= FIELD_PREP(XSPI_FLSHCR_TDH_MASK, 0x01);
	writel(reg, base + XSPI_FLSHCR);

	reg = FIELD_PREP(XSPI_SMPR_DLLFSMPFA_MASK, 0x04);
	writel(reg, base + XSPI_SMPR);

	/* Enable module */
	reg = readl(base + XSPI_MCR);
	reg &= ~XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);
}

static void nxp_xspi_sw_reset(struct nxp_xspi *xspi)
{
	void __iomem *base = xspi->iobase;
	bool mdis_flag = false;
	u32 reg;
	int ret;

	reg = readl(base + XSPI_MCR);

	/*
	 * Per RM, when reset SWRSTSD and SWRSTHD, XSPI must be
	 * enabled (MDIS = 0).
	 * So if MDIS is 1, should clear it before assert SWRSTSD
	 * and SWRSTHD.
	 */
	if (reg & XSPI_MCR_MDIS) {
		reg &= ~XSPI_MCR_MDIS;
		writel(reg, base + XSPI_MCR);
		mdis_flag = true;
	}

	/* Software reset for AHB domain and Serial flash memory domain */
	reg |= XSPI_MCR_SWRSTHD | XSPI_MCR_SWRSTSD;
	/* Software Reset for IPS Target Group Queue 0 */
	reg |= XSPI_MCR_IPS_TG_RST;
	writel(reg, base + XSPI_MCR);

	/* IPS_TG_RST will self-clear to 0 once IPS_TG_RST complete */
	ret = readl_poll_timeout(base + XSPI_MCR, reg, !(reg & XSPI_MCR_IPS_TG_RST),
			      100, 5000);
	if (ret == -ETIMEDOUT)
		dev_warn(xspi->dev, "XSPI_MCR_IPS_TG_RST do not self-clear in 5ms!");

	/*
	 * Per RM, must wait for at least three system cycles and
	 * three flash cycles after changing the value of reset field.
	 * delay 5us for safe.
	 */
	fsleep(5);

	/*
	 * Per RM, before dessert SWRSTSD and SWRSTHD, XSPI must be
	 * disabled (MIDS = 1).
	 */
	reg = readl(base + XSPI_MCR);
	reg |= XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);

	/* deassert software reset */
	reg &= ~(XSPI_MCR_SWRSTHD | XSPI_MCR_SWRSTSD);
	writel(reg, base + XSPI_MCR);

	/*
	 * Per RM, must wait for at least three system cycles and
	 * three flash cycles after changing the value of reset field.
	 * delay 5us for safe.
	 */
	fsleep(5);

	/* Re-enable XSPI if it is enabled at beginning */
	if (!mdis_flag) {
		reg &= ~XSPI_MCR_MDIS;
		writel(reg, base + XSPI_MCR);
	}
}

static void nxp_xspi_dll_bypass(struct nxp_xspi *xspi)
{
	void __iomem *base = xspi->iobase;
	int ret;
	u32 reg;

	nxp_xspi_sw_reset(xspi);

	writel(0, base + XSPI_DLLCRA);

	/* Set SLV EN first */
	reg = XSPI_DLLCRA_SLV_EN;
	writel(reg, base + XSPI_DLLCRA);

	reg = XSPI_DLLCRA_FREQEN |
	      FIELD_PREP(XSPI_DLLCRA_SLV_DLY_COARSE_MASK, 0x0) |
	      XSPI_DLLCRA_SLV_EN | XSPI_DLLCRA_SLV_DLL_BYPASS;
	writel(reg, base + XSPI_DLLCRA);

	reg |= XSPI_DLLCRA_SLV_UPD;
	writel(reg, base + XSPI_DLLCRA);

	ret = readl_poll_timeout(base + XSPI_DLLSR, reg,
			      reg & XSPI_DLLSR_SLVA_LOCK, 0, POLL_TOUT_US);
	if (ret)
		dev_err(xspi->dev,
			"DLL SLVA unlock, the DLL status is %x, need to check!\n",
			readl(base + XSPI_DLLSR));
}

static void nxp_xspi_dll_auto(struct nxp_xspi *xspi, unsigned long rate)
{
	void __iomem *base = xspi->iobase;
	int ret;
	u32 reg;

	nxp_xspi_sw_reset(xspi);

	writel(0, base + XSPI_DLLCRA);

	/* Set SLV EN first */
	reg = XSPI_DLLCRA_SLV_EN;
	writel(reg, base + XSPI_DLLCRA);

	reg = FIELD_PREP(XSPI_DLLCRA_DLL_REFCNTR_MASK, 0x02) |
	      FIELD_PREP(XSPI_DLLCRA_DLLRES_MASK, 0x08) |
	      XSPI_DLLCRA_SLAVE_AUTO_UPDT | XSPI_DLLCRA_SLV_EN;
	if (rate > 133000000)
		reg |= XSPI_DLLCRA_FREQEN;

	writel(reg, base + XSPI_DLLCRA);

	reg |= XSPI_DLLCRA_SLV_UPD;
	writel(reg, base + XSPI_DLLCRA);

	reg |= XSPI_DLLCRA_DLLEN;
	writel(reg, base + XSPI_DLLCRA);

	ret = readl_poll_timeout(base + XSPI_DLLSR, reg,
			      reg & XSPI_DLLSR_DLLA_LOCK, 0, POLL_TOUT_US);
	if (ret)
		dev_err(xspi->dev,
			"DLL unlock, the DLL status is %x, need to check!\n",
			readl(base + XSPI_DLLSR));

	ret = readl_poll_timeout(base + XSPI_DLLSR, reg,
			      reg & XSPI_DLLSR_SLVA_LOCK, 0, POLL_TOUT_US);
	if (ret)
		dev_err(xspi->dev,
			"DLL SLVA unlock, the DLL status is %x, need to check!\n",
			readl(base + XSPI_DLLSR));
}

static void nxp_xspi_select_mem(struct nxp_xspi *xspi, struct spi_device *spi,
				const struct spi_mem_op *op)
{
	/* xspi only support one DTR mode: 8D-8D-8D */
	bool op_is_dtr = op->cmd.dtr && op->addr.dtr && op->dummy.dtr && op->data.dtr;
	unsigned long root_clk_rate, rate;
	uint64_t cs0_top_address;
	uint64_t cs1_top_address;
	u32 reg;
	int ret;

	/*
	 * Return when following condition all meet,
	 * 1, if previously selected target device is same as current
	 *    requested target device.
	 * 2, the DTR or STR mode do not change.
	 * 3, previous operation max rate equals current one.
	 *
	 * For other case, need to re-config.
	 */
	if (xspi->selected == spi_get_chipselect(spi, 0) &&
	    (!!(xspi->flags & XSPI_DTR_PROTO) == op_is_dtr) &&
	    (xspi->pre_op_rate == op->max_freq))
		return;

	if (op_is_dtr) {
		nxp_xspi_enable_ddr(xspi);
		xspi->flags |= XSPI_DTR_PROTO;
	} else {
		nxp_xspi_disable_ddr(xspi);
		xspi->flags &= ~XSPI_DTR_PROTO;
	}
	rate = min_t(unsigned long, xspi->support_max_rate, op->max_freq);
	/*
	 * There is two dividers between xspi_clk_root(from SoC CCM) and xspi_sfif.
	 * xspi_clk_root ---->divider1 ----> ipg_clk_2xsfif
	 *                              |
	 *                              |
	 *                              |---> divider2 ---> ipg_clk_sfif
	 * divider1 is controlled by SOCCR, SOCCR default value is 0.
	 * divider2 fix to divide 2.
	 * when SOCCR = 0:
	 *        ipg_clk_2xsfif = xspi_clk_root
	 *        ipg_clk_sfif = ipg_clk_2xsfif / 2 = xspi_clk_root / 2
	 * ipg_clk_2xsfif is used for DTR mode.
	 * xspi_sck(output to device) is defined based on xspi_sfif clock.
	 */
	root_clk_rate = rate * 2;

	clk_disable_unprepare(xspi->clk);

	ret = clk_set_rate(xspi->clk, root_clk_rate);
	if (ret)
		return;

	ret = clk_prepare_enable(xspi->clk);
	if (ret)
		return;

	xspi->pre_op_rate = op->max_freq;
	xspi->selected = spi_get_chipselect(spi, 0);

	if (xspi->selected) {		/* CS1 select */
		cs0_top_address = xspi->memmap_phy;
		cs1_top_address = SZ_4G - 1;
	} else {			/* CS0 select */
		cs0_top_address = SZ_4G - 1;
		cs1_top_address = SZ_4G - 1;
	}
	writel(cs0_top_address, xspi->iobase + XSPI_SFA1AD);
	writel(cs1_top_address, xspi->iobase + XSPI_SFA2AD);

	reg = readl(xspi->iobase + XSPI_SFACR);
	if (op->data.swap16)
		reg |= XSPI_SFACR_BYTE_SWAP;
	else
		reg &= ~XSPI_SFACR_BYTE_SWAP;
	writel(reg, xspi->iobase + XSPI_SFACR);

	if (!op_is_dtr || rate < 60000000)
		nxp_xspi_dll_bypass(xspi);
	else
		nxp_xspi_dll_auto(xspi, rate);
}

static int nxp_xspi_ahb_read(struct nxp_xspi *xspi, const struct spi_mem_op *op)
{
	u32 start = op->addr.val;
	u32 len = op->data.nbytes;

	/* If necessary, ioremap before AHB read */
	if ((!xspi->ahb_addr) || start < xspi->memmap_start ||
	     start + len > xspi->memmap_start + xspi->memmap_len) {
		if (xspi->ahb_addr)
			iounmap(xspi->ahb_addr);

		xspi->memmap_start = start;
		xspi->memmap_len = len > NXP_XSPI_MIN_IOMAP ?
				len : NXP_XSPI_MIN_IOMAP;

		xspi->ahb_addr = ioremap(xspi->memmap_phy + xspi->memmap_start,
					 xspi->memmap_len);

		if (!xspi->ahb_addr) {
			dev_err(xspi->dev, "failed to alloc memory\n");
			return -ENOMEM;
		}
	}

	/* Read out the data directly from the AHB buffer. */
	memcpy_fromio(op->data.buf.in,
			xspi->ahb_addr + start - xspi->memmap_start, len);

	return 0;
}

static int nxp_xspi_fill_txfifo(struct nxp_xspi *xspi,
				 const struct spi_mem_op *op)
{
	void __iomem *base = xspi->iobase;
	u8 *buf = (u8 *)op->data.buf.out;
	u32 reg, left;
	int i;

	for (i = 0; i < ALIGN(op->data.nbytes, 4); i += 4) {
		reg = readl(base + XSPI_FR);
		reg |= XSPI_FR_TBFF;
		writel(reg, base + XSPI_FR);
		/* Read again to check whether the tx fifo has rom */
		reg = readl(base + XSPI_FR);
		if (!(reg & XSPI_FR_TBFF)) {
			WARN_ON(1);
			return -EIO;
		}

		if (i == ALIGN_DOWN(op->data.nbytes, 4)) {
			/* Use 0xFF for extra bytes */
			left = 0xFFFFFFFF;
			/* The last 1 to 3 bytes */
			memcpy((u8 *)&left, buf + i, op->data.nbytes - i);
			writel(left, base + XSPI_TBDR);
		} else {
			writel(*(u32 *)(buf + i), base + XSPI_TBDR);
		}
	}

	return 0;
}

static int nxp_xspi_read_rxfifo(struct nxp_xspi *xspi,
				const struct spi_mem_op *op)
{
	u32 watermark, watermark_bytes, reg;
	void __iomem *base = xspi->iobase;
	u8 *buf = (u8 *) op->data.buf.in;
	int i, ret, len;

	/*
	 * Config the rx watermark half of the 64 memory-mapped RX data buffer RBDRn
	 * refer to the RBCT config in nxp_xspi_do_op()
	 */
	watermark = 32;
	watermark_bytes = watermark * 4;

	len = op->data.nbytes;

	while (len >= watermark_bytes) {
		/* Make sure the RX FIFO contains valid data before read */
		ret = readl_poll_timeout(base + XSPI_FR, reg,
				      reg & XSPI_FR_RBDF, 0, POLL_TOUT_US);
		if (ret) {
			WARN_ON(1);
			return ret;
		}

		for (i = 0; i < watermark; i++)
			*(u32 *)(buf + i * 4) = readl(base + XSPI_RBDR0 + i * 4);

		len = len - watermark_bytes;
		buf = buf + watermark_bytes;
		/* Pop up data to RXFIFO for next read. */
		reg = readl(base + XSPI_FR);
		reg |= XSPI_FR_RBDF;
		writel(reg, base + XSPI_FR);
	}

	/* Wait for the total data transfer finished */
	ret = readl_poll_timeout(base + XSPI_SR, reg, !(reg & XSPI_SR_BUSY), 0, POLL_TOUT_US);
	if (ret) {
		WARN_ON(1);
		return ret;
	}

	i = 0;
	while (len >= 4) {
		*(u32 *)(buf) = readl(base + XSPI_RBDR0 + i);
		i += 4;
		len -= 4;
		buf += 4;
	}

	if (len > 0) {
		reg = readl(base + XSPI_RBDR0 + i);
		memcpy(buf, (u8 *)&reg, len);
	}

	/* Invalid RXFIFO first */
	reg = readl(base + XSPI_MCR);
	reg |= XSPI_MCR_CLR_RXF;
	writel(reg, base + XSPI_MCR);
	/* Wait for the CLR_RXF clear */
	ret = readl_poll_timeout(base + XSPI_MCR, reg,
			      !(reg & XSPI_MCR_CLR_RXF), 1, POLL_TOUT_US);
	WARN_ON(ret);

	return ret;
}

static int nxp_xspi_do_op(struct nxp_xspi *xspi, const struct spi_mem_op *op)
{
	void __iomem *base = xspi->iobase;
	int watermark, err = 0;
	u32 reg, len;

	len = op->data.nbytes;
	if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) {
		/* Clear the TX FIFO. */
		reg = readl(base + XSPI_MCR);
		reg |= XSPI_MCR_CLR_TXF;
		writel(reg, base + XSPI_MCR);
		/* Wait for the CLR_TXF clear */
		err = readl_poll_timeout(base + XSPI_MCR, reg,
				      !(reg & XSPI_MCR_CLR_TXF), 1, POLL_TOUT_US);
		if (err) {
			WARN_ON(1);
			return err;
		}

		/* Cover the no 4bytes alignment data length */
		watermark = (xspi->devtype_data->txfifo - ALIGN(op->data.nbytes, 4)) / 4 + 1;
		reg = FIELD_PREP(XSPI_TBCT_WMRK_MASK, watermark);
		writel(reg, base + XSPI_TBCT);
		/*
		 * According to the RM, for TBDR register, a write transaction on the
		 * flash memory with data size of less than 32 bits leads to the removal
		 * of one data entry from the TX buffer. The valid bits are used and the
		 * rest of the bits are discarded.
		 * But for data size large than 32 bits, according to test, for no 4bytes
		 * alignment data, the last 1~3 bytes will lost, because TX buffer use
		 * 4 bytes entries.
		 * So here adjust the transfer data length to make it 4bytes alignment.
		 * then will meet the upper watermark setting, trigger the 4bytes entries
		 * pop out.
		 * Will use extra 0xff to append, refer to nxp_xspi_fill_txfifo().
		 */
		if (len > 4)
			len = ALIGN(op->data.nbytes, 4);

	} else if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) {
		/* Invalid RXFIFO first */
		reg = readl(base + XSPI_MCR);
		reg |= XSPI_MCR_CLR_RXF;
		writel(reg, base + XSPI_MCR);
		/* Wait for the CLR_RXF clear */
		err = readl_poll_timeout(base + XSPI_MCR, reg,
				      !(reg & XSPI_MCR_CLR_RXF), 1, POLL_TOUT_US);
		if (err) {
			WARN_ON(1);
			return err;
		}

		reg = FIELD_PREP(XSPI_RBCT_WMRK_MASK, 31);
		writel(reg, base + XSPI_RBCT);
	}

	init_completion(&xspi->c);

	/* Config the data address */
	writel(op->addr.val + xspi->memmap_phy, base + XSPI_SFP_TG_SFAR);

	/* Config the data size and lut id, trigger the transfer */
	reg = FIELD_PREP(XSPI_SFP_TG_IPCR_SEQID_MASK, XSPI_SEQID_LUT) |
	      FIELD_PREP(XSPI_SFP_TG_IPCR_IDATSZ_MASK, len);
	writel(reg, base + XSPI_SFP_TG_IPCR);

	if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) {
		err = nxp_xspi_fill_txfifo(xspi, op);
		if (err)
			return err;
	}

	/* Wait for the interrupt. */
	if (!wait_for_completion_timeout(&xspi->c, msecs_to_jiffies(1000)))
		err = -ETIMEDOUT;

	/* Invoke IP data read. */
	if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN)
		err = nxp_xspi_read_rxfifo(xspi, op);

	return err;
}

static int nxp_xspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
{
	struct nxp_xspi *xspi = spi_controller_get_devdata(mem->spi->controller);
	void __iomem *base = xspi->iobase;
	u32 reg;
	int err;

	guard(mutex)(&xspi->lock);

	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(xspi->dev, pm);
	err = PM_RUNTIME_ACQUIRE_ERR(&pm);
	if (err)
		return err;

	/* Wait for controller being ready. */
	err = readl_poll_timeout(base + XSPI_SR, reg,
			      !(reg & XSPI_SR_BUSY), 1, POLL_TOUT_US);
	if (err) {
		dev_err(xspi->dev, "SR keeps in BUSY!");
		return err;
	}

	nxp_xspi_select_mem(xspi, mem->spi, op);

	nxp_xspi_prepare_lut(xspi, op);

	/*
	 * For read:
	 *     the address in AHB mapped range will use AHB read.
	 *     the address out of AHB mapped range will use IP read.
	 * For write:
	 *     all use IP write.
	 */
	if ((op->data.dir == SPI_MEM_DATA_IN) && !needs_ip_only(xspi)
		&& ((op->addr.val + op->data.nbytes) <= xspi->memmap_phy_size))
		err = nxp_xspi_ahb_read(xspi, op);
	else
		err = nxp_xspi_do_op(xspi, op);

	nxp_xspi_sw_reset(xspi);

	return err;
}

static int nxp_xspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
	struct nxp_xspi *xspi = spi_controller_get_devdata(mem->spi->controller);

	if (op->data.dir == SPI_MEM_DATA_OUT) {
		if (op->data.nbytes > xspi->devtype_data->txfifo)
			op->data.nbytes = xspi->devtype_data->txfifo;
	} else {
		/* Limit data bytes to RX FIFO in case of IP read only */
		if (needs_ip_only(xspi) && (op->data.nbytes > xspi->devtype_data->rxfifo))
			op->data.nbytes = xspi->devtype_data->rxfifo;

		/* Address in AHB mapped range prefer to use AHB read. */
		if (!needs_ip_only(xspi) && (op->addr.val < xspi->memmap_phy_size)
			&& ((op->addr.val + op->data.nbytes) > xspi->memmap_phy_size))
			op->data.nbytes = xspi->memmap_phy_size - op->addr.val;
	}

	return 0;
}

static void nxp_xspi_config_ahb_buffer(struct nxp_xspi *xspi)
{
	void __iomem *base = xspi->iobase;
	u32 ahb_data_trans_size;
	u32 reg;

	writel(0xA, base + XSPI_BUF0CR);
	writel(0x2, base + XSPI_BUF1CR);
	writel(0xD, base + XSPI_BUF2CR);

	/* Configure buffer3 for All Master Access */
	reg = FIELD_PREP(XSPI_BUF3CR_MSTRID_MASK, 0x06) |
	      XSPI_BUF3CR_ALLMST;

	ahb_data_trans_size = xspi->devtype_data->ahb_buf_size / 8;
	reg |= FIELD_PREP(XSPI_BUF3CR_ADATSZ_MASK, ahb_data_trans_size);
	writel(reg, base + XSPI_BUF3CR);

	/* Only the buffer3 is used */
	writel(0, base + XSPI_BUF0IND);
	writel(0, base + XSPI_BUF1IND);
	writel(0, base + XSPI_BUF2IND);

	/* AHB only use ID=15 for read */
	reg = FIELD_PREP(XSPI_BFGENCR_SEQID_MASK, XSPI_SEQID_LUT);
	reg |= XSPI_BFGENCR_WR_FLUSH_EN;
	/* No limit for align */
	reg |= FIELD_PREP(XSPI_BFGENCR_ALIGN_MASK, 0);
	writel(reg, base + XSPI_BFGENCR);
}

static int nxp_xspi_default_setup(struct nxp_xspi *xspi)
{
	void __iomem *base = xspi->iobase;
	u32 reg;

	/* Bypass SFP check, clear MGC_GVLD, MGC_GVLDMDAD, MGC_GVLDFRAD */
	writel(0, base + XSPI_MGC);

	/* Enable the EENV0 SFP check */
	reg = readl(base + XSPI_TG0MDAD);
	reg |= XSPI_TG0MDAD_VLD;
	writel(reg, base + XSPI_TG0MDAD);

	/* Give read/write access right to EENV0 */
	reg = readl(base + XSPI_FRAD0_WORD2);
	reg &= ~XSPI_FRAD0_WORD2_MD0ACP_MASK;
	reg |= FIELD_PREP(XSPI_FRAD0_WORD2_MD0ACP_MASK, 0x03);
	writel(reg, base + XSPI_FRAD0_WORD2);

	/* Enable the FRAD check for EENV0 */
	reg = readl(base + XSPI_FRAD0_WORD3);
	reg |= XSPI_FRAD0_WORD3_VLD;
	writel(reg, base + XSPI_FRAD0_WORD3);

	/*
	 * Config the timeout to max value, this timeout will affect the
	 * TBDR and RBDRn access right after IP cmd triggered.
	 */
	writel(0xFFFFFFFF, base + XSPI_MTO);

	/* Disable module */
	reg = readl(base + XSPI_MCR);
	reg |= XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);

	nxp_xspi_sw_reset(xspi);

	reg = readl(base + XSPI_MCR);
	reg &= ~(XSPI_MCR_CKN_FA_EN | XSPI_MCR_DQS_FA_SEL_MASK |
		 XSPI_MCR_DOZE | XSPI_MCR_VAR_LAT_EN |
		 XSPI_MCR_DDR_EN | XSPI_MCR_DQS_OUT_EN);
	reg |= XSPI_MCR_DQS_EN;
	reg |= XSPI_MCR_ISD3FA | XSPI_MCR_ISD2FA;
	writel(reg, base + XSPI_MCR);

	reg = readl(base + XSPI_SFACR);
	reg &= ~(XSPI_SFACR_FORCE_A10 | XSPI_SFACR_WA_4B_EN |
		 XSPI_SFACR_BYTE_SWAP | XSPI_SFACR_WA |
		 XSPI_SFACR_CAS_MASK);
	reg |= XSPI_SFACR_FORCE_A10;
	writel(reg, base + XSPI_SFACR);

	nxp_xspi_config_ahb_buffer(xspi);

	reg = FIELD_PREP(XSPI_FLSHCR_TCSH_MASK, 0x03) |
	      FIELD_PREP(XSPI_FLSHCR_TCSS_MASK, 0x03);
	writel(reg, base + XSPI_FLSHCR);

	/* Enable module */
	reg = readl(base + XSPI_MCR);
	reg &= ~XSPI_MCR_MDIS;
	writel(reg, base + XSPI_MCR);

	xspi->selected = -1;

	/* Enable the interrupt */
	writel(XSPI_RSER_TFIE, base + XSPI_RSER);

	return 0;
}

static const char *nxp_xspi_get_name(struct spi_mem *mem)
{
	struct nxp_xspi *xspi = spi_controller_get_devdata(mem->spi->controller);
	struct device *dev = &mem->spi->dev;
	const char *name;

	/* Set custom name derived from the platform_device of the controller. */
	if (of_get_available_child_count(xspi->dev->of_node) == 1)
		return dev_name(xspi->dev);

	name = devm_kasprintf(dev, GFP_KERNEL,
			      "%s-%d", dev_name(xspi->dev),
			      spi_get_chipselect(mem->spi, 0));

	if (!name) {
		dev_err(dev, "failed to get memory for custom flash name\n");
		return ERR_PTR(-ENOMEM);
	}

	return name;
}

static const struct spi_controller_mem_ops nxp_xspi_mem_ops = {
	.adjust_op_size = nxp_xspi_adjust_op_size,
	.supports_op = nxp_xspi_supports_op,
	.exec_op = nxp_xspi_exec_op,
	.get_name = nxp_xspi_get_name,
};

static const struct spi_controller_mem_caps nxp_xspi_mem_caps = {
	.dtr = true,
	.per_op_freq = true,
	.swap16 = true,
};

static void nxp_xspi_cleanup(void *data)
{
	struct nxp_xspi *xspi = data;
	u32 reg;

	pm_runtime_get_sync(xspi->dev);

	/* Disable interrupt */
	writel(0, xspi->iobase + XSPI_RSER);
	/* Clear all the internal logic flags */
	writel(0xFFFFFFFF, xspi->iobase + XSPI_FR);
	/* Disable the hardware */
	reg = readl(xspi->iobase + XSPI_MCR);
	reg |= XSPI_MCR_MDIS;
	writel(reg, xspi->iobase + XSPI_MCR);

	pm_runtime_put_sync(xspi->dev);

	if (xspi->ahb_addr)
		iounmap(xspi->ahb_addr);
}

static int nxp_xspi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct spi_controller *ctlr;
	struct nxp_xspi *xspi;
	struct resource *res;
	int ret, irq;

	ctlr = devm_spi_alloc_host(dev, sizeof(*xspi));
	if (!ctlr)
		return -ENOMEM;

	ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL |
			  SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL;

	xspi = spi_controller_get_devdata(ctlr);
	xspi->dev = dev;
	xspi->devtype_data = device_get_match_data(dev);
	if (!xspi->devtype_data)
		return -ENODEV;

	platform_set_drvdata(pdev, xspi);

	/* Find the resources - configuration register address space */
	xspi->iobase = devm_platform_ioremap_resource_byname(pdev, "base");
	if (IS_ERR(xspi->iobase))
		return PTR_ERR(xspi->iobase);

	/* Find the resources - controller memory mapped space */
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmap");
	if (!res)
		return -ENODEV;

	/* Assign memory mapped starting address and mapped size. */
	xspi->memmap_phy = res->start;
	xspi->memmap_phy_size = resource_size(res);

	/* Find the clocks */
	xspi->clk = devm_clk_get(dev, "per");
	if (IS_ERR(xspi->clk))
		return PTR_ERR(xspi->clk);

	/* Find the irq */
	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return dev_err_probe(dev, irq,  "Failed to get irq source");

	pm_runtime_set_autosuspend_delay(dev, XSPI_RPM_TIMEOUT_MS);
	pm_runtime_use_autosuspend(dev);
	ret = devm_pm_runtime_enable(dev);
	if (ret)
		return ret;

	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to enable clock");

	/* Clear potential interrupt by write xspi errstat */
	writel(0xFFFFFFFF, xspi->iobase + XSPI_ERRSTAT);
	writel(0xFFFFFFFF, xspi->iobase + XSPI_FR);

	nxp_xspi_default_setup(xspi);

	ret = devm_request_irq(dev, irq,
			nxp_xspi_irq_handler, 0, pdev->name, xspi);
	if (ret)
		return dev_err_probe(dev, ret, "failed to request irq");

	ret = devm_mutex_init(dev, &xspi->lock);
	if (ret)
		return ret;

	ret = devm_add_action_or_reset(dev, nxp_xspi_cleanup, xspi);
	if (ret)
		return ret;

	ctlr->bus_num = -1;
	ctlr->num_chipselect = NXP_XSPI_MAX_CHIPSELECT;
	ctlr->mem_ops = &nxp_xspi_mem_ops;
	ctlr->mem_caps = &nxp_xspi_mem_caps;

	return devm_spi_register_controller(dev, ctlr);
}

static int nxp_xspi_runtime_suspend(struct device *dev)
{
	struct nxp_xspi *xspi = dev_get_drvdata(dev);
	u32 reg;

	reg = readl(xspi->iobase + XSPI_MCR);
	reg |= XSPI_MCR_MDIS;
	writel(reg, xspi->iobase + XSPI_MCR);

	clk_disable_unprepare(xspi->clk);

	return 0;
}

static int nxp_xspi_runtime_resume(struct device *dev)
{
	struct nxp_xspi *xspi = dev_get_drvdata(dev);
	u32 reg;
	int ret;

	ret = clk_prepare_enable(xspi->clk);
	if (ret)
		return ret;

	reg = readl(xspi->iobase + XSPI_MCR);
	reg &= ~XSPI_MCR_MDIS;
	writel(reg, xspi->iobase + XSPI_MCR);

	return 0;
}

static int nxp_xspi_suspend(struct device *dev)
{
	int ret;

	ret = pinctrl_pm_select_sleep_state(dev);
	if (ret) {
		dev_err(dev, "select flexspi sleep pinctrl failed!\n");
		return ret;
	}

	return pm_runtime_force_suspend(dev);
}

static int nxp_xspi_resume(struct device *dev)
{
	struct nxp_xspi *xspi = dev_get_drvdata(dev);
	int ret;

	ret = pm_runtime_force_resume(dev);
	if (ret)
		return ret;

	nxp_xspi_default_setup(xspi);

	ret = pinctrl_pm_select_default_state(dev);
	if (ret)
		dev_err(dev, "select flexspi default pinctrl failed!\n");

	return ret;
}


static const struct dev_pm_ops nxp_xspi_pm_ops = {
	RUNTIME_PM_OPS(nxp_xspi_runtime_suspend, nxp_xspi_runtime_resume, NULL)
	SYSTEM_SLEEP_PM_OPS(nxp_xspi_suspend, nxp_xspi_resume)
};

static const struct of_device_id nxp_xspi_dt_ids[] = {
	{ .compatible = "nxp,imx94-xspi", .data = (void *)&imx94_data, },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, nxp_xspi_dt_ids);

static struct platform_driver nxp_xspi_driver = {
	.driver = {
		.name	= "nxp-xspi",
		.of_match_table = nxp_xspi_dt_ids,
		.pm =   pm_ptr(&nxp_xspi_pm_ops),
	},
	.probe          = nxp_xspi_probe,
};
module_platform_driver(nxp_xspi_driver);

MODULE_DESCRIPTION("NXP xSPI Controller Driver");
MODULE_AUTHOR("NXP Semiconductor");
MODULE_AUTHOR("Haibo Chen <haibo.chen@nxp.com>");
MODULE_LICENSE("GPL");