diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c index 748056a43e..ee5d7fde9c 100644 --- a/drivers/mtd/nand/raw/mxs_nand.c +++ b/drivers/mtd/nand/raw/mxs_nand.c @@ -195,6 +195,7 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo, struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(chip); unsigned int block_mark_bit_offset; + int corr, ds_corr; /* The default for the length of Galois Field. */ geo->gf_len = 13; @@ -225,6 +226,17 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo, geo->ecc_strength = min(round_down(geo->ecc_strength, 2), nand_info->max_ecc_strength_supported); + /* check ecc strength, same as nand_ecc_is_strong_enough() did*/ + if (chip->ecc_step_ds) { + corr = mtd->writesize * geo->ecc_strength / + geo->ecc_chunkn_size; + ds_corr = mtd->writesize * chip->ecc_strength_ds / + chip->ecc_step_ds; + if (corr < ds_corr || + geo->ecc_strength < chip->ecc_strength_ds) + return -EINVAL; + } + block_mark_bit_offset = mtd->writesize * 8 - (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1) + MXS_NAND_METADATA_SIZE * 8); @@ -1111,6 +1123,7 @@ 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); + int err; if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) { printf("unsupported NAND chip, minimum ecc required %d\n" @@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo) return -EINVAL; } - if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) && - mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) { - dev_warn(mtd->dev, "use legacy bch geometry\n"); - return mxs_nand_legacy_calc_ecc_layout(geo, mtd); + /* use the legacy bch setting by default */ + if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) || + !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) { + dev_dbg(mtd->dev, "use legacy bch geometry\n"); + err = mxs_nand_legacy_calc_ecc_layout(geo, mtd); + if (!err) + return 0; } - if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize) - return mxs_nand_calc_ecc_for_large_oob(geo, mtd); + /* for large oob nand */ + if (mtd->oobsize > 1024) { + dev_dbg(mtd->dev, "use large oob bch geometry\n"); + err = mxs_nand_calc_ecc_for_large_oob(geo, mtd); + if (!err) + return 0; + } - return mxs_nand_calc_ecc_layout_by_info(geo, mtd, - chip->ecc_strength_ds, chip->ecc_step_ds); + /* otherwise use the minimum ecc nand chips required */ + dev_dbg(mtd->dev, "use minimum ecc bch geometry\n"); + err = mxs_nand_calc_ecc_layout_by_info(geo, mtd, chip->ecc_strength_ds, + chip->ecc_step_ds); - return 0; + if (err) + dev_err(mtd->dev, "none of the bch geometry setting works\n"); + + return err; +} + +void mxs_nand_dump_geo(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct mxs_nand_info *nand_info = nand_get_controller_data(nand); + struct bch_geometry *geo = &nand_info->bch_geometry; + + dev_dbg(mtd->dev, "BCH Geometry :\n" + "GF Length\t\t: %u\n" + "ECC Strength\t\t: %u\n" + "ECC for Meta\t\t: %u\n" + "ECC Chunk0 Size\t\t: %u\n" + "ECC Chunkn Size\t\t: %u\n" + "ECC Chunk Count\t\t: %u\n" + "Block Mark Byte Offset\t: %u\n" + "Block Mark Bit Offset\t: %u\n", + geo->gf_len, + geo->ecc_strength, + geo->ecc_for_meta, + geo->ecc_chunk0_size, + geo->ecc_chunkn_size, + geo->ecc_chunk_count, + geo->block_mark_byte_offset, + geo->block_mark_bit_offset); } /* @@ -1159,6 +1210,8 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd) if (ret) return ret; + mxs_nand_dump_geo(mtd); + /* Configure BCH and set NFC geometry */ mxs_reset_block(&bch_regs->hw_bch_ctrl_reg); diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c index 878796d555..b9833a646f 100644 --- a/drivers/mtd/nand/raw/mxs_nand_dt.c +++ b/drivers/mtd/nand/raw/mxs_nand_dt.c @@ -92,8 +92,6 @@ static int mxs_nand_dt_probe(struct udevice *dev) info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc"); - info->legacy_bch_geometry = dev_read_bool(dev, "fsl,legacy-bch-geometry"); - if (IS_ENABLED(CONFIG_CLK) && IS_ENABLED(CONFIG_IMX8)) { /* Assigned clock already set clock */ struct clk gpmi_clk; diff --git a/include/mxs_nand.h b/include/mxs_nand.h index 66c909318d..741dc8734e 100644 --- a/include/mxs_nand.h +++ b/include/mxs_nand.h @@ -44,8 +44,6 @@ struct mxs_nand_info { struct udevice *dev; unsigned int max_ecc_strength_supported; bool use_minimum_ecc; - /* legacy bch geometry flag */ - bool legacy_bch_geometry; int cur_chip; uint32_t cmd_queue_len;