[MTD] [NAND] atmel_nand: Work around AT32AP7000 ECC erratum

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Fri Jul 11 13:59:01 EDT 2008


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=d6248fddf717041f25781050e6392cc76525272d
Commit:     d6248fddf717041f25781050e6392cc76525272d
Parent:     23a346ca4a5a6f50f81062456af955155f68e313
Author:     Haavard Skinnemoen <haavard.skinnemoen at atmel.com>
AuthorDate: Thu Jul 3 23:40:18 2008 -0700
Committer:  David Woodhouse <David.Woodhouse at intel.com>
CommitDate: Fri Jul 11 14:52:02 2008 +0100

    [MTD] [NAND] atmel_nand: Work around AT32AP7000 ECC erratum
    
    The ALE signal isn't correctly wired up to the ECC controller on the
    AP7000, so it starts calculating ECC during the address cycles.
    
    Work around this by resetting the ECC controller between the address and
    data cycles.
    
    Signed-off-by: Håvard Skinnemoen <haavard.skinnemoen at atmel.com>
    Acked-by: Andrew Victor <linux at maxim.org.za>
    Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 drivers/mtd/nand/atmel_nand.c |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4814fc9..99aec46 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
 #define hard_ecc	1
@@ -264,6 +265,19 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
 	uint8_t *ecc_pos;
 	int stat;
 
+	/*
+	 * Errata: ALE is incorrectly wired up to the ECC controller
+	 * on the AP7000, so it will include the address cycles in the
+	 * ECC calculation.
+	 *
+	 * Workaround: Reset the parity registers before reading the
+	 * actual data.
+	 */
+	if (cpu_is_at32ap7000()) {
+		struct atmel_nand_host *host = chip->priv;
+		ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
+	}
+
 	/* read the page */
 	chip->read_buf(mtd, p, eccsize);
 
@@ -377,9 +391,16 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
 }
 
 /*
- * Enable HW ECC : unsused
+ * Enable HW ECC : unused on most chips
  */
-static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
+static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+	if (cpu_is_at32ap7000()) {
+		struct nand_chip *nand_chip = mtd->priv;
+		struct atmel_nand_host *host = nand_chip->priv;
+		ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
+	}
+}
 
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };



More information about the linux-mtd-cvs mailing list