* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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 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