Skip to content

Commit 74e24cd

Browse files
committed
mtd: rawnand: Drop OOB_FIRST placement scheme
This scheme has been introduced for the Davinci controller and means that the OOB area must be read *before* the rest of the data. This has nothing to do with the ECC in OOB placement as it could be understood and most importantly, there is no point in having this function out of the Davinci NAND controller driver. A DT property for this scheme has been added but never used, even by the Davinci driver which only uses this scheme to change the default nand_read_page(). Move the main read_page() helper into the Davinci driver and remove the remaining boilerplate. Signed-off-by: Miquel Raynal <[email protected]> Reviewed-by: Boris Brezillon <[email protected]> Link: https://lore.kernel.org/linux-mtd/[email protected]
1 parent f66a6fd commit 74e24cd

File tree

3 files changed

+98
-110
lines changed

3 files changed

+98
-110
lines changed

drivers/mtd/nand/raw/davinci_nand.c

Lines changed: 98 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,77 @@ static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
371371
return corrected;
372372
}
373373

374+
/**
375+
* nand_read_page_hwecc_oob_first - hw ecc, read oob first
376+
* @chip: nand chip info structure
377+
* @buf: buffer to store read data
378+
* @oob_required: caller requires OOB data read to chip->oob_poi
379+
* @page: page number to read
380+
*
381+
* Hardware ECC for large page chips, require OOB to be read first. For this
382+
* ECC mode, the write_page method is re-used from ECC_HW. These methods
383+
* read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
384+
* multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
385+
* the data area, by overwriting the NAND manufacturer bad block markings.
386+
*/
387+
static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
388+
uint8_t *buf,
389+
int oob_required, int page)
390+
{
391+
struct mtd_info *mtd = nand_to_mtd(chip);
392+
int i, eccsize = chip->ecc.size, ret;
393+
int eccbytes = chip->ecc.bytes;
394+
int eccsteps = chip->ecc.steps;
395+
uint8_t *p = buf;
396+
uint8_t *ecc_code = chip->ecc.code_buf;
397+
uint8_t *ecc_calc = chip->ecc.calc_buf;
398+
unsigned int max_bitflips = 0;
399+
400+
/* Read the OOB area first */
401+
ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
402+
if (ret)
403+
return ret;
404+
405+
ret = nand_read_page_op(chip, page, 0, NULL, 0);
406+
if (ret)
407+
return ret;
408+
409+
ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
410+
chip->ecc.total);
411+
if (ret)
412+
return ret;
413+
414+
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
415+
int stat;
416+
417+
chip->ecc.hwctl(chip, NAND_ECC_READ);
418+
419+
ret = nand_read_data_op(chip, p, eccsize, false, false);
420+
if (ret)
421+
return ret;
422+
423+
chip->ecc.calculate(chip, p, &ecc_calc[i]);
424+
425+
stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
426+
if (stat == -EBADMSG &&
427+
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
428+
/* check for empty pages with bitflips */
429+
stat = nand_check_erased_ecc_chunk(p, eccsize,
430+
&ecc_code[i],
431+
eccbytes, NULL, 0,
432+
chip->ecc.strength);
433+
}
434+
435+
if (stat < 0) {
436+
mtd->ecc_stats.failed++;
437+
} else {
438+
mtd->ecc_stats.corrected += stat;
439+
max_bitflips = max_t(unsigned int, max_bitflips, stat);
440+
}
441+
}
442+
return max_bitflips;
443+
}
444+
374445
/*----------------------------------------------------------------------*/
375446

376447
/* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -530,6 +601,13 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
530601
break;
531602
case NAND_ECC_HW:
532603
if (pdata->ecc_bits == 4) {
604+
int chunks = mtd->writesize / 512;
605+
606+
if (!chunks || mtd->oobsize < 16) {
607+
dev_dbg(&info->pdev->dev, "too small\n");
608+
return -EINVAL;
609+
}
610+
533611
/*
534612
* No sanity checks: CPUs must support this,
535613
* and the chips may not use NAND_BUSWIDTH_16.
@@ -552,6 +630,26 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
552630
info->chip.ecc.bytes = 10;
553631
info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
554632
info->chip.ecc.algo = NAND_ECC_BCH;
633+
634+
/*
635+
* Update ECC layout if needed ... for 1-bit HW ECC, the
636+
* default is OK, but it allocates 6 bytes when only 3
637+
* are needed (for each 512 bytes). For 4-bit HW ECC,
638+
* the default is not usable: 10 bytes needed, not 6.
639+
*
640+
* For small page chips, preserve the manufacturer's
641+
* badblock marking data ... and make sure a flash BBT
642+
* table marker fits in the free bytes.
643+
*/
644+
if (chunks == 1) {
645+
mtd_set_ooblayout(mtd,
646+
&hwecc4_small_ooblayout_ops);
647+
} else if (chunks == 4 || chunks == 8) {
648+
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
649+
info->chip.ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
650+
} else {
651+
return -EIO;
652+
}
555653
} else {
556654
/* 1bit ecc hamming */
557655
info->chip.ecc.calculate = nand_davinci_calculate_1bit;
@@ -567,34 +665,6 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
567665
return -EINVAL;
568666
}
569667

