summaryrefslogtreecommitdiff
path: root/0001-arm64-dts-allwinner-a64-h5-Add-CPU-idle-states.patch
diff options
context:
space:
mode:
Diffstat (limited to '0001-arm64-dts-allwinner-a64-h5-Add-CPU-idle-states.patch')
-rw-r--r--0001-arm64-dts-allwinner-a64-h5-Add-CPU-idle-states.patch157
1 files changed, 157 insertions, 0 deletions
diff --git a/0001-arm64-dts-allwinner-a64-h5-Add-CPU-idle-states.patch b/0001-arm64-dts-allwinner-a64-h5-Add-CPU-idle-states.patch
new file mode 100644
index 0000000..7aa451f
--- /dev/null
+++ b/0001-arm64-dts-allwinner-a64-h5-Add-CPU-idle-states.patch
@@ -0,0 +1,157 @@
+From 4c8fb634216bf73fac117436e1b936557dc97793 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Sat, 13 Mar 2021 23:54:25 -0600
+Subject: [PATCH] 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 <samuel@sholland.org>
+---
+ 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 cac47cc50..83b198d12 100644
+--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+@@ -61,6 +61,7 @@ cpu0: cpu@0 {
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ #cooling-cells = <2>;
++ cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>;
+ };
+
+ cpu1: cpu@1 {
+@@ -72,6 +73,7 @@ cpu1: cpu@1 {
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ #cooling-cells = <2>;
++ cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>;
+ };
+
+ cpu2: cpu@2 {
+@@ -83,6 +85,7 @@ cpu2: cpu@2 {
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ #cooling-cells = <2>;
++ cpu-idle-states = <&cpu_sleep>, <&cluster_sleep>;
+ };
+
+ cpu3: cpu@3 {
+@@ -94,6 +97,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 62952660b..975a76a9f 100644
+--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+@@ -24,6 +24,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 {
+@@ -34,6 +35,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 {
+@@ -44,6 +46,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 {
+@@ -54,6 +57,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.39.0
+