diff options
author | Benoît Thébaudeau <benoit@wsystem.com> | 2016-07-21 06:41:30 -0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-07-28 03:59:39 -0400 |
commit | d522649e2686ec98eb03078583736fdcb4ef8880 (patch) | |
tree | 700f67442f50a1d09af1dd8712110faa7451e5ae | |
parent | a1e98e09704ad247bff3c0de1bef6a73dc88b6d0 (diff) |
rtc: rv8803: Always apply the I²C workaround
The I²C NACK issue of the RV-8803 may occur after any I²C START
condition, depending on the timings. Consequently, the workaround must
be applied for all the I²C transfers.
This commit abstracts the I²C transfer code into register access
functions. This avoids duplicating the I²C workaround everywhere. This
also avoids the duplication of the code handling the return value of
i2c_smbus_read_i2c_block_data(). Error messages are issued in case of
definitive register access failures (if the workaround fails). This
change also makes the I²C transfer return value checks consistent.
Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r-- | drivers/rtc/rtc-rv8803.c | 179 |
1 files changed, 113 insertions, 66 deletions
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index aa1d6b67a9ee..09ab5cb1fa8a 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
22 | 22 | ||
23 | #define RV8803_I2C_TRY_COUNT 4 | ||
24 | |||
23 | #define RV8803_SEC 0x00 | 25 | #define RV8803_SEC 0x00 |
24 | #define RV8803_MIN 0x01 | 26 | #define RV8803_MIN 0x01 |
25 | #define RV8803_HOUR 0x02 | 27 | #define RV8803_HOUR 0x02 |
@@ -57,19 +59,85 @@ struct rv8803_data { | |||
57 | u8 ctrl; | 59 | u8 ctrl; |
58 | }; | 60 | }; |
59 | 61 | ||
62 | static int rv8803_read_reg(const struct i2c_client *client, u8 reg) | ||
63 | { | ||
64 | int try = RV8803_I2C_TRY_COUNT; | ||
65 | s32 ret; | ||
66 | |||
67 | /* | ||
68 | * There is a 61µs window during which the RTC does not acknowledge I2C | ||
69 | * transfers. In that case, ensure that there are multiple attempts. | ||
70 | */ | ||
71 | do | ||
72 | ret = i2c_smbus_read_byte_data(client, reg); | ||
73 | while ((ret == -ENXIO || ret == -EIO) && --try); | ||
74 | if (ret < 0) | ||
75 | dev_err(&client->dev, "Unable to read register 0x%02x\n", reg); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | static int rv8803_read_regs(const struct i2c_client *client, | ||
81 | u8 reg, u8 count, u8 *values) | ||
82 | { | ||
83 | int try = RV8803_I2C_TRY_COUNT; | ||
84 | s32 ret; | ||
85 | |||
86 | do | ||
87 | ret = i2c_smbus_read_i2c_block_data(client, reg, count, values); | ||
88 | while ((ret == -ENXIO || ret == -EIO) && --try); | ||
89 | if (ret != count) { | ||
90 | dev_err(&client->dev, | ||
91 | "Unable to read registers 0x%02x..0x%02x\n", | ||
92 | reg, reg + count - 1); | ||
93 | return ret < 0 ? ret : -EIO; | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value) | ||
100 | { | ||
101 | int try = RV8803_I2C_TRY_COUNT; | ||
102 | s32 ret; | ||
103 | |||
104 | do | ||
105 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
106 | while ((ret == -ENXIO || ret == -EIO) && --try); | ||
107 | if (ret) | ||
108 | dev_err(&client->dev, "Unable to write register 0x%02x\n", reg); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static int rv8803_write_regs(const struct i2c_client *client, | ||
114 | u8 reg, u8 count, const u8 *values) | ||
115 | { | ||
116 | int try = RV8803_I2C_TRY_COUNT; | ||
117 | s32 ret; | ||
118 | |||
119 | do | ||
120 | ret = i2c_smbus_write_i2c_block_data(client, reg, count, | ||
121 | values); | ||
122 | while ((ret == -ENXIO || ret == -EIO) && --try); | ||
123 | if (ret) | ||
124 | dev_err(&client->dev, | ||
125 | "Unable to write registers 0x%02x..0x%02x\n", | ||
126 | reg, reg + count - 1); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
60 | static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) | 131 | static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) |
61 | { | 132 | { |
62 | struct i2c_client *client = dev_id; | 133 | struct i2c_client *client = dev_id; |
63 | struct rv8803_data *rv8803 = i2c_get_clientdata(client); | 134 | struct rv8803_data *rv8803 = i2c_get_clientdata(client); |
64 | unsigned long events = 0; | 135 | unsigned long events = 0; |
65 | int flags, try = 0; | 136 | int flags; |
66 | 137 | ||
67 | mutex_lock(&rv8803->flags_lock); | 138 | mutex_lock(&rv8803->flags_lock); |
68 | 139 | ||
69 | do { | 140 | flags = rv8803_read_reg(client, RV8803_FLAG); |
70 | flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | ||
71 | try++; | ||
72 | } while (((flags == -ENXIO) || (flags == -EIO)) && (try < 4)); | ||
73 | if (flags <= 0) { | 141 | if (flags <= 0) { |
74 | mutex_unlock(&rv8803->flags_lock); | 142 | mutex_unlock(&rv8803->flags_lock); |
75 | return IRQ_NONE; | 143 | return IRQ_NONE; |
@@ -101,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) | |||
101 | 169 | ||
102 | if (events) { | 170 | if (events) { |
103 | rtc_update_irq(rv8803->rtc, 1, events); | 171 | rtc_update_irq(rv8803->rtc, 1, events); |
104 | i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); | 172 | rv8803_write_reg(client, RV8803_FLAG, flags); |
105 | i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, | 173 | rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl); |
106 | rv8803->ctrl); | ||
107 | } | 174 | } |
108 | 175 | ||
109 | mutex_unlock(&rv8803->flags_lock); | 176 | mutex_unlock(&rv8803->flags_lock); |
@@ -119,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) | |||
119 | u8 *date = date1; | 186 | u8 *date = date1; |
120 | int ret, flags; | 187 | int ret, flags; |
121 | 188 | ||
122 | flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); | 189 | flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); |
123 | if (flags < 0) | 190 | if (flags < 0) |
124 | return flags; | 191 | return flags; |
125 | 192 | ||
@@ -128,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm) | |||
128 | return -EINVAL; | 195 | return -EINVAL; |
129 | } | 196 | } |
130 | 197 | ||
131 | ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, | 198 | ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date); |
132 | 7, date); | 199 | if (ret) |
133 | if (ret != 7) | 200 | return ret; |
134 | return ret < 0 ? ret : -EIO; | ||
135 | 201 | ||
136 | if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) { | 202 | if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) { |
137 | ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC, | 203 | ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2); |
138 | 7, date2); | 204 | if (ret) |
139 | if (ret != 7) | 205 | return ret; |
140 | return ret < 0 ? ret : -EIO; | ||
141 | 206 | ||
142 | if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59)) | 207 | if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59)) |
143 | date = date2; | 208 | date = date2; |
@@ -171,21 +236,20 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm) | |||
171 | date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1); | 236 | date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1); |
172 | date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100); | 237 | date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100); |
173 | 238 | ||
174 | ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC, | 239 | ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date); |
175 | 7, date); | 240 | if (ret) |
176 | if (ret < 0) | ||
177 | return ret; | 241 | return ret; |
178 | 242 | ||
179 | mutex_lock(&rv8803->flags_lock); | 243 | mutex_lock(&rv8803->flags_lock); |
180 | 244 | ||
181 | flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG); | 245 | flags = rv8803_read_reg(rv8803->client, RV8803_FLAG); |
182 | if (flags < 0) { | 246 | if (flags < 0) { |
183 | mutex_unlock(&rv8803->flags_lock); | 247 | mutex_unlock(&rv8803->flags_lock); |
184 | return flags; | 248 | return flags; |
185 | } | 249 | } |
186 | 250 | ||
187 | ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, | 251 | ret = rv8803_write_reg(rv8803->client, RV8803_FLAG, |
188 | flags & ~RV8803_FLAG_V2F); | 252 | flags & ~RV8803_FLAG_V2F); |
189 | 253 | ||
190 | mutex_unlock(&rv8803->flags_lock); | 254 | mutex_unlock(&rv8803->flags_lock); |
191 | 255 | ||
@@ -199,12 +263,11 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
199 | u8 alarmvals[3]; | 263 | u8 alarmvals[3]; |
200 | int flags, ret; | 264 | int flags, ret; |
201 | 265 | ||
202 | ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN, | 266 | ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals); |
203 | 3, alarmvals); | 267 | if (ret) |
204 | if (ret != 3) | 268 | return ret; |
205 | return ret < 0 ? ret : -EIO; | ||
206 | 269 | ||
207 | flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | 270 | flags = rv8803_read_reg(client, RV8803_FLAG); |
208 | if (flags < 0) | 271 | if (flags < 0) |
209 | return flags; | 272 | return flags; |
210 | 273 | ||
@@ -237,10 +300,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
237 | 300 | ||
238 | mutex_lock(&rv8803->flags_lock); | 301 | mutex_lock(&rv8803->flags_lock); |
239 | 302 | ||
240 | ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl); | 303 | ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl); |
241 | if (ret != 2) { | 304 | if (ret) { |
242 | mutex_unlock(&rv8803->flags_lock); | 305 | mutex_unlock(&rv8803->flags_lock); |
243 | return ret < 0 ? ret : -EIO; | 306 | return ret; |
244 | } | 307 | } |
245 | 308 | ||
246 | alarmvals[0] = bin2bcd(alrm->time.tm_min); | 309 | alarmvals[0] = bin2bcd(alrm->time.tm_min); |
@@ -249,8 +312,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
249 | 312 | ||
250 | if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) { | 313 | if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) { |
251 | rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE); | 314 | rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE); |
252 | err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, | 315 | err = rv8803_write_reg(rv8803->client, RV8803_CTRL, |
253 | rv8803->ctrl); | 316 | rv8803->ctrl); |
254 | if (err) { | 317 | if (err) { |
255 | mutex_unlock(&rv8803->flags_lock); | 318 | mutex_unlock(&rv8803->flags_lock); |
256 | return err; | 319 | return err; |
@@ -258,13 +321,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
258 | } | 321 | } |
259 | 322 | ||
260 | ctrl[1] &= ~RV8803_FLAG_AF; | 323 | ctrl[1] &= ~RV8803_FLAG_AF; |
261 | err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]); | 324 | err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]); |
262 | mutex_unlock(&rv8803->flags_lock); | 325 | mutex_unlock(&rv8803->flags_lock); |
263 | if (err) | 326 | if (err) |
264 | return err; | 327 | return err; |
265 | 328 | ||
266 | err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN, | 329 | err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals); |
267 | 3, alarmvals); | ||
268 | if (err) | 330 | if (err) |
269 | return err; | 331 | return err; |
270 | 332 | ||
@@ -274,8 +336,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
274 | if (rv8803->rtc->aie_timer.enabled) | 336 | if (rv8803->rtc->aie_timer.enabled) |
275 | rv8803->ctrl |= RV8803_CTRL_AIE; | 337 | rv8803->ctrl |= RV8803_CTRL_AIE; |
276 | 338 | ||
277 | err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL, | 339 | err = rv8803_write_reg(rv8803->client, RV8803_CTRL, |
278 | rv8803->ctrl); | 340 | rv8803->ctrl); |
279 | if (err) | 341 | if (err) |
280 | return err; | 342 | return err; |
281 | } | 343 | } |
@@ -304,21 +366,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
304 | } | 366 | } |
305 | 367 | ||
306 | mutex_lock(&rv8803->flags_lock); | 368 | mutex_lock(&rv8803->flags_lock); |
307 | flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | 369 | flags = rv8803_read_reg(client, RV8803_FLAG); |
308 | if (flags < 0) { | 370 | if (flags < 0) { |
309 | mutex_unlock(&rv8803->flags_lock); | 371 | mutex_unlock(&rv8803->flags_lock); |
310 | return flags; | 372 | return flags; |
311 | } | 373 | } |
312 | flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF); | 374 | flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF); |
313 | err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); | 375 | err = rv8803_write_reg(client, RV8803_FLAG, flags); |
314 | mutex_unlock(&rv8803->flags_lock); | 376 | mutex_unlock(&rv8803->flags_lock); |
315 | if (err) | 377 | if (err) |
316 | return err; | 378 | return err; |
317 | 379 | ||
318 | if (ctrl != rv8803->ctrl) { | 380 | if (ctrl != rv8803->ctrl) { |
319 | rv8803->ctrl = ctrl; | 381 | rv8803->ctrl = ctrl; |
320 | err = i2c_smbus_write_byte_data(client, RV8803_CTRL, | 382 | err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl); |
321 | rv8803->ctrl); | ||
322 | if (err) | 383 | if (err) |
323 | return err; | 384 | return err; |
324 | } | 385 | } |
@@ -334,7 +395,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
334 | 395 | ||
335 | switch (cmd) { | 396 | switch (cmd) { |
336 | case RTC_VL_READ: | 397 | case RTC_VL_READ: |
337 | flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | 398 | flags = rv8803_read_reg(client, RV8803_FLAG); |
338 | if (flags < 0) | 399 | if (flags < 0) |
339 | return flags; | 400 | return flags; |
340 | 401 | ||
@@ -353,16 +414,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
353 | 414 | ||
354 | case RTC_VL_CLR: | 415 | case RTC_VL_CLR: |
355 | mutex_lock(&rv8803->flags_lock); | 416 | mutex_lock(&rv8803->flags_lock); |
356 | flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | 417 | flags = rv8803_read_reg(client, RV8803_FLAG); |
357 | if (flags < 0) { | 418 | if (flags < 0) { |
358 | mutex_unlock(&rv8803->flags_lock); | 419 | mutex_unlock(&rv8803->flags_lock); |
359 | return flags; | 420 | return flags; |
360 | } | 421 | } |
361 | 422 | ||
362 | flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F); | 423 | flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F); |
363 | ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags); | 424 | ret = rv8803_write_reg(client, RV8803_FLAG, flags); |
364 | mutex_unlock(&rv8803->flags_lock); | 425 | mutex_unlock(&rv8803->flags_lock); |
365 | if (ret < 0) | 426 | if (ret) |
366 | return ret; | 427 | return ret; |
367 | 428 | ||
368 | return 0; | 429 | return 0; |
@@ -380,8 +441,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj, | |||
380 | struct i2c_client *client = to_i2c_client(dev); | 441 | struct i2c_client *client = to_i2c_client(dev); |
381 | int ret; | 442 | int ret; |
382 | 443 | ||
383 | ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]); | 444 | ret = rv8803_write_reg(client, RV8803_RAM, buf[0]); |
384 | if (ret < 0) | 445 | if (ret) |
385 | return ret; | 446 | return ret; |
386 | 447 | ||
387 | return 1; | 448 | return 1; |
@@ -395,7 +456,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj, | |||
395 | struct i2c_client *client = to_i2c_client(dev); | 456 | struct i2c_client *client = to_i2c_client(dev); |
396 | int ret; | 457 | int ret; |
397 | 458 | ||
398 | ret = i2c_smbus_read_byte_data(client, RV8803_RAM); | 459 | ret = rv8803_read_reg(client, RV8803_RAM); |
399 | if (ret < 0) | 460 | if (ret < 0) |
400 | return ret; | 461 | return ret; |
401 | 462 | ||
@@ -425,7 +486,7 @@ static int rv8803_probe(struct i2c_client *client, | |||
425 | { | 486 | { |
426 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 487 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
427 | struct rv8803_data *rv8803; | 488 | struct rv8803_data *rv8803; |
428 | int err, flags, try = 0; | 489 | int err, flags; |
429 | 490 | ||
430 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | | 491 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | |
431 | I2C_FUNC_SMBUS_I2C_BLOCK)) { | 492 | I2C_FUNC_SMBUS_I2C_BLOCK)) { |
@@ -442,16 +503,7 @@ static int rv8803_probe(struct i2c_client *client, | |||
442 | rv8803->client = client; | 503 | rv8803->client = client; |
443 | i2c_set_clientdata(client, rv8803); | 504 | i2c_set_clientdata(client, rv8803); |
444 | 505 | ||
445 | /* | 506 | flags = rv8803_read_reg(client, RV8803_FLAG); |
446 | * There is a 60µs window where the RTC may not reply on the i2c bus in | ||
447 | * that case, the transfer is not ACKed. In that case, ensure there are | ||
448 | * multiple attempts. | ||
449 | */ | ||
450 | do { | ||
451 | flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); | ||
452 | try++; | ||
453 | } while (((flags == -ENXIO) || (flags == -EIO)) && (try < 4)); | ||
454 | |||
455 | if (flags < 0) | 507 | if (flags < 0) |
456 | return flags; | 508 | return flags; |
457 | 509 | ||
@@ -486,12 +538,7 @@ static int rv8803_probe(struct i2c_client *client, | |||
486 | return PTR_ERR(rv8803->rtc); | 538 | return PTR_ERR(rv8803->rtc); |
487 | } | 539 | } |
488 | 540 | ||
489 | try = 0; | 541 | err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); |
490 | do { | ||
491 | err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT, | ||
492 | RV8803_EXT_WADA); | ||
493 | try++; | ||
494 | } while (((err == -ENXIO) || (flags == -EIO)) && (try < 4)); | ||
495 | if (err) | 542 | if (err) |
496 | return err; | 543 | return err; |
497 | 544 | ||