diff options
-rw-r--r-- | drivers/nvmem/sprd-efuse.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/nvmem/sprd-efuse.c b/drivers/nvmem/sprd-efuse.c index 7a189ef52333..43b3f6ef8c20 100644 --- a/drivers/nvmem/sprd-efuse.c +++ b/drivers/nvmem/sprd-efuse.c @@ -217,12 +217,14 @@ static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub, * Enable the auto-check function to validate if the programming is * successful. */ - sprd_efuse_set_auto_check(efuse, true); + if (lock) + sprd_efuse_set_auto_check(efuse, true); writel(*data, efuse->base + SPRD_EFUSE_MEM(blk)); /* Disable auto-check and data double after programming */ - sprd_efuse_set_auto_check(efuse, false); + if (lock) + sprd_efuse_set_auto_check(efuse, false); sprd_efuse_set_data_double(efuse, false); /* @@ -237,7 +239,7 @@ static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub, writel(SPRD_EFUSE_ERR_CLR_MASK, efuse->base + SPRD_EFUSE_ERR_CLR); ret = -EBUSY; - } else { + } else if (lock) { sprd_efuse_set_prog_lock(efuse, lock); writel(0, efuse->base + SPRD_EFUSE_MEM(blk)); sprd_efuse_set_prog_lock(efuse, false); @@ -322,6 +324,7 @@ unlock: static int sprd_efuse_write(void *context, u32 offset, void *val, size_t bytes) { struct sprd_efuse *efuse = context; + bool lock; int ret; ret = sprd_efuse_lock(efuse); @@ -332,7 +335,20 @@ static int sprd_efuse_write(void *context, u32 offset, void *val, size_t bytes) if (ret) goto unlock; - ret = sprd_efuse_raw_prog(efuse, offset, false, false, val); + /* + * If the writing bytes are equal with the block width, which means the + * whole block will be programmed. For this case, we should not allow + * this block to be programmed again by locking this block. + * + * If the block was programmed partially, we should allow this block to + * be programmed again. + */ + if (bytes < SPRD_EFUSE_BLOCK_WIDTH) + lock = false; + else + lock = true; + + ret = sprd_efuse_raw_prog(efuse, offset, false, lock, val); clk_disable_unprepare(efuse->clk); |