@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
-spinand-objs := core.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
+spinand-objs := core.o on-die-ecc-engine.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
@@ -200,13 +200,6 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
enable ? CFG_QUAD_ENABLE : 0);
}
-static int spinand_ecc_enable(struct spinand_device *spinand,
- bool enable)
-{
- return spinand_upd_cfg(spinand, CFG_ECC_ENABLE,
- enable ? CFG_ECC_ENABLE : 0);
-}
-
static int spinand_write_enable_op(struct spinand_device *spinand)
{
struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
@@ -463,35 +456,6 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock);
}
-static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
-{
- struct nand_device *nand = spinand_to_nand(spinand);
-
- if (spinand->eccinfo.get_status)
- return spinand->eccinfo.get_status(spinand, status);
-
- switch (status & STATUS_ECC_MASK) {
- case STATUS_ECC_NO_BITFLIPS:
- return 0;
-
- case STATUS_ECC_HAS_BITFLIPS:
- /*
- * We have no way to know exactly how many bitflips have been
- * fixed, so let's return the maximum possible value so that
- * wear-leveling layers move the data immediately.
- */
- return nand->ecc.ctx.conf.strength;
-
- case STATUS_ECC_UNCOR_ERROR:
- return -EBADMSG;
-
- default:
- break;
- }
-
- return -EINVAL;
-}
-
static int spinand_read_page(struct spinand_device *spinand,
const struct nand_page_io_req *req,
bool ecc_enabled)
new file mode 100644
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * On-die Error-Correcting Code (ECC) engine for SPI-NAND devices
+ *
+ * Copyright (C) 2019 Macronix
+ * Author:
+ * Miquèl RAYNAL <miquel.raynal@bootlin.com>
+ * Taken from the SPI-NAND core code written by:
+ * Boris BREZILLON <bbrezillon@kernel.org>
+ */
+
+#include <linux/mtd/spinand.h>
+
+int spinand_ecc_enable(struct spinand_device *spinand, bool enable)
+{
+ return spinand_upd_cfg(spinand, CFG_ECC_ENABLE,
+ enable ? CFG_ECC_ENABLE : 0);
+}
+
+int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
+{
+ struct nand_device *nand = spinand_to_nand(spinand);
+
+ if (spinand->eccinfo.get_status)
+ return spinand->eccinfo.get_status(spinand, status);
+
+ switch (status & STATUS_ECC_MASK) {
+ case STATUS_ECC_NO_BITFLIPS:
+ return 0;
+
+ case STATUS_ECC_HAS_BITFLIPS:
+ /*
+ * We have no way to know exactly how many bitflips have been
+ * fixed, so let's return the maximum possible value so that
+ * wear-leveling layers move the data immediately.
+ */
+ return nand->ecc.ctx.conf.strength;
+
+ case STATUS_ECC_UNCOR_ERROR:
+ return -EBADMSG;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
@@ -419,5 +419,7 @@ int spinand_match_and_init(struct spinand_device *dev,
int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
int spinand_select_target(struct spinand_device *spinand, unsigned int target);
+int spinand_ecc_enable(struct spinand_device *spinand, bool enable);
+int spinand_check_ecc_status(struct spinand_device *spinand, u8 status);
#endif /* __LINUX_MTD_SPINAND_H */
Prepare the creation of a SPI-NAND chips on-die ECC engine by moving some code out of the core. The next step is to actually create that engine by implementing the generic ECC interface. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> --- drivers/mtd/nand/spi/Makefile | 2 +- drivers/mtd/nand/spi/core.c | 36 ------------------ drivers/mtd/nand/spi/on-die-ecc-engine.c | 47 ++++++++++++++++++++++++ include/linux/mtd/spinand.h | 2 + 4 files changed, 50 insertions(+), 37 deletions(-) create mode 100644 drivers/mtd/nand/spi/on-die-ecc-engine.c