summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-10-26 11:52:15 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2009-10-26 13:06:02 +0100
commitef0aa39fb4d6391b12469347b67a776b1c4fb9d4 (patch)
tree48861744f9e4550acb4da549838c2b8588d82a3b
parent011f6dca8980f3fd3391c9a7963dc877d1592edf (diff)
downloadbarebox-ef0aa39fb4d6391b12469347b67a776b1c4fb9d4.tar.gz
barebox-ef0aa39fb4d6391b12469347b67a776b1c4fb9d4.tar.xz
imx_nand: add booting from 2k NAND support
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/nand/nand_imx.c83
1 files changed, 46 insertions, 37 deletions
diff --git a/drivers/nand/nand_imx.c b/drivers/nand/nand_imx.c
index fd299d78c8..039cd58e5e 100644
--- a/drivers/nand/nand_imx.c
+++ b/drivers/nand/nand_imx.c
@@ -215,7 +215,7 @@ static void __nand_boot_init send_cmd(struct imx_nand_host *host, u16 cmd)
* @param addr address to be written to NFC.
* @param islast True if this is the last address cycle for command
*/
-static void __nand_boot_init send_addr(struct imx_nand_host *host, u16 addr)
+static void __nand_boot_init noinline send_addr(struct imx_nand_host *host, u16 addr)
{
MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
@@ -884,19 +884,18 @@ 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);
-}
-
-static int __nand_boot_init block_is_bad(struct imx_nand_host *host, u32 offs)
-{
- send_cmd(host, NAND_CMD_READOOB);
- nfc_addr(host, offs);
- send_page(host, NFC_OUTPUT);
-
- return (readw(host->regs + SPARE_AREA0 + 4) & 0xff) == 0xff ? 0 : 1;
+ if (host->pagesize_2k) {
+ send_addr(host, offs & 0xff);
+ send_addr(host, offs & 0xff);
+ send_addr(host, (offs >> 11) & 0xff);
+ send_addr(host, (offs >> 19) & 0xff);
+ send_addr(host, (offs >> 27) & 0xff);
+ } else {
+ send_addr(host, offs & 0xff);
+ send_addr(host, (offs >> 9) & 0xff);
+ send_addr(host, (offs >> 17) & 0xff);
+ send_addr(host, (offs >> 25) & 0xff);
+ }
}
void __nand_boot_init imx_nand_load_image(void *dest, int size)
@@ -944,35 +943,45 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size)
tmp = readw(host.regs + NFC_CONFIG1);
tmp |= NFC_ECC_EN;
+ tmp &= ~NFC_SP_EN;
writew(tmp, host.regs + NFC_CONFIG1);
block = page = 0;
while (1) {
- if (!block_is_bad(&host, block * blocksize)) {
- page = 0;
- while (page * pagesize < blocksize) {
- debug("page: %d block: %d dest: %p src "
- "0x%08x\n",
- page, block, dest,
- block * blocksize +
- page * pagesize);
-
- send_cmd(&host, NAND_CMD_READ0);
- nfc_addr(&host, block * blocksize +
- page * pagesize);
- if (host.pagesize_2k)
- send_cmd(&host, NAND_CMD_READSTART);
- send_page(&host, NFC_OUTPUT);
- page++;
- memcpy32(dest, host.regs, 512);
- dest += pagesize;
- size -= pagesize;
- if (size <= 0)
- return;
+ page = 0;
+ while (page * pagesize < blocksize) {
+ debug("page: %d block: %d dest: %p src "
+ "0x%08x\n",
+ page, block, dest,
+ block * blocksize +
+ page * pagesize);
+
+ send_cmd(&host, NAND_CMD_READ0);
+ nfc_addr(&host, block * blocksize +
+ page * pagesize);
+ if (host.pagesize_2k)
+ send_cmd(&host, NAND_CMD_READSTART);
+ send_page(&host, NFC_OUTPUT);
+ page++;
+
+ if (host.pagesize_2k) {
+ if ((readw(host.regs + SPARE_AREA0) & 0xff)
+ != 0xff)
+ continue;
+ } else {
+ if ((readw(host.regs + SPARE_AREA0 + 4) & 0xff00)
+ != 0xff00)
+ continue;
}
- } else
- debug("skip bad block at 0x%08x\n", block * blocksize);
+
+ memcpy32(dest, host.regs, pagesize);
+ dest += pagesize;
+ size -= pagesize;
+
+ if (size <= 0)
+ return;
+ }
block++;
}
}