aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorJosh Wu <josh.wu@atmel.com>2012-06-25 06:07:43 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-07-06 13:17:07 -0400
commit3dfe41a4c705223c66373968327407e11c2fb1a1 (patch)
tree65ab13c0ae765811058ad60a3a4eeae826da0dc9 /drivers/mtd/nand
parent95c1b0ce2ad8bfc0092782a75e86b219eb2c5204 (diff)
mtd: at91: extract hw ecc initialization to one function
This patch moves hw ecc initialization code to one function. Signed-off-by: Hong Xu <hong.xu@atmel.com> Signed-off-by: Josh Wu <josh.wu@atmel.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/atmel_nand.c127
1 files changed, 66 insertions, 61 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 97ac6712bb19..7a41a04beb87 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -527,6 +527,66 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
527} 527}
528#endif 528#endif
529 529
530static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
531 struct atmel_nand_host *host)
532{
533 struct mtd_info *mtd = &host->mtd;
534 struct nand_chip *nand_chip = &host->nand_chip;
535 struct resource *regs;
536
537 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
538 if (!regs) {
539 dev_err(host->dev,
540 "Can't get I/O resource regs, use software ECC\n");
541 nand_chip->ecc.mode = NAND_ECC_SOFT;
542 return 0;
543 }
544
545 host->ecc = ioremap(regs->start, resource_size(regs));
546 if (host->ecc == NULL) {
547 dev_err(host->dev, "ioremap failed\n");
548 return -EIO;
549 }
550
551 /* ECC is calculated for the whole page (1 step) */
552 nand_chip->ecc.size = mtd->writesize;
553
554 /* set ECC page size and oob layout */
555 switch (mtd->writesize) {
556 case 512:
557 nand_chip->ecc.layout = &atmel_oobinfo_small;
558 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
559 break;
560 case 1024:
561 nand_chip->ecc.layout = &atmel_oobinfo_large;
562 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
563 break;
564 case 2048:
565 nand_chip->ecc.layout = &atmel_oobinfo_large;
566 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
567 break;
568 case 4096:
569 nand_chip->ecc.layout = &atmel_oobinfo_large;
570 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
571 break;
572 default:
573 /* page size not handled by HW ECC */
574 /* switching back to soft ECC */
575 nand_chip->ecc.mode = NAND_ECC_SOFT;
576 return 0;
577 }
578
579 /* set up for HW ECC */
580 nand_chip->ecc.calculate = atmel_nand_calculate;
581 nand_chip->ecc.correct = atmel_nand_correct;
582 nand_chip->ecc.hwctl = atmel_nand_hwctl;
583 nand_chip->ecc.read_page = atmel_nand_read_page;
584 nand_chip->ecc.bytes = 4;
585 nand_chip->ecc.strength = 1;
586
587 return 0;
588}
589
530/* 590/*
531 * Probe for the NAND device. 591 * Probe for the NAND device.
532 */ 592 */
@@ -535,7 +595,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
535 struct atmel_nand_host *host; 595 struct atmel_nand_host *host;
536 struct mtd_info *mtd; 596 struct mtd_info *mtd;
537 struct nand_chip *nand_chip; 597 struct nand_chip *nand_chip;
538 struct resource *regs;
539 struct resource *mem; 598 struct resource *mem;
540 struct mtd_part_parser_data ppdata = {}; 599 struct mtd_part_parser_data ppdata = {};
541 int res; 600 int res;
@@ -587,29 +646,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
587 nand_chip->dev_ready = atmel_nand_device_ready; 646 nand_chip->dev_ready = atmel_nand_device_ready;
588 647
589 nand_chip->ecc.mode = host->board.ecc_mode; 648 nand_chip->ecc.mode = host->board.ecc_mode;
590
591 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
592 if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) {
593 printk(KERN_ERR "atmel_nand: can't get I/O resource "
594 "regs\nFalling back on software ECC\n");
595 nand_chip->ecc.mode = NAND_ECC_SOFT;
596 }
597
598 if (nand_chip->ecc.mode == NAND_ECC_HW) {
599 host->ecc = ioremap(regs->start, resource_size(regs));
600 if (host->ecc == NULL) {
601 printk(KERN_ERR "atmel_nand: ioremap failed\n");
602 res = -EIO;
603 goto err_ecc_ioremap;
604 }
605 nand_chip->ecc.calculate = atmel_nand_calculate;
606 nand_chip->ecc.correct = atmel_nand_correct;
607 nand_chip->ecc.hwctl = atmel_nand_hwctl;
608 nand_chip->ecc.read_page = atmel_nand_read_page;
609 nand_chip->ecc.bytes = 4;
610 nand_chip->ecc.strength = 1;
611 }
612
613 nand_chip->chip_delay = 20; /* 20us command delay time */ 649 nand_chip->chip_delay = 20; /* 20us command delay time */
614 650
615 if (host->board.bus_width_16) /* 16-bit bus width */ 651 if (host->board.bus_width_16) /* 16-bit bus width */
@@ -661,40 +697,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
661 } 697 }
662 698
663 if (nand_chip->ecc.mode == NAND_ECC_HW) { 699 if (nand_chip->ecc.mode == NAND_ECC_HW) {
664 /* ECC is calculated for the whole page (1 step) */ 700 res = atmel_hw_nand_init_params(pdev, host);
665 nand_chip->ecc.size = mtd->writesize; 701 if (res != 0)
666 702 goto err_hw_ecc;
667 /* set ECC page size and oob layout */
668 switch (mtd->writesize) {
669 case 512:
670 nand_chip->ecc.layout = &atmel_oobinfo_small;
671 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
672 break;
673 case 1024:
674 nand_chip->ecc.layout = &atmel_oobinfo_large;
675 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
676 break;
677 case 2048:
678 nand_chip->ecc.layout = &atmel_oobinfo_large;
679 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
680 break;
681 case 4096:
682 nand_chip->ecc.layout = &atmel_oobinfo_large;
683 ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
684 break;
685 default:
686 /* page size not handled by HW ECC */
687 /* switching back to soft ECC */
688 nand_chip->ecc.mode = NAND_ECC_SOFT;
689 nand_chip->ecc.calculate = NULL;
690 nand_chip->ecc.correct = NULL;
691 nand_chip->ecc.hwctl = NULL;
692 nand_chip->ecc.read_page = NULL;
693 nand_chip->ecc.postpad = 0;
694 nand_chip->ecc.prepad = 0;
695 nand_chip->ecc.bytes = 0;
696 break;
697 }
698 } 703 }
699 704
700 /* second phase scan */ 705 /* second phase scan */
@@ -711,15 +716,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
711 return res; 716 return res;
712 717
713err_scan_tail: 718err_scan_tail:
719 if (host->ecc)
720 iounmap(host->ecc);
721err_hw_ecc:
714err_scan_ident: 722err_scan_ident:
715err_no_card: 723err_no_card:
716 atmel_nand_disable(host); 724 atmel_nand_disable(host);
717 platform_set_drvdata(pdev, NULL); 725 platform_set_drvdata(pdev, NULL);
718 if (host->dma_chan) 726 if (host->dma_chan)
719 dma_release_channel(host->dma_chan); 727 dma_release_channel(host->dma_chan);
720 if (host->ecc)
721 iounmap(host->ecc);
722err_ecc_ioremap:
723 iounmap(host->io_base); 728 iounmap(host->io_base);
724err_nand_ioremap: 729err_nand_ioremap:
725 kfree(host); 730 kfree(host);