[PATCH] nandboot with 2k pages


Thu Dec 11 11:56:01 CET 2008


---
 drivers/nand/nand_imx.c             |   94 +++++++++++++++++++++++++++++------
 include/asm-arm/arch-imx/imx-nand.h |    2 +-
 2 files changed, 79 insertions(+), 17 deletions(-)

diff --git a/drivers/nand/nand_imx.c b/drivers/nand/nand_imx.c
index f7f50b0..3bf67de 100644
--- a/drivers/nand/nand_imx.c
+++ b/drivers/nand/nand_imx.c
@@ -1090,26 +1090,74 @@ static struct driver_d imx_nand_driver = {

 static void __nand_boot_init nfc_addr(struct imx_nand_host *host, u32 offs)
 {
-	send_addr(host, offs & 0xff);
-	send_addr(host, (offs >> 9) & 0xff);
-	send_addr(host, (offs >> 17) & 0xff);
-	send_addr(host, (offs >> 25) & 0xff);
+	if (!host->pagesize_2k) {
+		send_addr(host, offs & 0xff);
+		send_addr(host, (offs >> 9) & 0xff);
+		send_addr(host, (offs >> 17) & 0xff);
+		send_addr(host, (offs >> 25) & 0xff);
+	} else {
+		/* imx27 Nand flash controller can only read full 2k page */
+		send_addr(host, 0);
+		send_addr(host, 0);
+		send_addr(host, (offs >> 11) & 0xff);
+		send_addr(host, (offs >> 19) & 0xff);
+		/* FIXME: add another send_addr for nandflash > 1Gbit
+		 * if (read electronic signature byte 5 > 1 Gbit)
+		 *	send_addr(host, (offs >> 28) & 0xff);
+		 */
+
+		/* send read start command */
+		send_cmd(host, NAND_CMD_READSTART);
+	}
 }

-static int __nand_boot_init block_is_bad(struct imx_nand_host *host, u32 offs)
+static int __nand_boot_init block_is_bad(struct imx_nand_host *host, u32 offs,
+					 u32 pagesize)
 {
-	send_cmd(host, NAND_CMD_READOOB);
-	nfc_addr(host, offs);
-	send_read_page(host, 0, 1);
-
-	return (readw(host->regs + SPARE_AREA0) & 0xff) == 0xff ? 0 : 1;
+	if (!host->pagesize_2k) {
+		send_cmd(host, NAND_CMD_READOOB);
+		nfc_addr(host, offs);
+		send_read_page(host, 0, 1);
+		if ((readw(host->regs + SPARE_AREA0) & 0xff) != 0xff)
+			return 1;
+	} else {
+		/* The AdvancedToolKit Mark the two first page of each block */
+		/* check first page */
+		send_cmd(host, NAND_CMD_READ0);
+		nfc_addr(host, offs);
+		send_read_page(host, 0, 1);
+		send_read_page(host, 1, 1);
+		send_read_page(host, 2, 1);
+		send_read_page(host, 3, 1);
+
+		if (readw(host->regs + NFC_ECC_STATUS_RESULT) & 0xa)
+			return 1;
+
+		if ((readw(host->regs + SPARE_AREA0 + 4) & 0xFF00) != 0xFF00)
+			return 1;
+
+		/* check second page */
+		send_cmd(host, NAND_CMD_READ0);
+		nfc_addr(host, offs + pagesize);
+		send_read_page(host, 0, 1);
+		send_read_page(host, 1, 1);
+		send_read_page(host, 2, 1);
+		send_read_page(host, 3, 1);
+
+		if (readw(host->regs + NFC_ECC_STATUS_RESULT) & 0xa)
+			return 1;
+
+		if ((readw(host->regs + SPARE_AREA0 + 4) & 0xFF00) != 0xFF00)
+			return 1;
+	
+	}
+	return 0;
 }

-void __nand_boot_init imx_nand_load_image(void *dest, int size, int pagesize,
-		int blocksize)
+void __nand_boot_init imx_nand_load_image(void *dest, int size, int blocksize)
 {
 	struct imx_nand_host host;
-	u32 tmp, page, block;
+	u32 tmp, page, block, pagesize;

 	PCCR1 |= PCCR1_NFC_BAUDEN;

@@ -1117,6 +1165,10 @@ void __nand_boot_init imx_nand_load_image(void
*dest, int size, int pagesize,
 	case GPCR_BOOT_8BIT_NAND_2k:
 	case GPCR_BOOT_16BIT_NAND_2k:
 		host.pagesize_2k = 1;
+		pagesize = 2048;
+		break;
+	default:
+		pagesize = 512;
 	}

 	host.regs = (void __iomem *)IMX_NFC_BASE;
@@ -1134,14 +1186,19 @@ void __nand_boot_init imx_nand_load_image(void
*dest, int size, int pagesize,
 	/* Unlock Block Command for given address range */
 	writew(0x4, host.regs + NFC_WRPROT);

+	/* clear all operation  */
+	writew(0x8000, host.regs + NFC_CONFIG1);
+
+	/* enable ECC, disable spare only and interrupt */
 	tmp = readw(host.regs + NFC_CONFIG1);
-	tmp |= NFC_ECC_EN;
+	tmp |= NFC_ECC_EN | NFC_INT_MSK;
+	tmp &= ~ NFC_SP_EN;
 	writew(tmp, host.regs + NFC_CONFIG1);

 	block = page = 0;

 	while (1) {
-		if (!block_is_bad(&host, block * blocksize)) {
+		if (!block_is_bad(&host, block * blocksize, pagesize)) {
 			page = 0;
 			while (page * pagesize < blocksize) {
 				debug("page: %d block: %d dest: %p src "
@@ -1154,8 +1211,13 @@ void __nand_boot_init imx_nand_load_image(void
*dest, int size, int pagesize,
 				nfc_addr(&host, block * blocksize +
 						page * pagesize);
 				send_read_page(&host, 0, 0);
+				if (host.pagesize_2k) {
+					send_read_page(&host, 1, 0);
+					send_read_page(&host, 2, 0);
+					send_read_page(&host, 3, 0);
+				}
 				page++;
-				memcpy32(dest, host.regs, 512);
+				memcpy32(dest, host.regs, pagesize);
 				dest += pagesize;
 				size -= pagesize;
 				if (size <= 0)
diff --git a/include/asm-arm/arch-imx/imx-nand.h
b/include/asm-arm/arch-imx/imx-nand.h
index 5ebe0be..eca8fef 100644
--- a/include/asm-arm/arch-imx/imx-nand.h
+++ b/include/asm-arm/arch-imx/imx-nand.h
@@ -3,7 +3,7 @@

 #include <linux/mtd/mtd.h>

-void imx_nand_load_image(void *dest, int size, int pagesize, int blocksize);
+void imx_nand_load_image(void *dest, int size, int blocksize);

 struct imx_nand_platform_data {
 	int width;
-- 
1.4.4.4

------=_Part_52959_933696.1229345345706--


More information about the U-Boot mailing list