|
@@ -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
|