From f6424c22aa3673a0313a306be339495c67c41891 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Beh=C3=BAn?= Date: Fri, 22 Mar 2019 14:26:19 +0100 Subject: [PATCH] mtd: rawnand: fsl_elbc: Make SW ECC work MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Move the code that choses ECC into _attach_chip, which is executed only after the chip->ecc.* properties were loaded from device-tree. This way we know which ECC method was chosen by the device-tree and can set methods appropriately. The chip->ecc.*page methods should be set to fsl_elbc_*page only in HW ECC mode. Signed-off-by: Marek Behún Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/fsl_elbc_nand.c | 52 ++++++++++++++++++---------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 513897ce173e..423828ff68e6 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -730,24 +730,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->controller = &elbc_fcm_ctrl->controller; nand_set_controller_data(chip, priv); - chip->ecc.read_page = fsl_elbc_read_page; - chip->ecc.write_page = fsl_elbc_write_page; - chip->ecc.write_subpage = fsl_elbc_write_subpage; - - /* If CS Base Register selects full hardware ECC then use it */ - if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == - BR_DECC_CHK_GEN) { - chip->ecc.mode = NAND_ECC_HW; - mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); - chip->ecc.size = 512; - chip->ecc.bytes = 3; - chip->ecc.strength = 1; - } else { - /* otherwise fall back to default software ECC */ - chip->ecc.mode = NAND_ECC_SOFT; - chip->ecc.algo = NAND_ECC_HAMMING; - } - return 0; } @@ -759,6 +741,40 @@ static int fsl_elbc_attach_chip(struct nand_chip *chip) struct fsl_lbc_regs __iomem *lbc = ctrl->regs; unsigned int al; + switch (chip->ecc.mode) { + /* + * if ECC was not chosen in DT, decide whether to use HW or SW ECC from + * CS Base Register + */ + case NAND_ECC_NONE: + /* If CS Base Register selects full hardware ECC then use it */ + if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == + BR_DECC_CHK_GEN) { + chip->ecc.read_page = fsl_elbc_read_page; + chip->ecc.write_page = fsl_elbc_write_page; + chip->ecc.write_subpage = fsl_elbc_write_subpage; + + chip->ecc.mode = NAND_ECC_HW; + mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); + chip->ecc.size = 512; + chip->ecc.bytes = 3; + chip->ecc.strength = 1; + } else { + /* otherwise fall back to default software ECC */ + chip->ecc.mode = NAND_ECC_SOFT; + chip->ecc.algo = NAND_ECC_HAMMING; + } + break; + + /* if SW ECC was chosen in DT, we do not need to set anything here */ + case NAND_ECC_SOFT: + break; + + /* should we also implement NAND_ECC_HW to do as the code above? */ + default: + return -EINVAL; + } + /* calculate FMR Address Length field */ al = 0; if (chip->pagemask & 0xffff0000) -- 2.30.2