Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[cascardo/linux.git] / drivers / rtc / rtc-omap.c
index 1abd88e..8e5851a 100644 (file)
@@ -1,10 +1,11 @@
 /*
- * TI OMAP1 Real Time Clock interface for Linux
+ * TI OMAP Real Time Clock interface for Linux
  *
  * Copyright (C) 2003 MontaVista Software, Inc.
  * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
  *
  * Copyright (C) 2006 David Brownell (new RTC framework)
+ * Copyright (C) 2014 Johan Hovold <johan@kernel.org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,7 +26,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
 
-/* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
+/*
+ * The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
  * with century-range alarm matching, driven by the 32kHz clock.
  *
  * The main user-visible ways it differs from PC RTCs are by omitting
 
 #define OMAP_RTC_IRQWAKEEN             0x7c
 
+#define OMAP_RTC_ALARM2_SECONDS_REG    0x80
+#define OMAP_RTC_ALARM2_MINUTES_REG    0x84
+#define OMAP_RTC_ALARM2_HOURS_REG      0x88
+#define OMAP_RTC_ALARM2_DAYS_REG       0x8c
+#define OMAP_RTC_ALARM2_MONTHS_REG     0x90
+#define OMAP_RTC_ALARM2_YEARS_REG      0x94
+
+#define OMAP_RTC_PMIC_REG              0x98
+
 /* OMAP_RTC_CTRL_REG bit fields: */
 #define OMAP_RTC_CTRL_SPLIT            BIT(7)
 #define OMAP_RTC_CTRL_DISABLE          BIT(6)
@@ -80,6 +91,7 @@
 
 /* OMAP_RTC_STATUS_REG bit fields: */
 #define OMAP_RTC_STATUS_POWER_UP       BIT(7)
+#define OMAP_RTC_STATUS_ALARM2         BIT(7)
 #define OMAP_RTC_STATUS_ALARM          BIT(6)
 #define OMAP_RTC_STATUS_1D_EVENT       BIT(5)
 #define OMAP_RTC_STATUS_1H_EVENT       BIT(4)
 #define OMAP_RTC_STATUS_BUSY           BIT(0)
 
 /* OMAP_RTC_INTERRUPTS_REG bit fields: */
+#define OMAP_RTC_INTERRUPTS_IT_ALARM2  BIT(4)
 #define OMAP_RTC_INTERRUPTS_IT_ALARM   BIT(3)
 #define OMAP_RTC_INTERRUPTS_IT_TIMER   BIT(2)
 
 /* OMAP_RTC_IRQWAKEEN bit fields: */
 #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN        BIT(1)
 
+/* OMAP_RTC_PMIC bit fields: */
+#define OMAP_RTC_PMIC_POWER_EN_EN      BIT(16)
+
 /* OMAP_RTC_KICKER values */
 #define        KICK0_VALUE                     0x83e70b13
 #define        KICK1_VALUE                     0x95a4f1e0
@@ -106,6 +122,8 @@ struct omap_rtc_device_type {
        bool has_32kclk_en;
        bool has_kicker;
        bool has_irqwakeen;
+       bool has_pmic_mode;
+       bool has_power_up_reset;
 };
 
 struct omap_rtc {
@@ -114,6 +132,7 @@ struct omap_rtc {
        int irq_alarm;
        int irq_timer;
        u8 interrupts_reg;
+       bool is_pmic_controller;
        const struct omap_rtc_device_type *type;
 };
 
@@ -122,6 +141,11 @@ static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg)
        return readb(rtc->base + reg);
 }
 
+static inline u32 rtc_readl(struct omap_rtc *rtc, unsigned int reg)
+{
+       return readl(rtc->base + reg);
+}
+
 static inline void rtc_write(struct omap_rtc *rtc, unsigned int reg, u8 val)
 {
        writeb(val, rtc->base + reg);
@@ -132,19 +156,20 @@ static inline void rtc_writel(struct omap_rtc *rtc, unsigned int reg, u32 val)
        writel(val, rtc->base + reg);
 }
 
