Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource/drivers/arm_arch_timer: Don't assume clock runs in suspend

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>

authored by

Brian Norris and committed by
Daniel Lezcano
d8ec7595 baa73d9e

+13 -1
+5
Documentation/devicetree/bindings/arm/arch_timer.txt
··· 38 38 architecturally-defined reset values. Only supported for 32-bit 39 39 systems which follow the ARMv7 architected reset values. 40 40 41 + - arm,no-tick-in-suspend : The main counter does not tick when the system is in 42 + low-power system suspend on some SoCs. This behavior does not match the 43 + Architecture Reference Manual's specification that the system counter "must 44 + be implemented in an always-on power domain." 45 + 41 46 42 47 Example: 43 48
+8 -1
drivers/clocksource/arm_arch_timer.c
··· 81 81 static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; 82 82 static bool arch_timer_c3stop; 83 83 static bool arch_timer_mem_use_virtual; 84 + static bool arch_counter_suspend_stop; 84 85 85 86 static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); 86 87 ··· 577 576 .rating = 400, 578 577 .read = arch_counter_read, 579 578 .mask = CLOCKSOURCE_MASK(56), 580 - .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, 579 + .flags = CLOCK_SOURCE_IS_CONTINUOUS, 581 580 }; 582 581 583 582 static struct cyclecounter cyclecounter = { ··· 617 616 arch_timer_read_counter = arch_counter_get_cntvct_mem; 618 617 } 619 618 619 + if (!arch_counter_suspend_stop) 620 + clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; 620 621 start_count = arch_timer_read_counter(); 621 622 clocksource_register_hz(&clocksource_counter, arch_timer_rate); 622 623 cyclecounter.mult = clocksource_counter.mult; ··· 909 906 if (IS_ENABLED(CONFIG_ARM) && 910 907 of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) 911 908 arch_timer_uses_ppi = PHYS_SECURE_PPI; 909 + 910 + /* On some systems, the counter stops ticking when in suspend. */ 911 + arch_counter_suspend_stop = of_property_read_bool(np, 912 + "arm,no-tick-in-suspend"); 912 913 913 914 return arch_timer_init(); 914 915 }