[PATCH] sf: Add lock info option to sf command list
Simon Glass
sjg at chromium.org
Fri Aug 9 17:57:48 CEST 2024
Hi Venkatesh,
On Fri, 9 Aug 2024 at 03:39, Venkatesh Yadav Abbarapu
<venkatesh.abbarapu at amd.com> wrote:
>
> 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(-)
Please can you add to doc/usage/cmd/sf.c and extend the test in
test/dm/sf.c ? Let me know if you need help with the test.
>
> 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;
Shouldn't be needed, see below.
> +
> + 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 0 is better than CMD_RET_SUCCESS, to avoid confusion that
success might be anything other than 0.
> + }
> +
> + 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);
Eek this is a mess. Before adding your feature, please create a patch
to refactor this code to use U_BOOT_CMD_WITH_SUBCMDS() like other
commands with subcommands.
> 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);
Are we trying to keep this in sync with Linux mtd? It seems that Linux
has split these ops into a separate struct. We should really be using
an MTD uclass here, I suspect. But that is another discussion...
We have these members:
int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
int (*flash_is_unlocked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
int (*quad_enable)(struct spi_nor *nor);
int (*octal_dtr_enable)(struct spi_nor *nor);
int (*ready)(struct spi_nor *nor);
It seems to me that we need to sort this out a bit one day. But for
now (and your patch), how about a lock_info() call which fills in a
new 'struct spi_nor_info' with all the useful info? Then you can put
your bool in that struct and we can extend it to other things as
needed.
>
> 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
>
Regards,
SImon
More information about the U-Boot
mailing list