-/* we rely on the rtc framework to handle locking (rtc->ops_lock),
+/*
+ * We rely on the rtc framework to handle locking (rtc->ops_lock),
  * so the only other requirement is that register accesses which
  * require BUSY to be clear are made with IRQs locally disabled
  */
 static void rtc_wait_not_busy(struct omap_rtc *rtc)
 {
-       int     count = 0;
-       u8      status;
+       int count;
+       u8 status;
 
        /* BUSY may stay active for 1/32768 second (~30 usec) */
        for (count = 0; count < 50; count++) {
                status = rtc_read(rtc, OMAP_RTC_STATUS_REG);
-               if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
+               if (!(status & OMAP_RTC_STATUS_BUSY))
                        break;
                udelay(1);
        }
@@ -153,9 +178,9 @@ static void rtc_wait_not_busy(struct omap_rtc *rtc)
 
 static irqreturn_t rtc_irq(int irq, void *dev_id)
 {
-       struct omap_rtc         *rtc = dev_id;
-       unsigned long           events = 0;
-       u8                      irq_data;
+       struct omap_rtc *rtc = dev_id;
+       unsigned long events = 0;
+       u8 irq_data;
 
        irq_data = rtc_read(rtc, OMAP_RTC_STATUS_REG);
 
@@ -233,25 +258,28 @@ static void bcd2tm(struct rtc_time *tm)
        tm->tm_year = bcd2bin(tm->tm_year) + 100;
 }
 
-
-static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static void omap_rtc_read_time_raw(struct omap_rtc *rtc, struct rtc_time *tm)
 {
-       struct omap_rtc *rtc = dev_get_drvdata(dev);
-
-       /* we don't report wday/yday/isdst ... */
-       local_irq_disable();
-       rtc_wait_not_busy(rtc);
-
        tm->tm_sec = rtc_read(rtc, OMAP_RTC_SECONDS_REG);
        tm->tm_min = rtc_read(rtc, OMAP_RTC_MINUTES_REG);
        tm->tm_hour = rtc_read(rtc, OMAP_RTC_HOURS_REG);
        tm->tm_mday = rtc_read(rtc, OMAP_RTC_DAYS_REG);
        tm->tm_mon = rtc_read(rtc, OMAP_RTC_MONTHS_REG);
        tm->tm_year = rtc_read(rtc, OMAP_RTC_YEARS_REG);
+}
+
+static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct omap_rtc *rtc = dev_get_drvdata(dev);
 
+       /* we don't report wday/yday/isdst ... */
+       local_irq_disable();
+       rtc_wait_not_busy(rtc);
+       omap_rtc_read_time_raw(rtc, tm);
        local_irq_enable();
 
        bcd2tm(tm);
+
        return 0;
 }
 
@@ -261,6 +289,7 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
        if (tm2bcd(tm) < 0)
                return -EINVAL;
+
        local_irq_disable();
        rtc_wait_not_busy(rtc);
 
@@ -279,6 +308,7 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
        struct omap_rtc *rtc = dev_get_drvdata(dev);
+       u8 interrupts;
 
        local_irq_disable();
        rtc_wait_not_busy(rtc);
@@ -293,8 +323,9 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
        local_irq_enable();
 
        bcd2tm(&alm->time);
-       alm->enabled = !!(rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG)
-                       & OMAP_RTC_INTERRUPTS_IT_ALARM);
+
+       interrupts = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
+       alm->enabled = !!(interrupts & OMAP_RTC_INTERRUPTS_IT_ALARM);
 
        return 0;
 }
@@ -337,6 +368,70 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
        return 0;
 }
 
