mtd: rawnand: davinci: add ROM supported OOB layout

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>
This commit is contained in:
Marcus Folkesson
2025-01-09 08:58:31 +01:00
committed by Miquel Raynal
parent 6df2d9553e
commit d0b806fc99

View 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;
}