[PATCH] sf: Add lock info option to sf command list

Venkatesh Yadav Abbarapu venkatesh.abbarapu at amd.com
Fri Aug 9 11:38:41 CEST 2024


Many SPI flashes have status/OTP bit for TOP or BOTTOM selection
in the status register that can protect selected regions of
the SPI NOR.

Take this bit into consideration while locking the region.
The command "sf lockinfo" shows whether the flash is TOP or
BOTTOM protected, based on this info the "offset" is provided to
the "sf protect lock" command.

Versal> sf erase 0 100000
SF: 1048576 bytes @ 0x0 Erased: OK
Versal>sf lockinfo
Flash is BOTTOM protected
Versal> sf protect lock 0 20000
Versal> sf erase 0 20000
ERROR: flash area is locked
Versal> sf protect unlock 0 20000
Versal> sf erase 0 20000
SF: 131072 bytes @ 0x0 Erased: OK

Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu at amd.com>
---
 cmd/sf.c                       | 30 +++++++++++++++++++++++++++++-
 drivers/mtd/spi/spi-nor-core.c | 16 ++++++++++++++++
 include/linux/mtd/spi-nor.h    |  1 +
 include/spi.h                  |  3 +++
 include/spi_flash.h            |  8 ++++++++
 5 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/cmd/sf.c b/cmd/sf.c
index f43a2e08b3..62afa91057 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -413,6 +413,30 @@ static int do_spi_protect(int argc, char *const argv[])
 	return ret == 0 ? 0 : 1;
 }
 
+static int do_spi_lock_info(int argc, char *const argv[])
+{
+	int ret;
+
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	ret = spi_flash_lock_info(flash);
+	if (ret < 0) {
+		printf("Flash info is not set\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (ret == BOTTOM_PROTECT) {
+		printf("Flash is BOTTOM protected\n");
+		return CMD_RET_SUCCESS;
+	} else if (ret == TOP_PROTECT) {
+		printf("Flash is TOP protected\n");
+		return CMD_RET_SUCCESS;
+	}
+
+	return CMD_RET_FAILURE;
+}
+
 enum {
 	STAGE_ERASE,
 	STAGE_CHECK,
@@ -607,6 +631,8 @@ static int do_spi_flash(struct cmd_tbl *cmdtp, int flag, int argc,
 		ret = do_spi_flash_erase(argc, argv);
 	else if (IS_ENABLED(CONFIG_SPI_FLASH_LOCK) && strcmp(cmd, "protect") == 0)
 		ret = do_spi_protect(argc, argv);
+	else if (IS_ENABLED(CONFIG_SPI_FLASH_LOCK) && strcmp(cmd, "lockinfo") == 0)
+		ret = do_spi_lock_info(argc, argv);
 	else if (IS_ENABLED(CONFIG_CMD_SF_TEST) && !strcmp(cmd, "test"))
 		ret = do_spi_flash_test(argc, argv);
 	else
@@ -632,7 +658,9 @@ U_BOOT_LONGHELP(sf,
 	"					  or to start of mtd `partition'\n"
 #ifdef CONFIG_SPI_FLASH_LOCK
 	"sf protect lock/unlock sector len	- protect/unprotect 'len' bytes starting\n"
-	"					  at address 'sector'"
+	"					  at address 'sector'\n"
+	"sf lockinfo				- shows whether the flash locking is top or bottom\n"
+	"					  protected\n"
 #endif
 #ifdef CONFIG_CMD_SF_TEST
 	"\nsf test offset len		- run a very basic destructive test"
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index aea611fef5..2114be1e61 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -1410,6 +1410,21 @@ static int stm_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len)
 
 	return stm_is_unlocked_sr(nor, ofs, len, status);
 }
+
+static bool stm_lock_info(struct spi_nor *nor)
+{
+	int status;
+
+	status = read_sr(nor);
+	if (status < 0)
+		return status;
+
+	if (status & SR_TB)
+		return BOTTOM_PROTECT;
+
+	return TOP_PROTECT;
+}
+
 #endif /* CONFIG_SPI_FLASH_STMICRO */
 #endif
 
@@ -4145,6 +4160,7 @@ int spi_nor_scan(struct spi_nor *nor)
 		nor->flash_lock = stm_lock;
 		nor->flash_unlock = stm_unlock;
 		nor->flash_is_unlocked = stm_is_unlocked;
+		nor->flash_lock_info = stm_lock_info;
 	}
 #endif
 
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d1dbf3eadb..48d39a7052 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -580,6 +580,7 @@ struct spi_nor {
 	int (*quad_enable)(struct spi_nor *nor);
 	int (*octal_dtr_enable)(struct spi_nor *nor);
 	int (*ready)(struct spi_nor *nor);
+	bool (*flash_lock_info)(struct spi_nor *nor);
 
 	struct {
 		struct spi_mem_dirmap_desc *rdesc;
diff --git a/include/spi.h b/include/spi.h
index 7e38cc2a2a..46d27f7564 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -38,6 +38,9 @@
 
 #define SPI_DEFAULT_WORDLEN	8
 
+#define BOTTOM_PROTECT		1
+#define TOP_PROTECT		0
+
 /**
  * struct dm_spi_bus - SPI bus info
  *
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 10d19fd4b1..b8a6456fe4 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -202,4 +202,12 @@ static inline int spi_flash_protect(struct spi_flash *flash, u32 ofs, u32 len,
 		return flash->flash_unlock(flash, ofs, len);
 }
 
+static inline int spi_flash_lock_info(struct spi_flash *flash)
+{
+	if (!flash->flash_lock_info)
+		return -EOPNOTSUPP;
+
+	return flash->flash_lock_info(flash);
+}
+
 #endif /* _SPI_FLASH_H_ */
-- 
2.17.1



More information about the U-Boot mailing list