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>
This commit is contained in:
Marek Behún 2019-03-22 14:26:19 +01:00 committed by Miquel Raynal
parent 070fb9744d
commit f6424c22aa

View file

@ -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)