]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mtd: rawnand: davinci: add ROM supported OOB layout
authorMarcus Folkesson <marcus.folkesson@combitech.com>
Thu, 9 Jan 2025 07:58:31 +0000 (08:58 +0100)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Wed, 15 Jan 2025 18:07:19 +0000 (19:07 +0100)
Add support for the OOB layout used by the ROM bootloader.
The same layout is used by both Keystone [1] and OMAPL138/DA850 [2]
which currently is the only users of davinci-nand.

Only select this layout if the `nand-is-boot-medium` property is set.
This to avoid breaking any existing devices out there.

[1] https://www.ti.com/lit/ug/spruhj3/spruhj3.pdf
[2] https://www.ti.com/lit/an/sprab41f/sprab41f.pdf

Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
drivers/mtd/nand/raw/davinci_nand.c

index ee87ca669c92fa2dc25dea1b5b908abc08508468..3986553881d0e5ff56e4350880edc983b877e0a5 100644 (file)
@@ -488,6 +488,44 @@ static const struct mtd_ooblayout_ops hwecc4_small_ooblayout_ops = {
        .free = hwecc4_ooblayout_small_free,
 };
 
+static int hwecc4_ooblayout_large_ecc(struct mtd_info *mtd, int section,
+                                      struct mtd_oob_region *oobregion)
+{
+       struct nand_device *nand = mtd_to_nanddev(mtd);
+       unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+       int nregions = total_ecc_bytes / 10; /* 10 bytes per chunk */
+
+       if (section >= nregions)
+               return -ERANGE;
+
+       oobregion->offset = (section * 16) + 6;
+       oobregion->length = 10;
+
+       return 0;
+}
+
+static int hwecc4_ooblayout_large_free(struct mtd_info *mtd, int section,
+                                      struct mtd_oob_region *oobregion)
+{
+       struct nand_device *nand = mtd_to_nanddev(mtd);
+       unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+       int nregions = total_ecc_bytes / 10; /* 10 bytes per chunk */
+
+       /* First region is used for BBT */
+       if (section >= (nregions - 1))
+               return -ERANGE;
+
+       oobregion->offset = ((section + 1) * 16);
+       oobregion->length = 6;
+
+       return 0;
+}
+
+static const struct mtd_ooblayout_ops hwecc4_large_ooblayout_ops = {
+       .ecc = hwecc4_ooblayout_large_ecc,
+       .free = hwecc4_ooblayout_large_free,
+};
+
 #if defined(CONFIG_OF)
 static const struct of_device_id davinci_nand_of_match[] = {
        {.compatible = "ti,davinci-nand", },
@@ -650,9 +688,12 @@ 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_get_large_page_ooblayout());
                                chip->ecc.read_page = nand_read_page_hwecc_oob_first;
+
+                               if (chip->options & NAND_IS_BOOT_MEDIUM)
+                                       mtd_set_ooblayout(mtd, &hwecc4_large_ooblayout_ops);
+                               else
+                                       mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());
                        } else {
                                return -EIO;
                        }