*   0    1     2       3    4
         *   nand erase [clean] [off size]
         */
-       if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
+       if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
                nand_erase_options_t opts;
                /* "clean" at index 2 means request to write cleanmarker */
                int clean = argc > 2 && !strcmp("clean", argv[2]);
                int o = clean ? 3 : 2;
-               int scrub = !strcmp(cmd, "scrub");
+               int scrub = !strncmp(cmd, "scrub", 5);
+               int part = 0;
+               int chip = 0;
+               int spread = 0;
+               int args = 2;
+
+               if (cmd[5] != 0) {
+                       if (!strcmp(&cmd[5], ".spread")) {
+                               spread = 1;
+                       } else if (!strcmp(&cmd[5], ".part")) {
+                               part = 1;
+                               args = 1;
+                       } else if (!strcmp(&cmd[5], ".chip")) {
+                               chip = 1;
+                               args = 0;
+                       } else {
+                               goto usage;
+                       }
+               }
+
+               /*
+                * Don't allow missing arguments to cause full chip/partition
+                * erases -- easy to do accidentally, e.g. with a misspelled
+                * variable name.
+                */
+               if (argc != o + args)
+                       goto usage;
 
-               printf("\nNAND %s: ", scrub ? "scrub" : "erase");
+               printf("\nNAND %s: ", cmd);
                /* skip first two or three arguments, look for offset and size */
                if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
                        return 1;
                opts.length = size;
                opts.jffs2  = clean;
                opts.quiet  = quiet;
+               opts.spread = spread;
 
                if (scrub) {
                        puts("Warning: "
        "nand write - addr off|partition size\n"
        "    read/write 'size' bytes starting at offset 'off'\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 erase[.spread] [clean] [off [size]] - erase 'size' bytes "
+       "from offset 'off'\n"
+       "    With '.spread', erase enough for given file size, otherwise,\n"
+       "    'size' includes skipped bad blocks.\n"
+       "nand erase.part [clean] partition - erase entire mtd partition'\n"
+       "nand erase.chip [clean] - erase entire chip'\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 scrub off size | scrub.part partition | scrub.chip\n"
+       "    really clean NAND erasing bad blocks (UNSAFE)\n"
        "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
        "nand biterr off - make a bit error at offset (UNSAFE)"
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 
 {
        struct jffs2_unknown_node cleanmarker;
        erase_info_t erase;
-       ulong erase_length;
+       unsigned long erase_length, erased_length; /* in blocks */
        int bbtest = 1;
        int result;
        int percent_complete = -1;
        struct mtd_oob_ops oob_opts;
        struct nand_chip *chip = meminfo->priv;
 
+       if ((opts->offset & (meminfo->writesize - 1)) != 0) {
+               printf("Attempt to erase non page aligned data\n");
+               return -1;
+       }
+
        memset(&erase, 0, sizeof(erase));
        memset(&oob_opts, 0, sizeof(oob_opts));
 
        erase.mtd = meminfo;
        erase.len  = meminfo->erasesize;
        erase.addr = opts->offset;
-       erase_length = opts->length;
+       erase_length = lldiv(opts->length + meminfo->erasesize - 1,
+                            meminfo->erasesize);
 
        cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
        cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
                priv_nand->bbt = NULL;
        }
 
-       if (erase_length < meminfo->erasesize) {
-               printf("Warning: Erase size 0x%08lx smaller than one "  \
-                      "erase block 0x%08x\n",erase_length, meminfo->erasesize);
-               printf("         Erasing 0x%08x instead\n", meminfo->erasesize);
-               erase_length = meminfo->erasesize;
-       }
-
-       for (;
-            erase.addr < opts->offset + erase_length;
+       for (erased_length = 0;
+            erased_length < erase_length;
             erase.addr += meminfo->erasesize) {
 
                WATCHDOG_RESET ();
                                               "0x%08llx                 "
                                               "                         \n",
                                               erase.addr);
+
+                               if (!opts->spread)
+                                       erased_length++;
+
                                continue;
 
                        } else if (ret < 0) {
                        }
                }
 
+               erased_length++;
+
                result = meminfo->erase(meminfo, &erase);
                if (result != 0) {
                        printf("\n%s: MTD Erase failure: %d\n",
                }
 
                if (!opts->quiet) {
-                       unsigned long long n =(unsigned long long)
-                               (erase.addr + meminfo->erasesize - opts->offset)
-                               * 100;
+                       unsigned long long n = erased_length * 100ULL;
                        int percent;
 
                        do_div(n, erase_length);
 
 typedef struct nand_read_options nand_read_options_t;
 
 struct nand_erase_options {
-       ulong length;           /* number of bytes to erase */
-       ulong offset;           /* first address in NAND to erase */
+       loff_t length;          /* number of bytes to erase */
+       loff_t offset;          /* first address in NAND to erase */
        int quiet;              /* don't display progress messages */
        int jffs2;              /* if true: format for jffs2 usage
                                 * (write appropriate cleanmarker blocks) */
        int scrub;              /* if true, really clean NAND by erasing
                                 * bad blocks (UNSAFE) */
+
+       /* Don't include skipped bad blocks in size to be erased */
+       int spread;
 };
 
 typedef struct nand_erase_options nand_erase_options_t;