aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorArnaud Ebalard <arno@natisbad.org>2015-02-13 17:41:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-14 00:21:43 -0500
commitc8a1d8a523e1018c3b7d23c7e1c99bf20006bcbf (patch)
treef1f435d1a863c7faac6589402ef7c1a104caadf2 /drivers/rtc
parent0b2f6228b2909a82006f87d28df45a0725a95094 (diff)
rtc: rtc-ab-b5ze-s3: add sub-minute alarm support
Abracon AB-RTCMC-32.768kHz-B5ZE-S3 alarm is only accurate to the minute. For that reason, UIE mode is currently not supported by the driver. But the device provides a watchdog timer which can be coupled with the alarm mechanism to extend support and provide sub-minute alarm capability. This patch implements that extension. More precisely, it makes use of the watchdog timer for alarms which are less that four minutes in the future (with second accuracy) and use standard alarm mechanism for other alarms (with minute accuracy). Signed-off-by: Arnaud Ebalard <arno@natisbad.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Peter Huewe <peter.huewe@infineon.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Thierry Reding <treding@nvidia.com> Cc: Mark Brown <broonie@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Rob Herring <robherring2@gmail.com> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Stephen Warren <swarren@wwwdotorg.org> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk> Cc: Grant Likely <grant.likely@linaro.org> Cc: Rob Landley <rob@landley.net> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Cc: Kumar Gala <galak@codeaurora.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c291
1 files changed, 262 insertions, 29 deletions
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index bbbf06f55e17..cfc2ef98d393 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -133,6 +133,7 @@ struct abb5zes3_rtc_data {
133 int irq; 133 int irq;
134 134
135 bool battery_low; 135 bool battery_low;
136 bool timer_alarm; /* current alarm is via timer A */
136}; 137};
137 138
138/* 139/*
@@ -192,6 +193,22 @@ static int _abb5zes3_rtc_update_alarm(struct device *dev, bool enable)
192 return ret; 193 return ret;
193} 194}
194 195
196/* Enable or disable timer (watchdog timer A interrupt generation) */
197static int _abb5zes3_rtc_update_timer(struct device *dev, bool enable)
198{
199 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
200 int ret;
201
202 ret = regmap_update_bits(data->regmap, ABB5ZES3_REG_CTRL2,
203 ABB5ZES3_REG_CTRL2_WTAIE,
204 enable ? ABB5ZES3_REG_CTRL2_WTAIE : 0);
205 if (ret)
206 dev_err(dev, "%s: writing timer INT failed (%d)\n",
207 __func__, ret);
208
209 return ret;
210}
211
195/* 212/*
196 * Note: we only read, so regmap inner lock protection is sufficient, i.e. 213 * Note: we only read, so regmap inner lock protection is sufficient, i.e.
197 * we do not need driver's main lock protection. 214 * we do not need driver's main lock protection.
@@ -277,7 +294,92 @@ static int abb5zes3_rtc_set_time(struct device *dev, struct rtc_time *tm)
277 return ret; 294 return ret;
278} 295}
279 296
280static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) 297/*
298 * Set provided TAQ and Timer A registers (TIMA_CLK and TIMA) based on
299 * given number of seconds.
300 */
301static inline void sec_to_timer_a(u8 secs, u8 *taq, u8 *timer_a)
302{
303 *taq = ABB5ZES3_REG_TIMA_CLK_TAQ1; /* 1Hz */
304 *timer_a = secs;
305}
306
307/*
308 * Return current number of seconds in Timer A. As we only use
309 * timer A with a 1Hz freq, this is what we expect to have.
310 */
311static inline int sec_from_timer_a(u8 *secs, u8 taq, u8 timer_a)
312{
313 if (taq != ABB5ZES3_REG_TIMA_CLK_TAQ1) /* 1Hz */
314 return -EINVAL;
315
316 *secs = timer_a;
317
318 return 0;
319}
320
321/*
322 * Read alarm currently configured via a watchdog timer using timer A. This
323 * is done by reading current RTC time and adding remaining timer time.
324 */
325static int _abb5zes3_rtc_read_timer(struct device *dev,
326 struct rtc_wkalrm *alarm)
327{
328 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
329 struct rtc_time rtc_tm, *alarm_tm = &alarm->time;
330 u8 regs[ABB5ZES3_TIMA_SEC_LEN + 1];
331 unsigned long rtc_secs;
332 unsigned int reg;
333 u8 timer_secs;
334 int ret;
335
336 /*
337 * Instead of doing two separate calls, because they are consecutive,
338 * we grab both clockout register and Timer A section. The latter is
339 * used to decide if timer A is enabled (as a watchdog timer).
340 */
341 ret = regmap_bulk_read(data->regmap, ABB5ZES3_REG_TIM_CLK, regs,
342 ABB5ZES3_TIMA_SEC_LEN + 1);
343 if (ret) {
344 dev_err(dev, "%s: reading Timer A section failed (%d)\n",
345 __func__, ret);
346 goto err;
347 }
348
349 /* get current time ... */
350 ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
351 if (ret)
352 goto err;
353
354 /* ... convert to seconds ... */
355 ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
356 if (ret)
357 goto err;
358
359 /* ... add remaining timer A time ... */
360 ret = sec_from_timer_a(&timer_secs, regs[1], regs[2]);
361 if (ret)
362 goto err;
363
364 /* ... and convert back. */
365 rtc_time_to_tm(rtc_secs + timer_secs, alarm_tm);
366
367 ret = regmap_read(data->regmap, ABB5ZES3_REG_CTRL2, &reg);
368 if (ret) {
369 dev_err(dev, "%s: reading ctrl reg failed (%d)\n",
370 __func__, ret);
371 goto err;
372 }
373
374 alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL2_WTAIE);
375
376err:
377 return ret;
378}
379
380/* Read alarm currently configured via a RTC alarm registers. */
381static int _abb5zes3_rtc_read_alarm(struct device *dev,
382 struct rtc_wkalrm *alarm)
281{ 383{
282 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 384 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
283 struct rtc_time rtc_tm, *alarm_tm = &alarm->time; 385 struct rtc_time rtc_tm, *alarm_tm = &alarm->time;
@@ -286,7 +388,6 @@ static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
286 unsigned int reg; 388 unsigned int reg;
287 int ret; 389 int ret;
288 390
289 mutex_lock(&data->lock);
290 ret = regmap_bulk_read(data->regmap, ABB5ZES3_REG_ALRM_MN, regs, 391 ret = regmap_bulk_read(data->regmap, ABB5ZES3_REG_ALRM_MN, regs,
291 ABB5ZES3_ALRM_SEC_LEN); 392 ABB5ZES3_ALRM_SEC_LEN);
292 if (ret) { 393 if (ret) {
@@ -340,13 +441,39 @@ static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
340 alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL1_AIE); 441 alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL1_AIE);
341 442
342err: 443err:
444 return ret;
445}
446
447/*
448 * As the Alarm mechanism supported by the chip is only accurate to the
449 * minute, we use the watchdog timer mechanism provided by timer A
450 * (up to 256 seconds w/ a second accuracy) for low alarm values (below
451 * 4 minutes). Otherwise, we use the common alarm mechanism provided
452 * by the chip. In order for that to work, we keep track of currently
453 * configured timer type via 'timer_alarm' flag in our private data
454 * structure.
455 */
456static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
457{
458 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
459 int ret;
460
461 mutex_lock(&data->lock);
462 if (data->timer_alarm)
463 ret = _abb5zes3_rtc_read_timer(dev, alarm);
464 else
465 ret = _abb5zes3_rtc_read_alarm(dev, alarm);
343 mutex_unlock(&data->lock); 466 mutex_unlock(&data->lock);
344 467
345 return ret; 468 return ret;
346} 469}
347 470
348/* ALARM is only accurate to the minute (not the second) */ 471/*
349static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 472 * Set alarm using chip alarm mechanism. It is only accurate to the
473 * minute (not the second). The function expects alarm interrupt to
474 * be disabled.
475 */
476static int _abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
350{ 477{
351 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 478 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
352 struct rtc_time *alarm_tm = &alarm->time; 479 struct rtc_time *alarm_tm = &alarm->time;
@@ -355,7 +482,6 @@ static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
355 struct rtc_time rtc_tm; 482 struct rtc_time rtc_tm;
356 int ret, enable = 1; 483 int ret, enable = 1;
357 484
358 mutex_lock(&data->lock);
359 ret = _abb5zes3_rtc_read_time(dev, &rtc_tm); 485 ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
360 if (ret) 486 if (ret)
361 goto err; 487 goto err;
@@ -397,18 +523,13 @@ static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
397 } 523 }
398 } 524 }
399 525
400 /* Disable the alarm before modifying it */ 526 /*
401 ret = _abb5zes3_rtc_update_alarm(dev, 0); 527 * Program all alarm registers but DW one. For each register, setting
402 if (ret < 0) { 528 * MSB to 0 enables associated alarm.
403 dev_err(dev, "%s: unable to disable the alarm (%d)\n", 529 */
404 __func__, ret); 530 regs[0] = bin2bcd(alarm_tm->tm_min) & 0x7f;
405 goto err; 531 regs[1] = bin2bcd(alarm_tm->tm_hour) & 0x3f;
406 } 532 regs[2] = bin2bcd(alarm_tm->tm_mday) & 0x3f;
407
408 /* Program alarm registers */
409 regs[0] = bin2bcd(alarm_tm->tm_min) & 0x7f; /* minute */
410 regs[1] = bin2bcd(alarm_tm->tm_hour) & 0x3f; /* hour */
411 regs[2] = bin2bcd(alarm_tm->tm_mday) & 0x3f; /* day of the month */
412 regs[3] = ABB5ZES3_REG_ALRM_DW_AE; /* do not match day of the week */ 533 regs[3] = ABB5ZES3_REG_ALRM_DW_AE; /* do not match day of the week */
413 534
414 ret = regmap_bulk_write(data->regmap, ABB5ZES3_REG_ALRM_MN, regs, 535 ret = regmap_bulk_write(data->regmap, ABB5ZES3_REG_ALRM_MN, regs,
@@ -419,15 +540,115 @@ static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
419 goto err; 540 goto err;
420 } 541 }
421 542
422 /* Enable or disable alarm */ 543 /* Record currently configured alarm is not a timer */
544 data->timer_alarm = 0;
545
546 /* Enable or disable alarm interrupt generation */
423 ret = _abb5zes3_rtc_update_alarm(dev, enable); 547 ret = _abb5zes3_rtc_update_alarm(dev, enable);
424 548
425err: 549err:
426 mutex_unlock(&data->lock); 550 return ret;
551}
552
553/*
554 * Set alarm using timer watchdog (via timer A) mechanism. The function expects
555 * timer A interrupt to be disabled.
556 */
557static int _abb5zes3_rtc_set_timer(struct device *dev, struct rtc_wkalrm *alarm,
558 u8 secs)
559{
560 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
561 u8 regs[ABB5ZES3_TIMA_SEC_LEN];
562 u8 mask = ABB5ZES3_REG_TIM_CLK_TAC0 | ABB5ZES3_REG_TIM_CLK_TAC1;
563 int ret = 0;
564
565 /* Program given number of seconds to Timer A registers */
566 sec_to_timer_a(secs, &regs[0], &regs[1]);
567 ret = regmap_bulk_write(data->regmap, ABB5ZES3_REG_TIMA_CLK, regs,
568 ABB5ZES3_TIMA_SEC_LEN);
569 if (ret < 0) {
570 dev_err(dev, "%s: writing timer section failed\n", __func__);
571 goto err;
572 }
573
574 /* Configure Timer A as a watchdog timer */
575 ret = regmap_update_bits(data->regmap, ABB5ZES3_REG_TIM_CLK,
576 mask, ABB5ZES3_REG_TIM_CLK_TAC1);
577 if (ret)
578 dev_err(dev, "%s: failed to update timer\n", __func__);
579
580 /* Record currently configured alarm is a timer */
581 data->timer_alarm = 1;
427 582
583 /* Enable or disable timer interrupt generation */
584 ret = _abb5zes3_rtc_update_timer(dev, alarm->enabled);
585
586err:
428 return ret; 587 return ret;
429} 588}
430 589
590/*
591 * The chip has an alarm which is only accurate to the minute. In order to
592 * handle alarms below that limit, we use the watchdog timer function of
593 * timer A. More precisely, the timer method is used for alarms below 240
594 * seconds.
595 */
596static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
597{
598 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
599 struct rtc_time *alarm_tm = &alarm->time;
600 unsigned long rtc_secs, alarm_secs;
601 struct rtc_time rtc_tm;
602 int ret;
603
604 mutex_lock(&data->lock);
605 ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
606 if (ret)
607 goto err;
608
609 ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
610 if (ret)
611 goto err;
612
613 ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
614 if (ret)
615 goto err;
616
617 /* Let's first disable both the alarm and the timer interrupts */
618 ret = _abb5zes3_rtc_update_alarm(dev, false);
619 if (ret < 0) {
620 dev_err(dev, "%s: unable to disable alarm (%d)\n", __func__,
621 ret);
622 goto err;
623 }
624 ret = _abb5zes3_rtc_update_timer(dev, false);
625 if (ret < 0) {
626 dev_err(dev, "%s: unable to disable timer (%d)\n", __func__,
627 ret);
628 goto err;
629 }
630
631 data->timer_alarm = 0;
632
633 /*
634 * Let's now configure the alarm; if we are expected to ring in
635 * more than 240s, then we setup an alarm. Otherwise, a timer.
636 */
637 if ((alarm_secs > rtc_secs) && ((alarm_secs - rtc_secs) <= 240))
638 ret = _abb5zes3_rtc_set_timer(dev, alarm,
639 alarm_secs - rtc_secs);
640 else
641 ret = _abb5zes3_rtc_set_alarm(dev, alarm);
642
643 err:
644 mutex_unlock(&data->lock);
645
646 if (ret)
647 dev_err(dev, "%s: unable to configure alarm (%d)\n", __func__,
648 ret);
649
650 return ret;
651 }
431 652
432/* Enable or disable battery low irq generation */ 653/* Enable or disable battery low irq generation */
433static inline int _abb5zes3_rtc_battery_low_irq_enable(struct regmap *regmap, 654static inline int _abb5zes3_rtc_battery_low_irq_enable(struct regmap *regmap,
@@ -446,7 +667,7 @@ static inline int _abb5zes3_rtc_battery_low_irq_enable(struct regmap *regmap,
446static int abb5zes3_rtc_check_setup(struct device *dev) 667static int abb5zes3_rtc_check_setup(struct device *dev)
447{ 668{
448 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 669 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
449 struct regmap *regmap = data->regmap; 670 struct regmap *regmap = data->regmap;
450 unsigned int reg; 671 unsigned int reg;
451 int ret; 672 int ret;
452 u8 mask; 673 u8 mask;
@@ -579,7 +800,10 @@ static int abb5zes3_rtc_alarm_irq_enable(struct device *dev,
579 800
580 if (rtc_data->irq) { 801 if (rtc_data->irq) {
581 mutex_lock(&rtc_data->lock); 802 mutex_lock(&rtc_data->lock);
582 ret = _abb5zes3_rtc_update_alarm(dev, enable); 803 if (rtc_data->timer_alarm)
804 ret = _abb5zes3_rtc_update_timer(dev, enable);
805 else
806 ret = _abb5zes3_rtc_update_alarm(dev, enable);
583 mutex_unlock(&rtc_data->lock); 807 mutex_unlock(&rtc_data->lock);
584 } 808 }
585 809
@@ -629,6 +853,23 @@ static irqreturn_t _abb5zes3_rtc_interrupt(int irq, void *data)
629 handled = IRQ_HANDLED; 853 handled = IRQ_HANDLED;
630 } 854 }
631 855
856 /* Check watchdog Timer A flag */
857 if (regs[ABB5ZES3_REG_CTRL2] & ABB5ZES3_REG_CTRL2_WTAF) {
858 dev_dbg(dev, "RTC timer!\n");
859
860 rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
861
862 /*
863 * Acknowledge and disable the alarm. Note: WTAF
864 * flag had been cleared when reading CTRL2
865 */
866 _abb5zes3_rtc_update_timer(dev, 0);
867
868 rtc_data->timer_alarm = 0;
869
870 handled = IRQ_HANDLED;
871 }
872
632 return handled; 873 return handled;
633} 874}
634 875
@@ -712,14 +953,6 @@ static int abb5zes3_probe(struct i2c_client *client,
712 goto err; 953 goto err;
713 } 954 }
714 955
715 /*
716 * AB-B5Z5E only supports a coarse granularity alarm (one minute
717 * resolution up to one month) so we cannot support UIE mode
718 * using the device's alarm. Note it should be feasible to support
719 * such a feature using one of the two timers the device provides.
720 */
721 data->rtc->uie_unsupported = 1;
722
723 /* Enable battery low detection interrupt if battery not already low */ 956 /* Enable battery low detection interrupt if battery not already low */
724 if (!data->battery_low && data->irq) { 957 if (!data->battery_low && data->irq) {
725 ret = _abb5zes3_rtc_battery_low_irq_enable(regmap, true); 958 ret = _abb5zes3_rtc_battery_low_irq_enable(regmap, true);