nvmem: sprd: Optimize the block lock operation
[linux-2.6-microblaze.git] / drivers / nvmem / sprd-efuse.c
index 7a189ef..43b3f6e 100644 (file)
@@ -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);