diff mbox series

[04/11] spi: spi-nxp-fspi: add function to select sample clock source for flash reading

Message ID 1657012303-6464-4-git-send-email-haibo.chen@nxp.com (mailing list archive)
State New, archived
Headers show
Series [01/11] spi: spi-nxp-fspi: enable runtime pm for fspi | expand

Commit Message

Bough Chen July 5, 2022, 9:11 a.m. UTC
From: Haibo Chen <haibo.chen@nxp.com>

fspi 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, fspi use mode 0 after reset.
For 8-8-8-DTR mode, need to use mode 3, otherwise 8-8-8-DTR read always
get incorrect data.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/spi/spi-nxp-fspi.c | 47 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

Comments

Michael Walle July 6, 2022, 9:02 p.m. UTC | #1
Am 2022-07-05 11:11, schrieb haibo.chen@nxp.com:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> fspi 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, fspi use mode 0 after reset.
> For 8-8-8-DTR mode, need to use mode 3, otherwise 8-8-8-DTR read always
> get incorrect data.
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
>  drivers/spi/spi-nxp-fspi.c | 47 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
> 
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index c32a4f53fa2a..34679dc0e1ad 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -380,6 +380,7 @@ struct nxp_fspi {
>  	struct pm_qos_request pm_qos_req;
>  	int selected;
>  #define FSPI_INITILIZED		(1 << 0)
> +#define FSPI_RXCLKSRC_3		(1 << 1)
>  	int flags;
>  };
> 
> @@ -877,6 +878,50 @@ static int nxp_fspi_do_op(struct nxp_fspi *f,
> const struct spi_mem_op *op)
>  	return err;
>  }
> 
> +/*
> + * 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,
> +						 const struct spi_mem_op *op)
> +{
> +	u32 reg;
> +
> +	/*
> +	 * For 8-8-8-DTR 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 8-8-8-DTR mode, also need to
> +	 * change the mode back to mode 0.
> +	 */
> +	if (!(f->flags & FSPI_RXCLKSRC_3) &&
> +			op->cmd.dtr && op->addr.dtr &&
> +			op->dummy.dtr && op->data.dtr) {
> +		reg = fspi_readl(f, f->iobase + FSPI_MCR0);
> +		reg |= FSPI_MCR0_RXCLKSRC(3);
> +		fspi_writel(f, reg, f->iobase + FSPI_MCR0);
> +		f->flags |= FSPI_RXCLKSRC_3;
> +	} else if ((f->flags & FSPI_RXCLKSRC_3) &&
> +			!op->cmd.dtr && !op->addr.dtr &&
> +			!op->dummy.dtr && !op->data.dtr) {
> +		reg = fspi_readl(f, f->iobase + FSPI_MCR0);
> +		reg &= ~FSPI_MCR0_RXCLKSRC(3);	/* select mode 0 */
> +		fspi_writel(f, reg, f->iobase + FSPI_MCR0);
> +		f->flags &= ~FSPI_RXCLKSRC_3;
> +	}

How is this supposed to work? Are you unconditionally enable
flash provided read strobes if DTR is used? What if the
flash doesn't provide one or the board haven't DQS connected?

-michael
diff mbox series

Patch

diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index c32a4f53fa2a..34679dc0e1ad 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -380,6 +380,7 @@  struct nxp_fspi {
 	struct pm_qos_request pm_qos_req;
 	int selected;
 #define FSPI_INITILIZED		(1 << 0)
+#define FSPI_RXCLKSRC_3		(1 << 1)
 	int flags;
 };
 
@@ -877,6 +878,50 @@  static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op)
 	return err;
 }
 
+/*
+ * 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,
+						 const struct spi_mem_op *op)
+{
+	u32 reg;
+
+	/*
+	 * For 8-8-8-DTR 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 8-8-8-DTR mode, also need to
+	 * change the mode back to mode 0.
+	 */
+	if (!(f->flags & FSPI_RXCLKSRC_3) &&
+			op->cmd.dtr && op->addr.dtr &&
+			op->dummy.dtr && op->data.dtr) {
+		reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+		reg |= FSPI_MCR0_RXCLKSRC(3);
+		fspi_writel(f, reg, f->iobase + FSPI_MCR0);
+		f->flags |= FSPI_RXCLKSRC_3;
+	} else if ((f->flags & FSPI_RXCLKSRC_3) &&
+			!op->cmd.dtr && !op->addr.dtr &&
+			!op->dummy.dtr && !op->data.dtr) {
+		reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+		reg &= ~FSPI_MCR0_RXCLKSRC(3);	/* select mode 0 */
+		fspi_writel(f, reg, f->iobase + FSPI_MCR0);
+		f->flags &= ~FSPI_RXCLKSRC_3;
+	}
+
+}
+
 static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
 {
 	struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
@@ -897,6 +942,8 @@  static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
 
 	nxp_fspi_select_mem(f, mem->spi);
 
+	nxp_fspi_select_rx_sample_clk_source(f, op);
+
 	nxp_fspi_prepare_lut(f, op);
 	/*
 	 * If we have large chunks of data, we read them through the AHB bus by