diff options
author | Josh Wu <josh.wu@atmel.com> | 2012-06-25 06:07:43 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-07-06 13:17:07 -0400 |
commit | 3dfe41a4c705223c66373968327407e11c2fb1a1 (patch) | |
tree | 65ab13c0ae765811058ad60a3a4eeae826da0dc9 /drivers/mtd/nand | |
parent | 95c1b0ce2ad8bfc0092782a75e86b219eb2c5204 (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.c | 127 |
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 | ||
530 | static 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 | ||
713 | err_scan_tail: | 718 | err_scan_tail: |
719 | if (host->ecc) | ||
720 | iounmap(host->ecc); | ||
721 | err_hw_ecc: | ||
714 | err_scan_ident: | 722 | err_scan_ident: |
715 | err_no_card: | 723 | err_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); | ||
722 | err_ecc_ioremap: | ||
723 | iounmap(host->io_base); | 728 | iounmap(host->io_base); |
724 | err_nand_ioremap: | 729 | err_nand_ioremap: |
725 | kfree(host); | 730 | kfree(host); |