mtd: rawnand: Use the ECC framework OOB layouts
authorMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 27 Aug 2020 08:52:05 +0000 (10:52 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Wed, 30 Sep 2020 14:43:52 +0000 (16:43 +0200)
No need to have our own in the raw NAND core.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200827085208.16276-18-miquel.raynal@bootlin.com
drivers/mtd/nand/raw/arasan-nand-controller.c
drivers/mtd/nand/raw/atmel/nand-controller.c
drivers/mtd/nand/raw/davinci_nand.c
drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_bch.c
drivers/mtd/nand/raw/nand_toshiba.c
drivers/mtd/nand/raw/vf610_nfc.c
include/linux/mtd/rawnand.h

index 006bc3d..fbb4ea7 100644 (file)
@@ -980,7 +980,7 @@ static int anfc_init_hw_ecc_controller(struct arasan_nfc *nfc,
                return -EINVAL;
        }
 
-       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+       mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
 
        ecc->steps = mtd->writesize / ecc->size;
        ecc->algo = NAND_ECC_ALGO_BCH;
index 3d162fd..7fcc5e6 100644 (file)
@@ -1108,7 +1108,7 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
 
        chip->options |= NAND_NO_SUBPAGE_WRITE;
 
-       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+       mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
 
        return 0;
 }
index 58966a9..427f320 100644 (file)
@@ -645,7 +645,8 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
                                mtd_set_ooblayout(mtd,
                                                  &hwecc4_small_ooblayout_ops);
                        } else if (chunks == 4 || chunks == 8) {
-                               mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+                               mtd_set_ooblayout(mtd,
+                                                 nand_get_large_page_ooblayout());
                                info->chip.ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
                        } else {
                                return -EIO;
index 70309f1..0e9d426 100644 (file)
@@ -243,8 +243,10 @@ static int ingenic_nand_attach_chip(struct nand_chip *chip)
        /* For legacy reasons we use a different layout on the qi,lb60 board. */
        if (of_machine_is_compatible("qi,lb60"))
                mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
-       else
+       else if (nfc->soc_info->oob_layout)
                mtd_set_ooblayout(mtd, nfc->soc_info->oob_layout);
+       else
+               mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
 
        return 0;
 }
@@ -532,7 +534,6 @@ static const struct jz_soc_info jz4740_soc_info = {
        .data_offset = 0x00000000,
        .cmd_offset = 0x00008000,
        .addr_offset = 0x00010000,
-       .oob_layout = &nand_ooblayout_lp_ops,
 };
 
 static const struct jz_soc_info jz4725b_soc_info = {
@@ -546,7 +547,6 @@ static const struct jz_soc_info jz4780_soc_info = {
        .data_offset = 0x00000000,
        .cmd_offset = 0x00400000,
        .addr_offset = 0x00800000,
-       .oob_layout = &nand_ooblayout_lp_ops,
 };
 
 static const struct of_device_id ingenic_nand_dt_match[] = {
index 2c102ae..4b41de5 100644 (file)
 
 #include "internals.h"
 
-/* Define default oob placement schemes for large and small page devices */
-static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
-                                struct mtd_oob_region *oobregion)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-       if (section > 1)
-               return -ERANGE;
-
-       if (!section) {
-               oobregion->offset = 0;
-               if (mtd->oobsize == 16)
-                       oobregion->length = 4;
-               else
-                       oobregion->length = 3;
-       } else {
-               if (mtd->oobsize == 8)
-                       return -ERANGE;
-
-               oobregion->offset = 6;
-               oobregion->length = ecc->total - 4;
-       }
-
-       return 0;
-}
-
-static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section,
-                                 struct mtd_oob_region *oobregion)
-{
-       if (section > 1)
-               return -ERANGE;
-
-       if (mtd->oobsize == 16) {
-               if (section)
-                       return -ERANGE;
-
-               oobregion->length = 8;
-               oobregion->offset = 8;
-       } else {
-               oobregion->length = 2;
-               if (!section)
-                       oobregion->offset = 3;
-               else
-                       oobregion->offset = 6;
-       }
-
-       return 0;
-}
-
-const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = {
-       .ecc = nand_ooblayout_ecc_sp,
-       .free = nand_ooblayout_free_sp,
-};
-EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops);
-
-static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
-                                struct mtd_oob_region *oobregion)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-       if (section || !ecc->total)
-               return -ERANGE;
-
-       oobregion->length = ecc->total;
-       oobregion->offset = mtd->oobsize - oobregion->length;
-
-       return 0;
-}
-
-static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
-                                 struct mtd_oob_region *oobregion)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-       if (section)
-               return -ERANGE;
-
-       oobregion->length = mtd->oobsize - ecc->total - 2;
-       oobregion->offset = 2;
-
-       return 0;
-}
-
-const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
-       .ecc = nand_ooblayout_ecc_lp,
-       .free = nand_ooblayout_free_lp,
-};
-EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
-
-/*
- * Support the old "large page" layout used for 1-bit Hamming ECC where ECC
- * are placed at a fixed offset.
- */
-static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
-                                        struct mtd_oob_region *oobregion)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-       if (section)
-               return -ERANGE;
-
-       switch (mtd->oobsize) {
-       case 64:
-               oobregion->offset = 40;
-               break;
-       case 128:
-               oobregion->offset = 80;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       oobregion->length = ecc->total;
-       if (oobregion->offset + oobregion->length > mtd->oobsize)
-               return -ERANGE;
-
-       return 0;
-}
-
-static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
-                                         struct mtd_oob_region *oobregion)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct nand_ecc_ctrl *ecc = &chip->ecc;
-       int ecc_offset = 0;
-
-       if (section < 0 || section > 1)
-               return -ERANGE;
-
-       switch (mtd->oobsize) {
-       case 64:
-               ecc_offset = 40;
-               break;
-       case 128:
-               ecc_offset = 80;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (section == 0) {
-               oobregion->offset = 2;
-               oobregion->length = ecc_offset - 2;
-       } else {
-               oobregion->offset = ecc_offset + ecc->total;
-               oobregion->length = mtd->oobsize - oobregion->offset;
-       }
-
-       return 0;
-}
-
-static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
-       .ecc = nand_ooblayout_ecc_lp_hamming,
-       .free = nand_ooblayout_free_lp_hamming,
-};
-
 static int nand_pairing_dist3_get_info(struct mtd_info *mtd, int page,
                                       struct mtd_pairing_info *info)
 {
@@ -5372,7 +5212,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
                                return -EINVAL;
                        }
 
