| From 4ab10417085fae142c7fa40f53de1475467abe53 Mon Sep 17 00:00:00 2001 |
| From: Brian Norris <briannorris@chromium.org> |
| Date: Tue, 4 Oct 2016 11:12:09 -0700 |
| Subject: [PATCH] clocksource/drivers/arm_arch_timer: Don't assume clock runs |
| in suspend |
| |
| commit d8ec7595a013237f82d965dcf981571aeb41855b upstream. |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt |
| index e774128935d5..3919b82dabae 100644 |
| --- a/Documentation/devicetree/bindings/arm/arch_timer.txt |
| +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt |
| @@ -32,6 +32,11 @@ to deliver its interrupts via SPIs. |
| architecturally-defined reset values. Only supported for 32-bit |
| systems which follow the ARMv7 architected reset values. |
| |
| +- arm,no-tick-in-suspend : The main counter does not tick when the system is in |
| + low-power system suspend on some SoCs. This behavior does not match the |
| + Architecture Reference Manual's specification that the system counter "must |
| + be implemented in an always-on power domain." |
| + |
| |
| Example: |
| |
| diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c |
| index 57700541f951..81fca7d97db0 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; |
| static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; |
| static bool arch_timer_c3stop; |
| static bool arch_timer_mem_use_virtual; |
| +static bool arch_counter_suspend_stop; |
| |
| static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); |
| |
| @@ -490,7 +491,7 @@ static struct clocksource clocksource_counter = { |
| .rating = 400, |
| .read = arch_counter_read, |
| .mask = CLOCKSOURCE_MASK(56), |
| - .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, |
| + .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| }; |
| |
| static struct cyclecounter cyclecounter = { |
| @@ -526,6 +527,8 @@ static void __init arch_counter_register(unsigned type) |
| clocksource_counter.name = "arch_mem_counter"; |
| } |
| |
| + if (!arch_counter_suspend_stop) |
| + clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; |
| start_count = arch_timer_read_counter(); |
| clocksource_register_hz(&clocksource_counter, arch_timer_rate); |
| cyclecounter.mult = clocksource_counter.mult; |
| @@ -808,6 +811,10 @@ static int __init arch_timer_of_init(struct device_node *np) |
| of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) |
| arch_timer_uses_ppi = PHYS_SECURE_PPI; |
| |
| + /* On some systems, the counter stops ticking when in suspend. */ |
| + arch_counter_suspend_stop = of_property_read_bool(np, |
| + "arm,no-tick-in-suspend"); |
| + |
| return arch_timer_init(); |
| } |
| CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); |
| -- |
| 2.12.0 |
| |