diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile
index 5aa1f0a2f294a9..ea87c79e646080 100644
--- a/arch/arm/boot/dts/overlays/Makefile
+++ b/arch/arm/boot/dts/overlays/Makefile
@@ -221,6 +221,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
pwm.dtbo \
pwm-2chan.dtbo \
pwm-gpio.dtbo \
+ pwm-gpio-fan.dtbo \
pwm-ir-tx.dtbo \
pwm-pio.dtbo \
pwm1.dtbo \
diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
index eae80564281c61..803965cce2a43e 100644
--- a/arch/arm/boot/dts/overlays/README
+++ b/arch/arm/boot/dts/overlays/README
@@ -4076,6 +4076,46 @@ Load: dtoverlay=pwm-gpio,=
Params: gpio Output pin (default 4)
+Name: pwm-gpio-fan
+Info: Configure a GPIO connected PWM cooling fan controlled by the
+ software-based GPIO PWM kernel module
+Load: dtoverlay=pwm-gpio-fan,=
+Params: fan_gpio BCM number of the pin driving the fan,
+ default 18 (GPIO 18)
+ fan_temp0 CPU temperature at which fan is started with
+ low speed in millicelsius,
+ default 55000 (55 °C)
+ fan_temp1 CPU temperature at which fan is switched
+ to medium speed in millicelsius,
+ default 60000 (60 °C)
+ fan_temp2 CPU temperature at which fan is switched
+ to high speed in millicelsius,
+ default 67500 (67.5 °C)
+ fan_temp3 CPU temperature at which fan is switched
+ to max speed in millicelsius,
+ default 75000 (75 °C)
+ fan_temp0_hyst Temperature hysteris at which fan is stopped
+ in millicelsius,default 5000 (resulting
+ in 50 °C)
+ fan_temp1_hyst Temperature hysteris at which fan is switched
+ back to low speed in millicelsius,
+ default 5000 (resulting in 55 °C)
+ fan_temp2_hyst Temperature hysteris at which fan is switched
+ back to medium speed in millicelsius,
+ default 5000 (resulting in 62.5 °C)
+ fan_temp3_hyst Temperature hysteris at which fan is switched
+ back to high speed in millicelsius,
+ default 5000 (resulting in 70 °C)
+ fan_temp0_speed Fan speed for low cooling state in range
+ 0 to 255, default 114 (45% PWM duty cycle)
+ fan_temp1_speed Fan speed for medium cooling state in range
+ 0 to 255, default 152 (60% PWM duty cycle)
+ fan_temp2_speed Fan speed for high cooling state in range
+ 0 to 255, default 204 (80% PWM duty cycle)
+ fan_temp3_speed Fan speed for max cooling state in range
+ 0 to 255, default 255 (100% PWM duty cycle)
+
+
Name: pwm-ir-tx
Info: Use GPIO pin as pwm-assisted infrared transmitter output.
This is an alternative to "gpio-ir-tx". pwm-ir-tx makes use
diff --git a/arch/arm/boot/dts/overlays/pwm-gpio-fan-overlay.dts b/arch/arm/boot/dts/overlays/pwm-gpio-fan-overlay.dts
new file mode 100644
index 00000000000000..dc5e586a3251c6
--- /dev/null
+++ b/arch/arm/boot/dts/overlays/pwm-gpio-fan-overlay.dts
@@ -0,0 +1,170 @@
+/*
+ * Overlay for a GPIO connected PWM cooling fan controlled by software GPIO PWM
+ *
+ * Optional parameters:
+ * - "fan_gpio" BCM number of the pin driving the fan, default 18 (GPIO18)
+ *
+ * - "fan_temp0" CPU temperature at which fan is started with low speed in millicelsius,
+ * default 55000 (55 °C)
+ * - "fan_temp1" CPU temperature at which fan is switched to medium speed in millicelsius,
+ * default 60000 (60 °C)
+ * - "fan_temp2" CPU temperature at which fan is switched to high speed in millicelsius,
+ * default 67500 (67.5 °C)
+ * - "fan_temp3" CPU temperature at which fan is switched to max speed in millicelsius,
+ * default 75000 (75 °C)
+ * - "fan_temp0_hyst" Temperature hysteris at which fan is stopped in millicelsius,
+ * default 5000 (resulting in 50 °C)
+ * - "fan_temp1_hyst" Temperature hysteris at which fan is switched back to low speed
+ * in millicelsius, default 5000 (resulting in 55 °C)
+ * - "fan_temp2_hyst" Temperature hysteris at which fan is switched back to medium speed
+ * in millicelsius, default 5000 (resulting in 62.5 °C)
+ * - "fan_temp3_hyst" Temperature hysteris at which fan is switched back to high speed
+ * in millicelsius, default 5000 (resulting in 70 °C)
+ * - "fan_temp0_speed" Fan speed for low cooling state in range 0 to 255,
+ * default 114 (45% PWM duty cycle)
+ * - "fan_temp1_speed" Fan speed for medium cooling state in range 0 to 255,
+ * default 152 (60% PWM duty cycle)
+ * - "fan_temp2_speed" Fan speed for high cooling state in range 0 to 255,
+ * default 204 (80% PWM duty cycle)
+ * - "fan_temp3_speed" Fan speed for max cooling state in range 0 to 255,
+ * default 255 (100% PWM duty cycle)
+ *
+ * N.B.
+ * - Uses the software GPIO PWM kernel module instead of the Pis hardware PWMs (PWM0/PWM1).
+ * This will allow for an undisturbed concurrent usage of the Pis analogue audio output.
+ *
+ * Requires:
+ * - A PWM controlled cooling fan connected to the GPIO, such as an
+ * Argon mini-fan, HighPi Pro Fan or Waveshare FAN-4020-PWM-5V
+ * - Raspberry Pi OS Bookworm with kernel 6.6.62 or above
+ *
+ * Build:
+ * - sudo dtc -I dts -O dtb -o /boot/firmware/overlays/pwm-gpiofan.dtbo pwm-gpiofan-overlay.dts
+ *
+ * Activate:
+ * - sudo nano /boot/firmware/config.txt add "dtoverlay=pwm-gpiofan"
+ *
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+ __overlay__ {
+ pwm_gpio_pins: pwm_gpio_pins {
+ brcm,pins = <18>; /* gpio-pin = 18 */
+ brcm,function = <1>; /* gpio function = output */
+ brcm,pull = <0>; /* gpio pull up/down = off */
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/";
+ __overlay__ {
+ pwm_gpio: pwm_gpio {
+ compatible="pwm-gpio";
+ #pwm-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_gpio_pins>;
+ gpios = <&gpio 18 0>; /* gpio-pin = 18 */
+ };
+ };
+ };
+
+ fragment@2 {
+ target-path = "/";
+ __overlay__ {
+ fan0: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ /* in ns = 20ms = 50 Hz */
+ pwms = <&pwm_gpio 0 20000000 0>;
+
+ cooling-min-state = <0>;
+ cooling-max-state = <4>;
+ /* PWM duty cycle values in a range from 0 to 255 */
+ /* which correspond to thermal cooling states 0 to 4 */
+ cooling-levels = <0 114 152 204 255>;
+ };
+ };
+ };
+
+ fragment@3 {
+ target = <&cpu_thermal>;
+ __overlay__ {
+ /* in ms = poll every 2s */
+ polling-delay = <2000>;
+ };
+ };
+
+ fragment@4 {
+ target = <&thermal_trips>;
+ __overlay__ {
+ /* below temperatures in millicelsius */
+ trip0: trip0 {
+ temperature = <55000>; /* 55 °C */
+ hysteresis = <5000>; /* 5 °C */
+ type = "active";
+ };
+ trip1: trip1 {
+ temperature = <60000>; /* 60 °C */
+ hysteresis = <5000>; /* 5 °C */
+ type = "active";
+ };
+ trip2: trip2 {
+ temperature = <67500>; /* 67.5 °C */
+ hysteresis = <5000>; /* 5 °C */
+ type = "active";
+ };
+ trip3: trip3 {
+ temperature = <75000>; /* 75 °C */
+ hysteresis = <5000>; /* 5 °C */
+ type = "active";
+ };
+ };
+ };
+
+ fragment@5 {
+ target = <&cooling_maps>;
+ __overlay__ {
+ map0 {
+ cooling-device = <&fan0 0 1>;
+ trip = <&trip0>;
+ };
+ map1 {
+ cooling-device = <&fan0 1 2>;
+ trip = <&trip1>;
+ };
+ map2 {
+ cooling-device = <&fan0 2 3>;
+ trip = <&trip2>;
+ };
+ map3 {
+ cooling-device = <&fan0 3 4>;
+ trip = <&trip3>;
+ };
+ };
+ };
+
+ __overrides__ {
+ fan_gpio = <&pwm_gpio>,"gpios:4",
+ <&pwm_gpio_pins>,"brcm,pins:0";
+ fan_temp0 = <&trip0>,"temperature:0";
+ fan_temp0_hyst = <&trip0>,"hysteresis:0";
+ fan_temp0_speed = <&fan0>,"cooling-levels:4";
+ fan_temp1 = <&trip1>,"temperature:0";
+ fan_temp1_hyst = <&trip1>,"hysteresis:0";
+ fan_temp1_speed = <&fan0>,"cooling-levels:8";
+ fan_temp2 = <&trip2>,"temperature:0";
+ fan_temp2_hyst = <&trip2>,"hysteresis:0";
+ fan_temp2_speed = <&fan0>,"cooling-levels:12";
+ fan_temp3 = <&trip3>,"temperature:0";
+ fan_temp3_hyst = <&trip3>,"hysteresis:0";
+ fan_temp3_speed = <&fan0>,"cooling-levels:16";
+ };
+
+};