void nand_init(void) { int i; unsigned int size = 0; for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); size += nand_info[i].size; if (nand_curr_device == -1) nand_curr_device = i; } printf("%lu MB ", size / (1024 * 1024)); #if defined(CFG_NAND_FLASH_BBT) printf("(Flash Based BBT Enabled)"); #endif printf("\n"); #ifdef CFG_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); #endif }
int board_nand_init(struct nand_chip *nand) { int cs = (ulong)nand->IO_ADDR_W & 0x00000003; ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; nand->eccmode = NAND_ECC_SOFT; nand->hwcontrol = ndfc_hwcontrol; nand->read_byte = ndfc_read_byte; nand->write_byte = ndfc_write_byte; nand->dev_ready = ndfc_dev_ready; #ifndef CONFIG_NAND_SPL nand->write_buf = ndfc_write_buf; nand->read_buf = ndfc_read_buf; nand->verify_buf = ndfc_verify_buf; #else /* * Setup EBC (CS0 only right now) */ mtebc(EBC0_CFG, 0xb8400000); mtebc(pb0cr, CFG_EBC_PB0CR); mtebc(pb0ap, CFG_EBC_PB0AP); #endif /* * Select required NAND chip in NDFC */ board_nand_select_device(nand, cs); out32(base + NDFC_BCFG0 + (cs << 2), 0x80002222); return 0; }
int board_nand_init(struct nand_chip *nand) { int cs = (ulong)nand->IO_ADDR_W & 0x00000003; ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00; static int chip = 0; /* * Save chip-select for this chip # */ ndfc_cs[chip] = cs; /* * Select required NAND chip in NDFC */ board_nand_select_device(nand, chip); nand->IO_ADDR_R = (void __iomem *)(base + NDFC_DATA); nand->IO_ADDR_W = (void __iomem *)(base + NDFC_DATA); nand->cmd_ctrl = ndfc_hwcontrol; nand->chip_delay = 50; 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.strength = 1; nand->select_chip = ndfc_select_chip; #ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT nand->options |= NAND_BUSWIDTH_16; #endif #ifndef CONFIG_NAND_SPL nand->write_buf = ndfc_write_buf; nand->verify_buf = ndfc_verify_buf; nand->read_byte = ndfc_read_byte; chip++; #else /* * Setup EBC (CS0 only right now) */ mtebc(EBC0_CFG, CONFIG_SYS_NDFC_EBC0_CFG); mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR); mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP); #endif return 0; }
int board_nand_init(struct nand_chip *nand) { static int UpmInit = 0; volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR; volatile memctl8260_t *memctl = &immr->im_memctl; if (hwinf.nand == 0) return -1; /* Setup the UPM */ if (UpmInit == 0) { switch (hwinf.busclk_real) { case 100000000: upmconfig (UPMB, (uint *) upmTable100, sizeof (upmTable100) / sizeof (uint)); break; case 133333333: upmconfig (UPMB, (uint *) upmTable133, sizeof (upmTable133) / sizeof (uint)); break; default: upmconfig (UPMB, (uint *) upmTable67, sizeof (upmTable67) / sizeof (uint)); break; } UpmInit = 1; } /* Setup the memctrl */ memctl->memc_or3 = CONFIG_SYS_NAND_OR; memctl->memc_br3 = CONFIG_SYS_NAND_BR; memctl->memc_mbmr = (MxMR_OP_NORM); nand->ecc.mode = NAND_ECC_SOFT; nand->cmd_ctrl = upmnand_hwcontrol; nand->read_byte = upmnand_read_byte; nand->dev_ready = tqm8272_dev_ready; #ifndef CONFIG_NAND_SPL nand->write_buf = tqm8272_write_buf; nand->read_buf = tqm8272_read_buf; nand->verify_buf = tqm8272_verify_buf; #endif /* * Select required NAND chip */ board_nand_select_device(nand, 0); return 0; }
int board_nand_init(struct nand_chip *nand) { int cs = (ulong)nand->IO_ADDR_W & 0x00000003; ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00; static int chip = 0; /* * Save chip-select for this chip # */ ndfc_cs[chip] = cs; /* * Select required NAND chip in NDFC */ board_nand_select_device(nand, chip); nand->IO_ADDR_R = (void __iomem *)(base + NDFC_DATA); nand->IO_ADDR_W = (void __iomem *)(base + NDFC_DATA); nand->cmd_ctrl = ndfc_hwcontrol; nand->chip_delay = 50; 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.strength = 1; nand->select_chip = ndfc_select_chip; #ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT nand->options |= NAND_BUSWIDTH_16; #endif nand->write_buf = ndfc_write_buf; #if defined(CONFIG_MTD_NAND_VERIFY_WRITE) nand->verify_buf = ndfc_verify_buf; #endif nand->read_byte = ndfc_read_byte; chip++; return 0; }
void nand_init(void) { int i; unsigned int size = 0; for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); size += nand_info[i].size; if (nand_curr_device == -1) nand_curr_device = i; } // printf("%lu MiB\n", size / (1024 * 1024)); //HJ #ifdef CFG_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); #endif }
void nand_init(void) { int i; unsigned int size = 0; for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { //CONFIG_SYS_MAX_NAND_DEVICE == 1 nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); size += nand_info[i].size / 1024; if (nand_curr_device == -1) nand_curr_device = i; } printf("%u MiB\n", size / 1024); printf("zhaodehaoxinku\n"); #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); #endif }
void nand_init(void) { #ifdef CONFIG_SYS_NAND_SELF_INIT board_nand_init(); #else int i; for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) nand_init_chip(i); #endif printf("%lu MiB\n", total_nand_size / 1024); #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); #endif }
static int set_dev(int dev) { if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) { puts("No such device\n"); return -1; } if (nand_curr_device == dev) return 0; printf("Device %d: %s", dev, nand_info[dev].name); puts("... is now current device\n"); nand_curr_device = dev; #ifdef CONFIG_SYS_NAND_SELECT_DEVICE board_nand_select_device(nand_info[dev].priv, dev); #endif return 0; }
void nand_init(void) { int i; unsigned int size = 0; for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); size += nand_info[i].size / 1024; if (nand_curr_device == -1) nand_curr_device = i; } #if defined(MV_NAND_GANG_MODE) printf("%u MiB - Gang\n", size / 1024); #else printf("%u MiB\n", size / 1024); #endif #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); #endif }
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int i, dev, ret = 0; ulong addr, off; size_t size; char *cmd, *s; nand_info_t *nand; #ifdef CONFIG_SYS_NAND_QUIET int quiet = CONFIG_SYS_NAND_QUIET; #else int quiet = 0; #endif const char *quiet_str = getenv("quiet"); /* at least two arguments please */ if (argc < 2) goto usage; if (quiet_str) quiet = simple_strtoul(quiet_str, NULL, 0) != 0; cmd = argv[1]; if (strcmp(cmd, "info") == 0) { putc('\n'); for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { if (nand_info[i].name) nand_print_info(i); } return 0; } if (strcmp(cmd, "device") == 0) { if (argc < 3) { putc('\n'); if ((nand_curr_device < 0) || (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE)) puts("no devices available\n"); else nand_print_info(nand_curr_device); return 0; } dev = (int)simple_strtoul(argv[2], NULL, 10); if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) { puts("No such device\n"); return 1; } printf("Device %d: %s", dev, nand_info[dev].name); puts("... is now current device\n"); nand_curr_device = dev; #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[dev].priv, dev); #endif return 0; } 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 #ifdef CONFIG_ENV_OFFSET_OOB && strcmp(cmd, "env.oob") != 0 #endif ) goto usage; #ifdef CONFIG_ENV_OFFSET_OOB /* this command operates only on the first nand device */ if (strcmp(cmd, "env.oob") == 0) { return do_nand_env_oob(cmdtp, &nand_info[0], argc - 1, argv + 1); } #endif /* the following commands operate on the current device */ if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[nand_curr_device].name) { puts("\nno devices available\n"); return 1; } nand = &nand_info[nand_curr_device]; if (strcmp(cmd, "bad") == 0) { printf("\nDevice %d bad blocks:\n", nand_curr_device); for (off = 0; off < nand->size; off += nand->erasesize) if (nand_block_isbad(nand, off)) printf(" %08lx\n", off); return 0; } /* * Syntax is: * 0 1 2 3 4 * nand erase [clean] [off size] */ 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 o = clean ? 3 : 2; int scrub = !strcmp(cmd, "scrub"); printf("\nNAND %s: ", scrub ? "scrub" : "erase"); /* skip first two or three arguments, look for offset and size */ if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0) return 1; memset(&opts, 0, sizeof(opts)); opts.offset = off; opts.length = size; opts.jffs2 = clean; opts.quiet = quiet; if (scrub) { puts("Warning: " "scrub option will erase all factory set " "bad blocks!\n" " " "There is no reliable way to recover them.\n" " " "Use this command only for testing purposes " "if you\n" " " "are sure of what you are doing!\n" "\nReally scrub this NAND flash? <y/N>\n"); if (getc() == 'y') { puts("y"); if (getc() == '\r') opts.scrub = 1; else { puts("scrub aborted\n"); return -1; } } else { puts("scrub aborted\n"); return -1; } } ret = nand_erase_opts(nand, &opts); printf("%s\n", ret ? "ERROR" : "OK"); return ret == 0 ? 0 : 1; } if (strncmp(cmd, "dump", 4) == 0) { if (argc < 3) goto usage; s = strchr(cmd, '.'); off = (int)simple_strtoul(argv[2], NULL, 16); if (s != NULL && strcmp(s, ".oob") == 0) ret = nand_dump(nand, off, 1); else ret = nand_dump(nand, off, 0); return ret == 0 ? 1 : 0; } if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { int read; if (argc < 4) goto usage; addr = (ulong)simple_strtoul(argv[2], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ 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 || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { 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 (!strcmp(s, ".oob")) { /* 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, &ops); else ret = nand->write_oob(nand, off, &ops); } else {
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i, dev, ret = 0; uint32_t addr, cmp_addr; uint64_t off; uint64_t size; char *cmd, *s; nand_info_t *nand; #ifdef CONFIG_SYS_NAND_QUIET int quiet = CONFIG_SYS_NAND_QUIET; #else int quiet = 0; #endif const char *quiet_str = getenv("quiet"); /* at least two arguments please */ if (argc < 2) goto usage; if (quiet_str) quiet = simple_strtoul(quiet_str, NULL, 0) != 0; cmd = argv[1]; if (strcmp(cmd, "info") == 0) { for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { if (nand_info[i].name) nand_print_info(i); } return 0; } if (strcmp(cmd, "device") == 0) { if (argc < 3) { putc('\n'); if ((nand_curr_device < 0) || (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE)) puts("no devices available\n"); else nand_print_info(nand_curr_device); return 0; } dev = (int)simple_strtoul(argv[2], NULL, 10); if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) { puts("No such device\n"); return 1; } printf("Device %d: %s", dev, nand_info[dev].name); puts("... is now current device\n"); nand_curr_device = dev; #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[dev].priv, dev); #endif return 0; } 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, "pattern") != 0 && strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) goto usage; /* the following commands operate on the current device */ if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[nand_curr_device].name) { puts("\nno devices available\n"); return 1; } nand = &nand_info[nand_curr_device]; if (strcmp(cmd, "bad") == 0) { printf("\nDevice %d bad blocks:\n", nand_curr_device); for (off = 0; off < nand->size; off += nand->erasesize) if (nand_block_isbad(nand, off)) printf(" %12llx\n", off); return 0; } /* * Syntax is: * 0 1 2 3 4 * nand erase [clean] [off size] */ 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 o = clean ? 3 : 2; int scrub = !strcmp(cmd, "scrub"); printf("\nNAND %s: ", scrub ? "scrub" : "erase"); /* skip first two or three arguments, look for offset and size */ if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0) return 1; memset(&opts, 0, sizeof(opts)); opts.offset = off; opts.length = size; opts.jffs2 = clean; opts.quiet = quiet; if (scrub) { puts("Warning: " "scrub option will erase all factory set " "bad blocks!\n" " " "There is no reliable way to recover them.\n" " " "Use this command only for testing purposes " "if you\n" " " "are sure of what you are doing!\n" "\nReally scrub this NAND flash? <y/N>\n"); if (getc() == 'y' && getc() == '\r') { opts.scrub = 1; } else { puts("scrub aborted\n"); return -1; } } ret = nand_erase_opts(nand, &opts); printf("%s\n", ret ? "ERROR" : "OK"); return ret == 0 ? 0 : 1; } if (strncmp(cmd, "dump", 4) == 0) { if (argc < 3) goto usage; s = strchr(cmd, '.'); off = simple_strtoull(argv[2], NULL, 16); if (s != NULL && strcmp(s, ".oob") == 0) ret = nand_dump(nand, off, 1); else ret = nand_dump(nand, off, 0); return ret == 0 ? 1 : 0; } if (strncmp(cmd, "pattern", 4) == 0) { int chunk_num; uint64_t offset, chunk64, cmp64; nand_erase_options_t opts; memset(&opts, 0, sizeof(opts)); // nand pattern addr cmp_addr chunk_size // 0 1 2 3 4 if (argc < 5) goto usage; addr = simple_strtoul(argv[2], NULL, 16); cmp_addr = simple_strtoul(argv[3], NULL, 16); chunk64 = simple_strtoull(argv[4], NULL, 16); cmp64 = chunk64; chunk_num = (int) (nand->size / chunk64); printf("NAND size [0x%llx], chunk size [0x%llx], number of chunks [%d]\n", nand->size, chunk64, chunk_num); printf("Erasing all chip...\n"); opts.offset = 0; opts.length = nand->size; opts.jffs2 = 0; opts.quiet = 0; opts.scrub = 0; if (nand_erase_opts(nand, &opts) != 0) { printf("[FAILED]\n"); return 1; } else { printf("[OK]\n"); } offset = 0; while(offset < nand->size) { printf("0x%010llx:", offset); // printf("\tB:"); // if (nand_block_isbad(nand, i*chunk_size & ~(nand->erasesize - 1))) { // printf("[V]\n"); // continue; // } else { // printf("[X]"); // } // size_include_bad = get_len_incl_bad (nand, offset, chunk_size); // opts.offset = offset; // opts.length = size_include_bad; // opts.quiet = 1; // printf("\tE:"); // if (nand_erase_opts(nand, &opts) != 0) { // printf("[X]\n"); // return 1; // } else { // printf("[V]"); // } printf("\tW:"); chunk64 = cmp64; if (nand_write_skip_bad(nand, offset, &chunk64, (u_char *)addr) != 0) { printf("[X]\n"); return 1; } else { printf("[V]"); } printf("\tR:"); chunk64 = cmp64; if (nand_read_skip_bad(nand, offset, &chunk64, (u_char *)cmp_addr) != 0) { printf("[X]\n"); return 1; } else { printf("[V]"); } printf("\tC:"); if (memcmp((void *)addr, (void *)cmp_addr, cmp64) != 0) { printf("[X]\n"); return 1; } else { printf("[V]"); } printf("\n"); if (ctrlc()) { puts ("\nAbort\n"); return (-1); } offset += get_len_incl_bad (nand, offset, cmp64); } printf("NAND Pattern Test PASSED!\n"); return 0; } if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { int read; if (argc < 4) goto usage; addr = simple_strtoul(argv[2], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ 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 || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { 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 (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { .oobbuf = (uint8_t *)addr, .ooblen = size, .mode = MTD_OOB_RAW }; if (read) ret = nand->read_oob(nand, off, &ops); else ret = nand->write_oob(nand, off, &ops); } else {
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i, dev, ret = 0; ulong addr; loff_t off, size; char *cmd, *s; nand_info_t *nand; #ifdef CONFIG_SYS_NAND_QUIET int quiet = CONFIG_SYS_NAND_QUIET; #else int quiet = 0; #endif const char *quiet_str = getenv("quiet"); #if ((defined CONFIG_AML_NAND_KEY) || (defined MX_REVD) || (defined CONFIG_SECURE_NAND)) int chip_num , tmp_chip_num, error; nand = nand_info[nand_curr_device]; struct mtd_info *mtd =nand; struct aml_nand_chip *aml_chip = mtd_to_nand_chip(nand); #endif /* at least two arguments please */ if (argc < 2) goto usage; if (quiet_str) quiet = simple_strtoul(quiet_str, NULL, 0) != 0; cmd = argv[1]; #ifdef CONFIG_AML_NAND_KEY if (strcmp(cmd, "key") == 0){ aml_chip->key_protect = 1; //force nand key can be erased return 0; } #endif #ifdef CONFIG_SECURE_NAND if (strcmp(cmd, "secure") == 0){ aml_chip->secure_protect = 1; //force nand key can be erased return 0; } #endif #ifdef CONFIG_SECURE_NAND if (strcmp(cmd, "secure") == 0){ aml_chip->secure_protect = 1; //force nand key can be erased return 0; } #endif if(strcmp(cmd, "exist") == 0){ if(nand_info[1]){ printf("nand exist return 0\n"); return 0; } else{ printf("nand exist return 1\n"); return 1; } } #ifdef MX_REVD if (strcmp(cmd, "errstat") == 0){ printk("checking chiprev here\n"); if(aml_chip->err_sts == NAND_CHIP_REVB_HY_ERR){ printk("Must use RevD chip for Hynix 26nm/20nm nand boot without SPI!!!\n"); return NAND_CHIP_REVB_HY_ERR; } return 0; } #endif #ifdef CONFIG_SECURE_NAND if (strcmp(cmd, "secure") == 0){ aml_chip->secure_protect = 1; //force nand key can be erased return 0; } #endif if (strcmp(cmd, "info") == 0) { #ifdef CONFIG_AML_NAND_KEY aml_chip->key_protect = 0; //protect nand key can not be erased #endif #ifdef CONFIG_SECURE_NAND aml_chip->secure_protect = 0; //protect nand secure can not be erased #endif putc('\n'); for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { nand = nand_info[i]; if (!nand) { nand_init(); if (!nand) return -1; } if (nand->name) nand_print_info(i); } return 0; } if (strcmp(cmd, "init") == 0) { nand_init(); return 0; } //cmd for nand test , if nand is ok , then trigger power off if (strcmp(cmd, "test") == 0) { int ret=-1; puts("\ntest the nand flash ***\n"); for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { nand = nand_info[i]; if (!nand) { ret=nand_test_init(); printf("\n***nand_test_init()in NAND DEVICE %d returned:%d***\n ", i,ret); if (ret) return -1; } } return 0; } if (strcmp(cmd, "scrub_detect") == 0) { if (nand_curr_device < 0 || nand_curr_device >= (CONFIG_SYS_MAX_NAND_DEVICE+2)) { puts("\nno devices available\n"); return 1; } nand = nand_info[nand_curr_device]; aml_nand_stupid_dectect_badblock(nand); return 0; } if (strcmp(cmd, "device") == 0) { if (argc < 3) { putc('\n'); if ((nand_curr_device < 0) || (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE)) puts("no devices available\n"); else nand_print_info(nand_curr_device); return 0; } dev = (int)simple_strtoul(argv[2], NULL, 10); if (dev < 0 || dev >= (CONFIG_SYS_MAX_NAND_DEVICE+1) || !nand_info[dev]->name) { puts("No such device\n"); return 1; } printf("Device %d: %s", dev, nand_info[dev]->name); puts("... is now current device\n"); nand_curr_device = dev; #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* * Select the chip in the board/cpu specific driver */ board_nand_select_device(nand_info[dev]->priv, dev); #endif return 0; } 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 && strncmp(cmd, "rom_protect", 11) != 0 && strncmp(cmd, "wr_rd_cmp", 9) != 0 && strncmp(cmd, "rom_write", 9) != 0 && (strncmp(cmd, "rom_read", 8) != 0) && strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 && strcmp(cmd, "factory_info") != 0 && strcmp(cmd, "show_para_page")&& strncmp(cmd, "scrub_safe", 10) != 0) //my_ goto usage; /* the following commands operate on the current device */ if (nand_curr_device < 0 || nand_curr_device >= (CONFIG_SYS_MAX_NAND_DEVICE+2)) { puts("\nno devices available\n"); return 1; } nand = nand_info[nand_curr_device]; if (!nand) return -1; if (strcmp(cmd, "bad") == 0) { printf("\nDevice %d bad blocks:\n", nand_curr_device); for (off = 0; off < nand->size; off += nand->erasesize) if (nand_block_isbad(nand, off)) printf(" %09llx\n", off); return 0; } /* * Syntax is: * 0 1 2 3 4 * nand erase [clean] [off size] */ if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0 || strcmp(cmd, "scrub_safe") == 0) { nand_erase_options_t opts; int argc_cnt = 2; //printk("%s\n", argv[2]); /* if (isstring(argv[2])) { nand = get_mtd_device_nm(argv[2]); if (IS_ERR(nand)){ printf("get nand device err\n"); return 1; } argc_cnt++; } */ /* "clean" at index 2 means request to write cleanmarker */ int clean = argc > argc_cnt && !strcmp("clean", argv[argc_cnt]); if (clean) argc_cnt++; int o = argc_cnt; int scrub = !strncmp(cmd, "scrub",10); int scrub_safe = !strncmp(cmd, "scrub_safe",10); if(scrub_safe) printf("\nNAND %s: ", scrub_safe ? "scrub_safe" : "erase"); else printf("\nNAND %s: ", scrub ? "scrub" : "erase"); if (argv[argc_cnt]) { if(!strcmp(argv[argc_cnt], "whole")) { off = 0; size = nand->size; printf("whole chip.\n"); } } else { /* skip first two or three arguments, look for offset and size */ if ((strcmp(cmd, "erase") == 0) && (argc < 3)) { goto usage; } if ((arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)) { return 1; } } memset(&opts, 0, sizeof(opts)); opts.offset = off; opts.length = size; opts.jffs2 = clean; opts.quiet = quiet; if (scrub) { puts("Warning: " "scrub option will erase all factory set " "bad blocks!\n" " " "There is no reliable way to recover them.\n" " " "Use this command only for testing purposes " "if you\n" " " "are sure of what you are doing!\n" "\nReally scrub this NAND flash? <y/N>\n"); if(nand_protect) { if (getc() == 'y') { puts("y"); if (getc() == '\r') opts.scrub = 1; else { puts("scrub aborted\n"); return -1; } } else { puts("scrub aborted\n"); return -1; } } else { opts.scrub = 1; } } else if(scrub_safe){ puts("Warning: " "scrub_safe option will erase all " "bad blocks except factory bad blocks!\n"); opts.scrub = 2; // indicate scrub_safe } ret = nand_erase_opts(nand, &opts); printf("%s\n", ret ? "ERROR" : "OK"); #ifdef CONFIG_AML_NAND_KEY aml_chip->key_protect = 0; //protect nand key can not be erased #endif #ifdef CONFIG_SECURE_NAND aml_chip->secure_protect = 0; //protect nand secure can not be erased #endif return ret == 0 ? 0 : 1; } if (strncmp(cmd, "dump", 4) == 0) { if (argc < 3) goto usage; s = strchr(cmd, '.'); //off = (loff_t)simple_strtoul(argv[2], NULL, 16); if (!(str2longlong(argv[2], (unsigned long long*)(&off)))) return -1; if (s != NULL && strcmp(s, ".oob") == 0) ret = nand_dump(nand, off, 1); else ret = nand_dump(nand, off, 0); return ret == 0 ? 1 : 0; } if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { int read; if (argc < 4) goto usage; if (isstring(argv[2])) { nand = get_mtd_device_nm(argv[2]); if (IS_ERR(nand)) goto usage; addr = (ulong)simple_strtoul(argv[3], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ printf("\nNAND %s: %s ", read ? "read" : "write", argv[2]); if (argc == 4) { extern unsigned int get_mtd_size(char *name); off = 0; size = get_mtd_size(argv[2]); } else { if (arg_off_size(argc - 4, argv + 4, nand, &off, &size) != 0) return 1; } } else { addr = (ulong)simple_strtoul(argv[2], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ printf("\nNAND %s: ", read ? "read" : "write"); if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) return 1; } #ifdef CONFIG_AMLROM_NANDBOOT if((read==0) && ((off)<(1024* nand->writesize)) && (nand_curr_device == 0)){ printf("offset 0x%llx in aml-boot area ,abort\n", off); return -1; } #endif s = strchr(cmd, '.'); if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { if (read) ret = nand_read_skip_bad(nand, off, &size, (u_char *)addr, 0); else ret = nand_write_skip_bad(nand, off, &size, (u_char *)addr, 0); } else if (!strcmp(s, ".oob")) { /* 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, &ops); else ret = nand->write_oob(nand, off, &ops); } else if (!strcmp(s, ".raw")) {