summaryrefslogtreecommitdiff
path: root/drivers/mtd/spi-nor
diff options
context:
space:
mode:
authorTudor Ambarus <tudor.ambarus@microchip.com>2020-03-23 08:29:29 +0300
committerTudor Ambarus <tudor.ambarus@microchip.com>2020-03-24 08:44:00 +0300
commitb0e2d252f9280835a24e007dcd6feaef5a8809cd (patch)
tree43a9ca9d38be8c5e7c6f982c1b694e11e0bfb134 /drivers/mtd/spi-nor
parent5bb783cc92f0da8c36c8cc288d586a4ceb6c742a (diff)
downloadlinux-b0e2d252f9280835a24e007dcd6feaef5a8809cd.tar.xz
mtd: spi-nor: Set all BP bits to one when lock_len == mtd->size
When there are more BP settings than needed for defining the protected areas of the flash memory, most flashes will define the remaining settings as "protect all", i.e. the equivalent of having all the BP bits set to one. But there are flashes where the in-between BP values are undefined (not mentioned), and only the "all bits set" is protecting the entire memory. One such example is w25q80, where BP[2:0]=0b101 and 0b110 are not defined. Set all the BP bits to one when lock_len == mtd->size, to treat this special case. Suggested-by: Michael Walle <michael@walle.cc> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Reviewed-by: Jungseung Lee <js07.lee@samsung.com> Reviewed-by: Michael Walle <michael@walle.cc>
Diffstat (limited to 'drivers/mtd/spi-nor')
-rw-r--r--drivers/mtd/spi-nor/core.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index e0021dd34bfe..bc57b1b5ec62 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1682,13 +1682,19 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
*
* pow = ceil(log2(size / len)) = log2(size) - floor(log2(len))
*/
- pow = ilog2(mtd->size) - ilog2(lock_len);
- val = mask - (pow << SR_BP_SHIFT);
- if (val & ~mask)
- return -EINVAL;
- /* Don't "lock" with no region! */
- if (!(val & mask))
- return -EINVAL;
+ if (lock_len == mtd->size) {
+ val = mask;
+ } else {
+ pow = ilog2(mtd->size) - ilog2(lock_len);
+ val = mask - (pow << SR_BP_SHIFT);
+
+ if (val & ~mask)
+ return -EINVAL;
+
+ /* Don't "lock" with no region! */
+ if (!(val & mask))
+ return -EINVAL;
+ }
status_new = (status_old & ~mask & ~tb_mask) | val;