RT-Thread RTOS
An open source embedded real-time operating system
Thermal cooling devices

Cooling devices (in-tree)

Cooling drivers implement **struct rt_thermal_cooling_device_ops** and register with **rt_thermal_cooling_device_register**. Zones reference them from **cooling-maps** (see Thermal management).

Driver Kconfig compatible (typical)
PWM fan **RT_THERMAL_COOL_PWM_FAN** **pwm-fan**
GPIO fan **RT_THERMAL_COOL_GPIO_FAN** (see thermal-cool-gpio-fan.c)
DVFS **RT_THERMAL_COOL_DVFS** (see thermal-cool-dvfs.c)

Sources: components/drivers/thermal/thermal-cool-*.c.


PWM fan (<tt>thermal-cool-pwm-fan.c</tt>)

Role

Maps thermal cooling level (0 … max_level) to PWM duty via optional **cooling-levels** LUT. Optional **fan** regulator supply (property resolves as supply name **fan** → **rt_regulator_get(dev, "fan")**).

Device tree

fan0: fan {
compatible = "pwm-fan";
pwms = <&pwm0 0 40000>; /* phandle, channel, period (ns) */
cooling-levels = <0 64 128 192 255>;
/* optional: bind regulator supply id "fan" on this node */
};

Referenced from zone:

cooling-device = <&fan0 0 4>; /* min level 0, max level 4 */
Property Role
**pwms** **#pwm-cells**: channel, period
**cooling-levels** PWM scale values per level; array length − 1 = max_level
Regulator **rt_regulator_get(dev, "fan")** — wire **fan** supply in regulator/DT as on your BSP

Ops behavior

Op Behavior
**get_max_level** **levels_nr - 1**
**get_cur_level** Current level (spinlock)
**set_cur_level** LUT → **rt_pwm_set**; level 0 powers off PWM/regulator

Power sequence: on — **rt_pwm_enable** then **rt_regulator_enable**; off — reverse with rollback on error.

Probe flow

  1. Parse **pwms**, ensure PWM controller probed (**rt_platform_ofw_request** if needed).
  2. Optional **rt_regulator_get(dev, "fan")**.
  3. Read **cooling-levels** array.
  4. **rt_thermal_cooling_device_register** — attaches default **dumb** governor.
  5. Initial **set_cur_level(0)** (fan off).

Platform driver: **RT_PLATFORM_DRIVER_EXPORT(pwm_fan_cool_driver)**.


GPIO fan (<tt>thermal-cool-gpio-fan.c</tt>)

Kconfig: **RT_THERMAL_COOL_GPIO_FAN** (**RT_USING_PIN**, **RT_USING_OFW**).

Controls fan speed via GPIO pins and a speed table (RPM / control value). Suitable for multi-wire fan tach/control GPIOs rather than PWM.

Inspect **gpio_fan_cool_probe** in the source for exact property names on your BSP.


DVFS cooling (<tt>thermal-cool-dvfs.c</tt>)

Kconfig: **RT_THERMAL_COOL_DVFS** + **RT_USING_DVFS**.

Exposes OPP table indices as cooling levels — **set_cur_level** selects a lower performance point. Use when passive trip should throttle CPU/GPU frequency instead of spinning a fan.


Integration checklist

  1. Register cooling device in platform **probe** before dependent zone (or rely on init order).
  2. Set **parent.ofw_node** on **rt_thermal_cooling_device.parent** so **thermal_ofw_setup** can match **cooling-device** phandles.
  3. Define **cooling-levels** (PWM) or max level in ops consistently with DT **cooling-device** min/max cells.
  4. Zone **cooling-maps** **trip** must point at a trip node parsed under the same thermal zone.
  5. Test with **rt_thermal_zone_device_update** or wait for poller — verify **set_cur_level** at each trip.

Pitfalls

  • Level 0: PWM driver turns off output; confirm acoustic/thermal spec allows full stop.
  • Regulator + PWM order: supply must match driver sequence (enable PWM before rail or as coded).
  • **set_cur_level in ISR**: uses spinlock — do not call from ISR.
  • Governor: **dumb** only nudges level on temperature delta vs **hysteresis** — custom governor may be needed for fine control.

See also