Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers/rtc/rtc-omap.c: enable RTC_IRQWAKEEN bits when Alarm is set

When RTC CLKTRCTRL bit is configured in HW_AUTO, module goes to sleep in
IDLE state.

The Alarm SWakeup event can be used to wakeup the RTC when it is in IDLE
state. In order to do so, the alarm needs to be set and enabled before
RTC enters the IDLE state. Also the wakeup generation for alarm/timer
event needs to be set (bits [1:0] in RTC_IRQWAKEEN register).

Currently RTC_IRQWAKEEN bits are set only in suspend/resume paths. With
this ALARM interrupts are not generated when it enters IDLE state. So
programming the RTC_IRQWAKEEN bits when ever ALARM is set.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Acked-by: Sekhar Nori <nsekhar@ti.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
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>

authored by

Lokesh Vutla and committed by
Linus Torvalds
ab7f580b 9dcc87fe

+33 -34
+33 -34
drivers/rtc/rtc-omap.c
··· 171 171 172 172 static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 173 173 { 174 - u8 reg; 174 + u8 reg, irqwake_reg = 0; 175 + struct platform_device *pdev = to_platform_device(dev); 176 + const struct platform_device_id *id_entry = 177 + platform_get_device_id(pdev); 175 178 176 179 local_irq_disable(); 177 180 rtc_wait_not_busy(); 178 181 reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); 179 - if (enabled) 182 + if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) 183 + irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN); 184 + 185 + if (enabled) { 180 186 reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; 181 - else 187 + irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 188 + } else { 182 189 reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; 190 + irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 191 + } 183 192 rtc_wait_not_busy(); 184 193 rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); 194 + if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) 195 + rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN); 185 196 local_irq_enable(); 186 197 187 198 return 0; ··· 292 281 293 282 static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 294 283 { 295 - u8 reg; 284 + u8 reg, irqwake_reg = 0; 285 + struct platform_device *pdev = to_platform_device(dev); 286 + const struct platform_device_id *id_entry = 287 + platform_get_device_id(pdev); 296 288 297 289 if (tm2bcd(&alm->time) < 0) 298 290 return -EINVAL; ··· 311 297 rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); 312 298 313 299 reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); 314 - if (alm->enabled) 300 + if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) 301 + irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN); 302 + 303 + if (alm->enabled) { 315 304 reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; 316 - else 305 + irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 306 + } else { 317 307 reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; 308 + irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 309 + } 318 310 rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); 311 + if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) 312 + rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN); 319 313 320 314 local_irq_enable(); 321 315 ··· 525 503 526 504 static int omap_rtc_suspend(struct device *dev) 527 505 { 528 - u8 irqwake_stat; 529 - struct platform_device *pdev = to_platform_device(dev); 530 - const struct platform_device_id *id_entry = 531 - platform_get_device_id(pdev); 532 - 533 506 irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); 534 507 535 508 /* FIXME the RTC alarm is not currently acting as a wakeup event 536 509 * source on some platforms, and in fact this enable() call is just 537 510 * saving a flag that's never used... 538 511 */ 539 - if (device_may_wakeup(dev)) { 512 + if (device_may_wakeup(dev)) 540 513 enable_irq_wake(omap_rtc_alarm); 541 - 542 - if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) { 543 - irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN); 544 - irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 545 - rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN); 546 - } 547 - } else { 514 + else 548 515 rtc_write(0, OMAP_RTC_INTERRUPTS_REG); 549 - } 550 516 551 517 /* Disable the clock/module */ 552 518 pm_runtime_put_sync(dev); ··· 544 534 545 535 static int omap_rtc_resume(struct device *dev) 546 536 { 547 - u8 irqwake_stat; 548 - struct platform_device *pdev = to_platform_device(dev); 549 - const struct platform_device_id *id_entry = 550 - platform_get_device_id(pdev); 551 - 552 537 /* Enable the clock/module so that we can access the registers */ 553 538 pm_runtime_get_sync(dev); 554 539 555 - if (device_may_wakeup(dev)) { 540 + if (device_may_wakeup(dev)) 556 541 disable_irq_wake(omap_rtc_alarm); 557 - 558 - if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) { 559 - irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN); 560 - irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; 561 - rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN); 562 - } 563 - } else { 542 + else 564 543 rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); 565 - } 544 + 566 545 return 0; 567 546 } 568 547 #endif