diff options
author | Ivo Clarysse <ivo.clarysse@gmail.com> | 2010-04-08 10:14:44 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-05-13 20:02:32 -0400 |
commit | d484018056816178abffacb84b8c16628e880c83 (patch) | |
tree | 830502fd8d5129d8662c6fd1f1dfcde4b3eeeed9 /drivers/mtd | |
parent | 9d5da3a9b849cf42fc165e90b1d39e2fd1e199a8 (diff) |
mtd: mxc_nand: set NFC registers after reset
This patch allows the mxc_nand driver to reset the NAND
flash controller. NFC registers are (re-)set after
completion of the reset, as a reset will have reverted
the NFC registers to their default values.
Signed-off-by: Ivo Clarysse <ivo.clarysse@gmail.com>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 90 |
1 files changed, 48 insertions, 42 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 2ba3be1f4937..b527aa2d687d 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -542,6 +542,41 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
542 | } | 542 | } |
543 | } | 543 | } |
544 | 544 | ||
545 | static void preset(struct mtd_info *mtd) | ||
546 | { | ||
547 | struct nand_chip *nand_chip = mtd->priv; | ||
548 | struct mxc_nand_host *host = nand_chip->priv; | ||
549 | uint16_t tmp; | ||
550 | |||
551 | /* disable interrupt, disable spare enable */ | ||
552 | tmp = readw(host->regs + NFC_CONFIG1); | ||
553 | tmp |= NFC_INT_MSK; | ||
554 | tmp &= ~NFC_SP_EN; | ||
555 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | ||
556 | tmp |= NFC_ECC_EN; | ||
557 | } else { | ||
558 | tmp &= ~NFC_ECC_EN; | ||
559 | } | ||
560 | writew(tmp, host->regs + NFC_CONFIG1); | ||
561 | /* preset operation */ | ||
562 | |||
563 | /* Unlock the internal RAM Buffer */ | ||
564 | writew(0x2, host->regs + NFC_CONFIG); | ||
565 | |||
566 | /* Blocks to be unlocked */ | ||
567 | if (nfc_is_v21()) { | ||
568 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | ||
569 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | ||
570 | } else if (nfc_is_v1()) { | ||
571 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | ||
572 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | ||
573 | } else | ||
574 | BUG(); | ||
575 | |||
576 | /* Unlock Block Command for given address range */ | ||
577 | writew(0x4, host->regs + NFC_WRPROT); | ||
578 | } | ||
579 | |||
545 | /* Used by the upper layer to write command to NAND Flash for | 580 | /* Used by the upper layer to write command to NAND Flash for |
546 | * different operations to be carried out on NAND Flash */ | 581 | * different operations to be carried out on NAND Flash */ |
547 | static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | 582 | static void mxc_nand_command(struct mtd_info *mtd, unsigned command, |
@@ -559,6 +594,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
559 | 594 | ||
560 | /* Command pre-processing step */ | 595 | /* Command pre-processing step */ |
561 | switch (command) { | 596 | switch (command) { |
597 | case NAND_CMD_RESET: | ||
598 | send_cmd(host, command, false); | ||
599 | preset(mtd); | ||
600 | break; | ||
562 | 601 | ||
563 | case NAND_CMD_STATUS: | 602 | case NAND_CMD_STATUS: |
564 | host->buf_start = 0; | 603 | host->buf_start = 0; |
@@ -680,7 +719,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
680 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | 719 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; |
681 | struct mxc_nand_host *host; | 720 | struct mxc_nand_host *host; |
682 | struct resource *res; | 721 | struct resource *res; |
683 | uint16_t tmp; | ||
684 | int err = 0, nr_parts = 0; | 722 | int err = 0, nr_parts = 0; |
685 | struct nand_ecclayout *oob_smallpage, *oob_largepage; | 723 | struct nand_ecclayout *oob_smallpage, *oob_largepage; |
686 | 724 | ||
@@ -744,51 +782,17 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
744 | host->spare_len = 64; | 782 | host->spare_len = 64; |
745 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 783 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
746 | oob_largepage = &nandv2_hw_eccoob_largepage; | 784 | oob_largepage = &nandv2_hw_eccoob_largepage; |
785 | this->ecc.bytes = 9; | ||
747 | } else if (nfc_is_v1()) { | 786 | } else if (nfc_is_v1()) { |
748 | host->regs = host->base; | 787 | host->regs = host->base; |
749 | host->spare0 = host->base + 0x800; | 788 | host->spare0 = host->base + 0x800; |
750 | host->spare_len = 16; | 789 | host->spare_len = 16; |
751 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 790 | oob_smallpage = &nandv1_hw_eccoob_smallpage; |
752 | oob_largepage = &nandv1_hw_eccoob_largepage; | 791 | oob_largepage = &nandv1_hw_eccoob_largepage; |
753 | } else | ||
754 | BUG(); | ||
755 | |||
756 | /* disable interrupt and spare enable */ | ||
757 | tmp = readw(host->regs + NFC_CONFIG1); | ||
758 | tmp |= NFC_INT_MSK; | ||
759 | tmp &= ~NFC_SP_EN; | ||
760 | writew(tmp, host->regs + NFC_CONFIG1); | ||
761 | |||
762 | init_waitqueue_head(&host->irq_waitq); | ||
763 | |||
764 | host->irq = platform_get_irq(pdev, 0); | ||
765 | |||
766 | err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); | ||
767 | if (err) | ||
768 | goto eirq; | ||
769 | |||
770 | /* Reset NAND */ | ||
771 | this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
772 | |||
773 | /* preset operation */ | ||
774 | /* Unlock the internal RAM Buffer */ | ||
775 | writew(0x2, host->regs + NFC_CONFIG); | ||
776 | |||
777 | /* Blocks to be unlocked */ | ||
778 | if (nfc_is_v21()) { | ||
779 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | ||
780 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | ||
781 | this->ecc.bytes = 9; | ||
782 | } else if (nfc_is_v1()) { | ||
783 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | ||
784 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | ||
785 | this->ecc.bytes = 3; | 792 | this->ecc.bytes = 3; |
786 | } else | 793 | } else |
787 | BUG(); | 794 | BUG(); |
788 | 795 | ||
789 | /* Unlock Block Command for given address range */ | ||
790 | writew(0x4, host->regs + NFC_WRPROT); | ||
791 | |||
792 | this->ecc.size = 512; | 796 | this->ecc.size = 512; |
793 | this->ecc.layout = oob_smallpage; | 797 | this->ecc.layout = oob_smallpage; |
794 | 798 | ||
@@ -797,14 +801,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
797 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 801 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
798 | this->ecc.correct = mxc_nand_correct_data; | 802 | this->ecc.correct = mxc_nand_correct_data; |
799 | this->ecc.mode = NAND_ECC_HW; | 803 | this->ecc.mode = NAND_ECC_HW; |
800 | tmp = readw(host->regs + NFC_CONFIG1); | ||
801 | tmp |= NFC_ECC_EN; | ||
802 | writew(tmp, host->regs + NFC_CONFIG1); | ||
803 | } else { | 804 | } else { |
804 | this->ecc.mode = NAND_ECC_SOFT; | 805 | this->ecc.mode = NAND_ECC_SOFT; |
805 | tmp = readw(host->regs + NFC_CONFIG1); | ||
806 | tmp &= ~NFC_ECC_EN; | ||
807 | writew(tmp, host->regs + NFC_CONFIG1); | ||
808 | } | 806 | } |
809 | 807 | ||
810 | /* NAND bus width determines access funtions used by upper layer */ | 808 | /* NAND bus width determines access funtions used by upper layer */ |
@@ -818,6 +816,14 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
818 | this->options |= NAND_USE_FLASH_BBT; | 816 | this->options |= NAND_USE_FLASH_BBT; |
819 | } | 817 | } |
820 | 818 | ||
819 | init_waitqueue_head(&host->irq_waitq); | ||
820 | |||
821 | host->irq = platform_get_irq(pdev, 0); | ||
822 | |||
823 | err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); | ||
824 | if (err) | ||
825 | goto eirq; | ||
826 | |||
821 | /* first scan to find the device and get the page size */ | 827 | /* first scan to find the device and get the page size */ |
822 | if (nand_scan_ident(mtd, 1, NULL)) { | 828 | if (nand_scan_ident(mtd, 1, NULL)) { |
823 | err = -ENXIO; | 829 | err = -ENXIO; |