diff options
Diffstat (limited to 'drivers/mtd/nand/pxa3xx_nand.c')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 399 |
1 files changed, 187 insertions, 212 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index f44044381360..3264b1d5a638 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <plat/pxa3xx_nand.h> | 27 | #include <plat/pxa3xx_nand.h> |
28 | 28 | ||
29 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) | 29 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) |
30 | #define NAND_STOP_DELAY (2 * HZ/50) | ||
30 | 31 | ||
31 | /* registers and bit definitions */ | 32 | /* registers and bit definitions */ |
32 | #define NDCR (0x00) /* Control register */ | 33 | #define NDCR (0x00) /* Control register */ |
@@ -52,16 +53,18 @@ | |||
52 | #define NDCR_ND_MODE (0x3 << 21) | 53 | #define NDCR_ND_MODE (0x3 << 21) |
53 | #define NDCR_NAND_MODE (0x0) | 54 | #define NDCR_NAND_MODE (0x0) |
54 | #define NDCR_CLR_PG_CNT (0x1 << 20) | 55 | #define NDCR_CLR_PG_CNT (0x1 << 20) |
55 | #define NDCR_CLR_ECC (0x1 << 19) | 56 | #define NDCR_STOP_ON_UNCOR (0x1 << 19) |
56 | #define NDCR_RD_ID_CNT_MASK (0x7 << 16) | 57 | #define NDCR_RD_ID_CNT_MASK (0x7 << 16) |
57 | #define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK) | 58 | #define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK) |
58 | 59 | ||
59 | #define NDCR_RA_START (0x1 << 15) | 60 | #define NDCR_RA_START (0x1 << 15) |
60 | #define NDCR_PG_PER_BLK (0x1 << 14) | 61 | #define NDCR_PG_PER_BLK (0x1 << 14) |
61 | #define NDCR_ND_ARB_EN (0x1 << 12) | 62 | #define NDCR_ND_ARB_EN (0x1 << 12) |
63 | #define NDCR_INT_MASK (0xFFF) | ||
62 | 64 | ||
63 | #define NDSR_MASK (0xfff) | 65 | #define NDSR_MASK (0xfff) |
64 | #define NDSR_RDY (0x1 << 11) | 66 | #define NDSR_RDY (0x1 << 12) |
67 | #define NDSR_FLASH_RDY (0x1 << 11) | ||
65 | #define NDSR_CS0_PAGED (0x1 << 10) | 68 | #define NDSR_CS0_PAGED (0x1 << 10) |
66 | #define NDSR_CS1_PAGED (0x1 << 9) | 69 | #define NDSR_CS1_PAGED (0x1 << 9) |
67 | #define NDSR_CS0_CMDD (0x1 << 8) | 70 | #define NDSR_CS0_CMDD (0x1 << 8) |
@@ -104,13 +107,15 @@ enum { | |||
104 | }; | 107 | }; |
105 | 108 | ||
106 | enum { | 109 | enum { |
107 | STATE_READY = 0, | 110 | STATE_IDLE = 0, |
108 | STATE_CMD_HANDLE, | 111 | STATE_CMD_HANDLE, |
109 | STATE_DMA_READING, | 112 | STATE_DMA_READING, |
110 | STATE_DMA_WRITING, | 113 | STATE_DMA_WRITING, |
111 | STATE_DMA_DONE, | 114 | STATE_DMA_DONE, |
112 | STATE_PIO_READING, | 115 | STATE_PIO_READING, |
113 | STATE_PIO_WRITING, | 116 | STATE_PIO_WRITING, |
117 | STATE_CMD_DONE, | ||
118 | STATE_READY, | ||
114 | }; | 119 | }; |
115 | 120 | ||
116 | struct pxa3xx_nand_info { | 121 | struct pxa3xx_nand_info { |
@@ -292,7 +297,48 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | |||
292 | } | 297 | } |
293 | } | 298 | } |
294 | 299 | ||
295 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | 300 | /** |
301 | * NOTE: it is a must to set ND_RUN firstly, then write | ||
302 | * command buffer, otherwise, it does not work. | ||
303 | * We enable all the interrupt at the same time, and | ||
304 | * let pxa3xx_nand_irq to handle all logic. | ||
305 | */ | ||
306 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) | ||
307 | { | ||
308 | uint32_t ndcr; | ||
309 | |||
310 | ndcr = info->reg_ndcr; | ||
311 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; | ||
312 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; | ||
313 | ndcr |= NDCR_ND_RUN; | ||
314 | |||
315 | /* clear status bits and run */ | ||
316 | nand_writel(info, NDCR, 0); | ||
317 | nand_writel(info, NDSR, NDSR_MASK); | ||
318 | nand_writel(info, NDCR, ndcr); | ||
319 | } | ||
320 | |||
321 | static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) | ||
322 | { | ||
323 | uint32_t ndcr; | ||
324 | int timeout = NAND_STOP_DELAY; | ||
325 | |||
326 | /* wait RUN bit in NDCR become 0 */ | ||
327 | ndcr = nand_readl(info, NDCR); | ||
328 | while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) { | ||
329 | ndcr = nand_readl(info, NDCR); | ||
330 | udelay(1); | ||
331 | } | ||
332 | |||
333 | if (timeout <= 0) { | ||
334 | ndcr &= ~NDCR_ND_RUN; | ||
335 | nand_writel(info, NDCR, ndcr); | ||
336 | } | ||
337 | /* clear status bits */ | ||
338 | nand_writel(info, NDSR, NDSR_MASK); | ||
339 | } | ||
340 | |||
341 | static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | ||
296 | uint16_t cmd, int column, int page_addr) | 342 | uint16_t cmd, int column, int page_addr) |
297 | { | 343 | { |
298 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; | 344 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
@@ -319,21 +365,18 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | |||
319 | 365 | ||
320 | if (cmd == cmdset->program) | 366 | if (cmd == cmdset->program) |
321 | info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; | 367 | info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; |
322 | |||
323 | return 0; | ||
324 | } | 368 | } |
325 | 369 | ||
326 | static int prepare_erase_cmd(struct pxa3xx_nand_info *info, | 370 | static void prepare_erase_cmd(struct pxa3xx_nand_info *info, |
327 | uint16_t cmd, int page_addr) | 371 | uint16_t cmd, int page_addr) |
328 | { | 372 | { |
329 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 373 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
330 | info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); | 374 | info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); |
331 | info->ndcb1 = page_addr; | 375 | info->ndcb1 = page_addr; |
332 | info->ndcb2 = 0; | 376 | info->ndcb2 = 0; |
333 | return 0; | ||
334 | } | 377 | } |
335 | 378 | ||
336 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | 379 | static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) |
337 | { | 380 | { |
338 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; | 381 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
339 | 382 | ||
@@ -343,7 +386,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | |||
343 | 386 | ||
344 | info->oob_size = 0; | 387 | info->oob_size = 0; |
345 | if (cmd == cmdset->read_id) { | 388 | if (cmd == cmdset->read_id) { |
346 | info->ndcb0 |= NDCB0_CMD_TYPE(3); | 389 | info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1); |
347 | info->data_size = 8; | 390 | info->data_size = 8; |
348 | } else if (cmd == cmdset->read_status) { | 391 | } else if (cmd == cmdset->read_status) { |
349 | info->ndcb0 |= NDCB0_CMD_TYPE(4); | 392 | info->ndcb0 |= NDCB0_CMD_TYPE(4); |
@@ -352,9 +395,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | |||
352 | cmd == cmdset->unlock) { | 395 | cmd == cmdset->unlock) { |
353 | info->ndcb0 |= NDCB0_CMD_TYPE(5); | 396 | info->ndcb0 |= NDCB0_CMD_TYPE(5); |
354 | } else | 397 | } else |
355 | return -EINVAL; | 398 | BUG(); |
356 | |||
357 | return 0; | ||
358 | } | 399 | } |
359 | 400 | ||
360 | static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) | 401 | static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) |
@@ -402,10 +443,8 @@ static int write_cmd(struct pxa3xx_nand_info *info) | |||
402 | return 0; | 443 | return 0; |
403 | } | 444 | } |
404 | 445 | ||
405 | static int handle_data_pio(struct pxa3xx_nand_info *info) | 446 | static void handle_data_pio(struct pxa3xx_nand_info *info) |
406 | { | 447 | { |
407 | int ret, timeout = CHIP_DELAY_TIMEOUT; | ||
408 | |||
409 | switch (info->state) { | 448 | switch (info->state) { |
410 | case STATE_PIO_WRITING: | 449 | case STATE_PIO_WRITING: |
411 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, | 450 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, |
@@ -413,14 +452,6 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
413 | if (info->oob_size > 0) | 452 | if (info->oob_size > 0) |
414 | __raw_writesl(info->mmio_base + NDDB, info->oob_buff, | 453 | __raw_writesl(info->mmio_base + NDDB, info->oob_buff, |
415 | DIV_ROUND_UP(info->oob_size, 4)); | 454 | DIV_ROUND_UP(info->oob_size, 4)); |
416 | |||
417 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
418 | |||
419 | ret = wait_for_completion_timeout(&info->cmd_complete, timeout); | ||
420 | if (!ret) { | ||
421 | printk(KERN_ERR "program command time out\n"); | ||
422 | return -1; | ||
423 | } | ||
424 | break; | 455 | break; |
425 | case STATE_PIO_READING: | 456 | case STATE_PIO_READING: |
426 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, | 457 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, |
@@ -432,14 +463,11 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
432 | default: | 463 | default: |
433 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 464 | printk(KERN_ERR "%s: invalid state %d\n", __func__, |
434 | info->state); | 465 | info->state); |
435 | return -EINVAL; | 466 | BUG(); |
436 | } | 467 | } |
437 | |||
438 | info->state = STATE_READY; | ||
439 | return 0; | ||
440 | } | 468 | } |
441 | 469 | ||
442 | static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | 470 | static void start_data_dma(struct pxa3xx_nand_info *info) |
443 | { | 471 | { |
444 | struct pxa_dma_desc *desc = info->data_desc; | 472 | struct pxa_dma_desc *desc = info->data_desc; |
445 | int dma_len = ALIGN(info->data_size + info->oob_size, 32); | 473 | int dma_len = ALIGN(info->data_size + info->oob_size, 32); |
@@ -447,14 +475,21 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | |||
447 | desc->ddadr = DDADR_STOP; | 475 | desc->ddadr = DDADR_STOP; |
448 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; | 476 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; |
449 | 477 | ||
450 | if (dir_out) { | 478 | switch (info->state) { |
479 | case STATE_DMA_WRITING: | ||
451 | desc->dsadr = info->data_buff_phys; | 480 | desc->dsadr = info->data_buff_phys; |
452 | desc->dtadr = info->mmio_phys + NDDB; | 481 | desc->dtadr = info->mmio_phys + NDDB; |
453 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; | 482 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; |
454 | } else { | 483 | break; |
484 | case STATE_DMA_READING: | ||
455 | desc->dtadr = info->data_buff_phys; | 485 | desc->dtadr = info->data_buff_phys; |
456 | desc->dsadr = info->mmio_phys + NDDB; | 486 | desc->dsadr = info->mmio_phys + NDDB; |
457 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; | 487 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; |
488 | break; | ||
489 | default: | ||
490 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | ||
491 | info->state); | ||
492 | BUG(); | ||
458 | } | 493 | } |
459 | 494 | ||
460 | DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; | 495 | DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; |
@@ -472,93 +507,60 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) | |||
472 | 507 | ||
473 | if (dcsr & DCSR_BUSERR) { | 508 | if (dcsr & DCSR_BUSERR) { |
474 | info->retcode = ERR_DMABUSERR; | 509 | info->retcode = ERR_DMABUSERR; |
475 | complete(&info->cmd_complete); | ||
476 | } | 510 | } |
477 | 511 | ||
478 | if (info->state == STATE_DMA_WRITING) { | 512 | info->state = STATE_DMA_DONE; |
479 | info->state = STATE_DMA_DONE; | 513 | enable_int(info, NDCR_INT_MASK); |
480 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | 514 | nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); |
481 | } else { | ||
482 | info->state = STATE_READY; | ||
483 | complete(&info->cmd_complete); | ||
484 | } | ||
485 | } | 515 | } |
486 | 516 | ||
487 | static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | 517 | static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) |
488 | { | 518 | { |
489 | struct pxa3xx_nand_info *info = devid; | 519 | struct pxa3xx_nand_info *info = devid; |
490 | unsigned int status; | 520 | unsigned int status, is_completed = 0; |
491 | 521 | ||
492 | status = nand_readl(info, NDSR); | 522 | status = nand_readl(info, NDSR); |
493 | 523 | ||
494 | if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) { | 524 | if (status & NDSR_DBERR) |
495 | if (status & NDSR_DBERR) | 525 | info->retcode = ERR_DBERR; |
496 | info->retcode = ERR_DBERR; | 526 | if (status & NDSR_SBERR) |
497 | else if (status & NDSR_SBERR) | 527 | info->retcode = ERR_SBERR; |
498 | info->retcode = ERR_SBERR; | 528 | if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { |
499 | 529 | /* whether use dma to transfer data */ | |
500 | disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); | ||
501 | |||
502 | if (info->use_dma) { | ||
503 | info->state = STATE_DMA_READING; | ||
504 | start_data_dma(info, 0); | ||
505 | } else { | ||
506 | info->state = STATE_PIO_READING; | ||
507 | complete(&info->cmd_complete); | ||
508 | } | ||
509 | } else if (status & NDSR_WRDREQ) { | ||
510 | disable_int(info, NDSR_WRDREQ); | ||
511 | if (info->use_dma) { | 530 | if (info->use_dma) { |
512 | info->state = STATE_DMA_WRITING; | 531 | disable_int(info, NDCR_INT_MASK); |
513 | start_data_dma(info, 1); | 532 | info->state = (status & NDSR_RDDREQ) ? |
533 | STATE_DMA_READING : STATE_DMA_WRITING; | ||
534 | start_data_dma(info); | ||
535 | goto NORMAL_IRQ_EXIT; | ||
514 | } else { | 536 | } else { |
515 | info->state = STATE_PIO_WRITING; | 537 | info->state = (status & NDSR_RDDREQ) ? |
516 | complete(&info->cmd_complete); | 538 | STATE_PIO_READING : STATE_PIO_WRITING; |
539 | handle_data_pio(info); | ||
517 | } | 540 | } |
518 | } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) { | ||
519 | if (status & NDSR_CS0_BBD) | ||
520 | info->retcode = ERR_BBERR; | ||
521 | |||
522 | disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
523 | info->state = STATE_READY; | ||
524 | complete(&info->cmd_complete); | ||
525 | } | 541 | } |
526 | nand_writel(info, NDSR, status); | 542 | if (status & NDSR_CS0_CMDD) { |
527 | return IRQ_HANDLED; | 543 | info->state = STATE_CMD_DONE; |
528 | } | 544 | is_completed = 1; |
529 | |||
530 | static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event) | ||
531 | { | ||
532 | uint32_t ndcr; | ||
533 | int ret, timeout = CHIP_DELAY_TIMEOUT; | ||
534 | |||
535 | if (write_cmd(info)) { | ||
536 | info->retcode = ERR_SENDCMD; | ||
537 | goto fail_stop; | ||
538 | } | 545 | } |
546 | if (status & NDSR_FLASH_RDY) | ||
547 | info->state = STATE_READY; | ||
539 | 548 | ||
540 | info->state = STATE_CMD_HANDLE; | 549 | if (status & NDSR_WRCMDREQ) { |
541 | 550 | nand_writel(info, NDSR, NDSR_WRCMDREQ); | |
542 | enable_int(info, event); | 551 | status &= ~NDSR_WRCMDREQ; |
543 | 552 | info->state = STATE_CMD_HANDLE; | |
544 | ret = wait_for_completion_timeout(&info->cmd_complete, timeout); | 553 | nand_writel(info, NDCB0, info->ndcb0); |
545 | if (!ret) { | 554 | nand_writel(info, NDCB0, info->ndcb1); |
546 | printk(KERN_ERR "command execution timed out\n"); | 555 | nand_writel(info, NDCB0, info->ndcb2); |
547 | info->retcode = ERR_SENDCMD; | ||
548 | goto fail_stop; | ||
549 | } | 556 | } |
550 | 557 | ||
551 | if (info->use_dma == 0 && info->data_size > 0) | 558 | /* clear NDSR to let the controller exit the IRQ */ |
552 | if (handle_data_pio(info)) | 559 | nand_writel(info, NDSR, status); |
553 | goto fail_stop; | 560 | if (is_completed) |
554 | 561 | complete(&info->cmd_complete); | |
555 | return 0; | 562 | NORMAL_IRQ_EXIT: |
556 | 563 | return IRQ_HANDLED; | |
557 | fail_stop: | ||
558 | ndcr = nand_readl(info, NDCR); | ||
559 | nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); | ||
560 | udelay(10); | ||
561 | return -ETIMEDOUT; | ||
562 | } | 564 | } |
563 | 565 | ||
564 | static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) | 566 | static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) |
@@ -580,14 +582,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
580 | { | 582 | { |
581 | struct pxa3xx_nand_info *info = mtd->priv; | 583 | struct pxa3xx_nand_info *info = mtd->priv; |
582 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; | 584 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
583 | int ret; | 585 | int ret, exec_cmd = 0; |
584 | 586 | ||
585 | info->use_dma = (use_dma) ? 1 : 0; | 587 | info->use_dma = (use_dma) ? 1 : 0; |
586 | info->use_ecc = 0; | 588 | info->use_ecc = 0; |
587 | info->data_size = 0; | 589 | info->data_size = 0; |
588 | info->state = STATE_READY; | 590 | info->state = 0; |
589 | 591 | info->retcode = ERR_NONE; | |
590 | init_completion(&info->cmd_complete); | ||
591 | 592 | ||
592 | switch (command) { | 593 | switch (command) { |
593 | case NAND_CMD_READOOB: | 594 | case NAND_CMD_READOOB: |
@@ -596,36 +597,18 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
596 | info->buf_start = mtd->writesize + column; | 597 | info->buf_start = mtd->writesize + column; |
597 | memset(info->data_buff, 0xFF, info->buf_count); | 598 | memset(info->data_buff, 0xFF, info->buf_count); |
598 | 599 | ||
599 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) | 600 | prepare_read_prog_cmd(info, cmdset->read1, column, page_addr); |
600 | break; | 601 | exec_cmd = 1; |
601 | |||
602 | pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); | ||
603 | |||
604 | /* We only are OOB, so if the data has error, does not matter */ | ||
605 | if (info->retcode == ERR_DBERR) | ||
606 | info->retcode = ERR_NONE; | ||
607 | break; | 602 | break; |
608 | 603 | ||
609 | case NAND_CMD_READ0: | 604 | case NAND_CMD_READ0: |
610 | info->use_ecc = 1; | 605 | info->use_ecc = 1; |
611 | info->retcode = ERR_NONE; | ||
612 | info->buf_start = column; | 606 | info->buf_start = column; |
613 | info->buf_count = mtd->writesize + mtd->oobsize; | 607 | info->buf_count = mtd->writesize + mtd->oobsize; |
614 | memset(info->data_buff, 0xFF, info->buf_count); | 608 | memset(info->data_buff, 0xFF, info->buf_count); |
615 | 609 | ||
616 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) | 610 | prepare_read_prog_cmd(info, cmdset->read1, column, page_addr); |
617 | break; | 611 | exec_cmd = 1; |
618 | |||
619 | pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); | ||
620 | |||
621 | if (info->retcode == ERR_DBERR) { | ||
622 | /* for blank page (all 0xff), HW will calculate its ECC as | ||
623 | * 0, which is different from the ECC information within | ||
624 | * OOB, ignore such double bit errors | ||
625 | */ | ||
626 | if (is_buf_blank(info->data_buff, mtd->writesize)) | ||
627 | info->retcode = ERR_NONE; | ||
628 | } | ||
629 | break; | 612 | break; |
630 | case NAND_CMD_SEQIN: | 613 | case NAND_CMD_SEQIN: |
631 | info->buf_start = column; | 614 | info->buf_start = column; |
@@ -639,17 +622,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
639 | case NAND_CMD_PAGEPROG: | 622 | case NAND_CMD_PAGEPROG: |
640 | info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; | 623 | info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; |
641 | 624 | ||
642 | if (prepare_read_prog_cmd(info, cmdset->program, | 625 | prepare_read_prog_cmd(info, cmdset->program, |
643 | info->seqin_column, info->seqin_page_addr)) | 626 | info->seqin_column, info->seqin_page_addr); |
644 | break; | 627 | exec_cmd = 1; |
645 | |||
646 | pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); | ||
647 | break; | 628 | break; |
648 | case NAND_CMD_ERASE1: | 629 | case NAND_CMD_ERASE1: |
649 | if (prepare_erase_cmd(info, cmdset->erase, page_addr)) | 630 | prepare_erase_cmd(info, cmdset->erase, page_addr); |
650 | break; | 631 | exec_cmd = 1; |
651 | |||
652 | pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
653 | break; | 632 | break; |
654 | case NAND_CMD_ERASE2: | 633 | case NAND_CMD_ERASE2: |
655 | break; | 634 | break; |
@@ -660,40 +639,69 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
660 | info->buf_count = (command == NAND_CMD_READID) ? | 639 | info->buf_count = (command == NAND_CMD_READID) ? |
661 | info->read_id_bytes : 1; | 640 | info->read_id_bytes : 1; |
662 | 641 | ||
663 | if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? | 642 | prepare_other_cmd(info, (command == NAND_CMD_READID) ? |
664 | cmdset->read_id : cmdset->read_status)) | 643 | cmdset->read_id : cmdset->read_status); |
665 | break; | 644 | exec_cmd = 1; |
666 | |||
667 | pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); | ||
668 | break; | 645 | break; |
669 | case NAND_CMD_RESET: | 646 | case NAND_CMD_RESET: |
670 | if (prepare_other_cmd(info, cmdset->reset)) | 647 | prepare_other_cmd(info, cmdset->reset); |
671 | break; | 648 | exec_cmd = 1; |
672 | |||
673 | ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); | ||
674 | if (ret == 0) { | ||
675 | int timeout = 2; | ||
676 | uint32_t ndcr; | ||
677 | |||
678 | while (timeout--) { | ||
679 | if (nand_readl(info, NDSR) & NDSR_RDY) | ||
680 | break; | ||
681 | msleep(10); | ||
682 | } | ||
683 | |||
684 | ndcr = nand_readl(info, NDCR); | ||
685 | nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); | ||
686 | } | ||
687 | break; | 649 | break; |
688 | default: | 650 | default: |
689 | printk(KERN_ERR "non-supported command.\n"); | 651 | printk(KERN_ERR "non-supported command.\n"); |
690 | break; | 652 | break; |
691 | } | 653 | } |
692 | 654 | ||
693 | if (info->retcode == ERR_DBERR) { | 655 | if (exec_cmd) { |
694 | printk(KERN_ERR "double bit error @ page %08x\n", page_addr); | 656 | init_completion(&info->cmd_complete); |
695 | info->retcode = ERR_NONE; | 657 | pxa3xx_nand_start(info); |
658 | |||
659 | ret = wait_for_completion_timeout(&info->cmd_complete, | ||
660 | CHIP_DELAY_TIMEOUT); | ||
661 | if (!ret) { | ||
662 | printk(KERN_ERR "Wait time out!!!\n"); | ||
663 | /* Stop State Machine for next command cycle */ | ||
664 | pxa3xx_nand_stop(info); | ||
665 | } | ||
666 | info->state = STATE_IDLE; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, | ||
671 | struct nand_chip *chip, const uint8_t *buf) | ||
672 | { | ||
673 | chip->write_buf(mtd, buf, mtd->writesize); | ||
674 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
675 | } | ||
676 | |||
677 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | ||
678 | struct nand_chip *chip, uint8_t *buf, int page) | ||
679 | { | ||
680 | struct pxa3xx_nand_info *info = mtd->priv; | ||
681 | |||
682 | chip->read_buf(mtd, buf, mtd->writesize); | ||
683 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
684 | |||
685 | if (info->retcode == ERR_SBERR) { | ||
686 | switch (info->use_ecc) { | ||
687 | case 1: | ||
688 | mtd->ecc_stats.corrected++; | ||
689 | break; | ||
690 | case 0: | ||
691 | default: | ||
692 | break; | ||
693 | } | ||
694 | } else if (info->retcode == ERR_DBERR) { | ||
695 | /* | ||
696 | * for blank page (all 0xff), HW will calculate its ECC as | ||
697 | * 0, which is different from the ECC information within | ||
698 | * OOB, ignore such double bit errors | ||
699 | */ | ||
700 | if (is_buf_blank(buf, mtd->writesize)) | ||
701 | mtd->ecc_stats.failed++; | ||
696 | } | 702 | } |
703 | |||
704 | return 0; | ||
697 | } | 705 | } |
698 | 706 | ||
699 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) | 707 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) |
@@ -770,47 +778,13 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) | |||
770 | return 0; | 778 | return 0; |
771 | } | 779 | } |
772 | 780 | ||
773 | static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode) | ||
774 | { | ||
775 | return; | ||
776 | } | ||
777 | |||
778 | static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd, | ||
779 | const uint8_t *dat, uint8_t *ecc_code) | ||
780 | { | ||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, | ||
785 | uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) | ||
786 | { | ||
787 | struct pxa3xx_nand_info *info = mtd->priv; | ||
788 | /* | ||
789 | * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we | ||
790 | * consider it as a ecc error which will tell the caller the | ||
791 | * read fail We have distinguish all the errors, but the | ||
792 | * nand_read_ecc only check this function return value | ||
793 | * | ||
794 | * Corrected (single-bit) errors must also be noted. | ||
795 | */ | ||
796 | if (info->retcode == ERR_SBERR) | ||
797 | return 1; | ||
798 | else if (info->retcode != ERR_NONE) | ||
799 | return -1; | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) | 781 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) |
805 | { | 782 | { |
806 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; | 783 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
807 | uint32_t ndcr; | 784 | uint32_t ndcr; |
808 | uint8_t id_buff[8]; | 785 | uint8_t id_buff[8]; |
809 | 786 | ||
810 | if (prepare_other_cmd(info, cmdset->read_id)) { | 787 | prepare_other_cmd(info, cmdset->read_id); |
811 | printk(KERN_ERR "failed to prepare command\n"); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | 788 | ||
815 | /* Send command */ | 789 | /* Send command */ |
816 | if (write_cmd(info)) | 790 | if (write_cmd(info)) |
@@ -836,7 +810,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
836 | { | 810 | { |
837 | struct platform_device *pdev = info->pdev; | 811 | struct platform_device *pdev = info->pdev; |
838 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 812 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
839 | uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ | 813 | uint32_t ndcr = 0x0; /* enable all interrupts */ |
840 | 814 | ||
841 | if (f->page_size != 2048 && f->page_size != 512) | 815 | if (f->page_size != 2048 && f->page_size != 512) |
842 | return -EINVAL; | 816 | return -EINVAL; |
@@ -888,11 +862,12 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
888 | info->reg_ndcr = ndcr; | 862 | info->reg_ndcr = ndcr; |
889 | info->cmdset = &default_cmdset; | 863 | info->cmdset = &default_cmdset; |
890 | 864 | ||
891 | if (__readid(info, &id)) | 865 | pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); |
866 | id = *((uint16_t *)(info->data_buff)); | ||
867 | if (id == 0) | ||
892 | return -ENODEV; | 868 | return -ENODEV; |
893 | 869 | ||
894 | /* Lookup the flash id */ | 870 | /* Lookup the flash id */ |
895 | id = (id >> 8) & 0xff; /* device id is byte 2 */ | ||
896 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 871 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
897 | if (id == nand_flash_ids[i].id) { | 872 | if (id == nand_flash_ids[i].id) { |
898 | type = &nand_flash_ids[i]; | 873 | type = &nand_flash_ids[i]; |
@@ -935,8 +910,8 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | |||
935 | /* we use default timing to detect id */ | 910 | /* we use default timing to detect id */ |
936 | f = DEFAULT_FLASH_TYPE; | 911 | f = DEFAULT_FLASH_TYPE; |
937 | pxa3xx_nand_config_flash(info, f); | 912 | pxa3xx_nand_config_flash(info, f); |
938 | if (__readid(info, &id)) | 913 | pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); |
939 | goto fail_detect; | 914 | id = *((uint16_t *)(info->data_buff)); |
940 | 915 | ||
941 | for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) { | 916 | for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) { |
942 | /* we first choose the flash definition from platfrom */ | 917 | /* we first choose the flash definition from platfrom */ |
@@ -954,7 +929,6 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | |||
954 | dev_warn(&info->pdev->dev, | 929 | dev_warn(&info->pdev->dev, |
955 | "failed to detect configured nand flash; found %04x instead of\n", | 930 | "failed to detect configured nand flash; found %04x instead of\n", |
956 | id); | 931 | id); |
957 | fail_detect: | ||
958 | return -ENODEV; | 932 | return -ENODEV; |
959 | } | 933 | } |
960 | 934 | ||
@@ -1025,6 +999,8 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | |||
1025 | this->select_chip = pxa3xx_nand_select_chip; | 999 | this->select_chip = pxa3xx_nand_select_chip; |
1026 | this->dev_ready = pxa3xx_nand_dev_ready; | 1000 | this->dev_ready = pxa3xx_nand_dev_ready; |
1027 | this->cmdfunc = pxa3xx_nand_cmdfunc; | 1001 | this->cmdfunc = pxa3xx_nand_cmdfunc; |
1002 | this->ecc.read_page = pxa3xx_nand_read_page_hwecc; | ||
1003 | this->ecc.write_page = pxa3xx_nand_write_page_hwecc; | ||
1028 | this->read_word = pxa3xx_nand_read_word; | 1004 | this->read_word = pxa3xx_nand_read_word; |
1029 | this->read_byte = pxa3xx_nand_read_byte; | 1005 | this->read_byte = pxa3xx_nand_read_byte; |
1030 | this->read_buf = pxa3xx_nand_read_buf; | 1006 | this->read_buf = pxa3xx_nand_read_buf; |
@@ -1032,9 +1008,6 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | |||
1032 | this->verify_buf = pxa3xx_nand_verify_buf; | 1008 | this->verify_buf = pxa3xx_nand_verify_buf; |
1033 | 1009 | ||
1034 | this->ecc.mode = NAND_ECC_HW; | 1010 | this->ecc.mode = NAND_ECC_HW; |
1035 | this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; | ||
1036 | this->ecc.calculate = pxa3xx_nand_ecc_calculate; | ||
1037 | this->ecc.correct = pxa3xx_nand_ecc_correct; | ||
1038 | this->ecc.size = info->page_size; | 1011 | this->ecc.size = info->page_size; |
1039 | 1012 | ||
1040 | if (info->page_size == 2048) | 1013 | if (info->page_size == 2048) |
@@ -1177,10 +1150,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1177 | 1150 | ||
1178 | platform_set_drvdata(pdev, NULL); | 1151 | platform_set_drvdata(pdev, NULL); |
1179 | 1152 | ||
1180 | del_mtd_device(mtd); | ||
1181 | #ifdef CONFIG_MTD_PARTITIONS | ||
1182 | del_mtd_partitions(mtd); | ||
1183 | #endif | ||
1184 | irq = platform_get_irq(pdev, 0); | 1153 | irq = platform_get_irq(pdev, 0); |
1185 | if (irq >= 0) | 1154 | if (irq >= 0) |
1186 | free_irq(irq, info); | 1155 | free_irq(irq, info); |
@@ -1198,7 +1167,13 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1198 | clk_disable(info->clk); | 1167 | clk_disable(info->clk); |
1199 | clk_put(info->clk); | 1168 | clk_put(info->clk); |
1200 | 1169 | ||
1201 | kfree(mtd); | 1170 | if (mtd) { |
1171 | del_mtd_device(mtd); | ||
1172 | #ifdef CONFIG_MTD_PARTITIONS | ||
1173 | del_mtd_partitions(mtd); | ||
1174 | #endif | ||
1175 | kfree(mtd); | ||
1176 | } | ||
1202 | return 0; | 1177 | return 0; |
1203 | } | 1178 | } |
1204 | 1179 | ||
@@ -1232,10 +1207,10 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1232 | nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); | 1207 | nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); |
1233 | 1208 | ||
1234 | if (nr_parts) | 1209 | if (nr_parts) |
1235 | return add_mtd_partitions(mtd, parts, nr_parts); | 1210 | return add_mtd_partitions(info->mtd, parts, nr_parts); |
1236 | } | 1211 | } |
1237 | 1212 | ||
1238 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1213 | return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); |
1239 | #else | 1214 | #else |
1240 | return 0; | 1215 | return 0; |
1241 | #endif | 1216 | #endif |
@@ -1247,7 +1222,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) | |||
1247 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); | 1222 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1248 | struct mtd_info *mtd = info->mtd; | 1223 | struct mtd_info *mtd = info->mtd; |
1249 | 1224 | ||
1250 | if (info->state != STATE_READY) { | 1225 | if (info->state) { |
1251 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); | 1226 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); |
1252 | return -EAGAIN; | 1227 | return -EAGAIN; |
1253 | } | 1228 | } |