@@ -238,9 +238,14 @@ static void gpmi_dump_info(struct gpmi_nand_data *this)
geo->block_mark_bit_offset);
}
-static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
+static bool gpmi_check_ecc(struct gpmi_nand_data *this)
{
+ struct nand_chip *chip = &this->nand;
+ struct mtd_info *mtd = nand_to_mtd(&this->nand);
struct bch_geometry *geo = &this->bch_geometry;
+ const struct nand_ecc_props *requirements =
+ nanddev_get_ecc_requirements(&chip->base);
+ int corr, ds_corr;
/* Do the sanity check. */
if (GPMI_IS_MXS(this)) {
@@ -248,7 +253,22 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
if (geo->gf_len == 14)
return false;
}
- return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
+
+ if (geo->ecc_strength > this->devdata->bch_max_ecc_strength)
+ return false;
+
+ /* check ecc strength, same as nand_ecc_is_strong_enough() did */
+ if (requirements->step_size) {
+ corr = mtd->writesize * geo->ecc_strength /
+ geo->ecc_chunk_size;
+ ds_corr = mtd->writesize * requirements->strength /
+ requirements->step_size;
+ if (corr < ds_corr ||
+ geo->ecc_strength < requirements->strength)
+ return false;
+ }
+
+ return true;
}
/*
@@ -514,24 +534,32 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
static int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
struct nand_chip *chip = &this->nand;
+ struct mtd_info *mtd = nand_to_mtd(&this->nand);
const struct nand_ecc_props *requirements =
nanddev_get_ecc_requirements(&chip->base);
+ bool use_minimun_ecc;
+ int err;
- if (chip->ecc.strength > 0 && chip->ecc.size > 0)
- return set_geometry_by_ecc_info(this, chip->ecc.strength,
- chip->ecc.size);
-
- if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
- || legacy_set_geometry(this)) {
- if (!(requirements->strength > 0 && requirements->step_size > 0))
- return -EINVAL;
+ use_minimun_ecc = of_property_read_bool(this->dev->of_node,
+ "fsl,use-minimum-ecc");
- return set_geometry_by_ecc_info(this,
- requirements->strength,
- requirements->step_size);
+ /* use legacy bch geometry settings by default*/
+ if ((!use_minimun_ecc && mtd->oobsize < 1024) ||
+ !(requirements->strength > 0 && requirements->step_size > 0)) {
+ dev_dbg(this->dev, "use legacy bch geometry\n");
+ err = legacy_set_geometry(this);
+ if (!err)
+ return 0;
}
- return 0;
+ /* otherwise use the minimum ecc nand chip required */
+ dev_dbg(this->dev, "use minimum ecc bch geometry\n");
+ err = set_geometry_by_ecc_info(this, requirements->strength,
+ requirements->step_size);
+ if (err)
+ dev_err(this->dev, "none of the bch geometry setting works\n");
+
+ return err;
}
/* Configures the geometry for BCH. */