[PATCH v3 v3 3/3] mtd: spi-nor: add locking support for is25xxxxx device

From: Sagar Shrikant Kadam
Date: Tue May 07 2019 - 12:03:17 EST


Implement a basic locking scheme for ISSI devices similar to that of
stm_lock mechanism. The is25xxxxx devices have 4 bits for selecting
the range of blocks to be locked/protected from erase/write.

The current implementation enables block protection as per the table
defined into datasheet for is25wp256d device.

Signed-off-by: Sagar Shrikant Kadam <sagar.kadam@xxxxxxxxxx>
---
drivers/mtd/spi-nor/spi-nor.c | 51 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 3942b26..5986260 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1459,6 +1459,56 @@ static int macronix_quad_enable(struct spi_nor *nor)

return 0;
}
+/**
+ * issi_lock() - set BP[0123] write-protection.
+ * @nor: pointer to a 'struct spi_nor'.
+ * @ofs: offset from which to lock memory.
+ * @len: number of bytes to unlock.
+ *
+ * Lock a region of the flash.Implementation is based on stm_lock
+ * Supports the block protection bits BP{0,1,2,3} in the status register
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int issi_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ int status_old, status_new, blk_prot;
+ u8 mask = SR_BP3 | SR_BP2 | SR_BP1 | SR_BP0;
+ u8 shift = ffs(mask) - 1;
+ u8 pow;
+ loff_t num_blks;
+
+ status_old = read_sr(nor);
+
+ /* if status reg is Write protected don't update bit protection */
+ if (status_old & SR_SRWD) {
+ dev_err(nor->dev,
+ "Status register is Write Protected, can't lock bit
+ protection bits...\n");
+ return -EINVAL;
+ }
+ num_blks = len / nor->info->sector_size;
+
+ pow = order_base_2(num_blks);
+
+ blk_prot = mask & (((pow+1) & 0xf)<<shift);
+
+ /*
+ * Return if older protected blocks include the new requested block's
+ */
+ if (((status_old >> shift) & 0x0f) > blk_prot) {
+ dev_info(nor->dev, "newly requested blocks are
+ already protected ");
+ return 0;
+ }
+
+ status_new = status_old | blk_prot;
+
+ if (status_old == status_new)
+ return 0;
+
+ return write_sr_and_check(nor, status_new, mask);
+}

/**
* issi_unlock() - clear BP[0123] write-protection.
@@ -4124,6 +4174,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
/* NOR protection support for ISSI chips */
if (JEDEC_MFR(info) == SNOR_MFR_ISSI ||
info->flags & SPI_NOR_HAS_LOCK) {
+ nor->flash_lock = issi_lock;
nor->flash_unlock = issi_unlock;

}
--
1.9.1


--
The information transmitted is intended only for the person or entity to
which it is addressed and may contain confidential and/or privileged
material. If you are not the intended recipient of this message please do
not read, copy, use or disclose this communication and notify the sender
immediately. It should be noted that any review, retransmission,
dissemination or other use of, or taking action or reliance upon, this
information by persons or entities other than the intended recipient is
prohibited.