aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-s35390a.c')
-rw-r--r--drivers/rtc/rtc-s35390a.c167
1 files changed, 131 insertions, 36 deletions
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index f40afdd0e5f5..00662dd28d66 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)
@@ -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;
@@ -265,27 +316,61 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
265 char buf[3], sts; 316 char buf[3], sts;
266 int i, err; 317 int i, err;
267 318
319 /*
320 * initialize all members to -1 to signal the core that they are not
321 * defined by the hardware.
322 */
323 alm->time.tm_sec = -1;
324 alm->time.tm_min = -1;
325 alm->time.tm_hour = -1;
326 alm->time.tm_mday = -1;
327 alm->time.tm_mon = -1;
328 alm->time.tm_year = -1;
329 alm->time.tm_wday = -1;
330 alm->time.tm_yday = -1;
331 alm->time.tm_isdst = -1;
332
268 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); 333 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
269 if (err < 0) 334 if (err < 0)
270 return err; 335 return err;
271 336
272 if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) 337 if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
273 return -EINVAL; 338 /*
339 * When the alarm isn't enabled, the register to configure
340 * the alarm time isn't accessible.
341 */
342 alm->enabled = 0;
343 return 0;
344 } else {
345 alm->enabled = 1;
346 }
274 347
275 err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); 348 err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
276 if (err < 0) 349 if (err < 0)
277 return err; 350 return err;
278 351
279 /* This chip returns the bits of each byte in reverse order */ 352 /* This chip returns the bits of each byte in reverse order */
280 for (i = 0; i < 3; ++i) { 353 for (i = 0; i < 3; ++i)
281 buf[i] = bitrev8(buf[i]); 354 buf[i] = bitrev8(buf[i]);
282 buf[i] &= ~0x80;
283 }
284 355
285 alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); 356 /*
286 alm->time.tm_hour = s35390a_reg2hr(s35390a, 357 * B0 of the three matching registers is an enable flag. Iff it is set
287 buf[S35390A_ALRM_BYTE_HOURS]); 358 * the configured value is used for matching.
288 alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); 359 */
360 if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
361 alm->time.tm_wday =
362 bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
363
364 if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
365 alm->time.tm_hour =
366 s35390a_reg2hr(s35390a,
367 buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
368
369 if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
370 alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
371
372 /* alarm triggers always at s=0 */
373 alm->time.tm_sec = 0;
289 374
290 dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", 375 dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
291 __func__, alm->time.tm_min, alm->time.tm_hour, 376 __func__, alm->time.tm_min, alm->time.tm_hour,
@@ -327,11 +412,11 @@ static struct i2c_driver s35390a_driver;
327static int s35390a_probe(struct i2c_client *client, 412static int s35390a_probe(struct i2c_client *client,
328 const struct i2c_device_id *id) 413 const struct i2c_device_id *id)
329{ 414{
330 int err; 415 int err, err_reset;
331 unsigned int i; 416 unsigned int i;
332 struct s35390a *s35390a; 417 struct s35390a *s35390a;
333 struct rtc_time tm; 418 struct rtc_time tm;
334 char buf[1]; 419 char buf, status1;
335 420
336 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 421 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
337 err = -ENODEV; 422 err = -ENODEV;
@@ -360,29 +445,35 @@ static int s35390a_probe(struct i2c_client *client,
360 } 445 }
361 } 446 }
362 447
363 err = s35390a_reset(s35390a); 448 err_reset = s35390a_reset(s35390a, &status1);
364 if (err < 0) { 449 if (err_reset < 0) {
450 err = err_reset;
365 dev_err(&client->dev, "error resetting chip\n"); 451 dev_err(&client->dev, "error resetting chip\n");
366 goto exit_dummy; 452 goto exit_dummy;
367 } 453 }
368 454
369 err = s35390a_disable_test_mode(s35390a); 455 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; 456 s35390a->twentyfourhour = 1;
382 else 457 else
383 s35390a->twentyfourhour = 0; 458 s35390a->twentyfourhour = 0;
384 459
385 if (s35390a_get_datetime(client, &tm) < 0) 460 if (status1 & S35390A_FLAG_INT2) {
461 /* disable alarm (and maybe test mode) */
462 buf = 0;
463 err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
464 if (err < 0) {
465 dev_err(&client->dev, "error disabling alarm");
466 goto exit_dummy;
467 }
468 } else {
469 err = s35390a_disable_test_mode(s35390a);
470 if (err < 0) {
471 dev_err(&client->dev, "error disabling test mode\n");
472 goto exit_dummy;
473 }
474 }
475
476 if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
386 dev_warn(&client->dev, "clock needs to be set\n"); 477 dev_warn(&client->dev, "clock needs to be set\n");
387 478
388 device_set_wakeup_capable(&client->dev, 1); 479 device_set_wakeup_capable(&client->dev, 1);
@@ -395,6 +486,10 @@ static int s35390a_probe(struct i2c_client *client,
395 err = PTR_ERR(s35390a->rtc); 486 err = PTR_ERR(s35390a->rtc);
396 goto exit_dummy; 487 goto exit_dummy;
397 } 488 }
489
490 if (status1 & S35390A_FLAG_INT2)
491 rtc_update_irq(s35390a->rtc, 1, RTC_AF);
492
398 return 0; 493 return 0;
399 494
400exit_dummy: 495exit_dummy: