Commit 7fd130f7 authored by Miquel Raynal's avatar Miquel Raynal

mtd: rawnand: marvell: support 8b/512B strength for 2kiB pages layout

Add support for the layout used by 2kiB page NAND chips requesting at
least 8-bit of correction per 512 bytes. This layout requires a bit of
handling as:
1/ It can only fit if the NAND chip has at least 128 OOB bytes.
2/ The Bad Block Markers are located in the middle of the data bytes
   and shall not be used.
3/ It has been experimentally observed that, for certain layouts, the ECC
   engine tries to correct data while it should not because the errors
   are uncorrectable. While this is harmless for truly bad pages, it
   creates bitflips in empty pages. To avoid such scenario that
   augments artificially the number of bitflips we re-read in raw mode
   the entire page instead of just the ECC bytes. This is done only
   for this layout to avoid an unneeded penalty with other setups.
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: default avatarBoris Brezillon <boris.brezillon@bootlin.com>
parent dbfc6718
...@@ -284,6 +284,7 @@ static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = { ...@@ -284,6 +284,7 @@ static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = {
MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0), MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0),
MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0), MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0),
MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0), MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0),
MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30),
MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0), MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0),
MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30), MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30),
}; };
...@@ -1348,9 +1349,11 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, ...@@ -1348,9 +1349,11 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip,
* page is empty. In this case, it is normal that the ECC check failed * page is empty. In this case, it is normal that the ECC check failed
* and we just ignore the error. * and we just ignore the error.
* *
* However, for any subpage read error reported by ->correct(), the ECC * However, it has been empirically observed that for some layouts (e.g
* bytes must be read in raw mode and the full subpage must be checked * 2k page, 8b strength per 512B chunk), the controller tries to correct
* to see if it is entirely empty of if there was an actual error. * bits and may create itself bitflips in the erased area. To overcome
* this strange behavior, the whole page is re-read in raw mode, not
* only the ECC bytes.
*/ */
for (chunk = 0; chunk < lt->nchunks; chunk++) { for (chunk = 0; chunk < lt->nchunks; chunk++) {
int data_off_in_page, spare_off_in_page, ecc_off_in_page; int data_off_in_page, spare_off_in_page, ecc_off_in_page;
...@@ -1383,6 +1386,21 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, ...@@ -1383,6 +1386,21 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip,
ecc_len = chunk < lt->full_chunk_cnt ? lt->ecc_bytes : ecc_len = chunk < lt->full_chunk_cnt ? lt->ecc_bytes :
lt->last_ecc_bytes; lt->last_ecc_bytes;
/*
* Only re-read the ECC bytes, unless we are using the 2k/8b
* layout which is buggy in the sense that the ECC engine will
* try to correct data bytes anyway, creating bitflips. In this
* case, re-read the entire page.
*/
if (lt->writesize == 2048 && lt->strength == 8) {
nand_change_read_column_op(chip, data_off_in_page,
buf + data_off, data_len,
false);
nand_change_read_column_op(chip, spare_off_in_page,
chip->oob_poi + spare_off, spare_len,
false);
}
nand_change_read_column_op(chip, ecc_off_in_page, nand_change_read_column_op(chip, ecc_off_in_page,
chip->oob_poi + ecc_off, ecc_len, chip->oob_poi + ecc_off, ecc_len,
false); false);
...@@ -2166,6 +2184,16 @@ static int marvell_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, ...@@ -2166,6 +2184,16 @@ static int marvell_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
return -ENOTSUPP; return -ENOTSUPP;
} }
/* Special care for the layout 2k/8-bit/512B */
if (l->writesize == 2048 && l->strength == 8) {
if (mtd->oobsize < 128) {
dev_err(nfc->dev, "Requested layout needs at least 128 OOB bytes\n");
return -ENOTSUPP;
} else {
chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
}
}
mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops); mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops);
ecc->steps = l->nchunks; ecc->steps = l->nchunks;
ecc->size = l->data_bytes; ecc->size = l->data_bytes;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment