Unverified Commit 760951dd authored by Mark Brown's avatar Mark Brown
Browse files

spi: spi-nxp-fspi: few fix for flexspi

Merge series from Haibo Chen <haibo.chen@nxp.com>:

PATCH 1: different operations maybe require different max frequency, so
         add flexspi to handle such case, re-config the clock rate when
	 new coming operation require new clock frequency.
Patch 2: add workaround for erratum ERR050272. Since only add 4us dealy
	 in nxp_fspi_dll_calibration(), so do not distinguish different
	 platforms.
Patch 3: add max frequency limitation for different sample clock source
         selection. Datasheet give max 66MHz for mode 0 and 166MHz for
	 mode 3. And IC suggest to add this limitation on all SoCs for
	 safety and stability.
parents 6b6e0310 f43579ef
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -404,6 +404,10 @@ struct nxp_fspi {
#define FSPI_NEED_INIT		BIT(0)
#define FSPI_DTR_MODE		BIT(1)
	int flags;
	/* save the previous operation clock rate */
	unsigned long pre_op_rate;
	/* the max clock rate fspi output to device */
	unsigned long max_rate;
};

static inline int needs_ip_only(struct nxp_fspi *f)
@@ -685,10 +689,13 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
	 * change the mode back to mode 0.
	 */
	reg = fspi_readl(f, f->iobase + FSPI_MCR0);
	if (op_is_dtr)
	if (op_is_dtr) {
		reg |= FSPI_MCR0_RXCLKSRC(3);
	else	/*select mode 0 */
		f->max_rate = 166000000;
	} else {	/*select mode 0 */
		reg &= ~FSPI_MCR0_RXCLKSRC(3);
		f->max_rate = 66000000;
	}
	fspi_writel(f, reg, f->iobase + FSPI_MCR0);
}

@@ -719,6 +726,12 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
				   0, POLL_TOUT, true);
	if (ret)
		dev_warn(f->dev, "DLL lock failed, please fix it!\n");

	/*
	 * For ERR050272, DLL lock status bit is not accurate,
	 * wait for 4us more as a workaround.
	 */
	udelay(4);
}

/*
@@ -780,11 +793,17 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
	uint64_t size_kb;

	/*
	 * Return, if previously selected target device is same as current
	 * requested target device. Also the DTR or STR mode do not change.
	 * Return when following condition all meet,
	 * 1, if previously selected target device is same as current
	 *    requested target device.
	 * 2, the DTR or STR mode do not change.
	 * 3, previous operation max rate equals current one.
	 *
	 * For other case, need to re-config.
	 */
	if ((f->selected == spi_get_chipselect(spi, 0)) &&
	    (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr))
	    (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr) &&
	    (f->pre_op_rate == op->max_freq))
		return;

	/* Reset FLSHxxCR0 registers */
@@ -802,6 +821,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
	dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));

	nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
	rate = min(f->max_rate, op->max_freq);

	if (op_is_dtr) {
		f->flags |= FSPI_DTR_MODE;
@@ -832,6 +852,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
	else
		nxp_fspi_dll_override(f);

	f->pre_op_rate = op->max_freq;

	f->selected = spi_get_chipselect(spi, 0);
}