[U-Boot] [PATCH] drivers: nand: brcmnand: fix nand_chip ecc layout structure

The current brcmnand driver is based on 4.18 linux kernel which uses mtd_set_ooblayout to set ecc layout. But nand base code in u-boot is from old kernel which does not use this new API and expect nand_chip.ecc.layout structure to be set. This cause nand_scan_tail function running into a bug check if the device has a different oob size than the default ones.
This patch ports the brcmstb_choose_ecc_layout function from kernel 4.6.7 that supports the ecc layout struture and replaces the mtd_set_ooblayout method
Signed-off-by: William Zhang william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 260 +++++++++-------------- 1 file changed, 104 insertions(+), 156 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index faa6da42d5..0745929253 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -888,183 +888,131 @@ static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl, }
/* - * Set mtd->ooblayout to the appropriate mtd_ooblayout_ops given - * the layout/configuration. - * Returns -ERRCODE on failure. + * Returns a nand_ecclayout strucutre for the given layout/configuration. + * Returns NULL on failure. */ -static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) +static struct nand_ecclayout *brcmnand_create_layout(int ecc_level, + struct brcmnand_host *host) { - struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = nand_get_controller_data(chip); - struct brcmnand_cfg *cfg = &host->hwcfg; - int sas = cfg->spare_area_size << cfg->sector_size_1k; - int sectors = cfg->page_size / (512 << cfg->sector_size_1k); - - if (section >= sectors) - return -ERANGE; - - oobregion->offset = (section * sas) + 6; - oobregion->length = 3; - - return 0; -} - -static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_cfg *cfg = &host->hwcfg; - int sas = cfg->spare_area_size << cfg->sector_size_1k; - int sectors = cfg->page_size / (512 << cfg->sector_size_1k); + int i, j; + struct nand_ecclayout *layout; + int req; + int sectors; + int sas; + int idx1, idx2;
- if (section >= sectors * 2) - return -ERANGE; - - oobregion->offset = (section / 2) * sas; - - if (section & 1) { - oobregion->offset += 9; - oobregion->length = 7; - } else { - oobregion->length = 6; - - /* First sector of each page may have BBI */ - if (!section) { - /* - * Small-page NAND use byte 6 for BBI while large-page - * NAND use byte 0. - */ - if (cfg->page_size > 512) - oobregion->offset++; - oobregion->length--; +#ifndef __UBOOT__ + layout = devm_kzalloc(&host->pdev->dev, sizeof(*layout), GFP_KERNEL); +#else + layout = devm_kzalloc(host->pdev, sizeof(*layout), GFP_KERNEL); +#endif + if (!layout) + return NULL; + + sectors = cfg->page_size / (512 << cfg->sector_size_1k); + sas = cfg->spare_area_size << cfg->sector_size_1k; + + /* Hamming */ + if (is_hamming_ecc(host->ctrl, cfg)) { + for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) { + /* First sector of each page may have BBI */ + if (i == 0) { + layout->oobfree[idx2].offset = i * sas + 1; + /* Small-page NAND use byte 6 for BBI */ + if (cfg->page_size == 512) + layout->oobfree[idx2].offset--; + layout->oobfree[idx2].length = 5; + } else { + layout->oobfree[idx2].offset = i * sas; + layout->oobfree[idx2].length = 6; + } + idx2++; + layout->eccpos[idx1++] = i * sas + 6; + layout->eccpos[idx1++] = i * sas + 7; + layout->eccpos[idx1++] = i * sas + 8; + layout->oobfree[idx2].offset = i * sas + 9; + layout->oobfree[idx2].length = 7; + idx2++; + /* Leave zero-terminated entry for OOBFREE */ + if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE || + idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) + break; } - } - - return 0; -} - -static const struct mtd_ooblayout_ops brcmnand_hamming_ooblayout_ops = { - .ecc = brcmnand_hamming_ooblayout_ecc, - .free = brcmnand_hamming_ooblayout_free, -}; - -static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = nand_get_controller_data(chip); - struct brcmnand_cfg *cfg = &host->hwcfg; - int sas = cfg->spare_area_size << cfg->sector_size_1k; - int sectors = cfg->page_size / (512 << cfg->sector_size_1k); - - if (section >= sectors) - return -ERANGE;
- oobregion->offset = (section * (sas + 1)) - chip->ecc.bytes; - oobregion->length = chip->ecc.bytes; - - return 0; -} - -static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = nand_get_controller_data(chip); - struct brcmnand_cfg *cfg = &host->hwcfg; - int sas = cfg->spare_area_size << cfg->sector_size_1k; - int sectors = cfg->page_size / (512 << cfg->sector_size_1k); - - if (section >= sectors) - return -ERANGE; - - if (sas <= chip->ecc.bytes) - return 0; - - oobregion->offset = section * sas; - oobregion->length = sas - chip->ecc.bytes; - - if (!section) { - oobregion->offset++; - oobregion->length--; + return layout; }
- return 0; -} - -static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = nand_get_controller_data(chip); - struct brcmnand_cfg *cfg = &host->hwcfg; - int sas = cfg->spare_area_size << cfg->sector_size_1k; + /* + * CONTROLLER_VERSION: + * < v5.0: ECC_REQ = ceil(BCH_T * 13/8) + * >= v5.0: ECC_REQ = ceil(BCH_T * 14/8) + * But we will just be conservative. + */ + req = DIV_ROUND_UP(ecc_level * 14, 8); + if (req >= sas) { + dev_err(&host->pdev->dev, + "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n", + req, sas); + return NULL; + }
- if (section > 1 || sas - chip->ecc.bytes < 6 || - (section && sas - chip->ecc.bytes == 6)) - return -ERANGE; + layout->eccbytes = req * sectors; + for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) { + for (j = sas - req; j < sas && idx1 < + MTD_MAX_ECCPOS_ENTRIES_LARGE; j++, idx1++) + layout->eccpos[idx1] = i * sas + j;
- if (!section) { - oobregion->offset = 0; - oobregion->length = 5; - } else { - oobregion->offset = 6; - oobregion->length = sas - chip->ecc.bytes - 6; + /* First sector of each page may have BBI */ + if (i == 0) { + if (cfg->page_size == 512 && (sas - req >= 6)) { + /* Small-page NAND use byte 6 for BBI */ + layout->oobfree[idx2].offset = 0; + layout->oobfree[idx2].length = 5; + idx2++; + if (sas - req > 6) { + layout->oobfree[idx2].offset = 6; + layout->oobfree[idx2].length = + sas - req - 6; + idx2++; + } + } else if (sas > req + 1) { + layout->oobfree[idx2].offset = i * sas + 1; + layout->oobfree[idx2].length = sas - req - 1; + idx2++; + } + } else if (sas > req) { + layout->oobfree[idx2].offset = i * sas; + layout->oobfree[idx2].length = sas - req; + idx2++; + } + /* Leave zero-terminated entry for OOBFREE */ + if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE || + idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) + break; }
- return 0; + return layout; }
-static const struct mtd_ooblayout_ops brcmnand_bch_lp_ooblayout_ops = { - .ecc = brcmnand_bch_ooblayout_ecc, - .free = brcmnand_bch_ooblayout_free_lp, -}; - -static const struct mtd_ooblayout_ops brcmnand_bch_sp_ooblayout_ops = { - .ecc = brcmnand_bch_ooblayout_ecc, - .free = brcmnand_bch_ooblayout_free_sp, -}; - -static int brcmstb_choose_ecc_layout(struct brcmnand_host *host) +static struct nand_ecclayout *brcmstb_choose_ecc_layout( + struct brcmnand_host *host) { + struct nand_ecclayout *layout; struct brcmnand_cfg *p = &host->hwcfg; - struct mtd_info *mtd = nand_to_mtd(&host->chip); - struct nand_ecc_ctrl *ecc = &host->chip.ecc; unsigned int ecc_level = p->ecc_level; - int sas = p->spare_area_size << p->sector_size_1k; - int sectors = p->page_size / (512 << p->sector_size_1k);
if (p->sector_size_1k) ecc_level <<= 1;
- if (is_hamming_ecc(host->ctrl, p)) { - ecc->bytes = 3 * sectors; - mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops); - return 0; - } - - /* - * CONTROLLER_VERSION: - * < v5.0: ECC_REQ = ceil(BCH_T * 13/8) - * >= v5.0: ECC_REQ = ceil(BCH_T * 14/8) - * But we will just be conservative. - */ - ecc->bytes = DIV_ROUND_UP(ecc_level * 14, 8); - if (p->page_size == 512) - mtd_set_ooblayout(mtd, &brcmnand_bch_sp_ooblayout_ops); - else - mtd_set_ooblayout(mtd, &brcmnand_bch_lp_ooblayout_ops); - - if (ecc->bytes >= sas) { + layout = brcmnand_create_layout(ecc_level, host); + if (!layout) { dev_err(&host->pdev->dev, - "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n", - ecc->bytes, sas); - return -EINVAL; + "no proper ecc_layout for this NAND cfg\n"); + return NULL; }
- return 0; + return layout; }
static void brcmnand_wp(struct mtd_info *mtd, int wp) @@ -2383,9 +2331,9 @@ static int brcmnand_init_cs(struct brcmnand_host *host, ofnode dn) /* only use our internal HW threshold */ mtd->bitflip_threshold = 1;
- ret = brcmstb_choose_ecc_layout(host); - if (ret) - return ret; + chip->ecc.layout = brcmstb_choose_ecc_layout(host); + if (!chip->ecc.layout) + return -ENXIO;
ret = nand_scan_tail(mtd); if (ret)

