aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-s35390a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-s35390a.c')
-rw-r--r--drivers/rtc/rtc-s35390a.c157
1 files changed, 119 insertions, 38 deletions
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index f40afdd0e5f5..5dab4665ca3b 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -15,6 +15,7 @@
15#include <linux/bitrev.h> 15#include <linux/bitrev.h>
16#include <linux/bcd.h> 16#include <linux/bcd.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/delay.h>
18 19
19#define S35390A_CMD_STATUS1 0 20#define S35390A_CMD_STATUS1 0
20#define S35390A_CMD_STATUS2 1 21#define S35390A_CMD_STATUS2 1
@@ -34,10 +35,14 @@
34#define S35390A_ALRM_BYTE_HOURS 1 35#define S35390A_ALRM_BYTE_HOURS 1
35#define S35390A_ALRM_BYTE_MINS 2 36#define S35390A_ALRM_BYTE_MINS 2
36 37
38/* flags for STATUS1 */
37#define S35390A_FLAG_POC 0x01 39#define S35390A_FLAG_POC 0x01
38#define S35390A_FLAG_BLD 0x02 40#define S35390A_FLAG_BLD 0x02
41#define S35390A_FLAG_INT2 0x04
39#define S35390A_FLAG_24H 0x40 42#define S35390A_FLAG_24H 0x40
40#define S35390A_FLAG_RESET 0x80 43#define S35390A_FLAG_RESET 0x80
44
45/* flag for STATUS2 */
41#define S35390A_FLAG_TEST 0x01 46#define S35390A_FLAG_TEST 0x01
42 47
43#define S35390A_INT2_MODE_MASK 0xF0 48#define S35390A_INT2_MODE_MASK 0xF0
@@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
94 return 0; 99 return 0;
95} 100}
96 101
97static int s35390a_reset(struct s35390a *s35390a) 102/*
103 * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
104 * To keep the information if an irq is pending, pass the value read from
105 * STATUS1 to the caller.
106 */
107static int s35390a_reset(struct s35390a *s35390a, char *status1)
98{ 108{
99 char buf[1]; 109 char buf;
100 110 int ret;
101 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0) 111 unsigned initcount = 0;
102 return -EIO; 112
103 113 ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
104 if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD))) 114 if (ret < 0)
115 return ret;
116
117 if (*status1 & S35390A_FLAG_POC)
118 /*
119 * Do not communicate for 0.5 seconds since the power-on
120 * detection circuit is in operation.
121 */
122 msleep(500);
123 else if (!(*status1 & S35390A_FLAG_BLD))
124 /*
125 * If both POC and BLD are unset everything is fine.
126 */
105 return 0; 127 return 0;
106 128
107 buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H); 129 /*
108 buf[0] &= 0xf0; 130 * At least one of POC and BLD are set, so reinitialise chip. Keeping
109 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); 131 * this information in the hardware to know later that the time isn't
132 * valid is unfortunately not possible because POC and BLD are cleared
133 * on read. So the reset is best done now.
134 *
135 * The 24H bit is kept over reset, so set it already here.
136 */
137initialize:
138 *status1 = S35390A_FLAG_24H;
139 buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
140 ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
141
142 if (ret < 0)
143 return ret;
144
145 ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
146 if (ret < 0)
147 return ret;
148
149 if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
150 /* Try up to five times to reset the chip */
151 if (initcount < 5) {
152 ++initcount;
153 goto initialize;
154 } else
155 return -EIO;
156 }
157
158 return 1;
110} 159}
111 160
112static int s35390a_disable_test_mode(struct s35390a *s35390a) 161static int s35390a_disable_test_mode(struct s35390a *s35390a)
@@ -217,12 +266,12 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
217 alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, 266 alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
218 alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); 267 alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
219 268
220 /* disable interrupt */ 269 /* disable interrupt (which deasserts the irq line) */
221 err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); 270 err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
222 if (err < 0) 271 if (err < 0)
223 return err; 272 return err;
224 273
225 /* clear pending interrupt, if any */ 274 /* clear pending interrupt (in STATUS1 only), if any */
226 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); 275 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));
227 if (err < 0) 276 if (err < 0)
228 return err; 277 return err;
@@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
242 291
243 if (alm->time.tm_wday != -1) 292 if (alm->time.tm_wday != -1)
244 buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; 293 buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
294 else
295 buf[S35390A_ALRM_BYTE_WDAY] = 0;
245 296
246 buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, 297 buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
247 alm->time.tm_hour) | 0x80; 298 alm->time.tm_hour) | 0x80;
@@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
269 if (err < 0) 320 if (err < 0)
270 return err; 321 return err;
271 322
272 if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) 323 if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
273 return -EINVAL; 324 /*
325 * When the alarm isn't enabled, the register to configure
326 * the alarm time isn't accessible.
327 */
328 alm->enabled = 0;
329 return 0;
330 } else {
331 alm->enabled = 1;
332 }
274 333
275 err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); 334 err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
276 if (err < 0) 335 if (err < 0)
277 return err; 336 return err;
278 337
279 /* This chip returns the bits of each byte in reverse order */ 338 /* This chip returns the bits of each byte in reverse order */
280 for (i = 0; i < 3; ++i) { 339 for (i = 0; i < 3; ++i)
281 buf[i] = bitrev8(buf[i]); 340 buf[i] = bitrev8(buf[i]);
282 buf[i] &= ~0x80;
283 }
284 341
285 alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); 342 /*
286 alm->time.tm_hour = s35390a_reg2hr(s35390a, 343 * B0 of the three matching registers is an enable flag. Iff it is set
287 buf[S35390A_ALRM_BYTE_HOURS]); 344 * the configured value is used for matching.
288 alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); 345 */
346 if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
347 alm->time.tm_wday =
348 bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
349
350 if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
351 alm->time.tm_hour =
352 s35390a_reg2hr(s35390a,
353 buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
354
355 if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
356 alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
357
358 /* alarm triggers always at s=0 */
359 alm->time.tm_sec = 0;
289 360
290 dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", 361 dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
291 __func__, alm->time.tm_min, alm->time.tm_hour, 362 __func__, alm->time.tm_min, alm->time.tm_hour,
@@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver;
327static int s35390a_probe(struct i2c_client *client, 398static int s35390a_probe(struct i2c_client *client,
328 const struct i2c_device_id *id) 399 const struct i2c_device_id *id)
329{ 400{
330 int err; 401 int err, err_reset;
331 unsigned int i; 402 unsigned int i;
332 struct s35390a *s35390a; 403 struct s35390a *s35390a;
333 struct rtc_time tm; 404 struct rtc_time tm;
334 char buf[1]; 405 char buf, status1;
335 406
336 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 407 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
337 err = -ENODEV; 408 err = -ENODEV;
@@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client,
360 } 431 }
361 } 432 }
362 433
363 err = s35390a_reset(s35390a); 434 err_reset = s35390a_reset(s35390a, &status1);
364 if (err < 0) { 435 if (err_reset < 0) {
436 err = err_reset;
365 dev_err(&client->dev, "error resetting chip\n"); 437 dev_err(&client->dev, "error resetting chip\n");
366 goto exit_dummy; 438 goto exit_dummy;
367 } 439 }
368 440
369 err = s35390a_disable_test_mode(s35390a); 441 if (status1 & S35390A_FLAG_24H)
370 if (err < 0) {
371 dev_err(&client->dev, "error disabling test mode\n");
372 goto exit_dummy;
373 }
374
375 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
376 if (err < 0) {
377 dev_err(&client->dev, "error checking 12/24 hour mode\n");
378 goto exit_dummy;
379 }
380 if (buf[0] & S35390A_FLAG_24H)
381 s35390a->twentyfourhour = 1; 442 s35390a->twentyfourhour = 1;
382 else 443 else
383 s35390a->twentyfourhour = 0; 444 s35390a->twentyfourhour = 0;
384 445
385 if (s35390a_get_datetime(client, &tm) < 0) 446 if (status1 & S35390A_FLAG_INT2) {
447 /* disable alarm (and maybe test mode) */
448 buf = 0;
449 err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
450 if (err < 0) {
451 dev_err(&client->dev, "error disabling alarm");
452 goto exit_dummy;
453 }
454 } else {
455 err = s35390a_disable_test_mode(s35390a);
456 if (err < 0) {
457 dev_err(&client->dev, "error disabling test mode\n");
458 goto exit_dummy;
459 }
460 }
461
462 if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
386 dev_warn(&client->dev, "clock needs to be set\n"); 463 dev_warn(&client->dev, "clock needs to be set\n");
387 464
388 device_set_wakeup_capable(&client->dev, 1); 465 device_set_wakeup_capable(&client->dev, 1);
@@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client,
395 err = PTR_ERR(s35390a->rtc); 472 err = PTR_ERR(s35390a->rtc);
396 goto exit_dummy; 473 goto exit_dummy;
397 } 474 }
475
476 if (status1 & S35390A_FLAG_INT2)
477 rtc_update_irq(s35390a->rtc, 1, RTC_AF);
478
398 return 0; 479 return 0;
399 480
400exit_dummy: 481exit_dummy: