X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-redboot.git;a=blobdiff_plain;f=packages%2Fdevs%2Fflash%2Farm%2Fmxc%2Fv2_0%2Fsrc%2Fmxc_nfc.c;h=4bcf00603d792217f80dd424c790ca50366f86d6;hp=f7890f5b74df4268345d505e0c5de37c4388dc17;hb=9de9d39b630ad85d97cb8355109360301998239f;hpb=14a8b354264303f70c73fda081ab2091339926d7 diff --git a/packages/devs/flash/arm/mxc/v2_0/src/mxc_nfc.c b/packages/devs/flash/arm/mxc/v2_0/src/mxc_nfc.c index f7890f5b..4bcf0060 100644 --- a/packages/devs/flash/arm/mxc/v2_0/src/mxc_nfc.c +++ b/packages/devs/flash/arm/mxc/v2_0/src/mxc_nfc.c @@ -322,7 +322,7 @@ static int flash_enable; 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; @@ -340,11 +340,16 @@ static flash_addr_t nfc_l_to_p(flash_addr_t addr) 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 */ @@ -739,7 +744,7 @@ static int nfc_is_badblock(u32 block, u8 *buf) 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); @@ -1073,9 +1078,12 @@ int nfc_erase_region(flash_addr_t addr, u32 len, bool skip_bad, bool verbose) 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", @@ -1731,7 +1739,7 @@ local_cmd_entry("info", local_cmd_entry("show", "Show a page main/spare areas or spare area only (-s)", - "-f [-s]", + "-f | -b [-s]", nand_show, NAND_cmds ); @@ -1816,24 +1824,33 @@ static void nand_usage(char *why) 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) { @@ -1873,7 +1890,7 @@ static void nand_read(int argc, char *argv[]) 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; } @@ -1916,6 +1933,12 @@ static void nand_read(int argc, char *argv[]) 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++) { @@ -1958,7 +1981,7 @@ static void nand_write(int argc, char *argv[]) &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; } @@ -1969,8 +1992,9 @@ static void nand_write(int argc, char *argv[]) } 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); } @@ -1995,9 +2019,11 @@ static void nand_write(int argc, char *argv[]) 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)) { @@ -2017,7 +2043,7 @@ static void nand_write(int argc, char *argv[]) } 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; } @@ -2105,7 +2131,7 @@ static void nand_erase(int argc, char *argv[]) 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; } @@ -2114,19 +2140,26 @@ static void nand_erase(int argc, char *argv[]) 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); @@ -2150,7 +2183,7 @@ static void nand_scan(int argc, char *argv[]) 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; } @@ -2353,29 +2386,24 @@ static void print_page(u32 addr, bool spare_only) 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"); } }