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 <[email protected]>
Acked-by: Kevin Hilman <[email protected]>
Acked-by: Sekhar Nori <[email protected]>
Cc: Grant Likely <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Rob Landley <[email protected]>
Cc: Alessandro Zummo <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
Hebbar Gururaja 2013-09-11 14:24:18 -07:00 • committed by Linus Torvalds
commit 8af750e3f5
2 changed files with 57 additions and 9 deletions

View file

@ -70,6 +70,8 @@
#define OMAP_RTC_KICK0_REG 0x6c
#define OMAP_RTC_KICK1_REG 0x70
#define OMAP_RTC_IRQWAKEEN 0x7c
/* OMAP_RTC_CTRL_REG bit fields: */
#define OMAP_RTC_CTRL_SPLIT (1<<7)
#define OMAP_RTC_CTRL_DISABLE (1<<6)
@ -94,12 +96,21 @@
#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3)
#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2)
/* OMAP_RTC_IRQWAKEEN bit fields: */
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1)
/* OMAP_RTC_KICKER values */
#define KICK0_VALUE 0x83e70b13
#define KICK1_VALUE 0x95a4f1e0
#define OMAP_RTC_HAS_KICKER 0x1
/*
* Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
* generation for event Alarm.
*/
#define OMAP_RTC_HAS_IRQWAKEEN 0x2
static void __iomem *rtc_base;
#define rtc_read(addr) readb(rtc_base + (addr))
@ -299,12 +310,18 @@ static struct rtc_class_ops omap_rtc_ops = {
static int omap_rtc_alarm;
static int omap_rtc_timer;
#define OMAP_RTC_DATA_DA830_IDX 1
#define OMAP_RTC_DATA_AM3352_IDX 1
#define OMAP_RTC_DATA_DA830_IDX 2
static struct platform_device_id omap_rtc_devtype[] = {
{
.name = DRIVER_NAME,
}, {
},
[OMAP_RTC_DATA_AM3352_IDX] = {
.name = "am3352-rtc",
.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
},
[OMAP_RTC_DATA_DA830_IDX] = {
.name = "da830-rtc",
.driver_data = OMAP_RTC_HAS_KICKER,
},
@ -316,6 +333,9 @@ static const struct of_device_id omap_rtc_of_match[] = {
{ .compatible = "ti,da830-rtc",
.data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
},
{ .compatible = "ti,am3352-rtc",
.data = &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
},
{},
};
MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
@ -464,16 +484,28 @@ static u8 irqstat;
static int omap_rtc_suspend(struct device *dev)
{
u8 irqwake_stat;
struct platform_device *pdev = to_platform_device(dev);
const struct platform_device_id *id_entry =
platform_get_device_id(pdev);
irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
/* FIXME the RTC alarm is not currently acting as a wakeup event
* source, and in fact this enable() call is just saving a flag
* that's never used...
* source on some platforms, and in fact this enable() call is just
* saving a flag that's never used...
*/
if (device_may_wakeup(dev))
if (device_may_wakeup(dev)) {
enable_irq_wake(omap_rtc_alarm);
else
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
}
} else {
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
}
/* Disable the clock/module */
pm_runtime_put_sync(dev);
@ -483,13 +515,25 @@ static int omap_rtc_suspend(struct device *dev)
static int omap_rtc_resume(struct device *dev)
{
u8 irqwake_stat;
struct platform_device *pdev = to_platform_device(dev);
const struct platform_device_id *id_entry =
platform_get_device_id(pdev);
/* Enable the clock/module so that we can access the registers */
pm_runtime_get_sync(dev);
if (device_may_wakeup(dev))
if (device_may_wakeup(dev)) {
disable_irq_wake(omap_rtc_alarm);
else
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
}
} else {
rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
}
return 0;
}
#endif