mirror of
https://github.com/torvalds/linux.git
synced 2026-05-05 23:05:25 -04:00
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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user