RE: [PATCH] mtd: spi-nor: allow force unlocking via DT property

From: Takahiro.Kuwano

Date: Thu Aug 06 2026 - 01:41:28 EST


Hi,

> Some SPI NOR flash chips (such as generic or unlisted chips used in vendor
> devices like Tenda AX12L Pro) have Block Protection (BP) bits set in the
> Status Register by bootloaders or factory settings, locking flash blocks.
>
> Because vendors frequently switch between various generic SPI NOR flash
> chips ("Flash Lottery"), it is impractical to upstream explicit chip ID
> flags (SNOR_F_HAS_LOCK) for every possible generic chip variant.
>
> This patch introduces support for the "linux,force-sr-unlock" Device Tree
> property:
> 1. In spi_nor_init(), trigger spi_nor_try_unlock_all() if "linux,force-sr-unlock"
> is present in the flash DT node, even when CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE
> is active and the chip is non-volatile.
> 2. In spi_nor_try_unlock_all(), bypass the SNOR_F_HAS_LOCK flag check when
> "linux,force-sr-unlock" is specified, ensure locking_ops are initialized,
> and invoke Linux kernel's native spi_nor_unlock() mechanism.

Does this work for generic(unlisted) SPI NOR flash chips with 4-bit BP
and/or CMP bit? I think we need to rely on ID database to know what block
protection bits are available in the chip.

>
> Signed-off-by: Chen Minqiang <ptpt52@xxxxxxxxx>
> ---
> drivers/mtd/spi-nor/core.c | 3 ++-
> drivers/mtd/spi-nor/swp.c | 7 ++++++-
> 2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index ccf4396cdcd0..ef0bdc1254bb 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -3332,7 +3332,8 @@ static int spi_nor_init(struct spi_nor *nor)
> spi_nor_cache_sr_lock_bits(nor, NULL);
> if (IS_ENABLED(CONFIG_MTD_SPI_NOR_SWP_DISABLE) ||
> (IS_ENABLED(CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE) &&
> - nor->flags & SNOR_F_SWP_IS_VOLATILE)) {
> + nor->flags & SNOR_F_SWP_IS_VOLATILE) ||
> + of_property_read_bool(spi_nor_get_flash_node(nor), "linux,force-sr-unlock")) {
> spi_nor_try_unlock_all(nor);
> }
>
> diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c
> index 235070b215d1..a190d10c1630 100644
> --- a/drivers/mtd/spi-nor/swp.c
> +++ b/drivers/mtd/spi-nor/swp.c
> @@ -628,11 +628,16 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, u64 len)
> */
> void spi_nor_try_unlock_all(struct spi_nor *nor)
> {
> + struct device_node *np = spi_nor_get_flash_node(nor);
> + bool force_unlock = of_property_read_bool(np, "linux,force-sr-unlock");
> int ret;
>
> - if (!(nor->flags & SNOR_F_HAS_LOCK))
> + if (!(nor->flags & SNOR_F_HAS_LOCK) && !force_unlock)
> return;
>
> + if (!nor->params->locking_ops)
> + spi_nor_init_default_locking_ops(nor);
> +
> dev_dbg(nor->dev, "Unprotecting entire flash array\n");
>
> ret = spi_nor_unlock(&nor->mtd, 0, nor->params->size);
> --
> 2.17.1

Thanks,
Takahiro