[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