Skip to content

Commit 99d822b

Browse files
Haibo Chenbroonie
authored andcommitted
spi: spi-nxp-fspi: use DLL calibration when clock rate > 100MHz
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> Link: https://lore.kernel.org/r/20230322090451.3179431-2-haibo.chen@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 1ab09f1 commit 99d822b

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

drivers/spi/spi-nxp-fspi.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,15 @@
214214

215215
#define FSPI_DLLACR 0xC0
216216
#define FSPI_DLLACR_OVRDEN BIT(8)
217+
#define FSPI_DLLACR_SLVDLY(x) ((x) << 3)
218+
#define FSPI_DLLACR_DLLRESET BIT(1)
219+
#define FSPI_DLLACR_DLLEN BIT(0)
217220

218221
#define FSPI_DLLBCR 0xC4
219222
#define FSPI_DLLBCR_OVRDEN BIT(8)
223+
#define FSPI_DLLBCR_SLVDLY(x) ((x) << 3)
224+
#define FSPI_DLLBCR_DLLRESET BIT(1)
225+
#define FSPI_DLLBCR_DLLEN BIT(0)
220226

221227
#define FSPI_STS0 0xE0
222228
#define FSPI_STS0_DLPHB(x) ((x) << 8)
@@ -231,6 +237,16 @@
231237
#define FSPI_STS1_AHB_ERRCD(x) ((x) << 8)
232238
#define FSPI_STS1_AHB_ERRID(x) (x)
233239

240+
#define FSPI_STS2 0xE8
241+
#define FSPI_STS2_BREFLOCK BIT(17)
242+
#define FSPI_STS2_BSLVLOCK BIT(16)
243+
#define FSPI_STS2_AREFLOCK BIT(1)
244+
#define FSPI_STS2_ASLVLOCK BIT(0)
245+
#define FSPI_STS2_AB_LOCK (FSPI_STS2_BREFLOCK | \
246+
FSPI_STS2_BSLVLOCK | \
247+
FSPI_STS2_AREFLOCK | \
248+
FSPI_STS2_ASLVLOCK)
249+
234250
#define FSPI_AHBSPNST 0xEC
235251
#define FSPI_AHBSPNST_DATLFT(x) ((x) << 16)
236252
#define FSPI_AHBSPNST_BUFID(x) ((x) << 1)
@@ -615,6 +631,35 @@ static int nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
615631
return 0;
616632
}
617633

634+
static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
635+
{
636+
int ret;
637+
638+
/* Reset the DLL, set the DLLRESET to 1 and then set to 0 */
639+
fspi_writel(f, FSPI_DLLACR_DLLRESET, f->iobase + FSPI_DLLACR);
640+
fspi_writel(f, FSPI_DLLBCR_DLLRESET, f->iobase + FSPI_DLLBCR);
641+
fspi_writel(f, 0, f->iobase + FSPI_DLLACR);
642+
fspi_writel(f, 0, f->iobase + FSPI_DLLBCR);
643+
644+
/*
645+
* Enable the DLL calibration mode.
646+
* The delay target for slave delay line is:
647+
* ((SLVDLYTARGET+1) * 1/32 * clock cycle of reference clock.
648+
* When clock rate > 100MHz, recommend SLVDLYTARGET is 0xF, which
649+
* means half of clock cycle of reference clock.
650+
*/
651+
fspi_writel(f, FSPI_DLLACR_DLLEN | FSPI_DLLACR_SLVDLY(0xF),
652+
f->iobase + FSPI_DLLACR);
653+
fspi_writel(f, FSPI_DLLBCR_DLLEN | FSPI_DLLBCR_SLVDLY(0xF),
654+
f->iobase + FSPI_DLLBCR);
655+
656+
/* Wait to get REF/SLV lock */
657+
ret = fspi_readl_poll_tout(f, f->iobase + FSPI_STS2, FSPI_STS2_AB_LOCK,
658+
0, POLL_TOUT, true);
659+
if (ret)
660+
dev_warn(f->dev, "DLL lock failed, please fix it!\n");
661+
}
662+
618663
/*
619664
* In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
620665
* 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)
690735
if (ret)
691736
return;
692737

738+
/*
739+
* If clock rate > 100MHz, then switch from DLL override mode to
740+
* DLL calibration mode.
741+
*/
742+
if (rate > 100000000)
743+
nxp_fspi_dll_calibration(f);
744+
693745
f->selected = spi_get_chipselect(spi, 0);
694746
}
695747

0 commit comments

Comments
 (0)