diff mbox series

[2/2] spi: spi-nxp-fspi: use DLL calibration when clock rate > 100MHz

Message ID 20230322090451.3179431-2-haibo.chen@nxp.com
State Accepted
Commit 99d822b3adc4f9af59cefdc6619cb3f64182efed
Headers show
Series [1/2] spi: spi-nxp-fspi: correct the comment for the DLL config | expand

Commit Message

Bough Chen March 22, 2023, 9:04 a.m. UTC
From: Haibo Chen <haibo.chen@nxp.com>

When clock rate > 100MHz, use the DLL calibration mode, and finally
add the suggested half of the current clock cycle to sample the data.

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

Comments

Han Xu March 23, 2023, 1:52 a.m. UTC | #1
On 23/03/22 05:04PM, haibo.chen@nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> When clock rate > 100MHz, use the DLL calibration mode, and finally
> add the suggested half of the current clock cycle to sample the data.
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>

Reviewed-by: Han Xu <han.xu@nxp.com>
Tested-by: Han Xu <han.xu@nxp.com>

> ---
>  drivers/spi/spi-nxp-fspi.c | 52 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
> index 6735c22b9137..544017655787 100644
> --- a/drivers/spi/spi-nxp-fspi.c
> +++ b/drivers/spi/spi-nxp-fspi.c
> @@ -214,9 +214,15 @@
>  
>  #define FSPI_DLLACR			0xC0
>  #define FSPI_DLLACR_OVRDEN		BIT(8)
> +#define FSPI_DLLACR_SLVDLY(x)		((x) << 3)
> +#define FSPI_DLLACR_DLLRESET		BIT(1)
> +#define FSPI_DLLACR_DLLEN		BIT(0)
>  
>  #define FSPI_DLLBCR			0xC4
>  #define FSPI_DLLBCR_OVRDEN		BIT(8)
> +#define FSPI_DLLBCR_SLVDLY(x)		((x) << 3)
> +#define FSPI_DLLBCR_DLLRESET		BIT(1)
> +#define FSPI_DLLBCR_DLLEN		BIT(0)
>  
>  #define FSPI_STS0			0xE0
>  #define FSPI_STS0_DLPHB(x)		((x) << 8)
> @@ -231,6 +237,16 @@
>  #define FSPI_STS1_AHB_ERRCD(x)		((x) << 8)
>  #define FSPI_STS1_AHB_ERRID(x)		(x)
>  
> +#define FSPI_STS2			0xE8
> +#define FSPI_STS2_BREFLOCK		BIT(17)
> +#define FSPI_STS2_BSLVLOCK		BIT(16)
> +#define FSPI_STS2_AREFLOCK		BIT(1)
> +#define FSPI_STS2_ASLVLOCK		BIT(0)
> +#define FSPI_STS2_AB_LOCK		(FSPI_STS2_BREFLOCK | \
> +					 FSPI_STS2_BSLVLOCK | \
> +					 FSPI_STS2_AREFLOCK | \
> +					 FSPI_STS2_ASLVLOCK)
> +
>  #define FSPI_AHBSPNST			0xEC
>  #define FSPI_AHBSPNST_DATLFT(x)		((x) << 16)
>  #define FSPI_AHBSPNST_BUFID(x)		((x) << 1)
> @@ -615,6 +631,35 @@ static int nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
>  	return 0;
>  }
>  
> +static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
> +{
> +	int ret;
> +
> +	/* Reset the DLL, set the DLLRESET to 1 and then set to 0 */
> +	fspi_writel(f, FSPI_DLLACR_DLLRESET, f->iobase + FSPI_DLLACR);
> +	fspi_writel(f, FSPI_DLLBCR_DLLRESET, f->iobase + FSPI_DLLBCR);
> +	fspi_writel(f, 0, f->iobase + FSPI_DLLACR);
> +	fspi_writel(f, 0, f->iobase + FSPI_DLLBCR);
> +
> +	/*
> +	 * Enable the DLL calibration mode.
> +	 * The delay target for slave delay line is:
> +	 *   ((SLVDLYTARGET+1) * 1/32 * clock cycle of reference clock.
> +	 * When clock rate > 100MHz, recommend SLVDLYTARGET is 0xF, which
> +	 * means half of clock cycle of reference clock.
> +	 */
> +	fspi_writel(f, FSPI_DLLACR_DLLEN | FSPI_DLLACR_SLVDLY(0xF),
> +		    f->iobase + FSPI_DLLACR);
> +	fspi_writel(f, FSPI_DLLBCR_DLLEN | FSPI_DLLBCR_SLVDLY(0xF),
> +		    f->iobase + FSPI_DLLBCR);
> +
> +	/* Wait to get REF/SLV lock */
> +	ret = fspi_readl_poll_tout(f, f->iobase + FSPI_STS2, FSPI_STS2_AB_LOCK,
> +				   0, POLL_TOUT, true);
> +	if (ret)
> +		dev_warn(f->dev, "DLL lock failed, please fix it!\n");
> +}
> +
>  /*
>   * In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
>   * register and start base address of the slave device.
> @@ -690,6 +735,13 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi)
>  	if (ret)
>  		return;
>  
> +	/*
> +	 * If clock rate > 100MHz, then switch from DLL override mode to
> +	 * DLL calibration mode.
> +	 */
> +	if (rate > 100000000)
> +		nxp_fspi_dll_calibration(f);
> +
>  	f->selected = spi_get_chipselect(spi, 0);
>  }
>  
> -- 
> 2.34.1
>
diff mbox series

