[PATCH] mtd: nand: pxa3xx: simplify ECC hardware parameters

Replace the if/else chain in pxa_ecc_init() with a lookup table. This makes the code more concise and hopefully easier to follow. Remove the unused ecc_layout tables and replace it with a single dummy one (the pxa3xx driver has never used this but the mtd subsystem expects it to be provided).
Tested on an Allied Telesis x530 switch with Micron MT29F2G08ABAEAWP NAND Flash.
Signed-off-by: Chris Packham judge.packham@gmail.com --- This code was taken from the Marvell SDK for the AC5/AC5X integrated switch/CPU. There are other changes to support the SoC which I will likely attempt to upstream soon but I think this stands on it's own merit as a nice clean up.
Reports of testing on other combinations of hardware would be greatly appreciated.
drivers/mtd/nand/raw/pxa3xx_nand.c | 247 ++++++++--------------------- 1 file changed, 68 insertions(+), 179 deletions(-)
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 9c29e8a6c214..fcd1b9c63614 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -330,89 +330,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { }; #endif
-static struct nand_ecclayout ecc_layout_2KB_bch4bit = { - .eccbytes = 32, - .eccpos = { - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63}, - .oobfree = { {2, 30} } +struct marvell_hw_ecc_layout { + int page_size; + int strength; + unsigned int ecc_size; + unsigned int nfullchunks; + unsigned int chunk_size; + unsigned int spare_size; + unsigned int last_chunk_size; + unsigned int last_spare_size; };
-static struct nand_ecclayout ecc_layout_2KB_bch8bit = { - .eccbytes = 64, - .eccpos = { - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95}, - .oobfree = { {1, 4}, {6, 26} } +static const struct marvell_hw_ecc_layout nfc_layouts[] = { + /* page_size strength ecc_size nfullchunks chunk_size spare_size last_chunk last_spare */ + { 512, 1, 8, 1, 512, 8, 0, 0 }, + { 2048, 1, 24, 1, 2048, 40, 0, 0 }, + + { 2048, 4, 32, 1, 2048, 32, 0, 0 }, + { 2048, 8, 32, 1, 1024, 0, 1024, 32 }, + { 2048, 12, 32, 2, 704, 0, 640, 0 }, + { 2048, 16, 32, 4, 512, 0, 0, 32 }, + { 4096, 4, 32, 2, 2048, 32, 0, 0 }, + { 4096, 8, 32, 4, 1024, 0, 0, 64 }, + { 4096, 12, 32, 5, 704, 0, 576, 32 }, + { 4096, 16, 32, 8, 512, 0, 0, 32 }, + + { 8192, 4, 32, 4, 2048, 32, 0, 0 }, + { 8192, 8, 32, 8, 1024, 0, 0, 160 }, + { 8192, 12, 32, 11, 704, 0, 448, 64 }, + { 8192, 16, 32, 16, 512, 0, 0, 32 }, + { }, };
-static struct nand_ecclayout ecc_layout_4KB_bch4bit = { - .eccbytes = 64, - .eccpos = { - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}, - /* Bootrom looks in bytes 0 & 5 for bad blocks */ - .oobfree = { {6, 26}, { 64, 32} } -}; - -static struct nand_ecclayout ecc_layout_8KB_bch4bit = { - .eccbytes = 128, - .eccpos = { - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, - - 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, - - 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255}, - - /* Bootrom looks in bytes 0 & 5 for bad blocks */ - .oobfree = { {1, 4}, {6, 26}, { 64, 32}, {128, 32}, {192, 32} } -}; - -static struct nand_ecclayout ecc_layout_4KB_bch8bit = { - .eccbytes = 128, - .eccpos = { - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63}, +static struct nand_ecclayout ecc_layout_empty = { + .eccbytes = 0, + .eccpos = { }, .oobfree = { } };
-static struct nand_ecclayout ecc_layout_8KB_bch8bit = { - .eccbytes = 256, - .eccpos = {}, - /* HW ECC handles all ECC data and all spare area is free for OOB */ - .oobfree = {{0, 160} } -}; - #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11) @@ -1549,113 +1504,47 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, struct nand_ecc_ctrl *ecc, int strength, int ecc_stepsize, int page_size) { - if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { - info->nfullchunks = 1; - info->ntotalchunks = 1; - info->chunk_size = 2048; - info->spare_size = 40; - info->ecc_size = 24; - ecc->mode = NAND_ECC_HW; - ecc->size = 512; - ecc->strength = 1; + int i = 0;
- } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) { - info->nfullchunks = 1; - info->ntotalchunks = 1; - info->chunk_size = 512; - info->spare_size = 8; - info->ecc_size = 8; - ecc->mode = NAND_ECC_HW; - ecc->size = 512; - ecc->strength = 1; + /* if ecc strength is 1 ecc algo is Hamming else bch */ + info->ecc_bch = (strength == 1) ? 0 : 1;
- /* - * Required ECC: 4-bit correction per 512 bytes - * Select: 16-bit correction per 2048 bytes + ecc->mode = NAND_ECC_HW; + + /* ecc->layout is not in use for pxa driver (but shouldn't be NULL)*/ + if (info->ecc_bch == 1) + ecc->layout = &ecc_layout_empty; + + /* for bch actual ecc strength is 16 per chunk */ + ecc->strength = (info->ecc_bch == 1) ? 16 : 1; + + while (nfc_layouts[i].strength) { + if (strength == nfc_layouts[i].strength && page_size == nfc_layouts[i].page_size) { + info->nfullchunks = nfc_layouts[i].nfullchunks; + info->chunk_size = nfc_layouts[i].chunk_size; + info->spare_size = nfc_layouts[i].spare_size; + info->last_chunk_size = nfc_layouts[i].last_chunk_size; + info->last_spare_size = nfc_layouts[i].last_spare_size; + info->ntotalchunks = (info->last_spare_size || info->last_chunk_size) ? + info->nfullchunks + 1 : info->nfullchunks; + info->ecc_size = nfc_layouts[i].ecc_size; + break; + } + ++i; + } + + /* for bch the ecc is calculated per chunk size and for Hamming it is 512 */ + ecc->size = (info->ecc_bch) ? info->chunk_size : 512; + + /* nand_scan_tail func perform validity tests for ECC strength, and it + * assumes that all chunks are with same size. in our case when ecc is 12 + * the chunk size is 704 but the last chunk is with different size so + * we cheat it nand_scan_tail validity tests by set info->ecc_size value to 512 */ - } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) { - info->ecc_bch = 1; - info->nfullchunks = 1; - info->ntotalchunks = 1; - info->chunk_size = 2048; - info->spare_size = 32; - info->ecc_size = 32; - ecc->mode = NAND_ECC_HW; - ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_2KB_bch4bit; - ecc->strength = 16; + if (strength == 12) + ecc->size = 512;
- } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { - info->ecc_bch = 1; - info->nfullchunks = 2; - info->ntotalchunks = 2; - info->chunk_size = 2048; - info->spare_size = 32; - info->ecc_size = 32; - ecc->mode = NAND_ECC_HW; - ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_4KB_bch4bit; - ecc->strength = 16; - - } else if (strength == 4 && ecc_stepsize == 512 && page_size == 8192) { - info->ecc_bch = 1; - info->nfullchunks = 4; - info->ntotalchunks = 4; - info->chunk_size = 2048; - info->spare_size = 32; - info->ecc_size = 32; - ecc->mode = NAND_ECC_HW; - ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_8KB_bch4bit; - ecc->strength = 16; - - /* - * Required ECC: 8-bit correction per 512 bytes - * Select: 16-bit correction per 1024 bytes - */ - } else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) { - info->ecc_bch = 1; - info->nfullchunks = 1; - info->ntotalchunks = 2; - info->chunk_size = 1024; - info->spare_size = 0; - info->last_chunk_size = 1024; - info->last_spare_size = 32; - info->ecc_size = 32; - ecc->mode = NAND_ECC_HW; - ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_2KB_bch8bit; - ecc->strength = 16; - - } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) { - info->ecc_bch = 1; - info->nfullchunks = 4; - info->ntotalchunks = 5; - info->chunk_size = 1024; - info->spare_size = 0; - info->last_chunk_size = 0; - info->last_spare_size = 64; - info->ecc_size = 32; - ecc->mode = NAND_ECC_HW; - ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_4KB_bch8bit; - ecc->strength = 16; - - } else if (strength == 8 && ecc_stepsize == 512 && page_size == 8192) { - info->ecc_bch = 1; - info->nfullchunks = 8; - info->ntotalchunks = 9; - info->chunk_size = 1024; - info->spare_size = 0; - info->last_chunk_size = 0; - info->last_spare_size = 160; - info->ecc_size = 32; - ecc->mode = NAND_ECC_HW; - ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_8KB_bch8bit; - ecc->strength = 16; - - } else { + if (ecc_stepsize != 512 || !(nfc_layouts[i].strength)) { dev_err(info->controller.active->mtd.dev, "ECC strength %d at page size %d is not supported\n", strength, page_size);

Hi Chris,
On Thu, Aug 25, 2022 at 7:00 AM Chris Packham judge.packham@gmail.com wrote:
Replace the if/else chain in pxa_ecc_init() with a lookup table. This makes the code more concise and hopefully easier to follow. Remove the unused ecc_layout tables and replace it with a single dummy one (the pxa3xx driver has never used this but the mtd subsystem expects it to be provided).
These are two functional changes, so please split into two patches.
Thanks and regards, Dario
Tested on an Allied Telesis x530 switch with Micron MT29F2G08ABAEAWP NAND Flash.
Signed-off-by: Chris Packham judge.packham@gmail.com
This code was taken from the Marvell SDK for the AC5/AC5X integrated switch/CPU. There are other changes to support the SoC which I will likely attempt to upstream soon but I think this stands on it's own merit as a nice clean up.
Reports of testing on other combinations of hardware would be greatly appreciated.
drivers/mtd/nand/raw/pxa3xx_nand.c | 247 ++++++++--------------------- 1 file changed, 68 insertions(+), 179 deletions(-)
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 9c29e8a6c214..fcd1b9c63614 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -330,89 +330,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { }; #endif
-static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
.eccbytes = 32,
.eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63},
.oobfree = { {2, 30} }
+struct marvell_hw_ecc_layout {
int page_size;
int strength;
unsigned int ecc_size;
unsigned int nfullchunks;
unsigned int chunk_size;
unsigned int spare_size;
unsigned int last_chunk_size;
unsigned int last_spare_size;
};
-static struct nand_ecclayout ecc_layout_2KB_bch8bit = {
.eccbytes = 64,
.eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95},
.oobfree = { {1, 4}, {6, 26} }
+static const struct marvell_hw_ecc_layout nfc_layouts[] = {
/* page_size strength ecc_size nfullchunks chunk_size spare_size last_chunk last_spare */
{ 512, 1, 8, 1, 512, 8, 0, 0 },
{ 2048, 1, 24, 1, 2048, 40, 0, 0 },
{ 2048, 4, 32, 1, 2048, 32, 0, 0 },
{ 2048, 8, 32, 1, 1024, 0, 1024, 32 },
{ 2048, 12, 32, 2, 704, 0, 640, 0 },
{ 2048, 16, 32, 4, 512, 0, 0, 32 },
{ 4096, 4, 32, 2, 2048, 32, 0, 0 },
{ 4096, 8, 32, 4, 1024, 0, 0, 64 },
{ 4096, 12, 32, 5, 704, 0, 576, 32 },
{ 4096, 16, 32, 8, 512, 0, 0, 32 },
{ 8192, 4, 32, 4, 2048, 32, 0, 0 },
{ 8192, 8, 32, 8, 1024, 0, 0, 160 },
{ 8192, 12, 32, 11, 704, 0, 448, 64 },
{ 8192, 16, 32, 16, 512, 0, 0, 32 },
{ },
};
-static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
.eccbytes = 64,
.eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127},
/* Bootrom looks in bytes 0 & 5 for bad blocks */
.oobfree = { {6, 26}, { 64, 32} }
-};
-static struct nand_ecclayout ecc_layout_8KB_bch4bit = {
.eccbytes = 128,
.eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191,
224, 225, 226, 227, 228, 229, 230, 231,
232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255},
/* Bootrom looks in bytes 0 & 5 for bad blocks */
.oobfree = { {1, 4}, {6, 26}, { 64, 32}, {128, 32}, {192, 32} }
-};
-static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
.eccbytes = 128,
.eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63},
+static struct nand_ecclayout ecc_layout_empty = {
.eccbytes = 0,
.eccpos = { }, .oobfree = { }
};
-static struct nand_ecclayout ecc_layout_8KB_bch8bit = {
.eccbytes = 256,
.eccpos = {},
/* HW ECC handles all ECC data and all spare area is free for OOB */
.oobfree = {{0, 160} }
-};
#define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11) @@ -1549,113 +1504,47 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, struct nand_ecc_ctrl *ecc, int strength, int ecc_stepsize, int page_size) {
if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
info->nfullchunks = 1;
info->ntotalchunks = 1;
info->chunk_size = 2048;
info->spare_size = 40;
info->ecc_size = 24;
ecc->mode = NAND_ECC_HW;
ecc->size = 512;
ecc->strength = 1;
int i = 0;
} else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) {
info->nfullchunks = 1;
info->ntotalchunks = 1;
info->chunk_size = 512;
info->spare_size = 8;
info->ecc_size = 8;
ecc->mode = NAND_ECC_HW;
ecc->size = 512;
ecc->strength = 1;
/* if ecc strength is 1 ecc algo is Hamming else bch */
info->ecc_bch = (strength == 1) ? 0 : 1;
/*
* Required ECC: 4-bit correction per 512 bytes
* Select: 16-bit correction per 2048 bytes
ecc->mode = NAND_ECC_HW;
/* ecc->layout is not in use for pxa driver (but shouldn't be NULL)*/
if (info->ecc_bch == 1)
ecc->layout = &ecc_layout_empty;
/* for bch actual ecc strength is 16 per chunk */
ecc->strength = (info->ecc_bch == 1) ? 16 : 1;
while (nfc_layouts[i].strength) {
if (strength == nfc_layouts[i].strength && page_size == nfc_layouts[i].page_size) {
info->nfullchunks = nfc_layouts[i].nfullchunks;
info->chunk_size = nfc_layouts[i].chunk_size;
info->spare_size = nfc_layouts[i].spare_size;
info->last_chunk_size = nfc_layouts[i].last_chunk_size;
info->last_spare_size = nfc_layouts[i].last_spare_size;
info->ntotalchunks = (info->last_spare_size || info->last_chunk_size) ?
info->nfullchunks + 1 : info->nfullchunks;
info->ecc_size = nfc_layouts[i].ecc_size;
break;
}
++i;
}
/* for bch the ecc is calculated per chunk size and for Hamming it is 512 */
ecc->size = (info->ecc_bch) ? info->chunk_size : 512;
/* nand_scan_tail func perform validity tests for ECC strength, and it
* assumes that all chunks are with same size. in our case when ecc is 12
* the chunk size is 704 but the last chunk is with different size so
* we cheat it nand_scan_tail validity tests by set info->ecc_size value to 512 */
} else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) {
info->ecc_bch = 1;
info->nfullchunks = 1;
info->ntotalchunks = 1;
info->chunk_size = 2048;
info->spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_2KB_bch4bit;
ecc->strength = 16;
if (strength == 12)
ecc->size = 512;
} else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
info->ecc_bch = 1;
info->nfullchunks = 2;
info->ntotalchunks = 2;
info->chunk_size = 2048;
info->spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_4KB_bch4bit;
ecc->strength = 16;
} else if (strength == 4 && ecc_stepsize == 512 && page_size == 8192) {
info->ecc_bch = 1;
info->nfullchunks = 4;
info->ntotalchunks = 4;
info->chunk_size = 2048;
info->spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_8KB_bch4bit;
ecc->strength = 16;
/*
* Required ECC: 8-bit correction per 512 bytes
* Select: 16-bit correction per 1024 bytes
*/
} else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) {
info->ecc_bch = 1;
info->nfullchunks = 1;
info->ntotalchunks = 2;
info->chunk_size = 1024;
info->spare_size = 0;
info->last_chunk_size = 1024;
info->last_spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_2KB_bch8bit;
ecc->strength = 16;
} else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) {
info->ecc_bch = 1;
info->nfullchunks = 4;
info->ntotalchunks = 5;
info->chunk_size = 1024;
info->spare_size = 0;
info->last_chunk_size = 0;
info->last_spare_size = 64;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_4KB_bch8bit;
ecc->strength = 16;
} else if (strength == 8 && ecc_stepsize == 512 && page_size == 8192) {
info->ecc_bch = 1;
info->nfullchunks = 8;
info->ntotalchunks = 9;
info->chunk_size = 1024;
info->spare_size = 0;
info->last_chunk_size = 0;
info->last_spare_size = 160;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_8KB_bch8bit;
ecc->strength = 16;
} else {
if (ecc_stepsize != 512 || !(nfc_layouts[i].strength)) { dev_err(info->controller.active->mtd.dev, "ECC strength %d at page size %d is not supported\n", strength, page_size);
-- 2.37.2

On 25.08.22 06:59, Chris Packham wrote:
Replace the if/else chain in pxa_ecc_init() with a lookup table. This makes the code more concise and hopefully easier to follow. Remove the unused ecc_layout tables and replace it with a single dummy one (the pxa3xx driver has never used this but the mtd subsystem expects it to be provided).
Tested on an Allied Telesis x530 switch with Micron MT29F2G08ABAEAWP NAND Flash.
Signed-off-by: Chris Packham judge.packham@gmail.com
Applied to u-boot-marvell/master
Thanks, Stefan
This code was taken from the Marvell SDK for the AC5/AC5X integrated switch/CPU. There are other changes to support the SoC which I will likely attempt to upstream soon but I think this stands on it's own merit as a nice clean up.
Reports of testing on other combinations of hardware would be greatly appreciated.
drivers/mtd/nand/raw/pxa3xx_nand.c | 247 ++++++++--------------------- 1 file changed, 68 insertions(+), 179 deletions(-)
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 9c29e8a6c214..fcd1b9c63614 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -330,89 +330,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { }; #endif
-static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
- .eccbytes = 32,
- .eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63},
- .oobfree = { {2, 30} }
+struct marvell_hw_ecc_layout {
- int page_size;
- int strength;
- unsigned int ecc_size;
- unsigned int nfullchunks;
- unsigned int chunk_size;
- unsigned int spare_size;
- unsigned int last_chunk_size;
- unsigned int last_spare_size; };
-static struct nand_ecclayout ecc_layout_2KB_bch8bit = {
- .eccbytes = 64,
- .eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95},
- .oobfree = { {1, 4}, {6, 26} }
+static const struct marvell_hw_ecc_layout nfc_layouts[] = {
- /* page_size strength ecc_size nfullchunks chunk_size spare_size last_chunk last_spare */
- { 512, 1, 8, 1, 512, 8, 0, 0 },
- { 2048, 1, 24, 1, 2048, 40, 0, 0 },
- { 2048, 4, 32, 1, 2048, 32, 0, 0 },
- { 2048, 8, 32, 1, 1024, 0, 1024, 32 },
- { 2048, 12, 32, 2, 704, 0, 640, 0 },
- { 2048, 16, 32, 4, 512, 0, 0, 32 },
- { 4096, 4, 32, 2, 2048, 32, 0, 0 },
- { 4096, 8, 32, 4, 1024, 0, 0, 64 },
- { 4096, 12, 32, 5, 704, 0, 576, 32 },
- { 4096, 16, 32, 8, 512, 0, 0, 32 },
- { 8192, 4, 32, 4, 2048, 32, 0, 0 },
- { 8192, 8, 32, 8, 1024, 0, 0, 160 },
- { 8192, 12, 32, 11, 704, 0, 448, 64 },
- { 8192, 16, 32, 16, 512, 0, 0, 32 },
- { }, };
-static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
- .eccbytes = 64,
- .eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127},
- /* Bootrom looks in bytes 0 & 5 for bad blocks */
- .oobfree = { {6, 26}, { 64, 32} }
-};
-static struct nand_ecclayout ecc_layout_8KB_bch4bit = {
- .eccbytes = 128,
- .eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191,
224, 225, 226, 227, 228, 229, 230, 231,
232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255},
- /* Bootrom looks in bytes 0 & 5 for bad blocks */
- .oobfree = { {1, 4}, {6, 26}, { 64, 32}, {128, 32}, {192, 32} }
-};
-static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
- .eccbytes = 128,
- .eccpos = {
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63},
+static struct nand_ecclayout ecc_layout_empty = {
- .eccbytes = 0,
- .eccpos = { }, .oobfree = { } };
-static struct nand_ecclayout ecc_layout_8KB_bch8bit = {
- .eccbytes = 256,
- .eccpos = {},
- /* HW ECC handles all ECC data and all spare area is free for OOB */
- .oobfree = {{0, 160} }
-};
- #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11)
@@ -1549,113 +1504,47 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, struct nand_ecc_ctrl *ecc, int strength, int ecc_stepsize, int page_size) {
- if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
info->nfullchunks = 1;
info->ntotalchunks = 1;
info->chunk_size = 2048;
info->spare_size = 40;
info->ecc_size = 24;
ecc->mode = NAND_ECC_HW;
ecc->size = 512;
ecc->strength = 1;
- int i = 0;
- } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) {
info->nfullchunks = 1;
info->ntotalchunks = 1;
info->chunk_size = 512;
info->spare_size = 8;
info->ecc_size = 8;
ecc->mode = NAND_ECC_HW;
ecc->size = 512;
ecc->strength = 1;
- /* if ecc strength is 1 ecc algo is Hamming else bch */
- info->ecc_bch = (strength == 1) ? 0 : 1;
- /*
* Required ECC: 4-bit correction per 512 bytes
* Select: 16-bit correction per 2048 bytes
- ecc->mode = NAND_ECC_HW;
- /* ecc->layout is not in use for pxa driver (but shouldn't be NULL)*/
- if (info->ecc_bch == 1)
ecc->layout = &ecc_layout_empty;
- /* for bch actual ecc strength is 16 per chunk */
- ecc->strength = (info->ecc_bch == 1) ? 16 : 1;
- while (nfc_layouts[i].strength) {
if (strength == nfc_layouts[i].strength && page_size == nfc_layouts[i].page_size) {
info->nfullchunks = nfc_layouts[i].nfullchunks;
info->chunk_size = nfc_layouts[i].chunk_size;
info->spare_size = nfc_layouts[i].spare_size;
info->last_chunk_size = nfc_layouts[i].last_chunk_size;
info->last_spare_size = nfc_layouts[i].last_spare_size;
info->ntotalchunks = (info->last_spare_size || info->last_chunk_size) ?
info->nfullchunks + 1 : info->nfullchunks;
info->ecc_size = nfc_layouts[i].ecc_size;
break;
}
++i;
- }
- /* for bch the ecc is calculated per chunk size and for Hamming it is 512 */
- ecc->size = (info->ecc_bch) ? info->chunk_size : 512;
- /* nand_scan_tail func perform validity tests for ECC strength, and it
* assumes that all chunks are with same size. in our case when ecc is 12
* the chunk size is 704 but the last chunk is with different size so
*/* we cheat it nand_scan_tail validity tests by set info->ecc_size value to 512
- } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) {
info->ecc_bch = 1;
info->nfullchunks = 1;
info->ntotalchunks = 1;
info->chunk_size = 2048;
info->spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_2KB_bch4bit;
ecc->strength = 16;
- if (strength == 12)
ecc->size = 512;
- } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
info->ecc_bch = 1;
info->nfullchunks = 2;
info->ntotalchunks = 2;
info->chunk_size = 2048;
info->spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_4KB_bch4bit;
ecc->strength = 16;
- } else if (strength == 4 && ecc_stepsize == 512 && page_size == 8192) {
info->ecc_bch = 1;
info->nfullchunks = 4;
info->ntotalchunks = 4;
info->chunk_size = 2048;
info->spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_8KB_bch4bit;
ecc->strength = 16;
- /*
* Required ECC: 8-bit correction per 512 bytes
* Select: 16-bit correction per 1024 bytes
*/
- } else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) {
info->ecc_bch = 1;
info->nfullchunks = 1;
info->ntotalchunks = 2;
info->chunk_size = 1024;
info->spare_size = 0;
info->last_chunk_size = 1024;
info->last_spare_size = 32;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_2KB_bch8bit;
ecc->strength = 16;
- } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) {
info->ecc_bch = 1;
info->nfullchunks = 4;
info->ntotalchunks = 5;
info->chunk_size = 1024;
info->spare_size = 0;
info->last_chunk_size = 0;
info->last_spare_size = 64;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_4KB_bch8bit;
ecc->strength = 16;
- } else if (strength == 8 && ecc_stepsize == 512 && page_size == 8192) {
info->ecc_bch = 1;
info->nfullchunks = 8;
info->ntotalchunks = 9;
info->chunk_size = 1024;
info->spare_size = 0;
info->last_chunk_size = 0;
info->last_spare_size = 160;
info->ecc_size = 32;
ecc->mode = NAND_ECC_HW;
ecc->size = info->chunk_size;
ecc->layout = &ecc_layout_8KB_bch8bit;
ecc->strength = 16;
- } else {
- if (ecc_stepsize != 512 || !(nfc_layouts[i].strength)) { dev_err(info->controller.active->mtd.dev, "ECC strength %d at page size %d is not supported\n", strength, page_size);
Viele Grüße, Stefan Roese
participants (3)
-
Chris Packham
-
Dario Binacchi
-
Stefan Roese