diff options
author | David Jander <david@protonic.nl> | 2013-09-02 03:46:11 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-10-23 11:20:32 -0400 |
commit | 43e30f23b589642a7eaff005bc30444a5247976c (patch) | |
tree | a8c467e71306d5cea46c52ecd795839bb7438832 | |
parent | 61e6cfa80de5760bbe406f4e815b7739205754d2 (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.c | 12 | ||||
-rw-r--r-- | include/linux/mfd/da9052/da9052.h | 20 |
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 | ||
89 | static 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 | */ | ||
93 | static 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); |