-                       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+                       mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
 
                }
 
@@ -5381,7 +5221,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
                 * used, otherwise we don't know how many bytes can really be
                 * used.
                 */
-               if (mtd->ooblayout == &nand_ooblayout_lp_ops &&
+               if (mtd->ooblayout == nand_get_large_page_ooblayout() &&
                    ecc->options & NAND_ECC_MAXIMIZE) {
                        int steps, bytes;
 
@@ -5783,11 +5623,12 @@ static int nand_scan_tail(struct nand_chip *chip)
                switch (mtd->oobsize) {
                case 8:
                case 16:
-                       mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops);
+                       mtd_set_ooblayout(mtd, nand_get_small_page_ooblayout());
                        break;
                case 64:
                case 128:
-                       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
+                       mtd_set_ooblayout(mtd,
+                                         nand_get_large_page_hamming_ooblayout());
                        break;
                default:
                        /*
@@ -5799,7 +5640,7 @@ static int nand_scan_tail(struct nand_chip *chip)
                         */
                        if (ecc->engine_type == NAND_ECC_ENGINE_TYPE_NONE) {
                                mtd_set_ooblayout(mtd,
-                                               &nand_ooblayout_lp_ops);
+                                                 nand_get_large_page_ooblayout());
                                break;
                        }
 
@@ -5954,7 +5795,10 @@ static int nand_scan_tail(struct nand_chip *chip)
                ret = -EINVAL;
                goto err_nand_manuf_cleanup;
        }
+
        ecc->total = ecc->steps * ecc->bytes;
+       chip->base.ecc.ctx.total = ecc->total;
+
        if (ecc->total > mtd->oobsize) {
                WARN(1, "Total number of ECC bytes exceeded oobsize\n");
                ret = -EINVAL;
index d5af8c5..9d19ac1 100644 (file)
@@ -165,6 +165,7 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
         */
        nand->ecc.steps = eccsteps;
        nand->ecc.total = eccsteps * eccbytes;
+       nand->base.ecc.ctx.total = nand->ecc.total;
        if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) {
                pr_warn("invalid ecc layout\n");
                goto fail;
index fb66623..cf4f379 100644 (file)
@@ -140,7 +140,7 @@ static void toshiba_nand_benand_init(struct nand_chip *chip)
 
        chip->options |= NAND_SUBPAGE_READ;
 
-       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+       mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
 }
 
 static void toshiba_nand_decode_id(struct nand_chip *chip)
index 8ee2c1f..50dc0c9 100644 (file)
@@ -779,7 +779,7 @@ static int vf610_nfc_attach_chip(struct nand_chip *chip)
                mtd->oobsize = 64;
 
        /* Use default large page ECC layout defined in NAND core */
-       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+       mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
        if (chip->ecc.strength == 32) {
                nfc->ecc_mode = ECC_60_BYTE;
                chip->ecc.bytes = 60;
index 967b616..1bbce6f 100644 (file)
@@ -14,6 +14,7 @@
 #define __LINUX_MTD_RAWNAND_H
 
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/flashchip.h>
 #include <linux/mtd/bbm.h>
 #include <linux/mtd/jedec.h>
@@ -1156,9 +1157,6 @@ struct nand_chip {
        void *priv;
 };
 
-extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
-extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops;
-
 static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
 {
        return container_of(mtd, struct nand_chip, base.mtd);