+static struct omap_rtc *omap_rtc_power_off_rtc;
+
+/*
+ * omap_rtc_poweroff: RTC-controlled power off
+ *
+ * The RTC can be used to control an external PMIC via the pmic_power_en pin,
+ * which can be configured to transition to OFF on ALARM2 events.
+ *
+ * Notes:
+ * The two-second alarm offset is the shortest offset possible as the alarm
+ * registers must be set before the next timer update and the offset
+ * calculation is too heavy for everything to be done within a single access
+ * period (~15 us).
+ *
+ * Called with local interrupts disabled.
+ */
+static void omap_rtc_power_off(void)
+{
+       struct omap_rtc *rtc = omap_rtc_power_off_rtc;
+       struct rtc_time tm;
+       unsigned long now;
+       u32 val;
+
+       /* enable pmic_power_en control */
+       val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
+       rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);
+
+       /* set alarm two seconds from now */
+       omap_rtc_read_time_raw(rtc, &tm);
+       bcd2tm(&tm);
+       rtc_tm_to_time(&tm, &now);
+       rtc_time_to_tm(now + 2, &tm);
+
+       if (tm2bcd(&tm) < 0) {
+               dev_err(&rtc->rtc->dev, "power off failed\n");
+               return;
+       }
+
+       rtc_wait_not_busy(rtc);
+
+       rtc_write(rtc, OMAP_RTC_ALARM2_SECONDS_REG, tm.tm_sec);
+       rtc_write(rtc, OMAP_RTC_ALARM2_MINUTES_REG, tm.tm_min);
+       rtc_write(rtc, OMAP_RTC_ALARM2_HOURS_REG, tm.tm_hour);
+       rtc_write(rtc, OMAP_RTC_ALARM2_DAYS_REG, tm.tm_mday);
+       rtc_write(rtc, OMAP_RTC_ALARM2_MONTHS_REG, tm.tm_mon);
+       rtc_write(rtc, OMAP_RTC_ALARM2_YEARS_REG, tm.tm_year);
+
+       /*
+        * enable ALARM2 interrupt
+        *
+        * NOTE: this fails on AM3352 if rtc_write (writeb) is used
+        */
+       val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
+       rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG,
+                       val | OMAP_RTC_INTERRUPTS_IT_ALARM2);
+
+       /*
+        * Wait for alarm to trigger (within two seconds) and external PMIC to
+        * power off the system. Add a 500 ms margin for external latencies
+        * (e.g. debounce circuits).
+        */
+       mdelay(2500);
+}
+
 static struct rtc_class_ops omap_rtc_ops = {
        .read_time      = omap_rtc_read_time,
        .set_time       = omap_rtc_set_time,
@@ -346,12 +441,14 @@ static struct rtc_class_ops omap_rtc_ops = {
 };
 
 static const struct omap_rtc_device_type omap_rtc_default_type = {
+       .has_power_up_reset = true,
 };
 
 static const struct omap_rtc_device_type omap_rtc_am3352_type = {
        .has_32kclk_en  = true,
        .has_kicker     = true,
        .has_irqwakeen  = true,
+       .has_pmic_mode  = true,
 };
 
 static const struct omap_rtc_device_type omap_rtc_da830_type = {
@@ -389,9 +486,9 @@ MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 
 static int __init omap_rtc_probe(struct platform_device *pdev)
 {
-       struct omap_rtc         *rtc;
-       struct resource         *res;
-       u8                      reg, new_ctrl;
+       struct omap_rtc *rtc;
+       struct resource *res;
+       u8 reg, mask, new_ctrl;
        const struct platform_device_id *id_entry;
        const struct of_device_id *of_id;
        int ret;
@@ -403,6 +500,9 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
        if (of_id) {
                rtc->type = of_id->data;
+               rtc->is_pmic_controller = rtc->type->has_pmic_mode &&
+                               of_property_read_bool(pdev->dev.of_node,
+                                               "system-power-controller");
        } else {
                id_entry = platform_get_device_id(pdev);
                rtc->type = (void *)id_entry->driver_data;
@@ -448,23 +548,32 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 
        /* clear old status */
        reg = rtc_read(rtc, OMAP_RTC_STATUS_REG);
-       if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
-               dev_info(&pdev->dev, "RTC power up reset detected\n");
-               rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_POWER_UP);
+
+       mask = OMAP_RTC_STATUS_ALARM;
+
+       if (rtc->type->has_pmic_mode)
+               mask |= OMAP_RTC_STATUS_ALARM2;
+
+       if (rtc->type->has_power_up_reset) {
+               mask |= OMAP_RTC_STATUS_POWER_UP;
+               if (reg & OMAP_RTC_STATUS_POWER_UP)
+                       dev_info(&pdev->dev, "RTC power up reset detected\n");
        }
-       if (reg & (u8) OMAP_RTC_STATUS_ALARM)
-               rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM);
+
+       if (reg & mask)
+               rtc_write(rtc, OMAP_RTC_STATUS_REG, reg & mask);
 
        /* On boards with split power, RTC_ON_NOFF won't reset the RTC */
        reg = rtc_read(rtc, OMAP_RTC_CTRL_REG);
-       if (reg & (u8) OMAP_RTC_CTRL_STOP)
+       if (reg & OMAP_RTC_CTRL_STOP)
                dev_info(&pdev->dev, "already running\n");
 
        /* force to 24 hour mode */
-       new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
+       new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT | OMAP_RTC_CTRL_AUTO_COMP);
        new_ctrl |= OMAP_RTC_CTRL_STOP;
 
-       /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
+       /*
+        * BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
         *
         *  - Device wake-up capability setting should come through chip
         *    init logic. OMAP1 boards should initialize the "wakeup capable"
@@ -478,7 +587,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
         *    is write-only, and always reads as zero...)
         */
 
-       if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT)
+       if (new_ctrl & OMAP_RTC_CTRL_SPLIT)
                dev_info(&pdev->dev, "split power mode\n");
 
        if (reg != new_ctrl)
