diff options
author | Sneha Narnakaje <nsnehaprabha@ti.com> | 2009-09-18 15:51:48 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-09-19 14:16:57 -0400 |
commit | f12a9473283e68ae708e9ada37cb352ea2652397 (patch) | |
tree | d0886b69596a6031ac705352daa38a13fa0dcc06 | |
parent | 6e0cb135b3f3713b95ea41a11155e83a8c70f5f8 (diff) |
mtd: nand: DaVinci: Add 4-bit ECC support for large page NAND chips
This patch adds 4-bit ECC support for large page NAND chips using the new
ECC mode NAND_ECC_HW_OOB_FIRST. The platform data from board-dm355-evm
has been adjusted to use this mode.
The patches have been verified on DM355 device with 2KiB-page Micron
devices using mtd-tests and JFFS2. Error correction up to 4 bits has
also been verified using nandwrite/nanddump utilities.
Reviewed-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Sneha Narnakaje <nsnehaprabha@ti.com>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Troy Kisky <troy.kisky@boundarydevices.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 0fad6487e6f4..f13f5b9afaf7 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -348,6 +348,12 @@ compare: | |||
348 | if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3])) | 348 | if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3])) |
349 | return 0; | 349 | return 0; |
350 | 350 | ||
351 | /* | ||
352 | * Clear any previous address calculation by doing a dummy read of an | ||
353 | * error address register. | ||
354 | */ | ||
355 | davinci_nand_readl(info, NAND_ERR_ADD1_OFFSET); | ||
356 | |||
351 | /* Start address calculation, and wait for it to complete. | 357 | /* Start address calculation, and wait for it to complete. |
352 | * We _could_ start reading more data while this is working, | 358 | * We _could_ start reading more data while this is working, |
353 | * to speed up the overall page read. | 359 | * to speed up the overall page read. |
@@ -359,8 +365,10 @@ compare: | |||
359 | 365 | ||
360 | switch ((fsr >> 8) & 0x0f) { | 366 | switch ((fsr >> 8) & 0x0f) { |
361 | case 0: /* no error, should not happen */ | 367 | case 0: /* no error, should not happen */ |
368 | davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET); | ||
362 | return 0; | 369 | return 0; |
363 | case 1: /* five or more errors detected */ | 370 | case 1: /* five or more errors detected */ |
371 | davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET); | ||
364 | return -EIO; | 372 | return -EIO; |
365 | case 2: /* error addresses computed */ | 373 | case 2: /* error addresses computed */ |
366 | case 3: | 374 | case 3: |
@@ -500,6 +508,26 @@ static struct nand_ecclayout hwecc4_small __initconst = { | |||
500 | }, | 508 | }, |
501 | }; | 509 | }; |
502 | 510 | ||
511 | /* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash, | ||
512 | * storing ten ECC bytes plus the manufacturer's bad block marker byte, | ||
513 | * and not overlapping the default BBT markers. | ||
514 | */ | ||
515 | static struct nand_ecclayout hwecc4_2048 __initconst = { | ||
516 | .eccbytes = 40, | ||
517 | .eccpos = { | ||
518 | /* at the end of spare sector */ | ||
519 | 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, | ||
520 | 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, | ||
521 | 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, | ||
522 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, | ||
523 | }, | ||
524 | .oobfree = { | ||
525 | /* 2 bytes at offset 0 hold manufacturer badblock markers */ | ||
526 | {.offset = 2, .length = 22, }, | ||
527 | /* 5 bytes at offset 8 hold BBT markers */ | ||
528 | /* 8 bytes at offset 16 hold JFFS2 clean markers */ | ||
529 | }, | ||
530 | }; | ||
503 | 531 | ||
504 | static int __init nand_davinci_probe(struct platform_device *pdev) | 532 | static int __init nand_davinci_probe(struct platform_device *pdev) |
505 | { | 533 | { |
@@ -690,15 +718,20 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
690 | info->mtd.oobsize - 16; | 718 | info->mtd.oobsize - 16; |
691 | goto syndrome_done; | 719 | goto syndrome_done; |
692 | } | 720 | } |
721 | if (chunks == 4) { | ||
722 | info->ecclayout = hwecc4_2048; | ||
723 | info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST; | ||
724 | goto syndrome_done; | ||
725 | } | ||
693 | 726 | ||
694 | /* For large page chips we'll be wanting to use a | 727 | /* 4KiB page chips are not yet supported. The eccpos from |
695 | * not-yet-implemented mode that reads OOB data | 728 | * nand_ecclayout cannot hold 80 bytes and change to eccpos[] |
696 | * before reading the body of the page, to avoid | 729 | * breaks userspace ioctl interface with mtd-utils. Once we |
697 | * the "infix OOB" model of NAND_ECC_HW_SYNDROME | 730 | * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used |
698 | * (and preserve manufacturer badblock markings). | 731 | * for the 4KiB page chips. |
699 | */ | 732 | */ |
700 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " | 733 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " |
701 | "for large page NAND\n"); | 734 | "for 4KiB-page NAND\n"); |
702 | ret = -EIO; | 735 | ret = -EIO; |
703 | goto err_scan; | 736 | goto err_scan; |
704 | 737 | ||