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>
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index 99f392e..e334181 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_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 @@
 		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)
@@ -961,6 +960,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;
 }
 
@@ -980,14 +1001,9 @@
 	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;