From 6dbbc8affb6ab22f940d13d0e928d5e881127ca4 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
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 <skylake.huang@mediatek.com>
---
 cmd/mtd.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -492,6 +492,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[])
@@ -540,6 +576,7 @@ static char mtd_help_text[] =
 	"\n"
 	"Specific functions:\n"
 	"mtd bad                               <name>\n"
+	"mtd markbad                           <name> <off>\n"
 	"\n"
 	"With:\n"
 	"\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n"
@@ -565,4 +602,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));
