diff options
author | Tero Kristo <t-kristo@ti.com> | 2017-08-15 11:42:17 +0300 |
---|---|---|
committer | Tero Kristo <t-kristo@ti.com> | 2017-12-01 15:15:38 +0200 |
commit | 3d8598fb9c5a77837d9c0951efc5c36fdf91d87c (patch) | |
tree | 51ce4c28c45914709817e762824ad23f48ce3f54 /drivers/clk/ti | |
parent | 5b385a45e001955a8f0fb0c98c12039002280a5e (diff) | |
download | linux-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.c | 14 |
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; |