]> Pileus Git - ~andy/linux/commitdiff
mfd: da9052: Avoid multiwrite mode due to silicon errata
authorDavid Jander <david@protonic.nl>
Mon, 2 Sep 2013 07:46:11 +0000 (09:46 +0200)
committerLee Jones <lee.jones@linaro.org>
Wed, 23 Oct 2013 15:20:32 +0000 (16:20 +0100)
DA9053 (up to revision bc) can corrupt internal registers when multi-write
mode is enabled and power is removed or during shutdown.

Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
drivers/mfd/da9052-i2c.c
include/linux/mfd/da9052/da9052.h

index 6a9fec40d018308a39e1ea24b086bfc94dfb77f0..c319c4ef5d499c9f59140adf941987ac6d024bb2 100644 (file)
@@ -86,7 +86,11 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
        return 0;
 }
 
-static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
+/*
+ * According to errata item 24, multiwrite mode should be avoided
+ * in order to prevent register data corruption after power-down.
+ */
+static int da9052_i2c_disable_multiwrite(struct da9052 *da9052)
 {
        int reg_val, ret;
 
@@ -94,8 +98,8 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
        if (ret < 0)
                return ret;
 
-       if (reg_val & DA9052_CONTROL_B_WRITEMODE) {
-               reg_val &= ~DA9052_CONTROL_B_WRITEMODE;
+       if (!(reg_val & DA9052_CONTROL_B_WRITEMODE)) {
+               reg_val |= DA9052_CONTROL_B_WRITEMODE;
                ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG,
                                   reg_val);
                if (ret < 0)
@@ -154,7 +158,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
                return ret;
        }
 
-       ret = da9052_i2c_enable_multiwrite(da9052);
+       ret = da9052_i2c_disable_multiwrite(da9052);
        if (ret < 0)
                return ret;
 
index 786d02eb79d2210ef8c3dfe145e3c8d0e0123ef1..21e21b81cc7551db7203b7d027b688feebd3577c 100644 (file)
@@ -148,10 +148,15 @@ static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
                                     unsigned reg_cnt, unsigned char *val)
 {
        int ret;
+       unsigned int tmp;
+       int i;
 
-       ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
-       if (ret < 0)
-               return ret;
+       for (i = 0; i < reg_cnt; i++) {
+               ret = regmap_read(da9052->regmap, reg + i, &tmp);
+               val[i] = (unsigned char)tmp;
+               if (ret < 0)
+                       return ret;
+       }
 
        if (da9052->fix_io) {
                ret = da9052->fix_io(da9052, reg);
@@ -166,10 +171,13 @@ static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
                                      unsigned reg_cnt, unsigned char *val)
 {
        int ret;
+       int i;
 
-       ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
-       if (ret < 0)
-               return ret;
+       for (i = 0; i < reg_cnt; i++) {
+               ret = regmap_write(da9052->regmap, reg + i, val[i]);
+               if (ret < 0)
+                       return ret;
+       }
 
        if (da9052->fix_io) {
                ret = da9052->fix_io(da9052, reg);