aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorIvo Clarysse <ivo.clarysse@gmail.com>2010-04-08 10:14:44 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-05-13 20:02:32 -0400
commitd484018056816178abffacb84b8c16628e880c83 (patch)
tree830502fd8d5129d8662c6fd1f1dfcde4b3eeeed9 /drivers/mtd
parent9d5da3a9b849cf42fc165e90b1d39e2fd1e199a8 (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.c90
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
545static 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 */
547static void mxc_nand_command(struct mtd_info *mtd, unsigned command, 582static 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;