From d55e03fe67dd8815f806ee9533f58d247f523681 Mon Sep 17 00:00:00 2001 From: Jonathan Goyvaerts Date: Thu, 29 Oct 2026 13:49:38 -0300 Subject: [PATCH 1/3] arm64: dts: apple: t6040-j616s: Run the fans on the CPU die like macOS The CPU die zone runs both fans at full speed (5777 rpm) from a 95 C TCMz. Any all-core load gets there within seconds, so a kernel build or a game puts the fans at maximum, louder than this machine ever runs under macOS. macOS 26.6.2 on this machine (Mac16,7), 300 s of all-core load at full clocks (P 3852 MHz, E 2592 MHz, thermal pressure Nominal throughout, SMC fan targets F0Tg/F1Tg sampled every 2 s): TCMz fans F0/F1 (rpm) < 100 C off (95 C after 11 s, still off) ~100 C start at their minimum, 1350/1458 ~104.5 C targets leave the minimum 110.9 C (42 s) ~2200/2400, the peak 106.5 C steady 3450/3730 (60-65% of maximum), never higher Give the CPU die zone its own ladder on those numbers: fans at their minimum from 100 C (state 1), 104 C state 2, 106 C state 4 (~3250 rpm, where macOS settles), 108 C state 5, and full speed only at 111 C, just under the 113 C passive trip. Below 100 C the fans stay with the SMC, as under macOS. The GPU zones keep their ladder: there is no macOS measurement under GPU load yet. Signed-off-by: Jonathan Goyvaerts Assisted-by: LLM --- arch/arm64/boot/dts/apple/t6040-j616s.dts | 25 +++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/apple/t6040-j616s.dts b/arch/arm64/boot/dts/apple/t6040-j616s.dts index 83b29a6c3f866..a4833a4f27c1e 100644 --- a/arch/arm64/boot/dts/apple/t6040-j616s.dts +++ b/arch/arm64/boot/dts/apple/t6040-j616s.dts @@ -329,6 +329,13 @@ * highest state any zone asks for and goes back to the SMC once no * zone asks for anything. States 1-8 of a fan run it from its minimum * (1350 rpm) to its maximum (5777 rpm) in even steps. + * + * The CPU die ladder follows macOS 26.6.2 on this machine under 300 s + * of all-core load at full clocks (P 3852, E 2592 MHz, never + * throttled): the fans stay off up to TCMz ~100 C, start at their + * minimum, leave it near 104.5 C, and hold the die at a steady 106.5 C + * with 3450/3730 rpm (60-65% of maximum), after a 110.9 C peak. Full + * speed is kept for 111 C, just under the 113 C passive trip. */ #define J616S_FAN_TRIP(label, node, temp, hyst) \ label: node { \ @@ -344,6 +351,13 @@ J616S_FAN_TRIP(zone##_fan4, trip-fan4, 90000, 5000) \ J616S_FAN_TRIP(zone##_fan5, trip-fan5, 95000, 5000) +#define J616S_CPU_FAN_TRIPS(zone) \ + J616S_FAN_TRIP(zone##_fan1, trip-fan1, 100000, 5000) \ + J616S_FAN_TRIP(zone##_fan2, trip-fan2, 104000, 3000) \ + J616S_FAN_TRIP(zone##_fan3, trip-fan3, 106000, 3000) \ + J616S_FAN_TRIP(zone##_fan4, trip-fan4, 108000, 2000) \ + J616S_FAN_TRIP(zone##_fan5, trip-fan5, 111000, 2000) + #define J616S_FAN_MAP(trip_label, node, state) \ node { \ trip = <&trip_label>; \ @@ -358,6 +372,13 @@ J616S_FAN_MAP(zone##_fan4, map-fan4, 5) \ J616S_FAN_MAP(zone##_fan5, map-fan5, 8) +#define J616S_CPU_FAN_MAPS(zone) \ + J616S_FAN_MAP(zone##_fan1, map-fan1, 1) \ + J616S_FAN_MAP(zone##_fan2, map-fan2, 2) \ + J616S_FAN_MAP(zone##_fan3, map-fan3, 4) \ + J616S_FAN_MAP(zone##_fan4, map-fan4, 5) \ + J616S_FAN_MAP(zone##_fan5, map-fan5, 8) + thermal-zones { cpu-die-thermal { polling-delay-passive = <1000>; @@ -365,7 +386,7 @@ thermal-sensors = <&smc_hwmon 0>; /* TCMz */ trips { - J616S_FAN_TRIPS(cpu_die) + J616S_CPU_FAN_TRIPS(cpu_die) cpu_die_passive: cpu-die-passive { temperature = <113000>; @@ -381,7 +402,7 @@ }; cooling-maps { - J616S_FAN_MAPS(cpu_die) + J616S_CPU_FAN_MAPS(cpu_die) map-e { trip = <&cpu_die_passive>; From a4a2b435dbd7ae00174725c1a7fb50765ca6be19 Mon Sep 17 00:00:00 2001 From: Jonathan Goyvaerts Date: Thu, 29 Oct 2026 14:07:52 -0300 Subject: [PATCH 2/3] arm64: dts: apple: t6040-j616s: Hold the CPU die fan speeds through TCMz noise Under all-core load on a J616s with the macOS ladder, TCMz (the hottest of the die sensors) swings by up to 8 C between 2 s samples (99.5 -> 107.8 C), so with 2-5 C of hysteresis the fans hunted between 1350, 1980 and 3250 rpm 17 times in 110 s: audible pumping. macOS's SMC ramps its targets slowly instead. Widen the hysteresis to 10/8/7/5/3 C. Replaying the same 150 s trace through the trips gives no state change once the die first reaches 106 C: the fans hold ~3250 rpm, near macOS's steady 3450 rpm, and stay on until the die is clearly cooler, as under macOS. Signed-off-by: Jonathan Goyvaerts Assisted-by: LLM --- arch/arm64/boot/dts/apple/t6040-j616s.dts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/apple/t6040-j616s.dts b/arch/arm64/boot/dts/apple/t6040-j616s.dts index a4833a4f27c1e..4f18f94ebb464 100644 --- a/arch/arm64/boot/dts/apple/t6040-j616s.dts +++ b/arch/arm64/boot/dts/apple/t6040-j616s.dts @@ -335,7 +335,11 @@ * throttled): the fans stay off up to TCMz ~100 C, start at their * minimum, leave it near 104.5 C, and hold the die at a steady 106.5 C * with 3450/3730 rpm (60-65% of maximum), after a 110.9 C peak. Full - * speed is kept for 111 C, just under the 113 C passive trip. + * speed is kept for 111 C, just under the 113 C passive trip. TCMz, the + * hottest of the die sensors, swings by up to 8 C between samples + * under load, so the hysteresis spans that swing; a fan stays on its + * speed until the die is clearly cooler, as the SMC's slow ramp does + * under macOS. */ #define J616S_FAN_TRIP(label, node, temp, hyst) \ label: node { \ @@ -352,11 +356,11 @@ J616S_FAN_TRIP(zone##_fan5, trip-fan5, 95000, 5000) #define J616S_CPU_FAN_TRIPS(zone) \ - J616S_FAN_TRIP(zone##_fan1, trip-fan1, 100000, 5000) \ - J616S_FAN_TRIP(zone##_fan2, trip-fan2, 104000, 3000) \ - J616S_FAN_TRIP(zone##_fan3, trip-fan3, 106000, 3000) \ - J616S_FAN_TRIP(zone##_fan4, trip-fan4, 108000, 2000) \ - J616S_FAN_TRIP(zone##_fan5, trip-fan5, 111000, 2000) + J616S_FAN_TRIP(zone##_fan1, trip-fan1, 100000, 10000) \ + J616S_FAN_TRIP(zone##_fan2, trip-fan2, 104000, 8000) \ + J616S_FAN_TRIP(zone##_fan3, trip-fan3, 106000, 7000) \ + J616S_FAN_TRIP(zone##_fan4, trip-fan4, 108000, 5000) \ + J616S_FAN_TRIP(zone##_fan5, trip-fan5, 111000, 3000) #define J616S_FAN_MAP(trip_label, node, state) \ node { \ From 5c271f4b484e7ab9f64120512248ef8c7710468d Mon Sep 17 00:00:00 2001 From: Jonathan Goyvaerts Date: Thu, 29 Oct 2026 21:59:59 -0300 Subject: [PATCH 3/3] arm64: dts: apple: t6040-j616s: Keep full fan speed for the passive trip Under all-core load at full clocks (a Mesa build, P 4512 MHz), TCMz touches 111 C every half minute or so. The last step of the CPU die ladder then sends both fans from 3880 rpm straight to their 5777 rpm maximum, and back once the die is under 108 C: a loud surge that macOS never makes. macOS held this die at 106.5 C with at most 3730 rpm, even at its 110.9 C peak. Ask for state 6 (4510 rpm) at 111 C instead, and bind full speed to the 113 C passive trip, where the CPU clusters also start shedding clocks. The GPU zones keep their ladder. Signed-off-by: Jonathan Goyvaerts Assisted-by: LLM --- arch/arm64/boot/dts/apple/t6040-j616s.dts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/apple/t6040-j616s.dts b/arch/arm64/boot/dts/apple/t6040-j616s.dts index 4f18f94ebb464..9e77839cd0b64 100644 --- a/arch/arm64/boot/dts/apple/t6040-j616s.dts +++ b/arch/arm64/boot/dts/apple/t6040-j616s.dts @@ -334,12 +334,13 @@ * of all-core load at full clocks (P 3852, E 2592 MHz, never * throttled): the fans stay off up to TCMz ~100 C, start at their * minimum, leave it near 104.5 C, and hold the die at a steady 106.5 C - * with 3450/3730 rpm (60-65% of maximum), after a 110.9 C peak. Full - * speed is kept for 111 C, just under the 113 C passive trip. TCMz, the - * hottest of the die sensors, swings by up to 8 C between samples - * under load, so the hysteresis spans that swing; a fan stays on its - * speed until the die is clearly cooler, as the SMC's slow ramp does - * under macOS. + * with 3450/3730 rpm (60-65% of maximum), after a 110.9 C peak, never + * faster than 3730 rpm. So 111 C asks for state 6 (4510 rpm), and full + * speed waits for the 113 C passive trip, where the CPUs also shed + * clocks. TCMz, the hottest of the die sensors, swings by up to 8 C + * between samples under load, so the hysteresis spans that swing; a + * fan stays on its speed until the die is clearly cooler, as the + * SMC's slow ramp does under macOS. */ #define J616S_FAN_TRIP(label, node, temp, hyst) \ label: node { \ @@ -381,7 +382,8 @@ J616S_FAN_MAP(zone##_fan2, map-fan2, 2) \ J616S_FAN_MAP(zone##_fan3, map-fan3, 4) \ J616S_FAN_MAP(zone##_fan4, map-fan4, 5) \ - J616S_FAN_MAP(zone##_fan5, map-fan5, 8) + J616S_FAN_MAP(zone##_fan5, map-fan5, 6) \ + J616S_FAN_MAP(zone##_passive, map-fan6, 8) thermal-zones { cpu-die-thermal {