|
@@ -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
|
|
|
|
|
@@ -52,9 +54,13 @@
|
|
|
#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 |
|