Unverified Commit 99d822b3 authored by Haibo Chen's avatar Haibo Chen Committed by Mark Brown
Browse files

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: default avatarHaibo Chen <haibo.chen@nxp.com>
Link: https://lore.kernel.org/r/20230322090451.3179431-2-haibo.chen@nxp.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 1ab09f1d
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -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);
}