diff options
-rw-r--r-- | drivers/spi/nxp_fspi.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c index 7715ed9110..b7c922b1df 100644 --- a/drivers/spi/nxp_fspi.c +++ b/drivers/spi/nxp_fspi.c @@ -41,6 +41,11 @@ #include <spi.h> #include <spi-mem.h> #include <asm/io.h> +#ifdef CONFIG_FSL_LAYERSCAPE +#include <asm/arch/clock.h> +#include <asm/arch/soc.h> +#include <asm/arch/speed.h> +#endif #include <linux/bitops.h> #include <linux/kernel.h> #include <linux/sizes.h> @@ -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, |