diff options
| -rw-r--r-- | Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 66 |
2 files changed, 65 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt index b800070fe6e9..fa6a94226669 100644 --- a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt | |||
| @@ -7,6 +7,11 @@ Required properties: | |||
| 7 | region. | 7 | region. |
| 8 | - interrupts: rtc alarm interrupt | 8 | - interrupts: rtc alarm interrupt |
| 9 | 9 | ||
| 10 | Optional properties: | ||
| 11 | - stmp,crystal-freq: override crystal frequency as determined from fuse bits. | ||
| 12 | Only <32000> and <32768> are possible for the hardware. Use <0> for | ||
| 13 | "no crystal". | ||
| 14 | |||
| 10 | Example: | 15 | Example: |
| 11 | 16 | ||
| 12 | rtc@80056000 { | 17 | rtc@80056000 { |
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 | |
