
Signed-off-by:Frederic Rodo fred.rodo@gmail.com --- 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;