From: Greg Kroah-Hartman Date: Mon, 17 May 2021 10:33:32 +0000 (+0200) Subject: 5.11-stable patches X-Git-Tag: v5.4.120~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=37bfb90b70c38326423fd5c5c01416f3d6757582;p=thirdparty%2Fkernel%2Fstable-queue.git 5.11-stable patches added patches: clocksource-drivers-timer-ti-dm-handle-dra7-timer-wrap-errata-i940.patch clocksource-drivers-timer-ti-dm-prepare-to-handle-dra7-timer-wrap-issue.patch --- diff --git a/queue-5.11/clocksource-drivers-timer-ti-dm-handle-dra7-timer-wrap-errata-i940.patch b/queue-5.11/clocksource-drivers-timer-ti-dm-handle-dra7-timer-wrap-errata-i940.patch new file mode 100644 index 00000000000..54f1ac2421d --- /dev/null +++ b/queue-5.11/clocksource-drivers-timer-ti-dm-handle-dra7-timer-wrap-errata-i940.patch @@ -0,0 +1,205 @@ +From 25de4ce5ed02994aea8bc111d133308f6fd62566 Mon Sep 17 00:00:00 2001 +From: Tony Lindgren +Date: Tue, 23 Mar 2021 09:43:26 +0200 +Subject: clocksource/drivers/timer-ti-dm: Handle dra7 timer wrap errata i940 + +From: Tony Lindgren + +commit 25de4ce5ed02994aea8bc111d133308f6fd62566 upstream. + +There is a timer wrap issue on dra7 for the ARM architected timer. +In a typical clock configuration the timer fails to wrap after 388 days. + +To work around the issue, we need to use timer-ti-dm percpu timers instead. + +Let's configure dmtimer3 and 4 as percpu timers by default, and warn about +the issue if the dtb is not configured properly. + +Let's do this as a single patch so it can be backported to v5.8 and later +kernels easily. Note that this patch depends on earlier timer-ti-dm +systimer posted mode fixes, and a preparatory clockevent patch +"clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue". + +For more information, please see the errata for "AM572x Sitara Processors +Silicon Revisions 1.1, 2.0": + +https://www.ti.com/lit/er/sprz429m/sprz429m.pdf + +The concept is based on earlier reference patches done by Tero Kristo and +Keerthy. + +Cc: Keerthy +Cc: Tero Kristo +Signed-off-by: Tony Lindgren +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20210323074326.28302-3-tony@atomide.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/boot/dts/dra7-l4.dtsi | 4 - + arch/arm/boot/dts/dra7.dtsi | 20 +++++++ + drivers/clocksource/timer-ti-dm-systimer.c | 76 +++++++++++++++++++++++++++++ + include/linux/cpuhotplug.h | 1 + 4 files changed, 99 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/dra7-l4.dtsi ++++ b/arch/arm/boot/dts/dra7-l4.dtsi +@@ -1168,7 +1168,7 @@ + }; + }; + +- target-module@34000 { /* 0x48034000, ap 7 46.0 */ ++ timer3_target: target-module@34000 { /* 0x48034000, ap 7 46.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x34000 0x4>, + <0x34010 0x4>; +@@ -1195,7 +1195,7 @@ + }; + }; + +- target-module@36000 { /* 0x48036000, ap 9 4e.0 */ ++ timer4_target: target-module@36000 { /* 0x48036000, ap 9 4e.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x36000 0x4>, + <0x36010 0x4>; +--- a/arch/arm/boot/dts/dra7.dtsi ++++ b/arch/arm/boot/dts/dra7.dtsi +@@ -46,6 +46,7 @@ + + timer { + compatible = "arm,armv7-timer"; ++ status = "disabled"; /* See ARM architected timer wrap erratum i940 */ + interrupts = , + , + , +@@ -1241,3 +1242,22 @@ + assigned-clock-parents = <&sys_32k_ck>; + }; + }; ++ ++/* Local timers, see ARM architected timer wrap erratum i940 */ ++&timer3_target { ++ ti,no-reset-on-init; ++ ti,no-idle; ++ timer@0 { ++ assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER3_CLKCTRL 24>; ++ assigned-clock-parents = <&timer_sys_clk_div>; ++ }; ++}; ++ ++&timer4_target { ++ ti,no-reset-on-init; ++ ti,no-idle; ++ timer@0 { ++ assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 24>; ++ assigned-clock-parents = <&timer_sys_clk_div>; ++ }; ++}; +--- a/drivers/clocksource/timer-ti-dm-systimer.c ++++ b/drivers/clocksource/timer-ti-dm-systimer.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -630,6 +631,78 @@ err_out_free: + return error; + } + ++/* Dmtimer as percpu timer. See dra7 ARM architected timer wrap erratum i940 */ ++static DEFINE_PER_CPU(struct dmtimer_clockevent, dmtimer_percpu_timer); ++ ++static int __init dmtimer_percpu_timer_init(struct device_node *np, int cpu) ++{ ++ struct dmtimer_clockevent *clkevt; ++ int error; ++ ++ if (!cpu_possible(cpu)) ++ return -EINVAL; ++ ++ if (!of_property_read_bool(np->parent, "ti,no-reset-on-init") || ++ !of_property_read_bool(np->parent, "ti,no-idle")) ++ pr_warn("Incomplete dtb for percpu dmtimer %pOF\n", np->parent); ++ ++ clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu); ++ ++ error = dmtimer_clkevt_init_common(clkevt, np, CLOCK_EVT_FEAT_ONESHOT, ++ cpumask_of(cpu), "percpu-dmtimer", ++ 500); ++ if (error) ++ return error; ++ ++ return 0; ++} ++ ++/* See TRM for timer internal resynch latency */ ++static int omap_dmtimer_starting_cpu(unsigned int cpu) ++{ ++ struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu); ++ struct clock_event_device *dev = &clkevt->dev; ++ struct dmtimer_systimer *t = &clkevt->t; ++ ++ clockevents_config_and_register(dev, t->rate, 3, ULONG_MAX); ++ irq_force_affinity(dev->irq, cpumask_of(cpu)); ++ ++ return 0; ++} ++ ++static int __init dmtimer_percpu_timer_startup(void) ++{ ++ struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, 0); ++ struct dmtimer_systimer *t = &clkevt->t; ++ ++ if (t->sysc) { ++ cpuhp_setup_state(CPUHP_AP_TI_GP_TIMER_STARTING, ++ "clockevents/omap/gptimer:starting", ++ omap_dmtimer_starting_cpu, NULL); ++ } ++ ++ return 0; ++} ++subsys_initcall(dmtimer_percpu_timer_startup); ++ ++static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa) ++{ ++ struct device_node *arm_timer; ++ ++ arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer"); ++ if (of_device_is_available(arm_timer)) { ++ pr_warn_once("ARM architected timer wrap issue i940 detected\n"); ++ return 0; ++ } ++ ++ if (pa == 0x48034000) /* dra7 dmtimer3 */ ++ return dmtimer_percpu_timer_init(np, 0); ++ else if (pa == 0x48036000) /* dra7 dmtimer4 */ ++ return dmtimer_percpu_timer_init(np, 1); ++ ++ return 0; ++} ++ + /* Clocksource */ + static struct dmtimer_clocksource * + to_dmtimer_clocksource(struct clocksource *cs) +@@ -763,6 +836,9 @@ static int __init dmtimer_systimer_init( + if (clockevent == pa) + return dmtimer_clockevent_init(np); + ++ if (of_machine_is_compatible("ti,dra7")) ++ return dmtimer_percpu_quirk_init(np, pa); ++ + return 0; + } + +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -135,6 +135,7 @@ enum cpuhp_state { + CPUHP_AP_RISCV_TIMER_STARTING, + CPUHP_AP_CLINT_TIMER_STARTING, + CPUHP_AP_CSKY_TIMER_STARTING, ++ CPUHP_AP_TI_GP_TIMER_STARTING, + CPUHP_AP_HYPERV_TIMER_STARTING, + CPUHP_AP_KVM_STARTING, + CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING, diff --git a/queue-5.11/clocksource-drivers-timer-ti-dm-prepare-to-handle-dra7-timer-wrap-issue.patch b/queue-5.11/clocksource-drivers-timer-ti-dm-prepare-to-handle-dra7-timer-wrap-issue.patch new file mode 100644 index 00000000000..396f5404bd4 --- /dev/null +++ b/queue-5.11/clocksource-drivers-timer-ti-dm-prepare-to-handle-dra7-timer-wrap-issue.patch @@ -0,0 +1,149 @@ +From 3efe7a878a11c13b5297057bfc1e5639ce1241ce Mon Sep 17 00:00:00 2001 +From: Tony Lindgren +Date: Tue, 23 Mar 2021 09:43:25 +0200 +Subject: clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue + +From: Tony Lindgren + +commit 3efe7a878a11c13b5297057bfc1e5639ce1241ce upstream. + +There is a timer wrap issue on dra7 for the ARM architected timer. +In a typical clock configuration the timer fails to wrap after 388 days. + +To work around the issue, we need to use timer-ti-dm timers instead. + +Let's prepare for adding support for percpu timers by adding a common +dmtimer_clkevt_init_common() and call it from dmtimer_clockevent_init(). +This patch makes no intentional functional changes. + +Signed-off-by: Tony Lindgren +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20210323074326.28302-2-tony@atomide.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/clocksource/timer-ti-dm-systimer.c | 68 ++++++++++++++++++----------- + 1 file changed, 44 insertions(+), 24 deletions(-) + +--- a/drivers/clocksource/timer-ti-dm-systimer.c ++++ b/drivers/clocksource/timer-ti-dm-systimer.c +@@ -530,17 +530,17 @@ static void omap_clockevent_unidle(struc + writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup); + } + +-static int __init dmtimer_clockevent_init(struct device_node *np) ++static int __init dmtimer_clkevt_init_common(struct dmtimer_clockevent *clkevt, ++ struct device_node *np, ++ unsigned int features, ++ const struct cpumask *cpumask, ++ const char *name, ++ int rating) + { +- struct dmtimer_clockevent *clkevt; + struct clock_event_device *dev; + struct dmtimer_systimer *t; + int error; + +- clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL); +- if (!clkevt) +- return -ENOMEM; +- + t = &clkevt->t; + dev = &clkevt->dev; + +@@ -548,25 +548,23 @@ static int __init dmtimer_clockevent_ini + * We mostly use cpuidle_coupled with ARM local timers for runtime, + * so there's probably no use for CLOCK_EVT_FEAT_DYNIRQ here. + */ +- dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; +- dev->rating = 300; ++ dev->features = features; ++ dev->rating = rating; + dev->set_next_event = dmtimer_set_next_event; + dev->set_state_shutdown = dmtimer_clockevent_shutdown; + dev->set_state_periodic = dmtimer_set_periodic; + dev->set_state_oneshot = dmtimer_clockevent_shutdown; + dev->set_state_oneshot_stopped = dmtimer_clockevent_shutdown; + dev->tick_resume = dmtimer_clockevent_shutdown; +- dev->cpumask = cpu_possible_mask; ++ dev->cpumask = cpumask; + + dev->irq = irq_of_parse_and_map(np, 0); +- if (!dev->irq) { +- error = -ENXIO; +- goto err_out_free; +- } ++ if (!dev->irq) ++ return -ENXIO; + + error = dmtimer_systimer_setup(np, &clkevt->t); + if (error) +- goto err_out_free; ++ return error; + + clkevt->period = 0xffffffff - DIV_ROUND_CLOSEST(t->rate, HZ); + +@@ -578,32 +576,54 @@ static int __init dmtimer_clockevent_ini + writel_relaxed(OMAP_TIMER_CTRL_POSTED, t->base + t->ifctrl); + + error = request_irq(dev->irq, dmtimer_clockevent_interrupt, +- IRQF_TIMER, "clockevent", clkevt); ++ IRQF_TIMER, name, clkevt); + if (error) + goto err_out_unmap; + + writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena); + writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup); + +- pr_info("TI gptimer clockevent: %s%lu Hz at %pOF\n", +- of_find_property(np, "ti,timer-alwon", NULL) ? ++ pr_info("TI gptimer %s: %s%lu Hz at %pOF\n", ++ name, of_find_property(np, "ti,timer-alwon", NULL) ? + "always-on " : "", t->rate, np->parent); + +- clockevents_config_and_register(dev, t->rate, +- 3, /* Timer internal resynch latency */ ++ return 0; ++ ++err_out_unmap: ++ iounmap(t->base); ++ ++ return error; ++} ++ ++static int __init dmtimer_clockevent_init(struct device_node *np) ++{ ++ struct dmtimer_clockevent *clkevt; ++ int error; ++ ++ clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL); ++ if (!clkevt) ++ return -ENOMEM; ++ ++ error = dmtimer_clkevt_init_common(clkevt, np, ++ CLOCK_EVT_FEAT_PERIODIC | ++ CLOCK_EVT_FEAT_ONESHOT, ++ cpu_possible_mask, "clockevent", ++ 300); ++ if (error) ++ goto err_out_free; ++ ++ clockevents_config_and_register(&clkevt->dev, clkevt->t.rate, ++ 3, /* Timer internal resync latency */ + 0xffffffff); + + if (of_machine_is_compatible("ti,am33xx") || + of_machine_is_compatible("ti,am43")) { +- dev->suspend = omap_clockevent_idle; +- dev->resume = omap_clockevent_unidle; ++ clkevt->dev.suspend = omap_clockevent_idle; ++ clkevt->dev.resume = omap_clockevent_unidle; + } + + return 0; + +-err_out_unmap: +- iounmap(t->base); +- + err_out_free: + kfree(clkevt); + diff --git a/queue-5.11/series b/queue-5.11/series index 55ad2b0d211..2b7f00ce200 100644 --- a/queue-5.11/series +++ b/queue-5.11/series @@ -304,3 +304,5 @@ mm-fix-struct-page-layout-on-32-bit-systems.patch mips-reinstate-platform-__div64_32-handler.patch mips-avoid-divu-in-__div64_32-is-result-would-be-zero.patch mips-avoid-handcoded-divu-in-__div64_32-altogether.patch +clocksource-drivers-timer-ti-dm-prepare-to-handle-dra7-timer-wrap-issue.patch +clocksource-drivers-timer-ti-dm-handle-dra7-timer-wrap-errata-i940.patch