mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
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>
This commit is contained in:
parent
1ab09f1d07
commit
99d822b3ad
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user