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
1 changed files with 69 additions and 1 deletions
|
@ -139,6 +139,74 @@ const struct mtd_ooblayout_ops 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,
|
||||
loff_t ofs, uint64_t len)
|
||||
{
|
||||
|
@ -4559,7 +4627,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||
break;
|
||||
case 64:
|
||||
case 128:
|
||||
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
|
||||
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "No oob scheme defined for oobsize %d\n",
|
||||
|
|
Loading…
Reference in a new issue