From 93e8deccd1317f9731d9487314497de59becdb00 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 13 Mar 2021 23:54:25 -0600 Subject: [PATCH 278/478] arm64: dts: allwinner: a64/h5: Add CPU idle states Powering off idle CPUs saves about 30 mW compared to using WFI only. Additional power savings are possible by idling the L2 and downclocking the cluster when all CPUs are idle. Entry and exit latency were measured using a logic analyzer, with GPIO pins toggled in Linux after the calls to trace_cpu_idle() in cpuidle_enter_state(), and in the power management firmware after CPU power-off completes and immediately after detecting an interrupt. 800 us and 1500 us are worst-case values, largely driven by the fact that the power management firmware is single threaded. It can only handle commands to power off CPUs one at a time, and it cannot process any commands while powering on a CPU in response to an interrupt. The cluster suspend process reliably takes 36 us; I rounded this up to 50 us. If all CPUs enter the cluster idle state at the same time, exit latency is actually reduced, because there is no contention in that case. However, if only some CPUs enter the cluster idle state, behavior is the same as for CPU idle. Polling delay for the power management firmware to detect a pending interrupt is insignificant; it is less than 20 us. min-residency was chosen as the point where enabling the idle state consumed no more average power than disabling the idle state at a variety of interrupt rates. Signed-off-by: Samuel Holland --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 26 +++++++++++++++++++ arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 26 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 54747e99dfee..29ef980a39e2 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -54,6 +54,7 @@ cpu0: cpu@0 { clocks = <&ccu CLK_CPUX>; clock-names = "cpu"; #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; }; cpu1: cpu@1 { @@ -65,6 +66,7 @@ cpu1: cpu@1 { clocks = <&ccu CLK_CPUX>; clock-names = "cpu"; #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; }; cpu2: cpu@2 { @@ -76,6 +78,7 @@ cpu2: cpu@2 { clocks = <&ccu CLK_CPUX>; clock-names = "cpu"; #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; }; cpu3: cpu@3 { @@ -87,6 +90,29 @@ cpu3: cpu@3 { clocks = <&ccu CLK_CPUX>; clock-names = "cpu"; #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; + }; + + idle-states { + entry-method = "psci"; + + cpu_sleep: cpu-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <800>; + exit-latency-us = <1500>; + min-residency-us = <25000>; + arm,psci-suspend-param = <0x00010003>; + }; + + cluster_sleep: cluster-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <850>; + exit-latency-us = <1500>; + min-residency-us = <50000>; + arm,psci-suspend-param = <0x01010013>; + }; }; L2: l2-cache { diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi index e85695031a6b..02cc9be868f0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi @@ -18,6 +18,7 @@ cpu0: cpu@0 { clocks = <&ccu CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; }; cpu1: cpu@1 { @@ -28,6 +29,7 @@ cpu1: cpu@1 { clocks = <&ccu CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; }; cpu2: cpu@2 { @@ -38,6 +40,7 @@ cpu2: cpu@2 { clocks = <&ccu CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; }; cpu3: cpu@3 { @@ -48,6 +51,29 @@ cpu3: cpu@3 { clocks = <&ccu CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ #cooling-cells = <2>; + cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>; + }; + + idle-states { + entry-method = "psci"; + + cpu_sleep: cpu-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <800>; + exit-latency-us = <1500>; + min-residency-us = <25000>; + arm,psci-suspend-param = <0x00010003>; + }; + + cluster_sleep: cluster-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <850>; + exit-latency-us = <1500>; + min-residency-us = <50000>; + arm,psci-suspend-param = <0x01010013>; + }; }; }; -- 2.35.3