aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-10-22 10:09:33 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-10-22 10:09:33 -0400
commitfbad5696c5c45982d02e05b85922bad6eb6e6349 (patch)
treec0d2c95a81a985a7305c2fabb9f95743deb424a1 /drivers
parent04459d7c6239193fa8de4a5107ee8fdb0f366e35 (diff)
[MTD] NAND: CAFÉ NAND driver cleanup, fix ECC on reading empty flash
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/Makefile3
-rw-r--r--drivers/mtd/nand/cafe.c149
-rw-r--r--drivers/mtd/nand/cafe_ecc.c5
3 files changed, 109 insertions, 48 deletions
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 7cebc10c474e..f7a53f0b7017 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -25,4 +25,5 @@ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
26obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o 26obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
27 27
28nand-objs = nand_base.o nand_bbt.o 28nand-objs := nand_base.o nand_bbt.o
29cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
index 1fe110836cc1..10132efd0588 100644
--- a/drivers/mtd/nand/cafe.c
+++ b/drivers/mtd/nand/cafe.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * cafe_nand.c 2 * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
3 * 3 *
4 * Copyright © 2006 Red Hat, Inc. 4 * Copyright © 2006 Red Hat, Inc.
5 * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> 5 * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
@@ -30,13 +30,13 @@
30#define CAFE_NAND_TIMING3 0x2c 30#define CAFE_NAND_TIMING3 0x2c
31#define CAFE_NAND_NONMEM 0x30 31#define CAFE_NAND_NONMEM 0x30
32#define CAFE_NAND_ECC_RESULT 0x3C 32#define CAFE_NAND_ECC_RESULT 0x3C
33#define CAFE_NAND_DMA_CTRL 0x40
34#define CAFE_NAND_DMA_ADDR0 0x44
35#define CAFE_NAND_DMA_ADDR1 0x48
33#define CAFE_NAND_ECC_SYN01 0x50 36#define CAFE_NAND_ECC_SYN01 0x50
34#define CAFE_NAND_ECC_SYN23 0x54 37#define CAFE_NAND_ECC_SYN23 0x54
35#define CAFE_NAND_ECC_SYN45 0x58 38#define CAFE_NAND_ECC_SYN45 0x58
36#define CAFE_NAND_ECC_SYN67 0x5c 39#define CAFE_NAND_ECC_SYN67 0x5c
37#define CAFE_NAND_DMA_CTRL 0x40
38#define CAFE_NAND_DMA_ADDR0 0x44
39#define CAFE_NAND_DMA_ADDR1 0x48
40#define CAFE_NAND_READ_DATA 0x1000 40#define CAFE_NAND_READ_DATA 0x1000
41#define CAFE_NAND_WRITE_DATA 0x2000 41#define CAFE_NAND_WRITE_DATA 0x2000
42 42
@@ -75,12 +75,14 @@ static int cafe_device_ready(struct mtd_info *mtd)
75{ 75{
76 struct cafe_priv *cafe = mtd->priv; 76 struct cafe_priv *cafe = mtd->priv;
77 int result = !!(readl(cafe->mmio + CAFE_NAND_STATUS) | 0x40000000); 77 int result = !!(readl(cafe->mmio + CAFE_NAND_STATUS) | 0x40000000);
78
79 uint32_t irqs = readl(cafe->mmio + CAFE_NAND_IRQ); 78 uint32_t irqs = readl(cafe->mmio + CAFE_NAND_IRQ);
79
80 writel(irqs, cafe->mmio+CAFE_NAND_IRQ); 80 writel(irqs, cafe->mmio+CAFE_NAND_IRQ);
81
81 cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n", 82 cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
82 result?"":" not", irqs, readl(cafe->mmio + CAFE_NAND_IRQ), 83 result?"":" not", irqs, readl(cafe->mmio + CAFE_NAND_IRQ),
83 readl(cafe->mmio + 0x3008), readl(cafe->mmio + 0x300c)); 84 readl(cafe->mmio + 0x3008), readl(cafe->mmio + 0x300c));
85
84 return result; 86 return result;
85} 87}
86 88
@@ -93,6 +95,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
93 memcpy(cafe->dmabuf + cafe->datalen, buf, len); 95 memcpy(cafe->dmabuf + cafe->datalen, buf, len);
94 else 96 else
95 memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len); 97 memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len);
98
96 cafe->datalen += len; 99 cafe->datalen += len;
97 100
98 cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n", 101 cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
@@ -131,14 +134,13 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
131 int adrbytes = 0; 134 int adrbytes = 0;
132 uint32_t ctl1; 135 uint32_t ctl1;
133 uint32_t doneint = 0x80000000; 136 uint32_t doneint = 0x80000000;
134 int i;
135 137
136 cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n", 138 cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
137 command, column, page_addr); 139 command, column, page_addr);
138 140
139 if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) { 141 if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
140 /* Second half of a command we already calculated */ 142 /* Second half of a command we already calculated */
141 writel(cafe->ctl2 | 0x100 | command, cafe->mmio + 0x04); 143 writel(cafe->ctl2 | 0x100 | command, cafe->mmio + CAFE_NAND_CTRL2);
142 ctl1 = cafe->ctl1; 144 ctl1 = cafe->ctl1;
143 cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n", 145 cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
144 cafe->ctl1, cafe->nr_data); 146 cafe->ctl1, cafe->nr_data);
@@ -158,12 +160,12 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
158 for small-page chips, to position the buffer correctly? */ 160 for small-page chips, to position the buffer correctly? */
159 161
160 if (column != -1) { 162 if (column != -1) {
161 writel(column, cafe->mmio + 0x1c); 163 writel(column, cafe->mmio + CAFE_NAND_ADDR1);
162 adrbytes = 2; 164 adrbytes = 2;
163 if (page_addr != -1) 165 if (page_addr != -1)
164 goto write_adr2; 166 goto write_adr2;
165 } else if (page_addr != -1) { 167 } else if (page_addr != -1) {
166 writel(page_addr & 0xffff, cafe->mmio + 0x1c); 168 writel(page_addr & 0xffff, cafe->mmio + CAFE_NAND_ADDR1);
167 page_addr >>= 16; 169 page_addr >>= 16;
168 write_adr2: 170 write_adr2:
169 writel(page_addr, cafe->mmio+0x20); 171 writel(page_addr, cafe->mmio+0x20);
@@ -212,13 +214,15 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
212 writel(cafe->ctl2 | 0x100 | NAND_CMD_READSTART, cafe->mmio + CAFE_NAND_CTRL2); 214 writel(cafe->ctl2 | 0x100 | NAND_CMD_READSTART, cafe->mmio + CAFE_NAND_CTRL2);
213 215
214 do_command: 216 do_command:
215#if 0 217#if 1
216 // ECC on read only works if we ... 218 /* http://dev.laptop.org/ticket/200
219 ECC on read only works if we read precisely 0x80e bytes */
217 if (cafe->datalen == 2112) 220 if (cafe->datalen == 2112)
218 cafe->datalen = 2062; 221 cafe->datalen = 2062;
219#endif 222#endif
220 cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n", 223 cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
221 cafe->datalen, ctl1, readl(cafe->mmio+CAFE_NAND_CTRL2)); 224 cafe->datalen, ctl1, readl(cafe->mmio+CAFE_NAND_CTRL2));
225
222 /* NB: The datasheet lies -- we really should be subtracting 1 here */ 226 /* NB: The datasheet lies -- we really should be subtracting 1 here */
223 writel(cafe->datalen, cafe->mmio + CAFE_NAND_DATA_LEN); 227 writel(cafe->datalen, cafe->mmio + CAFE_NAND_DATA_LEN);
224 writel(0x90000000, cafe->mmio + CAFE_NAND_IRQ); 228 writel(0x90000000, cafe->mmio + CAFE_NAND_IRQ);
@@ -232,18 +236,16 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
232 the command. */ 236 the command. */
233 doneint = 0x10000000; 237 doneint = 0x10000000;
234 } 238 }
235 writel(dmactl, cafe->mmio + 0x40); 239 writel(dmactl, cafe->mmio + CAFE_NAND_DMA_CTRL);
236 } 240 }
237#if 0
238 printk("DMA setup is %x, status %x, ctl1 %x\n", readl(cafe->mmio + 0x40), readl(cafe->mmio + 0x0c), readl(cafe->mmio));
239 printk("DMA setup is %x, status %x, ctl1 %x\n", readl(cafe->mmio + 0x40), readl(cafe->mmio + 0x0c), readl(cafe->mmio));
240#endif
241 cafe->datalen = 0; 241 cafe->datalen = 0;
242 242
243#if 0 243#if 0
244 { int i;
244 printk("About to write command %08x\n", ctl1); 245 printk("About to write command %08x\n", ctl1);
245 for (i=0; i< 0x5c; i+=4) 246 for (i=0; i< 0x5c; i+=4)
246 printk("Register %x: %08x\n", i, readl(cafe->mmio + i)); 247 printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
248 }
247#endif 249#endif
248 writel(ctl1, cafe->mmio + CAFE_NAND_CTRL1); 250 writel(ctl1, cafe->mmio + CAFE_NAND_CTRL1);
249 /* Apply this short delay always to ensure that we do wait tWB in 251 /* Apply this short delay always to ensure that we do wait tWB in
@@ -299,6 +301,7 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
299 //struct cafe_priv *cafe = mtd->priv; 301 //struct cafe_priv *cafe = mtd->priv;
300 // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); 302 // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
301} 303}
304
302static int cafe_nand_interrupt(int irq, void *id, struct pt_regs *regs) 305static int cafe_nand_interrupt(int irq, void *id, struct pt_regs *regs)
303{ 306{
304 struct mtd_info *mtd = id; 307 struct mtd_info *mtd = id;
@@ -347,14 +350,34 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
347 * The hw generator calculates the error syndrome automatically. Therefor 350 * The hw generator calculates the error syndrome automatically. Therefor
348 * we need a special oob layout and handling. 351 * we need a special oob layout and handling.
349 */ 352 */
353
354static unsigned short cafe_empty_syndromes[8] = { 4095, 748, 2629, 2920, 875, 1454, 51, 1456 };
355
356static int is_all_ff(unsigned char *buf, int len)
357{
358 unsigned long *lbuf = (void *)buf;
359 int i;
360
361 for (i=0; i < (len/sizeof(long)); i++) {
362 if (lbuf[i] != ~0UL)
363 return 0;
364 }
365 i *= sizeof(long);
366 for (; i< len; i++) {
367 if (buf[i] != 0xff)
368 return 0;
369 }
370 return 1;
371}
372
350static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, 373static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
351 uint8_t *buf) 374 uint8_t *buf)
352{ 375{
353 struct cafe_priv *cafe = mtd->priv; 376 struct cafe_priv *cafe = mtd->priv;
354 377
355 dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", 378 cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
356 readl(cafe->mmio + CAFE_NAND_ECC_RESULT), 379 readl(cafe->mmio + CAFE_NAND_ECC_RESULT),
357 readl(cafe->mmio + CAFE_NAND_ECC_SYN01)); 380 readl(cafe->mmio + CAFE_NAND_ECC_SYN01));
358 381
359 chip->read_buf(mtd, buf, mtd->writesize); 382 chip->read_buf(mtd, buf, mtd->writesize);
360 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 383 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -369,7 +392,13 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
369 syn[i+1] = (tmp >> 16) & 0xfff; 392 syn[i+1] = (tmp >> 16) & 0xfff;
370 } 393 }
371 394
372 if ((i = cafe_correct_ecc(buf, syn)) < 0) { 395 /* FIXME: http://dev.laptop.org/ticket/215 */
396 if (!memcmp(syn, cafe_empty_syndromes, sizeof(syn))
397 && is_all_ff(chip->oob_poi, 14)
398 && is_all_ff(buf, mtd->writesize)) {
399 dev_dbg(&cafe->pdev->dev, "ECC error reported on empty block\n");
400 /* It was an empty block. Nothing to fix here except the hardware */
401 } else if ((i = cafe_correct_ecc(buf, syn)) < 0) {
373 dev_dbg(&cafe->pdev->dev, "Failed to correct ECC\n"); 402 dev_dbg(&cafe->pdev->dev, "Failed to correct ECC\n");
374 mtd->ecc_stats.failed++; 403 mtd->ecc_stats.failed++;
375 } else { 404 } else {
@@ -389,9 +418,13 @@ static struct nand_ecclayout cafe_oobinfo_2048 = {
389}; 418};
390 419
391/* Ick. The BBT code really ought to be able to work this bit out 420/* Ick. The BBT code really ought to be able to work this bit out
392 for itself from the above */ 421 for itself from the above, at least for the 2KiB case */
393static uint8_t cafe_bbt_pattern[] = {'B', 'b', 't', '0' }; 422static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
394static uint8_t cafe_mirror_pattern[] = {'1', 't', 'b', 'B' }; 423static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
424
425static uint8_t cafe_bbt_pattern_512[] = { 0xBB };
426static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
427
395 428
396static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { 429static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
397 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 430 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
@@ -400,7 +433,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
400 .len = 4, 433 .len = 4,
401 .veroffs = 18, 434 .veroffs = 18,
402 .maxblocks = 4, 435 .maxblocks = 4,
403 .pattern = cafe_bbt_pattern 436 .pattern = cafe_bbt_pattern_2048
404}; 437};
405 438
406static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = { 439static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
@@ -410,7 +443,7 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
410 .len = 4, 443 .len = 4,
411 .veroffs = 18, 444 .veroffs = 18,
412 .maxblocks = 4, 445 .maxblocks = 4,
413 .pattern = cafe_mirror_pattern 446 .pattern = cafe_mirror_pattern_2048
414}; 447};
415 448
416static struct nand_ecclayout cafe_oobinfo_512 = { 449static struct nand_ecclayout cafe_oobinfo_512 = {
@@ -419,6 +452,27 @@ static struct nand_ecclayout cafe_oobinfo_512 = {
419 .oobfree = {{14, 2}} 452 .oobfree = {{14, 2}}
420}; 453};
421 454
455static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
456 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
457 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
458 .offs = 14,
459 .len = 1,
460 .veroffs = 15,
461 .maxblocks = 4,
462 .pattern = cafe_bbt_pattern_512
463};
464
465static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
466 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
467 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
468 .offs = 14,
469 .len = 1,
470 .veroffs = 15,
471 .maxblocks = 4,
472 .pattern = cafe_mirror_pattern_512
473};
474
475
422static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, 476static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
423 struct nand_chip *chip, const uint8_t *buf) 477 struct nand_chip *chip, const uint8_t *buf)
424{ 478{
@@ -566,19 +620,21 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
566 ctrl |= 0x00007000; 620 ctrl |= 0x00007000;
567 writel(ctrl | 0x05, cafe->mmio + 0x3004); 621 writel(ctrl | 0x05, cafe->mmio + 0x3004);
568 writel(ctrl | 0x0a, cafe->mmio + 0x3004); 622 writel(ctrl | 0x0a, cafe->mmio + 0x3004);
569 writel(0, cafe->mmio + 0x40); 623 writel(0, cafe->mmio + CAFE_NAND_DMA_CTRL);
570 624
571 writel(0x7006, cafe->mmio + 0x3004); 625 writel(0x7006, cafe->mmio + 0x3004);
572 writel(0x700a, cafe->mmio + 0x3004); 626 writel(0x700a, cafe->mmio + 0x3004);
573 627
574 /* Set up DMA address */ 628 /* Set up DMA address */
575 writel(cafe->dmaaddr & 0xffffffff, cafe->mmio + 0x44); 629 writel(cafe->dmaaddr & 0xffffffff, cafe->mmio + CAFE_NAND_DMA_ADDR0);
576 if (sizeof(cafe->dmaaddr) > 4) 630 if (sizeof(cafe->dmaaddr) > 4)
577 writel((cafe->dmaaddr >> 16) >> 16, cafe->mmio + 0x48); 631 /* Shift in two parts to shut the compiler up */
632 writel((cafe->dmaaddr >> 16) >> 16, cafe->mmio + CAFE_NAND_DMA_ADDR1);
578 else 633 else
579 writel(0, cafe->mmio + 0x48); 634 writel(0, cafe->mmio + CAFE_NAND_DMA_ADDR1);
635
580 cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", 636 cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
581 readl(cafe->mmio+0x44), cafe->dmabuf); 637 readl(cafe->mmio + CAFE_NAND_DMA_ADDR0), cafe->dmabuf);
582 638
583 /* Enable NAND IRQ in global IRQ mask register */ 639 /* Enable NAND IRQ in global IRQ mask register */
584 writel(0x80000007, cafe->mmio + 0x300c); 640 writel(0x80000007, cafe->mmio + 0x300c);
@@ -620,27 +676,30 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
620 cafe->ctl2 |= 1<<29; /* 2KiB page size */ 676 cafe->ctl2 |= 1<<29; /* 2KiB page size */
621 677
622 /* Set up ECC according to the type of chip we found */ 678 /* Set up ECC according to the type of chip we found */
623 if (mtd->writesize == 512 || mtd->writesize == 2048) { 679 if (mtd->writesize == 2048) {
624 cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
625 cafe->nand.ecc.size = mtd->writesize;
626 cafe->nand.ecc.bytes = 14;
627 cafe->nand.ecc.layout = &cafe_oobinfo_2048; 680 cafe->nand.ecc.layout = &cafe_oobinfo_2048;
628 cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; 681 cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
629 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; 682 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
630 cafe->nand.ecc.hwctl = (void *)cafe_nand_bug; 683 } else if (mtd->writesize == 512) {
631 cafe->nand.ecc.calculate = (void *)cafe_nand_bug; 684 cafe->nand.ecc.layout = &cafe_oobinfo_512;
632 cafe->nand.ecc.correct = (void *)cafe_nand_bug; 685 cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
633 cafe->nand.write_page = cafe_nand_write_page; 686 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
634 cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
635 cafe->nand.ecc.write_oob = cafe_nand_write_oob;
636 cafe->nand.ecc.read_page = cafe_nand_read_page;
637 cafe->nand.ecc.read_oob = cafe_nand_read_oob;
638
639 } else { 687 } else {
640 printk(KERN_WARNING "Unexpected NAND flash writesize %d. Using software ECC\n", 688 printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
641 mtd->writesize); 689 mtd->writesize);
642 cafe->nand.ecc.mode = NAND_ECC_NONE; 690 goto out_irq;
643 } 691 }
692 cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
693 cafe->nand.ecc.size = mtd->writesize;
694 cafe->nand.ecc.bytes = 14;
695 cafe->nand.ecc.hwctl = (void *)cafe_nand_bug;
696 cafe->nand.ecc.calculate = (void *)cafe_nand_bug;
697 cafe->nand.ecc.correct = (void *)cafe_nand_bug;
698 cafe->nand.write_page = cafe_nand_write_page;
699 cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
700 cafe->nand.ecc.write_oob = cafe_nand_write_oob;
701 cafe->nand.ecc.read_page = cafe_nand_read_page;
702 cafe->nand.ecc.read_oob = cafe_nand_read_oob;
644 703
645 err = nand_scan_tail(mtd); 704 err = nand_scan_tail(mtd);
646 if (err) 705 if (err)
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
index 4df28a846fbc..c4bec37e73eb 100644
--- a/drivers/mtd/nand/cafe_ecc.c
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -499,10 +499,11 @@ static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
499} 499}
500 500
501static unsigned char gf64_inv[64] = { 501static unsigned char gf64_inv[64] = {
502 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25, 502 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
503 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6, 503 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6,
504 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41, 504 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41,
505 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32}; 505 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32
506};
506 507
507static unsigned short gf4096_inv(unsigned short din) 508static unsigned short gf4096_inv(unsigned short din)
508{ 509{