From e8751a9387add3fb786828498352103b7188b296 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 3 Aug 2021 14:32:57 +0530 Subject: spi: nxp-fspi: Add support for IP read only Add support for disabling AHB bus and read entire flash contents via IP bus only. Please note, this enables IP bus read using a quirk which can be enabled directly in device-type data or in existence of an errata where AHB bus may need to be disabled. Signed-off-by: Kuldeep Singh Acked-by: Jagan Teki --- drivers/spi/nxp_fspi.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers/spi/nxp_fspi.c') diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c index bba7a330e0c..7715ed91108 100644 --- a/drivers/spi/nxp_fspi.c +++ b/drivers/spi/nxp_fspi.c @@ -304,6 +304,9 @@ #define POLL_TOUT 5000 #define NXP_FSPI_MAX_CHIPSELECT 4 +/* Access flash memory using IP bus only */ +#define FSPI_QUIRK_USE_IP_ONLY BIT(0) + struct nxp_fspi_devtype_data { unsigned int rxfifo; unsigned int txfifo; @@ -338,6 +341,11 @@ struct nxp_fspi { const struct nxp_fspi_devtype_data *devtype_data; }; +static inline int needs_ip_only(struct nxp_fspi *f) +{ + return f->devtype_data->quirks & FSPI_QUIRK_USE_IP_ONLY; +} + /* * R/W functions for big- or little-endian registers: * The FSPI controller's endianness is independent of @@ -769,12 +777,14 @@ static int nxp_fspi_exec_op(struct spi_slave *slave, nxp_fspi_prepare_lut(f, op); /* - * If we have large chunks of data, we read them through the AHB bus - * by accessing the mapped memory. In all other cases we use - * IP commands to access the flash. + * If we have large chunks of data, we read them through the AHB bus by + * accessing the mapped memory. In all other cases we use IP commands + * to access the flash. Read via AHB bus may be corrupted due to + * existence of an errata and therefore discard AHB read in such cases. */ if (op->data.nbytes > (f->devtype_data->rxfifo - 4) && - op->data.dir == SPI_MEM_DATA_IN) { + op->data.dir == SPI_MEM_DATA_IN && + !needs_ip_only(f)) { nxp_fspi_read_ahb(f, op); } else { if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) @@ -808,6 +818,12 @@ static int nxp_fspi_adjust_op_size(struct spi_slave *slave, op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); } + /* Limit data bytes to RX FIFO in case of IP read only */ + if (needs_ip_only(f) && + op->data.dir == SPI_MEM_DATA_IN && + op->data.nbytes > f->devtype_data->rxfifo) + op->data.nbytes = f->devtype_data->rxfifo; + return 0; } -- cgit v1.2.3 From b9cfd8b0911209e2ebec887e497510ee42f9e788 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 3 Aug 2021 14:32:58 +0530 Subject: spi: nxp_fspi: Implement errata workaround for LS1028A Errata ERR050568 description says that "Flash access by FlexSPI AHB command may not work with platform frequency equal to 300 MHz" on LS1028A. By default, smaller length reads(equal to RX FIFO size) are done by IP bus and larger length reads using AHB bus. For adding errata workaround, use IP bus to read entire flash contents and disable AHB path when platform frequency is 300Mhz. Signed-off-by: Kuldeep Singh Reviewed-by: Jagan Teki --- drivers/spi/nxp_fspi.c | 53 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) (limited to 'drivers/spi/nxp_fspi.c') diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c index 7715ed91108..b7c922b1dfd 100644 --- a/drivers/spi/nxp_fspi.c +++ b/drivers/spi/nxp_fspi.c @@ -41,6 +41,11 @@ #include #include #include +#ifdef CONFIG_FSL_LAYERSCAPE +#include +#include +#include +#endif #include #include #include @@ -315,7 +320,7 @@ struct nxp_fspi_devtype_data { bool little_endian; }; -static const struct nxp_fspi_devtype_data lx2160a_data = { +static struct nxp_fspi_devtype_data lx2160a_data = { .rxfifo = SZ_512, /* (64 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ @@ -323,7 +328,7 @@ static const struct nxp_fspi_devtype_data lx2160a_data = { .little_endian = true, /* little-endian */ }; -static const struct nxp_fspi_devtype_data imx8mm_data = { +static struct nxp_fspi_devtype_data imx8mm_data = { .rxfifo = SZ_512, /* (64 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ @@ -338,7 +343,7 @@ struct nxp_fspi { u32 memmap_phy; u32 memmap_phy_size; struct clk clk, clk_en; - const struct nxp_fspi_devtype_data *devtype_data; + struct nxp_fspi_devtype_data *devtype_data; }; static inline int needs_ip_only(struct nxp_fspi *f) @@ -529,8 +534,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, for (i = 0; i < ARRAY_SIZE(lutval); i++) fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); - dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n", - op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]); + dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n", + op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); /* lock LUT */ fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY); @@ -827,6 +832,33 @@ static int nxp_fspi_adjust_op_size(struct spi_slave *slave, return 0; } +#ifdef CONFIG_FSL_LAYERSCAPE +static void erratum_err050568(struct nxp_fspi *f) +{ + struct sys_info sysinfo; + u32 svr = 0, freq = 0; + + /* Check for LS1028A variants */ + svr = SVR_SOC_VER(get_svr()); + if (svr != SVR_LS1017A || + svr != SVR_LS1018A || + svr != SVR_LS1027A || + svr != SVR_LS1028A) { + dev_dbg(f->dev, "Errata applicable only for LS1028A variants\n"); + return; + } + + /* Read PLL frequency */ + get_sys_info(&sysinfo); + freq = sysinfo.freq_systembus / 1000000; /* Convert to MHz */ + dev_dbg(f->dev, "svr: %08x, Frequency: %dMhz\n", svr, freq); + + /* Use IP bus only if PLL is 300MHz */ + if (freq == 300) + f->devtype_data->quirks |= FSPI_QUIRK_USE_IP_ONLY; +} +#endif + static int nxp_fspi_default_setup(struct nxp_fspi *f) { void __iomem *base = f->iobase; @@ -847,6 +879,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) return ret; #endif +#ifdef CONFIG_FSL_LAYERSCAPE + /* + * ERR050568: Flash access by FlexSPI AHB command may not work with + * platform frequency equal to 300 MHz on LS1028A. + * LS1028A reuses LX2160A compatible entry. Make errata applicable for + * Layerscape LS1028A platform family. + */ + if (device_is_compatible(f->dev, "nxp,lx2160a-fspi")) + erratum_err050568(f); +#endif + /* Reset the module */ /* w1c register, wait unit clear */ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0, -- cgit v1.2.3