[PATCH v1 4/7] write WPEN bit for SST26* devices when locking

Jagan Teki jagan at amarulasolutions.com
Fri Feb 26 10:56:13 CET 2021


On Thu, Jan 28, 2021 at 9:59 PM Bernhard Kirchen <schlimmchen at gmail.com> wrote:
>
> "sf protect lock" did only protect against accidental writes by
> software. it did not lock down the config or block-protection registers
> if the WP# pin was deasserted. hardware write protection was never
> enabled for these devices.
>
> this change implements setting the WPEN bit and clearing the IOC bit in
> SST26* devices' config register if any block is protected by "sf protect
> lock" command, thus enabling hardware write protection. this behavior is
> similar to the "sf protect lock" implementation for Micron (and
> compatible) chips.
>
> Signed-off-by: Bernhard Kirchen <bernhard.kirchen at mbconnectline.com>
> ---
>
>  drivers/mtd/spi/spi-nor-core.c | 64 ++++++++++++++++++++++++++++++++--
>  include/linux/mtd/spi-nor.h    |  1 +
>  2 files changed, 63 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> index 050aeac3fa..10c01cf20e 100644
> --- a/drivers/mtd/spi/spi-nor-core.c
> +++ b/drivers/mtd/spi/spi-nor-core.c
> @@ -185,7 +185,9 @@ static int read_fsr(struct spi_nor *nor)
>   * location. Return the configuration register value.
>   * Returns negative if error occurred.
>   */
> -#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
> +#if defined(CONFIG_SPI_FLASH_SPANSION) || \
> +       defined(CONFIG_SPI_FLASH_WINBOND) || \
> +       defined(CONFIG_SPI_FLASH_SST)
>  static int read_cr(struct spi_nor *nor)
>  {
>         int ret;
> @@ -972,6 +974,8 @@ read_err:
>  #define SST26_MAX_BPR_REG_LEN          (18 + 1)
>  #define SST26_BOUND_REG_SIZE           ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K)
>
> +static int write_cr(struct spi_nor *nor, u8 value);
> +
>  enum lock_ctl {
>         SST26_CTL_LOCK,
>         SST26_CTL_UNLOCK,
> @@ -994,6 +998,35 @@ static bool sst26_process_bpr(u32 bpr_size, u8 *cmd, u32 bit, enum lock_ctl ctl)
>         return false;
>  }
>
> +static int sst26_hardware_write_protection(struct spi_nor *nor, bool lock)
> +{
> +       int ret;
> +       u8 cr_val;
> +
> +       cr_val = read_cr(nor);
> +       if (cr_val < 0) {
> +               dev_err(nor->dev, "fail to read config register value\n");
> +               return cr_val;
> +       }
> +
> +       cr_val &= ~CR_WPEN;
> +
> +       if (lock) {
> +               // disallow further writes if WP# pin is not asserted.
> +               cr_val |= CR_WPEN;
> +               // force quad SPI disabled as otherwise WP# pin works as data line.
> +               cr_val &= ~CR_QUAD_EN_SPAN;
> +       }
> +
> +       ret = write_cr(nor, cr_val);
> +       if (ret < 0) {
> +               dev_err(nor->dev, "fail to configure WP# pin (hardware write protection)\n");
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
>  /*
>   * Lock, unlock or check lock status of the flash region of the flash (depending
>   * on the lock_ctl value)
> @@ -1101,6 +1134,14 @@ static int sst26_lock_ctl(struct spi_nor *nor, loff_t ofs, uint64_t len, enum lo
>                 return ret;
>         }
>
> +       // enable hardware write protection iff any protection bit is set
> +       for (i = 0; i < bpr_size; ++i)
> +               if (bpr_buff[i] != 0)
> +                       break;

This looks odd to traverse the list to find the protection bit set,
better to check the locked range something it was done in stmicro
flash chips.


More information about the U-Boot mailing list