diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c index 3cf3529888c7409a32881ad2f5127da3fb472d6b..c0714da44920287fc1be7ad76d2cacccc0bd927c 100644 --- a/drivers/rtc/rtc-at91.c +++ b/drivers/rtc/rtc-at91.c @@ -307,6 +307,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc); } platform_set_drvdata(pdev, rtc); + device_init_wakeup(&pdev->dev, 1); printk(KERN_INFO "AT91 Real Time Clock driver.\n"); return 0; @@ -327,6 +328,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev) rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); + device_init_wakeup(&pdev->dev, 0); return 0; } @@ -336,6 +338,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev) /* AT91RM9200 RTC Power management control */ static struct timespec at91_rtc_delta; +static u32 at91_rtc_imr; static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) { @@ -349,6 +352,18 @@ static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) rtc_tm_to_time(&tm, &time.tv_sec); save_time_delta(&at91_rtc_delta, &time); + /* this IRQ is shared with DBGU and other hardware which isn't + * necessarily doing PM like we are... + */ + at91_rtc_imr = at91_sys_read(AT91_RTC_IMR) + & (AT91_RTC_ALARM|AT91_RTC_SECEV); + if (at91_rtc_imr) { + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(AT91_ID_SYS); + else + at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); + } + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); @@ -367,6 +382,13 @@ static int at91_rtc_resume(struct platform_device *pdev) rtc_tm_to_time(&tm, &time.tv_sec); restore_time_delta(&at91_rtc_delta, &time); + if (at91_rtc_imr) { + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(AT91_ID_SYS); + else + at91_sys_write(AT91_RTC_IER, at91_rtc_imr); + } + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);