diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-10-19 21:11:40 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-10-19 21:11:40 -0400 |
commit | 8dd851de8184bb39c4ea86de20a0ed2496e6eb0d (patch) | |
tree | c391ac32f289e335628a00d0e9cc4f55acfccb27 /drivers/mtd/nand | |
parent | 5467fb025537eb92313fd3a557b2051cb41ba5e8 (diff) |
[MTD NAND] OLPC CAFÉ driver update
- Fix OOB handling, bad block table marker placement
- Some cleanups, enable runtime-optional debugging
- Allow BBT stuff to be skipped
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/cafe_nand.c | 135 |
1 files changed, 99 insertions, 36 deletions
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 8d7a795a9478..60cb019b1406 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> | 5 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | //#define DEBUG | 8 | #define DEBUG |
9 | 9 | ||
10 | #include <linux/device.h> | 10 | #include <linux/device.h> |
11 | #undef DEBUG | 11 | #undef DEBUG |
@@ -53,15 +53,24 @@ struct cafe_priv { | |||
53 | static int usedma = 1; | 53 | static int usedma = 1; |
54 | module_param(usedma, int, 0644); | 54 | module_param(usedma, int, 0644); |
55 | 55 | ||
56 | static int skipbbt = 0; | ||
57 | module_param(skipbbt, int, 0644); | ||
58 | |||
59 | static int debug = 0; | ||
60 | module_param(debug, int, 0644); | ||
61 | |||
62 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) | ||
63 | |||
64 | |||
56 | static int cafe_device_ready(struct mtd_info *mtd) | 65 | static int cafe_device_ready(struct mtd_info *mtd) |
57 | { | 66 | { |
58 | struct cafe_priv *cafe = mtd->priv; | 67 | struct cafe_priv *cafe = mtd->priv; |
59 | int result = !!(readl(cafe->mmio + CAFE_NAND_STATUS) | 0x40000000); | 68 | int result = !!(readl(cafe->mmio + CAFE_NAND_STATUS) | 0x40000000); |
60 | 69 | ||
61 | uint32_t irqs = readl(cafe->mmio + 0x10); | 70 | uint32_t irqs = readl(cafe->mmio + CAFE_NAND_IRQ); |
62 | writel(irqs, cafe->mmio+0x10); | 71 | writel(irqs, cafe->mmio+CAFE_NAND_IRQ); |
63 | dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n", | 72 | cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n", |
64 | result?"":" not", irqs, readl(cafe->mmio + 0x10), | 73 | result?"":" not", irqs, readl(cafe->mmio + CAFE_NAND_IRQ), |
65 | readl(cafe->mmio + 0x3008), readl(cafe->mmio + 0x300c)); | 74 | readl(cafe->mmio + 0x3008), readl(cafe->mmio + 0x300c)); |
66 | return result; | 75 | return result; |
67 | } | 76 | } |
@@ -77,7 +86,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
77 | memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len); | 86 | memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len); |
78 | cafe->datalen += len; | 87 | cafe->datalen += len; |
79 | 88 | ||
80 | dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n", | 89 | cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n", |
81 | len, cafe->datalen); | 90 | len, cafe->datalen); |
82 | } | 91 | } |
83 | 92 | ||
@@ -90,7 +99,7 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
90 | else | 99 | else |
91 | memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len); | 100 | memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len); |
92 | 101 | ||
93 | dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n", | 102 | cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n", |
94 | len, cafe->datalen); | 103 | len, cafe->datalen); |
95 | cafe->datalen += len; | 104 | cafe->datalen += len; |
96 | } | 105 | } |
@@ -101,7 +110,7 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd) | |||
101 | uint8_t d; | 110 | uint8_t d; |
102 | 111 | ||
103 | cafe_read_buf(mtd, &d, 1); | 112 | cafe_read_buf(mtd, &d, 1); |
104 | dev_dbg(&cafe->pdev->dev, "Read %02x\n", d); | 113 | cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d); |
105 | 114 | ||
106 | return d; | 115 | return d; |
107 | } | 116 | } |
@@ -115,14 +124,14 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
115 | uint32_t doneint = 0x80000000; | 124 | uint32_t doneint = 0x80000000; |
116 | int i; | 125 | int i; |
117 | 126 | ||
118 | dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n", | 127 | cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n", |
119 | command, column, page_addr); | 128 | command, column, page_addr); |
120 | 129 | ||
121 | if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) { | 130 | if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) { |
122 | /* Second half of a command we already calculated */ | 131 | /* Second half of a command we already calculated */ |
123 | writel(cafe->ctl2 | 0x100 | command, cafe->mmio + 0x04); | 132 | writel(cafe->ctl2 | 0x100 | command, cafe->mmio + 0x04); |
124 | ctl1 = cafe->ctl1; | 133 | ctl1 = cafe->ctl1; |
125 | dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n", | 134 | cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n", |
126 | cafe->ctl1, cafe->nr_data); | 135 | cafe->ctl1, cafe->nr_data); |
127 | goto do_command; | 136 | goto do_command; |
128 | } | 137 | } |
@@ -163,7 +172,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
163 | if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) { | 172 | if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) { |
164 | ctl1 |= (1<<26); /* rd */ | 173 | ctl1 |= (1<<26); /* rd */ |
165 | /* Always 5 bytes, for now */ | 174 | /* Always 5 bytes, for now */ |
166 | cafe->datalen = 5; | 175 | cafe->datalen = 4; |
167 | /* And one address cycle -- even for STATUS, since the controller doesn't work without */ | 176 | /* And one address cycle -- even for STATUS, since the controller doesn't work without */ |
168 | adrbytes = 1; | 177 | adrbytes = 1; |
169 | } else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || | 178 | } else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || |
@@ -183,7 +192,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
183 | deals with them both at once, later */ | 192 | deals with them both at once, later */ |
184 | cafe->ctl1 = ctl1; | 193 | cafe->ctl1 = ctl1; |
185 | cafe->ctl2 = 0; | 194 | cafe->ctl2 = 0; |
186 | dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n", | 195 | cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n", |
187 | cafe->ctl1, cafe->datalen); | 196 | cafe->ctl1, cafe->datalen); |
188 | return; | 197 | return; |
189 | } | 198 | } |
@@ -194,13 +203,14 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
194 | writel(cafe->ctl2 | 0x100 | NAND_CMD_READSTART, cafe->mmio + CAFE_NAND_CTRL2); | 203 | writel(cafe->ctl2 | 0x100 | NAND_CMD_READSTART, cafe->mmio + CAFE_NAND_CTRL2); |
195 | 204 | ||
196 | do_command: | 205 | do_command: |
197 | if (cafe->datalen == 2112) | 206 | // ECC on read only works if we ... |
198 | cafe->datalen = 2062; | 207 | // if (cafe->datalen == 2112) |
199 | dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n", | 208 | // cafe->datalen = 2062; |
209 | cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n", | ||
200 | cafe->datalen, ctl1, readl(cafe->mmio+CAFE_NAND_CTRL2)); | 210 | cafe->datalen, ctl1, readl(cafe->mmio+CAFE_NAND_CTRL2)); |
201 | /* NB: The datasheet lies -- we really should be subtracting 1 here */ | 211 | /* NB: The datasheet lies -- we really should be subtracting 1 here */ |
202 | writel(cafe->datalen, cafe->mmio + CAFE_NAND_DATA_LEN); | 212 | writel(cafe->datalen, cafe->mmio + CAFE_NAND_DATA_LEN); |
203 | writel(0x90000000, cafe->mmio + 0x10); | 213 | writel(0x90000000, cafe->mmio + CAFE_NAND_IRQ); |
204 | if (usedma && (ctl1 & (3<<25))) { | 214 | if (usedma && (ctl1 & (3<<25))) { |
205 | uint32_t dmactl = 0xc0000000 + cafe->datalen; | 215 | uint32_t dmactl = 0xc0000000 + cafe->datalen; |
206 | /* If WR or RD bits set, set up DMA */ | 216 | /* If WR or RD bits set, set up DMA */ |
@@ -230,20 +240,20 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
230 | ndelay(100); | 240 | ndelay(100); |
231 | 241 | ||
232 | if (1) { | 242 | if (1) { |
233 | int c = 50000; | 243 | int c = 500000; |
234 | uint32_t irqs; | 244 | uint32_t irqs; |
235 | 245 | ||
236 | while (c--) { | 246 | while (c--) { |
237 | irqs = readl(cafe->mmio + 0x10); | 247 | irqs = readl(cafe->mmio + CAFE_NAND_IRQ); |
238 | if (irqs & doneint) | 248 | if (irqs & doneint) |
239 | break; | 249 | break; |
240 | udelay(1); | 250 | udelay(1); |
241 | if (!(c & 1000)) | 251 | if (!(c % 100000)) |
242 | dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs); | 252 | cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs); |
243 | cpu_relax(); | 253 | cpu_relax(); |
244 | } | 254 | } |
245 | writel(doneint, cafe->mmio + 0x10); | 255 | writel(doneint, cafe->mmio + CAFE_NAND_IRQ); |
246 | dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n", command, 50000-c, irqs, readl(cafe->mmio + 0x10)); | 256 | cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n", command, 50000-c, irqs, readl(cafe->mmio + CAFE_NAND_IRQ)); |
247 | } | 257 | } |
248 | 258 | ||
249 | 259 | ||
@@ -276,18 +286,18 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
276 | static void cafe_select_chip(struct mtd_info *mtd, int chipnr) | 286 | static void cafe_select_chip(struct mtd_info *mtd, int chipnr) |
277 | { | 287 | { |
278 | //struct cafe_priv *cafe = mtd->priv; | 288 | //struct cafe_priv *cafe = mtd->priv; |
279 | // dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); | 289 | // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); |
280 | } | 290 | } |
281 | static int cafe_nand_interrupt(int irq, void *id, struct pt_regs *regs) | 291 | static int cafe_nand_interrupt(int irq, void *id, struct pt_regs *regs) |
282 | { | 292 | { |
283 | struct mtd_info *mtd = id; | 293 | struct mtd_info *mtd = id; |
284 | struct cafe_priv *cafe = mtd->priv; | 294 | struct cafe_priv *cafe = mtd->priv; |
285 | uint32_t irqs = readl(cafe->mmio + 0x10); | 295 | uint32_t irqs = readl(cafe->mmio + CAFE_NAND_IRQ); |
286 | writel(irqs & ~0x90000000, cafe->mmio + 0x10); | 296 | writel(irqs & ~0x90000000, cafe->mmio + CAFE_NAND_IRQ); |
287 | if (!irqs) | 297 | if (!irqs) |
288 | return IRQ_NONE; | 298 | return IRQ_NONE; |
289 | 299 | ||
290 | dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, readl(cafe->mmio + 0x10)); | 300 | cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, readl(cafe->mmio + CAFE_NAND_IRQ)); |
291 | return IRQ_HANDLED; | 301 | return IRQ_HANDLED; |
292 | } | 302 | } |
293 | 303 | ||
@@ -335,7 +345,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
335 | 345 | ||
336 | WARN_ON(chip->oob_poi != chip->buffers->oobrbuf); | 346 | WARN_ON(chip->oob_poi != chip->buffers->oobrbuf); |
337 | 347 | ||
338 | dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", readl(cafe->mmio + 0x3c), readl(cafe->mmio + 0x50)); | 348 | cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", readl(cafe->mmio + 0x3c), readl(cafe->mmio + 0x50)); |
339 | 349 | ||
340 | chip->read_buf(mtd, buf, mtd->writesize); | 350 | chip->read_buf(mtd, buf, mtd->writesize); |
341 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 351 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -343,7 +353,44 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
343 | return 0; | 353 | return 0; |
344 | } | 354 | } |
345 | 355 | ||
346 | static char foo[14]; | 356 | static struct nand_ecclayout cafe_oobinfo_2048 = { |
357 | .eccbytes = 14, | ||
358 | .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, | ||
359 | .oobfree = {{14, 50}} | ||
360 | }; | ||
361 | |||
362 | /* Ick. The BBT code really ought to be able to work this bit out | ||
363 | for itself from the above */ | ||
364 | static uint8_t cafe_bbt_pattern[] = {'B', 'b', 't', '0' }; | ||
365 | static uint8_t cafe_mirror_pattern[] = {'1', 't', 'b', 'B' }; | ||
366 | |||
367 | static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { | ||
368 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
369 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | ||
370 | .offs = 14, | ||
371 | .len = 4, | ||
372 | .veroffs = 18, | ||
373 | .maxblocks = 4, | ||
374 | .pattern = cafe_bbt_pattern | ||
375 | }; | ||
376 | |||
377 | static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = { | ||
378 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
379 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | ||
380 | .offs = 14, | ||
381 | .len = 4, | ||
382 | .veroffs = 18, | ||
383 | .maxblocks = 4, | ||
384 | .pattern = cafe_mirror_pattern | ||
385 | }; | ||
386 | |||
387 | static struct nand_ecclayout cafe_oobinfo_512 = { | ||
388 | .eccbytes = 14, | ||
389 | .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, | ||
390 | .oobfree = {{14, 2}} | ||
391 | }; | ||
392 | |||
393 | |||
347 | static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, | 394 | static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, |
348 | struct nand_chip *chip, const uint8_t *buf) | 395 | struct nand_chip *chip, const uint8_t *buf) |
349 | { | 396 | { |
@@ -352,8 +399,7 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, | |||
352 | WARN_ON(chip->oob_poi != chip->buffers->oobwbuf); | 399 | WARN_ON(chip->oob_poi != chip->buffers->oobwbuf); |
353 | 400 | ||
354 | chip->write_buf(mtd, buf, mtd->writesize); | 401 | chip->write_buf(mtd, buf, mtd->writesize); |
355 | chip->write_buf(mtd, foo, 14); | 402 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
356 | // chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
357 | 403 | ||
358 | /* Set up ECC autogeneration */ | 404 | /* Set up ECC autogeneration */ |
359 | cafe->ctl2 |= (1<<27) | (1<<30); | 405 | cafe->ctl2 |= (1<<27) | (1<<30); |
@@ -410,6 +456,10 @@ static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
410 | return 0; | 456 | return 0; |
411 | } | 457 | } |
412 | 458 | ||
459 | static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | ||
460 | { | ||
461 | return 0; | ||
462 | } | ||
413 | 463 | ||
414 | static int __devinit cafe_nand_probe(struct pci_dev *pdev, | 464 | static int __devinit cafe_nand_probe(struct pci_dev *pdev, |
415 | const struct pci_device_id *ent) | 465 | const struct pci_device_id *ent) |
@@ -461,6 +511,11 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
461 | 511 | ||
462 | /* Enable the following for a flash based bad block table */ | 512 | /* Enable the following for a flash based bad block table */ |
463 | cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; | 513 | cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; |
514 | |||
515 | if (skipbbt) { | ||
516 | cafe->nand.options |= NAND_SKIP_BBTSCAN; | ||
517 | cafe->nand.block_bad = cafe_nand_block_bad; | ||
518 | } | ||
464 | 519 | ||
465 | /* Timings from Marvell's test code (not verified or calculated by us) */ | 520 | /* Timings from Marvell's test code (not verified or calculated by us) */ |
466 | writel(0xffffffff, cafe->mmio + CAFE_NAND_IRQ_MASK); | 521 | writel(0xffffffff, cafe->mmio + CAFE_NAND_IRQ_MASK); |
@@ -473,7 +528,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
473 | writel(0xffffffff, cafe->mmio + CAFE_NAND_TIMING2); | 528 | writel(0xffffffff, cafe->mmio + CAFE_NAND_TIMING2); |
474 | writel(0xffffffff, cafe->mmio + CAFE_NAND_TIMING3); | 529 | writel(0xffffffff, cafe->mmio + CAFE_NAND_TIMING3); |
475 | #endif | 530 | #endif |
476 | writel(0xdfffffff, cafe->mmio + 0x14); | 531 | writel(0xffffffff, cafe->mmio + CAFE_NAND_IRQ_MASK); |
477 | err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd); | 532 | err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd); |
478 | if (err) { | 533 | if (err) { |
479 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); | 534 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); |
@@ -498,18 +553,18 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
498 | writel((cafe->dmaaddr >> 16) >> 16, cafe->mmio + 0x48); | 553 | writel((cafe->dmaaddr >> 16) >> 16, cafe->mmio + 0x48); |
499 | else | 554 | else |
500 | writel(0, cafe->mmio + 0x48); | 555 | writel(0, cafe->mmio + 0x48); |
501 | dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", | 556 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", |
502 | readl(cafe->mmio+0x44), cafe->dmabuf); | 557 | readl(cafe->mmio+0x44), cafe->dmabuf); |
503 | 558 | ||
504 | /* Enable NAND IRQ in global IRQ mask register */ | 559 | /* Enable NAND IRQ in global IRQ mask register */ |
505 | writel(0x80000007, cafe->mmio + 0x300c); | 560 | writel(0x80000007, cafe->mmio + 0x300c); |
506 | dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", | 561 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", |
507 | readl(cafe->mmio + 0x3004), readl(cafe->mmio + 0x300c)); | 562 | readl(cafe->mmio + 0x3004), readl(cafe->mmio + 0x300c)); |
508 | #endif | 563 | #endif |
509 | #if 1 | 564 | #if 1 |
510 | mtd->writesize=2048; | 565 | mtd->writesize=2048; |
511 | mtd->oobsize = 0x40; | 566 | mtd->oobsize = 0x40; |
512 | memset(cafe->dmabuf, 0xa5, 2112); | 567 | memset(cafe->dmabuf, 0x5a, 2112); |
513 | cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1); | 568 | cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1); |
514 | cafe->nand.read_byte(mtd); | 569 | cafe->nand.read_byte(mtd); |
515 | cafe->nand.read_byte(mtd); | 570 | cafe->nand.read_byte(mtd); |
@@ -528,7 +583,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
528 | #if 0 | 583 | #if 0 |
529 | writel(0x84600070, cafe->mmio); | 584 | writel(0x84600070, cafe->mmio); |
530 | udelay(10); | 585 | udelay(10); |
531 | dev_dbg(&cafe->pdev->dev, "Status %x\n", readl(cafe->mmio + 0x30)); | 586 | cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", readl(cafe->mmio + 0x30)); |
532 | #endif | 587 | #endif |
533 | /* Scan to find existance of the device */ | 588 | /* Scan to find existance of the device */ |
534 | if (nand_scan_ident(mtd, 1)) { | 589 | if (nand_scan_ident(mtd, 1)) { |
@@ -545,6 +600,9 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
545 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | 600 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; |
546 | cafe->nand.ecc.size = mtd->writesize; | 601 | cafe->nand.ecc.size = mtd->writesize; |
547 | cafe->nand.ecc.bytes = 14; | 602 | cafe->nand.ecc.bytes = 14; |
603 | cafe->nand.ecc.layout = &cafe_oobinfo_2048; | ||
604 | cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; | ||
605 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; | ||
548 | cafe->nand.ecc.hwctl = (void *)cafe_nand_bug; | 606 | cafe->nand.ecc.hwctl = (void *)cafe_nand_bug; |
549 | cafe->nand.ecc.calculate = (void *)cafe_nand_bug; | 607 | cafe->nand.ecc.calculate = (void *)cafe_nand_bug; |
550 | cafe->nand.ecc.correct = (void *)cafe_nand_bug; | 608 | cafe->nand.ecc.correct = (void *)cafe_nand_bug; |
@@ -564,7 +622,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
564 | if (err) | 622 | if (err) |
565 | goto out_irq; | 623 | goto out_irq; |
566 | 624 | ||
567 | |||
568 | pci_set_drvdata(pdev, mtd); | 625 | pci_set_drvdata(pdev, mtd); |
569 | add_mtd_device(mtd); | 626 | add_mtd_device(mtd); |
570 | goto out; | 627 | goto out; |
@@ -633,3 +690,9 @@ MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip"); | |||
633 | 690 | ||
634 | /* Correct ECC for 2048 bytes of 0xff: | 691 | /* Correct ECC for 2048 bytes of 0xff: |
635 | 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */ | 692 | 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */ |
693 | |||
694 | /* dwmw2's B-test board, in case of completely screwing it: | ||
695 | Bad eraseblock 2394 at 0x12b40000 | ||
696 | Bad eraseblock 2627 at 0x14860000 | ||
697 | Bad eraseblock 3349 at 0x1a2a0000 | ||
698 | */ | ||