aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/mxc_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/mxc_nand.c')
-rw-r--r--drivers/mtd/nand/mxc_nand.c66
1 files changed, 54 insertions, 12 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 40c26080ecda..76beea40d2cf 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -138,7 +138,14 @@ static struct nand_ecclayout nand_hw_eccoob_8 = {
138static struct nand_ecclayout nand_hw_eccoob_16 = { 138static struct nand_ecclayout nand_hw_eccoob_16 = {
139 .eccbytes = 5, 139 .eccbytes = 5,
140 .eccpos = {6, 7, 8, 9, 10}, 140 .eccpos = {6, 7, 8, 9, 10},
141 .oobfree = {{0, 6}, {12, 4}, } 141 .oobfree = {{0, 5}, {11, 5}, }
142};
143
144static struct nand_ecclayout nand_hw_eccoob_64 = {
145 .eccbytes = 20,
146 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
147 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
148 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
142}; 149};
143 150
144#ifdef CONFIG_MTD_PARTITIONS 151#ifdef CONFIG_MTD_PARTITIONS
@@ -192,7 +199,7 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries,
192 } 199 }
193 udelay(1); 200 udelay(1);
194 } 201 }
195 if (max_retries <= 0) 202 if (max_retries < 0)
196 DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n", 203 DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
197 __func__, param); 204 __func__, param);
198 } 205 }
@@ -795,9 +802,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
795 send_addr(host, (page_addr & 0xff), false); 802 send_addr(host, (page_addr & 0xff), false);
796 803
797 if (host->pagesize_2k) { 804 if (host->pagesize_2k) {
798 send_addr(host, (page_addr >> 8) & 0xFF, false); 805 if (mtd->size >= 0x10000000) {
799 if (mtd->size >= 0x40000000) 806 /* paddr_8 - paddr_15 */
807 send_addr(host, (page_addr >> 8) & 0xff, false);
800 send_addr(host, (page_addr >> 16) & 0xff, true); 808 send_addr(host, (page_addr >> 16) & 0xff, true);
809 } else
810 /* paddr_8 - paddr_15 */
811 send_addr(host, (page_addr >> 8) & 0xff, true);
801 } else { 812 } else {
802 /* One more address cycle for higher density devices */ 813 /* One more address cycle for higher density devices */
803 if (mtd->size >= 0x4000000) { 814 if (mtd->size >= 0x4000000) {
@@ -923,7 +934,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
923 this->ecc.mode = NAND_ECC_HW; 934 this->ecc.mode = NAND_ECC_HW;
924 this->ecc.size = 512; 935 this->ecc.size = 512;
925 this->ecc.bytes = 3; 936 this->ecc.bytes = 3;
926 this->ecc.layout = &nand_hw_eccoob_8;
927 tmp = readw(host->regs + NFC_CONFIG1); 937 tmp = readw(host->regs + NFC_CONFIG1);
928 tmp |= NFC_ECC_EN; 938 tmp |= NFC_ECC_EN;
929 writew(tmp, host->regs + NFC_CONFIG1); 939 writew(tmp, host->regs + NFC_CONFIG1);
@@ -957,12 +967,44 @@ static int __init mxcnd_probe(struct platform_device *pdev)
957 this->ecc.layout = &nand_hw_eccoob_16; 967 this->ecc.layout = &nand_hw_eccoob_16;
958 } 968 }
959 969
960 host->pagesize_2k = 0; 970 /* first scan to find the device and get the page size */
971 if (nand_scan_ident(mtd, 1)) {
972 err = -ENXIO;
973 goto escan;
974 }
961 975
962 /* Scan to find existence of the device */ 976 host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
963 if (nand_scan(mtd, 1)) { 977
964 DEBUG(MTD_DEBUG_LEVEL0, 978 if (this->ecc.mode == NAND_ECC_HW) {
965 "MXC_ND: Unable to find any NAND device.\n"); 979 switch (mtd->oobsize) {
980 case 8:
981 this->ecc.layout = &nand_hw_eccoob_8;
982 break;
983 case 16:
984 this->ecc.layout = &nand_hw_eccoob_16;
985 break;
986 case 64:
987 this->ecc.layout = &nand_hw_eccoob_64;
988 break;
989 default:
990 /* page size not handled by HW ECC */
991 /* switching back to soft ECC */
992 this->ecc.size = 512;
993 this->ecc.bytes = 3;
994 this->ecc.layout = &nand_hw_eccoob_8;
995 this->ecc.mode = NAND_ECC_SOFT;
996 this->ecc.calculate = NULL;
997 this->ecc.correct = NULL;
998 this->ecc.hwctl = NULL;
999 tmp = readw(host->regs + NFC_CONFIG1);
1000 tmp &= ~NFC_ECC_EN;
1001 writew(tmp, host->regs + NFC_CONFIG1);
1002 break;
1003 }
1004 }
1005
1006 /* second phase scan */
1007 if (nand_scan_tail(mtd)) {
966 err = -ENXIO; 1008 err = -ENXIO;
967 goto escan; 1009 goto escan;
968 } 1010 }
@@ -985,7 +1027,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
985 return 0; 1027 return 0;
986 1028
987escan: 1029escan:
988 free_irq(host->irq, NULL); 1030 free_irq(host->irq, host);
989eirq: 1031eirq:
990 iounmap(host->regs); 1032 iounmap(host->regs);
991eres: 1033eres:
@@ -1005,7 +1047,7 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
1005 platform_set_drvdata(pdev, NULL); 1047 platform_set_drvdata(pdev, NULL);
1006 1048
1007 nand_release(&host->mtd); 1049 nand_release(&host->mtd);
1008 free_irq(host->irq, NULL); 1050 free_irq(host->irq, host);
1009 iounmap(host->regs); 1051 iounmap(host->regs);
1010 kfree(host); 1052 kfree(host);
1011 1053