summaryrefslogtreecommitdiffstats
path: root/drivers/clk/ti
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2017-08-15 11:42:17 +0300
committerTero Kristo <t-kristo@ti.com>2017-12-01 15:15:38 +0200
commit3d8598fb9c5a77837d9c0951efc5c36fdf91d87c (patch)
tree51ce4c28c45914709817e762824ad23f48ce3f54 /drivers/clk/ti
parent5b385a45e001955a8f0fb0c98c12039002280a5e (diff)
downloadlinux-3d8598fb9c5a77837d9c0951efc5c36fdf91d87c.tar.gz
linux-3d8598fb9c5a77837d9c0951efc5c36fdf91d87c.tar.bz2
linux-3d8598fb9c5a77837d9c0951efc5c36fdf91d87c.zip
clk: ti: clkctrl: use fallback udelay approach if timekeeping is suspended
In certain cases it is possible that the timekeeping has been suspended already when attempting to disable/enable a clkctrl clock. This will happen at least on am43xx platform when attempting to enable / disable the clockevent source itself, burping out a warning from timekeeping core. The sequence of events leading to this: -> timekeeping_suspend() -> clockevents_suspend() -> omap_clkevt_idle() -> omap_hwmod_idle() -> _omap4_clkctrl_clk_disable() -> _omap4_is_timeout() Avoid the issue by checking if the timekeeping is suspended and using the fallback udelay approach for checking timeouts. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r--drivers/clk/ti/clkctrl.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
index 284ba449615c..38dbcc1b7e2c 100644
--- a/drivers/clk/ti/clkctrl.c
+++ b/drivers/clk/ti/clkctrl.c
@@ -21,6 +21,7 @@
#include <linux/of_address.h>
#include <linux/clk/ti.h>
#include <linux/delay.h>
+#include <linux/timekeeping.h>
#include "clock.h"
#define NO_IDLEST 0x1
@@ -90,7 +91,18 @@ static bool _omap4_is_ready(u32 val)
static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
{
- if (unlikely(_early_timeout)) {
+ /*
+ * There are two special cases where ktime_to_ns() can't be
+ * used to track the timeouts. First one is during early boot
+ * when the timers haven't been initialized yet. The second
+ * one is during suspend-resume cycle while timekeeping is
+ * being suspended / resumed. Clocksource for the system
+ * can be from a timer that requires pm_runtime access, which
+ * will eventually bring us here with timekeeping_suspended,
+ * during both suspend entry and resume paths. This happens
+ * at least on am43xx platform.
+ */
+ if (unlikely(_early_timeout || timekeeping_suspended)) {
if (time->cycles++ < timeout) {
udelay(1);
return false;