aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
authorBrian Norris <briannorris@chromium.org>2017-04-04 15:32:05 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-12 06:41:16 -0400
commit26cbe162df3d0282e5108711663b8dcdafb1ad33 (patch)
treec8dd2fc66bb25fc646f349c6cae47b1b18829e28 /drivers/clocksource/arm_arch_timer.c
parentd2f1000c3ae3ce285d99dae444f85baa53c1dfe6 (diff)
clocksource/drivers/arm_arch_timer: Don't assume clock runs in suspend
[ Upstream commit d8ec7595a013237f82d965dcf981571aeb41855b ] The ARM specifies that the system counter "must be implemented in an always-on power domain," and so we try to use the counter as a source of timekeeping across suspend/resume. Unfortunately, some SoCs (e.g., Rockchip's RK3399) do not keep the counter ticking properly when switched from their high-power clock to the lower-power clock used in system suspend. Support this quirk by adding a new device tree property. Signed-off-by: Brian Norris <briannorris@chromium.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 73c487da6d2a..a2503db7e533 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -81,6 +81,7 @@ static struct clock_event_device __percpu *arch_timer_evt;
81static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; 81static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
82static bool arch_timer_c3stop; 82static bool arch_timer_c3stop;
83static bool arch_timer_mem_use_virtual; 83static bool arch_timer_mem_use_virtual;
84static bool arch_counter_suspend_stop;
84 85
85static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); 86static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
86 87
@@ -576,7 +577,7 @@ static struct clocksource clocksource_counter = {
576 .rating = 400, 577 .rating = 400,
577 .read = arch_counter_read, 578 .read = arch_counter_read,
578 .mask = CLOCKSOURCE_MASK(56), 579 .mask = CLOCKSOURCE_MASK(56),
579 .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, 580 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
580}; 581};
581 582
582static struct cyclecounter cyclecounter = { 583static struct cyclecounter cyclecounter = {
@@ -616,6 +617,8 @@ static void __init arch_counter_register(unsigned type)
616 arch_timer_read_counter = arch_counter_get_cntvct_mem; 617 arch_timer_read_counter = arch_counter_get_cntvct_mem;
617 } 618 }
618 619
620 if (!arch_counter_suspend_stop)
621 clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
619 start_count = arch_timer_read_counter(); 622 start_count = arch_timer_read_counter();
620 clocksource_register_hz(&clocksource_counter, arch_timer_rate); 623 clocksource_register_hz(&clocksource_counter, arch_timer_rate);
621 cyclecounter.mult = clocksource_counter.mult; 624 cyclecounter.mult = clocksource_counter.mult;
@@ -907,6 +910,10 @@ static int __init arch_timer_of_init(struct device_node *np)
907 of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) 910 of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
908 arch_timer_uses_ppi = PHYS_SECURE_PPI; 911 arch_timer_uses_ppi = PHYS_SECURE_PPI;
909 912
913 /* On some systems, the counter stops ticking when in suspend. */
914 arch_counter_suspend_stop = of_property_read_bool(np,
915 "arm,no-tick-in-suspend");
916
910 return arch_timer_init(); 917 return arch_timer_init();
911} 918}
912CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); 919CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);