summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorMarek BehĂșn <marek.behun@nic.cz>2019-03-22 14:26:19 +0100
committerMiquel Raynal <miquel.raynal@bootlin.com>2019-04-18 08:54:02 +0200
commitf6424c22aa3673a0313a306be339495c67c41891 (patch)
tree1f9c7bcdcd26b01f4a4e7b0cb0a16794f8529f8c /drivers/mtd/nand
parent070fb9744d5b7f893da263149a4f3245bb618bdf (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')
-rw-r--r--drivers/mtd/nand/raw/fsl_elbc_nand.c52
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)