diff options
author | Ivo Clarysse <ivo.clarysse@gmail.com> | 2010-04-08 10:14:44 -0400 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2010-04-14 02:58:36 -0400 |
commit | 7422f27a8ad7f6a7474e324a61e5a7f8be166c25 (patch) | |
tree | 3e53f34417610eb66bcce7728428a02ab27d5df3 /drivers | |
parent | 8bcc84ad61a601f4d8fc960d5e6495d6fc88177b (diff) |
MXC: 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>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-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 b2900d8406d3..ed27d38de27a 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; |
@@ -679,7 +718,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
679 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | 718 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; |
680 | struct mxc_nand_host *host; | 719 | struct mxc_nand_host *host; |
681 | struct resource *res; | 720 | struct resource *res; |
682 | uint16_t tmp; | ||
683 | int err = 0, nr_parts = 0; | 721 | int err = 0, nr_parts = 0; |
684 | struct nand_ecclayout *oob_smallpage, *oob_largepage; | 722 | struct nand_ecclayout *oob_smallpage, *oob_largepage; |
685 | 723 | ||
@@ -743,51 +781,17 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
743 | host->spare_len = 64; | 781 | host->spare_len = 64; |
744 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 782 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
745 | oob_largepage = &nandv2_hw_eccoob_largepage; | 783 | oob_largepage = &nandv2_hw_eccoob_largepage; |
784 | this->ecc.bytes = 9; | ||
746 | } else if (nfc_is_v1()) { | 785 | } else if (nfc_is_v1()) { |
747 | host->regs = host->base; | 786 | host->regs = host->base; |
748 | host->spare0 = host->base + 0x800; | 787 | host->spare0 = host->base + 0x800; |
749 | host->spare_len = 16; | 788 | host->spare_len = 16; |
750 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 789 | oob_smallpage = &nandv1_hw_eccoob_smallpage; |
751 | oob_largepage = &nandv1_hw_eccoob_largepage; | 790 | oob_largepage = &nandv1_hw_eccoob_largepage; |
752 | } else | ||
753 | BUG(); | ||
754 | |||
755 | /* disable interrupt and spare enable */ | ||
756 | tmp = readw(host->regs + NFC_CONFIG1); | ||
757 | tmp |= NFC_INT_MSK; | ||
758 | tmp &= ~NFC_SP_EN; | ||
759 | writew(tmp, host->regs + NFC_CONFIG1); | ||
760 | |||
761 | init_waitqueue_head(&host->irq_waitq); | ||
762 | |||
763 | host->irq = platform_get_irq(pdev, 0); | ||
764 | |||
765 | err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); | ||
766 | if (err) | ||
767 | goto eirq; | ||
768 | |||
769 | /* Reset NAND */ | ||
770 | this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
771 | |||
772 | /* preset operation */ | ||
773 | /* Unlock the internal RAM Buffer */ | ||
774 | writew(0x2, host->regs + NFC_CONFIG); | ||
775 | |||
776 | /* Blocks to be unlocked */ | ||
777 | if (nfc_is_v21()) { | ||
778 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | ||
779 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | ||
780 | this->ecc.bytes = 9; | ||
781 | } else if (nfc_is_v1()) { | ||
782 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | ||
783 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | ||
784 | this->ecc.bytes = 3; | 791 | this->ecc.bytes = 3; |
785 | } else | 792 | } else |
786 | BUG(); | 793 | BUG(); |
787 | 794 | ||
788 | /* Unlock Block Command for given address range */ | ||
789 | writew(0x4, host->regs + NFC_WRPROT); | ||
790 | |||
791 | this->ecc.size = 512; | 795 | this->ecc.size = 512; |
792 | this->ecc.layout = oob_smallpage; | 796 | this->ecc.layout = oob_smallpage; |
793 | 797 | ||
@@ -796,14 +800,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
796 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 800 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
797 | this->ecc.correct = mxc_nand_correct_data; | 801 | this->ecc.correct = mxc_nand_correct_data; |
798 | this->ecc.mode = NAND_ECC_HW; | 802 | this->ecc.mode = NAND_ECC_HW; |
799 | tmp = readw(host->regs + NFC_CONFIG1); | ||
800 | tmp |= NFC_ECC_EN; | ||
801 | writew(tmp, host->regs + NFC_CONFIG1); | ||
802 | } else { | 803 | } else { |
803 | this->ecc.mode = NAND_ECC_SOFT; | 804 | this->ecc.mode = NAND_ECC_SOFT; |
804 | tmp = readw(host->regs + NFC_CONFIG1); | ||
805 | tmp &= ~NFC_ECC_EN; | ||
806 | writew(tmp, host->regs + NFC_CONFIG1); | ||
807 | } | 805 | } |
808 | 806 | ||
809 | /* NAND bus width determines access funtions used by upper layer */ | 807 | /* NAND bus width determines access funtions used by upper layer */ |
@@ -817,6 +815,14 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
817 | this->options |= NAND_USE_FLASH_BBT; | 815 | this->options |= NAND_USE_FLASH_BBT; |
818 | } | 816 | } |
819 | 817 | ||
818 | init_waitqueue_head(&host->irq_waitq); | ||
819 | |||
820 | host->irq = platform_get_irq(pdev, 0); | ||
821 | |||
822 | err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host); | ||
823 | if (err) | ||
824 | goto eirq; | ||
825 | |||
820 | /* first scan to find the device and get the page size */ | 826 | /* first scan to find the device and get the page size */ |
821 | if (nand_scan_ident(mtd, 1)) { | 827 | if (nand_scan_ident(mtd, 1)) { |
822 | err = -ENXIO; | 828 | err = -ENXIO; |