Commit 82ce7d0e authored by Kuldeep Singh's avatar Kuldeep Singh Committed by Mark Brown

spi: 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: default avatarKuldeep Singh <kuldeep.singh@nxp.com>
Link: https://lore.kernel.org/r/20210302124936.1972546-5-kuldeep.singh@nxp.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent c791e3c3
...@@ -49,8 +49,11 @@ ...@@ -49,8 +49,11 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/regmap.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/sys_soc.h>
#include <linux/mfd/syscon.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h> #include <linux/spi/spi-mem.h>
...@@ -311,6 +314,8 @@ ...@@ -311,6 +314,8 @@
#define NXP_FSPI_MAX_CHIPSELECT 4 #define NXP_FSPI_MAX_CHIPSELECT 4
#define NXP_FSPI_MIN_IOMAP SZ_4M #define NXP_FSPI_MIN_IOMAP SZ_4M
#define DCFG_RCWSR1 0x100
/* Access flash memory using IP bus only */ /* Access flash memory using IP bus only */
#define FSPI_QUIRK_USE_IP_ONLY BIT(0) #define FSPI_QUIRK_USE_IP_ONLY BIT(0)
...@@ -322,7 +327,7 @@ struct nxp_fspi_devtype_data { ...@@ -322,7 +327,7 @@ struct nxp_fspi_devtype_data {
bool little_endian; 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) */ .rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
...@@ -330,7 +335,7 @@ static const struct nxp_fspi_devtype_data lx2160a_data = { ...@@ -330,7 +335,7 @@ static const struct nxp_fspi_devtype_data lx2160a_data = {
.little_endian = true, /* little-endian */ .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) */ .rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
...@@ -338,7 +343,7 @@ static const struct nxp_fspi_devtype_data imx8mm_data = { ...@@ -338,7 +343,7 @@ static const struct nxp_fspi_devtype_data imx8mm_data = {
.little_endian = true, /* little-endian */ .little_endian = true, /* little-endian */
}; };
static const struct nxp_fspi_devtype_data imx8qxp_data = { static struct nxp_fspi_devtype_data imx8qxp_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */ .rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
...@@ -346,7 +351,7 @@ static const struct nxp_fspi_devtype_data imx8qxp_data = { ...@@ -346,7 +351,7 @@ static const struct nxp_fspi_devtype_data imx8qxp_data = {
.little_endian = true, /* little-endian */ .little_endian = true, /* little-endian */
}; };
static const struct nxp_fspi_devtype_data imx8dxl_data = { static struct nxp_fspi_devtype_data imx8dxl_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */ .rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
...@@ -364,7 +369,7 @@ struct nxp_fspi { ...@@ -364,7 +369,7 @@ struct nxp_fspi {
struct clk *clk, *clk_en; struct clk *clk, *clk_en;
struct device *dev; struct device *dev;
struct completion c; struct completion c;
const struct nxp_fspi_devtype_data *devtype_data; struct nxp_fspi_devtype_data *devtype_data;
struct mutex lock; struct mutex lock;
struct pm_qos_request pm_qos_req; struct pm_qos_request pm_qos_req;
int selected; int selected;
...@@ -915,6 +920,59 @@ static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) ...@@ -915,6 +920,59 @@ static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
return 0; return 0;
} }
static void erratum_err050568(struct nxp_fspi *f)
{
const struct soc_device_attribute ls1028a_soc_attr[] = {
{ .family = "QorIQ LS1028A" },
{ /* sentinel */ }
};
struct device_node *np;
struct regmap *map;
u32 val = 0, sysclk = 0;
int ret;
/* Check for LS1028A family */
if (!soc_device_match(ls1028a_soc_attr)) {
dev_dbg(f->dev, "Errata applicable only for LS1028A\n");
return;
}
/* Compute system clock frequency multiplier ratio */
map = syscon_regmap_lookup_by_compatible("fsl,ls1028a-dcfg");
if (IS_ERR(map)) {
dev_err(f->dev, "No syscon regmap\n");
goto err;
}
ret = regmap_read(map, DCFG_RCWSR1, &val);
if (ret < 0)
goto err;
/* Strap bits 6:2 define SYS_PLL_RAT i.e frequency multiplier ratio */
val = (val >> 2) & 0x1F;
WARN(val == 0, "Strapping is zero: Cannot determine ratio");
/* Compute system clock frequency */
np = of_find_node_by_name(NULL, "clock-sysclk");
if (!np)
goto err;
if (of_property_read_u32(np, "clock-frequency", &sysclk))
goto err;
sysclk = (sysclk * val) / 1000000; /* Convert sysclk to Mhz */
dev_dbg(f->dev, "val: 0x%08x, sysclk: %dMhz\n", val, sysclk);
/* Use IP bus only if PLL is 300MHz */
if (sysclk == 300)
f->devtype_data->quirks |= FSPI_QUIRK_USE_IP_ONLY;
return;
err:
dev_err(f->dev, "Errata cannot be executed. Read via IP bus may not work\n");
}
static int nxp_fspi_default_setup(struct nxp_fspi *f) static int nxp_fspi_default_setup(struct nxp_fspi *f)
{ {
void __iomem *base = f->iobase; void __iomem *base = f->iobase;
...@@ -933,6 +991,15 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) ...@@ -933,6 +991,15 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
if (ret) if (ret)
return ret; return ret;
/*
* 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.
*/
if (of_device_is_compatible(f->dev->of_node, "nxp,lx2160a-fspi"))
erratum_err050568(f);
/* Reset the module */ /* Reset the module */
/* w1c register, wait unit clear */ /* w1c register, wait unit clear */
ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0, ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0,
...@@ -1036,7 +1103,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) ...@@ -1036,7 +1103,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
f = spi_controller_get_devdata(ctlr); f = spi_controller_get_devdata(ctlr);
f->dev = dev; f->dev = dev;
f->devtype_data = device_get_match_data(dev); f->devtype_data = (struct nxp_fspi_devtype_data *)device_get_match_data(dev);
if (!f->devtype_data) { if (!f->devtype_data) {
ret = -ENODEV; ret = -ENODEV;
goto err_put_ctrl; goto err_put_ctrl;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment