From c6d33bfd8717f06265f73bafe4c6dc5569a5da16 Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 10:56:34 +0300 Subject: [PATCH 1/8] arm64: dts: allwinner: h616: add lowest possible frequency H616 core can be clocked at 288 MHz on CPU_PLL without adjusting PLL frequency divider which the kernel doesn't support at the moment. Running at 288 MHz compared to 488 MHz saves some 0.1W of power. --- arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi index aca22a7f0191..4791e1fd7c20 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi @@ -7,6 +7,13 @@ nvmem-cells = <&cpu_speed_grade>; opp-shared; + opp-288000000 { + opp-hz = /bits/ 64 <288000000>; + opp-microvolt = <900000>; + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-supported-hw = <0x1f>; + }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; opp-microvolt = <900000>; From f16c62646835533bdabdf2d6945dd46e4f8b847b Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 10:58:48 +0300 Subject: [PATCH 2/8] wb8: dts: don't enabled unused PMIC LDOs --- arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi index 8601b06607b1..48e81adf0aa0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi @@ -881,7 +881,6 @@ regulator-max-microvolt = <1800000>; regulator-step-delay-us = <25>; regulator-final-delay-us = <50>; - regulator-always-on; }; reg_bldo5: bldo5 { @@ -898,7 +897,6 @@ regulator-max-microvolt = <3300000>; regulator-step-delay-us = <25>; regulator-final-delay-us = <50>; - regulator-always-on; }; reg_cldo2: cldo2 { @@ -907,7 +905,6 @@ regulator-max-microvolt = <1800000>; regulator-step-delay-us = <25>; regulator-final-delay-us = <50>; - regulator-always-on; }; reg_cldo3: cldo3 { From 6c007ad72d866a670fd3f8cabcd0791fea31cdcf Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 11:40:25 +0300 Subject: [PATCH 3/8] wb8: dts: meaningful thermal throttling Update critical temperature to match T507 industrial temperature range. For thermal throttling we use step-wise throttling optimized for at least 10 years chip lifetime at full load. As the lifetime is limited not only by temperature by also by core voltage, we disallow high core voltage opps at higher core temperatures. --- .../allwinner/sun50i-h616-wirenboard8xx.dtsi | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi index 48e81adf0aa0..99d5b05133bb 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi @@ -460,6 +460,140 @@ status = "okay"; }; }; + + thermal-zones { + /* + target minimum lifetime is 100 000 hours or ~11.5 years. + As per T517 chip lifetime evaluation guide, it corresponds to + junction temperature of: + 125C @ 0.900V (note it's also absolute maximum Tj) + 115С @ 0.950V (not in the source, intrapolated) + 105C @ 1.000V + 95C @ 1.050V + 85C @ 1.100V (not in the source, extrapolated) + + Taking into account that the temperature sensor accuracy is + ±3°C from 0°C to +100°C, ±5°C from -25°C to +125°C Tj, max allowed + junction temperature should be: + 120C @ 0.900V + 110C @ 0.950V + 100C @ 1.000V (lower voltage to below 1.0V once hit 100C) + 92C @ 1.050V (lower voltage to below 1.05V once hit 92C) + 82C @ 1.100V (lower voltage to below 1.1V once hit 82C) + */ + cpu-thermal { + sustainable-power = <1100>; + + k_po = <45>; + k_pu = <90>; + k_i = <0>; + /delete-node/ trips; + /delete-node/ cooling-maps; + + trips { + cpu_max_for_1100mv: cpu-trip-0 { + temperature = <82000>; + type = "passive"; + hysteresis = <500>; + }; + cpu_max_for_1050mv: cpu-trip-1 { + temperature = <92000>; + type = "passive"; + hysteresis = <500>; + }; + + cpu_max_for_1000mv: cpu-trip-2 { + temperature = <100000>; + type = "passive"; + hysteresis = <500>; + }; + + cpu_max_for_950mv: cpu-trip-3 { + temperature = <110000>; + type = "passive"; + hysteresis = <500>; + }; + + + cpu_critical: cpu-trip-4 { + /* + 120C is the maximum recommended Tj, + temperature sensor accuracy is +/-5C @ Tj>100C + so we should not exceed 115C just in case + */ + temperature = <115000>; + type = "critical"; + hysteresis = <0>; + }; + }; + cooling-maps { + /* + The OPP voltages depends on revision and speed grade. + Anyway: + 2: 1200 MHz, 1.02V - 1.10V, 1.05V on ours + 3: 1104 MHz, 1.00V (use it to go lower than 1.05V) + 4: 1008 MHz, 0.94V - 1.02V, 0.95V on ours + 5: 936 MHz, 0.90V (lowest voltage, allowed at any Tj) + 6: 720 MHz, 0.90V + */ + + /* + The first two maps are to limit the voltage. + That's why we don't allow lower frequencies on the cooling device. + */ + map0 { + trip = <&cpu_max_for_1100mv>; + cooling-device = <&cpu0 2 2>, + <&cpu1 2 2>, + <&cpu2 2 2>, + <&cpu3 2 2>; + }; + + map1 { + trip = <&cpu_max_for_1050mv>; + cooling-device = <&cpu0 3 3>, + <&cpu1 3 3>, + <&cpu2 3 3>, + <&cpu3 3 3>; + }; + + /* + This is our target temperature point. + We nevertheless limit the frequency to 480 MHz, so the performace + is not too low. + */ + map2 { + trip = <&cpu_max_for_1000mv>; + cooling-device = <&cpu0 4 7>, + <&cpu1 4 7>, + <&cpu2 4 7>, + <&cpu3 4 7>; + }; + + /* + At this point we should do everything to maintain the temperature. + */ + map3 { + trip = <&cpu_max_for_950mv>; + cooling-device = <&cpu0 5 THERMAL_NO_LIMIT>, + <&cpu1 5 THERMAL_NO_LIMIT>, + <&cpu2 5 THERMAL_NO_LIMIT>, + <&cpu3 5 THERMAL_NO_LIMIT>; + }; + }; + }; + }; +}; + +// override GPU, VE and DDR critical temperatures +&gpu_temp_critical { + temperature = <115000>; +}; +&ve_temp_critical { + temperature = <115000>; +}; +&ddr_temp_critical { + temperature = <115000>; }; &spi1 { From 921b01f0efc973c76095bec1dca66b7175df3066 Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 14:58:42 +0300 Subject: [PATCH 4/8] wb8: dts: add thermal interfaces add debug, statistics interfaces and also make trips writable from userspace --- arch/arm64/configs/wb8_reduced_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/wb8_reduced_defconfig b/arch/arm64/configs/wb8_reduced_defconfig index 836caf2397db..c8ee08c633ab 100644 --- a/arch/arm64/configs/wb8_reduced_defconfig +++ b/arch/arm64/configs/wb8_reduced_defconfig @@ -397,6 +397,11 @@ CONFIG_SENSORS_LM90=m CONFIG_SENSORS_PWM_FAN=m CONFIG_SENSORS_INA2XX=m CONFIG_SENSORS_INA3221=m +CONFIG_THERMAL_NETLINK=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_THERMAL_DEBUGFS=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=5000 +CONFIG_THERMAL_WRITABLE_TRIPS=y CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y CONFIG_DEVFREQ_THERMAL=y From e16f58c5b5ffda00c295fa3f19629746a37f040b Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 15:00:18 +0300 Subject: [PATCH 5/8] wb8: dts: add netconsole as a module netconsole allows to send crash logs to other PC --- arch/arm64/configs/wb8_reduced_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/wb8_reduced_defconfig b/arch/arm64/configs/wb8_reduced_defconfig index c8ee08c633ab..8ed6e60f5d69 100644 --- a/arch/arm64/configs/wb8_reduced_defconfig +++ b/arch/arm64/configs/wb8_reduced_defconfig @@ -212,6 +212,8 @@ CONFIG_DM_ZERO=m CONFIG_NETDEVICES=y CONFIG_MACVLAN=m CONFIG_MACVTAP=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y CONFIG_TUN=y CONFIG_VETH=m CONFIG_VIRTIO_NET=y From 3964b4639365b023fbca50afadbd612ab5a00911 Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 15:12:49 +0300 Subject: [PATCH 6/8] arm64: dts: allwinner: h616: add CPU idle states and thermal idle devices Injecting idle has much greater effect on CPU power consumption than just lowering frequency under a constant 100% load. Thus, it's very useful for thermal throttling near critically high temperatures. Users are expected to explicitly reference thermal idle states in their cooling maps. --- .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi index 8435aec0f8c2..59a72bfba76c 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi @@ -27,6 +27,14 @@ enable-method = "psci"; clocks = <&ccu CLK_CPUX>; #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP>; + dynamic-power-coefficient = <100>; + + cpu0idle: thermal-idle { + #cooling-cells = <2>; + duration-us = <10000>; + exit-latency-us = <500>; + }; }; cpu1: cpu@1 { @@ -36,6 +44,13 @@ enable-method = "psci"; clocks = <&ccu CLK_CPUX>; #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP>; + + cpu1idle: thermal-idle { + #cooling-cells = <2>; + duration-us = <10000>; + exit-latency-us = <500>; + }; }; cpu2: cpu@2 { @@ -45,6 +60,13 @@ enable-method = "psci"; clocks = <&ccu CLK_CPUX>; #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP>; + + cpu2idle: thermal-idle { + #cooling-cells = <2>; + duration-us = <10000>; + exit-latency-us = <500>; + }; }; cpu3: cpu@3 { @@ -54,6 +76,25 @@ enable-method = "psci"; clocks = <&ccu CLK_CPUX>; #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP>; + + cpu3idle: thermal-idle { + #cooling-cells = <2>; + duration-us = <10000>; + exit-latency-us = <500>; + }; + }; + idle-states { + entry-method = "psci"; + + CPU_SLEEP: cpu-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <120>; + exit-latency-us = <250>; + min-residency-us = <900>; + }; }; }; From 60830473aff72eb7d99056c9205f8e3bfe8e4578 Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 15:14:06 +0300 Subject: [PATCH 7/8] wb8: defconfig: enable idle thermal Injecting idle can cool CPU better than just lowering the CPU frequency. --- arch/arm64/configs/wb8_reduced_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/wb8_reduced_defconfig b/arch/arm64/configs/wb8_reduced_defconfig index 8ed6e60f5d69..17daa2cb66f8 100644 --- a/arch/arm64/configs/wb8_reduced_defconfig +++ b/arch/arm64/configs/wb8_reduced_defconfig @@ -406,6 +406,7 @@ CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=5000 CONFIG_THERMAL_WRITABLE_TRIPS=y CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y +CONFIG_CPU_IDLE_THERMAL=y CONFIG_DEVFREQ_THERMAL=y CONFIG_THERMAL_EMULATION=y CONFIG_SUN8I_THERMAL=y @@ -704,6 +705,9 @@ CONFIG_PHY_CADENCE_TORRENT=m CONFIG_PHY_CADENCE_SIERRA=m CONFIG_PHY_QCOM_USB_HS=m CONFIG_PHY_SAMSUNG_USB2=y +CONFIG_POWERCAP=y +CONFIG_IDLE_INJECT=y +CONFIG_ARM_SCMI_POWERCAP=y CONFIG_ARM_CCI_PMU=m CONFIG_ARM_CCN=m CONFIG_ARM_CMN=m From caafa51b656563bf3dcdda3361e0c00088bb22bd Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 17 Jun 2024 15:15:42 +0300 Subject: [PATCH 8/8] wb8: dts: enable thermal idle cooling --- .../boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi index 99d5b05133bb..d26ae0e56283 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-wirenboard8xx.dtsi @@ -578,8 +578,11 @@ cooling-device = <&cpu0 5 THERMAL_NO_LIMIT>, <&cpu1 5 THERMAL_NO_LIMIT>, <&cpu2 5 THERMAL_NO_LIMIT>, - <&cpu3 5 THERMAL_NO_LIMIT>; - }; + <&cpu3 5 THERMAL_NO_LIMIT>, + /* don't inject idle to CPU0 so it's available for kernel tasks */ + <&cpu1idle THERMAL_NO_LIMIT 90>, + <&cpu2idle THERMAL_NO_LIMIT 90>, + <&cpu3idle THERMAL_NO_LIMIT 90>; }; }; }; };