1*4882a593Smuzhiyun================================= 2*4882a593SmuzhiyunPower allocator governor tunables 3*4882a593Smuzhiyun================================= 4*4882a593Smuzhiyun 5*4882a593SmuzhiyunTrip points 6*4882a593Smuzhiyun----------- 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunThe governor works optimally with the following two passive trip points: 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun1. "switch on" trip point: temperature above which the governor 11*4882a593Smuzhiyun control loop starts operating. This is the first passive trip 12*4882a593Smuzhiyun point of the thermal zone. 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun2. "desired temperature" trip point: it should be higher than the 15*4882a593Smuzhiyun "switch on" trip point. This the target temperature the governor 16*4882a593Smuzhiyun is controlling for. This is the last passive trip point of the 17*4882a593Smuzhiyun thermal zone. 18*4882a593Smuzhiyun 19*4882a593SmuzhiyunPID Controller 20*4882a593Smuzhiyun-------------- 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunThe power allocator governor implements a 23*4882a593SmuzhiyunProportional-Integral-Derivative controller (PID controller) with 24*4882a593Smuzhiyuntemperature as the control input and power as the controlled output: 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power 27*4882a593Smuzhiyun 28*4882a593Smuzhiyunwhere 29*4882a593Smuzhiyun - e = desired_temperature - current_temperature 30*4882a593Smuzhiyun - err_integral is the sum of previous errors 31*4882a593Smuzhiyun - diff_err = e - previous_error 32*4882a593Smuzhiyun 33*4882a593SmuzhiyunIt is similar to the one depicted below:: 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun k_d 36*4882a593Smuzhiyun | 37*4882a593Smuzhiyun current_temp | 38*4882a593Smuzhiyun | v 39*4882a593Smuzhiyun | +----------+ +---+ 40*4882a593Smuzhiyun | +----->| diff_err |-->| X |------+ 41*4882a593Smuzhiyun | | +----------+ +---+ | 42*4882a593Smuzhiyun | | | tdp actor 43*4882a593Smuzhiyun | | k_i | | get_requested_power() 44*4882a593Smuzhiyun | | | | | | | 45*4882a593Smuzhiyun | | | | | | | ... 46*4882a593Smuzhiyun v | v v v v v 47*4882a593Smuzhiyun +---+ | +-------+ +---+ +---+ +---+ +----------+ 48*4882a593Smuzhiyun | S |-----+----->| sum e |----->| X |--->| S |-->| S |-->|power | 49*4882a593Smuzhiyun +---+ | +-------+ +---+ +---+ +---+ |allocation| 50*4882a593Smuzhiyun ^ | ^ +----------+ 51*4882a593Smuzhiyun | | | | | 52*4882a593Smuzhiyun | | +---+ | | | 53*4882a593Smuzhiyun | +------->| X |-------------------+ v v 54*4882a593Smuzhiyun | +---+ granted performance 55*4882a593Smuzhiyun desired_temperature ^ 56*4882a593Smuzhiyun | 57*4882a593Smuzhiyun | 58*4882a593Smuzhiyun k_po/k_pu 59*4882a593Smuzhiyun 60*4882a593SmuzhiyunSustainable power 61*4882a593Smuzhiyun----------------- 62*4882a593Smuzhiyun 63*4882a593SmuzhiyunAn estimate of the sustainable dissipatable power (in mW) should be 64*4882a593Smuzhiyunprovided while registering the thermal zone. This estimates the 65*4882a593Smuzhiyunsustained power that can be dissipated at the desired control 66*4882a593Smuzhiyuntemperature. This is the maximum sustained power for allocation at 67*4882a593Smuzhiyunthe desired maximum temperature. The actual sustained power can vary 68*4882a593Smuzhiyunfor a number of reasons. The closed loop controller will take care of 69*4882a593Smuzhiyunvariations such as environmental conditions, and some factors related 70*4882a593Smuzhiyunto the speed-grade of the silicon. `sustainable_power` is therefore 71*4882a593Smuzhiyunsimply an estimate, and may be tuned to affect the aggressiveness of 72*4882a593Smuzhiyunthe thermal ramp. For reference, the sustainable power of a 4" phone 73*4882a593Smuzhiyunis typically 2000mW, while on a 10" tablet is around 4500mW (may vary 74*4882a593Smuzhiyundepending on screen size). 75*4882a593Smuzhiyun 76*4882a593SmuzhiyunIf you are using device tree, do add it as a property of the 77*4882a593Smuzhiyunthermal-zone. For example:: 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun thermal-zones { 80*4882a593Smuzhiyun soc_thermal { 81*4882a593Smuzhiyun polling-delay = <1000>; 82*4882a593Smuzhiyun polling-delay-passive = <100>; 83*4882a593Smuzhiyun sustainable-power = <2500>; 84*4882a593Smuzhiyun ... 85*4882a593Smuzhiyun 86*4882a593SmuzhiyunInstead, if the thermal zone is registered from the platform code, pass a 87*4882a593Smuzhiyun`thermal_zone_params` that has a `sustainable_power`. If no 88*4882a593Smuzhiyun`thermal_zone_params` were being passed, then something like below 89*4882a593Smuzhiyunwill suffice:: 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun static const struct thermal_zone_params tz_params = { 92*4882a593Smuzhiyun .sustainable_power = 3500, 93*4882a593Smuzhiyun }; 94*4882a593Smuzhiyun 95*4882a593Smuzhiyunand then pass `tz_params` as the 5th parameter to 96*4882a593Smuzhiyun`thermal_zone_device_register()` 97*4882a593Smuzhiyun 98*4882a593Smuzhiyunk_po and k_pu 99*4882a593Smuzhiyun------------- 100*4882a593Smuzhiyun 101*4882a593SmuzhiyunThe implementation of the PID controller in the power allocator 102*4882a593Smuzhiyunthermal governor allows the configuration of two proportional term 103*4882a593Smuzhiyunconstants: `k_po` and `k_pu`. `k_po` is the proportional term 104*4882a593Smuzhiyunconstant during temperature overshoot periods (current temperature is 105*4882a593Smuzhiyunabove "desired temperature" trip point). Conversely, `k_pu` is the 106*4882a593Smuzhiyunproportional term constant during temperature undershoot periods 107*4882a593Smuzhiyun(current temperature below "desired temperature" trip point). 108*4882a593Smuzhiyun 109*4882a593SmuzhiyunThese controls are intended as the primary mechanism for configuring 110*4882a593Smuzhiyunthe permitted thermal "ramp" of the system. For instance, a lower 111*4882a593Smuzhiyun`k_pu` value will provide a slower ramp, at the cost of capping 112*4882a593Smuzhiyunavailable capacity at a low temperature. On the other hand, a high 113*4882a593Smuzhiyunvalue of `k_pu` will result in the governor granting very high power 114*4882a593Smuzhiyunwhile temperature is low, and may lead to temperature overshooting. 115*4882a593Smuzhiyun 116*4882a593SmuzhiyunThe default value for `k_pu` is:: 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun 2 * sustainable_power / (desired_temperature - switch_on_temp) 119*4882a593Smuzhiyun 120*4882a593SmuzhiyunThis means that at `switch_on_temp` the output of the controller's 121*4882a593Smuzhiyunproportional term will be 2 * `sustainable_power`. The default value 122*4882a593Smuzhiyunfor `k_po` is:: 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun sustainable_power / (desired_temperature - switch_on_temp) 125*4882a593Smuzhiyun 126*4882a593SmuzhiyunFocusing on the proportional and feed forward values of the PID 127*4882a593Smuzhiyuncontroller equation we have:: 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun P_max = k_p * e + sustainable_power 130*4882a593Smuzhiyun 131*4882a593SmuzhiyunThe proportional term is proportional to the difference between the 132*4882a593Smuzhiyundesired temperature and the current one. When the current temperature 133*4882a593Smuzhiyunis the desired one, then the proportional component is zero and 134*4882a593Smuzhiyun`P_max` = `sustainable_power`. That is, the system should operate in 135*4882a593Smuzhiyunthermal equilibrium under constant load. `sustainable_power` is only 136*4882a593Smuzhiyunan estimate, which is the reason for closed-loop control such as this. 137*4882a593Smuzhiyun 138*4882a593SmuzhiyunExpanding `k_pu` we get:: 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) + 141*4882a593Smuzhiyun sustainable_power 142*4882a593Smuzhiyun 143*4882a593Smuzhiyunwhere: 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun - T_set is the desired temperature 146*4882a593Smuzhiyun - T is the current temperature 147*4882a593Smuzhiyun - T_on is the switch on temperature 148*4882a593Smuzhiyun 149*4882a593SmuzhiyunWhen the current temperature is the switch_on temperature, the above 150*4882a593Smuzhiyunformula becomes:: 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) + 153*4882a593Smuzhiyun sustainable_power = 2 * sustainable_power + sustainable_power = 154*4882a593Smuzhiyun 3 * sustainable_power 155*4882a593Smuzhiyun 156*4882a593SmuzhiyunTherefore, the proportional term alone linearly decreases power from 157*4882a593Smuzhiyun3 * `sustainable_power` to `sustainable_power` as the temperature 158*4882a593Smuzhiyunrises from the switch on temperature to the desired temperature. 159*4882a593Smuzhiyun 160*4882a593Smuzhiyunk_i and integral_cutoff 161*4882a593Smuzhiyun----------------------- 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun`k_i` configures the PID loop's integral term constant. This term 164*4882a593Smuzhiyunallows the PID controller to compensate for long term drift and for 165*4882a593Smuzhiyunthe quantized nature of the output control: cooling devices can't set 166*4882a593Smuzhiyunthe exact power that the governor requests. When the temperature 167*4882a593Smuzhiyunerror is below `integral_cutoff`, errors are accumulated in the 168*4882a593Smuzhiyunintegral term. This term is then multiplied by `k_i` and the result 169*4882a593Smuzhiyunadded to the output of the controller. Typically `k_i` is set low (1 170*4882a593Smuzhiyunor 2) and `integral_cutoff` is 0. 171*4882a593Smuzhiyun 172*4882a593Smuzhiyunk_d 173*4882a593Smuzhiyun--- 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun`k_d` configures the PID loop's derivative term constant. It's 176*4882a593Smuzhiyunrecommended to leave it as the default: 0. 177*4882a593Smuzhiyun 178*4882a593SmuzhiyunCooling device power API 179*4882a593Smuzhiyun======================== 180*4882a593Smuzhiyun 181*4882a593SmuzhiyunCooling devices controlled by this governor must supply the additional 182*4882a593Smuzhiyun"power" API in their `cooling_device_ops`. It consists on three ops: 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun1. :: 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun int get_requested_power(struct thermal_cooling_device *cdev, 187*4882a593Smuzhiyun struct thermal_zone_device *tz, u32 *power); 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun@cdev: 191*4882a593Smuzhiyun The `struct thermal_cooling_device` pointer 192*4882a593Smuzhiyun@tz: 193*4882a593Smuzhiyun thermal zone in which we are currently operating 194*4882a593Smuzhiyun@power: 195*4882a593Smuzhiyun pointer in which to store the calculated power 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun`get_requested_power()` calculates the power requested by the device 198*4882a593Smuzhiyunin milliwatts and stores it in @power . It should return 0 on 199*4882a593Smuzhiyunsuccess, -E* on failure. This is currently used by the power 200*4882a593Smuzhiyunallocator governor to calculate how much power to give to each cooling 201*4882a593Smuzhiyundevice. 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun2. :: 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun int state2power(struct thermal_cooling_device *cdev, struct 206*4882a593Smuzhiyun thermal_zone_device *tz, unsigned long state, 207*4882a593Smuzhiyun u32 *power); 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun@cdev: 210*4882a593Smuzhiyun The `struct thermal_cooling_device` pointer 211*4882a593Smuzhiyun@tz: 212*4882a593Smuzhiyun thermal zone in which we are currently operating 213*4882a593Smuzhiyun@state: 214*4882a593Smuzhiyun A cooling device state 215*4882a593Smuzhiyun@power: 216*4882a593Smuzhiyun pointer in which to store the equivalent power 217*4882a593Smuzhiyun 218*4882a593SmuzhiyunConvert cooling device state @state into power consumption in 219*4882a593Smuzhiyunmilliwatts and store it in @power. It should return 0 on success, -E* 220*4882a593Smuzhiyunon failure. This is currently used by thermal core to calculate the 221*4882a593Smuzhiyunmaximum power that an actor can consume. 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun3. :: 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun int power2state(struct thermal_cooling_device *cdev, u32 power, 226*4882a593Smuzhiyun unsigned long *state); 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun@cdev: 229*4882a593Smuzhiyun The `struct thermal_cooling_device` pointer 230*4882a593Smuzhiyun@power: 231*4882a593Smuzhiyun power in milliwatts 232*4882a593Smuzhiyun@state: 233*4882a593Smuzhiyun pointer in which to store the resulting state 234*4882a593Smuzhiyun 235*4882a593SmuzhiyunCalculate a cooling device state that would make the device consume at 236*4882a593Smuzhiyunmost @power mW and store it in @state. It should return 0 on success, 237*4882a593Smuzhiyun-E* on failure. This is currently used by the thermal core to convert 238*4882a593Smuzhiyuna given power set by the power allocator governor to a state that the 239*4882a593Smuzhiyuncooling device can set. It is a function because this conversion may 240*4882a593Smuzhiyundepend on external factors that may change so this function should the 241*4882a593Smuzhiyunbest conversion given "current circumstances". 242*4882a593Smuzhiyun 243*4882a593SmuzhiyunCooling device weights 244*4882a593Smuzhiyun---------------------- 245*4882a593Smuzhiyun 246*4882a593SmuzhiyunWeights are a mechanism to bias the allocation among cooling 247*4882a593Smuzhiyundevices. They express the relative power efficiency of different 248*4882a593Smuzhiyuncooling devices. Higher weight can be used to express higher power 249*4882a593Smuzhiyunefficiency. Weighting is relative such that if each cooling device 250*4882a593Smuzhiyunhas a weight of one they are considered equal. This is particularly 251*4882a593Smuzhiyunuseful in heterogeneous systems where two cooling devices may perform 252*4882a593Smuzhiyunthe same kind of compute, but with different efficiency. For example, 253*4882a593Smuzhiyuna system with two different types of processors. 254*4882a593Smuzhiyun 255*4882a593SmuzhiyunIf the thermal zone is registered using 256*4882a593Smuzhiyun`thermal_zone_device_register()` (i.e., platform code), then weights 257*4882a593Smuzhiyunare passed as part of the thermal zone's `thermal_bind_parameters`. 258*4882a593SmuzhiyunIf the platform is registered using device tree, then they are passed 259*4882a593Smuzhiyunas the `contribution` property of each map in the `cooling-maps` node. 260*4882a593Smuzhiyun 261*4882a593SmuzhiyunLimitations of the power allocator governor 262*4882a593Smuzhiyun=========================================== 263*4882a593Smuzhiyun 264*4882a593SmuzhiyunThe power allocator governor's PID controller works best if there is a 265*4882a593Smuzhiyunperiodic tick. If you have a driver that calls 266*4882a593Smuzhiyun`thermal_zone_device_update()` (or anything that ends up calling the 267*4882a593Smuzhiyungovernor's `throttle()` function) repetitively, the governor response 268*4882a593Smuzhiyunwon't be very good. Note that this is not particular to this 269*4882a593Smuzhiyungovernor, step-wise will also misbehave if you call its throttle() 270*4882a593Smuzhiyunfaster than the normal thermal framework tick (due to interrupts for 271*4882a593Smuzhiyunexample) as it will overreact. 272