@@ -506,6 +615,13 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
                        goto err;
        }
 
+       if (rtc->is_pmic_controller) {
+               if (!pm_power_off) {
+                       omap_rtc_power_off_rtc = rtc;
+                       pm_power_off = omap_rtc_power_off;
+               }
+       }
+
        return 0;
 
 err:
@@ -522,6 +638,12 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
        struct omap_rtc *rtc = platform_get_drvdata(pdev);
 
+       if (pm_power_off == omap_rtc_power_off &&
+                       omap_rtc_power_off_rtc == rtc) {
+               pm_power_off = NULL;
+               omap_rtc_power_off_rtc = NULL;
+       }
+
        device_init_wakeup(&pdev->dev, 0);
 
        /* leave rtc running, but disable irqs */
@@ -544,7 +666,8 @@ static int omap_rtc_suspend(struct device *dev)
 
        rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
 
-       /* FIXME the RTC alarm is not currently acting as a wakeup event
+       /*
+        * FIXME: the RTC alarm is not currently acting as a wakeup event
         * source on some platforms, and in fact this enable() call is just
         * saving a flag that's never used...
         */
@@ -580,8 +703,15 @@ static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume);
 static void omap_rtc_shutdown(struct platform_device *pdev)
 {
        struct omap_rtc *rtc = platform_get_drvdata(pdev);
+       u8 mask;
 
-       rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
+       /*
+        * Keep the ALARM interrupt enabled to allow the system to power up on
+        * alarm events.
+        */
+       mask = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
+       mask &= OMAP_RTC_INTERRUPTS_IT_ALARM;
+       rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, mask);
 }
 
 static struct platform_driver omap_rtc_driver = {
@@ -589,7 +719,6 @@ static struct platform_driver omap_rtc_driver = {
        .shutdown       = omap_rtc_shutdown,
        .driver         = {
                .name   = "omap_rtc",
-               .owner  = THIS_MODULE,
                .pm     = &omap_rtc_pm_ops,
                .of_match_table = omap_rtc_of_match,
        },