1eaf7b460SMauro Carvalho Chehab=================================
2eaf7b460SMauro Carvalho ChehabPower allocator governor tunables
3eaf7b460SMauro Carvalho Chehab=================================
4eaf7b460SMauro Carvalho Chehab
5eaf7b460SMauro Carvalho ChehabTrip points
6eaf7b460SMauro Carvalho Chehab-----------
7eaf7b460SMauro Carvalho Chehab
8eaf7b460SMauro Carvalho ChehabThe governor works optimally with the following two passive trip points:
9eaf7b460SMauro Carvalho Chehab
10eaf7b460SMauro Carvalho Chehab1.  "switch on" trip point: temperature above which the governor
11eaf7b460SMauro Carvalho Chehab    control loop starts operating.  This is the first passive trip
12eaf7b460SMauro Carvalho Chehab    point of the thermal zone.
13eaf7b460SMauro Carvalho Chehab
14eaf7b460SMauro Carvalho Chehab2.  "desired temperature" trip point: it should be higher than the
15eaf7b460SMauro Carvalho Chehab    "switch on" trip point.  This the target temperature the governor
16eaf7b460SMauro Carvalho Chehab    is controlling for.  This is the last passive trip point of the
17eaf7b460SMauro Carvalho Chehab    thermal zone.
18eaf7b460SMauro Carvalho Chehab
19eaf7b460SMauro Carvalho ChehabPID Controller
20eaf7b460SMauro Carvalho Chehab--------------
21eaf7b460SMauro Carvalho Chehab
22eaf7b460SMauro Carvalho ChehabThe power allocator governor implements a
23eaf7b460SMauro Carvalho ChehabProportional-Integral-Derivative controller (PID controller) with
24eaf7b460SMauro Carvalho Chehabtemperature as the control input and power as the controlled output:
25eaf7b460SMauro Carvalho Chehab
26eaf7b460SMauro Carvalho Chehab    P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power
27eaf7b460SMauro Carvalho Chehab
28eaf7b460SMauro Carvalho Chehabwhere
29eaf7b460SMauro Carvalho Chehab   -  e = desired_temperature - current_temperature
30eaf7b460SMauro Carvalho Chehab   -  err_integral is the sum of previous errors
31eaf7b460SMauro Carvalho Chehab   -  diff_err = e - previous_error
32eaf7b460SMauro Carvalho Chehab
33eaf7b460SMauro Carvalho ChehabIt is similar to the one depicted below::
34eaf7b460SMauro Carvalho Chehab
35eaf7b460SMauro Carvalho Chehab				      k_d
36eaf7b460SMauro Carvalho Chehab				       |
37eaf7b460SMauro Carvalho Chehab  current_temp                         |
38eaf7b460SMauro Carvalho Chehab       |                               v
39eaf7b460SMauro Carvalho Chehab       |              +----------+   +---+
40eaf7b460SMauro Carvalho Chehab       |       +----->| diff_err |-->| X |------+
41eaf7b460SMauro Carvalho Chehab       |       |      +----------+   +---+      |
42eaf7b460SMauro Carvalho Chehab       |       |                                |      tdp        actor
43eaf7b460SMauro Carvalho Chehab       |       |                      k_i       |       |  get_requested_power()
44eaf7b460SMauro Carvalho Chehab       |       |                       |        |       |        |     |
45eaf7b460SMauro Carvalho Chehab       |       |                       |        |       |        |     | ...
46eaf7b460SMauro Carvalho Chehab       v       |                       v        v       v        v     v
47eaf7b460SMauro Carvalho Chehab     +---+     |      +-------+      +---+    +---+   +---+   +----------+
48eaf7b460SMauro Carvalho Chehab     | S |-----+----->| sum e |----->| X |--->| S |-->| S |-->|power     |
49eaf7b460SMauro Carvalho Chehab     +---+     |      +-------+      +---+    +---+   +---+   |allocation|
50eaf7b460SMauro Carvalho Chehab       ^       |                                ^             +----------+
51eaf7b460SMauro Carvalho Chehab       |       |                                |                |     |
52eaf7b460SMauro Carvalho Chehab       |       |        +---+                   |                |     |
53eaf7b460SMauro Carvalho Chehab       |       +------->| X |-------------------+                v     v
54eaf7b460SMauro Carvalho Chehab       |                +---+                               granted performance
55eaf7b460SMauro Carvalho Chehab  desired_temperature     ^
56eaf7b460SMauro Carvalho Chehab			  |
57eaf7b460SMauro Carvalho Chehab			  |
58eaf7b460SMauro Carvalho Chehab		      k_po/k_pu
59eaf7b460SMauro Carvalho Chehab
60eaf7b460SMauro Carvalho ChehabSustainable power
61eaf7b460SMauro Carvalho Chehab-----------------
62eaf7b460SMauro Carvalho Chehab
63eaf7b460SMauro Carvalho ChehabAn estimate of the sustainable dissipatable power (in mW) should be
64eaf7b460SMauro Carvalho Chehabprovided while registering the thermal zone.  This estimates the
65eaf7b460SMauro Carvalho Chehabsustained power that can be dissipated at the desired control
66eaf7b460SMauro Carvalho Chehabtemperature.  This is the maximum sustained power for allocation at
67eaf7b460SMauro Carvalho Chehabthe desired maximum temperature.  The actual sustained power can vary
68eaf7b460SMauro Carvalho Chehabfor a number of reasons.  The closed loop controller will take care of
69eaf7b460SMauro Carvalho Chehabvariations such as environmental conditions, and some factors related
70eaf7b460SMauro Carvalho Chehabto the speed-grade of the silicon.  `sustainable_power` is therefore
71eaf7b460SMauro Carvalho Chehabsimply an estimate, and may be tuned to affect the aggressiveness of
72eaf7b460SMauro Carvalho Chehabthe thermal ramp. For reference, the sustainable power of a 4" phone
73eaf7b460SMauro Carvalho Chehabis typically 2000mW, while on a 10" tablet is around 4500mW (may vary
74*5a64f775SLukasz Lubadepending on screen size). It is possible to have the power value
75*5a64f775SLukasz Lubaexpressed in an abstract scale. The sustained power should be aligned
76*5a64f775SLukasz Lubato the scale used by the related cooling devices.
77eaf7b460SMauro Carvalho Chehab
78eaf7b460SMauro Carvalho ChehabIf you are using device tree, do add it as a property of the
79eaf7b460SMauro Carvalho Chehabthermal-zone.  For example::
80eaf7b460SMauro Carvalho Chehab
81eaf7b460SMauro Carvalho Chehab	thermal-zones {
82eaf7b460SMauro Carvalho Chehab		soc_thermal {
83eaf7b460SMauro Carvalho Chehab			polling-delay = <1000>;
84eaf7b460SMauro Carvalho Chehab			polling-delay-passive = <100>;
85eaf7b460SMauro Carvalho Chehab			sustainable-power = <2500>;
86eaf7b460SMauro Carvalho Chehab			...
87eaf7b460SMauro Carvalho Chehab
88eaf7b460SMauro Carvalho ChehabInstead, if the thermal zone is registered from the platform code, pass a
89eaf7b460SMauro Carvalho Chehab`thermal_zone_params` that has a `sustainable_power`.  If no
90eaf7b460SMauro Carvalho Chehab`thermal_zone_params` were being passed, then something like below
91eaf7b460SMauro Carvalho Chehabwill suffice::
92eaf7b460SMauro Carvalho Chehab
93eaf7b460SMauro Carvalho Chehab	static const struct thermal_zone_params tz_params = {
94eaf7b460SMauro Carvalho Chehab		.sustainable_power = 3500,
95eaf7b460SMauro Carvalho Chehab	};
96eaf7b460SMauro Carvalho Chehab
97eaf7b460SMauro Carvalho Chehaband then pass `tz_params` as the 5th parameter to
98eaf7b460SMauro Carvalho Chehab`thermal_zone_device_register()`
99eaf7b460SMauro Carvalho Chehab
100eaf7b460SMauro Carvalho Chehabk_po and k_pu
101eaf7b460SMauro Carvalho Chehab-------------
102eaf7b460SMauro Carvalho Chehab
103eaf7b460SMauro Carvalho ChehabThe implementation of the PID controller in the power allocator
104eaf7b460SMauro Carvalho Chehabthermal governor allows the configuration of two proportional term
105eaf7b460SMauro Carvalho Chehabconstants: `k_po` and `k_pu`.  `k_po` is the proportional term
106eaf7b460SMauro Carvalho Chehabconstant during temperature overshoot periods (current temperature is
107eaf7b460SMauro Carvalho Chehababove "desired temperature" trip point).  Conversely, `k_pu` is the
108eaf7b460SMauro Carvalho Chehabproportional term constant during temperature undershoot periods
109eaf7b460SMauro Carvalho Chehab(current temperature below "desired temperature" trip point).
110eaf7b460SMauro Carvalho Chehab
111eaf7b460SMauro Carvalho ChehabThese controls are intended as the primary mechanism for configuring
112eaf7b460SMauro Carvalho Chehabthe permitted thermal "ramp" of the system.  For instance, a lower
113eaf7b460SMauro Carvalho Chehab`k_pu` value will provide a slower ramp, at the cost of capping
114eaf7b460SMauro Carvalho Chehabavailable capacity at a low temperature.  On the other hand, a high
115eaf7b460SMauro Carvalho Chehabvalue of `k_pu` will result in the governor granting very high power
116eaf7b460SMauro Carvalho Chehabwhile temperature is low, and may lead to temperature overshooting.
117eaf7b460SMauro Carvalho Chehab
118eaf7b460SMauro Carvalho ChehabThe default value for `k_pu` is::
119eaf7b460SMauro Carvalho Chehab
120eaf7b460SMauro Carvalho Chehab    2 * sustainable_power / (desired_temperature - switch_on_temp)
121eaf7b460SMauro Carvalho Chehab
122eaf7b460SMauro Carvalho ChehabThis means that at `switch_on_temp` the output of the controller's
123eaf7b460SMauro Carvalho Chehabproportional term will be 2 * `sustainable_power`.  The default value
124eaf7b460SMauro Carvalho Chehabfor `k_po` is::
125eaf7b460SMauro Carvalho Chehab
126eaf7b460SMauro Carvalho Chehab    sustainable_power / (desired_temperature - switch_on_temp)
127eaf7b460SMauro Carvalho Chehab
128eaf7b460SMauro Carvalho ChehabFocusing on the proportional and feed forward values of the PID
129eaf7b460SMauro Carvalho Chehabcontroller equation we have::
130eaf7b460SMauro Carvalho Chehab
131eaf7b460SMauro Carvalho Chehab    P_max = k_p * e + sustainable_power
132eaf7b460SMauro Carvalho Chehab
133eaf7b460SMauro Carvalho ChehabThe proportional term is proportional to the difference between the
134eaf7b460SMauro Carvalho Chehabdesired temperature and the current one.  When the current temperature
135eaf7b460SMauro Carvalho Chehabis the desired one, then the proportional component is zero and
136eaf7b460SMauro Carvalho Chehab`P_max` = `sustainable_power`.  That is, the system should operate in
137eaf7b460SMauro Carvalho Chehabthermal equilibrium under constant load.  `sustainable_power` is only
138eaf7b460SMauro Carvalho Chehaban estimate, which is the reason for closed-loop control such as this.
139eaf7b460SMauro Carvalho Chehab
140eaf7b460SMauro Carvalho ChehabExpanding `k_pu` we get::
141eaf7b460SMauro Carvalho Chehab
142eaf7b460SMauro Carvalho Chehab    P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) +
143eaf7b460SMauro Carvalho Chehab	sustainable_power
144eaf7b460SMauro Carvalho Chehab
145eaf7b460SMauro Carvalho Chehabwhere:
146eaf7b460SMauro Carvalho Chehab
147eaf7b460SMauro Carvalho Chehab    - T_set is the desired temperature
148eaf7b460SMauro Carvalho Chehab    - T is the current temperature
149eaf7b460SMauro Carvalho Chehab    - T_on is the switch on temperature
150eaf7b460SMauro Carvalho Chehab
151eaf7b460SMauro Carvalho ChehabWhen the current temperature is the switch_on temperature, the above
152eaf7b460SMauro Carvalho Chehabformula becomes::
153eaf7b460SMauro Carvalho Chehab
154eaf7b460SMauro Carvalho Chehab    P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) +
155eaf7b460SMauro Carvalho Chehab	sustainable_power = 2 * sustainable_power + sustainable_power =
156eaf7b460SMauro Carvalho Chehab	3 * sustainable_power
157eaf7b460SMauro Carvalho Chehab
158eaf7b460SMauro Carvalho ChehabTherefore, the proportional term alone linearly decreases power from
159eaf7b460SMauro Carvalho Chehab3 * `sustainable_power` to `sustainable_power` as the temperature
160eaf7b460SMauro Carvalho Chehabrises from the switch on temperature to the desired temperature.
161eaf7b460SMauro Carvalho Chehab
162eaf7b460SMauro Carvalho Chehabk_i and integral_cutoff
163eaf7b460SMauro Carvalho Chehab-----------------------
164eaf7b460SMauro Carvalho Chehab
165eaf7b460SMauro Carvalho Chehab`k_i` configures the PID loop's integral term constant.  This term
166eaf7b460SMauro Carvalho Chehaballows the PID controller to compensate for long term drift and for
167eaf7b460SMauro Carvalho Chehabthe quantized nature of the output control: cooling devices can't set
168eaf7b460SMauro Carvalho Chehabthe exact power that the governor requests.  When the temperature
169eaf7b460SMauro Carvalho Chehaberror is below `integral_cutoff`, errors are accumulated in the
170eaf7b460SMauro Carvalho Chehabintegral term.  This term is then multiplied by `k_i` and the result
171eaf7b460SMauro Carvalho Chehabadded to the output of the controller.  Typically `k_i` is set low (1
172eaf7b460SMauro Carvalho Chehabor 2) and `integral_cutoff` is 0.
173eaf7b460SMauro Carvalho Chehab
174eaf7b460SMauro Carvalho Chehabk_d
175eaf7b460SMauro Carvalho Chehab---
176eaf7b460SMauro Carvalho Chehab
177eaf7b460SMauro Carvalho Chehab`k_d` configures the PID loop's derivative term constant.  It's
178eaf7b460SMauro Carvalho Chehabrecommended to leave it as the default: 0.
179eaf7b460SMauro Carvalho Chehab
180eaf7b460SMauro Carvalho ChehabCooling device power API
181eaf7b460SMauro Carvalho Chehab========================
182eaf7b460SMauro Carvalho Chehab
183eaf7b460SMauro Carvalho ChehabCooling devices controlled by this governor must supply the additional
184eaf7b460SMauro Carvalho Chehab"power" API in their `cooling_device_ops`.  It consists on three ops:
185eaf7b460SMauro Carvalho Chehab
186eaf7b460SMauro Carvalho Chehab1. ::
187eaf7b460SMauro Carvalho Chehab
188eaf7b460SMauro Carvalho Chehab    int get_requested_power(struct thermal_cooling_device *cdev,
189eaf7b460SMauro Carvalho Chehab			    struct thermal_zone_device *tz, u32 *power);
190eaf7b460SMauro Carvalho Chehab
191eaf7b460SMauro Carvalho Chehab
192eaf7b460SMauro Carvalho Chehab@cdev:
193eaf7b460SMauro Carvalho Chehab	The `struct thermal_cooling_device` pointer
194eaf7b460SMauro Carvalho Chehab@tz:
195eaf7b460SMauro Carvalho Chehab	thermal zone in which we are currently operating
196eaf7b460SMauro Carvalho Chehab@power:
197eaf7b460SMauro Carvalho Chehab	pointer in which to store the calculated power
198eaf7b460SMauro Carvalho Chehab
199eaf7b460SMauro Carvalho Chehab`get_requested_power()` calculates the power requested by the device
200eaf7b460SMauro Carvalho Chehabin milliwatts and stores it in @power .  It should return 0 on
201eaf7b460SMauro Carvalho Chehabsuccess, -E* on failure.  This is currently used by the power
202eaf7b460SMauro Carvalho Chehaballocator governor to calculate how much power to give to each cooling
203eaf7b460SMauro Carvalho Chehabdevice.
204eaf7b460SMauro Carvalho Chehab
205eaf7b460SMauro Carvalho Chehab2. ::
206eaf7b460SMauro Carvalho Chehab
207eaf7b460SMauro Carvalho Chehab	int state2power(struct thermal_cooling_device *cdev, struct
208eaf7b460SMauro Carvalho Chehab			thermal_zone_device *tz, unsigned long state,
209eaf7b460SMauro Carvalho Chehab			u32 *power);
210eaf7b460SMauro Carvalho Chehab
211eaf7b460SMauro Carvalho Chehab@cdev:
212eaf7b460SMauro Carvalho Chehab	The `struct thermal_cooling_device` pointer
213eaf7b460SMauro Carvalho Chehab@tz:
214eaf7b460SMauro Carvalho Chehab	thermal zone in which we are currently operating
215eaf7b460SMauro Carvalho Chehab@state:
216eaf7b460SMauro Carvalho Chehab	A cooling device state
217eaf7b460SMauro Carvalho Chehab@power:
218eaf7b460SMauro Carvalho Chehab	pointer in which to store the equivalent power
219eaf7b460SMauro Carvalho Chehab
220eaf7b460SMauro Carvalho ChehabConvert cooling device state @state into power consumption in
221eaf7b460SMauro Carvalho Chehabmilliwatts and store it in @power.  It should return 0 on success, -E*
222eaf7b460SMauro Carvalho Chehabon failure.  This is currently used by thermal core to calculate the
223eaf7b460SMauro Carvalho Chehabmaximum power that an actor can consume.
224eaf7b460SMauro Carvalho Chehab
225eaf7b460SMauro Carvalho Chehab3. ::
226eaf7b460SMauro Carvalho Chehab
227eaf7b460SMauro Carvalho Chehab	int power2state(struct thermal_cooling_device *cdev, u32 power,
228eaf7b460SMauro Carvalho Chehab			unsigned long *state);
229eaf7b460SMauro Carvalho Chehab
230eaf7b460SMauro Carvalho Chehab@cdev:
231eaf7b460SMauro Carvalho Chehab	The `struct thermal_cooling_device` pointer
232eaf7b460SMauro Carvalho Chehab@power:
233eaf7b460SMauro Carvalho Chehab	power in milliwatts
234eaf7b460SMauro Carvalho Chehab@state:
235eaf7b460SMauro Carvalho Chehab	pointer in which to store the resulting state
236eaf7b460SMauro Carvalho Chehab
237eaf7b460SMauro Carvalho ChehabCalculate a cooling device state that would make the device consume at
238eaf7b460SMauro Carvalho Chehabmost @power mW and store it in @state.  It should return 0 on success,
239eaf7b460SMauro Carvalho Chehab-E* on failure.  This is currently used by the thermal core to convert
240eaf7b460SMauro Carvalho Chehaba given power set by the power allocator governor to a state that the
241eaf7b460SMauro Carvalho Chehabcooling device can set.  It is a function because this conversion may
242eaf7b460SMauro Carvalho Chehabdepend on external factors that may change so this function should the
243eaf7b460SMauro Carvalho Chehabbest conversion given "current circumstances".
244eaf7b460SMauro Carvalho Chehab
245eaf7b460SMauro Carvalho ChehabCooling device weights
246eaf7b460SMauro Carvalho Chehab----------------------
247eaf7b460SMauro Carvalho Chehab
248eaf7b460SMauro Carvalho ChehabWeights are a mechanism to bias the allocation among cooling
249eaf7b460SMauro Carvalho Chehabdevices.  They express the relative power efficiency of different
250eaf7b460SMauro Carvalho Chehabcooling devices.  Higher weight can be used to express higher power
251eaf7b460SMauro Carvalho Chehabefficiency.  Weighting is relative such that if each cooling device
252eaf7b460SMauro Carvalho Chehabhas a weight of one they are considered equal.  This is particularly
253eaf7b460SMauro Carvalho Chehabuseful in heterogeneous systems where two cooling devices may perform
254eaf7b460SMauro Carvalho Chehabthe same kind of compute, but with different efficiency.  For example,
255eaf7b460SMauro Carvalho Chehaba system with two different types of processors.
256eaf7b460SMauro Carvalho Chehab
257eaf7b460SMauro Carvalho ChehabIf the thermal zone is registered using
258eaf7b460SMauro Carvalho Chehab`thermal_zone_device_register()` (i.e., platform code), then weights
259eaf7b460SMauro Carvalho Chehabare passed as part of the thermal zone's `thermal_bind_parameters`.
260eaf7b460SMauro Carvalho ChehabIf the platform is registered using device tree, then they are passed
261eaf7b460SMauro Carvalho Chehabas the `contribution` property of each map in the `cooling-maps` node.
262eaf7b460SMauro Carvalho Chehab
263eaf7b460SMauro Carvalho ChehabLimitations of the power allocator governor
264eaf7b460SMauro Carvalho Chehab===========================================
265eaf7b460SMauro Carvalho Chehab
266eaf7b460SMauro Carvalho ChehabThe power allocator governor's PID controller works best if there is a
267eaf7b460SMauro Carvalho Chehabperiodic tick.  If you have a driver that calls
268eaf7b460SMauro Carvalho Chehab`thermal_zone_device_update()` (or anything that ends up calling the
269eaf7b460SMauro Carvalho Chehabgovernor's `throttle()` function) repetitively, the governor response
270eaf7b460SMauro Carvalho Chehabwon't be very good.  Note that this is not particular to this
271eaf7b460SMauro Carvalho Chehabgovernor, step-wise will also misbehave if you call its throttle()
272eaf7b460SMauro Carvalho Chehabfaster than the normal thermal framework tick (due to interrupts for
273eaf7b460SMauro Carvalho Chehabexample) as it will overreact.
274*5a64f775SLukasz Luba
275*5a64f775SLukasz LubaEnergy Model requirements
276*5a64f775SLukasz Luba=========================
277*5a64f775SLukasz Luba
278*5a64f775SLukasz LubaAnother important thing is the consistent scale of the power values
279*5a64f775SLukasz Lubaprovided by the cooling devices. All of the cooling devices in a single
280*5a64f775SLukasz Lubathermal zone should have power values reported either in milli-Watts
281*5a64f775SLukasz Lubaor scaled to the same 'abstract scale'.
282