mtd: spi-nor: allow force unlocking via DT property
Subsystems (2)
PATCH 1/1 mtd: spi-nor: allow force unlocking via DT property
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.
--- drivers/mtd/spi-nor/core.c | 3 ++- drivers/mtd/spi-nor/swp.c | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/mtd/spi-nor/core.c +2 -1
@@ -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); }
drivers/mtd/spi-nor/swp.c +6 -1
@@ -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);
Signature · 1 line
2.17.1
[email protected]
reviewerHi,
Quoted 8 lines
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.
Quoted 8 lines
This patch introduces support for the "linux,force-sr-unlock" Device Tree property:
1. Inspi_nor_init(), triggerspi_nor_try_unlock_all()if "linux,force-sr-unlock" is present in the flash DT node, even whenCONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILEis active and the chip is non-volatile.
2. Inspi_nor_try_unlock_all(), bypass theSNOR_F_HAS_LOCKflag check when "linux,force-sr-unlock" is specified, ensurelocking_opsare initialized, and invoke Linux kernel's nativespi_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.
Quoted 44 lines
Signed-off-by Chen Minqiang <[email protected]>--- drivers/mtd/spi-nor/core.c | 3 ++- drivers/mtd/spi-nor/swp.c | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-)drivers/mtd/spi-nor/core.c +2
-1@@ -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); }drivers/mtd/spi-nor/swp.c +6
-2@@ -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); --
Quoted 1 line
2.17.1
Thanks,
Takahiro