diff options
author | Stefan Agner | 2018-06-22 18:06:18 +0200 |
---|---|---|
committer | Stefano Babic | 2018-06-27 09:07:55 +0200 |
commit | 627544506f5709bb2d14f0db66661a27cd78ec0a (patch) | |
tree | 73efc9966be76585343913bfdb14c428885d121d | |
parent | f75e83bfae2bcf36197e25b8b3d539b0652b83fa (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.c | 44 |
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; |