diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2014-11-21 11:00:01 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-11-30 11:40:09 -0500 |
commit | f9a49ab53a269fda39ae57063bd336b4bd62fa76 (patch) | |
tree | 5ae5866c83027df010fbcc78755f46e4a380ce68 | |
parent | 0f077eb5cfaf453ad7379963a721b8c04f7c62a2 (diff) |
clocksource: time-armada-370-xp: add suspend/resume support
This commit adds a set of suspend/resume syscore_ops to respectively
save and restore a number of timer registers, in order to make sure
the clockevent and clocksource devices continue to work properly
across a suspend/resume cycle.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lkml.kernel.org/r/1416585613-2113-5-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r-- | drivers/clocksource/time-armada-370-xp.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 0451e62fac7a..ff37d3abb806 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/sched_clock.h> | 44 | #include <linux/sched_clock.h> |
45 | #include <linux/percpu.h> | 45 | #include <linux/percpu.h> |
46 | #include <linux/syscore_ops.h> | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * Timer block registers. | 49 | * Timer block registers. |
@@ -223,6 +224,28 @@ static struct notifier_block armada_370_xp_timer_cpu_nb = { | |||
223 | .notifier_call = armada_370_xp_timer_cpu_notify, | 224 | .notifier_call = armada_370_xp_timer_cpu_notify, |
224 | }; | 225 | }; |
225 | 226 | ||
227 | static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; | ||
228 | |||
229 | static int armada_370_xp_timer_suspend(void) | ||
230 | { | ||
231 | timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); | ||
232 | timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static void armada_370_xp_timer_resume(void) | ||
237 | { | ||
238 | writel(0xffffffff, timer_base + TIMER0_VAL_OFF); | ||
239 | writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); | ||
240 | writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); | ||
241 | writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); | ||
242 | } | ||
243 | |||
244 | struct syscore_ops armada_370_xp_timer_syscore_ops = { | ||
245 | .suspend = armada_370_xp_timer_suspend, | ||
246 | .resume = armada_370_xp_timer_resume, | ||
247 | }; | ||
248 | |||
226 | static void __init armada_370_xp_timer_common_init(struct device_node *np) | 249 | static void __init armada_370_xp_timer_common_init(struct device_node *np) |
227 | { | 250 | { |
228 | u32 clr = 0, set = 0; | 251 | u32 clr = 0, set = 0; |
@@ -285,6 +308,8 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) | |||
285 | /* Immediately configure the timer on the boot CPU */ | 308 | /* Immediately configure the timer on the boot CPU */ |
286 | if (!res) | 309 | if (!res) |
287 | armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); | 310 | armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); |
311 | |||
312 | register_syscore_ops(&armada_370_xp_timer_syscore_ops); | ||
288 | } | 313 | } |
289 | 314 | ||
290 | static void __init armada_xp_timer_init(struct device_node *np) | 315 | static void __init armada_xp_timer_init(struct device_node *np) |