aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorHebbar Gururaja <gururaja.hebbar@ti.com>2013-09-11 17:24:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:58:54 -0400
commit8af750e3f5ca21eaa5595a96a4cf5eaa996deed4 (patch)
tree7118ce404a069e098ab779a2d764de8c798c9c79 /drivers/rtc
parent453b4c6db59f7f6411a0b5eb58389a1fa129cc9a (diff)
drivers/rtc/rtc-omap.c: add rtc wakeup support to alarm events
On some platforms (like AM33xx), a special register (RTC_IRQWAKEEN) is available to enable Alarm Wakeup feature. This register needs to be properly handled for the rtcwake to work properly. Platforms using such IP should set "ti,am3352-rtc" in rtc device dt compatibility node. Signed-off-by: Hebbar Gururaja <gururaja.hebbar@ti.com> Acked-by: Kevin Hilman <khilman@linaro.org> Acked-by: Sekhar Nori <nsekhar@ti.com> Cc: Grant Likely <grant.likely@linaro.org> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Rob Landley <rob@landley.net> Cc: Alessandro Zummo <a.zummo@towertech.it> 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-omap.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index c6ffbaec32a4..c7d97ee59327 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -70,6 +70,8 @@
70#define OMAP_RTC_KICK0_REG 0x6c 70#define OMAP_RTC_KICK0_REG 0x6c
71#define OMAP_RTC_KICK1_REG 0x70 71#define OMAP_RTC_KICK1_REG 0x70
72 72
73#define OMAP_RTC_IRQWAKEEN 0x7c
74
73/* OMAP_RTC_CTRL_REG bit fields: */ 75/* OMAP_RTC_CTRL_REG bit fields: */
74#define OMAP_RTC_CTRL_SPLIT (1<<7) 76#define OMAP_RTC_CTRL_SPLIT (1<<7)
75#define OMAP_RTC_CTRL_DISABLE (1<<6) 77#define OMAP_RTC_CTRL_DISABLE (1<<6)
@@ -94,12 +96,21 @@
94#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) 96#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3)
95#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) 97#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2)
96 98
99/* OMAP_RTC_IRQWAKEEN bit fields: */
100#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1)
101
97/* OMAP_RTC_KICKER values */ 102/* OMAP_RTC_KICKER values */
98#define KICK0_VALUE 0x83e70b13 103#define KICK0_VALUE 0x83e70b13
99#define KICK1_VALUE 0x95a4f1e0 104#define KICK1_VALUE 0x95a4f1e0
100 105
101#define OMAP_RTC_HAS_KICKER 0x1 106#define OMAP_RTC_HAS_KICKER 0x1
102 107
108/*
109 * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
110 * generation for event Alarm.
111 */
112#define OMAP_RTC_HAS_IRQWAKEEN 0x2
113
103static void __iomem *rtc_base; 114static void __iomem *rtc_base;
104 115
105#define rtc_read(addr) readb(rtc_base + (addr)) 116#define rtc_read(addr) readb(rtc_base + (addr))
@@ -299,12 +310,18 @@ static struct rtc_class_ops omap_rtc_ops = {
299static int omap_rtc_alarm; 310static int omap_rtc_alarm;
300static int omap_rtc_timer; 311static int omap_rtc_timer;
301 312
302#define OMAP_RTC_DATA_DA830_IDX 1 313#define OMAP_RTC_DATA_AM3352_IDX 1
314#define OMAP_RTC_DATA_DA830_IDX 2
303 315
304static struct platform_device_id omap_rtc_devtype[] = { 316static struct platform_device_id omap_rtc_devtype[] = {
305 { 317 {
306 .name = DRIVER_NAME, 318 .name = DRIVER_NAME,
307 }, { 319 },
320 [OMAP_RTC_DATA_AM3352_IDX] = {
321 .name = "am3352-rtc",
322 .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
323 },
324 [OMAP_RTC_DATA_DA830_IDX] = {
308 .name = "da830-rtc", 325 .name = "da830-rtc",
309 .driver_data = OMAP_RTC_HAS_KICKER, 326 .driver_data = OMAP_RTC_HAS_KICKER,
310 }, 327 },
@@ -316,6 +333,9 @@ static const struct of_device_id omap_rtc_of_match[] = {
316 { .compatible = "ti,da830-rtc", 333 { .compatible = "ti,da830-rtc",
317 .data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX], 334 .data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
318 }, 335 },
336 { .compatible = "ti,am3352-rtc",
337 .data = &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
338 },
319 {}, 339 {},
320}; 340};
321MODULE_DEVICE_TABLE(of, omap_rtc_of_match); 341MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
@@ -464,16 +484,28 @@ static u8 irqstat;
464 484
465static int omap_rtc_suspend(struct device *dev) 485static int omap_rtc_suspend(struct device *dev)
466{ 486{
487 u8 irqwake_stat;
488 struct platform_device *pdev = to_platform_device(dev);
489 const struct platform_device_id *id_entry =
490 platform_get_device_id(pdev);
491
467 irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); 492 irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
468 493
469 /* FIXME the RTC alarm is not currently acting as a wakeup event 494 /* FIXME the RTC alarm is not currently acting as a wakeup event
470 * source, and in fact this enable() call is just saving a flag 495 * source on some platforms, and in fact this enable() call is just
471 * that's never used... 496 * saving a flag that's never used...
472 */ 497 */
473 if (device_may_wakeup(dev)) 498 if (device_may_wakeup(dev)) {
474 enable_irq_wake(omap_rtc_alarm); 499 enable_irq_wake(omap_rtc_alarm);
475 else 500
501 if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
502 irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
503 irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
504 rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
505 }
506 } else {
476 rtc_write(0, OMAP_RTC_INTERRUPTS_REG); 507 rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
508 }
477 509
478 /* Disable the clock/module */ 510 /* Disable the clock/module */
479 pm_runtime_put_sync(dev); 511 pm_runtime_put_sync(dev);
@@ -483,13 +515,25 @@ static int omap_rtc_suspend(struct device *dev)
483 515
484static int omap_rtc_resume(struct device *dev) 516static int omap_rtc_resume(struct device *dev)
485{ 517{
518 u8 irqwake_stat;
519 struct platform_device *pdev = to_platform_device(dev);
520 const struct platform_device_id *id_entry =
521 platform_get_device_id(pdev);
522
486 /* Enable the clock/module so that we can access the registers */ 523 /* Enable the clock/module so that we can access the registers */
487 pm_runtime_get_sync(dev); 524 pm_runtime_get_sync(dev);
488 525
489 if (device_may_wakeup(dev)) 526 if (device_may_wakeup(dev)) {
490 disable_irq_wake(omap_rtc_alarm); 527 disable_irq_wake(omap_rtc_alarm);
491 else 528
529 if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
530 irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
531 irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
532 rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
533 }
534 } else {
492 rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); 535 rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
536 }
493 return 0; 537 return 0;
494} 538}
495#endif 539#endif