| #include <command.h> |
| #include <malloc.h> |
| #include <common.h> |
| #include <linux/mtd/mtd.h> |
| #include <mtd/pxa3xx_bbm.h> |
| |
| extern int nand_curr_device; |
| extern struct mtd_info nand_info[]; |
| extern struct mtd_info onenand_mtd; |
| extern int pxa3xx_update_bbt(struct mtd_info *mtd, loff_t offs); |
| |
| int not_updating = 1; |
| int do_bbt (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| struct pxa3xx_bbm *bbm; |
| struct mtd_info *mtd; |
| int is_nand = 0, ret, block, bbm_type = BBM_NONE; |
| struct erase_info instr = { |
| .callback = NULL, |
| }; |
| ulong addr; |
| |
| switch (argc) { |
| case 0: |
| case 1: |
| case 2: |
| default: |
| printf ("Usage:\n%s\n", cmdtp->usage); |
| return 1; |
| case 3: |
| case 4: |
| case 5: |
| if (strcmp(argv[2], "nand") == 0) { |
| |
| is_nand = 1; |
| mtd = &nand_info[nand_curr_device]; |
| if (nand_curr_device < 0) { |
| printf ("There is no nand device on current CS\n"); |
| return 0; |
| } |
| } |
| #ifdef CONFIG_CMD_ONENAND |
| if (strcmp(argv[2], "onenand") == 0) { |
| is_nand = 2; |
| if (onenand_mtd.size == 0) { |
| printf ("There is no onenand device\n"); |
| return 0; |
| } |
| |
| mtd = &onenand_mtd; |
| } |
| #endif |
| if (!is_nand) |
| { |
| printf ("Usage:\n%s\n", cmdtp->usage); |
| return 1; |
| } |
| |
| bbm = mtd->bbm; |
| if (strcmp (argv[1], "show") == 0) { |
| if (bbm) |
| bbm->is_init = 0; |
| |
| pxa3xx_scan_bbt(mtd); |
| } |
| else if (strcmp(argv[1], "init") == 0) { |
| if (argc == 3) |
| bbm_type = BBM_LEGACY; |
| else { |
| if (strcmp(argv[3], "new") == 0) |
| bbm_type = BBM_NEW; |
| else if (strcmp(argv[3], "old") == 0) |
| bbm_type = BBM_LEGACY; |
| |
| if (bbm_type == BBM_NONE) { |
| printf("You should either select" |
| " new or old\n"); |
| return 1; |
| } |
| } |
| |
| pxa3xx_bbm_recovery(mtd, bbm_type, NULL, 0, 1); |
| } |
| else if (strcmp(argv[1], "recreate") == 0) { |
| puts("Warning: " |
| "recreate option will erase all content on your flash!\n" |
| " " |
| "are sure of what you are doing!\n" |
| "Also SHOULD NOTE THAT this only for old BBM scheme!\n" |
| "\nReally erase this NAND flash for recreate bbt? <y/N>\n"); |
| |
| do { |
| if (getc() == 'y' && getc() == '\r') |
| break; |
| |
| puts("recreate aborted\n"); |
| return -1; |
| } while (0); |
| |
| addr = (ulong)simple_strtoul(argv[3], NULL, 16); |
| block = addr >> mtd->erasesize_shift; |
| if (block <= 0) |
| block = 1; |
| printf("ready to init flash...\n"); |
| bbm->no_sync = 1; |
| instr.addr = mtd->erasesize * block; |
| instr.len = mtd->erasesize; |
| |
| printf("erasing..\n"); |
| while (instr.addr < mtd->size) { |
| printf("%llx\r", instr.addr); |
| ret = mtd->_erase(mtd, &instr); |
| if (ret) { |
| printf("erase failed at %llx\n", instr.addr); |
| return -1; |
| } |
| instr.addr += mtd->erasesize; |
| } |
| printf("\ndone!\n"); |
| bbm->no_sync = 0; |
| pxa3xx_update_bbt(mtd, 0); |
| } |
| else if (strcmp(argv[1], "convert") == 0) { |
| struct reloc_table *table; |
| struct reloc_item *item; |
| int old_bbm_slot; |
| char *buf; |
| |
| buf = malloc(mtd->writesize); |
| old_bbm_slot = page_search(mtd, PXA_BEGIN_SLOT, |
| (mtd->erasesize >> mtd->writesize_shift) - 1, |
| ORDER_REVERSE, PXA_RELOC_HEADER, buf, BBM_HALF_MASK); |
| if (old_bbm_slot < 0) { |
| printf("Seems there is no old bbm slot on your board!!\n"); |
| printf("Convertion failed!!!\n"); |
| return 1; |
| } |
| |
| table = (struct reloc_table *)buf; |
| item = (struct reloc_item *)&table[1]; |
| pxa3xx_bbm_recovery(mtd, BBM_NEW, item, table->total, 0); |
| } |
| else if (strcmp(argv[1], "mark") == 0) { |
| addr = (ulong)simple_strtoul(argv[3], NULL, 16); |
| block = addr >> mtd->erasesize_shift; |
| |
| ret = pxa3xx_block_markbad(mtd, addr); |
| if (ret == 0) { |
| printf("block %d successfully marked as bad\n", |
| block); |
| return 0; |
| } else { |
| printf("block %d NOT marked as bad! ERROR %d\n", |
| block, ret); |
| } |
| } |
| else { |
| printf ("Usage:\n%s\n", cmdtp->usage); |
| return 1; |
| } |
| } |
| |
| return 1; |
| } |
| |
| U_BOOT_CMD( |
| bbt, 4, 1, do_bbt, |
| "bbt\t- Bad Block Management\n", |
| "show [nand | onenand]\t- show nand/onenand relocation table\n" |
| "bbt init [nand | onenand]\t- init relocation table\n" |
| "bbt recreate [nand | onenand] addr\t- rebuild the bbt by erasing the whole flash after sepecified addr\n" |
| "bbt convert [nand | onenand]\t- convert the old bbm to new bbm scheme if old existed\n" |
| "bbt mark [nand | onenand] addr\t- mark bad block\n" |
| ); |