aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2016-10-27 01:57:26 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-11-04 18:11:39 -0400
commitefce21fc43e00a76aee7b0a1eda73730ed2d5d3a (patch)
tree8c41f0898936931b4db2cea74850ba926aa36388
parent3984903a2e3906d3def220e688040ce93368200a (diff)
rtc: omap: prevent disabling of clock/module during suspend
If RTC is running from an internal clock source, the RTC module can't be disabled; otherwise it stops ticking completely. Current suspend handler implementation disables the clock/module unconditionally, instead fix this by disabling the clock only if we are running on external clock source, which is not affected by suspend. The prevention of disabling the clock must be done via implementing the runtime_pm handlers for the device, and returning an error code from the runtime suspend handler; otherwise OMAP core PM will disable the clocks for the driver. Signed-off-by: Tero Kristo <t-kristo@ti.com> Signed-off-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r--drivers/rtc/rtc-omap.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index dddaa60871b9..51e52446eacb 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -147,6 +147,7 @@ struct omap_rtc {
147 u8 interrupts_reg; 147 u8 interrupts_reg;
148 bool is_pmic_controller; 148 bool is_pmic_controller;
149 bool has_ext_clk; 149 bool has_ext_clk;
150 bool is_suspending;
150 const struct omap_rtc_device_type *type; 151 const struct omap_rtc_device_type *type;
151 struct pinctrl_dev *pctldev; 152 struct pinctrl_dev *pctldev;
152}; 153};
@@ -900,8 +901,7 @@ static int omap_rtc_suspend(struct device *dev)
900 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); 901 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
901 rtc->type->lock(rtc); 902 rtc->type->lock(rtc);
902 903
903 /* Disable the clock/module */ 904 rtc->is_suspending = true;
904 pm_runtime_put_sync(dev);
905 905
906 return 0; 906 return 0;
907} 907}
@@ -910,9 +910,6 @@ static int omap_rtc_resume(struct device *dev)
910{ 910{
911 struct omap_rtc *rtc = dev_get_drvdata(dev); 911 struct omap_rtc *rtc = dev_get_drvdata(dev);
912 912
913 /* Enable the clock/module so that we can access the registers */
914 pm_runtime_get_sync(dev);
915
916 rtc->type->unlock(rtc); 913 rtc->type->unlock(rtc);
917 if (device_may_wakeup(dev)) 914 if (device_may_wakeup(dev))
918 disable_irq_wake(rtc->irq_alarm); 915 disable_irq_wake(rtc->irq_alarm);
@@ -920,11 +917,34 @@ static int omap_rtc_resume(struct device *dev)
920 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg); 917 rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg);
921 rtc->type->lock(rtc); 918 rtc->type->lock(rtc);
922 919
920 rtc->is_suspending = false;
921
923 return 0; 922 return 0;
924} 923}
925#endif 924#endif
926 925
927static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume); 926#ifdef CONFIG_PM
927static int omap_rtc_runtime_suspend(struct device *dev)
928{
929 struct omap_rtc *rtc = dev_get_drvdata(dev);
930
931 if (rtc->is_suspending && !rtc->has_ext_clk)
932 return -EBUSY;
933
934 return 0;
935}
936
937static int omap_rtc_runtime_resume(struct device *dev)
938{
939 return 0;
940}
941#endif
942
943static const struct dev_pm_ops omap_rtc_pm_ops = {
944 SET_SYSTEM_SLEEP_PM_OPS(omap_rtc_suspend, omap_rtc_resume)
945 SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend,
946 omap_rtc_runtime_resume, NULL)
947};
928 948
929static void omap_rtc_shutdown(struct platform_device *pdev) 949static void omap_rtc_shutdown(struct platform_device *pdev)
930{ 950{