aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorVladimir Barinov <vova.barinov@gmail.com>2009-05-25 05:06:17 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-06-05 13:15:41 -0400
commitbd3fd62ecc99c709739cb969be76f44903a4043b (patch)
treea0dd30dac98177e35bb097c4cd6b3974b202b139 /drivers/mtd
parentf36e20c01ad0104688f2eaebdf2213e749929c97 (diff)
mtd: MXC NAND support for 2KiB page size flashes
- Add support for 2KiB page size flashes - Fix page address access for large pages - Detect oob layout at runtime - handle pagesize_2k variable - Fix oob16 layout: reserve location 5 of oob area since it's used for bbt Signed-off-by: Vladimir Barinov <vova.barinov@gmail.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/mxc_nand.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index d5aea6951d0b..d03bd4eff722 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
@@ -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) {
@@ -919,7 +930,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
919 this->ecc.mode = NAND_ECC_HW; 930 this->ecc.mode = NAND_ECC_HW;
920 this->ecc.size = 512; 931 this->ecc.size = 512;
921 this->ecc.bytes = 3; 932 this->ecc.bytes = 3;
922 this->ecc.layout = &nand_hw_eccoob_8;
923 tmp = readw(host->regs + NFC_CONFIG1); 933 tmp = readw(host->regs + NFC_CONFIG1);
924 tmp |= NFC_ECC_EN; 934 tmp |= NFC_ECC_EN;
925 writew(tmp, host->regs + NFC_CONFIG1); 935 writew(tmp, host->regs + NFC_CONFIG1);
@@ -953,12 +963,44 @@ static int __init mxcnd_probe(struct platform_device *pdev)
953 this->ecc.layout = &nand_hw_eccoob_16; 963 this->ecc.layout = &nand_hw_eccoob_16;
954 } 964 }
955 965
956 host->pagesize_2k = 0; 966 /* first scan to find the device and get the page size */
967 if (nand_scan_ident(mtd, 1)) {
968 err = -ENXIO;
969 goto escan;
970 }
957 971
958 /* Scan to find existence of the device */ 972 host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
959 if (nand_scan(mtd, 1)) { 973
960 DEBUG(MTD_DEBUG_LEVEL0, 974 if (this->ecc.mode == NAND_ECC_HW) {
961 "MXC_ND: Unable to find any NAND device.\n"); 975 switch (mtd->oobsize) {
976 case 8:
977 this->ecc.layout = &nand_hw_eccoob_8;
978 break;
979 case 16:
980 this->ecc.layout = &nand_hw_eccoob_16;
981 break;
982 case 64:
983 this->ecc.layout = &nand_hw_eccoob_64;
984 break;
985 default:
986 /* page size not handled by HW ECC */
987 /* switching back to soft ECC */
988 this->ecc.size = 512;
989 this->ecc.bytes = 3;
990 this->ecc.layout = &nand_hw_eccoob_8;
991 this->ecc.mode = NAND_ECC_SOFT;
992 this->ecc.calculate = NULL;
993 this->ecc.correct = NULL;
994 this->ecc.hwctl = NULL;
995 tmp = readw(host->regs + NFC_CONFIG1);
996 tmp &= ~NFC_ECC_EN;
997 writew(tmp, host->regs + NFC_CONFIG1);
998 break;
999 }
1000 }
1001
1002 /* second phase scan */
1003 if (nand_scan_tail(mtd)) {
962 err = -ENXIO; 1004 err = -ENXIO;
963 goto escan; 1005 goto escan;
964 } 1006 }