diff options
author | Aaron Sierra <asierra@xes-inc.com> | 2017-12-05 21:13:44 +0300 |
---|---|---|
committer | Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> | 2017-12-13 02:36:00 +0300 |
commit | 2666067fdba26a0a87cf50bb38f5a73aabd0f517 (patch) | |
tree | dc1a09cb8202e95f8aa4c3ecf0800d3f9a57e2af /drivers/mtd/spi-nor/spi-nor.c | |
parent | 20ccb993f29bd6ad17699dd0b349db086e3ca719 (diff) | |
download | linux-2666067fdba26a0a87cf50bb38f5a73aabd0f517.tar.xz |
mtd: spi-nor: Check that BP bits are set properly
Previously, the lock and unlock functions returned success even if the
BP bits were not actually updated in the status register due to
hardware write protection. Introduce write_sr_and_check() to write and
read back the status register to ensure the desired BP bits are
actually set as requested.
Signed-off-by: Joe Schultz <jschultz@xes-inc.com>
Signed-off-by: Aaron Sierra <asierra@xes-inc.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
Diffstat (limited to 'drivers/mtd/spi-nor/spi-nor.c')
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 07d040ff574b..1e4b4dfe26b5 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -566,6 +566,27 @@ erase_err: return ret; } +/* Write status register and ensure bits in mask match written values */ +static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) +{ + int ret; + + write_enable(nor); + ret = write_sr(nor, status_new); + if (ret) + return ret; + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + ret = read_sr(nor); + if (ret < 0) + return ret; + + return ((ret & mask) != (status_new & mask)) ? -EIO : 0; +} + static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, uint64_t *len) { @@ -664,7 +685,6 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; - int ret; status_old = read_sr(nor); if (status_old < 0) @@ -728,11 +748,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) if ((status_new & mask) < (status_old & mask)) return -EINVAL; - write_enable(nor); - ret = write_sr(nor, status_new); - if (ret) - return ret; - return spi_nor_wait_till_ready(nor); + return write_sr_and_check(nor, status_new, mask); } /* @@ -749,7 +765,6 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; - int ret; status_old = read_sr(nor); if (status_old < 0) @@ -816,11 +831,7 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) if ((status_new & mask) > (status_old & mask)) return -EINVAL; - write_enable(nor); - ret = write_sr(nor, status_new); - if (ret) - return ret; - return spi_nor_wait_till_ready(nor); + return write_sr_and_check(nor, status_new, mask); } /* |