Patch

diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 6735c22b9137..544017655787 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -214,9 +214,15 @@ 
 
 #define FSPI_DLLACR			0xC0
 #define FSPI_DLLACR_OVRDEN		BIT(8)
+#define FSPI_DLLACR_SLVDLY(x)		((x) << 3)
+#define FSPI_DLLACR_DLLRESET		BIT(1)
+#define FSPI_DLLACR_DLLEN		BIT(0)
 
 #define FSPI_DLLBCR			0xC4
 #define FSPI_DLLBCR_OVRDEN		BIT(8)
+#define FSPI_DLLBCR_SLVDLY(x)		((x) << 3)
+#define FSPI_DLLBCR_DLLRESET		BIT(1)
+#define FSPI_DLLBCR_DLLEN		BIT(0)
 
 #define FSPI_STS0			0xE0
 #define FSPI_STS0_DLPHB(x)		((x) << 8)
@@ -231,6 +237,16 @@ 
 #define FSPI_STS1_AHB_ERRCD(x)		((x) << 8)
 #define FSPI_STS1_AHB_ERRID(x)		(x)
 
+#define FSPI_STS2			0xE8
+#define FSPI_STS2_BREFLOCK		BIT(17)
+#define FSPI_STS2_BSLVLOCK		BIT(16)
+#define FSPI_STS2_AREFLOCK		BIT(1)
+#define FSPI_STS2_ASLVLOCK		BIT(0)
+#define FSPI_STS2_AB_LOCK		(FSPI_STS2_BREFLOCK | \
+					 FSPI_STS2_BSLVLOCK | \
+					 FSPI_STS2_AREFLOCK | \
+					 FSPI_STS2_ASLVLOCK)
+
 #define FSPI_AHBSPNST			0xEC
 #define FSPI_AHBSPNST_DATLFT(x)		((x) << 16)
 #define FSPI_AHBSPNST_BUFID(x)		((x) << 1)
@@ -615,6 +631,35 @@  static int nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
 	return 0;
 }
 
+static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
+{
+	int ret;
+
+	/* Reset the DLL, set the DLLRESET to 1 and then set to 0 */
+	fspi_writel(f, FSPI_DLLACR_DLLRESET, f->iobase + FSPI_DLLACR);
+	fspi_writel(f, FSPI_DLLBCR_DLLRESET, f->iobase + FSPI_DLLBCR);
+	fspi_writel(f, 0, f->iobase + FSPI_DLLACR);
+	fspi_writel(f, 0, f->iobase + FSPI_DLLBCR);
+
+	/*
+	 * Enable the DLL calibration mode.
+	 * The delay target for slave delay line is:
+	 *   ((SLVDLYTARGET+1) * 1/32 * clock cycle of reference clock.
+	 * When clock rate > 100MHz, recommend SLVDLYTARGET is 0xF, which
+	 * means half of clock cycle of reference clock.
+	 */
+	fspi_writel(f, FSPI_DLLACR_DLLEN | FSPI_DLLACR_SLVDLY(0xF),
+		    f->iobase + FSPI_DLLACR);
+	fspi_writel(f, FSPI_DLLBCR_DLLEN | FSPI_DLLBCR_SLVDLY(0xF),
+		    f->iobase + FSPI_DLLBCR);
+
+	/* Wait to get REF/SLV lock */
+	ret = fspi_readl_poll_tout(f, f->iobase + FSPI_STS2, FSPI_STS2_AB_LOCK,
+				   0, POLL_TOUT, true);
+	if (ret)
+		dev_warn(f->dev, "DLL lock failed, please fix it!\n");
+}
+
 /*
  * In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
  * register and start base address of the slave device.
@@ -690,6 +735,13 @@  static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi)
 	if (ret)
 		return;
 
+	/*
+	 * If clock rate > 100MHz, then switch from DLL override mode to
+	 * DLL calibration mode.
+	 */
+	if (rate > 100000000)
+		nxp_fspi_dll_calibration(f);
+
 	f->selected = spi_get_chipselect(spi, 0);
 }