From 6dbbc8affb6ab22f940d13d0e928d5e881127ca4 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Mon, 25 Jul 2022 11:22:57 +0800 Subject: [PATCH 44/71] cmd: mtd: add markbad subcommand for NMBM testing This patch adds: * Mark bad block on lower mtd device and erase on upper mtd device, which will trigger remapping: $ mtd markbad spi-nand0 0x20000 (mark block1 as bad) $ mtd erase nmbm0 0x20000 0x20000 (let nmbm detect the bad block and remap it) * Clear bad block mark through: $ mtd erase.dontskipbad spi-nand0 0x20000 0x20000 (After cleaning bad block mark, we need to rebuild nmbm manage table.) Signed-off-by: SkyLake.Huang --- cmd/mtd.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) --- a/cmd/mtd.c +++ b/cmd/mtd.c @@ -504,6 +504,42 @@ out_put_mtd: return CMD_RET_SUCCESS; } +static int do_mtd_markbad(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct mtd_info *mtd; + loff_t off; + int ret; + + if (argc < 3) + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR(mtd) || !mtd) + return CMD_RET_FAILURE; + + if (!mtd_can_have_bb(mtd)) { + printf("Only NAND-based devices can have mark blocks\n"); + goto out_put_mtd; + } + + off = simple_strtoull(argv[2], NULL, 0); + + ret = mtd_block_markbad(mtd, off); + if (!ret) { + printf("MTD device %s block at 0x%08llx marked bad\n", + mtd->name, off); + } else { + printf("MTD device %s block at 0x%08llx mark bad failed\n", + mtd->name, off); + } + +out_put_mtd: + put_mtd_device(mtd); + + return CMD_RET_SUCCESS; +} + #ifdef CONFIG_AUTO_COMPLETE static int mtd_name_complete(int argc, char *const argv[], char last_char, int maxv, char *cmdv[]) @@ -551,6 +587,7 @@ U_BOOT_LONGHELP(mtd, "\n" "Specific functions:\n" "mtd bad \n" + "mtd markbad \n" "\n" "With:\n" "\t: NAND partition/chip name (or corresponding DM device name or OF path)\n" @@ -575,4 +612,6 @@ U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils" U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase, mtd_name_complete), U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad, + mtd_name_complete), + U_BOOT_SUBCMD_MKENT_COMPLETE(markbad, 3, 1, do_mtd_markbad, mtd_name_complete));