mtd: MXC NAND support for 2KiB page size flashes

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Fri Jun 5 14:59:20 EDT 2009


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=bd3fd62ecc99c709739cb969be76f44903a4043b
Commit:     bd3fd62ecc99c709739cb969be76f44903a4043b
Parent:     f36e20c01ad0104688f2eaebdf2213e749929c97
Author:     Vladimir Barinov <vova.barinov at gmail.com>
AuthorDate: Mon May 25 13:06:17 2009 +0400
Committer:  David Woodhouse <David.Woodhouse at intel.com>
CommitDate: Fri Jun 5 18:15:41 2009 +0100

    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 at gmail.com>
    Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 drivers/mtd/nand/mxc_nand.c |   60 ++++++++++++++++++++++++++++++++++++------
 1 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index d5aea69..d03bd4e 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 = {
 static struct nand_ecclayout nand_hw_eccoob_16 = {
 	.eccbytes = 5,
 	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 6}, {12, 4}, }
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+
+static struct nand_ecclayout nand_hw_eccoob_64 = {
+	.eccbytes = 20,
+	.eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
+		   38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
+	.oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
 };
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -795,9 +802,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 		send_addr(host, (page_addr & 0xff), false);
 
 		if (host->pagesize_2k) {
-			send_addr(host, (page_addr >> 8) & 0xFF, false);
-			if (mtd->size >= 0x40000000)
+			if (mtd->size >= 0x10000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, false);
 				send_addr(host, (page_addr >> 16) & 0xff, true);
+			} else
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, true);
 		} else {
 			/* One more address cycle for higher density devices */
 			if (mtd->size >= 0x4000000) {
@@ -919,7 +930,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
 		this->ecc.bytes = 3;
-		this->ecc.layout = &nand_hw_eccoob_8;
 		tmp = readw(host->regs + NFC_CONFIG1);
 		tmp |= NFC_ECC_EN;
 		writew(tmp, host->regs + NFC_CONFIG1);
@@ -953,12 +963,44 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		this->ecc.layout = &nand_hw_eccoob_16;
 	}
 
-	host->pagesize_2k = 0;
+	/* first scan to find the device and get the page size */
+	if (nand_scan_ident(mtd, 1)) {
+		err = -ENXIO;
+		goto escan;
+	}
 
-	/* Scan to find existence of the device */
-	if (nand_scan(mtd, 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0,
-		      "MXC_ND: Unable to find any NAND device.\n");
+	host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
+
+	if (this->ecc.mode == NAND_ECC_HW) {
+		switch (mtd->oobsize) {
+		case 8:
+			this->ecc.layout = &nand_hw_eccoob_8;
+			break;
+		case 16:
+			this->ecc.layout = &nand_hw_eccoob_16;
+			break;
+		case 64:
+			this->ecc.layout = &nand_hw_eccoob_64;
+			break;
+		default:
+			/* page size not handled by HW ECC */
+			/* switching back to soft ECC */
+			this->ecc.size = 512;
+			this->ecc.bytes = 3;
+			this->ecc.layout = &nand_hw_eccoob_8;
+			this->ecc.mode = NAND_ECC_SOFT;
+			this->ecc.calculate = NULL;
+			this->ecc.correct = NULL;
+			this->ecc.hwctl = NULL;
+			tmp = readw(host->regs + NFC_CONFIG1);
+			tmp &= ~NFC_ECC_EN;
+			writew(tmp, host->regs + NFC_CONFIG1);
+			break;
+		}
+	}
+
+	/* second phase scan */
+	if (nand_scan_tail(mtd)) {
 		err = -ENXIO;
 		goto escan;
 	}



More information about the linux-mtd-cvs mailing list