diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 2939cdcb2688..eb09eddf39b8 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -42,6 +42,8 @@ | |||
42 | #define STMP3XXX_RTC_STAT 0x10 | 42 | #define STMP3XXX_RTC_STAT 0x10 |
43 | #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 | 43 | #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 |
44 | #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000 | 44 | #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000 |
45 | #define STMP3XXX_RTC_STAT_XTAL32000_PRESENT 0x10000000 | ||
46 | #define STMP3XXX_RTC_STAT_XTAL32768_PRESENT 0x08000000 | ||
45 | 47 | ||
46 | #define STMP3XXX_RTC_SECONDS 0x30 | 48 | #define STMP3XXX_RTC_SECONDS 0x30 |
47 | 49 | ||
@@ -52,9 +54,13 @@ | |||
52 | #define STMP3XXX_RTC_PERSISTENT0 0x60 | 54 | #define STMP3XXX_RTC_PERSISTENT0 0x60 |
53 | #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 | 55 | #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 |
54 | #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 | 56 | #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 |
55 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002 | 57 | #define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0) |
56 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 | 58 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN (1 << 1) |
57 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 | 59 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN (1 << 2) |
60 | #define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP (1 << 4) | ||
61 | #define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP (1 << 5) | ||
62 | #define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ (1 << 6) | ||
63 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE (1 << 7) | ||
58 | 64 | ||
59 | #define STMP3XXX_RTC_PERSISTENT1 0x70 | 65 | #define STMP3XXX_RTC_PERSISTENT1 0x70 |
60 | /* missing bitmask in headers */ | 66 | /* missing bitmask in headers */ |
@@ -248,6 +254,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
248 | { | 254 | { |
249 | struct stmp3xxx_rtc_data *rtc_data; | 255 | struct stmp3xxx_rtc_data *rtc_data; |
250 | struct resource *r; | 256 | struct resource *r; |
257 | u32 rtc_stat; | ||
258 | u32 pers0_set, pers0_clr; | ||
259 | u32 crystalfreq = 0; | ||
251 | int err; | 260 | int err; |
252 | 261 | ||
253 | rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL); | 262 | rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL); |
@@ -268,8 +277,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
268 | 277 | ||
269 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); | 278 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); |
270 | 279 | ||
271 | if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) & | 280 | rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT); |
272 | STMP3XXX_RTC_STAT_RTC_PRESENT)) { | 281 | if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) { |
273 | dev_err(&pdev->dev, "no device onboard\n"); | 282 | dev_err(&pdev->dev, "no device onboard\n"); |
274 | return -ENODEV; | 283 | return -ENODEV; |
275 | } | 284 | } |
@@ -282,9 +291,54 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
282 | return err; | 291 | return err; |
283 | } | 292 | } |
284 | 293 | ||
294 | /* | ||
295 | * Obviously the rtc needs a clock input to be able to run. | ||
296 | * This clock can be provided by an external 32k crystal. If that one is | ||
297 | * missing XTAL must not be disabled in suspend which consumes a | ||
298 | * lot of power. Normally the presence and exact frequency (supported | ||
299 | * are 32000 Hz and 32768 Hz) is detectable from fuses, but as reality | ||
300 | * proves these fuses are not blown correctly on all machines, so the | ||
301 | * frequency can be overridden in the device tree. | ||
302 | */ | ||
303 | if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32000_PRESENT) | ||
304 | crystalfreq = 32000; | ||
305 | else if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32768_PRESENT) | ||
306 | crystalfreq = 32768; | ||
307 | |||
308 | of_property_read_u32(pdev->dev.of_node, "stmp,crystal-freq", | ||
309 | &crystalfreq); | ||
310 | |||
311 | switch (crystalfreq) { | ||
312 | case 32000: | ||
313 | /* keep 32kHz crystal running in low-power mode */ | ||
314 | pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | | ||
315 | STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | | ||
316 | STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; | ||
317 | pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; | ||
318 | break; | ||
319 | case 32768: | ||
320 | /* keep 32.768kHz crystal running in low-power mode */ | ||
321 | pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | | ||
322 | STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; | ||
323 | pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP | | ||
324 | STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ; | ||
325 | break; | ||
326 | default: | ||
327 | dev_warn(&pdev->dev, | ||
328 | "invalid crystal-freq specified in device-tree. Assuming no crystal\n"); | ||
329 | /* fall-through */ | ||
330 | case 0: | ||
331 | /* keep XTAL on in low-power mode */ | ||
332 | pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; | ||
333 | pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | | ||
334 | STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; | ||
335 | } | ||
336 | |||
337 | writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); | ||
338 | |||
285 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | | 339 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
286 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | | 340 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | |
287 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, | 341 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr, |
288 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); | 342 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); |
289 | 343 | ||
290 | writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | | 344 | writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | |