mtd: nand: add ooblayout for old hamming layout
The old 1-bit hamming layout requires ECC data to be placed at a
fixed offset, and not necessarily at the end of the OOB area.
Add this old layout back in order to fix legacy setups.
Fixes: 41b207a70d
("mtd: nand: implement the default mtd_ooblayout_ops")
Cc: <stable@vger.kernel.org>
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
This commit is contained in:
parent
b98e1995e4
commit
6a623e0769
|
@ -139,6 +139,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
|
||||||
|
.ecc = nand_ooblayout_ecc_lp_hamming,
|
||||||
|
.free = nand_ooblayout_free_lp_hamming,
|
||||||
|
};
|
||||||
|
|
||||||
static int check_offs_len(struct mtd_info *mtd,
|
static int check_offs_len(struct mtd_info *mtd,
|
||||||
loff_t ofs, uint64_t len)
|
loff_t ofs, uint64_t len)
|
||||||
{
|
{
|
||||||
|
@ -4559,7 +4627,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
case 128:
|
case 128:
|
||||||
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
|
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN(1, "No oob scheme defined for oobsize %d\n",
|
WARN(1, "No oob scheme defined for oobsize %d\n",
|
||||||
|
|
Loading…
Reference in New Issue