Skip to content
  • Michael Walle's avatar
    31ad3eff
    mtd: spi-nor: keep lock bits if they are non-volatile · 31ad3eff
    Michael Walle authored
    
    
    Traditionally, Linux unlocks the whole flash because there are legacy
    devices which has the write protection bits set by default at startup.
    If you actually want to use the flash protection bits, eg. because there
    is a read-only part for a bootloader, this automatic unlocking is
    harmful. If there is no hardware write protection in place (usually
    called WP#), a startup of the kernel just discards this protection.
    
    I've gone through the datasheets of all the flashes (except the Intel
    ones where I could not find any datasheet nor reference) which supports
    the unlocking feature and looked how the sector protection was
    implemented. The currently supported flashes can be divided into the
    following two categories:
     (1) block protection bits are non-volatile. Thus they keep their values
         at reset and power-cycle
     (2) flashes where these bits are volatile. After reset or power-cycle,
         the whole memory array is protected.
         (a) some devices needs a special "Global Unprotect" command, eg.
             the Atmel AT25DF041A.
         (b) some devices require to clear the BPn bits in the status
             register.
    
    Due to the reasons above, we do not want to clear the bits for flashes
    which belong to category (1). Fortunately for us, only Atmel flashes
    fall into category (2a). Implement the "Global Protect" and "Global
    Unprotect" commands for these. For (2b) we can use normal block
    protection locking scheme.
    
    This patch adds a new flag to indicate the case (2). Only if we have
    such a flash we unlock the whole flash array. To be backwards compatible
    it also introduces a kernel configuration option which restores the
    complete legacy behavior ("Disable write protection on any flashes").
    Hopefully, this will clean up "unlock the entire flash for legacy
    devices" once and for all.
    
    For reference here are the actually commits which introduced the legacy
    behavior (and extended the behavior to other chip manufacturers):
    
    commit f80e521c ("mtd: m25p80: add support for the Intel/Numonyx {16,32,64}0S33B SPI flash chips")
    commit ea60658a ("mtd: m25p80: disable SST software protection bits by default")
    commit 72289824 ("[MTD] m25p80: fix bug - ATmel spi flash fails to be copied to")
    
    Actually, this might also fix handling of the Atmel AT25DF flashes,
    because the original commit 72289824 ("[MTD] m25p80: fix bug -
    ATmel spi flash fails to be copied to") was writing a 0 to the status
    register, which is a "Global Unprotect". This might not be the case in
    the current code which only handles the block protection bits BP2, BP1
    and BP0. Thus, it depends on the current contents of the status register
    if this unlock actually corresponds to a "Global Unprotect" command. In
    the worst case, the current code might leave the AT25DF flashes in a
    write protected state.
    
    The commit 191f5c2e ("mtd: spi-nor: use 16-bit WRR command when QE
    is set on spansion flashes") changed that behavior by just clearing BP2
    to BP0 instead of writing a 0 to the status register.
    
    Further, the commit 3e0930f1 ("mtd: spi-nor: Rework the disabling
    of block write protection") expanded the unlock_all() feature to ANY
    flash which supports locking.
    
    Signed-off-by: default avatarMichael Walle <michael@walle.cc>
    Signed-off-by: default avatarVignesh Raghavendra <vigneshr@ti.com>
    Reviewed-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
    Link: https://lore.kernel.org/r/20201203162959.29589-8-michael@walle.cc
    31ad3eff
    mtd: spi-nor: keep lock bits if they are non-volatile
    Michael Walle authored
    
    
    Traditionally, Linux unlocks the whole flash because there are legacy
    devices which has the write protection bits set by default at startup.
    If you actually want to use the flash protection bits, eg. because there
    is a read-only part for a bootloader, this automatic unlocking is
    harmful. If there is no hardware write protection in place (usually
    called WP#), a startup of the kernel just discards this protection.
    
    I've gone through the datasheets of all the flashes (except the Intel
    ones where I could not find any datasheet nor reference) which supports
    the unlocking feature and looked how the sector protection was
    implemented. The currently supported flashes can be divided into the
    following two categories:
     (1) block protection bits are non-volatile. Thus they keep their values
         at reset and power-cycle
     (2) flashes where these bits are volatile. After reset or power-cycle,
         the whole memory array is protected.
         (a) some devices needs a special "Global Unprotect" command, eg.
             the Atmel AT25DF041A.
         (b) some devices require to clear the BPn bits in the status
             register.
    
    Due to the reasons above, we do not want to clear the bits for flashes
    which belong to category (1). Fortunately for us, only Atmel flashes
    fall into category (2a). Implement the "Global Protect" and "Global
    Unprotect" commands for these. For (2b) we can use normal block
    protection locking scheme.
    
    This patch adds a new flag to indicate the case (2). Only if we have
    such a flash we unlock the whole flash array. To be backwards compatible
    it also introduces a kernel configuration option which restores the
    complete legacy behavior ("Disable write protection on any flashes").
    Hopefully, this will clean up "unlock the entire flash for legacy
    devices" once and for all.
    
    For reference here are the actually commits which introduced the legacy
    behavior (and extended the behavior to other chip manufacturers):
    
    commit f80e521c ("mtd: m25p80: add support for the Intel/Numonyx {16,32,64}0S33B SPI flash chips")
    commit ea60658a ("mtd: m25p80: disable SST software protection bits by default")
    commit 72289824 ("[MTD] m25p80: fix bug - ATmel spi flash fails to be copied to")
    
    Actually, this might also fix handling of the Atmel AT25DF flashes,
    because the original commit 72289824 ("[MTD] m25p80: fix bug -
    ATmel spi flash fails to be copied to") was writing a 0 to the status
    register, which is a "Global Unprotect". This might not be the case in
    the current code which only handles the block protection bits BP2, BP1
    and BP0. Thus, it depends on the current contents of the status register
    if this unlock actually corresponds to a "Global Unprotect" command. In
    the worst case, the current code might leave the AT25DF flashes in a
    write protected state.
    
    The commit 191f5c2e ("mtd: spi-nor: use 16-bit WRR command when QE
    is set on spansion flashes") changed that behavior by just clearing BP2
    to BP0 instead of writing a 0 to the status register.
    
    Further, the commit 3e0930f1 ("mtd: spi-nor: Rework the disabling
    of block write protection") expanded the unlock_all() feature to ANY
    flash which supports locking.
    
    Signed-off-by: default avatarMichael Walle <michael@walle.cc>
    Signed-off-by: default avatarVignesh Raghavendra <vigneshr@ti.com>
    Reviewed-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
    Link: https://lore.kernel.org/r/20201203162959.29589-8-michael@walle.cc
Loading