#include <linux/of_device.h>
 #endif
 
+/* I2C safe register check */
+static inline bool i2c_safe_reg(unsigned char reg)
+{
+       switch (reg) {
+       case DA9052_STATUS_A_REG:
+       case DA9052_STATUS_B_REG:
+       case DA9052_STATUS_C_REG:
+       case DA9052_STATUS_D_REG:
+       case DA9052_ADC_RES_L_REG:
+       case DA9052_ADC_RES_H_REG:
+       case DA9052_VDD_RES_REG:
+       case DA9052_ICHG_AV_REG:
+       case DA9052_TBAT_RES_REG:
+       case DA9052_ADCIN4_RES_REG:
+       case DA9052_ADCIN5_RES_REG:
+       case DA9052_ADCIN6_RES_REG:
+       case DA9052_TJUNC_RES_REG:
+       case DA9052_TSI_X_MSB_REG:
+       case DA9052_TSI_Y_MSB_REG:
+       case DA9052_TSI_LSB_REG:
+       case DA9052_TSI_Z_MSB_REG:
+               return true;
+       default:
+               return false;
+       }
+}
+
+/*
+ * There is an issue with DA9052 and DA9053_AA/BA/BB PMIC where the PMIC
+ * gets lockup up or fails to respond following a system reset.
+ * This fix is to follow any read or write with a dummy read to a safe
+ * register.
+ */
+int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
+{
+       int val;
+
+       switch (da9052->chip_id) {
+       case DA9052:
+       case DA9053_AA:
+       case DA9053_BA:
+       case DA9053_BB:
+               /* A dummy read to a safe register address. */
+       if (!i2c_safe_reg(reg))
+                       return regmap_read(da9052->regmap,
+                                          DA9052_PARK_REGISTER,
+                                          &val);
+               break;
+       default:
+               /*
+                * For other chips parking of I2C register
+                * to a safe place is not required.
+                */
+               break;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(da9052_i2c_fix);
+
 static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
 {
        int reg_val, ret;
 
        da9052->dev = &client->dev;
        da9052->chip_irq = client->irq;
+       da9052->fix_io = da9052_i2c_fix;
 
        i2c_set_clientdata(client, da9052);
 
 
        u8 chip_id;
 
        int chip_irq;
+
+       /* SOC I/O transfer related fixes for DA9052/53 */
+       int (*fix_io) (struct da9052 *da9052, unsigned char reg);
 };
 
 /* ADC API */
        ret = regmap_read(da9052->regmap, reg, &val);
        if (ret < 0)
                return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
        return val;
 }
 
 static inline int da9052_reg_write(struct da9052 *da9052, unsigned char reg,
                                    unsigned char val)
 {
-       return regmap_write(da9052->regmap, reg, val);
+       int ret;
+
+       ret = regmap_write(da9052->regmap, reg, val);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
                                     unsigned reg_cnt, unsigned char *val)
 {
-       return regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
+       int ret;
+
+       ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
                                      unsigned reg_cnt, unsigned char *val)
 {
-       return regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
+       int ret;
+
+       ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static inline int da9052_reg_update(struct da9052 *da9052, unsigned char reg,
                                     unsigned char bit_mask,
                                     unsigned char reg_val)
 {
-       return regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val);
+       int ret;
+
+       ret = regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 int da9052_device_init(struct da9052 *da9052, u8 chip_id);