]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/rtc/rtc-omap.c
Merge tag 'pm+acpi-fixes-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / drivers / rtc / rtc-omap.c
index c6ffbaec32a4b509609fe03dad3e57b2db16e439..c7d97ee59327a7bec079b7ab452fdbbb45728b56 100644 (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)
 #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