Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / arch / arm / mach-bcmbca / otp / skp_hw.c
diff --git a/arch/arm/mach-bcmbca/otp/skp_hw.c b/arch/arm/mach-bcmbca/otp/skp_hw.c
new file mode 100644 (file)
index 0000000..9e1ea04
--- /dev/null
@@ -0,0 +1,955 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright 2020 Broadcom Ltd.
+ */
+/**********************************************************************
+ *     
+ * sko_hw.c                     
+ * Includes both secure and non-secure otp operations 
+ *
+ *     
+ ********************************************************************* 
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include "linux/printk.h"
+#include <asm/arch/misc.h>
+#include "otp_map_cmn.h"
+#include "skp.h"
+
+//#define DBG_OTP
+
+#ifdef DBG_OTP
+#define _ETR(__p__)  printf("%s \n\t\t\t\t -> :%s :%d  code %d / 0x%x\n",__FILE__,__FUNCTION__,__LINE__,__p__,__p__)
+#define _DPRT(...)  printf(__VA_ARGS__) 
+#else
+#define _ETR(__p__)
+#define _DPRT(...)
+#endif
+
+static otp_hw_cmn_err_t  lookup_row(otp_hw_cmn_t* dev, 
+       u32 addr,
+       otp_hw_cmn_row_t** row)
+{
+       u32 i;
+       otp_hw_cmn_row_t* rows = dev->rows;
+       for (i = 0; i < dev->row_max; i++) {
+               if (rows[i].addr == addr) {
+                       *row = &rows[i];
+                       return OTP_HW_CMN_OK;   
+               }
+       }
+       _ETR(OTP_HW_CMN_ERR_UNSP);
+       return OTP_HW_CMN_ERR_UNSP;
+}
+
+/******************** FSR ACCESS FUNCTIONS ********************/
+__weak u32 fsr_hw_readl(void* dev, u32 offs)
+{
+       u32 val;
+       otp_hw_cmn_t* hw_dev = (otp_hw_cmn_t*)dev; 
+       val = readl(hw_dev->mm+FSR_OFFSET+offs);
+       _DPRT("0x%p > 0x%x\n",(void*)(hw_dev->mm+offs+FSR_OFFSET), val);
+       return val;
+}
+
+__weak void fsr_hw_writel(void* dev, u32 offs, u32 data)
+{
+       otp_hw_cmn_t* hw_dev = (otp_hw_cmn_t*)dev; 
+       _DPRT("0x%p < 0x%x\n",(void*)(hw_dev->mm+offs+FSR_OFFSET), data);
+       writel(data, hw_dev->mm+FSR_OFFSET+offs);
+}
+
+static  otp_hw_cmn_err_t fsr_poll_otp_status(otp_hw_cmn_t* dev, 
+                                               u32 fsr_offs)
+{
+       int to = 10000, errc = 0; 
+
+       do {
+               u32 st = fsr_hw_readl(dev, FSR_OTP_STATUS_OFFSET+fsr_offs);
+               _DPRT("Fsr status 0x%x\n",st);
+               if (!FSR_OTP_STATUS_ACTIVE(fsr_hw_readl(dev, FSR_OTP_STATUS_OFFSET+fsr_offs) )) {
+                       break;
+               }
+               udelay(1);
+               to--;
+       } while(to);
+
+       errc = FSR_OTP_STATUS_CMD_ERROR(fsr_hw_readl(dev,FSR_OTP_STATUS_OFFSET+fsr_offs));
+       if (errc) {
+               _DPRT("%s: ERROR: otp status err 0x%x\n",
+                       __FUNCTION__, fsr_hw_readl(dev, FSR_OTP_STATUS_OFFSET+fsr_offs));
+       }
+       return (!to || errc);
+}
+
+static otp_hw_cmn_err_t fsr_read(otp_hw_cmn_t* dev,
+                       otp_hw_cmn_row_t  *row,
+                       otp_hw_cmn_row_conf_t* row_conf,
+                       u32 *data,
+                       u32 size)
+{
+        int i;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       u32 fsr_offs;
+       u32 raw_read = 0;
+       u32 desc = 0;
+
+       fsr_offs = FSR_SIZE*(row->addr-FSR_START_ROW_ADDR);
+       if (row_conf && row_conf->op_type != OTP_HW_CMN_CTL_OTPCMD_ECC) {
+               _DPRT("%s %d \n\t\t\t\t Raw read!\n",
+                       __FUNCTION__,__LINE__);
+               raw_read = 1;
+       }
+
+       /* 1 - Check portal status */
+       /* Issue RELOAD_DESC command to FSR_PORTAL_FP0_OTP_COMMAND */
+       fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_RELOAD_DESC);
+       /* Check cmd complete,FSR_PORTAL_FP0_OTP_STATUS active(31)=0 cmd_err(7:0)=0 */
+       if (fsr_poll_otp_status(dev, fsr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO; 
+               _ETR(rc);
+               goto err;
+       }
+
+       /* Check valid(20)==1, ready(21)==1 */
+       if (!FSR_PORTAL_VALID(fsr_hw_readl(dev, FSR_PORTAL_STATUS_OFFSET+fsr_offs))) {
+               /* Portal is empty --> return zeroed data */
+               _DPRT("%s %d \n\t\t\t\t Empty Portal! portal_status 0x%x\n",
+                       __FUNCTION__,__LINE__,
+                       fsr_hw_readl(dev, FSR_PORTAL_STATUS_OFFSET+fsr_offs));
+               memset(data, 0x0, size);
+               rc = OTP_HW_CMN_OK; 
+               goto err;
+       }
+
+       /* DESC status is in FSR_PORTAL_FP0_PORTAL_STATUS */
+       /* RLOCK = 1 --> Cant read */
+       if( FSR_PORTAL_RLOCK(fsr_hw_readl(dev, FSR_PORTAL_STATUS_OFFSET+fsr_offs)) ) {
+               rc = OTP_HW_CMN_ERR_FAIL; 
+               _DPRT("%s %d \n\t\t\t\t Cant Read! RLOCK is set!\n",
+                       __FUNCTION__,__LINE__);
+               _ETR(rc);
+               goto err;
+       }
+
+       /* RAW and ECC_PGM_DIS = 0 --> Cant raw read */
+       if( raw_read && !FSR_PORTAL_ECC_DIS(fsr_hw_readl(dev, FSR_PORTAL_STATUS_OFFSET+fsr_offs))){
+               rc = OTP_HW_CMN_ERR_FAIL; 
+               _DPRT("%s %d \n\t\t\t\t Cant Read RAW! ECC_DIS is NOT set!\n",
+                       __FUNCTION__,__LINE__);
+               _ETR(rc);
+               goto err;
+       }
+
+       /* 2 - Read Decriptor to determine portal size */
+       /* Issue READ_DESC command to FSR_PORTAL_FP0_OTP_COMMAND */
+       fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_READ_DESC);
+       /* Check command complete */
+       if (fsr_poll_otp_status(dev, fsr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO; 
+               _ETR(rc);
+               goto err;
+       }
+       /* DESC is in FSR_PORTAL_FP0_DATA */
+       /* Check valid(31)==1 , this should succeed as PORTAL status is good*/
+       desc = fsr_hw_readl(dev, FSR_DATA_OFFSET+fsr_offs);
+       if(!FSR_RD_DGOOD(desc)) {
+               _ETR(rc);
+               _DPRT("%s %d \n\t\t\t\t desc 0x%x\n",
+                       __FUNCTION__,__LINE__,
+                       fsr_hw_readl(dev, FSR_DATA_OFFSET+fsr_offs));
+               rc = OTP_HW_CMN_ERR_FAIL; 
+               goto err;
+       }
+       /* Check if requested data fits inside this FSR, check SIZE(23:12) */
+       if(size/sizeof(u32) > FSR_RD_DDATA_SIZE(desc)) {
+               _ETR(rc);
+               _DPRT("%s %d \n\t\t\t\t size 0x%x > 0x%0x\n",
+                       __FUNCTION__,__LINE__, size/sizeof(u32), FSR_RD_DDATA_SIZE(desc));
+               rc =  OTP_HW_CMN_ERR_BAD_PARAM; 
+               goto err;
+       }
+
+       /* 3 - Read data */
+       for (i = 0; i < size/sizeof(u32); i++ ) {
+               /* Issue READ_DATA command - Set WORD SEL(15:4) to pick word# */
+               fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,
+                       (i<<FSR_PORTAL_OTP_CMD_WORD_SEL_SHIFT)|FSR_OTP_CMD_READ_DATA);
+               /* Check command complete */
+               if (fsr_poll_otp_status(dev, fsr_offs)) {
+                       rc = OTP_HW_CMN_ERR_TMO; 
+                       _ETR(rc);
+                       goto err;
+               }
+
+               /* Read data from FSR_PORTAL_FP0_DATA */
+               data[i] = fsr_hw_readl(dev, FSR_DATA_OFFSET+fsr_offs);
+               _DPRT("%s %d \n\t\t\t\t read data[%d] 0x%x \n",
+                       __FUNCTION__,__LINE__, i, data[i]);
+
+               /* Optional - Read ECC from FSR_PORTAL_FP0_RD_ECC */
+       }
+       rc = OTP_HW_CMN_OK;
+err:
+       return rc;
+}
+
+static otp_hw_cmn_err_t fsr_write(otp_hw_cmn_t* dev,
+                       otp_hw_cmn_row_t  *row,
+                       otp_hw_cmn_row_conf_t* row_conf,
+                       u32 *data,
+                       u32 size)
+{
+        int i;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       u32 fsr_offs; 
+       otp_hw_cmn_ctl_cmd_t ctl = {.ctl = OTP_HW_CMN_CTL_OTPCMD_AUTH_PROG};
+       u32 res = 0;
+       u32 raw_write = 0;
+       u32 desc = 0;
+       otp_hw_cmn_t *ext_drv = dev->drv_ext;
+
+       fsr_offs = FSR_SIZE*(row->addr-FSR_START_ROW_ADDR);
+       if (row_conf && row_conf->op_type != OTP_HW_CMN_CTL_OTPCMD_ECC) {
+               _DPRT("%s %d \n\t\t\t\t Raw write!\n",
+                       __FUNCTION__,__LINE__);
+               raw_write = 1;
+       }
+
+       /* 1 - Place OTP in program mode */
+       rc = ext_drv->ctl(ext_drv, &ctl, &res);
+       if (rc) {
+               _ETR(rc);
+               goto err;
+       }
+       ctl.ctl = OTP_HW_CMN_CTL_OTPCMD_AUTH_PROG_DONE;
+       rc = ext_drv->ctl(ext_drv, &ctl, &res);
+       if (rc) {
+               _ETR(rc);
+               goto err;
+       }
+
+       /* 2 - Check portal status */
+       /* Issue RELOAD_DESC command to FSR_PORTAL_FP0_OTP_COMMAND */
+       fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_RELOAD_DESC);
+       /* Check cmd complete,FSR_PORTAL_FP0_OTP_STATUS active(31)=0 cmd_err(7:0)=0 */
+       if (fsr_poll_otp_status(dev, fsr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO; 
+               _ETR(rc);
+               goto err;
+       }
+
+       /* Check valid(20)==1, ready(21)==1*/
+       if (!FSR_PORTAL_VALID(fsr_hw_readl(dev, FSR_PORTAL_STATUS_OFFSET+fsr_offs))) {
+               /* If Portal DESC is not valid ---> empty!, program it */
+               /* Set VALID = 1 and RLOCK = 0 */
+               desc = FSR_RD_DESC_VALID_MASK<<FSR_RD_DESC_VALID_SHIFT;
+
+               /* If RAW, set ECC_PGM_DIS */
+               if( raw_write )
+                       desc |= FSR_RD_DESC_ECC_PGM_DIS_MASK<<FSR_RD_DESC_ECC_PGM_DIS_SHIFT;
+
+               /* A - Write descriptor to FSR_PORTAL_FP0_DATA */
+               fsr_hw_writel(dev, FSR_DATA_OFFSET+fsr_offs,desc);
+
+               /* B - Issue PGM_DESC command to FSR_PORTAL_FP0_OTP_COMMAND */
+               fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_PGM_DESC);
+               /* Check cmd complete,FSR_PORTAL_FP0_OTP_STATUS active(31)=0 cmd_err(7:0)=0 */
+               if (fsr_poll_otp_status(dev, fsr_offs)) {
+                       rc = OTP_HW_CMN_ERR_TMO; 
+                       _ETR(rc);
+                       goto err;
+               }
+
+               /* C - Issue PGM_DESC_ECC command to FSR_PORTAL_FP0_OTP_COMMAND */
+               fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_PGM_DESC_ECC);
+               /* Check cmd complete,FSR_PORTAL_FP0_OTP_STATUS active(31)=0 cmd_err(7:0)=0 */
+               if (fsr_poll_otp_status(dev, fsr_offs)) {
+                       rc = OTP_HW_CMN_ERR_TMO; 
+                       _ETR(rc);
+                       goto err;
+               }
+
+               /* D - Issue RELOAD_DESC command to FSR_PORTAL_FP0_OTP_COMMAND */
+               fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_RELOAD_DESC);
+               /* Check cmd complete,FSR_PORTAL_FP0_OTP_STATUS active(31)=0 cmd_err(7:0)=0 */
+               if (fsr_poll_otp_status(dev, fsr_offs)) {
+                       rc = OTP_HW_CMN_ERR_TMO; 
+                       _ETR(rc);
+                       goto err;
+               }
+       } else {
+               /* Valid PORTAL and DESC */
+               /* DESC status is in FSR_PORTAL_FP0_PORTAL_STATUS */
+               /* RLOCK = 1 --> Cant write */
+               if( FSR_PORTAL_RLOCK(fsr_hw_readl(dev, FSR_PORTAL_STATUS_OFFSET+fsr_offs)) ) {
+                       rc = OTP_HW_CMN_ERR_WRITE_FAIL; 
+                       _DPRT("%s %d \n\t\t\t\t Cant Write! RLOCK is set!\n",
+                               __FUNCTION__,__LINE__);
+                       _ETR(rc);
+                       goto err;
+               }
+
+               /* RAW and ECC_PGM_DIS = 0 --> Cant raw write */
+               if( raw_write && !FSR_PORTAL_ECC_DIS(fsr_hw_readl(dev, 
+                               FSR_PORTAL_STATUS_OFFSET+fsr_offs))) {
+                       rc = OTP_HW_CMN_ERR_WRITE_FAIL; 
+                       _DPRT("%s %d \n\t\t\t\t Cant Write RAW! ECC_DIS is NOT set!\n",
+                               __FUNCTION__,__LINE__);
+                       _ETR(rc);
+                       goto err;
+               }
+
+               /* NOT RAW and ECC_PGM_DIS = 1 --> Cant non-raw write without ECC */
+               if( !raw_write && FSR_PORTAL_ECC_DIS(fsr_hw_readl(dev, 
+                               FSR_PORTAL_STATUS_OFFSET+fsr_offs))) {
+                       rc = OTP_HW_CMN_ERR_WRITE_FAIL; 
+                       _DPRT("%s %d \n\t\t\t\t Cant Write Non-raw! ECC_DIS is set!\n",
+                               __FUNCTION__,__LINE__);
+                       _ETR(rc);
+                       goto err;
+               }
+       }
+
+
+       /* 3 - Read Decriptor to determine portal size */
+       /* Issue READ_DESC command to FSR_PORTAL_FP0_OTP_COMMAND */
+       fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,FSR_OTP_CMD_READ_DESC);
+       /* Check command complete */
+       if (fsr_poll_otp_status(dev, fsr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO; 
+               _ETR(rc);
+               goto err;
+       }
+       /* Read and check if descriptor is valid(31) */
+       desc = fsr_hw_readl(dev, FSR_DATA_OFFSET+fsr_offs);
+       if(!FSR_RD_DGOOD(desc)) {
+               _ETR(rc);
+               _DPRT("%s %d \n\t\t\t\t desc 0x%x\n",
+                       __FUNCTION__,__LINE__,
+                       fsr_hw_readl(dev, FSR_DATA_OFFSET+fsr_offs));
+               rc = OTP_HW_CMN_ERR_FAIL; 
+               goto err;
+       }
+       /* Check if requested data fits inside this FSR, check SIZE(23:12) */
+       if(size/sizeof(u32) > FSR_RD_DDATA_SIZE(desc)) {
+               _ETR(rc);
+               _DPRT("%s %d \n\t\t\t\t size 0x%x > 0x%0x\n",
+                       __FUNCTION__,__LINE__, size/sizeof(u32), FSR_RD_DDATA_SIZE(desc));
+               rc =  OTP_HW_CMN_ERR_BAD_PARAM; 
+               goto err;
+       }
+       /* If not a raw_write, check if portal has been written to */
+       if( !raw_write ) {
+               for (i = 0; i < size/sizeof(u32); i++ ) {
+                       /* Issue READ_DATA command - Set WORD SEL(15:4) to pick word# */
+                       fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,
+                               (i<<FSR_PORTAL_OTP_CMD_WORD_SEL_SHIFT)|FSR_OTP_CMD_READ_DATA);
+                       /* Check command complete */
+                       if (fsr_poll_otp_status(dev, fsr_offs)) {
+                               rc = OTP_HW_CMN_ERR_TMO; 
+                               _ETR(rc);
+                               goto err;
+                       }
+
+                       /* Read ECC from FSR_PORTAL_FP0_RD_ECC */
+                       if(fsr_hw_readl(dev,FSR_RD_ECC_OFFSET+fsr_offs) & FSR_PORTAL_RD_ECC_MASK) {
+                               rc = OTP_HW_CMN_ERR_WRITE_FAIL; 
+                               _DPRT("%s %d \n\t\t\t\t Cannot overwrite portal! ECC is set!\n",
+                                       __FUNCTION__,__LINE__);
+                               _ETR(rc);
+                               goto err;
+                       }
+               }
+       }
+
+       /* 4 - Write data and ECC ( if reqd ) */
+       for (i = 0; i < size/sizeof(u32); i++ ) {
+               /* Read data from FSR_PORTAL_FP0_DATA */
+               _DPRT("%s %d \n\t\t\t\t write data[%d] 0x%x \n",
+                       __FUNCTION__,__LINE__, i, data[i]);
+
+               fsr_hw_writel(dev, FSR_DATA_OFFSET+fsr_offs, data[i]);
+
+               /* Issue WRITE_DATA command - Set WORD SEL(15:4) to pick word# */
+               fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,
+                       (i<<FSR_PORTAL_OTP_CMD_WORD_SEL_SHIFT)|FSR_OTP_CMD_PGM_DATA);
+               /* Check command complete */
+               if (fsr_poll_otp_status(dev, fsr_offs)) {
+                       rc = OTP_HW_CMN_ERR_TMO; 
+                       _ETR(rc);
+                       goto err;
+               }
+
+               if( !raw_write ) {              
+                       /* Issue WRITE_ECC command - Set WORD SEL(15:4) to pick word# */
+                       fsr_hw_writel(dev, FSR_OTP_CMD_OFFSET+fsr_offs,
+                               (i<<FSR_PORTAL_OTP_CMD_WORD_SEL_SHIFT)|FSR_OTP_CMD_PGM_DATA_ECC);
+                       /* Check command complete */
+                       if (fsr_poll_otp_status(dev, fsr_offs)) {
+                               rc = OTP_HW_CMN_ERR_TMO; 
+                               _ETR(rc);
+                               goto err;
+                       }
+               }
+       }
+       
+       _DPRT("Fused FSR rows as expected \n");
+               rc = OTP_HW_CMN_OK; 
+err:
+        return rc;
+}
+
+/******************** KSR ACCESS FUNCTIONS ********************/
+__weak u32 ksr_hw_readl(void* dev, u32 offs)
+{
+       otp_hw_cmn_t* hw_dev = (otp_hw_cmn_t*)dev; 
+       return readl(hw_dev->mm+KSR_OFFSET+offs);
+}
+
+__weak void ksr_hw_writel(void* dev, u32 offs, u32 data)
+{
+       otp_hw_cmn_t* hw_dev = (otp_hw_cmn_t*)dev; 
+       _DPRT("0x%x < 0x%x\n",hw_dev->mm+offs, data);
+       writel(data, hw_dev->mm+KSR_OFFSET+offs);
+}
+
+static  otp_hw_cmn_err_t ksr_poll_otp_status(otp_hw_cmn_t* dev, 
+                                               u32 ksr_offs)
+{
+       int to = 10000, errc = 0; 
+
+       do {
+               u32 st = ksr_hw_readl(dev, KSR_OTP_STATUS_OFFSET+ksr_offs);
+               _DPRT("Ksr status 0x%x\n",st);
+               if (!KSR_OTP_STATUS_ACTIVE(ksr_hw_readl(dev, KSR_OTP_STATUS_OFFSET+ksr_offs) )) {
+                       break;
+               }
+               udelay(1);
+               to--;
+       } while(to);
+
+       errc = KSR_OTP_STATUS_CMD_ERROR(ksr_hw_readl(dev,KSR_OTP_STATUS_OFFSET+ksr_offs));
+       if (errc) {
+               printf("%s: ERROR: otp status err 0x%x\n",
+                       __FUNCTION__, ksr_hw_readl(dev, KSR_OTP_STATUS_OFFSET+ksr_offs));
+       }
+       return (!to || errc);
+}
+
+static otp_hw_cmn_err_t ksr_read(otp_hw_cmn_t* dev,
+                       otp_hw_cmn_row_t  *row,
+                       otp_hw_cmn_row_conf_t* row_conf,
+                       u32 *data,
+                       u32 size)
+{
+        int i;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       u32 ksr_offs;
+       ksr_offs = KSR_SIZE*(row->addr-KSR_START_ROW_ADDR);
+       if ( !KSR_PORTAL_VALID(ksr_hw_readl(dev, KSR_PORTAL_STATUS_OFFSET+ksr_offs)) ||
+               !KSR_RD_DGOOD(ksr_hw_readl(dev, KSR_RD_DESC_OFFSET+ksr_offs))) {
+               _ETR(rc);
+               _DPRT("%s %d \n\t\t\t\t portal_status 0x%x rd_desc 0x%x\n",
+                       __FUNCTION__,__LINE__,ksr_hw_readl(dev, KSR_PORTAL_STATUS_OFFSET+ksr_offs), ksr_hw_readl(dev, KSR_RD_DESC_OFFSET+ksr_offs));
+               rc = OTP_HW_CMN_ERR_KEY_EMPTY; 
+               goto err;
+       }
+       for (i = 0; i <  size/sizeof(u32); i++ ) {
+               data[i] = ksr_hw_readl(dev, KSR_DATA_OFFSET+i*sizeof(u32)+ksr_offs);
+               _DPRT("%s %d \n\t\t\t\t data[%d] 0x%x \n",
+                       __FUNCTION__,__LINE__, i, data[i]);
+       }
+       rc = OTP_HW_CMN_OK;
+err:
+       return rc;
+
+}
+
+static otp_hw_cmn_err_t ksr_write(otp_hw_cmn_t* dev,
+                       otp_hw_cmn_row_t  *row,
+                       otp_hw_cmn_row_conf_t* row_conf,
+                       u32 *data,
+                       u32 size)
+{
+        int i;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       u32 ksr_offs; 
+       otp_hw_cmn_ctl_cmd_t ctl = {.ctl = OTP_HW_CMN_CTL_OTPCMD_AUTH_PROG};
+       u32 res = 0;
+       otp_hw_cmn_t *ext_drv = dev->drv_ext;
+       ksr_offs = KSR_SIZE*(row->addr-KSR_START_ROW_ADDR);
+       
+/*
+       1) Set OTP in program mode using classic CPU access as mentioned in Sec3.
+       2) Write bit[31] (valid) to “1” and bit[7:0] PAC fields as required (refer RDB for definition) into KEY_PORTAL_KP0_PGM_DESCRIPTOR
+       3) Issue PGM_DESCRIPTOR_WORD command, write bit[3:0] CMD field to “0x8”  in KEY_PORTAL_KP0_OTP_COMMAND, 
+               this command programs into the OTP Macro one 32-bit Descriptor word. The data to be written comes from the KP_PGM_DESCRIPTOR register.
+       4) Wait/Check for command_active to be low which indicates that the command issued is completed. 
+               Poll for the register bit “command_active(bit [31])” in KEY_PORTAL_KP0_OTP_STATUS. 
+               Once command is completed. Check for the bits[7:0] CMD_ERR (refer RDB for definition of the bits).
+       5) Issue PGM_DESCRIPTOR_ECC command, write bit[3:0] CMD field to “0x9”  in KEY_PORTAL_KP0_OTP_COMMAND, 
+               this command programs into the OTP Macro just the 10 ECC bits for the Descriptor row, 
+               which the OTP Controller automatically calculates based on the OTP data already programmed in this row.
+       6) Wait/Check for command_active to be low which indicates that the command issued is completed. 
+               Poll for the register bit “command_active(bit [31])” in KEY_PORTAL_KP0_OTP_STATUS.
+               Once command is completed. Check for the bits[7:0] CMD_ERR (refer RDB for definition of the bits).
+       7) Write all the 8 Keys into KEY_PORTAL_KP0_DATA_0, KEY_PORTAL_KP0_DATA_1, KEY_PORTAL_KP0_DATA_2, KEY_PORTAL_KP0_DATA_3, 
+               KEY_PORTAL_KP0_DATA_4, KEY_PORTAL_KP0_DATA_5, KEY_PORTAL_KP0_DATA_6, KEY_PORTAL_KP0_DATA_7 respectively.
+       8) Issue PGM_KEY command, write bit[3:0] CMD field to “0x2”  in KEY_PORTAL_KP0_OTP_COMMAND, 
+               this command programs (in the OTP Array) the entire key (including the CRC value) for this Key Portal. 
+               The hardware internally calculates the CRC value for the key and programs it into the CRC OTP field for this key.
+       9) Wait/Check for command_active to be low which indicates that the command issued is completed. 
+               Poll for the register bit “command_active(bit [31])” in KEY_PORTAL_KP0_OTP_STATUS. 
+               Once command is completed. Check for the bits[7:0] CMD_ERR (refer RDB for definition of the bits).
+       10) Issue chip reset.
+4.3 KSR PORTAL CPU READ ACCESS:
+
+KSR sectioned region thru portal can be accessed only in secure-boot mode, i.e. bit 2 in Row13 and bit 28 in Row 14 should be “1”.
+
+All 6 Key portals can be accessed in any order. Below sequence is explained by considering Key portal0 as an example same applies for other 5 Key portals as well.
+
+       1) Upon chip reboot, design loads the KSR descriptor, checks for its validity, 
+               and loads the keys into the registers once they are good.
+       2) Read KEY_PORTAL_KP0_RD_DESCRIPTOR, check for bit[29] DGOOD, this should be “1” which indicates descriptor 
+                       validity checks passed and the also all 8 Keys are good with no CRC/ECC errors. 
+               a. If DGOOD is “0”, all 8 keys read in Step(3) will be zeroes, KEY_PORTAL_KP0_PORTAL_STATUS 
+                       register will have more status info bits like Descriptor validity, Desc ECC error, Data ECC error, Keys loaded (Refer RDB).
+       3) Read KEY_PORTAL_KP0_PAC register, this register initially gets loaded with the PAC values 
+                       from OTP but later can also be programmed, based on the PAC permissions Key portal registers can be accessed. Please refer RDB for more information. 
+       4) Read all the 8 Keys which are loaded in KEY_PORTAL_KP0_DATA_0, KEY_PORTAL_KP0_DATA_1, KEY_PORTAL_KP0_DATA_2, KEY_PORTAL_KP0_DATA_3, KEY_PORTAL_KP0_DATA_4, KEY_PORTAL_KP0_DATA_5, KEY_PORTAL_KP0_DATA_6, KEY_PORTAL_KP0_DATA_7 respectively.
+
+*/
+       rc = ext_drv->ctl(ext_drv, &ctl, &res);
+       if (rc) {
+               _ETR(rc);
+               goto err;
+       }
+
+       ctl.ctl = OTP_HW_CMN_CTL_OTPCMD_AUTH_PROG_DONE;
+       rc = ext_drv->ctl(ext_drv, &ctl, &res);
+       if (rc) {
+               _ETR(rc);
+               goto err;
+       }
+
+       _ETR((u32)row_conf->perm);
+       _ETR(KSR_PORTAL_PGM_DESC_SRW_PERM);
+       if (ksr_poll_otp_status(dev, ksr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO; 
+               _ETR(rc);
+               goto err;
+       }
+       ksr_hw_writel(dev, KSR_PGM_DESC_OFFSET + ksr_offs, (u32)row_conf->perm);
+       _ETR(ksr_hw_readl(dev, KSR_PGM_DESC_OFFSET+ksr_offs));
+       ksr_hw_writel(dev, KSR_OTP_CMD_OFFSET + ksr_offs, KSR_PORTAL_OTP_CMD_PGM_DESC_WORD);
+       if (ksr_poll_otp_status(dev, ksr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO; 
+               _ETR(rc);
+               goto err;
+       }
+       _ETR(KSR_PORTAL_OTP_CMD_PGM_DESC_WORD);
+       if ((row_conf->op_type&OTP_HW_CMN_CTL_OTPCMD_ECC)) {
+               ksr_hw_writel(dev, KSR_OTP_CMD_OFFSET+ksr_offs,KSR_PORTAL_OTP_CMD_PGM_DESC_ECC);
+               if (ksr_poll_otp_status(dev,ksr_offs)) {
+                       rc = OTP_HW_CMN_ERR_TMO; 
+                       _ETR(rc);
+                       goto err;
+               }
+               _ETR(KSR_PORTAL_OTP_CMD_PGM_DESC_ECC);
+       }
+       for (i = 0 ; i <  size/sizeof(u32); i++) {
+               ksr_hw_writel(dev, KSR_DATA_OFFSET+ksr_offs+i*sizeof(u32), data[i]);
+       }
+       ksr_hw_writel(dev, KSR_OTP_CMD_OFFSET + ksr_offs, KSR_PORTAL_OTP_CMD_PGM_KEY);
+       _ETR(ksr_hw_readl(dev, KSR_OTP_CMD_OFFSET+ksr_offs));
+       if (ksr_poll_otp_status(dev, ksr_offs)) {
+               rc = OTP_HW_CMN_ERR_TMO;
+               _ETR(rc);
+               goto err;
+       }
+       
+       _DPRT("Fused KSR rows as expected \n");
+               rc = OTP_HW_CMN_OK; 
+err:
+        return rc;
+}
+
+static otp_hw_cmn_err_t ksr_set_populated_pacs(otp_hw_cmn_t *dev, u32 pac_val)
+{
+       int i;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       /* First 2 KSR Portals have their PACS fused via their descriptors -- ignore */
+       for (i = 2; i < KSR_MAX_ROW_ADDR; i++) { 
+               /* If portal is valid and descriptor is good, we have valid data so lock NS */
+               if ( KSR_PORTAL_VALID(ksr_hw_readl(dev, KSR_PORTAL_STATUS_OFFSET+i*KSR_SIZE)) &&
+                       KSR_RD_DGOOD(ksr_hw_readl(dev, KSR_RD_DESC_OFFSET+i*KSR_SIZE))) {
+                               ksr_hw_writel(dev, KSR_PAC_OFFSET+i*KSR_SIZE, pac_val);
+               }
+       }
+       rc = OTP_HW_CMN_OK;
+       return rc;
+}
+
+static otp_hw_cmn_err_t ksr_set_all_pacs(otp_hw_cmn_t *dev, u32 pac_val)
+{
+       int i;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       /* First 2 KSR Portals have their PACS fused via their descriptors -- ignore */
+       for (i = 2; i < KSR_MAX_ROW_ADDR; i++) { 
+               ksr_hw_writel(dev, KSR_PAC_OFFSET+i*KSR_SIZE, pac_val);
+       }
+       rc = OTP_HW_CMN_OK;
+       return rc;
+
+}
+
+static otp_hw_cmn_err_t ksr_portal_lock(otp_hw_cmn_t *dev,
+                       u32 addr, 
+                       otp_hw_cmn_perm_t perm,
+                       u8 lock)
+{
+       otp_hw_cmn_row_t  *row;
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       u32 curr_perm_mask = 0;
+       u32 perm_mask = 0;
+       if ( lookup_row(dev, addr, &row)) {
+               rc = OTP_HW_CMN_ERR_UNSP;
+               _ETR(rc); 
+               goto err;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_PAC_NSRD) {
+               perm_mask |= KSR_PERM_PAC_NSR_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_PAC_SRD) {
+               perm_mask |= KSR_PERM_PAC_SR_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_PAC_NSW) {
+               perm_mask |= KSR_PERM_PAC_NSW_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_PAC_SW) {
+               perm_mask |= KSR_PERM_PAC_SW_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_SRD) {
+               perm_mask |= KSR_PERM_BLK_SR_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_NSRD) {
+               perm_mask |= KSR_PERM_BLK_NSR_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_SW) {
+               perm_mask |= KSR_PERM_BLK_SW_LOCK;
+       }
+       if (perm & OTP_HW_CMN_CTL_LOCK_NSW) {
+               perm_mask |= KSR_PERM_BLK_NSW_LOCK;
+       }
+       if (perm_mask) {
+               curr_perm_mask = ksr_hw_readl(dev, KSR_PAC_OFFSET + row->addr*KSR_SIZE);
+               if( lock ) {
+                       ksr_hw_writel(dev, KSR_PAC_OFFSET + row->addr*KSR_SIZE, 
+                               curr_perm_mask|perm_mask);
+               } else {
+                       ksr_hw_writel(dev, KSR_PAC_OFFSET + row->addr*KSR_SIZE, 
+                               curr_perm_mask&(~perm_mask));
+               }
+
+               rc = OTP_HW_CMN_OK;
+       }
+err:
+       return rc;
+}
+
+static otp_hw_cmn_err_t ksr_multi_portal_lock(otp_hw_cmn_t *dev,
+                       otp_hw_cmn_perm_t perm,
+                       u8 lock)
+{
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       if( lock ) {
+               if (perm & OTP_HW_CMN_CTL_LOCK_NS) {
+                       rc = ksr_set_all_pacs(dev, KSR_PERM_LOCK_NS);
+               } else if (perm & OTP_HW_CMN_CTL_LOCK_ALL) {
+                       rc = ksr_set_all_pacs(dev, KSR_PERM_LOCK_ALL);
+               } else if (perm & OTP_HW_CMN_CTL_LOCK_S) {
+                       rc = ksr_set_all_pacs(dev, KSR_PERM_LOCK_S);
+               } 
+       } else {
+               if (perm & OTP_HW_CMN_CTL_LOCK_NS || perm & OTP_HW_CMN_CTL_LOCK_NS_PROV ) {
+                       rc = ksr_set_all_pacs(dev, KSR_PERM_UNLOCK_NS);
+                       if( perm & OTP_HW_CMN_CTL_LOCK_NS_PROV) {
+                               /* LOCK NS access for keys that are populated */
+                               rc = ksr_set_populated_pacs(dev, KSR_PERM_LOCK_NS);
+                       }
+               } else if (perm & OTP_HW_CMN_CTL_LOCK_S) {
+                       rc = ksr_set_all_pacs(dev, KSR_PERM_UNLOCK_S);
+               } else if (perm & OTP_HW_CMN_CTL_LOCK_ALL) {
+                       rc = ksr_set_all_pacs(dev, KSR_PERM_UNLOCK_ALL);
+               } 
+       }
+       return rc;
+}
+
+static otp_hw_cmn_err_t ksr_portal_status(otp_hw_cmn_t *dev,
+                       u32 addr,
+                       otp_hw_cmn_status_t status,
+                       u32* res)
+{
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       u32 perm_mask = 0,ksr_offs;
+        otp_hw_cmn_row_t  *row = NULL;
+
+       if ( lookup_row(dev, addr, &row)) {
+               rc = OTP_HW_CMN_ERR_UNSP;
+               _ETR(rc); 
+               goto err;
+       } 
+
+       ksr_offs = KSR_SIZE*(row->addr-KSR_START_ROW_ADDR);
+       perm_mask = ksr_hw_readl(dev, KSR_PAC_OFFSET+ksr_offs);
+       
+       if (!(perm_mask & KSR_PERM_PAC_NSR_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_NSRD_PAC_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_PAC_SR_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_SRD_PAC_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_PAC_NSW_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_NSW_PAC_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_PAC_SW_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_SW_PAC_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_BLK_SR_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_SRD_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_BLK_NSR_LOCK)) {
+               status &=  ~OTP_HW_CMN_STATUS_NSRD_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_BLK_SW_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_SW_LOCKED;
+       }
+       if (!(perm_mask & KSR_PERM_BLK_NSW_LOCK)) {
+               status &= ~OTP_HW_CMN_STATUS_NSW_LOCKED;
+       }
+       if ( !KSR_PORTAL_VALID(ksr_hw_readl(dev, KSR_PORTAL_STATUS_OFFSET+ksr_offs)) ||
+               !KSR_RD_DGOOD(ksr_hw_readl(dev, KSR_RD_DESC_OFFSET+ksr_offs))) {
+               status &= ~OTP_HW_CMN_STATUS_ROW_DATA_VALID;
+       }
+       *res = status;
+       rc = OTP_HW_CMN_OK;
+err:
+       return rc;
+}
+
+
+/******************** SKP ACCESS FUNCTIONS ********************/
+static  otp_hw_cmn_err_t skp_write(otp_hw_cmn_t* dev, 
+               u32 addr,
+               otp_hw_cmn_row_conf_t* conf,
+               const u32* data,
+               u32 size)
+{
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+        otp_hw_cmn_row_t *row;
+       otp_hw_cmn_row_conf_t* row_conf;
+       if (!dev->drv_ext) {
+               rc = OTP_HW_CMN_ERR_INVAL;
+               _ETR(rc);
+               goto err;
+       }
+       if (lookup_row(dev, addr, &row)) {
+               rc = OTP_HW_CMN_ERR_UNSP;
+               _ETR(rc);
+               goto err;
+       }
+
+       if ((int)size <= 0 || (int)size > row->range*sizeof(u32) || (int)row->addr < 0) {
+               rc = OTP_HW_CMN_ERR_INVAL; 
+               _ETR(rc);
+               goto err;
+       }
+
+       row_conf = conf?conf:&row->conf;
+       if( (int)row->addr < KSR_MAX_ROW_ADDR ) {
+               rc = ksr_write( dev, row, row_conf, (u32*)data, size );
+       } else if(((int)row->addr >=FSR_START_ROW_ADDR) && ((int)row->addr < FSR_MAX_ROW_ADDR)) {
+               rc = fsr_write( dev, row, row_conf, (u32*)data, size );
+       } else {
+               rc = OTP_HW_CMN_ERR_INVAL; 
+               _ETR(rc);
+       }
+err:
+       _DPRT("%s: rc %d\n", __FUNCTION__, rc);
+       return rc;
+
+}
+
+static otp_hw_cmn_err_t skp_read(otp_hw_cmn_t *dev,
+                       u32 addr,
+                       otp_hw_cmn_row_conf_t* conf,
+                       u32 *data,
+                       u32 size)
+{
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+        otp_hw_cmn_row_t  *row;
+       otp_hw_cmn_row_conf_t* row_conf;
+       if (!dev->drv_ext) {
+               rc = OTP_HW_CMN_ERR_INVAL; 
+               _ETR(rc);
+               goto err;
+       }
+       if( lookup_row(dev, addr, &row)) {
+               rc = OTP_HW_CMN_ERR_UNSP;
+               _ETR(rc); 
+               goto err;
+       }
+       if ((int)size <= 0 || (int)size > row->range*sizeof(u32) || (int)row->addr < 0) {
+               rc = OTP_HW_CMN_ERR_INVAL; 
+               _ETR(rc);
+               goto err;
+       }
+
+       row_conf = conf? conf : &row->conf;
+       if( (int)row->addr < KSR_MAX_ROW_ADDR ) {
+               rc = ksr_read( dev, row, row_conf, (u32*)data, size );
+       } else if(((int)row->addr >=FSR_START_ROW_ADDR) && ((int)row->addr < FSR_MAX_ROW_ADDR)) {
+               rc = fsr_read( dev, row, row_conf, (u32*)data, size );
+       } else {
+               rc = OTP_HW_CMN_ERR_INVAL; 
+               _ETR(rc);
+       }
+err:
+       _DPRT("%s: rc %d\n", __FUNCTION__, rc);
+       return rc;
+}
+
+static  otp_hw_cmn_err_t skp_hw_write(otp_hw_cmn_t* dev, 
+               u32 addr,
+               const u32* data,
+               u32 size)
+{
+       otp_hw_cmn_row_conf_t *cfg =  
+                               !(dev->ctl_cmd.ctl&OTP_HW_CMN_CTL_CONF)? NULL: &dev->row_conf;
+       _ETR(dev->ctl_cmd.ctl); 
+       return skp_write(dev, addr, cfg, data, size);
+}
+
+static otp_hw_cmn_err_t skp_hw_read(otp_hw_cmn_t *dev,
+                       u32 addr,
+                       u32 *data,
+                       u32 size)
+{
+
+       otp_hw_cmn_row_conf_t *cfg =  
+                         !(dev->ctl_cmd.ctl&OTP_HW_CMN_CTL_CONF)? NULL : &dev->row_conf;
+       _ETR(dev->ctl_cmd.ctl); 
+       return skp_read(dev, addr, cfg, data, size);
+
+}
+
+static otp_hw_cmn_err_t skp_hw_lock(otp_hw_cmn_t *dev,
+                       u32 addr, 
+                       otp_hw_cmn_perm_t perm,
+                       u8 lock)
+{
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       switch ( perm ) {
+               case OTP_HW_CMN_CTL_LOCK_NS:
+               case OTP_HW_CMN_CTL_LOCK_NS_PROV:
+               case OTP_HW_CMN_CTL_LOCK_ALL:
+               case OTP_HW_CMN_CTL_LOCK_S:
+                       /* TODO: Add FSR support */
+                       rc = ksr_multi_portal_lock(dev, perm, lock);
+               break;
+               default:
+                       /* TODO: Add FSR support */
+                       rc = ksr_portal_lock(dev, addr, perm, lock);
+       }
+       return rc;
+}
+
+
+static otp_hw_cmn_err_t skp_hw_status(otp_hw_cmn_t *dev,
+                       u32 addr,
+                       otp_hw_cmn_status_t status,
+                       u32* res)
+{
+
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_FAIL; 
+       /* TODO: Add FSR support */
+       rc = ksr_portal_status(dev, addr, status, res);
+       return rc;
+}
+
+__weak otp_hw_cmn_err_t sotp_hw_cmn_ctl(otp_hw_cmn_t *dev, 
+                       const otp_hw_cmn_ctl_cmd_t *cmd,
+                       u32* res)
+{
+       otp_hw_cmn_err_t rc = OTP_HW_CMN_ERR_UNSP;
+       switch ((u32)(cmd->ctl)) {
+               case OTP_HW_CMN_CTL_CONF:
+                       memcpy(&dev->row_conf, 
+                               (otp_hw_cmn_row_conf_t*)cmd->data, 
+                               cmd->size);
+
+                       dev->ctl_cmd.ctl |= cmd->ctl;
+                       rc = OTP_HW_CMN_OK;
+                       break;
+               case (~((u32)OTP_HW_CMN_CTL_CONF)):
+                       dev->ctl_cmd.ctl &= ~cmd->ctl;
+                       rc = OTP_HW_CMN_OK;
+                       break;
+               case OTP_HW_CMN_CTL_UNLOCK: {
+                               otp_hw_ctl_data_t* ctl_data = (otp_hw_ctl_data_t*)cmd->data;
+                               rc = skp_hw_lock(dev, ctl_data->addr, ctl_data->perm, 0);
+                       }
+                       break;
+               case OTP_HW_CMN_CTL_LOCK: {
+                               otp_hw_ctl_data_t* ctl_data = (otp_hw_ctl_data_t*)cmd->data;
+                               rc = skp_hw_lock(dev, ctl_data->addr, ctl_data->perm, 1);
+                       }
+                       break;
+               case OTP_HW_CMN_CTL_STATUS: {
+                               otp_hw_ctl_data_t* ctl_data = (otp_hw_ctl_data_t*)cmd->data;    
+                               rc = skp_hw_status(dev, ctl_data->addr, ctl_data->status, res);
+                       }
+                       break;
+               default :
+                       break;  
+       }
+       return rc;
+       
+}
+
+
+__weak otp_hw_cmn_err_t sotp_hw_dev_mmap(otp_hw_cmn_t* dev)
+{
+       dev->mm = KSR_BASE;
+       return OTP_HW_CMN_OK;
+}
+
+__weak otp_hw_cmn_err_t sotp_hw_init(otp_hw_cmn_t* dev)
+{
+       DEFINE_SOTP_MAP_ROW_INITLR(rows);
+       if (sotp_hw_dev_mmap(dev)) {
+               return OTP_HW_CMN_ERR_FAIL;
+       }
+       dev->rows = rows;
+       dev->row_max = sizeof(rows)/sizeof(otp_hw_cmn_row_t);
+       return OTP_HW_CMN_OK;
+}
+
+
+otp_hw_cmn_err_t sotp_hw_cmn_init(otp_hw_cmn_t* dev)
+{
+       if (sotp_hw_init(dev)) {
+               _ETR(OTP_HW_CMN_ERR_FAIL);
+               return OTP_HW_CMN_ERR_FAIL;
+       }
+       dev->read = skp_hw_read;
+       dev->write = skp_hw_write;
+       dev->ctl = sotp_hw_cmn_ctl;
+       return OTP_HW_CMN_OK;
+}