From cfa460adfdefcc30d104e1a9ee44994ee349bb7b Mon Sep 17 00:00:00 2001 From: William Juul Date: Wed, 31 Oct 2007 13:53:06 +0100 Subject: Update MTD to that of Linux 2.6.22.1 A lot changed in the Linux MTD code, since it was last ported from Linux to U-Boot. This patch takes U-Boot NAND support to the level of Linux 2.6.22.1 and will enable support for very large NAND devices (4KB pages) and ease the compatibility between U-Boot and Linux filesystems. This patch is tested on two custom boards with PPC and ARM processors running YAFFS in U-Boot and Linux using gcc-4.1.2 cross compilers. MAKEALL ppc/arm has some issues: * DOC/OneNand/nand_spl is not building (I have not tried porting these parts, and since I do not have any HW and I am not familiar with this code/HW I think its best left to someone else.) Except for the issues mentioned above, I have ported all drivers necessary to run MAKEALL ppc/arm without errors and warnings. Many drivers were trivial to port, but some were not so trivial. The following drivers must be examined carefully and maybe rewritten to some degree: cpu/ppc4xx/ndfc.c cpu/arm926ejs/davinci/nand.c board/delta/nand.c board/zylonite/nand.c Signed-off-by: William Juul Signed-off-by: Stig Olsen Signed-off-by: Scott Wood --- common/cmd_nand.c | 273 ++++++++++++++++++++++++++---------------------------- 1 file changed, 131 insertions(+), 142 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 9e38bf768..3e76d8207 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -18,6 +18,7 @@ * */ #include +#include #if defined(CONFIG_CMD_NAND) @@ -34,7 +35,7 @@ int mtdparts_init(void); int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); int find_dev_and_part(const char *id, struct mtd_device **dev, - u8 *part_num, struct part_info **part); + u8 *part_num, struct part_info **part); #endif static int nand_dump_oob(nand_info_t *nand, ulong off) @@ -47,32 +48,38 @@ static int nand_dump(nand_info_t *nand, ulong off) int i; u_char *buf, *p; - buf = malloc(nand->oobblock + nand->oobsize); + buf = malloc(nand->writesize + nand->oobsize); if (!buf) { puts("No memory for page buffer\n"); return 1; } - off &= ~(nand->oobblock - 1); - i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize); + off &= ~(nand->writesize - 1); +#if 0 + i = nand_read_raw(nand, buf, off, nand->writesize, nand->oobsize); +#else + size_t dummy; + loff_t addr = (loff_t) off; + i = nand->read(nand, addr, nand->writesize, &dummy, buf); +#endif if (i < 0) { printf("Error (%d) reading page %08lx\n", i, off); free(buf); return 1; } printf("Page %08lx dump:\n", off); - i = nand->oobblock >> 4; p = buf; + i = nand->writesize >> 4; p = buf; while (i--) { - printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x" - " %02x %02x %02x %02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], - p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); p += 16; } puts("OOB:\n"); i = nand->oobsize >> 3; while (i--) { - printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); p += 8; } free(buf); @@ -155,7 +162,7 @@ out: int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int i, dev, ret; + int i, dev, ret = 0; ulong addr, off; size_t size; char *cmd, *s; @@ -182,8 +189,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { if (nand_info[i].name) printf("Device %d: %s, sector size %u KiB\n", - i, nand_info[i].name, - nand_info[i].erasesize >> 10); + i, nand_info[i].name, + nand_info[i].erasesize >> 10); } return 0; } @@ -192,11 +199,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (argc < 3) { if ((nand_curr_device < 0) || - (nand_curr_device >= CFG_MAX_NAND_DEVICE)) + (nand_curr_device >= CFG_MAX_NAND_DEVICE)) puts("\nno devices available\n"); else printf("\nDevice %d: %s\n", nand_curr_device, - nand_info[nand_curr_device].name); + nand_info[nand_curr_device].name); return 0; } dev = (int)simple_strtoul(argv[2], NULL, 10); @@ -219,11 +226,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 && - strncmp(cmd, "dump", 4) != 0 && - strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && - strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && - strcmp(cmd, "biterr") != 0 && - strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) + strncmp(cmd, "dump", 4) != 0 && + strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && + strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && + strcmp(cmd, "biterr") != 0 && + strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) goto usage; /* the following commands operate on the current device */ @@ -250,7 +257,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) { nand_erase_options_t opts; /* "clean" at index 2 means request to write cleanmarker */ - int clean = argc > 2 && !strcmp("clean", argv[2]); + int clean = !strcmp("clean", argv[2]); int o = clean ? 3 : 2; int scrub = !strcmp(cmd, "scrub"); @@ -260,6 +267,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; memset(&opts, 0, sizeof(opts)); + opts.offset = off; opts.length = size; opts.jffs2 = clean; @@ -320,40 +328,41 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) printf("\nNAND %s: ", read ? "read" : "write"); if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) return 1; - + s = strchr(cmd, '.'); if (s != NULL && - (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { + (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { if (read) { /* read */ nand_read_options_t opts; memset(&opts, 0, sizeof(opts)); - opts.buffer = (u_char*) addr; - opts.length = size; - opts.offset = off; - opts.quiet = quiet; - ret = nand_read_opts(nand, &opts); + opts.buffer = (u_char*) addr; + opts.length = size; + opts.offset = off; + opts.quiet = quiet; +// ret = nand_read_opts(nand, &opts); } else { /* write */ - nand_write_options_t opts; + mtd_oob_ops_t opts; memset(&opts, 0, sizeof(opts)); - opts.buffer = (u_char*) addr; - opts.length = size; - opts.offset = off; - /* opts.forcejffs2 = 1; */ - opts.pad = 1; - opts.blockalign = 1; - opts.quiet = quiet; - ret = nand_write_opts(nand, &opts); + opts.datbuf = (u_char*) addr; + opts.len = size; + opts.ooblen = 64; + opts.mode = MTD_OOB_AUTO; + ret = nand_write_opts(nand, off, &opts); } } else if (s != NULL && !strcmp(s, ".oob")) { - /* read out-of-band data */ + /* out-of-band data */ + mtd_oob_ops_t ops = { + .oobbuf = (u8 *)addr, + .ooblen = size, + .mode = MTD_OOB_RAW + }; + if (read) - ret = nand->read_oob(nand, off, size, &size, - (u_char *) addr); + ret = nand->read_oob(nand, off, &ops); else - ret = nand->write_oob(nand, off, size, &size, - (u_char *) addr); + ret = nand->write_oob(nand, off, &ops); } else { if (read) ret = nand_read(nand, off, &size, (u_char *)addr); @@ -397,44 +406,44 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } if (status) { - ulong block_start = 0; +// ulong block_start = 0; ulong off; - int last_status = -1; +// int last_status = -1; struct nand_chip *nand_chip = nand->priv; /* check the WP bit */ nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1); printf("device is %swrite protected\n", (nand_chip->read_byte(nand) & 0x80 ? - "NOT " : "" ) ); - - for (off = 0; off < nand->size; off += nand->oobblock) { - int s = nand_get_lock_status(nand, off); - - /* print message only if status has changed - * or at end of chip - */ - if (off == nand->size - nand->oobblock - || (s != last_status && off != 0)) { - - printf("%08lx - %08lx: %8lu pages %s%s%s\n", - block_start, - off-1, - (off-block_start)/nand->oobblock, - ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), - ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), - ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); - } - - last_status = s; - } - } else { - if (!nand_lock(nand, tight)) { - puts("NAND flash successfully locked\n"); - } else { - puts("Error locking NAND flash\n"); - return 1; + "NOT " : "" ) ); + + for (off = 0; off < nand->size; off += nand->writesize) { +// int s = nand_get_lock_status(nand, off); +// +// /* print message only if status has changed +// * or at end of chip +// */ +// if (off == nand->size - nand->writesize +// || (s != last_status && off != 0)) { +// +// printf("%08lx - %08lx: %8d pages %s%s%s\n", +// block_start, +// off-1, +// (off-block_start)/nand->writesize, +// ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), +// ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), +// ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); +// } +// +// last_status = s; } + } else { +// if (!nand_lock(nand, tight)) { +// puts("NAND flash successfully locked\n"); +// } else { +// puts("Error locking NAND flash\n"); +// return 1; +// } } return 0; } @@ -443,13 +452,13 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) return 1; - if (!nand_unlock(nand, off, size)) { - puts("NAND flash successfully unlocked\n"); - } else { - puts("Error unlocking NAND flash, " - "write and erase will probably fail\n"); - return 1; - } +// if (!nand_unlock(nand, off, size)) { +// puts("NAND flash successfully unlocked\n"); +// } else { +// puts("Error unlocking NAND flash, " +// "write and erase will probably fail\n"); +// return 1; +// } return 0; } @@ -459,24 +468,26 @@ usage: } U_BOOT_CMD(nand, 5, 1, do_nand, - "nand - NAND sub-system\n", - "info - show available NAND devices\n" - "nand device [dev] - show or set current device\n" - "nand read[.jffs2] - addr off|partition size\n" - "nand write[.jffs2] - addr off|partition size - read/write `size' bytes starting\n" - " at offset `off' to/from memory address `addr'\n" - "nand erase [clean] [off size] - erase `size' bytes from\n" - " offset `off' (entire device if not specified)\n" - "nand bad - show bad blocks\n" - "nand dump[.oob] off - dump page\n" - "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n" - "nand markbad off - mark bad block at offset (UNSAFE)\n" - "nand biterr off - make a bit error at offset (UNSAFE)\n" - "nand lock [tight] [status] - bring nand to lock state or display locked pages\n" - "nand unlock [offset] [size] - unlock section\n"); + "nand - NAND sub-system\n", + "info - show available NAND devices\n" + "nand device [dev] - show or set current device\n" + "nand read[.jffs2] - addr off|partition size\n" + "nand write[.jffs2] - addr off|partition size\n" + " read/write 'size' bytes starting at offset 'off'\n" + " to/from memory address 'addr'\n" + "nand erase [clean] [off size] - erase 'size' bytes from\n" + " offset 'off' (entire device if not specified)\n" + "nand bad - show bad blocks\n" + "nand dump[.oob] off - dump page\n" + "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n" + "nand markbad off - mark bad block at offset (UNSAFE)\n" + "nand biterr off - make a bit error at offset (UNSAFE)\n" + "nand lock [tight] [status]\n" + " bring nand to lock state or display locked pages\n" + "nand unlock [offset] [size] - unlock section\n"); static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, - ulong offset, ulong addr, char *cmd) + ulong offset, ulong addr, char *cmd) { int r; char *ep, *s; @@ -494,19 +505,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset); - cnt = nand->oobblock; - if (jffs2) { - nand_read_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.buffer = (u_char*) addr; - opts.length = cnt; - opts.offset = offset; - opts.quiet = 1; - r = nand_read_opts(nand, &opts); - } else { - r = nand_read(nand, offset, &cnt, (u_char *) addr); - } - + cnt = nand->writesize; + r = nand_read(nand, offset, &cnt, (u_char *) addr); if (r) { puts("** Read error\n"); show_boot_progress (-56); @@ -537,18 +537,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, return 1; } - if (jffs2) { - nand_read_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.buffer = (u_char*) addr; - opts.length = cnt; - opts.offset = offset; - opts.quiet = 1; - r = nand_read_opts(nand, &opts); - } else { - r = nand_read(nand, offset, &cnt, (u_char *) addr); - } - + r = nand_read(nand, offset, &cnt, (u_char *) addr); if (r) { puts("** Read error\n"); show_boot_progress (-58); @@ -614,7 +603,7 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else addr = CFG_LOAD_ADDR; return nand_load_image(cmdtp, &nand_info[dev->id->num], - part->offset, addr, argv[0]); + part->offset, addr, argv[0]); } } #endif @@ -704,8 +693,8 @@ void archflashwp(void *archdata, int wp); #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) -#undef NAND_DEBUG -#undef PSYCHO_DEBUG +#undef NAND_DEBUG +#undef PSYCHO_DEBUG /* ****************** WARNING ********************* * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will @@ -720,16 +709,16 @@ void archflashwp(void *archdata, int wp); * and attempting to program or erase bad blocks can affect * the data in _other_ (good) blocks. */ -#define ALLOW_ERASE_BAD_DEBUG 0 +#define ALLOW_ERASE_BAD_DEBUG 0 #define CONFIG_MTD_NAND_ECC /* enable ECC */ #define CONFIG_MTD_NAND_ECC_JFFS2 /* bits for nand_legacy_rw() `cmd'; or together as needed */ -#define NANDRW_READ 0x01 -#define NANDRW_WRITE 0x00 -#define NANDRW_JFFS2 0x02 -#define NANDRW_JFFS2_SKIP 0x04 +#define NANDRW_READ 0x01 +#define NANDRW_WRITE 0x00 +#define NANDRW_JFFS2 0x02 +#define NANDRW_JFFS2_SKIP 0x04 /* * Imports from nand_legacy.c @@ -737,15 +726,15 @@ void archflashwp(void *archdata, int wp); extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; extern int curr_device; extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, - size_t len, int clean); + size_t len, int clean); extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start, - size_t len, size_t *retlen, u_char *buf); + size_t len, size_t *retlen, u_char *buf); extern void nand_print(struct nand_chip *nand); extern void nand_print_bad(struct nand_chip *nand); extern int nand_read_oob(struct nand_chip *nand, size_t ofs, - size_t len, size_t *retlen, u_char *buf); + size_t len, size_t *retlen, u_char *buf); extern int nand_write_oob(struct nand_chip *nand, size_t ofs, - size_t len, size_t *retlen, const u_char *buf); + size_t len, size_t *retlen, const u_char *buf); int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) @@ -878,7 +867,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else if (cmdtail && !strcmp (cmdtail, ".i")) { cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ if (cmd & NANDRW_READ) - cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ + cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ } #endif /* CFG_NAND_SKIP_BAD_DOT_I */ else if (cmdtail) { @@ -928,7 +917,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } U_BOOT_CMD( - nand, 5, 1, do_nand, + nand, 5, 1, do_nand, "nand - legacy NAND sub-system\n", "info - show available NAND devices\n" "nand device [dev] - show or set current device\n" @@ -992,7 +981,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) dev = simple_strtoul(boot_device, &ep, 16); if ((dev >= CFG_MAX_NAND_DEVICE) || - (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) { + (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) { printf ("\n** Device %d not available\n", dev); show_boot_progress (-55); return 1; @@ -1000,11 +989,11 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) show_boot_progress (55); printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n", - dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR, - offset); + dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR, + offset); if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset, - SECTORSIZE, NULL, (u_char *)addr)) { + SECTORSIZE, NULL, (u_char *)addr)) { printf ("** Read error on %d\n", dev); show_boot_progress (-56); return 1; @@ -1035,8 +1024,8 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) show_boot_progress (57); if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, - offset + SECTORSIZE, cnt, NULL, - (u_char *)(addr+SECTORSIZE))) { + offset + SECTORSIZE, cnt, NULL, + (u_char *)(addr+SECTORSIZE))) { printf ("** Read error on %d\n", dev); show_boot_progress (-58); return 1; @@ -1077,7 +1066,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } U_BOOT_CMD( - nboot, 4, 1, do_nandboot, + nboot, 4, 1, do_nandboot, "nboot - boot from NAND device\n", "loadAddr dev\n" ); -- cgit v1.2.3-70-g09d2 From 4cbb651b29cb64d378a06729970e1e153bb605b1 Mon Sep 17 00:00:00 2001 From: William Juul Date: Thu, 8 Nov 2007 10:39:53 +0100 Subject: Remove white space at end. Signed-off-by: William Juul Signed-off-by: Scott Wood --- board/bf537-stamp/nand.c | 4 ++-- board/dave/PPChameleonEVB/nand.c | 2 +- board/nc650/nand.c | 2 +- board/netstar/nand.c | 2 +- board/prodrive/alpr/nand.c | 2 +- board/sc3/sc3nand.c | 4 ++-- common/cmd_nand.c | 2 +- cpu/arm926ejs/davinci/nand.c | 2 +- drivers/mtd/nand/nand_base.c | 4 ++-- drivers/mtd/nand/nand_util.c | 10 +++++----- include/linux/mtd/nand.h | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c index bdf1d6ee4..d90bdd071 100644 --- a/board/bf537-stamp/nand.c +++ b/board/bf537-stamp/nand.c @@ -50,7 +50,7 @@ static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) if( ctrl & NAND_ALE ) IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE; else - IO_ADDR_W = CFG_NAND_BASE; + IO_ADDR_W = CFG_NAND_BASE; this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; } this->IO_ADDR_R = this->IO_ADDR_W; @@ -59,7 +59,7 @@ static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) SSYNC(); if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); + writeb(cmd, this->IO_ADDR_W); } int bfin_device_ready(struct mtd_info *mtd) diff --git a/board/dave/PPChameleonEVB/nand.c b/board/dave/PPChameleonEVB/nand.c index 4bc4257c8..ea6400c04 100644 --- a/board/dave/PPChameleonEVB/nand.c +++ b/board/dave/PPChameleonEVB/nand.c @@ -52,7 +52,7 @@ static void ppchameleonevb_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int } if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); + writeb(cmd, this->IO_ADDR_W); } diff --git a/board/nc650/nand.c b/board/nc650/nand.c index faec6053f..f59f5e2c9 100644 --- a/board/nc650/nand.c +++ b/board/nc650/nand.c @@ -48,7 +48,7 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) } if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); + writeb(cmd, this->IO_ADDR_W); } #elif defined(CONFIG_IDS852_REV2) /* diff --git a/board/netstar/nand.c b/board/netstar/nand.c index 302d78efe..961c92112 100644 --- a/board/netstar/nand.c +++ b/board/netstar/nand.c @@ -46,7 +46,7 @@ static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c IO_ADDR_W |= MASK_ALE; } this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; - + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } diff --git a/board/prodrive/alpr/nand.c b/board/prodrive/alpr/nand.c index 3224d3dd6..e1495feea 100644 --- a/board/prodrive/alpr/nand.c +++ b/board/prodrive/alpr/nand.c @@ -57,7 +57,7 @@ static struct alpr_ndfc_regs *alpr_ndfc = NULL; * There are 2 NAND devices on the board, a Hynix HY27US08561A (1 GByte). */ static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) -{ +{ struct nand_chip *this = mtd->priv; if (ctrl & NAND_CTRL_CHANGE) { diff --git a/board/sc3/sc3nand.c b/board/sc3/sc3nand.c index 2f2e74589..8ead7c850 100644 --- a/board/sc3/sc3nand.c +++ b/board/sc3/sc3nand.c @@ -46,7 +46,7 @@ static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) if ( ctrl & NAND_CLE ) set_bit (SC3_NAND_CLE, sc3_control_base); else - clear_bit (SC3_NAND_CLE, sc3_control_base); + clear_bit (SC3_NAND_CLE, sc3_control_base); if ( ctrl & NAND_ALE ) set_bit (SC3_NAND_ALE, sc3_control_base); else @@ -54,7 +54,7 @@ static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) if ( ctrl & NAND_NCE ) set_bit (SC3_NAND_CE, sc3_control_base); else - clear_bit (SC3_NAND_CE, sc3_control_base); + clear_bit (SC3_NAND_CE, sc3_control_base); } if (cmd != NAND_CMD_NONE) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 3e76d8207..f825234a7 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -328,7 +328,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) printf("\nNAND %s: ", read ? "read" : "write"); if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) return 1; - + s = strchr(cmd, '.'); if (s != NULL && (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c index 43041b635..196fc146b 100644 --- a/cpu/arm926ejs/davinci/nand.c +++ b/cpu/arm926ejs/davinci/nand.c @@ -376,7 +376,7 @@ int board_nand_init(struct nand_chip *nand) // nand->autooob = &davinci_nand_oobinfo; nand->ecc.calculate = nand_davinci_calculate_ecc; nand->ecc.correct = nand_davinci_correct_data; - nand->ecc.hwctl = nand_davinci_enable_hwecc; + nand->ecc.hwctl = nand_davinci_enable_hwecc; #else nand->ecc.mode = NAND_ECC_SOFT; #endif diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index aeb179731..e21a18baa 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2080,7 +2080,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, /* Calculate pages in each block */ pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); - + /* Select the NAND device */ chip->select_chip(mtd, chipnr); @@ -2748,7 +2748,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) BUG(); } #endif - + ret = nand_scan_ident(mtd, maxchips); if (!ret) ret = nand_scan_tail(mtd); diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 78e70cc80..9fe486698 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -128,7 +128,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) for (; erase.addr < opts->offset + erase_length; erase.addr += meminfo->erasesize) { - + WATCHDOG_RESET (); if (!opts->scrub && bbtest) { @@ -163,7 +163,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) chip->ops.datbuf = NULL; chip->ops.oobbuf = buf; chip->ops.ooboffs = chip->badblockpos & ~0x01; - + result = meminfo->write_oob(meminfo, erase.addr + meminfo->oobsize, &chip->ops); @@ -254,7 +254,7 @@ static struct nand_ecclayout autoplace_ecclayout = { * @chip: nand chip structure * @oob: oob data buffer * @ops: oob ops structure - * + * * Copied from nand_base.c */ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, @@ -314,13 +314,13 @@ int nand_write_opts(nand_info_t *mtd, loff_t to, mtd_oob_ops_t *ops) uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; int ret, subpage; - + ops->retlen = 0; if (!writelen) return 0; printk("nand_write_opts: to: 0x%08x, ops->len: 0x%08x\n", to, ops->len); - + /* reject writes, which are not page aligned */ if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { printk(KERN_NOTICE "nand_write: " diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index db8bd7ba2..2984f5f28 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -421,7 +421,7 @@ struct nand_chip { struct nand_ecc_ctrl ecc; struct nand_buffers *buffers; - + struct nand_hw_control hwcontrol; struct mtd_oob_ops ops; -- cgit v1.2.3-70-g09d2 From 5e1dae5c3db7f4026f31b6a2a81ecd9e9dee475f Mon Sep 17 00:00:00 2001 From: William Juul Date: Fri, 9 Nov 2007 13:32:30 +0100 Subject: Fixing coding style issues - Fixing leading white spaces - Fixing indentation where 4 spaces are used instead of tab - Removing C++ comments (//), wherever I introduced them Signed-off-by: William Juul Signed-off-by: Scott Wood --- board/bf537-stamp/nand.c | 2 +- board/dave/PPChameleonEVB/nand.c | 4 +- board/delta/nand.c | 2 +- board/esd/common/esd405ep_nand.c | 6 +-- board/nc650/nand.c | 8 +-- board/netstar/nand.c | 2 +- board/prodrive/alpr/nand.c | 2 +- board/prodrive/pdnb3/nand.c | 2 +- board/sc3/sc3nand.c | 6 +-- board/tqc/tqm8272/tqm8272.c | 2 +- board/zylonite/nand.c | 2 +- common/cmd_nand.c | 110 +++++++++++++++++++++------------------ cpu/arm926ejs/davinci/nand.c | 18 +++---- cpu/ppc4xx/ndfc.c | 14 ++--- drivers/mtd/nand/diskonchip.c | 10 ++-- drivers/mtd/nand/nand_base.c | 2 +- include/linux/mtd/compat.h | 6 +-- include/linux/mtd/nand.h | 7 +-- 18 files changed, 106 insertions(+), 99 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c index d90bdd071..9800083c9 100644 --- a/board/bf537-stamp/nand.c +++ b/board/bf537-stamp/nand.c @@ -40,7 +40,7 @@ static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { register struct nand_chip *this = mtd->priv; - u32 IO_ADDR_W = (u32) this->IO_ADDR_W; + u32 IO_ADDR_W = (u32) this->IO_ADDR_W; if (ctrl & NAND_CTRL_CHANGE) { if( ctrl & NAND_CLE ) diff --git a/board/dave/PPChameleonEVB/nand.c b/board/dave/PPChameleonEVB/nand.c index ea6400c04..3ccbf650d 100644 --- a/board/dave/PPChameleonEVB/nand.c +++ b/board/dave/PPChameleonEVB/nand.c @@ -36,7 +36,7 @@ static void ppchameleonevb_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int struct nand_chip *this = mtd->priv; ulong base = (ulong) this->IO_ADDR_W; - if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) MACRO_NAND_CTL_SETCLE((unsigned long)base); else @@ -51,7 +51,7 @@ static void ppchameleonevb_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int MACRO_NAND_DISABLE_CE((unsigned long)base); } - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } diff --git a/board/delta/nand.c b/board/delta/nand.c index 51520f5fb..b007b090d 100644 --- a/board/delta/nand.c +++ b/board/delta/nand.c @@ -549,7 +549,7 @@ int board_nand_init(struct nand_chip *nand) nand->write_buf = dfc_write_buf; nand->cmdfunc = dfc_cmdfunc; -// nand->autooob = &delta_oob; +/* nand->autooob = &delta_oob; */ nand->badblock_pattern = &delta_bbt_descr; return 0; } diff --git a/board/esd/common/esd405ep_nand.c b/board/esd/common/esd405ep_nand.c index 4bf81ab4a..40d1efb08 100644 --- a/board/esd/common/esd405ep_nand.c +++ b/board/esd/common/esd405ep_nand.c @@ -32,8 +32,8 @@ */ static void esd405ep_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; - if (ctrl & NAND_CTRL_CHANGE) { + struct nand_chip *this = mtd->priv; + if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CLE); else @@ -48,7 +48,7 @@ static void esd405ep_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CE); } - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } diff --git a/board/nc650/nand.c b/board/nc650/nand.c index f59f5e2c9..7dca97fdf 100644 --- a/board/nc650/nand.c +++ b/board/nc650/nand.c @@ -36,7 +36,7 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *this = mtd->priv; - if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) this->IO_ADDR_W += 2; else @@ -47,7 +47,7 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) this->IO_ADDR_W -= 1; } - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } #elif defined(CONFIG_IDS852_REV2) @@ -58,7 +58,7 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *this = mtd->priv; - if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) writeb(0, (volatile __u8 *) this->IO_ADDR_W + 0xa); else @@ -73,7 +73,7 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0xc); } - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } #else diff --git a/board/netstar/nand.c b/board/netstar/nand.c index 961c92112..e3ab66f2f 100644 --- a/board/netstar/nand.c +++ b/board/netstar/nand.c @@ -47,7 +47,7 @@ static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c } this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } diff --git a/board/prodrive/alpr/nand.c b/board/prodrive/alpr/nand.c index e1495feea..99f5737b8 100644 --- a/board/prodrive/alpr/nand.c +++ b/board/prodrive/alpr/nand.c @@ -58,7 +58,7 @@ static struct alpr_ndfc_regs *alpr_ndfc = NULL; */ static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd->priv; if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) diff --git a/board/prodrive/pdnb3/nand.c b/board/prodrive/pdnb3/nand.c index 281ae70af..1ce3c8c61 100644 --- a/board/prodrive/pdnb3/nand.c +++ b/board/prodrive/pdnb3/nand.c @@ -54,7 +54,7 @@ static struct pdnb3_ndfc_regs *pdnb3_ndfc; */ static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd->priv; if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) diff --git a/board/sc3/sc3nand.c b/board/sc3/sc3nand.c index 8ead7c850..45eff28c0 100644 --- a/board/sc3/sc3nand.c +++ b/board/sc3/sc3nand.c @@ -41,8 +41,8 @@ static void *sc3_control_base = (void *)0xEF600700; static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; - if (ctrl & NAND_CTRL_CHANGE) { + struct nand_chip *this = mtd->priv; + if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) set_bit (SC3_NAND_CLE, sc3_control_base); else @@ -57,7 +57,7 @@ static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) clear_bit (SC3_NAND_CE, sc3_control_base); } - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } diff --git a/board/tqc/tqm8272/tqm8272.c b/board/tqc/tqm8272/tqm8272.c index 5148f3de5..a0ec254ce 100644 --- a/board/tqc/tqm8272/tqm8272.c +++ b/board/tqc/tqm8272/tqm8272.c @@ -1070,7 +1070,7 @@ static u8 hwctl = 0; static void upmnand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd->priv; if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) diff --git a/board/zylonite/nand.c b/board/zylonite/nand.c index 47d5d4b0d..09bcbb233 100644 --- a/board/zylonite/nand.c +++ b/board/zylonite/nand.c @@ -553,7 +553,7 @@ int board_nand_init(struct nand_chip *nand) nand->write_buf = dfc_write_buf; nand->cmdfunc = dfc_cmdfunc; -// nand->autooob = &delta_oob; +/* nand->autooob = &delta_oob; */ nand->badblock_pattern = &delta_bbt_descr; return 0; } diff --git a/common/cmd_nand.c b/common/cmd_nand.c index f825234a7..339d82b5d 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -35,7 +35,7 @@ int mtdparts_init(void); int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); int find_dev_and_part(const char *id, struct mtd_device **dev, - u8 *part_num, struct part_info **part); + u8 *part_num, struct part_info **part); #endif static int nand_dump_oob(nand_info_t *nand, ulong off) @@ -340,7 +340,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) opts.length = size; opts.offset = off; opts.quiet = quiet; -// ret = nand_read_opts(nand, &opts); +/* ret = nand_read_opts(nand, &opts); */ } else { /* write */ mtd_oob_ops_t opts; @@ -406,44 +406,48 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } if (status) { -// ulong block_start = 0; ulong off; -// int last_status = -1; - +/* ulong block_start = 0; + int last_status = -1; +*/ struct nand_chip *nand_chip = nand->priv; /* check the WP bit */ nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1); printf("device is %swrite protected\n", (nand_chip->read_byte(nand) & 0x80 ? - "NOT " : "" ) ); + "NOT " : "")); for (off = 0; off < nand->size; off += nand->writesize) { -// int s = nand_get_lock_status(nand, off); -// -// /* print message only if status has changed -// * or at end of chip -// */ -// if (off == nand->size - nand->writesize -// || (s != last_status && off != 0)) { -// -// printf("%08lx - %08lx: %8d pages %s%s%s\n", -// block_start, -// off-1, -// (off-block_start)/nand->writesize, -// ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), -// ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), -// ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); -// } -// -// last_status = s; +#if 0 /* must be fixed */ + int s = nand_get_lock_status(nand, off); + + /* print message only if status has changed + * or at end of chip + */ + if (off == nand->size - nand->writesize + || (s != last_status && off != 0)) { + + printf("%08lx - %08lx: %8d pages %s%s%s\n", + block_start, + off-1, + (off-block_start)/nand->writesize, + ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), + ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); + } + + last_status = s; +#endif } } else { -// if (!nand_lock(nand, tight)) { -// puts("NAND flash successfully locked\n"); -// } else { -// puts("Error locking NAND flash\n"); -// return 1; -// } +#if 0 /* must be fixed */ + if (!nand_lock(nand, tight)) { + puts("NAND flash successfully locked\n"); + } else { + puts("Error locking NAND flash\n"); + return 1; + } +#endif } return 0; } @@ -452,13 +456,15 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) return 1; -// if (!nand_unlock(nand, off, size)) { -// puts("NAND flash successfully unlocked\n"); -// } else { -// puts("Error unlocking NAND flash, " -// "write and erase will probably fail\n"); -// return 1; -// } +#if 0 /* must be fixed */ + if (!nand_unlock(nand, off, size)) { + puts("NAND flash successfully unlocked\n"); + } else { + puts("Error unlocking NAND flash, " + "write and erase will probably fail\n"); + return 1; + } +#endif return 0; } @@ -691,7 +697,7 @@ U_BOOT_CMD(nboot, 4, 1, do_nandboot, void archflashwp(void *archdata, int wp); #endif -#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) #undef NAND_DEBUG #undef PSYCHO_DEBUG @@ -715,9 +721,9 @@ void archflashwp(void *archdata, int wp); #define CONFIG_MTD_NAND_ECC_JFFS2 /* bits for nand_legacy_rw() `cmd'; or together as needed */ -#define NANDRW_READ 0x01 -#define NANDRW_WRITE 0x00 -#define NANDRW_JFFS2 0x02 +#define NANDRW_READ 0x01 +#define NANDRW_WRITE 0x00 +#define NANDRW_JFFS2 0x02 #define NANDRW_JFFS2_SKIP 0x04 /* @@ -726,15 +732,15 @@ void archflashwp(void *archdata, int wp); extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; extern int curr_device; extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, - size_t len, int clean); + size_t len, int clean); extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start, - size_t len, size_t *retlen, u_char *buf); + size_t len, size_t *retlen, u_char *buf); extern void nand_print(struct nand_chip *nand); extern void nand_print_bad(struct nand_chip *nand); extern int nand_read_oob(struct nand_chip *nand, size_t ofs, - size_t len, size_t *retlen, u_char *buf); + size_t len, size_t *retlen, u_char *buf); extern int nand_write_oob(struct nand_chip *nand, size_t ofs, - size_t len, size_t *retlen, const u_char *buf); + size_t len, size_t *retlen, const u_char *buf); int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) @@ -828,11 +834,11 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (strncmp (argv[1], "read", 4) == 0 || strncmp (argv[1], "write", 5) == 0) { - ulong addr = simple_strtoul (argv[2], NULL, 16); - off_t off = simple_strtoul (argv[3], NULL, 16); - size_t size = simple_strtoul (argv[4], NULL, 16); - int cmd = (strncmp (argv[1], "read", 4) == 0) ? - NANDRW_READ : NANDRW_WRITE; + ulong addr = simple_strtoul (argv[2], NULL, 16); + off_t off = simple_strtoul (argv[3], NULL, 16); + size_t size = simple_strtoul (argv[4], NULL, 16); + int cmd = (strncmp (argv[1], "read", 4) == 0) ? + NANDRW_READ : NANDRW_WRITE; size_t total; int ret; char *cmdtail = strchr (argv[1], '.'); @@ -923,9 +929,9 @@ U_BOOT_CMD( "nand device [dev] - show or set current device\n" "nand read[.jffs2[s]] addr off size\n" "nand write[.jffs2] addr off size - read/write `size' bytes starting\n" - " at offset `off' to/from memory address `addr'\n" + " at offset `off' to/from memory address `addr'\n" "nand erase [clean] [off size] - erase `size' bytes from\n" - " offset `off' (entire device if not specified)\n" + " offset `off' (entire device if not specified)\n" "nand bad - show bad blocks\n" "nand read.oob addr off size - read out-of-band data\n" "nand write.oob addr off size - read out-of-band data\n" diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c index 196fc146b..6afd4d252 100644 --- a/cpu/arm926ejs/davinci/nand.c +++ b/cpu/arm926ejs/davinci/nand.c @@ -68,7 +68,7 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; } - if (cmd != NAND_CMD_NONE) + if (cmd != NAND_CMD_NONE) writeb(cmd, this->IO_ADDR_W); } @@ -363,22 +363,22 @@ int board_nand_init(struct nand_chip *nand) #endif #ifdef CFG_NAND_HW_ECC #ifdef CFG_NAND_LARGEPAGE - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.size = 2048; - nand->ecc.bytes = 12; + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.size = 2048; + nand->ecc.bytes = 12; #elif defined(CFG_NAND_SMALLPAGE) - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.size = 512; - nand->ecc.bytes = 3; + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.size = 512; + nand->ecc.bytes = 3; #else #error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" #endif -// nand->autooob = &davinci_nand_oobinfo; +/* nand->autooob = &davinci_nand_oobinfo; */ nand->ecc.calculate = nand_davinci_calculate_ecc; nand->ecc.correct = nand_davinci_correct_data; nand->ecc.hwctl = nand_davinci_enable_hwecc; #else - nand->ecc.mode = NAND_ECC_SOFT; + nand->ecc.mode = NAND_ECC_SOFT; #endif /* Set address of hardware control function */ diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c index 7818eb9c5..865482931 100644 --- a/cpu/ppc4xx/ndfc.c +++ b/cpu/ppc4xx/ndfc.c @@ -48,7 +48,7 @@ static u8 hwctl = 0; static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd->priv; if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_CLE ) @@ -183,12 +183,12 @@ int board_nand_init(struct nand_chip *nand) nand->read_buf = ndfc_read_buf; nand->dev_ready = ndfc_dev_ready; - nand->ecc.correct = nand_correct_data; - nand->ecc.hwctl = ndfc_enable_hwecc; - nand->ecc.calculate = ndfc_calculate_ecc; - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.size = 256; - nand->ecc.bytes = 3; + nand->ecc.correct = nand_correct_data; + nand->ecc.hwctl = ndfc_enable_hwecc; + nand->ecc.calculate = ndfc_calculate_ecc; + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.size = 256; + nand->ecc.bytes = 3; #ifndef CONFIG_NAND_SPL nand->write_buf = ndfc_write_buf; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index a03f982be..ce197f5ad 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -500,11 +500,11 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; - //ReadDOC(docptr, CDSNSlowIO); + /*ReadDOC(docptr, CDSNSlowIO); */ /* 11.4.5 -- delay twice to allow extended length cycle */ DoC_Delay(doc, 2); ReadDOC(docptr, ReadPipeInit); - //return ReadDOC(docptr, Mil_CDSN_IO); + /*return ReadDOC(docptr, Mil_CDSN_IO); */ return ReadDOC(docptr, LastDataRead); } @@ -1051,7 +1051,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, return ret; } -//u_char mydatabuf[528]; +/*u_char mydatabuf[528]; */ /* The strange out-of-order .oobfree list below is a (possibly unneeded) * attempt to retain compatibility. It used to read: @@ -1623,11 +1623,11 @@ static int __init doc_probe(unsigned long physadr) if (ChipID == DOC_ChipID_DocMilPlus16) { WriteDOC(~newval, virtadr, Mplus_AliasResolution); oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); - WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it + WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */ } else { WriteDOC(~newval, virtadr, AliasResolution); oldval = ReadDOC(doc->virtadr, AliasResolution); - WriteDOC(newval, virtadr, AliasResolution); // restore it + WriteDOC(newval, virtadr, AliasResolution); /* restore it */ } newval = ~newval; if (oldval == newval) { diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e21a18baa..4b1c564f7 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2557,7 +2557,7 @@ int nand_scan_tail(struct mtd_info *mtd) default: printk(KERN_WARNING "No oob scheme defined for " "oobsize %d\n", mtd->oobsize); -// BUG(); +/* BUG(); */ } } diff --git a/include/linux/mtd/compat.h b/include/linux/mtd/compat.h index 86a6e43ca..9036b74f8 100644 --- a/include/linux/mtd/compat.h +++ b/include/linux/mtd/compat.h @@ -18,10 +18,10 @@ #define KERN_DEBUG #define kmalloc(size, flags) malloc(size) -#define kzalloc(size, flags) calloc(size, 1) +#define kzalloc(size, flags) calloc(size, 1) #define vmalloc(size) malloc(size) -#define kfree(ptr) free(ptr) -#define vfree(ptr) free(ptr) +#define kfree(ptr) free(ptr) +#define vfree(ptr) free(ptr) #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2984f5f28..f9b7d36a7 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -236,11 +236,12 @@ struct nand_chip; * used instead of the per chip wait queue when a hw controller is available */ struct nand_hw_control { +/* XXX U-BOOT XXX */ #if 0 - spinlock_t lock; - wait_queue_head_t wq; + spinlock_t lock; + wait_queue_head_t wq; #endif - struct nand_chip *active; + struct nand_chip *active; }; /** -- cgit v1.2.3-70-g09d2 From 3043c045d5a9897faba7d5c7218c2f4d06cd0038 Mon Sep 17 00:00:00 2001 From: William Juul Date: Wed, 14 Nov 2007 14:28:11 +0100 Subject: Whitespace cleanup and marking broken code. Changes requested by maintainer Stefan Roese after posting patch to U-boot mailing list. Signed-off-by: William Juul Signed-off-by: Scott Wood --- common/cmd_doc.c | 5 +++ common/cmd_nand.c | 96 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 44 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 9d5b3001c..a55ca41d9 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -14,6 +14,11 @@ #include #include +/* + * ! BROKEN ! + * + * TODO: must be implemented and tested by someone with HW + */ #if 0 #ifdef CFG_DOC_SUPPORT_2000 #define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 339d82b5d..8b359e017 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -54,13 +54,9 @@ static int nand_dump(nand_info_t *nand, ulong off) return 1; } off &= ~(nand->writesize - 1); -#if 0 - i = nand_read_raw(nand, buf, off, nand->writesize, nand->oobsize); -#else size_t dummy; loff_t addr = (loff_t) off; i = nand->read(nand, addr, nand->writesize, &dummy, buf); -#endif if (i < 0) { printf("Error (%d) reading page %08lx\n", i, off); free(buf); @@ -199,7 +195,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (argc < 3) { if ((nand_curr_device < 0) || - (nand_curr_device >= CFG_MAX_NAND_DEVICE)) + (nand_curr_device >= CFG_MAX_NAND_DEVICE)) puts("\nno devices available\n"); else printf("\nDevice %d: %s\n", nand_curr_device, @@ -226,11 +222,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 && - strncmp(cmd, "dump", 4) != 0 && - strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && - strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && - strcmp(cmd, "biterr") != 0 && - strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) + strncmp(cmd, "dump", 4) != 0 && + strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && + strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && + strcmp(cmd, "biterr") != 0 && + strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) goto usage; /* the following commands operate on the current device */ @@ -257,7 +253,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) { nand_erase_options_t opts; /* "clean" at index 2 means request to write cleanmarker */ - int clean = !strcmp("clean", argv[2]); + int clean = argc > 2 && !strcmp("clean", argv[2]); int o = clean ? 3 : 2; int scrub = !strcmp(cmd, "scrub"); @@ -267,7 +263,6 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; memset(&opts, 0, sizeof(opts)); - opts.offset = off; opts.length = size; opts.jffs2 = clean; @@ -331,7 +326,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) s = strchr(cmd, '.'); if (s != NULL && - (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { + (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { if (read) { /* read */ nand_read_options_t opts; @@ -340,7 +335,13 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) opts.length = size; opts.offset = off; opts.quiet = quiet; -/* ret = nand_read_opts(nand, &opts); */ +/* + * ! BROKEN ! + * + * TODO: Function must be implemented + * + * ret = nand_read_opts(nand, &opts); + */ } else { /* write */ mtd_oob_ops_t opts; @@ -404,12 +405,17 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (!strcmp("status", argv[2])) status = 1; } - +/* + * ! BROKEN ! + * + * TODO: must be implemented and tested by someone with HW + */ +#if 0 if (status) { + ulong block_start = 0; ulong off; -/* ulong block_start = 0; int last_status = -1; -*/ + struct nand_chip *nand_chip = nand->priv; /* check the WP bit */ nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1); @@ -418,37 +424,34 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) "NOT " : "")); for (off = 0; off < nand->size; off += nand->writesize) { -#if 0 /* must be fixed */ int s = nand_get_lock_status(nand, off); /* print message only if status has changed * or at end of chip */ if (off == nand->size - nand->writesize - || (s != last_status && off != 0)) { + || (s != last_status && off != 0)) { printf("%08lx - %08lx: %8d pages %s%s%s\n", - block_start, - off-1, - (off-block_start)/nand->writesize, - ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), - ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), - ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); + block_start, + off-1, + (off-block_start)/nand->writesize, + ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), + ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); } last_status = s; -#endif } } else { -#if 0 /* must be fixed */ if (!nand_lock(nand, tight)) { puts("NAND flash successfully locked\n"); } else { puts("Error locking NAND flash\n"); return 1; } -#endif } +#endif return 0; } @@ -456,12 +459,17 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) return 1; -#if 0 /* must be fixed */ +/* + * ! BROKEN ! + * + * TODO: must be implemented and tested by someone with HW + */ +#if 0 if (!nand_unlock(nand, off, size)) { puts("NAND flash successfully unlocked\n"); } else { puts("Error unlocking NAND flash, " - "write and erase will probably fail\n"); + "write and erase will probably fail\n"); return 1; } #endif @@ -542,6 +550,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, puts ("** Unknown image type\n"); return 1; } + show_boot_progress (57); r = nand_read(nand, offset, &cnt, (u_char *) addr); if (r) { @@ -697,10 +706,10 @@ U_BOOT_CMD(nboot, 4, 1, do_nandboot, void archflashwp(void *archdata, int wp); #endif -#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) -#undef NAND_DEBUG -#undef PSYCHO_DEBUG +#undef NAND_DEBUG +#undef PSYCHO_DEBUG /* ****************** WARNING ********************* * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will @@ -715,7 +724,7 @@ void archflashwp(void *archdata, int wp); * and attempting to program or erase bad blocks can affect * the data in _other_ (good) blocks. */ -#define ALLOW_ERASE_BAD_DEBUG 0 +#define ALLOW_ERASE_BAD_DEBUG 0 #define CONFIG_MTD_NAND_ECC /* enable ECC */ #define CONFIG_MTD_NAND_ECC_JFFS2 @@ -732,13 +741,13 @@ void archflashwp(void *archdata, int wp); extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; extern int curr_device; extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, - size_t len, int clean); + size_t len, int clean); extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start, size_t len, size_t *retlen, u_char *buf); extern void nand_print(struct nand_chip *nand); extern void nand_print_bad(struct nand_chip *nand); extern int nand_read_oob(struct nand_chip *nand, size_t ofs, - size_t len, size_t *retlen, u_char *buf); + size_t len, size_t *retlen, u_char *buf); extern int nand_write_oob(struct nand_chip *nand, size_t ofs, size_t len, size_t *retlen, const u_char *buf); @@ -873,7 +882,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else if (cmdtail && !strcmp (cmdtail, ".i")) { cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ if (cmd & NANDRW_READ) - cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ + cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ } #endif /* CFG_NAND_SKIP_BAD_DOT_I */ else if (cmdtail) { @@ -887,8 +896,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) ret = nand_legacy_rw (nand_dev_desc + curr_device, cmd, off, size, - &total, - (u_char *) addr); + &total, (u_char *) addr); printf (" %d bytes %s: %s\n", total, (cmd & NANDRW_READ) ? "read" : "written", @@ -923,15 +931,15 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } U_BOOT_CMD( - nand, 5, 1, do_nand, + nand, 5, 1, do_nand, "nand - legacy NAND sub-system\n", "info - show available NAND devices\n" "nand device [dev] - show or set current device\n" "nand read[.jffs2[s]] addr off size\n" "nand write[.jffs2] addr off size - read/write `size' bytes starting\n" - " at offset `off' to/from memory address `addr'\n" + " at offset `off' to/from memory address `addr'\n" "nand erase [clean] [off size] - erase `size' bytes from\n" - " offset `off' (entire device if not specified)\n" + " offset `off' (entire device if not specified)\n" "nand bad - show bad blocks\n" "nand read.oob addr off size - read out-of-band data\n" "nand write.oob addr off size - read out-of-band data\n" @@ -987,7 +995,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) dev = simple_strtoul(boot_device, &ep, 16); if ((dev >= CFG_MAX_NAND_DEVICE) || - (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) { + (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) { printf ("\n** Device %d not available\n", dev); show_boot_progress (-55); return 1; @@ -1072,7 +1080,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } U_BOOT_CMD( - nboot, 4, 1, do_nandboot, + nboot, 4, 1, do_nandboot, "nboot - boot from NAND device\n", "loadAddr dev\n" ); -- cgit v1.2.3-70-g09d2 From 9ad754fef5053144daed3b007adaf1c9bec654c9 Mon Sep 17 00:00:00 2001 From: William Juul Date: Fri, 14 Dec 2007 16:33:45 +0100 Subject: make nand dump and nand dump.oob work Signed-off-by: William Juul Signed-off-by: Scott Wood --- common/cmd_nand.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 8b359e017..af1b1cadd 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -38,37 +38,44 @@ int find_dev_and_part(const char *id, struct mtd_device **dev, u8 *part_num, struct part_info **part); #endif -static int nand_dump_oob(nand_info_t *nand, ulong off) -{ - return 0; -} - -static int nand_dump(nand_info_t *nand, ulong off) +static int nand_dump(nand_info_t *nand, ulong off, int only_oob) { int i; - u_char *buf, *p; + u_char *datbuf, *oobbuf, *p; - buf = malloc(nand->writesize + nand->oobsize); - if (!buf) { + datbuf = malloc(nand->writesize + nand->oobsize); + oobbuf = malloc(nand->oobsize); + if (!datbuf || !oobbuf) { puts("No memory for page buffer\n"); return 1; } off &= ~(nand->writesize - 1); size_t dummy; loff_t addr = (loff_t) off; - i = nand->read(nand, addr, nand->writesize, &dummy, buf); + struct mtd_oob_ops ops; + memset(&ops, 0, sizeof(ops)); + ops.datbuf = datbuf; + ops.oobbuf = oobbuf; /* must exist, but oob data will be appended to ops.datbuf */ + ops.len = nand->writesize; + ops.ooblen = nand->oobsize; + ops.mode = MTD_OOB_RAW; + i = nand->read_oob(nand, addr, &ops); if (i < 0) { printf("Error (%d) reading page %08lx\n", i, off); - free(buf); + free(datbuf); + free(oobbuf); return 1; } printf("Page %08lx dump:\n", off); - i = nand->writesize >> 4; p = buf; + i = nand->writesize >> 4; + p = datbuf; + while (i--) { - printf("\t%02x %02x %02x %02x %02x %02x %02x %02x" - " %02x %02x %02x %02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], - p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + if (!only_oob) + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); p += 16; } puts("OOB:\n"); @@ -78,7 +85,8 @@ static int nand_dump(nand_info_t *nand, ulong off) p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); p += 8; } - free(buf); + free(datbuf); + free(oobbuf); return 0; } @@ -302,9 +310,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) off = (int)simple_strtoul(argv[2], NULL, 16); if (s != NULL && strcmp(s, ".oob") == 0) - ret = nand_dump_oob(nand, off); + ret = nand_dump(nand, off, 1); else - ret = nand_dump(nand, off); + ret = nand_dump(nand, off, 0); return ret == 0 ? 1 : 0; -- cgit v1.2.3-70-g09d2 From deac913effd8d80535c9ff4687b6fcdff540c554 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Sat, 5 Jan 2008 16:50:32 +0100 Subject: NAND: Fix compilation warning and small coding style issue Signed-off-by: Stefan Roese --- common/cmd_nand.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index af1b1cadd..710ba8f94 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -50,7 +50,6 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob) return 1; } off &= ~(nand->writesize - 1); - size_t dummy; loff_t addr = (loff_t) off; struct mtd_oob_ops ops; memset(&ops, 0, sizeof(ops)); @@ -415,7 +414,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } /* * ! BROKEN ! - * + * * TODO: must be implemented and tested by someone with HW */ #if 0 @@ -469,7 +468,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * ! BROKEN ! - * + * * TODO: must be implemented and tested by someone with HW */ #if 0 -- cgit v1.2.3-70-g09d2 From 984e03cdf1431bb593aeaa1b74c445d616f955d3 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 12 Jun 2008 13:13:23 -0500 Subject: NAND: Always skip blocks on read/write/boot. Use of the non-skipping versions was almost always (if not always) an error, and no valid use case has been identified. Signed-off-by: Scott Wood --- common/cmd_nand.c | 27 ++++++++++++++------------- doc/README.nand | 37 ++++++++++++------------------------- 2 files changed, 26 insertions(+), 38 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 710ba8f94..2c421e948 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -332,8 +332,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; s = strchr(cmd, '.'); - if (s != NULL && - (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { + if (!s || !strcmp(s, ".jffs2") || + !strcmp(s, ".e") || !strcmp(s, ".i")) { if (read) { /* read */ nand_read_options_t opts; @@ -372,10 +372,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else ret = nand->write_oob(nand, off, &ops); } else { - if (read) - ret = nand_read(nand, off, &size, (u_char *)addr); - else - ret = nand_write(nand, off, &size, (u_char *)addr); + printf("Unknown nand command suffix '%s'.\n", s); + return 1; } printf(" %d bytes %s: %s\n", size, @@ -492,10 +490,10 @@ U_BOOT_CMD(nand, 5, 1, do_nand, "nand - NAND sub-system\n", "info - show available NAND devices\n" "nand device [dev] - show or set current device\n" - "nand read[.jffs2] - addr off|partition size\n" - "nand write[.jffs2] - addr off|partition size\n" + "nand read - addr off|partition size\n" + "nand write - addr off|partition size\n" " read/write 'size' bytes starting at offset 'off'\n" - " to/from memory address 'addr'\n" + " to/from memory address 'addr', skipping bad blocks.\n" "nand erase [clean] [off size] - erase 'size' bytes from\n" " offset 'off' (entire device if not specified)\n" "nand bad - show bad blocks\n" @@ -514,15 +512,17 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, char *ep, *s; size_t cnt; image_header_t *hdr; - int jffs2 = 0; #if defined(CONFIG_FIT) const void *fit_hdr = NULL; #endif s = strchr(cmd, '.'); if (s != NULL && - (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) - jffs2 = 1; + (strcmp(s, ".jffs2") && !strcmp(s, ".e") && !strcmp(s, ".i"))) { + printf("Unknown nand load suffix '%s'\n", s); + show_boot_progress(-53); + return 1; + } printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset); @@ -559,6 +559,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, } show_boot_progress (57); + /* FIXME: skip bad blocks */ r = nand_read(nand, offset, &cnt, (u_char *) addr); if (r) { puts("** Read error\n"); @@ -680,7 +681,7 @@ usage: U_BOOT_CMD(nboot, 4, 1, do_nandboot, "nboot - boot from NAND device\n", - "[.jffs2] [partition] | [[[loadAddr] dev] offset]\n"); + "[partition] | [[[loadAddr] dev] offset]\n"); #endif diff --git a/doc/README.nand b/doc/README.nand index 647a6b8e6..0ad5e18dd 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -57,14 +57,9 @@ Commands: Print information about all of the NAND devices found. nand read addr ofs|partition size - Read `size' bytes from `ofs' in NAND flash to `addr'. If a page - cannot be read because it is marked bad or an uncorrectable data - error is found the command stops with an error. - - nand read.jffs2 addr ofs|partition size - Like `read', but the data for blocks that are marked bad is read as - 0xff. This gives a readable JFFS2 image that can be processed by - the JFFS2 commands such as ls and fsload. + Read `size' bytes from `ofs' in NAND flash to `addr'. Blocks that + are marked bad are skipped. If a page cannot be read because an + uncorrectable data error is found, the command stops with an error. nand read.oob addr ofs|partition size Read `size' bytes from the out-of-band data area corresponding to @@ -73,17 +68,15 @@ Commands: for bad blocks or ECC errors. nand write addr ofs|partition size - Write `size' bytes from `addr' to `ofs' in NAND flash. If a page - cannot be written because it is marked bad or the write fails the - command stops with an error. - - nand write.jffs2 addr ofs|partition size - Like `write', but blocks that are marked bad are skipped and the - data is written to the next block instead. This allows writing - a JFFS2 image, as long as the image is short enough to fit even - after skipping the bad blocks. Compact images, such as those - produced by mkfs.jffs2 should work well, but loading an image copied - from another flash is going to be trouble if there are any bad blocks. + Write `size' bytes from `addr' to `ofs' in NAND flash. Blocks that + are marked bad are skipped. If a page cannot be read because an + uncorrectable data error is found, the command stops with an error. + + As JFFS2 skips blocks similarly, this allows writing a JFFS2 image, + as long as the image is short enough to fit even after skipping the + bad blocks. Compact images, such as those produced by mkfs.jffs2 + should work well, but loading an image copied from another flash is + going to be trouble if there are any bad blocks. nand write.oob addr ofs|partition size Write `size' bytes from `addr' to the out-of-band data area @@ -215,12 +208,6 @@ JFFS2 related commands: using both the new code which is able to skip bad blocks "nand erase clean" additionally writes JFFS2-cleanmarkers in the oob. - "nand write.jffs2" - like "nand write" but skip found bad eraseblocks - - "nand read.jffs2" - like "nand read" but skip found bad eraseblocks - Miscellaneous and testing commands: "markbad [offset]" create an artificial bad block (for testing bad block handling) -- cgit v1.2.3-70-g09d2 From dfbf617ff055e4216f78d358b0867c548916d14b Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 12 Jun 2008 13:20:16 -0500 Subject: NAND read/write fix Implement block-skipping read/write, based on a patch from Morten Ebbell Hestens . Signed-off-by: Morten Ebbell Hestnes Signed-off-by: Scott Wood --- common/cmd_nand.c | 36 +- drivers/mtd/nand/nand_util.c | 762 ++++++++++--------------------------------- include/nand.h | 7 +- 3 files changed, 194 insertions(+), 611 deletions(-) (limited to 'common/cmd_nand.c') diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 2c421e948..520c15217 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -74,7 +74,8 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob) printf("\t%02x %02x %02x %02x %02x %02x %02x %02x" " %02x %02x %02x %02x %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], - p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + p[8], p[9], p[10], p[11], p[12], p[13], p[14], + p[15]); p += 16; } puts("OOB:\n"); @@ -317,7 +318,6 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } - /* read write */ if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { int read; @@ -334,31 +334,12 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) s = strchr(cmd, '.'); if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { - if (read) { - /* read */ - nand_read_options_t opts; - memset(&opts, 0, sizeof(opts)); - opts.buffer = (u_char*) addr; - opts.length = size; - opts.offset = off; - opts.quiet = quiet; -/* - * ! BROKEN ! - * - * TODO: Function must be implemented - * - * ret = nand_read_opts(nand, &opts); - */ - } else { - /* write */ - mtd_oob_ops_t opts; - memset(&opts, 0, sizeof(opts)); - opts.datbuf = (u_char*) addr; - opts.len = size; - opts.ooblen = 64; - opts.mode = MTD_OOB_AUTO; - ret = nand_write_opts(nand, off, &opts); - } + if (read) + ret = nand_read_skip_bad(nand, off, &size, + (u_char *)addr); + else + ret = nand_write_skip_bad(nand, off, &size, + (u_char *)addr); } else if (s != NULL && !strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { @@ -396,6 +377,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } return 1; } + if (strcmp(cmd, "biterr") == 0) { /* todo */ return 1; diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 9fe486698..02fe914db 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -248,586 +248,6 @@ static struct nand_ecclayout autoplace_ecclayout = { }; #endif - -/** - * nand_fill_oob - [Internal] Transfer client buffer to oob - * @chip: nand chip structure - * @oob: oob data buffer - * @ops: oob ops structure - * - * Copied from nand_base.c - */ -static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, - struct mtd_oob_ops *ops) -{ - size_t len = ops->ooblen; - - switch(ops->mode) { - - case MTD_OOB_PLACE: - case MTD_OOB_RAW: - memcpy(chip->oob_poi + ops->ooboffs, oob, len); - return oob + len; - - case MTD_OOB_AUTO: { - struct nand_oobfree *free = chip->ecc.layout->oobfree; - uint32_t boffs = 0, woffs = ops->ooboffs; - size_t bytes = 0; - - for(; free->length && len; free++, len -= bytes) { - /* Write request not from offset 0 ? */ - if (unlikely(woffs)) { - if (woffs >= free->length) { - woffs -= free->length; - continue; - } - boffs = free->offset + woffs; - bytes = min_t(size_t, len, - (free->length - woffs)); - woffs = 0; - } else { - bytes = min_t(size_t, len, free->length); - boffs = free->offset; - } - memcpy(chip->oob_poi + boffs, oob, bytes); - oob += bytes; - } - return oob; - } - default: - BUG(); - } - return NULL; -} - -#define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 - - -/* copied from nand_base.c: nand_do_write_ops() - * Only very small changes - */ -int nand_write_opts(nand_info_t *mtd, loff_t to, mtd_oob_ops_t *ops) -{ - int chipnr, realpage, page, blockmask, column; - struct nand_chip *chip = mtd->priv; - uint32_t writelen = ops->len; - uint8_t *oob = ops->oobbuf; - uint8_t *buf = ops->datbuf; - int ret, subpage; - - ops->retlen = 0; - if (!writelen) - return 0; - - printk("nand_write_opts: to: 0x%08x, ops->len: 0x%08x\n", to, ops->len); - - /* reject writes, which are not page aligned */ - if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { - printk(KERN_NOTICE "nand_write: " - "Attempt to write not page aligned data\n"); - return -EINVAL; - } - - column = to & (mtd->writesize - 1); - subpage = column || (writelen & (mtd->writesize - 1)); - - if (subpage && oob) { - printk(KERN_NOTICE "nand_write: " - "Attempt to write oob to subpage\n"); - return -EINVAL; - } - - chipnr = (int)(to >> chip->chip_shift); - chip->select_chip(mtd, chipnr); - - /* XXX U-BOOT XXX */ -#if 0 - /* Check, if it is write protected */ - if (nand_check_wp(mtd)) - return -EIO; -#endif - - realpage = (int)(to >> chip->page_shift); - page = realpage & chip->pagemask; - blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; - - /* Invalidate the page cache, when we write to the cached page */ - if (to <= (chip->pagebuf << chip->page_shift) && - (chip->pagebuf << chip->page_shift) < (to + ops->len)) - chip->pagebuf = -1; - - /* If we're not given explicit OOB data, let it be 0xFF */ - if (likely(!oob)) { - printf("!oob, writing %d bytes with 0xff to chip->oob_poi (0x%08x)\n", mtd->oobsize, chip->oob_poi); - memset(chip->oob_poi, 0xff, mtd->oobsize); - } - - while(1) { - int bytes = mtd->writesize; - int cached = writelen > bytes && page != blockmask; - uint8_t *wbuf = buf; - - /* Partial page write ? */ - if (unlikely(column || writelen < (mtd->writesize - 1))) { - cached = 0; - bytes = min_t(int, bytes - column, (int) writelen); - chip->pagebuf = -1; - memset(chip->buffers->databuf, 0xff, mtd->writesize); - memcpy(&chip->buffers->databuf[column], buf, bytes); - wbuf = chip->buffers->databuf; - } - - if (unlikely(oob)) - oob = nand_fill_oob(chip, oob, ops); - - ret = chip->write_page(mtd, chip, wbuf, page, cached, - (ops->mode == MTD_OOB_RAW)); - if (ret) - break; - - writelen -= bytes; - if (!writelen) - break; - - column = 0; - buf += bytes; - realpage++; - - page = realpage & chip->pagemask; - /* Check, if we cross a chip boundary */ - if (!page) { - chipnr++; - chip->select_chip(mtd, -1); - chip->select_chip(mtd, chipnr); - } - } - - ops->retlen = ops->len - writelen; - if (unlikely(oob)) - ops->oobretlen = ops->ooblen; - return ret; -} - -/* XXX U-BOOT XXX */ -#if 0 -/** - * nand_write_opts: - write image to NAND flash with support for various options - * - * @param meminfo NAND device to erase - * @param opts write options (@see nand_write_options) - * @return 0 in case of success - * - * This code is ported from nandwrite.c from Linux mtd utils by - * Steven J. Hill and Thomas Gleixner. - */ -int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts) -{ - int imglen = 0; - int pagelen; - int baderaseblock; - int blockstart = -1; - loff_t offs; - int readlen; - int ecclayoutchanged = 0; - int percent_complete = -1; - struct nand_ecclayout old_ecclayout; - ulong mtdoffset = opts->offset; - ulong erasesize_blockalign; - u_char *buffer = opts->buffer; - size_t written; - int result; - - if (opts->pad && opts->writeoob) { - printf("Can't pad when oob data is present.\n"); - return -1; - } - - /* set erasesize to specified number of blocks - to match - * jffs2 (virtual) block size */ - if (opts->blockalign == 0) { - erasesize_blockalign = meminfo->erasesize; - } else { - erasesize_blockalign = meminfo->erasesize * opts->blockalign; - } - - /* make sure device page sizes are valid */ - if (!(meminfo->oobsize == 16 && meminfo->writesize == 512) - && !(meminfo->oobsize == 8 && meminfo->writesize == 256) - && !(meminfo->oobsize == 64 && meminfo->writesize == 2048)) { - printf("Unknown flash (not normal NAND)\n"); - return -1; - } - - /* read the current oob info */ - memcpy(&old_ecclayout, &meminfo->ecclayout, sizeof(old_ecclayout)); - - /* write without ecc? */ - if (opts->noecc) { - memcpy(&meminfo->ecclayout, &none_ecclayout, - sizeof(meminfo->ecclayout)); - ecclayoutchanged = 1; - } - - /* autoplace ECC? */ - if (opts->autoplace && (old_ecclayout.useecc != MTD_NANDECC_AUTOPLACE)) { - - memcpy(&meminfo->ecclayout, &autoplace_ecclayout, - sizeof(meminfo->ecclayout)); - ecclayoutchanged = 1; - } - - /* force OOB layout for jffs2 or yaffs? */ - if (opts->forcejffs2 || opts->forceyaffs) { - struct nand_ecclayout *oobsel = - opts->forcejffs2 ? &jffs2_ecclayout : &yaffs_ecclayout; - - if (meminfo->oobsize == 8) { - if (opts->forceyaffs) { - printf("YAFSS cannot operate on " - "256 Byte page size\n"); - goto restoreoob; - } - /* Adjust number of ecc bytes */ - jffs2_ecclayout.eccbytes = 3; - } - - memcpy(&meminfo->ecclayout, oobsel, sizeof(meminfo->ecclayout)); - } - - /* get image length */ - imglen = opts->length; - pagelen = meminfo->writesize - + ((opts->writeoob != 0) ? meminfo->oobsize : 0); - - /* check, if file is pagealigned */ - if ((!opts->pad) && ((imglen % pagelen) != 0)) { - printf("Input block length is not page aligned\n"); - goto restoreoob; - } - - /* check, if length fits into device */ - if (((imglen / pagelen) * meminfo->writesize) - > (meminfo->size - opts->offset)) { - printf("Image %d bytes, NAND page %d bytes, " - "OOB area %u bytes, device size %u bytes\n", - imglen, pagelen, meminfo->writesize, meminfo->size); - printf("Input block does not fit into device\n"); - goto restoreoob; - } - - if (!opts->quiet) - printf("\n"); - - /* get data from input and write to the device */ - while (imglen && (mtdoffset < meminfo->size)) { - - WATCHDOG_RESET (); - - /* - * new eraseblock, check for bad block(s). Stay in the - * loop to be sure if the offset changes because of - * a bad block, that the next block that will be - * written to is also checked. Thus avoiding errors if - * the block(s) after the skipped block(s) is also bad - * (number of blocks depending on the blockalign - */ - while (blockstart != (mtdoffset & (~erasesize_blockalign+1))) { - blockstart = mtdoffset & (~erasesize_blockalign+1); - offs = blockstart; - baderaseblock = 0; - - /* check all the blocks in an erase block for - * bad blocks */ - do { - int ret = meminfo->block_isbad(meminfo, offs); - - if (ret < 0) { - printf("Bad block check failed\n"); - goto restoreoob; - } - if (ret == 1) { - baderaseblock = 1; - if (!opts->quiet) - printf("\rBad block at 0x%lx " - "in erase block from " - "0x%x will be skipped\n", - (long) offs, - blockstart); - } - - if (baderaseblock) { - mtdoffset = blockstart - + erasesize_blockalign; - } - offs += erasesize_blockalign - / opts->blockalign; - } while (offs < blockstart + erasesize_blockalign); - } - - readlen = meminfo->writesize; - if (opts->pad && (imglen < readlen)) { - readlen = imglen; - memset(data_buf + readlen, 0xff, - meminfo->writesize - readlen); - } - - /* read page data from input memory buffer */ - memcpy(data_buf, buffer, readlen); - buffer += readlen; - - if (opts->writeoob) { - /* read OOB data from input memory block, exit - * on failure */ - memcpy(oob_buf, buffer, meminfo->oobsize); - buffer += meminfo->oobsize; - - /* write OOB data first, as ecc will be placed - * in there*/ - result = meminfo->write_oob(meminfo, - mtdoffset, - meminfo->oobsize, - &written, - (unsigned char *) - &oob_buf); - - if (result != 0) { - printf("\nMTD writeoob failure: %d\n", - result); - goto restoreoob; - } - imglen -= meminfo->oobsize; - } - - /* write out the page data */ - result = meminfo->write(meminfo, - mtdoffset, - meminfo->writesize, - &written, - (unsigned char *) &data_buf); - - if (result != 0) { - printf("writing NAND page at offset 0x%lx failed\n", - mtdoffset); - goto restoreoob; - } - imglen -= readlen; - - if (!opts->quiet) { - unsigned long long n = (unsigned long long) - (opts->length-imglen) * 100; - int percent; - - do_div(n, opts->length); - percent = (int)n; - - /* output progress message only at whole percent - * steps to reduce the number of messages printed - * on (slow) serial consoles - */ - if (percent != percent_complete) { - printf("\rWriting data at 0x%lx " - "-- %3d%% complete.", - mtdoffset, percent); - percent_complete = percent; - } - } - - mtdoffset += meminfo->writesize; - } - - if (!opts->quiet) - printf("\n"); - -restoreoob: - if (ecclayoutchanged) { - memcpy(&meminfo->ecclayout, &old_ecclayout, - sizeof(meminfo->ecclayout)); - } - - if (imglen > 0) { - printf("Data did not fit into device, due to bad blocks\n"); - return -1; - } - - /* return happy */ - return 0; -} - -/** - * nand_read_opts: - read image from NAND flash with support for various options - * - * @param meminfo NAND device to erase - * @param opts read options (@see struct nand_read_options) - * @return 0 in case of success - * - */ -int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts) -{ - int imglen = opts->length; - int pagelen; - int baderaseblock; - int blockstart = -1; - int percent_complete = -1; - loff_t offs; - size_t readlen; - ulong mtdoffset = opts->offset; - u_char *buffer = opts->buffer; - int result; - - /* make sure device page sizes are valid */ - if (!(meminfo->oobsize == 16 && meminfo->writesize == 512) - && !(meminfo->oobsize == 8 && meminfo->writesize == 256) - && !(meminfo->oobsize == 64 && meminfo->writesize == 2048)) { - printf("Unknown flash (not normal NAND)\n"); - return -1; - } - - pagelen = meminfo->writesize - + ((opts->readoob != 0) ? meminfo->oobsize : 0); - - /* check, if length is not larger than device */ - if (((imglen / pagelen) * meminfo->writesize) - > (meminfo->size - opts->offset)) { - printf("Image %d bytes, NAND page %d bytes, " - "OOB area %u bytes, device size %u bytes\n", - imglen, pagelen, meminfo->writesize, meminfo->size); - printf("Input block is larger than device\n"); - return -1; - } - - if (!opts->quiet) - printf("\n"); - - /* get data from input and write to the device */ - while (imglen && (mtdoffset < meminfo->size)) { - - WATCHDOG_RESET (); - - /* - * new eraseblock, check for bad block(s). Stay in the - * loop to be sure if the offset changes because of - * a bad block, that the next block that will be - * written to is also checked. Thus avoiding errors if - * the block(s) after the skipped block(s) is also bad - * (number of blocks depending on the blockalign - */ - while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) { - blockstart = mtdoffset & (~meminfo->erasesize+1); - offs = blockstart; - baderaseblock = 0; - - /* check all the blocks in an erase block for - * bad blocks */ - do { - int ret = meminfo->block_isbad(meminfo, offs); - - if (ret < 0) { - printf("Bad block check failed\n"); - return -1; - } - if (ret == 1) { - baderaseblock = 1; - if (!opts->quiet) - printf("\rBad block at 0x%lx " - "in erase block from " - "0x%x will be skipped\n", - (long) offs, - blockstart); - } - - if (baderaseblock) { - mtdoffset = blockstart - + meminfo->erasesize; - } - offs += meminfo->erasesize; - - } while (offs < blockstart + meminfo->erasesize); - } - - - /* read page data to memory buffer */ - result = meminfo->read(meminfo, - mtdoffset, - meminfo->writesize, - &readlen, - (unsigned char *) &data_buf); - - if (result != 0) { - printf("reading NAND page at offset 0x%lx failed\n", - mtdoffset); - return -1; - } - - if (imglen < readlen) { - readlen = imglen; - } - - memcpy(buffer, data_buf, readlen); - buffer += readlen; - imglen -= readlen; - - if (opts->readoob) { - result = meminfo->read_oob(meminfo, - mtdoffset, - meminfo->oobsize, - &readlen, - (unsigned char *) - &oob_buf); - - if (result != 0) { - printf("\nMTD readoob failure: %d\n", - result); - return -1; - } - - - if (imglen < readlen) { - readlen = imglen; - } - - memcpy(buffer, oob_buf, readlen); - - buffer += readlen; - imglen -= readlen; - } - - if (!opts->quiet) { - unsigned long long n = (unsigned long long) - (opts->length-imglen) * 100; - int percent; - - do_div(n, opts->length); - percent = (int)n; - - /* output progress message only at whole percent - * steps to reduce the number of messages printed - * on (slow) serial consoles - */ - if (percent != percent_complete) { - if (!opts->quiet) - printf("\rReading data from 0x%lx " - "-- %3d%% complete.", - mtdoffset, percent); - percent_complete = percent; - } - } - - mtdoffset += meminfo->writesize; - } - - if (!opts->quiet) - printf("\n"); - - if (imglen > 0) { - printf("Could not read entire image due to bad blocks\n"); - return -1; - } - - /* return happy */ - return 0; -} -#endif - /* XXX U-BOOT XXX */ #if 0 /****************************************************************************** @@ -1007,4 +427,184 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) } #endif -#endif +/** + * get_len_incl_bad + * + * Check if length including bad blocks fits into device. + * + * @param nand NAND device + * @param offset offset in flash + * @param length image length + * @return image length including bad blocks + */ +static size_t get_len_incl_bad (nand_info_t *nand, size_t offset, + const size_t length) +{ + size_t len_incl_bad = 0; + size_t len_excl_bad = 0; + size_t block_len; + + while (len_excl_bad < length) { + block_len = nand->erasesize - (offset & (nand->erasesize - 1)); + + if (!nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) + len_excl_bad += block_len; + + len_incl_bad += block_len; + offset += block_len; + + if ((offset + len_incl_bad) >= nand->size) + break; + } + + return len_incl_bad; +} + +/** + * nand_write_skip_bad: + * + * Write image to NAND flash. + * Blocks that are marked bad are skipped and the is written to the next + * block instead as long as the image is short enough to fit even after + * skipping the bad blocks. + * + * @param nand NAND device + * @param offset offset in flash + * @param length buffer length + * @param buf buffer to read from + * @return 0 in case of success + */ +int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, + u_char *buffer) +{ + int rval; + size_t left_to_write = *length; + size_t len_incl_bad; + u_char *p_buffer = buffer; + + /* Reject writes, which are not page aligned */ + if ((offset & (nand->writesize - 1)) != 0 || + (*length & (nand->writesize - 1)) != 0) { + printf ("Attempt to write non page aligned data\n"); + return -EINVAL; + } + + len_incl_bad = get_len_incl_bad (nand, offset, *length); + + if ((offset + len_incl_bad) >= nand->size) { + printf ("Attempt to write outside the flash area\n"); + return -EINVAL; + } + + if (len_incl_bad == *length) { + rval = nand_write (nand, offset, length, buffer); + if (rval != 0) { + printf ("NAND write to offset %x failed %d\n", + offset, rval); + return rval; + } + } + + while (left_to_write > 0) { + size_t block_offset = offset & (nand->erasesize - 1); + size_t write_size; + + if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { + printf ("Skip bad block 0x%08x\n", + offset & ~(nand->erasesize - 1)); + offset += nand->erasesize - block_offset; + continue; + } + + if (left_to_write < (nand->erasesize - block_offset)) + write_size = left_to_write; + else + write_size = nand->erasesize - block_offset; + + rval = nand_write (nand, offset, &write_size, p_buffer); + if (rval != 0) { + printf ("NAND write to offset %x failed %d\n", + offset, rval); + *length -= left_to_write; + return rval; + } + + left_to_write -= write_size; + offset += write_size; + p_buffer += write_size; + } + + return 0; +} + +/** + * nand_read_skip_bad: + * + * Read image from NAND flash. + * Blocks that are marked bad are skipped and the next block is readen + * instead as long as the image is short enough to fit even after skipping the + * bad blocks. + * + * @param nand NAND device + * @param offset offset in flash + * @param length buffer length, on return holds remaining bytes to read + * @param buffer buffer to write to + * @return 0 in case of success + */ +int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, + u_char *buffer) +{ + int rval; + size_t left_to_read = *length; + size_t len_incl_bad; + u_char *p_buffer = buffer; + + len_incl_bad = get_len_incl_bad (nand, offset, *length); + + if ((offset + len_incl_bad) >= nand->size) { + printf ("Attempt to read outside the flash area\n"); + return -EINVAL; + } + + if (len_incl_bad == *length) { + rval = nand_read (nand, offset, length, buffer); + if (rval != 0) { + printf ("NAND read from offset %x failed %d\n", + offset, rval); + return rval; + } + } + + while (left_to_read > 0) { + size_t block_offset = offset & (nand->erasesize - 1); + size_t read_length; + + if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { + printf ("Skipping bad block 0x%08x\n", + offset & ~(nand->erasesize - 1)); + offset += nand->erasesize - block_offset; + continue; + } + + if (left_to_read < (nand->erasesize - block_offset)) + read_length = left_to_read; + else + read_length = nand->erasesize - block_offset; + + rval = nand_read (nand, offset, &read_length, p_buffer); + if (rval != 0) { + printf ("NAND read from offset %x failed %d\n", + offset, rval); + *length -= left_to_read; + return rval; + } + + left_to_read -= read_length; + offset += read_length; + p_buffer += read_length; + } + + return 0; +} + +#endif /* defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) */ diff --git a/include/nand.h b/include/nand.h index 83d597dc7..d5af4324c 100644 --- a/include/nand.h +++ b/include/nand.h @@ -108,9 +108,10 @@ struct nand_erase_options { typedef struct nand_erase_options nand_erase_options_t; -int nand_write_opts(nand_info_t *mtd, loff_t to, mtd_oob_ops_t *ops); - -int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts); +int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, + u_char *buffer); +int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, + u_char *buffer); int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); #define NAND_LOCK_STATUS_TIGHT 0x01 -- cgit v1.2.3-70-g09d2