aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-07-04 02:40:18 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-07-11 09:52:02 -0400
commitd6248fddf717041f25781050e6392cc76525272d (patch)
tree249f5a7e7021d782966119bc57dbf55acc1594e7 /drivers/mtd
parent23a346ca4a5a6f50f81062456af955155f68e313 (diff)
[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@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/atmel_nand.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4814fc9b237b..99aec46e2145 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -33,6 +33,7 @@
33#include <linux/io.h> 33#include <linux/io.h>
34 34
35#include <asm/arch/board.h> 35#include <asm/arch/board.h>
36#include <asm/arch/cpu.h>
36 37
37#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW 38#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
38#define hard_ecc 1 39#define hard_ecc 1
@@ -264,6 +265,19 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
264 uint8_t *ecc_pos; 265 uint8_t *ecc_pos;
265 int stat; 266 int stat;
266 267
268 /*
269 * Errata: ALE is incorrectly wired up to the ECC controller
270 * on the AP7000, so it will include the address cycles in the
271 * ECC calculation.
272 *
273 * Workaround: Reset the parity registers before reading the
274 * actual data.
275 */
276 if (cpu_is_at32ap7000()) {
277 struct atmel_nand_host *host = chip->priv;
278 ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
279 }
280
267 /* read the page */ 281 /* read the page */
268 chip->read_buf(mtd, p, eccsize); 282 chip->read_buf(mtd, p, eccsize);
269 283
@@ -377,9 +391,16 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
377} 391}
378 392
379/* 393/*
380 * Enable HW ECC : unsused 394 * Enable HW ECC : unused on most chips
381 */ 395 */
382static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { ; } 396static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
397{
398 if (cpu_is_at32ap7000()) {
399 struct nand_chip *nand_chip = mtd->priv;
400 struct atmel_nand_host *host = nand_chip->priv;
401 ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
402 }
403}
383 404
384#ifdef CONFIG_MTD_PARTITIONS 405#ifdef CONFIG_MTD_PARTITIONS
385static const char *part_probes[] = { "cmdlinepart", NULL }; 406static const char *part_probes[] = { "cmdlinepart", NULL };