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@xxxxxxxxxxx> --- 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 diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile index 753125082640..e8a04669bdb6 100644 --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile @@ -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 diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 9c8a5ee626cd..eb0b4ffdd8ed 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -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) diff --git a/drivers/mtd/nand/spi/on-die-ecc-engine.c b/drivers/mtd/nand/spi/on-die-ecc-engine.c new file mode 100644 index 000000000000..3d5b83238e14 --- /dev/null +++ b/drivers/mtd/nand/spi/on-die-ecc-engine.c @@ -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@xxxxxxxxxxx> + * Taken from the SPI-NAND core code written by: + * Boris BREZILLON <bbrezillon@xxxxxxxxxx> + */ + +#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; +} diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 75a28dc79a9c..77d9caff4a5c 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -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 */ -- 2.19.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/