[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250910030301.1368372-3-linchengming884@gmail.com>
Date: Wed, 10 Sep 2025 11:03:00 +0800
From: Cheng Ming Lin <linchengming884@...il.com>
To: miquel.raynal@...tlin.com,
richard@....at,
vigneshr@...com,
robh@...nel.org,
krzk+dt@...nel.org,
conor+dt@...nel.org
Cc: tudor.ambarus@...aro.org,
mmkurbanov@...utedevices.com,
Takahiro.Kuwano@...ineon.com,
pratyush@...nel.org,
linux-mtd@...ts.infradead.org,
devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org,
alvinzhou@...c.com.tw,
Cheng Ming Lin <chengminglin@...c.com.tw>
Subject: [PATCH v2 2/3] mtd: spi-nand: Add support for randomizer
From: Cheng Ming Lin <chengminglin@...c.com.tw>
Introduce randomizer initialization for SPI-NAND devices.
According to JESD22-A117E, there is no single data pattern that represents
a universal worst-case across all failure mechanisms. Different mechanisms
may stress programmed cells, erased cells, or cells influenced by adjacent
states, and thus specific patterns such as fully programmed, checkerboard,
or mostly erased are each only worst-case for certain desings or processes.
Given that no fixed pattern can cover all cases, the use of a randomized
data pattern is considered a practical mitigation strategy. A randomizer
distributes stress more evenly across the device by scrambling incoming
data before storage and restoring it on read. This helps reduce
pattern-dependent degradation and can therefore improve flash reliability.
Signed-off-by: Cheng Ming Lin <chengminglin@...c.com.tw>
---
drivers/mtd/nand/spi/core.c | 24 ++++++++++++++++++++++++
include/linux/mtd/spinand.h | 7 +++++++
2 files changed, 31 insertions(+)
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index ea47028d0..770304403 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -854,6 +854,25 @@ static void spinand_cont_read_init(struct spinand_device *spinand)
}
}
+static int spinand_randomizer_init(struct spinand_device *spinand)
+{
+ struct nand_device *nand = spinand_to_nand(spinand);
+ struct device_node *dn = nanddev_get_of_node(nand);
+ int ret, rand_dt;
+
+ rand_dt = of_property_read_bool(dn, "enable-randomizer-otp");
+ if (!rand_dt)
+ return 0;
+
+ if (spinand->set_randomizer) {
+ ret = spinand->set_randomizer(spinand);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static bool spinand_use_cont_read(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
@@ -1367,6 +1386,7 @@ int spinand_match_and_init(struct spinand_device *spinand,
spinand->user_otp = &table[i].user_otp;
spinand->read_retries = table[i].read_retries;
spinand->set_read_retry = table[i].set_read_retry;
+ spinand->set_randomizer = table[i].set_randomizer;
op = spinand_select_op_variant(spinand,
info->op_variants.read_cache);
@@ -1544,6 +1564,10 @@ static int spinand_init(struct spinand_device *spinand)
*/
spinand_cont_read_init(spinand);
+ ret = spinand_randomizer_init(spinand);
+ if (ret)
+ goto err_cleanup_ecc_engine;
+
mtd->_read_oob = spinand_mtd_read;
mtd->_write_oob = spinand_mtd_write;
mtd->_block_isbad = spinand_mtd_block_isbad;
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 927c10d78..66ea8eed4 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -500,6 +500,7 @@ struct spinand_user_otp {
* @user_otp: SPI NAND user OTP info.
* @read_retries: the number of read retry modes supported
* @set_read_retry: enable/disable read retry for data recovery
+ * @set_randomizer: enable randomizer
*
* Each SPI NAND manufacturer driver should have a spinand_info table
* describing all the chips supported by the driver.
@@ -521,6 +522,7 @@ struct spinand_info {
int (*configure_chip)(struct spinand_device *spinand);
int (*set_cont_read)(struct spinand_device *spinand,
bool enable);
+ int (*set_randomizer)(struct spinand_device *spinand);
struct spinand_fact_otp fact_otp;
struct spinand_user_otp user_otp;
unsigned int read_retries;
@@ -579,6 +581,9 @@ struct spinand_info {
.read_retries = __read_retries, \
.set_read_retry = __set_read_retry
+#define SPINAND_RANDOMIZER(__set_randomizer) \
+ .set_randomizer = __set_randomizer
+
#define SPINAND_INFO(__model, __id, __memorg, __eccreq, __op_variants, \
__flags, ...) \
{ \
@@ -634,6 +639,7 @@ struct spinand_dirmap {
* @user_otp: SPI NAND user OTP info.
* @read_retries: the number of read retry modes supported
* @set_read_retry: Enable/disable the read retry feature
+ * @set_randomizer: Enable the randomizer feature
*/
struct spinand_device {
struct nand_device base;
@@ -667,6 +673,7 @@ struct spinand_device {
bool cont_read_possible;
int (*set_cont_read)(struct spinand_device *spinand,
bool enable);
+ int (*set_randomizer)(struct spinand_device *spinand);
const struct spinand_fact_otp *fact_otp;
const struct spinand_user_otp *user_otp;
--
2.25.1
Powered by blists - more mailing lists