diff options
author | Marek BehĂșn <marek.behun@nic.cz> | 2019-03-22 14:26:19 +0100 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2019-04-18 08:54:02 +0200 |
commit | f6424c22aa3673a0313a306be339495c67c41891 (patch) | |
tree | 1f9c7bcdcd26b01f4a4e7b0cb0a16794f8529f8c /drivers/mtd/nand/raw/fsl_elbc_nand.c | |
parent | 070fb9744d5b7f893da263149a4f3245bb618bdf (diff) |
mtd: rawnand: fsl_elbc: Make SW ECC work
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 <marek.behun@nic.cz>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Diffstat (limited to 'drivers/mtd/nand/raw/fsl_elbc_nand.c')
-rw-r--r-- | drivers/mtd/nand/raw/fsl_elbc_nand.c | 52 |
1 files 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) |