The current brcmnand driver is based on 4.18 linux kernel which uses mtd_set_ooblayout to set ecc layout. But nand base code in u-boot is from old kernel which does not use this new API and expect nand_chip.ecc.layout structure to be set. This cause nand_scan_tail function running into a bug check if the device has a different oob size than the default ones.
This patch ports the brcmstb_choose_ecc_layout function from kernel 4.6.7 that supports the ecc layout struture and replaces the mtd_set_ooblayout method
Signed-off-by: William Zhang william.zhang@broadcom.com
Good catch, I've missed it when I have ported this driver to u-boot.
Reviewed-by: Philippe Reynes philippe.reynes@softathome.com
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 260 +++++++++-------------- 1 file changed, 104 insertions(+), 156 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index faa6da42d5..0745929253 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -888,183 +888,131 @@ static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl, }
/*
- Set mtd->ooblayout to the appropriate mtd_ooblayout_ops given
- the layout/configuration.
- Returns -ERRCODE on failure.
- Returns a nand_ecclayout strucutre for the given layout/configuration.
- Returns NULL on failure.
*/ -static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
+static struct nand_ecclayout *brcmnand_create_layout(int ecc_level,
- struct brcmnand_host *host)
{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct brcmnand_host *host = nand_get_controller_data(chip);
- struct brcmnand_cfg *cfg = &host->hwcfg;
- int sas = cfg->spare_area_size << cfg->sector_size_1k;
- int sectors = cfg->page_size / (512 << cfg->sector_size_1k);
- if (section >= sectors)
- return -ERANGE;
- oobregion->offset = (section * sas) + 6;
- oobregion->length = 3;
- return 0;
-}
-static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_cfg *cfg = &host->hwcfg;
- int sas = cfg->spare_area_size << cfg->sector_size_1k;
- int sectors = cfg->page_size / (512 << cfg->sector_size_1k);
- int i, j;
- struct nand_ecclayout *layout;
- int req;
- int sectors;
- int sas;
- int idx1, idx2;
- if (section >= sectors * 2)
- return -ERANGE;
- oobregion->offset = (section / 2) * sas;
- if (section & 1) {
- oobregion->offset += 9;
- oobregion->length = 7;
- } else {
- oobregion->length = 6;
- /* First sector of each page may have BBI */
- if (!section) {
- /*
- Small-page NAND use byte 6 for BBI while large-page
- NAND use byte 0.
- */
- if (cfg->page_size > 512)
- oobregion->offset++;
- oobregion->length--;
+#ifndef __UBOOT__
- layout = devm_kzalloc(&host->pdev->dev, sizeof(*layout), GFP_KERNEL);
+#else
- layout = devm_kzalloc(host->pdev, sizeof(*layout), GFP_KERNEL);
+#endif
- if (!layout)
- return NULL;
- sectors = cfg->page_size / (512 << cfg->sector_size_1k);
- sas = cfg->spare_area_size << cfg->sector_size_1k;
- /* Hamming */
- if (is_hamming_ecc(host->ctrl, cfg)) {
- for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) {
- /* First sector of each page may have BBI */
- if (i == 0) {
- layout->oobfree[idx2].offset = i * sas + 1;
- /* Small-page NAND use byte 6 for BBI */
- if (cfg->page_size == 512)
- layout->oobfree[idx2].offset--;
- layout->oobfree[idx2].length = 5;
- } else {
- layout->oobfree[idx2].offset = i * sas;
- layout->oobfree[idx2].length = 6;
- }
- idx2++;
- layout->eccpos[idx1++] = i * sas + 6;
- layout->eccpos[idx1++] = i * sas + 7;
- layout->eccpos[idx1++] = i * sas + 8;
- layout->oobfree[idx2].offset = i * sas + 9;
- layout->oobfree[idx2].length = 7;
- idx2++;
- /* Leave zero-terminated entry for OOBFREE */
- if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE ||
- idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1)
- break;
}
- }
- return 0;
-}
-static const struct mtd_ooblayout_ops brcmnand_hamming_ooblayout_ops = {
- .ecc = brcmnand_hamming_ooblayout_ecc,
- .free = brcmnand_hamming_ooblayout_free,
-};
-static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
struct nand_chip *chip = mtd_to_nand(mtd);
struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_cfg *cfg = &host->hwcfg;
int sas = cfg->spare_area_size << cfg->sector_size_1k;
int sectors = cfg->page_size / (512 << cfg->sector_size_1k);
if (section >= sectors)
return -ERANGE;
oobregion->offset = (section * (sas + 1)) - chip->ecc.bytes;
oobregion->length = chip->ecc.bytes;
return 0;
-}
-static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct brcmnand_host *host = nand_get_controller_data(chip);
- struct brcmnand_cfg *cfg = &host->hwcfg;
- int sas = cfg->spare_area_size << cfg->sector_size_1k;
- int sectors = cfg->page_size / (512 << cfg->sector_size_1k);
- if (section >= sectors)
- return -ERANGE;
- if (sas <= chip->ecc.bytes)
- return 0;
- oobregion->offset = section * sas;
- oobregion->length = sas - chip->ecc.bytes;
- if (!section) {
- oobregion->offset++;
- oobregion->length--;
- return layout;
}
- return 0;
-}
-static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct brcmnand_host *host = nand_get_controller_data(chip);
- struct brcmnand_cfg *cfg = &host->hwcfg;
- int sas = cfg->spare_area_size << cfg->sector_size_1k;
- /*
- CONTROLLER_VERSION:
- < v5.0: ECC_REQ = ceil(BCH_T * 13/8)
= v5.0: ECC_REQ = ceil(BCH_T * 14/8)
- But we will just be conservative.
- */
- req = DIV_ROUND_UP(ecc_level * 14, 8);
- if (req >= sas) {
- dev_err(&host->pdev->dev,
- "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n",
- req, sas);
- return NULL;
- }
- if (section > 1 || sas - chip->ecc.bytes < 6 ||
- (section && sas - chip->ecc.bytes == 6))
- return -ERANGE;
- layout->eccbytes = req * sectors;
- for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) {
- for (j = sas - req; j < sas && idx1 <
- MTD_MAX_ECCPOS_ENTRIES_LARGE; j++, idx1++)
- layout->eccpos[idx1] = i * sas + j;
- if (!section) {
- oobregion->offset = 0;
- oobregion->length = 5;
- } else {
- oobregion->offset = 6;
- oobregion->length = sas - chip->ecc.bytes - 6;
- /* First sector of each page may have BBI */
- if (i == 0) {
- if (cfg->page_size == 512 && (sas - req >= 6)) {
- /* Small-page NAND use byte 6 for BBI */
- layout->oobfree[idx2].offset = 0;
- layout->oobfree[idx2].length = 5;
- idx2++;
- if (sas - req > 6) {
- layout->oobfree[idx2].offset = 6;
- layout->oobfree[idx2].length =
- sas - req - 6;
- idx2++;
- }
- } else if (sas > req + 1) {
- layout->oobfree[idx2].offset = i * sas + 1;
- layout->oobfree[idx2].length = sas - req - 1;
- idx2++;
- }
- } else if (sas > req) {
- layout->oobfree[idx2].offset = i * sas;
- layout->oobfree[idx2].length = sas - req;
- idx2++;
- }
- /* Leave zero-terminated entry for OOBFREE */
- if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE ||
- idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1)
- break;
}
- return 0;
- return layout;
}
-static const struct mtd_ooblayout_ops brcmnand_bch_lp_ooblayout_ops = {
- .ecc = brcmnand_bch_ooblayout_ecc,
- .free = brcmnand_bch_ooblayout_free_lp,
-};
-static const struct mtd_ooblayout_ops brcmnand_bch_sp_ooblayout_ops = {
- .ecc = brcmnand_bch_ooblayout_ecc,
- .free = brcmnand_bch_ooblayout_free_sp,
-};
-static int brcmstb_choose_ecc_layout(struct brcmnand_host *host) +static struct nand_ecclayout *brcmstb_choose_ecc_layout(
- struct brcmnand_host *host)
{
- struct nand_ecclayout *layout;
struct brcmnand_cfg *p = &host->hwcfg;
- struct mtd_info *mtd = nand_to_mtd(&host->chip);
- struct nand_ecc_ctrl *ecc = &host->chip.ecc;
unsigned int ecc_level = p->ecc_level;
- int sas = p->spare_area_size << p->sector_size_1k;
- int sectors = p->page_size / (512 << p->sector_size_1k);
if (p->sector_size_1k) ecc_level <<= 1;
- if (is_hamming_ecc(host->ctrl, p)) {
- ecc->bytes = 3 * sectors;
- mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops);
- return 0;
- }
- /*
- CONTROLLER_VERSION:
- < v5.0: ECC_REQ = ceil(BCH_T * 13/8)
= v5.0: ECC_REQ = ceil(BCH_T * 14/8)
- But we will just be conservative.
- */
- ecc->bytes = DIV_ROUND_UP(ecc_level * 14, 8);
- if (p->page_size == 512)
- mtd_set_ooblayout(mtd, &brcmnand_bch_sp_ooblayout_ops);
- else
- mtd_set_ooblayout(mtd, &brcmnand_bch_lp_ooblayout_ops);
- if (ecc->bytes >= sas) {
- layout = brcmnand_create_layout(ecc_level, host);
- if (!layout) {
dev_err(&host->pdev->dev,
- "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n",
- ecc->bytes, sas);
- return -EINVAL;
- "no proper ecc_layout for this NAND cfg\n");
- return NULL;
}
- return 0;
- return layout;
}
static void brcmnand_wp(struct mtd_info *mtd, int wp) @@ -2383,9 +2331,9 @@ static int brcmnand_init_cs(struct brcmnand_host *host, ofnode dn) /* only use our internal HW threshold */ mtd->bitflip_threshold = 1;
- ret = brcmstb_choose_ecc_layout(host);
- if (ret)
- return ret;
- chip->ecc.layout = brcmstb_choose_ecc_layout(host);
- if (!chip->ecc.layout)
- return -ENXIO;
ret = nand_scan_tail(mtd); if (ret) -- 2.18.0

