aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Jander <david@protonic.nl>2013-09-02 03:46:11 -0400
committerLee Jones <lee.jones@linaro.org>2013-10-23 11:20:32 -0400
commit43e30f23b589642a7eaff005bc30444a5247976c (patch)
treea8c467e71306d5cea46c52ecd795839bb7438832
parent61e6cfa80de5760bbe406f4e815b7739205754d2 (diff)
mfd: da9052: Avoid multiwrite mode due to silicon errata
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>
-rw-r--r--drivers/mfd/da9052-i2c.c12
-rw-r--r--include/linux/mfd/da9052/da9052.h20
2 files changed, 22 insertions, 10 deletions
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 6a9fec40d018..c319c4ef5d49 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -86,7 +86,11 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
86 return 0; 86 return 0;
87} 87}
88 88
89static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) 89/*
90 * According to errata item 24, multiwrite mode should be avoided
91 * in order to prevent register data corruption after power-down.
92 */
93static int da9052_i2c_disable_multiwrite(struct da9052 *da9052)
90{ 94{
91 int reg_val, ret; 95 int reg_val, ret;
92 96
@@ -94,8 +98,8 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
94 if (ret < 0) 98 if (ret < 0)
95 return ret; 99 return ret;
96 100
97 if (reg_val & DA9052_CONTROL_B_WRITEMODE) { 101 if (!(reg_val & DA9052_CONTROL_B_WRITEMODE)) {
98 reg_val &= ~DA9052_CONTROL_B_WRITEMODE; 102 reg_val |= DA9052_CONTROL_B_WRITEMODE;
99 ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG, 103 ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG,
100 reg_val); 104 reg_val);
101 if (ret < 0) 105 if (ret < 0)
@@ -154,7 +158,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
154 return ret; 158 return ret;
155 } 159 }
156 160
157 ret = da9052_i2c_enable_multiwrite(da9052); 161 ret = da9052_i2c_disable_multiwrite(da9052);
158 if (ret < 0) 162 if (ret < 0)
159 return ret; 163 return ret;
160 164
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h
index 786d02eb79d2..21e21b81cc75 100644
--- a/include/linux/mfd/da9052/da9052.h
+++ b/include/linux/mfd/da9052/da9052.h
@@ -148,10 +148,15 @@ static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
148 unsigned reg_cnt, unsigned char *val) 148 unsigned reg_cnt, unsigned char *val)
149{ 149{
150 int ret; 150 int ret;
151 unsigned int tmp;
152 int i;
151 153
152 ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt); 154 for (i = 0; i < reg_cnt; i++) {
153 if (ret < 0) 155 ret = regmap_read(da9052->regmap, reg + i, &tmp);
154 return ret; 156 val[i] = (unsigned char)tmp;
157 if (ret < 0)
158 return ret;
159 }
155 160
156 if (da9052->fix_io) { 161 if (da9052->fix_io) {
157 ret = da9052->fix_io(da9052, reg); 162 ret = da9052->fix_io(da9052, reg);
@@ -166,10 +171,13 @@ static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
166 unsigned reg_cnt, unsigned char *val) 171 unsigned reg_cnt, unsigned char *val)
167{ 172{
168 int ret; 173 int ret;
174 int i;
169 175
170 ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt); 176 for (i = 0; i < reg_cnt; i++) {
171 if (ret < 0) 177 ret = regmap_write(da9052->regmap, reg + i, val[i]);
172 return ret; 178 if (ret < 0)
179 return ret;
180 }
173 181
174 if (da9052->fix_io) { 182 if (da9052->fix_io) {
175 ret = da9052->fix_io(da9052, reg); 183 ret = da9052->fix_io(da9052, reg);