aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/mxc_nand.c310
1 files changed, 77 insertions, 233 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 8fcb33da8efc..03d20086170b 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -107,15 +107,17 @@ struct mxc_nand_host {
107 struct device *dev; 107 struct device *dev;
108 108
109 void __iomem *regs; 109 void __iomem *regs;
110 int spare_only;
111 int status_request; 110 int status_request;
112 int pagesize_2k; 111 int pagesize_2k;
113 uint16_t col_addr;
114 struct clk *clk; 112 struct clk *clk;
115 int clk_act; 113 int clk_act;
116 int irq; 114 int irq;
117 115
118 wait_queue_head_t irq_waitq; 116 wait_queue_head_t irq_waitq;
117
118 uint8_t *data_buf;
119 unsigned int buf_start;
120 int spare_len;
119}; 121};
120 122
121/* Define delays in microsec for NAND device operations */ 123/* Define delays in microsec for NAND device operations */
@@ -227,23 +229,11 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
227} 229}
228 230
229static void send_page(struct mxc_nand_host *host, uint8_t buf_id, 231static void send_page(struct mxc_nand_host *host, uint8_t buf_id,
230 int spare_only, unsigned int ops) 232 unsigned int ops)
231{ 233{
232 DEBUG(MTD_DEBUG_LEVEL3, "send_page (%d)\n", spare_only);
233
234 /* NANDFC buffer 0 is used for page read/write */ 234 /* NANDFC buffer 0 is used for page read/write */
235 writew(buf_id, host->regs + NFC_BUF_ADDR); 235 writew(buf_id, host->regs + NFC_BUF_ADDR);
236 236
237 /* Configure spare or page+spare access */
238 if (!host->pagesize_2k) {
239 uint16_t config1 = readw(host->regs + NFC_CONFIG1);
240 if (spare_only)
241 config1 |= NFC_SP_EN;
242 else
243 config1 &= ~(NFC_SP_EN);
244 writew(config1, host->regs + NFC_CONFIG1);
245 }
246
247 writew(ops, host->regs + NFC_CONFIG2); 237 writew(ops, host->regs + NFC_CONFIG2);
248 238
249 /* Wait for operation to complete */ 239 /* Wait for operation to complete */
@@ -278,6 +268,7 @@ static void send_read_id(struct mxc_nand_host *host)
278 writeb(readb(main_buf + 8), main_buf + 4); 268 writeb(readb(main_buf + 8), main_buf + 4);
279 writeb(readb(main_buf + 10), main_buf + 5); 269 writeb(readb(main_buf + 10), main_buf + 5);
280 } 270 }
271 memcpy(host->data_buf, host->regs + MAIN_AREA0, 16);
281} 272}
282 273
283/* This function requests the NANDFC to perform a read of the 274/* This function requests the NANDFC to perform a read of the
@@ -363,32 +354,14 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
363{ 354{
364 struct nand_chip *nand_chip = mtd->priv; 355 struct nand_chip *nand_chip = mtd->priv;
365 struct mxc_nand_host *host = nand_chip->priv; 356 struct mxc_nand_host *host = nand_chip->priv;
366 uint8_t ret = 0; 357 uint8_t ret;
367 uint16_t col, rd_word;
368 uint16_t __iomem *main_buf = host->regs + MAIN_AREA0;
369 uint16_t __iomem *spare_buf = host->regs + SPARE_AREA0;
370 358
371 /* Check for status request */ 359 /* Check for status request */
372 if (host->status_request) 360 if (host->status_request)
373 return get_dev_status(host) & 0xFF; 361 return get_dev_status(host) & 0xFF;
374 362
375 /* Get column for 16-bit access */ 363 ret = *(uint8_t *)(host->data_buf + host->buf_start);
376 col = host->col_addr >> 1; 364 host->buf_start++;
377
378 /* If we are accessing the spare region */
379 if (host->spare_only)
380 rd_word = readw(&spare_buf[col]);
381 else
382 rd_word = readw(&main_buf[col]);
383
384 /* Pick upper/lower byte of word from RAM buffer */
385 if (host->col_addr & 0x1)
386 ret = (rd_word >> 8) & 0xFF;
387 else
388 ret = rd_word & 0xFF;
389
390 /* Update saved column address */
391 host->col_addr++;
392 365
393 return ret; 366 return ret;
394} 367}
@@ -397,33 +370,10 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
397{ 370{
398 struct nand_chip *nand_chip = mtd->priv; 371 struct nand_chip *nand_chip = mtd->priv;
399 struct mxc_nand_host *host = nand_chip->priv; 372 struct mxc_nand_host *host = nand_chip->priv;
400 uint16_t col, rd_word, ret; 373 uint16_t ret;
401 uint16_t __iomem *p;
402 374
403 DEBUG(MTD_DEBUG_LEVEL3, 375 ret = *(uint16_t *)(host->data_buf + host->buf_start);
404 "mxc_nand_read_word(col = %d)\n", host->col_addr); 376 host->buf_start += 2;
405
406 col = host->col_addr;
407 /* Adjust saved column address */
408 if (col < mtd->writesize && host->spare_only)
409 col += mtd->writesize;
410
411 if (col < mtd->writesize)
412 p = (host->regs + MAIN_AREA0) + (col >> 1);
413 else
414 p = (host->regs + SPARE_AREA0) + ((col - mtd->writesize) >> 1);
415
416 if (col & 1) {
417 rd_word = readw(p);
418 ret = (rd_word >> 8) & 0xff;
419 rd_word = readw(&p[1]);
420 ret |= (rd_word << 8) & 0xff00;
421
422 } else
423 ret = readw(p);
424
425 /* Update saved column address */
426 host->col_addr = col + 2;
427 377
428 return ret; 378 return ret;
429} 379}
@@ -436,94 +386,14 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
436{ 386{
437 struct nand_chip *nand_chip = mtd->priv; 387 struct nand_chip *nand_chip = mtd->priv;
438 struct mxc_nand_host *host = nand_chip->priv; 388 struct mxc_nand_host *host = nand_chip->priv;
439 int n, col, i = 0; 389 u16 col = host->buf_start;
440 390 int n = mtd->oobsize + mtd->writesize - col;
441 DEBUG(MTD_DEBUG_LEVEL3,
442 "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
443 len);
444
445 col = host->col_addr;
446
447 /* Adjust saved column address */
448 if (col < mtd->writesize && host->spare_only)
449 col += mtd->writesize;
450
451 n = mtd->writesize + mtd->oobsize - col;
452 n = min(len, n);
453
454 DEBUG(MTD_DEBUG_LEVEL3,
455 "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
456
457 while (n) {
458 void __iomem *p;
459
460 if (col < mtd->writesize)
461 p = host->regs + MAIN_AREA0 + (col & ~3);
462 else
463 p = host->regs + SPARE_AREA0 -
464 mtd->writesize + (col & ~3);
465
466 DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
467 __LINE__, p);
468
469 if (((col | (int)&buf[i]) & 3) || n < 16) {
470 uint32_t data = 0;
471
472 if (col & 3 || n < 4)
473 data = readl(p);
474
475 switch (col & 3) {
476 case 0:
477 if (n) {
478 data = (data & 0xffffff00) |
479 (buf[i++] << 0);
480 n--;
481 col++;
482 }
483 case 1:
484 if (n) {
485 data = (data & 0xffff00ff) |
486 (buf[i++] << 8);
487 n--;
488 col++;
489 }
490 case 2:
491 if (n) {
492 data = (data & 0xff00ffff) |
493 (buf[i++] << 16);
494 n--;
495 col++;
496 }
497 case 3:
498 if (n) {
499 data = (data & 0x00ffffff) |
500 (buf[i++] << 24);
501 n--;
502 col++;
503 }
504 }
505
506 writel(data, p);
507 } else {
508 int m = mtd->writesize - col;
509 391
510 if (col >= mtd->writesize) 392 n = min(n, len);
511 m += mtd->oobsize;
512 393
513 m = min(n, m) & ~3; 394 memcpy(host->data_buf + col, buf, n);
514 395
515 DEBUG(MTD_DEBUG_LEVEL3, 396 host->buf_start += n;
516 "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
517 __func__, __LINE__, n, m, i, col);
518
519 memcpy(p, &buf[i], m);
520 col += m;
521 i += m;
522 n -= m;
523 }
524 }
525 /* Update saved column address */
526 host->col_addr = col;
527} 397}
528 398
529/* Read the data buffer from the NAND Flash. To read the data from NAND 399/* Read the data buffer from the NAND Flash. To read the data from NAND
@@ -534,75 +404,14 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
534{ 404{
535 struct nand_chip *nand_chip = mtd->priv; 405 struct nand_chip *nand_chip = mtd->priv;
536 struct mxc_nand_host *host = nand_chip->priv; 406 struct mxc_nand_host *host = nand_chip->priv;
537 int n, col, i = 0; 407 u16 col = host->buf_start;
408 int n = mtd->oobsize + mtd->writesize - col;
538 409
539 DEBUG(MTD_DEBUG_LEVEL3, 410 n = min(n, len);
540 "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
541
542 col = host->col_addr;
543
544 /* Adjust saved column address */
545 if (col < mtd->writesize && host->spare_only)
546 col += mtd->writesize;
547
548 n = mtd->writesize + mtd->oobsize - col;
549 n = min(len, n);
550
551 while (n) {
552 void __iomem *p;
553
554 if (col < mtd->writesize)
555 p = host->regs + MAIN_AREA0 + (col & ~3);
556 else
557 p = host->regs + SPARE_AREA0 -
558 mtd->writesize + (col & ~3);
559
560 if (((col | (int)&buf[i]) & 3) || n < 16) {
561 uint32_t data;
562
563 data = readl(p);
564 switch (col & 3) {
565 case 0:
566 if (n) {
567 buf[i++] = (uint8_t) (data);
568 n--;
569 col++;
570 }
571 case 1:
572 if (n) {
573 buf[i++] = (uint8_t) (data >> 8);
574 n--;
575 col++;
576 }
577 case 2:
578 if (n) {
579 buf[i++] = (uint8_t) (data >> 16);
580 n--;
581 col++;
582 }
583 case 3:
584 if (n) {
585 buf[i++] = (uint8_t) (data >> 24);
586 n--;
587 col++;
588 }
589 }
590 } else {
591 int m = mtd->writesize - col;
592 411
593 if (col >= mtd->writesize) 412 memcpy(buf, host->data_buf + col, len);
594 m += mtd->oobsize;
595
596 m = min(n, m) & ~3;
597 memcpy(&buf[i], p, m);
598 col += m;
599 i += m;
600 n -= m;
601 }
602 }
603 /* Update saved column address */
604 host->col_addr = col;
605 413
414 host->buf_start += len;
606} 415}
607 416
608/* Used by the upper layer to verify the data in NAND Flash 417/* Used by the upper layer to verify the data in NAND Flash
@@ -641,6 +450,36 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
641 } 450 }
642} 451}
643 452
453/*
454 * Function to transfer data to/from spare area.
455 */
456static void copy_spare(struct mtd_info *mtd, bool bfrom)
457{
458 struct nand_chip *this = mtd->priv;
459 struct mxc_nand_host *host = this->priv;
460 u16 i, j;
461 u16 n = mtd->writesize >> 9;
462 u8 *d = host->data_buf + mtd->writesize;
463 u8 *s = host->regs + SPARE_AREA0;
464 u16 t = host->spare_len;
465
466 j = (mtd->oobsize / n >> 1) << 1;
467
468 if (bfrom) {
469 for (i = 0; i < n - 1; i++)
470 memcpy(d + i * j, s + i * t, j);
471
472 /* the last section */
473 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
474 } else {
475 for (i = 0; i < n - 1; i++)
476 memcpy(&s[i * t], &d[i * j], j);
477
478 /* the last section */
479 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
480 }
481}
482
644static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) 483static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
645{ 484{
646 struct nand_chip *nand_chip = mtd->priv; 485 struct nand_chip *nand_chip = mtd->priv;
@@ -707,19 +546,18 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
707 switch (command) { 546 switch (command) {
708 547
709 case NAND_CMD_STATUS: 548 case NAND_CMD_STATUS:
710 host->col_addr = 0; 549 host->buf_start = 0;
711 host->status_request = true; 550 host->status_request = true;
712 break; 551 break;
713 552
714 case NAND_CMD_READ0: 553 case NAND_CMD_READ0:
715 host->col_addr = column; 554 host->buf_start = column;
716 host->spare_only = false;
717 useirq = false; 555 useirq = false;
718 break; 556 break;
719 557
720 case NAND_CMD_READOOB: 558 case NAND_CMD_READOOB:
721 host->col_addr = column; 559 host->buf_start = column + mtd->writesize;
722 host->spare_only = true; 560
723 useirq = false; 561 useirq = false;
724 if (host->pagesize_2k) 562 if (host->pagesize_2k)
725 command = NAND_CMD_READ0; /* only READ0 is valid */ 563 command = NAND_CMD_READ0; /* only READ0 is valid */
@@ -739,15 +577,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
739 mxc_nand_command(mtd, NAND_CMD_READ0, 0, 577 mxc_nand_command(mtd, NAND_CMD_READ0, 0,
740 page_addr); 578 page_addr);
741 579
742 host->col_addr = column - mtd->writesize; 580 host->buf_start = column;
743 host->spare_only = true;
744 581
745 /* Set program pointer to spare region */ 582 /* Set program pointer to spare region */
746 if (!host->pagesize_2k) 583 if (!host->pagesize_2k)
747 send_cmd(host, NAND_CMD_READOOB, false); 584 send_cmd(host, NAND_CMD_READOOB, false);
748 } else { 585 } else {
749 host->spare_only = false; 586 host->buf_start = column;
750 host->col_addr = column;
751 587
752 /* Set program pointer to page start */ 588 /* Set program pointer to page start */
753 if (!host->pagesize_2k) 589 if (!host->pagesize_2k)
@@ -757,13 +593,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
757 break; 593 break;
758 594
759 case NAND_CMD_PAGEPROG: 595 case NAND_CMD_PAGEPROG:
760 send_page(host, 0, host->spare_only, NFC_INPUT); 596 memcpy(host->regs + MAIN_AREA0, host->data_buf, mtd->writesize);
597 copy_spare(mtd, false);
598 send_page(host, 0, NFC_INPUT);
761 599
762 if (host->pagesize_2k) { 600 if (host->pagesize_2k) {
763 /* data in 4 areas datas */ 601 /* data in 4 areas datas */
764 send_page(host, 1, host->spare_only, NFC_INPUT); 602 send_page(host, 1, NFC_INPUT);
765 send_page(host, 2, host->spare_only, NFC_INPUT); 603 send_page(host, 2, NFC_INPUT);
766 send_page(host, 3, host->spare_only, NFC_INPUT); 604 send_page(host, 3, NFC_INPUT);
767 } 605 }
768 606
769 break; 607 break;
@@ -789,16 +627,18 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
789 /* send read confirm command */ 627 /* send read confirm command */
790 send_cmd(host, NAND_CMD_READSTART, true); 628 send_cmd(host, NAND_CMD_READSTART, true);
791 /* read for each AREA */ 629 /* read for each AREA */
792 send_page(host, 0, host->spare_only, NFC_OUTPUT); 630 send_page(host, 0, NFC_OUTPUT);
793 send_page(host, 1, host->spare_only, NFC_OUTPUT); 631 send_page(host, 1, NFC_OUTPUT);
794 send_page(host, 2, host->spare_only, NFC_OUTPUT); 632 send_page(host, 2, NFC_OUTPUT);
795 send_page(host, 3, host->spare_only, NFC_OUTPUT); 633 send_page(host, 3, NFC_OUTPUT);
796 } else 634 } else
797 send_page(host, 0, host->spare_only, NFC_OUTPUT); 635 send_page(host, 0, NFC_OUTPUT);
636
637 memcpy(host->data_buf, host->regs + MAIN_AREA0, mtd->writesize);
638 copy_spare(mtd, true);
798 break; 639 break;
799 640
800 case NAND_CMD_READID: 641 case NAND_CMD_READID:
801 host->col_addr = 0;
802 send_read_id(host); 642 send_read_id(host);
803 break; 643 break;
804 644
@@ -824,10 +664,14 @@ static int __init mxcnd_probe(struct platform_device *pdev)
824 int err = 0, nr_parts = 0; 664 int err = 0, nr_parts = 0;
825 665
826 /* Allocate memory for MTD device structure and private data */ 666 /* Allocate memory for MTD device structure and private data */
827 host = kzalloc(sizeof(struct mxc_nand_host), GFP_KERNEL); 667 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
668 NAND_MAX_OOBSIZE, GFP_KERNEL);
828 if (!host) 669 if (!host)
829 return -ENOMEM; 670 return -ENOMEM;
830 671
672 host->data_buf = (uint8_t *)(host + 1);
673 host->spare_len = 16;
674
831 host->dev = &pdev->dev; 675 host->dev = &pdev->dev;
832 /* structures must be linked */ 676 /* structures must be linked */
833 this = &host->nand; 677 this = &host->nand;