[media] marvell-ccic: drop support for PIX_FMT_422P
[firefly-linux-kernel-4.4.55.git] / drivers / rtc / rtc-stmp3xxx.c
index 2939cdcb268855178ee77b469e470f8cff26881f..eb09eddf39b8a089441965f641eb27af01bde83a 100644 (file)
@@ -42,6 +42,8 @@
 #define STMP3XXX_RTC_STAT                      0x10
 #define STMP3XXX_RTC_STAT_STALE_SHIFT          16
 #define STMP3XXX_RTC_STAT_RTC_PRESENT          0x80000000
+#define STMP3XXX_RTC_STAT_XTAL32000_PRESENT    0x10000000
+#define STMP3XXX_RTC_STAT_XTAL32768_PRESENT    0x08000000
 
 #define STMP3XXX_RTC_SECONDS                   0x30
 
 #define STMP3XXX_RTC_PERSISTENT0               0x60
 #define STMP3XXX_RTC_PERSISTENT0_SET           0x64
 #define STMP3XXX_RTC_PERSISTENT0_CLR           0x68
-#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002
-#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN      0x00000004
-#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE    0x00000080
+#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE           (1 << 0)
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN         (1 << 1)
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN              (1 << 2)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP       (1 << 4)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP       (1 << 5)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ           (1 << 6)
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE            (1 << 7)
 
 #define STMP3XXX_RTC_PERSISTENT1               0x70
 /* missing bitmask in headers */
@@ -248,6 +254,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 {
        struct stmp3xxx_rtc_data *rtc_data;
        struct resource *r;
+       u32 rtc_stat;
+       u32 pers0_set, pers0_clr;
+       u32 crystalfreq = 0;
        int err;
 
        rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL);
@@ -268,8 +277,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 
        rtc_data->irq_alarm = platform_get_irq(pdev, 0);
 
-       if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) &
-                       STMP3XXX_RTC_STAT_RTC_PRESENT)) {
+       rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT);
+       if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) {
                dev_err(&pdev->dev, "no device onboard\n");
                return -ENODEV;
        }
@@ -282,9 +291,54 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
                return err;
        }
 
+       /*
+        * Obviously the rtc needs a clock input to be able to run.
+        * This clock can be provided by an external 32k crystal. If that one is
+        * missing XTAL must not be disabled in suspend which consumes a
+        * lot of power. Normally the presence and exact frequency (supported
+        * are 32000 Hz and 32768 Hz) is detectable from fuses, but as reality
+        * proves these fuses are not blown correctly on all machines, so the
+        * frequency can be overridden in the device tree.
+        */
+       if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32000_PRESENT)
+               crystalfreq = 32000;
+       else if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32768_PRESENT)
+               crystalfreq = 32768;
+
+       of_property_read_u32(pdev->dev.of_node, "stmp,crystal-freq",
+                            &crystalfreq);
+
+       switch (crystalfreq) {
+       case 32000:
+               /* keep 32kHz crystal running in low-power mode */
+               pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ |
+                       STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
+               pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP;
+               break;
+       case 32768:
+               /* keep 32.768kHz crystal running in low-power mode */
+               pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
+               pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ;
+               break;
+       default:
+               dev_warn(&pdev->dev,
+                        "invalid crystal-freq specified in device-tree. Assuming no crystal\n");
+               /* fall-through */
+       case 0:
+               /* keep XTAL on in low-power mode */
+               pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP;
+               pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+                       STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
+       }
+
+       writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+
        writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
-                       STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
+                       STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr,
                        rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 
        writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |