#include <malloc.h>
#include <mapmem.h>
#include <mtd.h>
+#include <dm/devres.h>
+#include <linux/err.h>
#include <linux/ctype.h>
printf(" - driver: %s\n", mtd->dev->driver->name);
}
#endif
+ if (IS_ENABLED(CONFIG_OF_CONTROL) && mtd->dev) {
+ char buf[256];
+ int res;
+
+ res = ofnode_get_path(mtd_get_ofnode(mtd), buf, 256);
+ printf(" - path: %s\n", res == 0 ? buf : "unavailable");
+ }
/* MTD device information */
printf(" - type: ");
return true;
}
-static int do_mtd_list(cmd_tbl_t *cmdtp, int flag, int argc,
- char * const argv[])
+static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
struct mtd_info *mtd;
int dev_nb = 0;
return ret;
}
-static int do_mtd_io(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mtd_io(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
bool dump, read, raw, woob, write_empty_pages, has_pages = false;
u64 start_off, off, len, remaining, default_len;
goto out_put_mtd;
}
- user_addr = simple_strtoul(argv[0], NULL, 16);
+ user_addr = hextoul(argv[0], NULL);
argc--;
argv++;
}
- start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
+ start_off = argc > 0 ? hextoul(argv[0], NULL) : 0;
if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) {
printf("Offset not aligned with a page (0x%x)\n",
mtd->writesize);
}
default_len = dump ? mtd->writesize : mtd->size;
- len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : default_len;
+ len = argc > 1 ? hextoul(argv[1], NULL) : default_len;
if (!mtd_is_aligned_with_min_io_size(mtd, len)) {
len = round_up(len, mtd->writesize);
printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n",
return ret;
}
-static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
- char * const argv[])
+static int do_mtd_erase(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
struct erase_info erase_op = {};
struct mtd_info *mtd;
u64 off, len;
bool scrub;
- int ret;
+ int ret = 0;
if (argc < 2)
return CMD_RET_USAGE;
argc -= 2;
argv += 2;
- off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
- len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size;
+ off = argc > 0 ? hextoul(argv[0], NULL) : 0;
+ len = argc > 1 ? hextoul(argv[1], NULL) : mtd->size;
if (!mtd_is_aligned_with_block_size(mtd, off)) {
printf("Offset not aligned with a block (0x%x)\n",
erase_op.mtd = mtd;
erase_op.addr = off;
- erase_op.len = len;
+ erase_op.len = mtd->erasesize;
erase_op.scrub = scrub;
- while (erase_op.len) {
+ while (len) {
ret = mtd_erase(mtd, &erase_op);
- /* Abort if its not a bad block error */
- if (ret != -EIO)
- break;
-
- printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
+ if (ret) {
+ /* Abort if its not a bad block error */
+ if (ret != -EIO)
+ break;
+ printf("Skipping bad block at 0x%08llx\n",
+ erase_op.addr);
+ }
- /* Skip bad block and continue behind it */
- erase_op.len -= erase_op.fail_addr - erase_op.addr;
- erase_op.len -= mtd->erasesize;
- erase_op.addr = erase_op.fail_addr + mtd->erasesize;
+ len -= mtd->erasesize;
+ erase_op.addr += mtd->erasesize;
}
if (ret && ret != -EIO)
return ret;
}
-static int do_mtd_bad(cmd_tbl_t *cmdtp, int flag, int argc,
- char * const argv[])
+static int do_mtd_bad(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
{
struct mtd_info *mtd;
loff_t off;
}
#ifdef CONFIG_AUTO_COMPLETE
-static int mtd_name_complete(int argc, char * const argv[], char last_char,
+static int mtd_name_complete(int argc, char *const argv[], char last_char,
int maxv, char *cmdv[])
{
int len = 0, n_found = 0;
"mtd bad <name>\n"
"\n"
"With:\n"
- "\t<name>: NAND partition/chip name\n"
+ "\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n"
"\t<addr>: user address from/to which data will be retrieved/stored\n"
"\t<off>: offset in <name> in bytes (default: start of the part)\n"
"\t\t* must be block-aligned for erase\n"