570-
/*
571-
* Update ECC layout if needed ... for 1-bit HW ECC, the default
572-
* is OK, but it allocates 6 bytes when only 3 are needed (for
573-
* each 512 bytes). For the 4-bit HW ECC, that default is not
574-
* usable: 10 bytes are needed, not 6.
575-
*/
576-
if (pdata->ecc_bits == 4) {
577-
int chunks = mtd->writesize / 512;
578-
579-
if (!chunks || mtd->oobsize < 16) {
580-
dev_dbg(&info->pdev->dev, "too small\n");
581-
return -EINVAL;
582-
}
583-
584-
/* For small page chips, preserve the manufacturer's
585-
* badblock marking data ... and make sure a flash BBT
586-
* table marker fits in the free bytes.
587-
*/
588-
if (chunks == 1) {
589-
mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
590-
} else if (chunks == 4 || chunks == 8) {
591-
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
592-
info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
593-
} else {
594-
return -EIO;
595-
}
596-
}
597-
598668
return ret;
599669
}
600670

drivers/mtd/nand/raw/nand_base.c

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3075,76 +3075,6 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
30753075
return max_bitflips;
30763076
}
30773077

3078-
/**
3079-
* nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first
3080-
* @chip: nand chip info structure
3081-
* @buf: buffer to store read data
3082-
* @oob_required: caller requires OOB data read to chip->oob_poi
3083-
* @page: page number to read
3084-
*
3085-
* Hardware ECC for large page chips, require OOB to be read first. For this
3086-
* ECC mode, the write_page method is re-used from ECC_HW. These methods
3087-
* read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
3088-
* multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
3089-
* the data area, by overwriting the NAND manufacturer bad block markings.
3090-
*/
3091-
static int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
3092-
int oob_required, int page)
3093-
{
3094-
struct mtd_info *mtd = nand_to_mtd(chip);
3095-
int i, eccsize = chip->ecc.size, ret;
3096-
int eccbytes = chip->ecc.bytes;
3097-
int eccsteps = chip->ecc.steps;
3098-
uint8_t *p = buf;
3099-
uint8_t *ecc_code = chip->ecc.code_buf;
3100-
uint8_t *ecc_calc = chip->ecc.calc_buf;
3101-
unsigned int max_bitflips = 0;
3102-
3103-
/* Read the OOB area first */
3104-
ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
3105-
if (ret)
3106-
return ret;
3107-
3108-
ret = nand_read_page_op(chip, page, 0, NULL, 0);
3109-
if (ret)
3110-
return ret;
3111-
3112-
ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
3113-
chip->ecc.total);
3114-
if (ret)
3115-
return ret;
3116-
3117-
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
3118-
int stat;
3119-
3120-
chip->ecc.hwctl(chip, NAND_ECC_READ);
3121-
3122-
ret = nand_read_data_op(chip, p, eccsize, false, false);
3123-
if (ret)
3124-
return ret;
3125-
3126-
chip->ecc.calculate(chip, p, &ecc_calc[i]);
3127-
3128-
stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
3129-
if (stat == -EBADMSG &&
3130-
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
3131-
/* check for empty pages with bitflips */
3132-
stat = nand_check_erased_ecc_chunk(p, eccsize,
3133-
&ecc_code[i], eccbytes,
3134-
NULL, 0,
3135-
chip->ecc.strength);
3136-
}
3137-
3138-
if (stat < 0) {
3139-
mtd->ecc_stats.failed++;
3140-
} else {
3141-
mtd->ecc_stats.corrected += stat;
3142-
max_bitflips = max_t(unsigned int, max_bitflips, stat);
3143-
}
3144-
}
3145-
return max_bitflips;
3146-
}
3147-
31483078
/**
31493079
* nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
31503080
* @chip: nand chip info structure
@@ -5080,7 +5010,6 @@ static const char * const nand_ecc_modes[] = {
50805010
[NAND_ECC_SOFT] = "soft",
50815011
[NAND_ECC_HW] = "hw",
50825012
[NAND_ECC_HW_SYNDROME] = "hw_syndrome",
5083-
[NAND_ECC_HW_OOB_FIRST] = "hw_oob_first",
50845013
[NAND_ECC_ON_DIE] = "on-die",
50855014
};
50865015

@@ -5829,16 +5758,6 @@ static int nand_scan_tail(struct nand_chip *chip)
58295758
*/
58305759

58315760
switch (ecc->mode) {
5832-
case NAND_ECC_HW_OOB_FIRST:
5833-
/* Similar to NAND_ECC_HW, but a separate read_page handle */
5834-
if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {
5835-
WARN(1, "No ECC functions supplied; hardware ECC not possible\n");
5836-
ret = -EINVAL;
5837-
goto err_nand_manuf_cleanup;
5838-
}
5839-
if (!ecc->read_page)
5840-
ecc->read_page = nand_read_page_hwecc_oob_first;
5841-
fallthrough;
58425761
case NAND_ECC_HW:
58435762
/* Use standard hwecc read page function? */
58445763
if (!ecc->read_page)

include/linux/mtd/rawnand.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ enum nand_ecc_mode {
8888
NAND_ECC_SOFT,
8989
NAND_ECC_HW,
9090
NAND_ECC_HW_SYNDROME,
91-
NAND_ECC_HW_OOB_FIRST,
9291
NAND_ECC_ON_DIE,
9392
};
9493

0 commit comments

Comments
 (0)