On 23/03/22 05:04PM, haibo.chen@xxxxxxx wrote: > From: Haibo Chen <haibo.chen@xxxxxxx> > > 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@xxxxxxx> Reviewed-by: Han Xu <han.xu@xxxxxxx> Tested-by: Han Xu <han.xu@xxxxxxx> > --- > 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 >