Am 04.09.19 um 19:51 schrieb William Zhang:
The current brcmnand driver is based on 4.18 linux kernel which uses mtd_set_ooblayout to set ecc layout. But nand base code in u-boot is from old kernel which does not use this new API and expect nand_chip.ecc.layout structure to be set. This cause nand_scan_tail function running into a bug check if the device has a different oob size than the default ones.
This patch ports the brcmstb_choose_ecc_layout function from kernel 4.6.7 that supports the ecc layout struture and replaces the mtd_set_ooblayout method
Signed-off-by: William Zhang william.zhang@broadcom.com
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 260 +++++++++-------------- 1 file changed, 104 insertions(+), 156 deletions(-)
applied to u-boot-mips, thanks.

Thank you Daniel!
-----Original Message----- From: Daniel Schwierzeck [mailto:daniel.schwierzeck@gmail.com] Sent: Friday, October 18, 2019 4:37 AM To: William Zhang; philippe.reynes@softathome.com Cc: u-boot@lists.denx.de Subject: Re: [U-Boot] [PATCH] drivers: nand: brcmnand: fix nand_chip ecc layout structure
Am 04.09.19 um 19:51 schrieb William Zhang:
The current brcmnand driver is based on 4.18 linux kernel which uses mtd_set_ooblayout to set ecc layout. But nand base code in u-boot is from old kernel which does not use this new API and expect nand_chip.ecc.layout structure to be set. This cause nand_scan_tail function running into a bug check if the device has a different oob size than the default ones.
This patch ports the brcmstb_choose_ecc_layout function from kernel 4.6.7 that supports the ecc layout struture and replaces the mtd_set_ooblayout method
Signed-off-by: William Zhang william.zhang@broadcom.com
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 260 +++++++++-------------- 1 file changed, 104 insertions(+), 156 deletions(-)
applied to u-boot-mips, thanks.
participants (3)
-
Daniel Schwierzeck
-
Philippe REYNES
-
William Zhang