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. ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/