+ struct nand_chip *chip = mtd_to_nand(mtd);
+
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+ return -ENOTSUPP;
+
+ switch (chip->ecc_step_ds) {
+ case SZ_512:
+ geo->gf_len = 13;
+ break;
+ case SZ_1K:
+ geo->gf_len = 14;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ geo->ecc_chunk_size = chip->ecc_step_ds;
+ geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
+
+ /* Keep the C >= O */
+ if (geo->ecc_chunk_size < mtd->oobsize)
+ return -EINVAL;
+
+ if (geo->ecc_strength > mxs_nand_max_ecc_strength_supported())
+ return -EINVAL;
+
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+
+ return 0;
+}
+
+static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
+ struct mtd_info *mtd)
+{
+ /* The default for the length of Galois Field. */
+ geo->gf_len = 13;
+
+ /* The default for chunk size. */
+ geo->ecc_chunk_size = 512;
+
+ if (geo->ecc_chunk_size < mtd->oobsize) {
+ geo->gf_len = 14;
+ geo->ecc_chunk_size *= 2;
+ }
+
+ if (mtd->oobsize > geo->ecc_chunk_size) {
+ printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
+ geo->ecc_chunk_size);
+ return -EINVAL;
+ }
+
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+
+ /*
+ * Determine the ECC layout with the formula:
+ * ECC bits per chunk = (total page spare data bits) /
+ * (bits per ECC level) / (chunks per page)
+ * where:
+ * total page spare data bits =
+ * (page oob size - meta data size) * (bits per byte)
+ */
+ geo->ecc_strength = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
+ / (geo->gf_len * geo->ecc_chunk_count);
+
+ geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
+ mxs_nand_max_ecc_strength_supported());
+
+ return 0;