aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Agner2018-06-22 18:06:18 +0200
committerStefano Babic2018-06-27 09:07:55 +0200
commit627544506f5709bb2d14f0db66661a27cd78ec0a (patch)
tree73efc9966be76585343913bfdb14c428885d121d
parentf75e83bfae2bcf36197e25b8b3d539b0652b83fa (diff)
mtd: nand: mxs_nand: add support for specific ECC strength
Add support for specified ECC strength/size using device tree properties nand-ecc-strength/nand-ecc-step-size. This aligns behavior with the mainline driver, such that: - If fsl,use-minimal-ecc is requested it will use data from data sheet/ONFI. If this is not available the driver will fail. - If nand-ecc-strength/nand-ecc-step-size are specified those value will be used. - By default maximum possible ECC strength is used Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
-rw-r--r--drivers/mtd/nand/mxs_nand.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index 99f392ef5cb..e3341812a20 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -161,15 +161,14 @@ static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
}
static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
- struct mtd_info *mtd)
+ struct mtd_info *mtd,
+ unsigned int ecc_strength,
+ unsigned int ecc_step)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
- if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
- return -ENOTSUPP;
-
- switch (chip->ecc_step_ds) {
+ switch (ecc_step) {
case SZ_512:
geo->gf_len = 13;
break;
@@ -180,8 +179,8 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
return -EINVAL;
}
- geo->ecc_chunk_size = chip->ecc_step_ds;
- geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
+ geo->ecc_chunk_size = ecc_step;
+ geo->ecc_strength = round_up(ecc_strength, 2);
/* Keep the C >= O */
if (geo->ecc_chunk_size < mtd->oobsize)
@@ -964,6 +963,28 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
return 0;
}
+static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+
+ if (chip->ecc.strength > 0 && chip->ecc.size > 0)
+ return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
+ chip->ecc.strength, chip->ecc.size);
+
+ if (nand_info->use_minimum_ecc ||
+ mxs_nand_calc_ecc_layout(geo, mtd)) {
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+ return -EINVAL;
+
+ return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
+ chip->ecc_strength_ds, chip->ecc_step_ds);
+ }
+
+ return 0;
+}
+
/*
* At this point, the physical NAND Flash chips have been identified and
* counted, so we know the physical geometry. This enables us to make some
@@ -980,14 +1001,9 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
struct bch_geometry *geo = &nand_info->bch_geometry;
struct mxs_bch_regs *bch_regs = nand_info->bch_regs;
uint32_t tmp;
- int ret = -ENOTSUPP;
-
- if (nand_info->use_minimum_ecc)
- ret = mxs_nand_calc_ecc_layout_by_info(geo, mtd);
-
- if (ret == -ENOTSUPP)
- ret = mxs_nand_calc_ecc_layout(geo, mtd);
+ int ret;
+ ret = mxs_nand_set_geometry(mtd, geo);
if (ret)
return ret;