static flash_addr_t nfc_l_to_p(flash_addr_t addr)
{
if (g_block_offset == 0) {
- return addr;
+ return addr & MXC_NAND_ADDR_MASK;
} else {
flash_addr_t ra;
u32 block = (addr & MXC_NAND_ADDR_MASK) / NF_BLK_SZ;
static int flash_addr_valid(flash_addr_t addr)
{
+ if (!flash_enable) {
+ nfc_printf(NFC_DEBUG_MIN, "No flash area enabled\n");
+ return 1;
+ }
if (addr < flash_region_start || addr >= flash_region_end) {
diag_printf("Flash address 0x%08llx is outside valid region 0x%08llx..0x%08llx\n",
(u64)addr, (u64)flash_region_start, (u64)flash_region_end);
+ return 0;
}
- return addr >= flash_region_start && addr < flash_region_end;
+ return 1;
}
/* FIXME: we should pass flash_addr_t as arguments */
res = (buf[off] >> sft) & 0x3;
if (res) {
addr = BLOCK_TO_OFFSET(block);
- diag_printf1("Block %u at %08llx is marked %s (%d) in BBT@%p[%02x] mask %02x\n",
+ diag_printf1("Block %u at 0x%08llx is marked %s (%d) in BBT@%p[%02x] mask %02x\n",
block, (u64)addr, res == BLK_RESERVED ? "reserved" :
res == BLK_BAD_FACTORY ? "factory bad" : "runtime bad",
res, buf, off, 3 << sft);
diag_printf("Error: invalid length %u (must be > 0 and block aligned)\n", len);
return FLASH_ERR_INVALID;
}
- addr = nfc_l_to_p(addr);
+ addr &= MXC_NAND_ADDR_MASK;
// now addr has to be block aligned
for (sz = 0; sz < len; addr += NF_BLK_SZ, j++, sz += NF_BLK_SZ) {
+ if (!flash_addr_valid(addr)) {
+ return 0;
+ }
blk = OFFSET_TO_BLOCK(addr);
if (skip_bad && nfc_is_badblock(blk, g_bbt)) {
diag_printf("\nSkipping bad block %u at addr 0x%08llx\n",
local_cmd_entry("show",
"Show a page main/spare areas or spare area only (-s)",
- "-f <raw page address> [-s]",
+ "-f <raw page address> | -b <block> [-s]",
nand_show,
NAND_cmds
);
static u32 curr_addr;
static void nand_show(int argc, char *argv[])
{
- u32 ra;
+ u32 ra, block;
bool flash_addr_set = false;
+ bool block_set = false;
bool spar_only = false;
- struct option_info opts[2];
+ struct option_info opts[3];
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
&ra, &flash_addr_set, "NAND FLASH memory byte address");
- init_opts(&opts[1], 's', false, OPTION_ARG_TYPE_FLG,
+ init_opts(&opts[1], 'b', true, OPTION_ARG_TYPE_NUM,
+ &block, &block_set, "NAND FLASH memory block number");
+ init_opts(&opts[2], 's', false, OPTION_ARG_TYPE_FLG,
&spar_only, NULL, "Spare only");
- if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, 0)) {
+ if (!scan_opts(argc, argv, 2, opts, NUM_ELEMS(opts), NULL, 0, NULL)) {
return;
}
- if (!flash_addr_set) {
+ if (flash_addr_set && block_set) {
+ nand_usage("options -f and -b are mutually exclusive");
+ return;
+ } else if (flash_addr_set) {
+ curr_addr = ra;
+ } else if (block_set) {
+ ra = BLOCK_TO_OFFSET(block) + (unsigned long)flash_info.start;
+ curr_addr = ra;
+ } else {
ra = curr_addr;
curr_addr += NF_PG_SZ;
- } else {
- curr_addr = ra;
}
if (ra % NF_PG_SZ) {
init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_NUM,
&col, &col_set, "column addr");
- if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
+ if (!scan_opts(argc, argv, 2, opts, NUM_ELEMS(opts), NULL, 0, NULL)) {
nand_usage("invalid arguments");
return;
}
diag_printf("\n** Error: flash address: 0x%08x out of range\n", ra);
return;
}
+ if (nfc_is_badblock(OFFSET_TO_BLOCK(ra), g_bbt)) {
+ diag_printf("\nSkipping bad block %u at addr=0x%08llx\n",
+ OFFSET_TO_BLOCK(ra), (u64)ra);
+ ra = (OFFSET_TO_BLOCK(ra) + 1) * NF_BLK_SZ;
+ continue;
+ }
pg_no = ra / NF_PG_SZ;
pg_off = ra % NF_PG_SZ;
for (i = 0; i < num_of_nand_chips; i++) {
&len, &length_set, "image length [in FLASH]");
init_opts(&opts[3], 'c', true, OPTION_ARG_TYPE_NUM,
&col, &col_set, "column addr");
- if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
+ if (!scan_opts(argc, argv, 2, opts, NUM_ELEMS(opts), NULL, 0, NULL)) {
nand_usage("invalid arguments");
return;
}
}
if ((mem_addr < (CYG_ADDRESS)ram_start) ||
- ((mem_addr+len) >= (CYG_ADDRESS)ram_end)) {
- diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
+ ((mem_addr + len) >= (CYG_ADDRESS)ram_end)) {
+ diag_printf("** WARNING: RAM address range: %p..%p may be invalid\n",
+ (void *)mem_addr, (void *)(mem_addr + len));
diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
}
mem_addr_st = mem_addr;
len_st = len;
ra &= MXC_NAND_ADDR_MASK;
+
+ mxc_nfc_buf_clear(NAND_SPAR_BUF0, 0xff, NF_SPARE_SZ);
do {
if (OFFSET_TO_BLOCK(ra) > (NF_BLK_CNT - 1)) {
- diag_printf("\nOut of range: addr=0x%08x\n", ra);
+ diag_printf("\nFlash address 0x%08x out of range\n", ra);
return;
}
if (nfc_is_badblock(OFFSET_TO_BLOCK(ra), g_bbt)) {
}
mark_blk_bad(OFFSET_TO_BLOCK(ra), g_bbt, BLK_BAD_RUNTIME);
ra = (OFFSET_TO_BLOCK(ra) + 1) * NF_BLK_SZ; //make sure block size aligned
- mem_addr = mem_addr_st; // rewind to blocl boundary
+ mem_addr = mem_addr_st; // rewind to block boundary
len = len_st;
continue;
}
init_opts(&opts[2], 'o', false, OPTION_ARG_TYPE_FLG,
&force_erase_set, &force_erase_set, "force erases block");
- if (!scan_opts(argc, argv, 2, opts, 4, 0, 0, 0)) {
+ if (!scan_opts(argc, argv, 2, opts, NUM_ELEMS(opts), NULL, 0, NULL)) {
nand_usage("invalid arguments");
return;
}
nand_usage("missing argument");
return;
}
- if ((ra % NF_BLK_SZ) != 0 ||
- (len % NF_BLK_SZ) != 0 || len == 0) {
- diag_printf("Address or length is not block aligned or length is zero!\n");
+ if ((ra % NF_BLK_SZ) != 0) {
+ diag_printf("Address must be block aligned!\n");
+ diag_printf("Block size is 0x%x\n", NF_BLK_SZ);
+ return;
+ }
+ if ((len % NF_BLK_SZ) != 0) {
+ diag_printf("length must be block aligned!\n");
diag_printf("Block size is 0x%x\n", NF_BLK_SZ);
return;
}
+ if (len == 0) {
+ diag_printf("length must be > 0!\n");
+ return;
+ }
- if (!verify_action("About to erase 0x%x bytes from nand offset 0x%x\n", len, ra)) {
+ if (!verify_action("About to erase 0x%08x bytes from nand offset 0x%08x", len, ra)) {
diag_printf("** Aborted\n");
return;
}
- // now ra is block aligned
if (force_erase_set == true) {
diag_printf("Force erase ...");
nfc_erase_region(ra, len, 0, 1);
init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG,
&force_rescan, NULL, "force low level re-scan");
- if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, 0)) {
+ if (!scan_opts(argc, argv, 2, opts, NUM_ELEMS(opts), NULL, 0, NULL)) {
nand_usage("invalid arguments");
return;
}
diag_printf("Non page-aligned read not supported here: 0x%x\n", addr);
return;
}
- if (spare_only) {
- diag_printf("Error %d: Not supported\n", __LINE__);
- return;
- } else {
- pg_no = addr / NF_PG_SZ;
- pg_off = addr % NF_PG_SZ;
- for (i = 0; i < num_of_nand_chips; i++) {
- if (nfc_read_page(i, pg_no, pg_off) != 0) {
- diag_printf("Error %d: uncorrectable. But still printing ...\n", __LINE__);
- }
- pg_off = 0;
- diag_printf("\n============ Printing block(%d) page(%d) ==============\n",
- blk_num, pg_num);
-
- diag_printf("<<<<<<<<< spare area >>>>>>>>>\n");
- print_pkt_16((u16*)NAND_SPAR_BUF0, NF_SPARE_SZ);
+ pg_no = addr / NF_PG_SZ;
+ pg_off = addr % NF_PG_SZ;
+ for (i = 0; i < num_of_nand_chips; i++) {
+ if (nfc_read_page(i, pg_no, pg_off) != 0) {
+ diag_printf("Error %d: uncorrectable. But still printing ...\n", __LINE__);
+ }
+ pg_off = 0;
+ diag_printf("\n============ Printing block(%d) page(%d) ==============\n",
+ blk_num, pg_num);
- if (!spare_only) {
- diag_printf("<<<<<<<<< main area >>>>>>>>>\n");
- print_pkt_16((u16*)NAND_MAIN_BUF0, NF_PG_SZ / num_of_nand_chips);
- }
+ diag_printf("<<<<<<<<< spare area >>>>>>>>>\n");
+ print_pkt_16((u16*)NAND_SPAR_BUF0, NF_SPARE_SZ);
- diag_printf("\n");
+ if (!spare_only) {
+ diag_printf("<<<<<<<<< main area >>>>>>>>>\n");
+ print_pkt_16((u16*)NAND_MAIN_BUF0, NF_PG_SZ / num_of_nand_chips);
}
+
+ diag_printf("\n");
}
}