mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 07:46:48 +00:00
mediatek: v5.15: backport spi-mem ecc support
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
This commit is contained in:
parent
3e5925225e
commit
861efe158a
@ -0,0 +1,224 @@
|
||||
From ad4944aa0b02cb043afe20bc2a018c161e65c992 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 16 Dec 2021 12:16:38 +0100
|
||||
Subject: [PATCH 01/15] mtd: nand: ecc: Add infrastructure to support hardware
|
||||
engines
|
||||
|
||||
Add the necessary helpers to register/unregister hardware ECC engines
|
||||
that will be called from ECC engine drivers.
|
||||
|
||||
Also add helpers to get the right engine from the user
|
||||
perspective. Keep a reference of the in use ECC engine in order to
|
||||
prevent modules to be unloaded. Put the reference when the engine gets
|
||||
retired.
|
||||
|
||||
A static list of hardware (only) ECC engines is setup to keep track of
|
||||
the registered engines.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20211216111654.238086-13-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit 96489c1c0b53131b0e1ec33e2060538379ad6152)
|
||||
---
|
||||
drivers/mtd/nand/core.c | 10 +++--
|
||||
drivers/mtd/nand/ecc.c | 88 ++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/nand.h | 28 +++++++++++++
|
||||
3 files changed, 123 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
|
||||
index 5e13a03d2b32..b228b4d13b7a 100644
|
||||
--- a/drivers/mtd/nand/core.c
|
||||
+++ b/drivers/mtd/nand/core.c
|
||||
@@ -232,7 +232,9 @@ static int nanddev_get_ecc_engine(struct nand_device *nand)
|
||||
nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand);
|
||||
break;
|
||||
case NAND_ECC_ENGINE_TYPE_ON_HOST:
|
||||
- pr_err("On-host hardware ECC engines not supported yet\n");
|
||||
+ nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand);
|
||||
+ if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER)
|
||||
+ return -EPROBE_DEFER;
|
||||
break;
|
||||
default:
|
||||
pr_err("Missing ECC engine type\n");
|
||||
@@ -252,7 +254,7 @@ static int nanddev_put_ecc_engine(struct nand_device *nand)
|
||||
{
|
||||
switch (nand->ecc.ctx.conf.engine_type) {
|
||||
case NAND_ECC_ENGINE_TYPE_ON_HOST:
|
||||
- pr_err("On-host hardware ECC engines not supported yet\n");
|
||||
+ nand_ecc_put_on_host_hw_engine(nand);
|
||||
break;
|
||||
case NAND_ECC_ENGINE_TYPE_NONE:
|
||||
case NAND_ECC_ENGINE_TYPE_SOFT:
|
||||
@@ -297,7 +299,9 @@ int nanddev_ecc_engine_init(struct nand_device *nand)
|
||||
/* Look for the ECC engine to use */
|
||||
ret = nanddev_get_ecc_engine(nand);
|
||||
if (ret) {
|
||||
- pr_err("No ECC engine found\n");
|
||||
+ if (ret != -EPROBE_DEFER)
|
||||
+ pr_err("No ECC engine found\n");
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
|
||||
index 6c43dfda01d4..078f5ec38de3 100644
|
||||
--- a/drivers/mtd/nand/ecc.c
|
||||
+++ b/drivers/mtd/nand/ecc.c
|
||||
@@ -96,6 +96,12 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+
|
||||
+static LIST_HEAD(on_host_hw_engines);
|
||||
+static DEFINE_MUTEX(on_host_hw_engines_mutex);
|
||||
|
||||
/**
|
||||
* nand_ecc_init_ctx - Init the ECC engine context
|
||||
@@ -611,6 +617,88 @@ struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand)
|
||||
}
|
||||
EXPORT_SYMBOL(nand_ecc_get_on_die_hw_engine);
|
||||
|
||||
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine)
|
||||
+{
|
||||
+ struct nand_ecc_engine *item;
|
||||
+
|
||||
+ if (!engine)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Prevent multiple registrations of one engine */
|
||||
+ list_for_each_entry(item, &on_host_hw_engines, node)
|
||||
+ if (item == engine)
|
||||
+ return 0;
|
||||
+
|
||||
+ mutex_lock(&on_host_hw_engines_mutex);
|
||||
+ list_add_tail(&engine->node, &on_host_hw_engines);
|
||||
+ mutex_unlock(&on_host_hw_engines_mutex);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nand_ecc_register_on_host_hw_engine);
|
||||
+
|
||||
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine)
|
||||
+{
|
||||
+ if (!engine)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&on_host_hw_engines_mutex);
|
||||
+ list_del(&engine->node);
|
||||
+ mutex_unlock(&on_host_hw_engines_mutex);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nand_ecc_unregister_on_host_hw_engine);
|
||||
+
|
||||
+static struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev)
|
||||
+{
|
||||
+ struct nand_ecc_engine *item;
|
||||
+
|
||||
+ list_for_each_entry(item, &on_host_hw_engines, node)
|
||||
+ if (item->dev == dev)
|
||||
+ return item;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand)
|
||||
+{
|
||||
+ struct nand_ecc_engine *engine = NULL;
|
||||
+ struct device *dev = &nand->mtd.dev;
|
||||
+ struct platform_device *pdev;
|
||||
+ struct device_node *np;
|
||||
+
|
||||
+ if (list_empty(&on_host_hw_engines))
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Check for an explicit nand-ecc-engine property */
|
||||
+ np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
|
||||
+ if (np) {
|
||||
+ pdev = of_find_device_by_node(np);
|
||||
+ if (!pdev)
|
||||
+ return ERR_PTR(-EPROBE_DEFER);
|
||||
+
|
||||
+ engine = nand_ecc_match_on_host_hw_engine(&pdev->dev);
|
||||
+ platform_device_put(pdev);
|
||||
+ of_node_put(np);
|
||||
+
|
||||
+ if (!engine)
|
||||
+ return ERR_PTR(-EPROBE_DEFER);
|
||||
+ }
|
||||
+
|
||||
+ if (engine)
|
||||
+ get_device(engine->dev);
|
||||
+
|
||||
+ return engine;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nand_ecc_get_on_host_hw_engine);
|
||||
+
|
||||
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand)
|
||||
+{
|
||||
+ put_device(nand->ecc.engine->dev);
|
||||
+}
|
||||
+EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine);
|
||||
+
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
||||
MODULE_DESCRIPTION("Generic ECC engine");
|
||||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
|
||||
index 32fc7edf65b3..4ddd20fe9c9e 100644
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -263,12 +263,36 @@ struct nand_ecc_engine_ops {
|
||||
struct nand_page_io_req *req);
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * enum nand_ecc_engine_integration - How the NAND ECC engine is integrated
|
||||
+ * @NAND_ECC_ENGINE_INTEGRATION_INVALID: Invalid value
|
||||
+ * @NAND_ECC_ENGINE_INTEGRATION_PIPELINED: Pipelined engine, performs on-the-fly
|
||||
+ * correction, does not need to copy
|
||||
+ * data around
|
||||
+ * @NAND_ECC_ENGINE_INTEGRATION_EXTERNAL: External engine, needs to bring the
|
||||
+ * data into its own area before use
|
||||
+ */
|
||||
+enum nand_ecc_engine_integration {
|
||||
+ NAND_ECC_ENGINE_INTEGRATION_INVALID,
|
||||
+ NAND_ECC_ENGINE_INTEGRATION_PIPELINED,
|
||||
+ NAND_ECC_ENGINE_INTEGRATION_EXTERNAL,
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct nand_ecc_engine - ECC engine abstraction for NAND devices
|
||||
+ * @dev: Host device
|
||||
+ * @node: Private field for registration time
|
||||
* @ops: ECC engine operations
|
||||
+ * @integration: How the engine is integrated with the host
|
||||
+ * (only relevant on %NAND_ECC_ENGINE_TYPE_ON_HOST engines)
|
||||
+ * @priv: Private data
|
||||
*/
|
||||
struct nand_ecc_engine {
|
||||
+ struct device *dev;
|
||||
+ struct list_head node;
|
||||
struct nand_ecc_engine_ops *ops;
|
||||
+ enum nand_ecc_engine_integration integration;
|
||||
+ void *priv;
|
||||
};
|
||||
|
||||
void of_get_nand_ecc_user_config(struct nand_device *nand);
|
||||
@@ -279,8 +303,12 @@ int nand_ecc_prepare_io_req(struct nand_device *nand,
|
||||
int nand_ecc_finish_io_req(struct nand_device *nand,
|
||||
struct nand_page_io_req *req);
|
||||
bool nand_ecc_is_strong_enough(struct nand_device *nand);
|
||||
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine);
|
||||
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine);
|
||||
struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
|
||||
struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand);
|
||||
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand);
|
||||
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand);
|
||||
|
||||
#if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING)
|
||||
struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void);
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 840b2f8dd2d0579e517140e1f9bbc482eaf4ed07 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 16 Dec 2021 12:16:39 +0100
|
||||
Subject: [PATCH 02/15] mtd: nand: Add a new helper to retrieve the ECC context
|
||||
|
||||
Introduce nand_to_ecc_ctx() which will allow to easily jump to the
|
||||
private pointer of an ECC context given a NAND device. This is very
|
||||
handy, from the prepare or finish ECC hook, to get the internal context
|
||||
out of the NAND device object.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20211216111654.238086-14-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit cda32a618debd3fad8e42757b198719ae180f8f4)
|
||||
---
|
||||
include/linux/mtd/nand.h | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
|
||||
index 4ddd20fe9c9e..b617efa0a881 100644
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -990,6 +990,11 @@ int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
|
||||
int nanddev_ecc_engine_init(struct nand_device *nand);
|
||||
void nanddev_ecc_engine_cleanup(struct nand_device *nand);
|
||||
|
||||
+static inline void *nand_to_ecc_ctx(struct nand_device *nand)
|
||||
+{
|
||||
+ return nand->ecc.ctx.priv;
|
||||
+}
|
||||
+
|
||||
/* BBT related functions */
|
||||
enum nand_bbt_block_status {
|
||||
NAND_BBT_BLOCK_STATUS_UNKNOWN,
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,80 @@
|
||||
From 784866bc4f9f25e0494b77750f95af2a2619e498 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 16 Dec 2021 12:16:41 +0100
|
||||
Subject: [PATCH 03/15] mtd: nand: ecc: Provide a helper to retrieve a
|
||||
pilelined engine device
|
||||
|
||||
In a pipelined engine situation, we might either have the host which
|
||||
internally has support for error correction, or have it using an
|
||||
external hardware block for this purpose. In the former case, the host
|
||||
is also the ECC engine. In the latter case, it is not. In order to get
|
||||
the right pointers on the right devices (for example: in order to devm_*
|
||||
allocate variables), let's introduce this helper which can safely be
|
||||
called by pipelined ECC engines in order to retrieve the right device
|
||||
structure.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20211216111654.238086-16-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit 5145abeb0649acf810a32e63bd762e617a9b3309)
|
||||
---
|
||||
drivers/mtd/nand/ecc.c | 31 +++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/nand.h | 1 +
|
||||
2 files changed, 32 insertions(+)
|
||||
|
||||
diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
|
||||
index 078f5ec38de3..5250764cedee 100644
|
||||
--- a/drivers/mtd/nand/ecc.c
|
||||
+++ b/drivers/mtd/nand/ecc.c
|
||||
@@ -699,6 +699,37 @@ void nand_ecc_put_on_host_hw_engine(struct nand_device *nand)
|
||||
}
|
||||
EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine);
|
||||
|
||||
+/*
|
||||
+ * In the case of a pipelined engine, the device registering the ECC
|
||||
+ * engine is not necessarily the ECC engine itself but may be a host controller.
|
||||
+ * It is then useful to provide a helper to retrieve the right device object
|
||||
+ * which actually represents the ECC engine.
|
||||
+ */
|
||||
+struct device *nand_ecc_get_engine_dev(struct device *host)
|
||||
+{
|
||||
+ struct platform_device *ecc_pdev;
|
||||
+ struct device_node *np;
|
||||
+
|
||||
+ /*
|
||||
+ * If the device node contains this property, it means we need to follow
|
||||
+ * it in order to get the right ECC engine device we are looking for.
|
||||
+ */
|
||||
+ np = of_parse_phandle(host->of_node, "nand-ecc-engine", 0);
|
||||
+ if (!np)
|
||||
+ return host;
|
||||
+
|
||||
+ ecc_pdev = of_find_device_by_node(np);
|
||||
+ if (!ecc_pdev) {
|
||||
+ of_node_put(np);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ platform_device_put(ecc_pdev);
|
||||
+ of_node_put(np);
|
||||
+
|
||||
+ return &ecc_pdev->dev;
|
||||
+}
|
||||
+
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
||||
MODULE_DESCRIPTION("Generic ECC engine");
|
||||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
|
||||
index b617efa0a881..615b3e3a3920 100644
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -309,6 +309,7 @@ struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
|
||||
struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand);
|
||||
struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand);
|
||||
void nand_ecc_put_on_host_hw_engine(struct nand_device *nand);
|
||||
+struct device *nand_ecc_get_engine_dev(struct device *host);
|
||||
|
||||
#if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING)
|
||||
struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void);
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,78 @@
|
||||
From 3e45577e70cbf8fdc5c13033114989794a3797d5 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 27 Jan 2022 10:17:56 +0100
|
||||
Subject: [PATCH 04/15] spi: spi-mem: Introduce a capability structure
|
||||
|
||||
Create a spi_controller_mem_caps structure and put it within the
|
||||
spi_controller structure close to the spi_controller_mem_ops
|
||||
strucure. So far the only field in this structure is the support for dtr
|
||||
operations, but soon we will add another parameter.
|
||||
|
||||
Also create a helper to parse the capabilities and check if the
|
||||
requested capability has been set or not.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
Reviewed-by: Mark Brown <broonie@kernel.org>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-2-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit 4a3cc7fb6e63bcfdedec25364738f1493345bd20)
|
||||
---
|
||||
include/linux/spi/spi-mem.h | 11 +++++++++++
|
||||
include/linux/spi/spi.h | 3 +++
|
||||
2 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
|
||||
index 85e2ff7b840d..38e5d45c9842 100644
|
||||
--- a/include/linux/spi/spi-mem.h
|
||||
+++ b/include/linux/spi/spi-mem.h
|
||||
@@ -285,6 +285,17 @@ struct spi_controller_mem_ops {
|
||||
unsigned long timeout_ms);
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct spi_controller_mem_caps - SPI memory controller capabilities
|
||||
+ * @dtr: Supports DTR operations
|
||||
+ */
|
||||
+struct spi_controller_mem_caps {
|
||||
+ bool dtr;
|
||||
+};
|
||||
+
|
||||
+#define spi_mem_controller_is_capable(ctlr, cap) \
|
||||
+ ((ctlr)->mem_caps && (ctlr)->mem_caps->cap)
|
||||
+
|
||||
/**
|
||||
* struct spi_mem_driver - SPI memory driver
|
||||
* @spidrv: inherit from a SPI driver
|
||||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
|
||||
index 6b0b686f6f90..8ac58b1a2a9f 100644
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -23,6 +23,7 @@ struct software_node;
|
||||
struct spi_controller;
|
||||
struct spi_transfer;
|
||||
struct spi_controller_mem_ops;
|
||||
+struct spi_controller_mem_caps;
|
||||
|
||||
/*
|
||||
* INTERFACES between SPI master-side drivers and SPI slave protocol handlers,
|
||||
@@ -419,6 +420,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
|
||||
* @mem_ops: optimized/dedicated operations for interactions with SPI memory.
|
||||
* This field is optional and should only be implemented if the
|
||||
* controller has native support for memory like operations.
|
||||
+ * @mem_caps: controller capabilities for the handling of memory operations.
|
||||
* @unprepare_message: undo any work done by prepare_message().
|
||||
* @slave_abort: abort the ongoing transfer request on an SPI slave controller
|
||||
* @cs_gpios: LEGACY: array of GPIO descs to use as chip select lines; one per
|
||||
@@ -643,6 +645,7 @@ struct spi_controller {
|
||||
|
||||
/* Optimized handlers for SPI memory-like operations. */
|
||||
const struct spi_controller_mem_ops *mem_ops;
|
||||
+ const struct spi_controller_mem_caps *mem_caps;
|
||||
|
||||
/* gpio chip select */
|
||||
int *cs_gpios;
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,56 @@
|
||||
From c9cae7e1e5c87d0aa76b7bededa5191a0c8cf25a Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 27 Jan 2022 10:17:57 +0100
|
||||
Subject: [PATCH 05/15] spi: spi-mem: Check the controller extra capabilities
|
||||
|
||||
Controllers can now provide a spi-mem capabilities structure. Let's make
|
||||
use of it in spi_mem_controller_default_supports_op(). As we want to
|
||||
check for DTR operations as well as normal operations in a single
|
||||
helper, let's pull the necessary checks from spi_mem_dtr_supports_op()
|
||||
for now.
|
||||
|
||||
However, because no controller provide these extra capabilities, this
|
||||
change has no effect so far.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-3-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit cb7e96ee81edaa48c67d84c14df2cbe464391c37)
|
||||
---
|
||||
drivers/spi/spi-mem.c | 17 +++++++++++++----
|
||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
|
||||
index 37f4443ce9a0..86e6597bc3dc 100644
|
||||
--- a/drivers/spi/spi-mem.c
|
||||
+++ b/drivers/spi/spi-mem.c
|
||||
@@ -173,11 +173,20 @@ EXPORT_SYMBOL_GPL(spi_mem_dtr_supports_op);
|
||||
bool spi_mem_default_supports_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
- if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
|
||||
- return false;
|
||||
+ struct spi_controller *ctlr = mem->spi->controller;
|
||||
+ bool op_is_dtr =
|
||||
+ op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr;
|
||||
|
||||
- if (op->cmd.nbytes != 1)
|
||||
- return false;
|
||||
+ if (op_is_dtr) {
|
||||
+ if (!spi_mem_controller_is_capable(ctlr, dtr))
|
||||
+ return false;
|
||||
+
|
||||
+ if (op->cmd.nbytes != 2)
|
||||
+ return false;
|
||||
+ } else {
|
||||
+ if (op->cmd.nbytes != 1)
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
return spi_mem_check_buswidth(mem, op);
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,122 @@
|
||||
From 2e5fba82e4aeb72d71230eef2541881615aaf7cf Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 27 Jan 2022 10:18:00 +0100
|
||||
Subject: [PATCH 06/15] spi: spi-mem: Kill the spi_mem_dtr_supports_op() helper
|
||||
|
||||
Now that spi_mem_default_supports_op() has access to the static
|
||||
controller capabilities (relating to memory operations), and now that
|
||||
these capabilities have been filled by the relevant controllers, there
|
||||
is no need for a specific helper checking only DTR operations, so let's
|
||||
just kill spi_mem_dtr_supports_op() and simply use
|
||||
spi_mem_default_supports_op() instead.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-6-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit 9a15efc5d5e6b5beaed0883e5bdcd0b1384c1b20)
|
||||
---
|
||||
drivers/spi/spi-cadence-quadspi.c | 5 +----
|
||||
drivers/spi/spi-mem.c | 10 ----------
|
||||
drivers/spi/spi-mxic.c | 10 +---------
|
||||
include/linux/spi/spi-mem.h | 11 -----------
|
||||
4 files changed, 2 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
|
||||
index 101cc71bffa7..2c98d6a9a2aa 100644
|
||||
--- a/drivers/spi/spi-cadence-quadspi.c
|
||||
+++ b/drivers/spi/spi-cadence-quadspi.c
|
||||
@@ -1252,10 +1252,7 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem,
|
||||
if (!(all_true || all_false))
|
||||
return false;
|
||||
|
||||
- if (all_true)
|
||||
- return spi_mem_dtr_supports_op(mem, op);
|
||||
- else
|
||||
- return spi_mem_default_supports_op(mem, op);
|
||||
+ return spi_mem_default_supports_op(mem, op);
|
||||
}
|
||||
|
||||
static int cqspi_of_get_flash_pdata(struct platform_device *pdev,
|
||||
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
|
||||
index 86e6597bc3dc..ed966d8129eb 100644
|
||||
--- a/drivers/spi/spi-mem.c
|
||||
+++ b/drivers/spi/spi-mem.c
|
||||
@@ -160,16 +160,6 @@ static bool spi_mem_check_buswidth(struct spi_mem *mem,
|
||||
return true;
|
||||
}
|
||||
|
||||
-bool spi_mem_dtr_supports_op(struct spi_mem *mem,
|
||||
- const struct spi_mem_op *op)
|
||||
-{
|
||||
- if (op->cmd.nbytes != 2)
|
||||
- return false;
|
||||
-
|
||||
- return spi_mem_check_buswidth(mem, op);
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(spi_mem_dtr_supports_op);
|
||||
-
|
||||
bool spi_mem_default_supports_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
|
||||
index 45889947afed..e895df09896a 100644
|
||||
--- a/drivers/spi/spi-mxic.c
|
||||
+++ b/drivers/spi/spi-mxic.c
|
||||
@@ -335,8 +335,6 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
|
||||
static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
- bool all_false;
|
||||
-
|
||||
if (op->data.buswidth > 8 || op->addr.buswidth > 8 ||
|
||||
op->dummy.buswidth > 8 || op->cmd.buswidth > 8)
|
||||
return false;
|
||||
@@ -348,13 +346,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
|
||||
if (op->addr.nbytes > 7)
|
||||
return false;
|
||||
|
||||
- all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
|
||||
- !op->data.dtr;
|
||||
-
|
||||
- if (all_false)
|
||||
- return spi_mem_default_supports_op(mem, op);
|
||||
- else
|
||||
- return spi_mem_dtr_supports_op(mem, op);
|
||||
+ return spi_mem_default_supports_op(mem, op);
|
||||
}
|
||||
|
||||
static int mxic_spi_mem_exec_op(struct spi_mem *mem,
|
||||
diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
|
||||
index 38e5d45c9842..4a1bfe689872 100644
|
||||
--- a/include/linux/spi/spi-mem.h
|
||||
+++ b/include/linux/spi/spi-mem.h
|
||||
@@ -330,10 +330,6 @@ void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
|
||||
|
||||
bool spi_mem_default_supports_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op);
|
||||
-
|
||||
-bool spi_mem_dtr_supports_op(struct spi_mem *mem,
|
||||
- const struct spi_mem_op *op);
|
||||
-
|
||||
#else
|
||||
static inline int
|
||||
spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr,
|
||||
@@ -356,13 +352,6 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
-
|
||||
-static inline
|
||||
-bool spi_mem_dtr_supports_op(struct spi_mem *mem,
|
||||
- const struct spi_mem_op *op)
|
||||
-{
|
||||
- return false;
|
||||
-}
|
||||
#endif /* CONFIG_SPI_MEM */
|
||||
|
||||
int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op);
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,79 @@
|
||||
From 9e7eb0ea442ecb1c3fe443289e288694f10c5148 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 27 Jan 2022 10:18:01 +0100
|
||||
Subject: [PATCH 07/15] spi: spi-mem: Add an ecc parameter to the spi_mem_op
|
||||
structure
|
||||
|
||||
Soon the SPI-NAND core will need a way to request a SPI controller to
|
||||
enable ECC support for a given operation. This is because of the
|
||||
pipelined integration of certain ECC engines, which are directly managed
|
||||
by the SPI controller itself.
|
||||
|
||||
Introduce a spi_mem_op additional field for this purpose: ecc.
|
||||
|
||||
So far this field is left unset and checked to be false by all
|
||||
the SPI controller drivers in their ->supports_op() hook, as they all
|
||||
call spi_mem_default_supports_op().
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Acked-by: Pratyush Yadav <p.yadav@ti.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-7-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit a433c2cbd75ab76f277364f44e76f32c7df306e7)
|
||||
---
|
||||
drivers/spi/spi-mem.c | 5 +++++
|
||||
include/linux/spi/spi-mem.h | 4 ++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
|
||||
index ed966d8129eb..f38ac31961c9 100644
|
||||
--- a/drivers/spi/spi-mem.c
|
||||
+++ b/drivers/spi/spi-mem.c
|
||||
@@ -178,6 +178,11 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (op->data.ecc) {
|
||||
+ if (!spi_mem_controller_is_capable(ctlr, ecc))
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
return spi_mem_check_buswidth(mem, op);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
|
||||
diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
|
||||
index 4a1bfe689872..2ba044d0d5e5 100644
|
||||
--- a/include/linux/spi/spi-mem.h
|
||||
+++ b/include/linux/spi/spi-mem.h
|
||||
@@ -89,6 +89,7 @@ enum spi_mem_data_dir {
|
||||
* @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not
|
||||
* @data.buswidth: number of IO lanes used to send/receive the data
|
||||
* @data.dtr: whether the data should be sent in DTR mode or not
|
||||
+ * @data.ecc: whether error correction is required or not
|
||||
* @data.dir: direction of the transfer
|
||||
* @data.nbytes: number of data bytes to send/receive. Can be zero if the
|
||||
* operation does not involve transferring data
|
||||
@@ -119,6 +120,7 @@ struct spi_mem_op {
|
||||
struct {
|
||||
u8 buswidth;
|
||||
u8 dtr : 1;
|
||||
+ u8 ecc : 1;
|
||||
enum spi_mem_data_dir dir;
|
||||
unsigned int nbytes;
|
||||
union {
|
||||
@@ -288,9 +290,11 @@ struct spi_controller_mem_ops {
|
||||
/**
|
||||
* struct spi_controller_mem_caps - SPI memory controller capabilities
|
||||
* @dtr: Supports DTR operations
|
||||
+ * @ecc: Supports operations with error correction
|
||||
*/
|
||||
struct spi_controller_mem_caps {
|
||||
bool dtr;
|
||||
+ bool ecc;
|
||||
};
|
||||
|
||||
#define spi_mem_controller_is_capable(ctlr, cap) \
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 94ef3c35b935a63f6c156957c92f6cf33c9a8dae Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 27 Jan 2022 10:18:02 +0100
|
||||
Subject: [PATCH 08/15] mtd: spinand: Delay a little bit the dirmap creation
|
||||
|
||||
As we will soon tweak the dirmap creation to act a little bit
|
||||
differently depending on the picked ECC engine, we need to initialize
|
||||
dirmaps after ECC engines. This should not have any effect as dirmaps
|
||||
are not yet used at this point.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-8-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit dc4c2cbf0be2d4a8e2a65013ea2815bb2c8ba949)
|
||||
---
|
||||
drivers/mtd/nand/spi/core.c | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
|
||||
index 2c8685f1f2fa..bb6b026b558b 100644
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -1208,14 +1208,6 @@ static int spinand_init(struct spinand_device *spinand)
|
||||
if (ret)
|
||||
goto err_free_bufs;
|
||||
|
||||
- ret = spinand_create_dirmaps(spinand);
|
||||
- if (ret) {
|
||||
- dev_err(dev,
|
||||
- "Failed to create direct mappings for read/write operations (err = %d)\n",
|
||||
- ret);
|
||||
- goto err_manuf_cleanup;
|
||||
- }
|
||||
-
|
||||
ret = nanddev_init(nand, &spinand_ops, THIS_MODULE);
|
||||
if (ret)
|
||||
goto err_manuf_cleanup;
|
||||
@@ -1250,6 +1242,14 @@ static int spinand_init(struct spinand_device *spinand)
|
||||
mtd->ecc_strength = nanddev_get_ecc_conf(nand)->strength;
|
||||
mtd->ecc_step_size = nanddev_get_ecc_conf(nand)->step_size;
|
||||
|
||||
+ ret = spinand_create_dirmaps(spinand);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev,
|
||||
+ "Failed to create direct mappings for read/write operations (err = %d)\n",
|
||||
+ ret);
|
||||
+ goto err_cleanup_ecc_engine;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_cleanup_ecc_engine:
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,105 @@
|
||||
From eb4a2d282c3c5752211d69be6dff2674119e5583 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Thu, 27 Jan 2022 10:18:03 +0100
|
||||
Subject: [PATCH 09/15] mtd: spinand: Create direct mapping descriptors for ECC
|
||||
operations
|
||||
|
||||
In order for pipelined ECC engines to be able to enable/disable the ECC
|
||||
engine only when needed and avoid races when future parallel-operations
|
||||
will be supported, we need to provide the information about the use of
|
||||
the ECC engine in the direct mapping hooks. As direct mapping
|
||||
configurations are meant to be static, it is best to create two new
|
||||
mappings: one for regular 'raw' accesses and one for accesses involving
|
||||
correction. It is up to the driver to use or not the new ECC enable
|
||||
boolean contained in the spi-mem operation.
|
||||
|
||||
As dirmaps are not free (they consume a few pages of MMIO address space)
|
||||
and because these extra entries are only meant to be used by pipelined
|
||||
engines, let's limit their use to this specific type of engine and save
|
||||
a bit of memory with all the other setups.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-9-miquel.raynal@bootlin.com
|
||||
(cherry picked from commit f9d7c7265bcff7d9a17425a8cddf702e8fe159c2)
|
||||
---
|
||||
drivers/mtd/nand/spi/core.c | 35 +++++++++++++++++++++++++++++++++--
|
||||
include/linux/mtd/spinand.h | 2 ++
|
||||
2 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
|
||||
index bb6b026b558b..ff8336870bc0 100644
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -381,7 +381,10 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
|
||||
}
|
||||
}
|
||||
|
||||
- rdesc = spinand->dirmaps[req->pos.plane].rdesc;
|
||||
+ if (req->mode == MTD_OPS_RAW)
|
||||
+ rdesc = spinand->dirmaps[req->pos.plane].rdesc;
|
||||
+ else
|
||||
+ rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc;
|
||||
|
||||
while (nbytes) {
|
||||
ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf);
|
||||
@@ -452,7 +455,10 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
|
||||
req->ooblen);
|
||||
}
|
||||
|
||||
- wdesc = spinand->dirmaps[req->pos.plane].wdesc;
|
||||
+ if (req->mode == MTD_OPS_RAW)
|
||||
+ wdesc = spinand->dirmaps[req->pos.plane].wdesc;
|
||||
+ else
|
||||
+ wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc;
|
||||
|
||||
while (nbytes) {
|
||||
ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf);
|
||||
@@ -865,6 +871,31 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
|
||||
|
||||
spinand->dirmaps[plane].rdesc = desc;
|
||||
|
||||
+ if (nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) {
|
||||
+ spinand->dirmaps[plane].wdesc_ecc = spinand->dirmaps[plane].wdesc;
|
||||
+ spinand->dirmaps[plane].rdesc_ecc = spinand->dirmaps[plane].rdesc;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ info.op_tmpl = *spinand->op_templates.update_cache;
|
||||
+ info.op_tmpl.data.ecc = true;
|
||||
+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
|
||||
+ spinand->spimem, &info);
|
||||
+ if (IS_ERR(desc))
|
||||
+ return PTR_ERR(desc);
|
||||
+
|
||||
+ spinand->dirmaps[plane].wdesc_ecc = desc;
|
||||
+
|
||||
+ info.op_tmpl = *spinand->op_templates.read_cache;
|
||||
+ info.op_tmpl.data.ecc = true;
|
||||
+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
|
||||
+ spinand->spimem, &info);
|
||||
+ if (IS_ERR(desc))
|
||||
+ return PTR_ERR(desc);
|
||||
+
|
||||
+ spinand->dirmaps[plane].rdesc_ecc = desc;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
|
||||
index 6988956b8492..3aa28240a77f 100644
|
||||
--- a/include/linux/mtd/spinand.h
|
||||
+++ b/include/linux/mtd/spinand.h
|
||||
@@ -389,6 +389,8 @@ struct spinand_info {
|
||||
struct spinand_dirmap {
|
||||
struct spi_mem_dirmap_desc *wdesc;
|
||||
struct spi_mem_dirmap_desc *rdesc;
|
||||
+ struct spi_mem_dirmap_desc *wdesc_ecc;
|
||||
+ struct spi_mem_dirmap_desc *rdesc_ecc;
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,93 @@
|
||||
From 41825166744c6e5664281611f5e6d9a2e9333c2b Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Sat, 2 Apr 2022 22:31:20 +0800
|
||||
Subject: [PATCH 10/15] mtd: nand: fix ecc parameters for mt7622
|
||||
|
||||
According to the datasheet, mt7622 only has 5 ECC capabilities instead
|
||||
of 7, and the decoding error register is arranged as follows:
|
||||
+------+---------+---------+---------+---------+
|
||||
| Bits | 19:15 | 14:10 | 9:5 | 4:0 |
|
||||
+------+---------+---------+---------+---------+
|
||||
| Name | ERRNUM3 | ERRNUM2 | ERRNUM1 | ERRNUM0 |
|
||||
+------+---------+---------+---------+---------+
|
||||
This means err_mask should be 0x1f instead of 0x3f and the number of
|
||||
bits shifted in mtk_ecc_get_stats should be 5 instead of 8.
|
||||
|
||||
This commit introduces err_shift for the difference in this register
|
||||
and fix other existing parameters.
|
||||
|
||||
Public MT7622 reference manual can be found on [0] and the info this
|
||||
commit is based on is from page 656 and page 660.
|
||||
|
||||
[0]: https://wiki.banana-pi.org/Banana_Pi_BPI-R64#Documents
|
||||
|
||||
Fixes: 98dea8d71931 ("mtd: nand: mtk: Support MT7622 NAND flash controller.")
|
||||
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
|
||||
(cherry picked from commit 088b769abd1bd21753002b17b696ae1778b16e8c)
|
||||
---
|
||||
drivers/mtd/nand/raw/mtk_ecc.c | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
|
||||
index c437d97debb8..ec9d1fb07006 100644
|
||||
--- a/drivers/mtd/nand/raw/mtk_ecc.c
|
||||
+++ b/drivers/mtd/nand/raw/mtk_ecc.c
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
struct mtk_ecc_caps {
|
||||
u32 err_mask;
|
||||
+ u32 err_shift;
|
||||
const u8 *ecc_strength;
|
||||
const u32 *ecc_regs;
|
||||
u8 num_ecc_strength;
|
||||
@@ -76,7 +77,7 @@ static const u8 ecc_strength_mt2712[] = {
|
||||
};
|
||||
|
||||
static const u8 ecc_strength_mt7622[] = {
|
||||
- 4, 6, 8, 10, 12, 14, 16
|
||||
+ 4, 6, 8, 10, 12
|
||||
};
|
||||
|
||||
enum mtk_ecc_regs {
|
||||
@@ -221,7 +222,7 @@ void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
|
||||
for (i = 0; i < sectors; i++) {
|
||||
offset = (i >> 2) << 2;
|
||||
err = readl(ecc->regs + ECC_DECENUM0 + offset);
|
||||
- err = err >> ((i % 4) * 8);
|
||||
+ err = err >> ((i % 4) * ecc->caps->err_shift);
|
||||
err &= ecc->caps->err_mask;
|
||||
if (err == ecc->caps->err_mask) {
|
||||
/* uncorrectable errors */
|
||||
@@ -449,6 +450,7 @@ EXPORT_SYMBOL(mtk_ecc_get_parity_bits);
|
||||
|
||||
static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
|
||||
.err_mask = 0x3f,
|
||||
+ .err_shift = 8,
|
||||
.ecc_strength = ecc_strength_mt2701,
|
||||
.ecc_regs = mt2701_ecc_regs,
|
||||
.num_ecc_strength = 20,
|
||||
@@ -459,6 +461,7 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
|
||||
|
||||
static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
|
||||
.err_mask = 0x7f,
|
||||
+ .err_shift = 8,
|
||||
.ecc_strength = ecc_strength_mt2712,
|
||||
.ecc_regs = mt2712_ecc_regs,
|
||||
.num_ecc_strength = 23,
|
||||
@@ -468,10 +471,11 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
|
||||
};
|
||||
|
||||
static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = {
|
||||
- .err_mask = 0x3f,
|
||||
+ .err_mask = 0x1f,
|
||||
+ .err_shift = 5,
|
||||
.ecc_strength = ecc_strength_mt7622,
|
||||
.ecc_regs = mt7622_ecc_regs,
|
||||
- .num_ecc_strength = 7,
|
||||
+ .num_ecc_strength = 5,
|
||||
.ecc_mode_shift = 4,
|
||||
.parity_bits = 13,
|
||||
.pg_irq_sel = 0,
|
||||
--
|
||||
2.35.1
|
||||
|
Loading…
Reference in New Issue
Block a user