diff options
Diffstat (limited to 'drivers/nand/nand_imx.c')
-rw-r--r-- | drivers/nand/nand_imx.c | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/drivers/nand/nand_imx.c b/drivers/nand/nand_imx.c index afd5637626..398a2686f4 100644 --- a/drivers/nand/nand_imx.c +++ b/drivers/nand/nand_imx.c @@ -200,12 +200,17 @@ static struct nand_ecclayout nandv2_hw_eccoob_largepage = { } }; -static void __nand_boot_init memcpy32(void *trg, const void *src, int size) +static void memcpy32(void *trg, const void *src, int size) { int i; unsigned int *t = trg; unsigned const int *s = src; +#ifdef CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS + if (!((unsigned long)trg & 0x3) && !((unsigned long)src & 0x3)) + memcpy(trg, src, size); + else +#endif for (i = 0; i < (size >> 2); i++) *t++ = *s++; } @@ -290,7 +295,7 @@ static void __nand_boot_init noinline send_addr(struct imx_nand_host *host, u16 * @param spare_only set true if only the spare area is transferred */ static void __nand_boot_init send_page(struct imx_nand_host *host, - unsigned int ops) + unsigned int ops, int wait) { int bufs, i; @@ -306,7 +311,8 @@ static void __nand_boot_init send_page(struct imx_nand_host *host, writew(ops, host->regs + NFC_CONFIG2); /* Wait for operation to complete */ - wait_op_done(host); + if (wait) + wait_op_done(host); } } @@ -499,7 +505,7 @@ static void imx_nand_write_buf(struct mtd_info *mtd, int n = mtd->oobsize + mtd->writesize - col; n = min(n, len); - memcpy32(host->data_buf + col, buf, n); + memcpy(host->data_buf + col, buf, n); host->buf_start += n; } @@ -523,7 +529,7 @@ static void imx_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len) n = min(n, len); - memcpy32(buf, host->data_buf + col, len); + memcpy(buf, host->data_buf + col, len); host->buf_start += len; } @@ -666,11 +672,17 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command, { struct nand_chip *nand_chip = mtd->priv; struct imx_nand_host *host = nand_chip->priv; + static int cached = -1; MTD_DEBUG(MTD_DEBUG_LEVEL3, "imx_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", command, column, page_addr); + if (cached != -1) + wait_op_done(host); + if (command != NAND_CMD_READ0) + cached = -1; + /* * Reset command state information */ @@ -697,17 +709,44 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command, command = NAND_CMD_READ0; - send_cmd(host, command); - mxc_do_addr_cycle(mtd, column, page_addr); + if (cached == page_addr) { + memcpy32(host->data_buf, host->main_area0, mtd->writesize); + copy_spare(mtd, 1); - if (host->pagesize_2k) - /* send read confirm command */ - send_cmd(host, NAND_CMD_READSTART); + send_cmd(host, command); + mxc_do_addr_cycle(mtd, column, page_addr + 1); + + if (host->pagesize_2k) + /* send read confirm command */ + send_cmd(host, NAND_CMD_READSTART); + + send_page(host, NFC_OUTPUT, 0); + + cached = page_addr + 1; + } else { + host->buf_start = column; + send_cmd(host, command); + mxc_do_addr_cycle(mtd, column, page_addr); + + if (host->pagesize_2k) + /* send read confirm command */ + send_cmd(host, NAND_CMD_READSTART); - send_page(host, NFC_OUTPUT); + send_page(host, NFC_OUTPUT, 1); + memcpy32(host->data_buf, host->main_area0, mtd->writesize); + copy_spare(mtd, 1); + + send_cmd(host, command); + mxc_do_addr_cycle(mtd, column, page_addr + 1); + + if (host->pagesize_2k) + /* send read confirm command */ + send_cmd(host, NAND_CMD_READSTART); + + send_page(host, NFC_OUTPUT, 0); + cached = page_addr + 1; + } - memcpy32(host->data_buf, host->main_area0, mtd->writesize); - copy_spare(mtd, 1); break; case NAND_CMD_SEQIN: @@ -744,7 +783,7 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: memcpy32(host->main_area0, host->data_buf, mtd->writesize); copy_spare(mtd, 0); - send_page(host, NFC_INPUT); + send_page(host, NFC_INPUT, 1); send_cmd(host, command); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -845,7 +884,7 @@ static int __init imxnd_probe(struct device_d *dev) #endif /* Allocate memory for MTD device structure and private data */ host = kzalloc(sizeof(struct imx_nand_host) + NAND_MAX_PAGESIZE + - NAND_MAX_OOBSIZE, GFP_KERNEL); + NAND_MAX_OOBSIZE * 2, GFP_KERNEL); if (!host) return -ENOMEM; @@ -1025,6 +1064,16 @@ static void __nand_boot_init nfc_addr(struct imx_nand_host *host, u32 offs) } } +static void __nand_boot_init __memcpy32(void *trg, const void *src, int size) +{ + int i; + unsigned int *t = trg; + unsigned const int *s = src; + + for (i = 0; i < (size >> 2); i++) + *t++ = *s++; +} + void __nand_boot_init imx_nand_load_image(void *dest, int size) { struct imx_nand_host host; @@ -1122,7 +1171,7 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size) page * pagesize); if (host.pagesize_2k) send_cmd(&host, NAND_CMD_READSTART); - send_page(&host, NFC_OUTPUT); + send_page(&host, NFC_OUTPUT, 1); page++; if (host.pagesize_2k) { @@ -1135,7 +1184,7 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size) continue; } - memcpy32(dest, host.base, pagesize); + __memcpy32(dest, host.base, pagesize); dest += pagesize; size -= pagesize; |