diff options
-rw-r--r-- | drivers/rtc/rtc-omap.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 8e5851aa4369..a5ff00931360 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -118,12 +118,15 @@ | |||
118 | #define KICK0_VALUE 0x83e70b13 | 118 | #define KICK0_VALUE 0x83e70b13 |
119 | #define KICK1_VALUE 0x95a4f1e0 | 119 | #define KICK1_VALUE 0x95a4f1e0 |
120 | 120 | ||
121 | struct omap_rtc; | ||
122 | |||
121 | struct omap_rtc_device_type { | 123 | struct omap_rtc_device_type { |
122 | bool has_32kclk_en; | 124 | bool has_32kclk_en; |
123 | bool has_kicker; | ||
124 | bool has_irqwakeen; | 125 | bool has_irqwakeen; |
125 | bool has_pmic_mode; | 126 | bool has_pmic_mode; |
126 | bool has_power_up_reset; | 127 | bool has_power_up_reset; |
128 | void (*lock)(struct omap_rtc *rtc); | ||
129 | void (*unlock)(struct omap_rtc *rtc); | ||
127 | }; | 130 | }; |
128 | 131 | ||
129 | struct omap_rtc { | 132 | struct omap_rtc { |
@@ -156,6 +159,26 @@ static inline void rtc_writel(struct omap_rtc *rtc, unsigned int reg, u32 val) | |||
156 | writel(val, rtc->base + reg); | 159 | writel(val, rtc->base + reg); |
157 | } | 160 | } |
158 | 161 | ||
162 | static void am3352_rtc_unlock(struct omap_rtc *rtc) | ||
163 | { | ||
164 | rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); | ||
165 | rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); | ||
166 | } | ||
167 | |||
168 | static void am3352_rtc_lock(struct omap_rtc *rtc) | ||
169 | { | ||
170 | rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); | ||
171 | rtc_writel(rtc, OMAP_RTC_KICK1_REG, 0); | ||
172 | } | ||
173 | |||
174 | static void default_rtc_unlock(struct omap_rtc *rtc) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | static void default_rtc_lock(struct omap_rtc *rtc) | ||
179 | { | ||
180 | } | ||
181 | |||
159 | /* | 182 | /* |
160 | * We rely on the rtc framework to handle locking (rtc->ops_lock), | 183 | * We rely on the rtc framework to handle locking (rtc->ops_lock), |
161 | * so the only other requirement is that register accesses which | 184 | * so the only other requirement is that register accesses which |
@@ -186,7 +209,9 @@ static irqreturn_t rtc_irq(int irq, void *dev_id) | |||
186 | 209 | ||
187 | /* alarm irq? */ | 210 | /* alarm irq? */ |
188 | if (irq_data & OMAP_RTC_STATUS_ALARM) { | 211 | if (irq_data & OMAP_RTC_STATUS_ALARM) { |
212 | rtc->type->unlock(rtc); | ||
189 | rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM); | 213 | rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM); |
214 | rtc->type->lock(rtc); | ||
190 | events |= RTC_IRQF | RTC_AF; | 215 | events |= RTC_IRQF | RTC_AF; |
191 | } | 216 | } |
192 | 217 | ||
@@ -218,9 +243,11 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
218 | irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | 243 | irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; |
219 | } | 244 | } |
220 | rtc_wait_not_busy(rtc); | 245 | rtc_wait_not_busy(rtc); |
246 | rtc->type->unlock(rtc); | ||
221 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); | 247 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); |
222 | if (rtc->type->has_irqwakeen) | 248 | if (rtc->type->has_irqwakeen) |
223 | rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); | 249 | rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); |
250 | rtc->type->lock(rtc); | ||
224 | local_irq_enable(); | 251 | local_irq_enable(); |
225 | 252 | ||
226 | return 0; | 253 | return 0; |
@@ -293,12 +320,14 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
293 | local_irq_disable(); | 320 | local_irq_disable(); |
294 | rtc_wait_not_busy(rtc); | 321 | rtc_wait_not_busy(rtc); |
295 | 322 | ||
323 | rtc->type->unlock(rtc); | ||
296 | rtc_write(rtc, OMAP_RTC_YEARS_REG, tm->tm_year); | 324 | rtc_write(rtc, OMAP_RTC_YEARS_REG, tm->tm_year); |
297 | rtc_write(rtc, OMAP_RTC_MONTHS_REG, tm->tm_mon); | 325 | rtc_write(rtc, OMAP_RTC_MONTHS_REG, tm->tm_mon); |
298 | rtc_write(rtc, OMAP_RTC_DAYS_REG, tm->tm_mday); | 326 | rtc_write(rtc, OMAP_RTC_DAYS_REG, tm->tm_mday); |
299 | rtc_write(rtc, OMAP_RTC_HOURS_REG, tm->tm_hour); | 327 | rtc_write(rtc, OMAP_RTC_HOURS_REG, tm->tm_hour); |
300 | rtc_write(rtc, OMAP_RTC_MINUTES_REG, tm->tm_min); | 328 | rtc_write(rtc, OMAP_RTC_MINUTES_REG, tm->tm_min); |
301 | rtc_write(rtc, OMAP_RTC_SECONDS_REG, tm->tm_sec); | 329 | rtc_write(rtc, OMAP_RTC_SECONDS_REG, tm->tm_sec); |
330 | rtc->type->lock(rtc); | ||
302 | 331 | ||
303 | local_irq_enable(); | 332 | local_irq_enable(); |
304 | 333 | ||
@@ -341,6 +370,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
341 | local_irq_disable(); | 370 | local_irq_disable(); |
342 | rtc_wait_not_busy(rtc); | 371 | rtc_wait_not_busy(rtc); |
343 | 372 | ||
373 | rtc->type->unlock(rtc); | ||
344 | rtc_write(rtc, OMAP_RTC_ALARM_YEARS_REG, alm->time.tm_year); | 374 | rtc_write(rtc, OMAP_RTC_ALARM_YEARS_REG, alm->time.tm_year); |
345 | rtc_write(rtc, OMAP_RTC_ALARM_MONTHS_REG, alm->time.tm_mon); | 375 | rtc_write(rtc, OMAP_RTC_ALARM_MONTHS_REG, alm->time.tm_mon); |
346 | rtc_write(rtc, OMAP_RTC_ALARM_DAYS_REG, alm->time.tm_mday); | 376 | rtc_write(rtc, OMAP_RTC_ALARM_DAYS_REG, alm->time.tm_mday); |
@@ -362,6 +392,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
362 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); | 392 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); |
363 | if (rtc->type->has_irqwakeen) | 393 | if (rtc->type->has_irqwakeen) |
364 | rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); | 394 | rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); |
395 | rtc->type->lock(rtc); | ||
365 | 396 | ||
366 | local_irq_enable(); | 397 | local_irq_enable(); |
367 | 398 | ||
@@ -391,6 +422,7 @@ static void omap_rtc_power_off(void) | |||
391 | unsigned long now; | 422 | unsigned long now; |
392 | u32 val; | 423 | u32 val; |
393 | 424 | ||
425 | rtc->type->unlock(rtc); | ||
394 | /* enable pmic_power_en control */ | 426 | /* enable pmic_power_en control */ |
395 | val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); | 427 | val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); |
396 | rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); | 428 | rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); |
@@ -423,6 +455,7 @@ static void omap_rtc_power_off(void) | |||
423 | val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); | 455 | val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); |
424 | rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, | 456 | rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, |
425 | val | OMAP_RTC_INTERRUPTS_IT_ALARM2); | 457 | val | OMAP_RTC_INTERRUPTS_IT_ALARM2); |
458 | rtc->type->lock(rtc); | ||
426 | 459 | ||
427 | /* | 460 | /* |
428 | * Wait for alarm to trigger (within two seconds) and external PMIC to | 461 | * Wait for alarm to trigger (within two seconds) and external PMIC to |
@@ -442,17 +475,21 @@ static struct rtc_class_ops omap_rtc_ops = { | |||
442 | 475 | ||
443 | static const struct omap_rtc_device_type omap_rtc_default_type = { | 476 | static const struct omap_rtc_device_type omap_rtc_default_type = { |
444 | .has_power_up_reset = true, | 477 | .has_power_up_reset = true, |
478 | .lock = default_rtc_lock, | ||
479 | .unlock = default_rtc_unlock, | ||
445 | }; | 480 | }; |
446 | 481 | ||
447 | static const struct omap_rtc_device_type omap_rtc_am3352_type = { | 482 | static const struct omap_rtc_device_type omap_rtc_am3352_type = { |
448 | .has_32kclk_en = true, | 483 | .has_32kclk_en = true, |
449 | .has_kicker = true, | ||
450 | .has_irqwakeen = true, | 484 | .has_irqwakeen = true, |
451 | .has_pmic_mode = true, | 485 | .has_pmic_mode = true, |
486 | .lock = am3352_rtc_lock, | ||
487 | .unlock = am3352_rtc_unlock, | ||
452 | }; | 488 | }; |
453 | 489 | ||
454 | static const struct omap_rtc_device_type omap_rtc_da830_type = { | 490 | static const struct omap_rtc_device_type omap_rtc_da830_type = { |
455 | .has_kicker = true, | 491 | .lock = am3352_rtc_lock, |
492 | .unlock = am3352_rtc_unlock, | ||
456 | }; | 493 | }; |
457 | 494 | ||
458 | static const struct platform_device_id omap_rtc_id_table[] = { | 495 | static const struct platform_device_id omap_rtc_id_table[] = { |
@@ -527,10 +564,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
527 | pm_runtime_enable(&pdev->dev); | 564 | pm_runtime_enable(&pdev->dev); |
528 | pm_runtime_get_sync(&pdev->dev); | 565 | pm_runtime_get_sync(&pdev->dev); |
529 | 566 | ||
530 | if (rtc->type->has_kicker) { | 567 | rtc->type->unlock(rtc); |
531 | rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); | ||
532 | rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); | ||
533 | } | ||
534 | 568 | ||
535 | /* | 569 | /* |
536 | * disable interrupts | 570 | * disable interrupts |
@@ -593,6 +627,8 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
593 | if (reg != new_ctrl) | 627 | if (reg != new_ctrl) |
594 | rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl); | 628 | rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl); |
595 | 629 | ||
630 | rtc->type->lock(rtc); | ||
631 | |||
596 | device_init_wakeup(&pdev->dev, true); | 632 | device_init_wakeup(&pdev->dev, true); |
597 | 633 | ||
598 | rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, | 634 | rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, |
@@ -626,8 +662,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
626 | 662 | ||
627 | err: | 663 | err: |
628 | device_init_wakeup(&pdev->dev, false); | 664 | device_init_wakeup(&pdev->dev, false); |
629 | if (rtc->type->has_kicker) | 665 | rtc->type->lock(rtc); |
630 | rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); | ||
631 | pm_runtime_put_sync(&pdev->dev); | 666 | pm_runtime_put_sync(&pdev->dev); |
632 | pm_runtime_disable(&pdev->dev); | 667 | pm_runtime_disable(&pdev->dev); |
633 | 668 | ||
@@ -646,11 +681,11 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
646 | 681 | ||
647 | device_init_wakeup(&pdev->dev, 0); | 682 | device_init_wakeup(&pdev->dev, 0); |
648 | 683 | ||
684 | rtc->type->unlock(rtc); | ||
649 | /* leave rtc running, but disable irqs */ | 685 | /* leave rtc running, but disable irqs */ |
650 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); | 686 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); |
651 | 687 | ||
652 | if (rtc->type->has_kicker) | 688 | rtc->type->lock(rtc); |
653 | rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); | ||
654 | 689 | ||
655 | /* Disable the clock/module */ | 690 | /* Disable the clock/module */ |
656 | pm_runtime_put_sync(&pdev->dev); | 691 | pm_runtime_put_sync(&pdev->dev); |
@@ -666,6 +701,7 @@ static int omap_rtc_suspend(struct device *dev) | |||
666 | 701 | ||
667 | rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); | 702 | rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); |
668 | 703 | ||
704 | rtc->type->unlock(rtc); | ||
669 | /* | 705 | /* |
670 | * FIXME: the RTC alarm is not currently acting as a wakeup event | 706 | * FIXME: the RTC alarm is not currently acting as a wakeup event |
671 | * source on some platforms, and in fact this enable() call is just | 707 | * source on some platforms, and in fact this enable() call is just |
@@ -675,6 +711,7 @@ static int omap_rtc_suspend(struct device *dev) | |||
675 | enable_irq_wake(rtc->irq_alarm); | 711 | enable_irq_wake(rtc->irq_alarm); |
676 | else | 712 | else |
677 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); | 713 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); |
714 | rtc->type->lock(rtc); | ||
678 | 715 | ||
679 | /* Disable the clock/module */ | 716 | /* Disable the clock/module */ |
680 | pm_runtime_put_sync(dev); | 717 | pm_runtime_put_sync(dev); |
@@ -689,10 +726,12 @@ static int omap_rtc_resume(struct device *dev) | |||
689 | /* Enable the clock/module so that we can access the registers */ | 726 | /* Enable the clock/module so that we can access the registers */ |
690 | pm_runtime_get_sync(dev); | 727 | pm_runtime_get_sync(dev); |
691 | 728 | ||
729 | rtc->type->unlock(rtc); | ||
692 | if (device_may_wakeup(dev)) | 730 | if (device_may_wakeup(dev)) |
693 | disable_irq_wake(rtc->irq_alarm); | 731 | disable_irq_wake(rtc->irq_alarm); |
694 | else | 732 | else |
695 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg); | 733 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg); |
734 | rtc->type->lock(rtc); | ||
696 | 735 | ||
697 | return 0; | 736 | return 0; |
698 | } | 737 | } |
@@ -709,9 +748,11 @@ static void omap_rtc_shutdown(struct platform_device *pdev) | |||
709 | * Keep the ALARM interrupt enabled to allow the system to power up on | 748 | * Keep the ALARM interrupt enabled to allow the system to power up on |
710 | * alarm events. | 749 | * alarm events. |
711 | */ | 750 | */ |
751 | rtc->type->unlock(rtc); | ||
712 | mask = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); | 752 | mask = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); |
713 | mask &= OMAP_RTC_INTERRUPTS_IT_ALARM; | 753 | mask &= OMAP_RTC_INTERRUPTS_IT_ALARM; |
714 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, mask); | 754 | rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, mask); |
755 | rtc->type->lock(rtc); | ||
715 | } | 756 | } |
716 | 757 | ||
717 | static struct platform_driver omap_rtc_driver = { | 758 | static struct platform_driver omap_rtc_driver = { |