blob: 926b1c410df2d44dd586ad2b3ed1193c48a4baee (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
@page page_device_thermal_cool 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 @ref page_device_thermal).
| 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 (`thermal-cool-pwm-fan.c`)
### 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
```dts
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:
```dts
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 (`thermal-cool-gpio-fan.c`)
**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 (`thermal-cool-dvfs.c`)
**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
- @ref page_device_thermal
- @ref page_device_pwm
- @ref page_device_regulator
- @ref page_device_pin
- `components/drivers/thermal/thermal-cool-pwm-fan.c`
|