diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-04 02:40:18 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 09:52:02 -0400 |
commit | d6248fddf717041f25781050e6392cc76525272d (patch) | |
tree | 249f5a7e7021d782966119bc57dbf55acc1594e7 /drivers/mtd | |
parent | 23a346ca4a5a6f50f81062456af955155f68e313 (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.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 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 | */ |
382 | static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { ; } | 396 | static 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 |
385 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 406 | static const char *part_probes[] = { "cmdlinepart", NULL }; |