Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
* [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs
@ 2026-07-27  9:08 haibo.chen
  2026-07-27  9:16 ` sashiko-bot
  2026-07-27 14:59 ` Frank Li
  0 siblings, 2 replies; 3+ messages in thread
From: haibo.chen @ 2026-07-27  9:08 UTC (permalink / raw)
  To: Han Xu, Yogesh Gaur, Mark Brown; +Cc: linux-spi, imx, linux-kernel, Haibo Chen

From: Haibo Chen <haibo.chen@nxp.com>

The commit f43579ef3500 ("spi: spi-nxp-fspi: limit the clock rate for
different sample clock source selection") introduced a global 166MHz
cap for DTR mode (RXCLKSRC=3), based on the i.MX8MN datasheet timing
specification (Section 3.9.9, page 65).

After reviewing the FlexSPI timing parameters in the datasheets for all
supported SoCs, the following corrections and additions are needed:

1. SDR mode (RXCLKSRC=0) limits vary per SoC:
   - i.MX8MN/MM/MP/95: 66MHz  (IMX8MNCEC §3.9.9, IMX8MMCEC §3.9.10,
                                IMX8MPCEC, IMX95CEC Rev.8 §4.11.7)
   - i.MX8QXP/QM/DXL/ULP: 60MHz (IMX8QXPCEC, IMX8QMCEC, IMX8DXLCEC,
                                   IMX8ULPCEC §7.3.1 ND mode)
   - LX2160A: 100MHz            (LX2160ACEC FlexSPI timing parameters)

2. DTR mode (RXCLKSRC=3) limits vary per SoC:
   - i.MX8MN/MM/MP/ULP: 166MHz
   - i.MX8QXP/QM/DXL: 200MHz   (same FlexSPI IP across this family)
   - i.MX95: 200MHz             (IMX95CEC §4.11.7.3.2.3 Table 106)
   - LX2160A: DTR disabled      (FSPI_QUIRK_DISABLE_DTR)

- Add max_sdr_rate and max_dtr_rate field to nxp_fspi_devtype_data
- Use per-SoC max_sdr_rate in nxp_fspi_select_rx_sample_clk_source(),
  falling back to 66MHz default when zero (preserves existing behavior
  for any future SoC entries that omit the field)
- Use per-SoC max_ddr_rate in nxp_fspi_select_rx_sample_clk_source(),
  falling back to 166MHz default when zero (preserves existing behavior
  for any future SoC entries that omit the field)
- Add dedicated imx8mp_data (previously aliased to imx8mm_data) with
  explicit frequency limits
- Update imx8qxp_data, imx8dxl_data with correct 60/200MHz limits
- Update imx8ulp_data with ND (Normal Drive, 1.0V) mode limits: 60/166MHz
- Update lx2160a_data with correct SDR 100MHz limit
- Update imx95_data with correct 66/200MHz limits

Note: i.MX8ULP limits are specified for Normal Drive (ND, 1.0V) mode
as this is the standard operating condition. Overdrive (OD, 1.05V)
allows up to 180MHz DTR but is not the default use case.

Fixes: f43579ef3500 ("spi: spi-nxp-fspi: limit the clock rate for different sample clock source selection")
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/spi/spi-nxp-fspi.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 78 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index d94a2a7b98d44db217ba96a8ce7df23e37a08ba4..1159f5fc8a3a69eb464f32fd92e283e84ebd67ab 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -340,6 +340,18 @@ struct nxp_fspi_devtype_data {
 	unsigned int quirks;
 	unsigned int lut_num;
 	bool little_endian;
+	/*
+	 * The max clock rate (Hz) that FlexSPI can output to the device
+	 * in SDR mode (RXCLKSRC=0). Defaults to 66MHz if zero.
+	 * Some SoCs (e.g. LX2160A) support up to 100MHz in SDR mode.
+	 */
+	unsigned long max_sdr_rate;
+	/*
+	 * The max clock rate (Hz) that FlexSPI can output to the device
+	 * in DTR mode (RXCLKSRC=3). Defaults to 166MHz if zero.
+	 * Some SoCs (e.g. i.MX95, i.MX8QM, i.MX8DXL) support up to 200MHz.
+	 */
+	unsigned long max_dtr_rate;
 };
 
 static struct nxp_fspi_devtype_data lx2160a_data = {
@@ -349,6 +361,10 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
 	.quirks = FSPI_QUIRK_DISABLE_DTR,
 	.lut_num = 32,
 	.little_endian = true,  /* little-endian    */
+	/*
+	 * LX2160ACEC: SDR RXCLKSRC=0 max 100MHz, DTR disabled via quirk.
+	 */
+	.max_sdr_rate = 100000000,
 };
 
 static struct nxp_fspi_devtype_data imx8mm_data = {
@@ -358,6 +374,21 @@ static struct nxp_fspi_devtype_data imx8mm_data = {
 	.quirks = 0,
 	.lut_num = 32,
 	.little_endian = true,  /* little-endian    */
+	/* IMX8MMCEC §3.9.10: SDR RXCLKSRC=0 max 66MHz, DDR RXCLKSRC=3 max 166MHz */
+	.max_sdr_rate = 66000000,
+	.max_dtr_rate = 166000000,
+};
+
+static struct nxp_fspi_devtype_data imx8mp_data = {
+	.rxfifo = SZ_512,       /* (64  * 64 bits)  */
+	.txfifo = SZ_1K,        /* (128 * 64 bits)  */
+	.ahb_buf_size = SZ_2K,  /* (256 * 64 bits)  */
+	.quirks = 0,
+	.lut_num = 32,
+	.little_endian = true,  /* little-endian    */
+	/* IMX8MPCEC: SDR RXCLKSRC=0 max 66MHz, DDR RXCLKSRC=3 max 166MHz */
+	.max_sdr_rate = 66000000,
+	.max_dtr_rate = 166000000,
 };
 
 static struct nxp_fspi_devtype_data imx8qxp_data = {
@@ -367,6 +398,12 @@ static struct nxp_fspi_devtype_data imx8qxp_data = {
 	.quirks = 0,
 	.lut_num = 32,
 	.little_endian = true,  /* little-endian    */
+	/*
+	 * IMX8QXPCEC: SDR RXCLKSRC=0 max 60MHz, DDR RXCLKSRC=3 max 200MHz.
+	 * i.MX8QM and i.MX8DXL share the same FlexSPI IP and limits.
+	 */
+	.max_sdr_rate = 60000000,
+	.max_dtr_rate = 200000000,
 };
 
 static struct nxp_fspi_devtype_data imx8dxl_data = {
@@ -376,6 +413,12 @@ static struct nxp_fspi_devtype_data imx8dxl_data = {
 	.quirks = FSPI_QUIRK_USE_IP_ONLY,
 	.lut_num = 32,
 	.little_endian = true,  /* little-endian    */
+	/*
+	 * IMX8DXLCEC (i.MX 8XLite): SDR RXCLKSRC=0 max 60MHz,
+	 * DDR RXCLKSRC=3 max 200MHz.
+	 */
+	.max_sdr_rate = 60000000,
+	.max_dtr_rate = 200000000,
 };
 
 static struct nxp_fspi_devtype_data imx8ulp_data = {
@@ -385,6 +428,27 @@ static struct nxp_fspi_devtype_data imx8ulp_data = {
 	.quirks = 0,
 	.lut_num = 16,
 	.little_endian = true,  /* little-endian    */
+	/*
+	 * IMX8ULPCEC §7.3.1, Normal Drive (ND, 1.0V) mode:
+	 * SDR RXCLKSRC=0 max 60MHz, DDR RXCLKSRC=3 max 166MHz.
+	 */
+	.max_sdr_rate = 60000000,
+	.max_dtr_rate = 166000000,
+};
+
+static struct nxp_fspi_devtype_data imx95_data = {
+	.rxfifo = SZ_512,       /* (64  * 64 bits)  */
+	.txfifo = SZ_1K,        /* (128 * 64 bits)  */
+	.ahb_buf_size = SZ_2K,  /* (256 * 64 bits)  */
+	.quirks = 0,
+	.lut_num = 32,
+	.little_endian = true,  /* little-endian    */
+	/*
+	 * IMX95CEC Rev.8 §4.11.7: SDR RXCLKSRC=0 max 66MHz,
+	 * DDR RXCLKSRC=3 max 200MHz (Nominal/Overdrive mode).
+	 */
+	.max_sdr_rate = 66000000,
+	.max_dtr_rate = 200000000,
 };
 
 struct nxp_fspi {
@@ -691,10 +755,20 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
 	reg = fspi_readl(f, f->iobase + FSPI_MCR0);
 	if (op_is_dtr) {
 		reg |= FSPI_MCR0_RXCLKSRC(3);
-		f->max_rate = 166000000;
+		/*
+		 * Use the SoC-specific DTR max rate if provided, otherwise
+		 * fall back to 166MHz (limit from IMX8MN datasheet §3.9.9).
+		 */
+		f->max_rate = f->devtype_data->max_dtr_rate ?
+			      f->devtype_data->max_dtr_rate : 166000000;
 	} else {	/*select mode 0 */
 		reg &= ~FSPI_MCR0_RXCLKSRC(3);
-		f->max_rate = 66000000;
+		/*
+		 * Use the SoC-specific SDR max rate if provided, otherwise
+		 * fall back to 66MHz (limit from IMX8MN datasheet §3.9.9).
+		 */
+		f->max_rate = f->devtype_data->max_sdr_rate ?
+			      f->devtype_data->max_sdr_rate : 66000000;
 	}
 	fspi_writel(f, reg, f->iobase + FSPI_MCR0);
 }
@@ -1457,10 +1531,11 @@ static const struct dev_pm_ops nxp_fspi_pm_ops = {
 static const struct of_device_id nxp_fspi_dt_ids[] = {
 	{ .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
 	{ .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, },
-	{ .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mm_data, },
+	{ .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mp_data, },
 	{ .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, },
 	{ .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, },
 	{ .compatible = "nxp,imx8ulp-fspi", .data = (void *)&imx8ulp_data, },
+	{ .compatible = "nxp,imx95-fspi",   .data = (void *)&imx95_data, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);

---
base-commit: c5e32e86ca02b003f86e095d379b38148999293d
change-id: 20260727-fspi-clock-adcae0c35283

Best regards,
-- 
Haibo Chen <haibo.chen@nxp.com>


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs
  2026-07-27  9:08 [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs haibo.chen
@ 2026-07-27  9:16 ` sashiko-bot
  2026-07-27 14:59 ` Frank Li
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-07-27  9:16 UTC (permalink / raw)
  To: haibo.chen; +Cc: imx, Frank.Li

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] Missing clock re-enable on error path in `nxp_fspi_select_mem` leads to synchronous aborts.
- [High] FlexSPI `MCR0` register is modified while the module is enabled.
- [High] Flawed detection of DTR mode for operations missing optional phases (e.g., commands with no data).
--

--- Patch [1]: [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs ---
commit 45fd7def019be2b4fb5ec79c57cfe9cfd93dcfb4
Author: Haibo Chen <haibo.chen@nxp.com>

spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs

This patch introduces per-SoC clock rate limits for both SDR and DTR modes
by adding max_sdr_rate and max_dtr_rate to nxp_fspi_devtype_data. It updates
nxp_fspi_select_rx_sample_clk_source() to use these SoC-specific limits instead
of a global 166MHz cap.

> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index d94a2a7b98d44..1159f5fc8a3a6 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c

[ ... ]

> @@ -691,10 +755,20 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
>  	reg = fspi_readl(f, f->iobase + FSPI_MCR0);
>  	if (op_is_dtr) {
>  		reg |= FSPI_MCR0_RXCLKSRC(3);

[Severity: High]
This is a pre-existing issue, but modifying the FlexSPI MCR0 register while
the module is enabled can lead to unpredictable IP behavior. 

Does this code need to assert the MDIS bit (disable the module) before
modifying MCR0, as hardware state machines might ignore register writes or
corrupt their internal state if changed on the fly?

> -		f->max_rate = 166000000;
> +		/*
> +		 * Use the SoC-specific DTR max rate if provided, otherwise
> +		 * fall back to 166MHz (limit from IMX8MN datasheet §3.9.9).
> +		 */
> +		f->max_rate = f->devtype_data->max_dtr_rate ?
> +			      f->devtype_data->max_dtr_rate : 166000000;
>  	} else {	/*select mode 0 */

[ ... ]


While reviewing this patch, I noticed a couple of other pre-existing issues
in nxp_fspi_select_mem() within the same file:

drivers/spi/spi-nxp-fspi.c:nxp_fspi_select_mem() {
    ...
	/* 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;
    ...
}

[Severity: High]
This is a pre-existing issue, but does this boolean check strictly require
all four phases to have the DTR flag set?

For an 8D-8D-8D command missing an optional phase (e.g., Read Status Register
missing an address phase), spi-mem sets nbytes=0 and dtr=0 for that phase.
This would evaluate to false, causing valid DTR operations to fall back to
SDR sample clock and half the target frequency.

drivers/spi/spi-nxp-fspi.c:nxp_fspi_select_mem() {
    ...
	nxp_fspi_clk_disable_unprep(f);

	ret = clk_set_rate(f->clk, rate);
	if (ret)
		return;

	ret = nxp_fspi_clk_prep_enable(f);
	if (ret)
		return;
    ...
}

[Severity: High]
This is a pre-existing issue, but does this code leave the FlexSPI clock
disabled on the error path?

If clk_set_rate() or nxp_fspi_clk_prep_enable() fails, the function returns
early without restoring the clock.

Since it returns void, the caller is unaware of the failure and might
immediately access hardware registers, which could lead to synchronous
external aborts.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260727-fspi-clock-v1-1-f4f3be6c366d@nxp.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs
  2026-07-27  9:08 [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs haibo.chen
  2026-07-27  9:16 ` sashiko-bot
@ 2026-07-27 14:59 ` Frank Li
  1 sibling, 0 replies; 3+ messages in thread
From: Frank Li @ 2026-07-27 14:59 UTC (permalink / raw)
  To: haibo.chen
  Cc: Han Xu, Yogesh Gaur, Mark Brown, linux-spi, imx, linux-kernel,
	Haibo Chen

On Mon, Jul 27, 2026 at 05:08:47PM +0800, haibo.chen@oss.nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
>
> The commit f43579ef3500 ("spi: spi-nxp-fspi: limit the clock rate for
> different sample clock source selection") introduced a global 166MHz
> cap for DTR mode (RXCLKSRC=3), based on the i.MX8MN datasheet timing
> specification (Section 3.9.9, page 65).
>
> After reviewing the FlexSPI timing parameters in the datasheets for all
> supported SoCs, the following corrections and additions are needed:
>
> 1. SDR mode (RXCLKSRC=0) limits vary per SoC:
>    - i.MX8MN/MM/MP/95: 66MHz  (IMX8MNCEC §3.9.9, IMX8MMCEC §3.9.10,
>                                 IMX8MPCEC, IMX95CEC Rev.8 §4.11.7)
>    - i.MX8QXP/QM/DXL/ULP: 60MHz (IMX8QXPCEC, IMX8QMCEC, IMX8DXLCEC,
>                                    IMX8ULPCEC §7.3.1 ND mode)
>    - LX2160A: 100MHz            (LX2160ACEC FlexSPI timing parameters)
>
> 2. DTR mode (RXCLKSRC=3) limits vary per SoC:
>    - i.MX8MN/MM/MP/ULP: 166MHz
>    - i.MX8QXP/QM/DXL: 200MHz   (same FlexSPI IP across this family)
>    - i.MX95: 200MHz             (IMX95CEC §4.11.7.3.2.3 Table 106)
>    - LX2160A: DTR disabled      (FSPI_QUIRK_DISABLE_DTR)
>
> - Add max_sdr_rate and max_dtr_rate field to nxp_fspi_devtype_data
> - Use per-SoC max_sdr_rate in nxp_fspi_select_rx_sample_clk_source(),
>   falling back to 66MHz default when zero (preserves existing behavior
>   for any future SoC entries that omit the field)
> - Use per-SoC max_ddr_rate in nxp_fspi_select_rx_sample_clk_source(),
>   falling back to 166MHz default when zero (preserves existing behavior
>   for any future SoC entries that omit the field)
> - Add dedicated imx8mp_data (previously aliased to imx8mm_data) with
>   explicit frequency limits
> - Update imx8qxp_data, imx8dxl_data with correct 60/200MHz limits
> - Update imx8ulp_data with ND (Normal Drive, 1.0V) mode limits: 60/166MHz
> - Update lx2160a_data with correct SDR 100MHz limit
> - Update imx95_data with correct 66/200MHz limits

Update related platform data with correct speed limation according to
datasheet.

You already list frequency at above 1/2, needn't duplicate these informaiton
again.

> Note: i.MX8ULP limits are specified for Normal Drive (ND, 1.0V) mode
> as this is the standard operating condition. Overdrive (OD, 1.05V)
> allows up to 180MHz DTR but is not the default use case.

Move this to comments.

Frank
>
> Fixes: f43579ef3500 ("spi: spi-nxp-fspi: limit the clock rate for different sample clock source selection")
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
>  drivers/spi/spi-nxp-fspi.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 78 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index d94a2a7b98d44db217ba96a8ce7df23e37a08ba4..1159f5fc8a3a69eb464f32fd92e283e84ebd67ab 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -340,6 +340,18 @@ struct nxp_fspi_devtype_data {
>  	unsigned int quirks;
>  	unsigned int lut_num;
>  	bool little_endian;
> +	/*
> +	 * The max clock rate (Hz) that FlexSPI can output to the device
> +	 * in SDR mode (RXCLKSRC=0). Defaults to 66MHz if zero.
> +	 * Some SoCs (e.g. LX2160A) support up to 100MHz in SDR mode.
> +	 */
> +	unsigned long max_sdr_rate;
> +	/*
> +	 * The max clock rate (Hz) that FlexSPI can output to the device
> +	 * in DTR mode (RXCLKSRC=3). Defaults to 166MHz if zero.
> +	 * Some SoCs (e.g. i.MX95, i.MX8QM, i.MX8DXL) support up to 200MHz.
> +	 */
> +	unsigned long max_dtr_rate;
>  };
>
>  static struct nxp_fspi_devtype_data lx2160a_data = {
> @@ -349,6 +361,10 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
>  	.quirks = FSPI_QUIRK_DISABLE_DTR,
>  	.lut_num = 32,
>  	.little_endian = true,  /* little-endian    */
> +	/*
> +	 * LX2160ACEC: SDR RXCLKSRC=0 max 100MHz, DTR disabled via quirk.
> +	 */
> +	.max_sdr_rate = 100000000,
>  };
>
>  static struct nxp_fspi_devtype_data imx8mm_data = {
> @@ -358,6 +374,21 @@ static struct nxp_fspi_devtype_data imx8mm_data = {
>  	.quirks = 0,
>  	.lut_num = 32,
>  	.little_endian = true,  /* little-endian    */
> +	/* IMX8MMCEC §3.9.10: SDR RXCLKSRC=0 max 66MHz, DDR RXCLKSRC=3 max 166MHz */
> +	.max_sdr_rate = 66000000,
> +	.max_dtr_rate = 166000000,
> +};
> +
> +static struct nxp_fspi_devtype_data imx8mp_data = {
> +	.rxfifo = SZ_512,       /* (64  * 64 bits)  */
> +	.txfifo = SZ_1K,        /* (128 * 64 bits)  */
> +	.ahb_buf_size = SZ_2K,  /* (256 * 64 bits)  */
> +	.quirks = 0,
> +	.lut_num = 32,
> +	.little_endian = true,  /* little-endian    */
> +	/* IMX8MPCEC: SDR RXCLKSRC=0 max 66MHz, DDR RXCLKSRC=3 max 166MHz */
> +	.max_sdr_rate = 66000000,
> +	.max_dtr_rate = 166000000,
>  };
>
>  static struct nxp_fspi_devtype_data imx8qxp_data = {
> @@ -367,6 +398,12 @@ static struct nxp_fspi_devtype_data imx8qxp_data = {
>  	.quirks = 0,
>  	.lut_num = 32,
>  	.little_endian = true,  /* little-endian    */
> +	/*
> +	 * IMX8QXPCEC: SDR RXCLKSRC=0 max 60MHz, DDR RXCLKSRC=3 max 200MHz.
> +	 * i.MX8QM and i.MX8DXL share the same FlexSPI IP and limits.
> +	 */
> +	.max_sdr_rate = 60000000,
> +	.max_dtr_rate = 200000000,
>  };
>
>  static struct nxp_fspi_devtype_data imx8dxl_data = {
> @@ -376,6 +413,12 @@ static struct nxp_fspi_devtype_data imx8dxl_data = {
>  	.quirks = FSPI_QUIRK_USE_IP_ONLY,
>  	.lut_num = 32,
>  	.little_endian = true,  /* little-endian    */
> +	/*
> +	 * IMX8DXLCEC (i.MX 8XLite): SDR RXCLKSRC=0 max 60MHz,
> +	 * DDR RXCLKSRC=3 max 200MHz.
> +	 */
> +	.max_sdr_rate = 60000000,
> +	.max_dtr_rate = 200000000,
>  };
>
>  static struct nxp_fspi_devtype_data imx8ulp_data = {
> @@ -385,6 +428,27 @@ static struct nxp_fspi_devtype_data imx8ulp_data = {
>  	.quirks = 0,
>  	.lut_num = 16,
>  	.little_endian = true,  /* little-endian    */
> +	/*
> +	 * IMX8ULPCEC §7.3.1, Normal Drive (ND, 1.0V) mode:
> +	 * SDR RXCLKSRC=0 max 60MHz, DDR RXCLKSRC=3 max 166MHz.
> +	 */
> +	.max_sdr_rate = 60000000,
> +	.max_dtr_rate = 166000000,
> +};
> +
> +static struct nxp_fspi_devtype_data imx95_data = {
> +	.rxfifo = SZ_512,       /* (64  * 64 bits)  */
> +	.txfifo = SZ_1K,        /* (128 * 64 bits)  */
> +	.ahb_buf_size = SZ_2K,  /* (256 * 64 bits)  */
> +	.quirks = 0,
> +	.lut_num = 32,
> +	.little_endian = true,  /* little-endian    */
> +	/*
> +	 * IMX95CEC Rev.8 §4.11.7: SDR RXCLKSRC=0 max 66MHz,
> +	 * DDR RXCLKSRC=3 max 200MHz (Nominal/Overdrive mode).
> +	 */
> +	.max_sdr_rate = 66000000,
> +	.max_dtr_rate = 200000000,
>  };
>
>  struct nxp_fspi {
> @@ -691,10 +755,20 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
>  	reg = fspi_readl(f, f->iobase + FSPI_MCR0);
>  	if (op_is_dtr) {
>  		reg |= FSPI_MCR0_RXCLKSRC(3);
> -		f->max_rate = 166000000;
> +		/*
> +		 * Use the SoC-specific DTR max rate if provided, otherwise
> +		 * fall back to 166MHz (limit from IMX8MN datasheet §3.9.9).
> +		 */
> +		f->max_rate = f->devtype_data->max_dtr_rate ?
> +			      f->devtype_data->max_dtr_rate : 166000000;
>  	} else {	/*select mode 0 */
>  		reg &= ~FSPI_MCR0_RXCLKSRC(3);
> -		f->max_rate = 66000000;
> +		/*
> +		 * Use the SoC-specific SDR max rate if provided, otherwise
> +		 * fall back to 66MHz (limit from IMX8MN datasheet §3.9.9).
> +		 */
> +		f->max_rate = f->devtype_data->max_sdr_rate ?
> +			      f->devtype_data->max_sdr_rate : 66000000;
>  	}
>  	fspi_writel(f, reg, f->iobase + FSPI_MCR0);
>  }
> @@ -1457,10 +1531,11 @@ static const struct dev_pm_ops nxp_fspi_pm_ops = {
>  static const struct of_device_id nxp_fspi_dt_ids[] = {
>  	{ .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
>  	{ .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, },
> -	{ .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mm_data, },
> +	{ .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mp_data, },
>  	{ .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, },
>  	{ .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, },
>  	{ .compatible = "nxp,imx8ulp-fspi", .data = (void *)&imx8ulp_data, },
> +	{ .compatible = "nxp,imx95-fspi",   .data = (void *)&imx95_data, },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);
>
> ---
> base-commit: c5e32e86ca02b003f86e095d379b38148999293d
> change-id: 20260727-fspi-clock-adcae0c35283
>
> Best regards,
> --
> Haibo Chen <haibo.chen@nxp.com>
>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-27 14:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27  9:08 [PATCH] spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs haibo.chen
2026-07-27  9:16 ` sashiko-bot
2026-07-27 14:59 ` Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox