* [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support
@ 2025-09-16 7:56 Haibo Chen
2025-09-16 7:56 ` [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override() Haibo Chen
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Haibo Chen @ 2025-09-16 7:56 UTC (permalink / raw)
To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen
this patch set add DTR mode support for flexspi.
For DTR mode, flexspi only support 8D-8D-8D mode.
Patch 1 extract nxp_fspi_dll_override(), prepare for adding the DTR mode.
in nor suspend, it will disable DTR mode, and enable DTR mode back
in nor resume. this require the flexspi driver has the ability to
set back to dll override mode in STR mode when clock rate < 100MHz.
Patch 2 Add the DDR LUT command support. flexspi use LUT command to handle
the dtr/str mode.
Patch 3 add the logic of sample clock source selection for STR/DTR mode
STR use the default mode 0, sample based on the internal dummy pad.
DTR use the mode 3, sample based on the external DQS pad, so this
board and device connect the DQS pad.
Patch 4 adjust the clock rate for DTR mode, when detect the DDR LUT command,
flexspi will automatically div 2 of the root clock and output to device.
Patch 5 finally add the DTR support in default after the upper 4 patches's
prepareation. Since lx2160a do not implement DQS pad, so can't support
this DTR mode.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
Haibo Chen (5):
spi: spi-nxp-fspi: extract function nxp_fspi_dll_override()
spi: spi-nxp-fspi: Add the DDR LUT command support
spi: spi-nxp-fspi: add the support for sample data from DQS pad
spi: spi-nxp-fspi: correct the clock rate for DTR mode
spi: spi-nxp-fspi: Add OCT-DTR mode support
drivers/spi/spi-nxp-fspi.c | 118 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 102 insertions(+), 16 deletions(-)
---
base-commit: c3067c2c38316c3ef013636c93daa285ee6aaa2e
change-id: 20250916-flexspi-ddr-f841f3d79aef
Best regards,
--
Haibo Chen <haibo.chen@nxp.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override()
2025-09-16 7:56 [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support Haibo Chen
@ 2025-09-16 7:56 ` Haibo Chen
2025-09-16 15:28 ` Frank Li
2025-09-16 7:56 ` [PATCH 2/5] spi: spi-nxp-fspi: Add the DDR LUT command support Haibo Chen
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Haibo Chen @ 2025-09-16 7:56 UTC (permalink / raw)
To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen
Extract function nxp_fspi_dll_override(), this is the suggested setting
when clock rate < 100MHz. Just the preparation of supportting DTR mode.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
drivers/spi/spi-nxp-fspi.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 848fa9319e36d65e8152931324b8e34eb162f5d3..a1c9ad03379682dc1fc2908fbd83e1ae8e91588f 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -674,6 +674,17 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
dev_warn(f->dev, "DLL lock failed, please fix it!\n");
}
+/*
+ * Config the DLL register to default value, enable the target clock delay
+ * line delay cell override mode, and use 1 fixed delay cell in DLL delay
+ * chain, this is the suggested setting when clock rate < 100MHz.
+ */
+static void nxp_fspi_dll_override(struct nxp_fspi *f)
+{
+ fspi_writel(f, FSPI_DLLACR_OVRDEN, f->iobase + FSPI_DLLACR);
+ fspi_writel(f, FSPI_DLLBCR_OVRDEN, f->iobase + FSPI_DLLBCR);
+}
+
/*
* In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
* register and start base address of the target device.
@@ -756,6 +767,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
*/
if (rate > 100000000)
nxp_fspi_dll_calibration(f);
+ else
+ nxp_fspi_dll_override(f);
f->selected = spi_get_chipselect(spi, 0);
}
@@ -1071,13 +1084,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
/* Disable the module */
fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0);
- /*
- * Config the DLL register to default value, enable the target clock delay
- * line delay cell override mode, and use 1 fixed delay cell in DLL delay
- * chain, this is the suggested setting when clock rate < 100MHz.
- */
- fspi_writel(f, FSPI_DLLACR_OVRDEN, base + FSPI_DLLACR);
- fspi_writel(f, FSPI_DLLBCR_OVRDEN, base + FSPI_DLLBCR);
+ nxp_fspi_dll_override(f);
/* enable module */
fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) |
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/5] spi: spi-nxp-fspi: Add the DDR LUT command support
2025-09-16 7:56 [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support Haibo Chen
2025-09-16 7:56 ` [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override() Haibo Chen
@ 2025-09-16 7:56 ` Haibo Chen
2025-09-16 15:31 ` Frank Li
2025-09-16 7:56 ` [PATCH 3/5] spi: spi-nxp-fspi: add the support for sample data from DQS pad Haibo Chen
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Haibo Chen @ 2025-09-16 7:56 UTC (permalink / raw)
To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen
For DTR mode, flexspi need to use DDR LUT command, flexspi will switch
to DDR mode when detect the DDR LUT command.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
drivers/spi/spi-nxp-fspi.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index a1c9ad03379682dc1fc2908fbd83e1ae8e91588f..6b3e6b427ba84734a2359a964635a8f05cd146fd 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -559,12 +559,22 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
u32 target_lut_reg;
/* cmd */
- lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
- op->cmd.opcode);
+ 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 & 0xFF);
+ lutidx++;
+ } else {
+ lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
+ op->cmd.opcode);
+ }
/* addr bytes */
if (op->addr.nbytes) {
- lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, op->addr.dtr ?
+ LUT_ADDR_DDR : LUT_ADDR,
LUT_PAD(op->addr.buswidth),
op->addr.nbytes * 8);
lutidx++;
@@ -572,7 +582,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
/* dummy bytes, if needed */
if (op->dummy.nbytes) {
- lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, op->dummy.dtr ?
+ LUT_DUMMY_DDR : LUT_DUMMY,
/*
* Due to FlexSPI controller limitation number of PAD for dummy
* buswidth needs to be programmed as equal to data buswidth.
@@ -587,7 +598,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
if (op->data.nbytes) {
lutval[lutidx / 2] |= LUT_DEF(lutidx,
op->data.dir == SPI_MEM_DATA_IN ?
- LUT_NXP_READ : LUT_NXP_WRITE,
+ (op->data.dtr ? LUT_READ_DDR : LUT_NXP_READ) :
+ (op->data.dtr ? LUT_WRITE_DDR : LUT_NXP_WRITE),
LUT_PAD(op->data.buswidth),
0);
lutidx++;
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/5] spi: spi-nxp-fspi: add the support for sample data from DQS pad
2025-09-16 7:56 [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support Haibo Chen
2025-09-16 7:56 ` [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override() Haibo Chen
2025-09-16 7:56 ` [PATCH 2/5] spi: spi-nxp-fspi: Add the DDR LUT command support Haibo Chen
@ 2025-09-16 7:56 ` Haibo Chen
2025-09-16 15:37 ` Frank Li
2025-09-16 7:56 ` [PATCH 4/5] spi: spi-nxp-fspi: correct the clock rate for DTR mode Haibo Chen
2025-09-16 7:56 ` [PATCH 5/5] spi: spi-nxp-fspi: Add OCT-DTR mode support Haibo Chen
4 siblings, 1 reply; 11+ messages in thread
From: Haibo Chen @ 2025-09-16 7:56 UTC (permalink / raw)
To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen
flexspi define four mode for sample clock source selection.
Here is the list of modes:
mode 0: Dummy Read strobe generated by FlexSPI Controller and loopback
internally
mode 1: Dummy Read strobe generated by FlexSPI Controller and loopback
from DQS pad
mode 2: Reserved
mode 3: Flash provided Read strobe and input from DQS pad
In default, flexspi use mode 0 after reset. And for DTR mode, flexspi
only support 8D-8D-8D mode. For 8D-8D-8D mode, IC suggest to use mode 3,
otherwise read always get incorrect data.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
drivers/spi/spi-nxp-fspi.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 6b3e6b427ba84734a2359a964635a8f05cd146fd..be1e56072b94f38af934556055e321d9834bb07b 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -400,6 +400,7 @@ struct nxp_fspi {
struct pm_qos_request pm_qos_req;
int selected;
#define FSPI_NEED_INIT (1 << 0)
+#define FSPI_DTR_MODE (1 << 1)
int flags;
};
@@ -657,6 +658,43 @@ static void nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
return;
}
+/*
+ * Sample Clock source selection for Flash Reading
+ * Four modes defined by fspi:
+ * mode 0: Dummy Read strobe generated by FlexSPI Controller
+ * and loopback internally
+ * mode 1: Dummy Read strobe generated by FlexSPI Controller
+ * and loopback from DQS pad
+ * mode 2: Reserved
+ * mode 3: Flash provided Read strobe and input from DQS pad
+ *
+ * fspi default use mode 0 after reset
+ */
+static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
+ bool op_is_dtr)
+{
+ u32 reg;
+
+ /*
+ * For 8D-8D-8D mode, need to use mode 3 (Flash provided Read
+ * strobe and input from DQS pad), otherwise read operaton may
+ * meet issue.
+ * This mode require flash device connect the DQS pad on board.
+ * For other modes, still use mode 0, keep align with before.
+ * spi_nor_suspend will disable 8D-8D-8D mode, also need to
+ * change the mode back to mode 0.
+ */
+ if (op_is_dtr) {
+ reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+ reg |= FSPI_MCR0_RXCLKSRC(3);
+ fspi_writel(f, reg, f->iobase + FSPI_MCR0);
+ } else {
+ reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+ reg &= ~FSPI_MCR0_RXCLKSRC(3); /* select mode 0 */
+ fspi_writel(f, reg, f->iobase + FSPI_MCR0);
+ }
+}
+
static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
{
int ret;
@@ -738,15 +776,18 @@ static void nxp_fspi_dll_override(struct nxp_fspi *f)
static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
const struct spi_mem_op *op)
{
+ /* flexspi 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 rate = op->max_freq;
int ret;
uint64_t size_kb;
/*
* Return, if previously selected target device is same as current
- * requested target device.
+ * requested target device. Also the DTR or STR mode do not change.
*/
- if (f->selected == spi_get_chipselect(spi, 0))
+ if ((f->selected == spi_get_chipselect(spi, 0)) &&
+ (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr))
return;
/* Reset FLSHxxCR0 registers */
@@ -763,6 +804,13 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
+ nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
+
+ if (op_is_dtr)
+ f->flags |= FSPI_DTR_MODE;
+ else
+ f->flags &= ~FSPI_DTR_MODE;
+
nxp_fspi_clk_disable_unprep(f);
ret = clk_set_rate(f->clk, rate);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/5] spi: spi-nxp-fspi: correct the clock rate for DTR mode
2025-09-16 7:56 [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support Haibo Chen
` (2 preceding siblings ...)
2025-09-16 7:56 ` [PATCH 3/5] spi: spi-nxp-fspi: add the support for sample data from DQS pad Haibo Chen
@ 2025-09-16 7:56 ` Haibo Chen
2025-09-16 15:39 ` Frank Li
2025-09-16 7:56 ` [PATCH 5/5] spi: spi-nxp-fspi: Add OCT-DTR mode support Haibo Chen
4 siblings, 1 reply; 11+ messages in thread
From: Haibo Chen @ 2025-09-16 7:56 UTC (permalink / raw)
To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen
For DTR mode, flexspi will automatically div 2 of the root clock
and output to device. the formula is:
device_clock = root_clock / (is_dtr ? 2 : 1);
So correct the clock rate setting for DTR mode to get the max
performance.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
drivers/spi/spi-nxp-fspi.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index be1e56072b94f38af934556055e321d9834bb07b..15b094e8e892f0b61c1f320bba897fa1f588be91 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -806,10 +806,15 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
- if (op_is_dtr)
+ if (op_is_dtr) {
f->flags |= FSPI_DTR_MODE;
- else
+ /* For DTR mode, flexspi will default div 2 and output to device.
+ * so here to config the root clock to 2 * device rate.
+ */
+ rate = rate * 2;
+ } else {
f->flags &= ~FSPI_DTR_MODE;
+ }
nxp_fspi_clk_disable_unprep(f);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/5] spi: spi-nxp-fspi: Add OCT-DTR mode support
2025-09-16 7:56 [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support Haibo Chen
` (3 preceding siblings ...)
2025-09-16 7:56 ` [PATCH 4/5] spi: spi-nxp-fspi: correct the clock rate for DTR mode Haibo Chen
@ 2025-09-16 7:56 ` Haibo Chen
2025-09-16 15:43 ` Frank Li
4 siblings, 1 reply; 11+ messages in thread
From: Haibo Chen @ 2025-09-16 7:56 UTC (permalink / raw)
To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen
Add OCT-DTR mode support in default, since flexspi do not supports
swapping bytes on a 16 bit boundary in OCT-DTR mode, so mark swap16
as false.
lx2160a do not support DQS, so add a quirk to disable DTR mode for this
platform.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
drivers/spi/spi-nxp-fspi.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 15b094e8e892f0b61c1f320bba897fa1f588be91..389cb20872db6d9653a146eac7182b9a4574496b 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -330,6 +330,8 @@
/* Access flash memory using IP bus only */
#define FSPI_QUIRK_USE_IP_ONLY BIT(0)
+/* Disable DTR */
+#define FSPI_QUIRK_DISABLE_DTR BIT(1)
struct nxp_fspi_devtype_data {
unsigned int rxfifo;
@@ -344,7 +346,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
- .quirks = 0,
+ .quirks = FSPI_QUIRK_DISABLE_DTR,
.lut_num = 32,
.little_endian = true, /* little-endian */
};
@@ -1236,6 +1238,13 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = {
};
static const struct spi_controller_mem_caps nxp_fspi_mem_caps = {
+ .dtr = true,
+ .swap16 = false,
+ .per_op_freq = true,
+};
+
+static const struct spi_controller_mem_caps nxp_fspi_mem_caps_quirks = {
+ .dtr = false,
.per_op_freq = true,
};
@@ -1351,7 +1360,12 @@ static int nxp_fspi_probe(struct platform_device *pdev)
ctlr->bus_num = -1;
ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
ctlr->mem_ops = &nxp_fspi_mem_ops;
- ctlr->mem_caps = &nxp_fspi_mem_caps;
+
+ if (f->devtype_data->quirks & FSPI_QUIRK_DISABLE_DTR)
+ ctlr->mem_caps = &nxp_fspi_mem_caps_quirks;
+ else
+ ctlr->mem_caps = &nxp_fspi_mem_caps;
+
ctlr->dev.of_node = np;
ret = devm_add_action_or_reset(dev, nxp_fspi_cleanup, f);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override()
2025-09-16 7:56 ` [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override() Haibo Chen
@ 2025-09-16 15:28 ` Frank Li
0 siblings, 0 replies; 11+ messages in thread
From: Frank Li @ 2025-09-16 15:28 UTC (permalink / raw)
To: Haibo Chen; +Cc: Han Xu, Yogesh Gaur, Mark Brown, linux-spi, imx, linux-kernel
On Tue, Sep 16, 2025 at 03:56:40PM +0800, Haibo Chen wrote:
> Extract function nxp_fspi_dll_override(), this is the suggested setting
> when clock rate < 100MHz. Just the preparation of supportting DTR mode.
>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
> drivers/spi/spi-nxp-fspi.c | 21 ++++++++++++++-------
> 1 file changed, 14 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index 848fa9319e36d65e8152931324b8e34eb162f5d3..a1c9ad03379682dc1fc2908fbd83e1ae8e91588f 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -674,6 +674,17 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
> dev_warn(f->dev, "DLL lock failed, please fix it!\n");
> }
>
> +/*
> + * Config the DLL register to default value, enable the target clock delay
> + * line delay cell override mode, and use 1 fixed delay cell in DLL delay
> + * chain, this is the suggested setting when clock rate < 100MHz.
> + */
> +static void nxp_fspi_dll_override(struct nxp_fspi *f)
> +{
> + fspi_writel(f, FSPI_DLLACR_OVRDEN, f->iobase + FSPI_DLLACR);
> + fspi_writel(f, FSPI_DLLBCR_OVRDEN, f->iobase + FSPI_DLLBCR);
> +}
> +
> /*
> * In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
> * register and start base address of the target device.
> @@ -756,6 +767,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
> */
> if (rate > 100000000)
> nxp_fspi_dll_calibration(f);
> + else
> + nxp_fspi_dll_override(f);
This one doesn't belong trivial code restruture. Suggest use new patch for
it.
Frank
>
> f->selected = spi_get_chipselect(spi, 0);
> }
> @@ -1071,13 +1084,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
> /* Disable the module */
> fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0);
>
> - /*
> - * Config the DLL register to default value, enable the target clock delay
> - * line delay cell override mode, and use 1 fixed delay cell in DLL delay
> - * chain, this is the suggested setting when clock rate < 100MHz.
> - */
> - fspi_writel(f, FSPI_DLLACR_OVRDEN, base + FSPI_DLLACR);
> - fspi_writel(f, FSPI_DLLBCR_OVRDEN, base + FSPI_DLLBCR);
> + nxp_fspi_dll_override(f);
>
> /* enable module */
> fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) |
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/5] spi: spi-nxp-fspi: Add the DDR LUT command support
2025-09-16 7:56 ` [PATCH 2/5] spi: spi-nxp-fspi: Add the DDR LUT command support Haibo Chen
@ 2025-09-16 15:31 ` Frank Li
0 siblings, 0 replies; 11+ messages in thread
From: Frank Li @ 2025-09-16 15:31 UTC (permalink / raw)
To: Haibo Chen; +Cc: Han Xu, Yogesh Gaur, Mark Brown, linux-spi, imx, linux-kernel
On Tue, Sep 16, 2025 at 03:56:41PM +0800, Haibo Chen wrote:
> For DTR mode, flexspi need to use DDR LUT command, flexspi will switch
> to DDR mode when detect the DDR LUT command.
>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
> drivers/spi/spi-nxp-fspi.c | 22 +++++++++++++++++-----
> 1 file changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index a1c9ad03379682dc1fc2908fbd83e1ae8e91588f..6b3e6b427ba84734a2359a964635a8f05cd146fd 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -559,12 +559,22 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
> u32 target_lut_reg;
>
> /* cmd */
> - lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
> - op->cmd.opcode);
> + 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 & 0xFF);
> + lutidx++;
> + } else {
> + lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
> + op->cmd.opcode);
> + }
>
> /* addr bytes */
> if (op->addr.nbytes) {
> - lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
> + lutval[lutidx / 2] |= LUT_DEF(lutidx, op->addr.dtr ?
> + LUT_ADDR_DDR : LUT_ADDR,
op->addr.dtr ? UT_ADDR_DDR : LUT_ADDR,
put ? to one line to look better.
> LUT_PAD(op->addr.buswidth),
> op->addr.nbytes * 8);
> lutidx++;
> @@ -572,7 +582,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
>
> /* dummy bytes, if needed */
> if (op->dummy.nbytes) {
> - lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
> + lutval[lutidx / 2] |= LUT_DEF(lutidx, op->dummy.dtr ?
> + LUT_DUMMY_DDR : LUT_DUMMY,
the same here.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> /*
> * Due to FlexSPI controller limitation number of PAD for dummy
> * buswidth needs to be programmed as equal to data buswidth.
> @@ -587,7 +598,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
> if (op->data.nbytes) {
> lutval[lutidx / 2] |= LUT_DEF(lutidx,
> op->data.dir == SPI_MEM_DATA_IN ?
> - LUT_NXP_READ : LUT_NXP_WRITE,
> + (op->data.dtr ? LUT_READ_DDR : LUT_NXP_READ) :
> + (op->data.dtr ? LUT_WRITE_DDR : LUT_NXP_WRITE),
> LUT_PAD(op->data.buswidth),
> 0);
> lutidx++;
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/5] spi: spi-nxp-fspi: add the support for sample data from DQS pad
2025-09-16 7:56 ` [PATCH 3/5] spi: spi-nxp-fspi: add the support for sample data from DQS pad Haibo Chen
@ 2025-09-16 15:37 ` Frank Li
0 siblings, 0 replies; 11+ messages in thread
From: Frank Li @ 2025-09-16 15:37 UTC (permalink / raw)
To: Haibo Chen; +Cc: Han Xu, Yogesh Gaur, Mark Brown, linux-spi, imx, linux-kernel
On Tue, Sep 16, 2025 at 03:56:42PM +0800, Haibo Chen wrote:
> flexspi define four mode for sample clock source selection.
> Here is the list of modes:
> mode 0: Dummy Read strobe generated by FlexSPI Controller and loopback
> internally
> mode 1: Dummy Read strobe generated by FlexSPI Controller and loopback
> from DQS pad
> mode 2: Reserved
> mode 3: Flash provided Read strobe and input from DQS pad
>
> In default, flexspi use mode 0 after reset. And for DTR mode, flexspi
> only support 8D-8D-8D mode. For 8D-8D-8D mode, IC suggest to use mode 3,
> otherwise read always get incorrect data.
>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
> drivers/spi/spi-nxp-fspi.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 50 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index 6b3e6b427ba84734a2359a964635a8f05cd146fd..be1e56072b94f38af934556055e321d9834bb07b 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -400,6 +400,7 @@ struct nxp_fspi {
> struct pm_qos_request pm_qos_req;
> int selected;
> #define FSPI_NEED_INIT (1 << 0)
> +#define FSPI_DTR_MODE (1 << 1)
Can you change to use BIT(1)
Frank
> int flags;
> };
>
> @@ -657,6 +658,43 @@ static void nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
> return;
> }
>
> +/*
> + * Sample Clock source selection for Flash Reading
> + * Four modes defined by fspi:
> + * mode 0: Dummy Read strobe generated by FlexSPI Controller
> + * and loopback internally
> + * mode 1: Dummy Read strobe generated by FlexSPI Controller
> + * and loopback from DQS pad
> + * mode 2: Reserved
> + * mode 3: Flash provided Read strobe and input from DQS pad
> + *
> + * fspi default use mode 0 after reset
> + */
> +static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
> + bool op_is_dtr)
> +{
> + u32 reg;
> +
> + /*
> + * For 8D-8D-8D mode, need to use mode 3 (Flash provided Read
> + * strobe and input from DQS pad), otherwise read operaton may
> + * meet issue.
> + * This mode require flash device connect the DQS pad on board.
> + * For other modes, still use mode 0, keep align with before.
> + * spi_nor_suspend will disable 8D-8D-8D mode, also need to
> + * change the mode back to mode 0.
> + */
> + if (op_is_dtr) {
> + reg = fspi_readl(f, f->iobase + FSPI_MCR0);
> + reg |= FSPI_MCR0_RXCLKSRC(3);
> + fspi_writel(f, reg, f->iobase + FSPI_MCR0);
> + } else {
> + reg = fspi_readl(f, f->iobase + FSPI_MCR0);
> + reg &= ~FSPI_MCR0_RXCLKSRC(3); /* select mode 0 */
> + fspi_writel(f, reg, f->iobase + FSPI_MCR0);
> + }
reg = fspi_readl(f, f->iobase + FSPI_MCR0);
if (op_is_dtr)
reg |= FSPI_MCR0_RXCLKSRC(3);
else
reg &= ~FSPI_MCR0_RXCLKSRC(3); /* select mode 0 */
fspi_writel(f, reg, f->iobase + FSPI_MCR0);
Is it better?
Frank
> +}
> +
> static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
> {
> int ret;
> @@ -738,15 +776,18 @@ static void nxp_fspi_dll_override(struct nxp_fspi *f)
> static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
> const struct spi_mem_op *op)
> {
> + /* flexspi 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 rate = op->max_freq;
> int ret;
> uint64_t size_kb;
>
> /*
> * Return, if previously selected target device is same as current
> - * requested target device.
> + * requested target device. Also the DTR or STR mode do not change.
> */
> - if (f->selected == spi_get_chipselect(spi, 0))
> + if ((f->selected == spi_get_chipselect(spi, 0)) &&
> + (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr))
> return;
>
> /* Reset FLSHxxCR0 registers */
> @@ -763,6 +804,13 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
>
> dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
>
> + nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
> +
> + if (op_is_dtr)
> + f->flags |= FSPI_DTR_MODE;
> + else
> + f->flags &= ~FSPI_DTR_MODE;
> +
> nxp_fspi_clk_disable_unprep(f);
>
> ret = clk_set_rate(f->clk, rate);
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/5] spi: spi-nxp-fspi: correct the clock rate for DTR mode
2025-09-16 7:56 ` [PATCH 4/5] spi: spi-nxp-fspi: correct the clock rate for DTR mode Haibo Chen
@ 2025-09-16 15:39 ` Frank Li
0 siblings, 0 replies; 11+ messages in thread
From: Frank Li @ 2025-09-16 15:39 UTC (permalink / raw)
To: Haibo Chen; +Cc: Han Xu, Yogesh Gaur, Mark Brown, linux-spi, imx, linux-kernel
On Tue, Sep 16, 2025 at 03:56:43PM +0800, Haibo Chen wrote:
> For DTR mode, flexspi will automatically div 2 of the root clock
> and output to device. the formula is:
> device_clock = root_clock / (is_dtr ? 2 : 1);
>
> So correct the clock rate setting for DTR mode to get the max
> performance.
>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
You can squash this to previous patch
This belong to add DTR support part.
Frank
> ---
> drivers/spi/spi-nxp-fspi.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index be1e56072b94f38af934556055e321d9834bb07b..15b094e8e892f0b61c1f320bba897fa1f588be91 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -806,10 +806,15 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
>
> nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
>
> - if (op_is_dtr)
> + if (op_is_dtr) {
> f->flags |= FSPI_DTR_MODE;
> - else
> + /* For DTR mode, flexspi will default div 2 and output to device.
> + * so here to config the root clock to 2 * device rate.
> + */
> + rate = rate * 2;
> + } else {
> f->flags &= ~FSPI_DTR_MODE;
> + }
>
> nxp_fspi_clk_disable_unprep(f);
>
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/5] spi: spi-nxp-fspi: Add OCT-DTR mode support
2025-09-16 7:56 ` [PATCH 5/5] spi: spi-nxp-fspi: Add OCT-DTR mode support Haibo Chen
@ 2025-09-16 15:43 ` Frank Li
0 siblings, 0 replies; 11+ messages in thread
From: Frank Li @ 2025-09-16 15:43 UTC (permalink / raw)
To: Haibo Chen; +Cc: Han Xu, Yogesh Gaur, Mark Brown, linux-spi, imx, linux-kernel
On Tue, Sep 16, 2025 at 03:56:44PM +0800, Haibo Chen wrote:
> Add OCT-DTR mode support in default, since flexspi do not supports
> swapping bytes on a 16 bit boundary in OCT-DTR mode, so mark swap16
> as false.
>
> lx2160a do not support DQS, so add a quirk to disable DTR mode for this
> platform.
>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
> drivers/spi/spi-nxp-fspi.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index 15b094e8e892f0b61c1f320bba897fa1f588be91..389cb20872db6d9653a146eac7182b9a4574496b 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -330,6 +330,8 @@
>
> /* Access flash memory using IP bus only */
> #define FSPI_QUIRK_USE_IP_ONLY BIT(0)
> +/* Disable DTR */
> +#define FSPI_QUIRK_DISABLE_DTR BIT(1)
>
> struct nxp_fspi_devtype_data {
> unsigned int rxfifo;
> @@ -344,7 +346,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
> .rxfifo = SZ_512, /* (64 * 64 bits) */
> .txfifo = SZ_1K, /* (128 * 64 bits) */
> .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
> - .quirks = 0,
> + .quirks = FSPI_QUIRK_DISABLE_DTR,
> .lut_num = 32,
> .little_endian = true, /* little-endian */
> };
> @@ -1236,6 +1238,13 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = {
> };
>
> static const struct spi_controller_mem_caps nxp_fspi_mem_caps = {
> + .dtr = true,
> + .swap16 = false,
> + .per_op_freq = true,
> +};
> +
> +static const struct spi_controller_mem_caps nxp_fspi_mem_caps_quirks = {
> + .dtr = false,
> .per_op_freq = true,
> };
>
> @@ -1351,7 +1360,12 @@ static int nxp_fspi_probe(struct platform_device *pdev)
> ctlr->bus_num = -1;
> ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
> ctlr->mem_ops = &nxp_fspi_mem_ops;
> - ctlr->mem_caps = &nxp_fspi_mem_caps;
> +
> + if (f->devtype_data->quirks & FSPI_QUIRK_DISABLE_DTR)
> + ctlr->mem_caps = &nxp_fspi_mem_caps_quirks;
the name 'nxp_fspi_mem_caps_quirks' is too general.
nxp_fspi_mem_caps_disable_dtr?
Frank
> + else
> + ctlr->mem_caps = &nxp_fspi_mem_caps;
> +
> ctlr->dev.of_node = np;
>
> ret = devm_add_action_or_reset(dev, nxp_fspi_cleanup, f);
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-09-16 15:43 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-16 7:56 [PATCH 0/5] spi: spi-nxp-fspi: add DTR mode support Haibo Chen
2025-09-16 7:56 ` [PATCH 1/5] spi: spi-nxp-fspi: extract function nxp_fspi_dll_override() Haibo Chen
2025-09-16 15:28 ` Frank Li
2025-09-16 7:56 ` [PATCH 2/5] spi: spi-nxp-fspi: Add the DDR LUT command support Haibo Chen
2025-09-16 15:31 ` Frank Li
2025-09-16 7:56 ` [PATCH 3/5] spi: spi-nxp-fspi: add the support for sample data from DQS pad Haibo Chen
2025-09-16 15:37 ` Frank Li
2025-09-16 7:56 ` [PATCH 4/5] spi: spi-nxp-fspi: correct the clock rate for DTR mode Haibo Chen
2025-09-16 15:39 ` Frank Li
2025-09-16 7:56 ` [PATCH 5/5] spi: spi-nxp-fspi: Add OCT-DTR mode support Haibo Chen
2025-09-16 15:43 ` Frank Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox