1========================================== 2Operating Performance Points (OPP) Library 3========================================== 4 5(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated 6 7.. Contents 8 9 1. Introduction 10 2. Initial OPP List Registration 11 3. OPP Search Functions 12 4. OPP Availability Control Functions 13 5. OPP Data Retrieval Functions 14 6. Data Structures 15 161. Introduction 17=============== 18 191.1 What is an Operating Performance Point (OPP)? 20------------------------------------------------- 21 22Complex SoCs of today consists of a multiple sub-modules working in conjunction. 23In an operational system executing varied use cases, not all modules in the SoC 24need to function at their highest performing frequency all the time. To 25facilitate this, sub-modules in a SoC are grouped into domains, allowing some 26domains to run at lower voltage and frequency while other domains run at 27voltage/frequency pairs that are higher. 28 29The set of discrete tuples consisting of frequency and voltage pairs that 30the device will support per domain are called Operating Performance Points or 31OPPs. 32 33As an example: 34 35Let us consider an MPU device which supports the following: 36{300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V}, 37{1GHz at minimum voltage of 1.3V} 38 39We can represent these as three OPPs as the following {Hz, uV} tuples: 40 41- {300000000, 1000000} 42- {800000000, 1200000} 43- {1000000000, 1300000} 44 451.2 Operating Performance Points Library 46---------------------------------------- 47 48OPP library provides a set of helper functions to organize and query the OPP 49information. The library is located in drivers/opp/ directory and the header 50is located in include/linux/pm_opp.h. OPP library can be enabled by enabling 51CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on 52CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to 53optionally boot at a certain OPP without needing cpufreq. 54 55Typical usage of the OPP library is as follows:: 56 57 (users) -> registers a set of default OPPs -> (library) 58 SoC framework -> modifies on required cases certain OPPs -> OPP layer 59 -> queries to search/retrieve information -> 60 61OPP layer expects each domain to be represented by a unique device pointer. SoC 62framework registers a set of initial OPPs per device with the OPP layer. This 63list is expected to be an optimally small number typically around 5 per device. 64This initial list contains a set of OPPs that the framework expects to be safely 65enabled by default in the system. 66 67Note on OPP Availability 68^^^^^^^^^^^^^^^^^^^^^^^^ 69 70As the system proceeds to operate, SoC framework may choose to make certain 71OPPs available or not available on each device based on various external 72factors. Example usage: Thermal management or other exceptional situations where 73SoC framework might choose to disable a higher frequency OPP to safely continue 74operations until that OPP could be re-enabled if possible. 75 76OPP library facilitates this concept in its implementation. The following 77operational functions operate only on available opps: 78opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, 79dev_pm_opp_get_opp_count 80 81dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer 82which can then be used for dev_pm_opp_enable/disable functions to make an 83opp available as required. 84 85WARNING: Users of OPP library should refresh their availability count using 86get_opp_count if dev_pm_opp_enable/disable functions are invoked for a 87device, the exact mechanism to trigger these or the notification mechanism 88to other dependent subsystems such as cpufreq are left to the discretion of 89the SoC specific framework which uses the OPP library. Similar care needs 90to be taken care to refresh the cpufreq table in cases of these operations. 91 922. Initial OPP List Registration 93================================ 94The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per 95device. It is expected that the SoC framework will register the OPP entries 96optimally- typical numbers range to be less than 5. The list generated by 97registering the OPPs is maintained by OPP library throughout the device 98operation. The SoC framework can subsequently control the availability of the 99OPPs dynamically using the dev_pm_opp_enable / disable functions. 100 101dev_pm_opp_add 102 Add a new OPP for a specific domain represented by the device pointer. 103 The OPP is defined using the frequency and voltage. Once added, the OPP 104 is assumed to be available and control of its availability can be done 105 with the dev_pm_opp_enable/disable functions. OPP library 106 internally stores and manages this information in the opp struct. 107 This function may be used by SoC framework to define a optimal list 108 as per the demands of SoC usage environment. 109 110 WARNING: 111 Do not use this function in interrupt context. 112 113 Example:: 114 115 soc_pm_init() 116 { 117 /* Do things */ 118 r = dev_pm_opp_add(mpu_dev, 1000000, 900000); 119 if (!r) { 120 pr_err("%s: unable to register mpu opp(%d)\n", r); 121 goto no_cpufreq; 122 } 123 /* Do cpufreq things */ 124 no_cpufreq: 125 /* Do remaining things */ 126 } 127 1283. OPP Search Functions 129======================= 130High level framework such as cpufreq operates on frequencies. To map the 131frequency back to the corresponding OPP, OPP library provides handy functions 132to search the OPP list that OPP library internally manages. These search 133functions return the matching pointer representing the opp if a match is 134found, else returns error. These errors are expected to be handled by standard 135error checks such as IS_ERR() and appropriate actions taken by the caller. 136 137Callers of these functions shall call dev_pm_opp_put() after they have used the 138OPP. Otherwise the memory for the OPP will never get freed and result in 139memleak. 140 141dev_pm_opp_find_freq_exact 142 Search for an OPP based on an *exact* frequency and 143 availability. This function is especially useful to enable an OPP which 144 is not available by default. 145 Example: In a case when SoC framework detects a situation where a 146 higher frequency could be made available, it can use this function to 147 find the OPP prior to call the dev_pm_opp_enable to actually make 148 it available:: 149 150 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 151 dev_pm_opp_put(opp); 152 /* dont operate on the pointer.. just do a sanity check.. */ 153 if (IS_ERR(opp)) { 154 pr_err("frequency not disabled!\n"); 155 /* trigger appropriate actions.. */ 156 } else { 157 dev_pm_opp_enable(dev,1000000000); 158 } 159 160 NOTE: 161 This is the only search function that operates on OPPs which are 162 not available. 163 164dev_pm_opp_find_freq_floor 165 Search for an available OPP which is *at most* the 166 provided frequency. This function is useful while searching for a lesser 167 match OR operating on OPP information in the order of decreasing 168 frequency. 169 Example: To find the highest opp for a device:: 170 171 freq = ULONG_MAX; 172 opp = dev_pm_opp_find_freq_floor(dev, &freq); 173 dev_pm_opp_put(opp); 174 175dev_pm_opp_find_freq_ceil 176 Search for an available OPP which is *at least* the 177 provided frequency. This function is useful while searching for a 178 higher match OR operating on OPP information in the order of increasing 179 frequency. 180 Example 1: To find the lowest opp for a device:: 181 182 freq = 0; 183 opp = dev_pm_opp_find_freq_ceil(dev, &freq); 184 dev_pm_opp_put(opp); 185 186 Example 2: A simplified implementation of a SoC cpufreq_driver->target:: 187 188 soc_cpufreq_target(..) 189 { 190 /* Do stuff like policy checks etc. */ 191 /* Find the best frequency match for the req */ 192 opp = dev_pm_opp_find_freq_ceil(dev, &freq); 193 dev_pm_opp_put(opp); 194 if (!IS_ERR(opp)) 195 soc_switch_to_freq_voltage(freq); 196 else 197 /* do something when we can't satisfy the req */ 198 /* do other stuff */ 199 } 200 2014. OPP Availability Control Functions 202===================================== 203A default OPP list registered with the OPP library may not cater to all possible 204situation. The OPP library provides a set of functions to modify the 205availability of a OPP within the OPP list. This allows SoC frameworks to have 206fine grained dynamic control of which sets of OPPs are operationally available. 207These functions are intended to *temporarily* remove an OPP in conditions such 208as thermal considerations (e.g. don't use OPPx until the temperature drops). 209 210WARNING: 211 Do not use these functions in interrupt context. 212 213dev_pm_opp_enable 214 Make a OPP available for operation. 215 Example: Lets say that 1GHz OPP is to be made available only if the 216 SoC temperature is lower than a certain threshold. The SoC framework 217 implementation might choose to do something as follows:: 218 219 if (cur_temp < temp_low_thresh) { 220 /* Enable 1GHz if it was disabled */ 221 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 222 dev_pm_opp_put(opp); 223 /* just error check */ 224 if (!IS_ERR(opp)) 225 ret = dev_pm_opp_enable(dev, 1000000000); 226 else 227 goto try_something_else; 228 } 229 230dev_pm_opp_disable 231 Make an OPP to be not available for operation 232 Example: Lets say that 1GHz OPP is to be disabled if the temperature 233 exceeds a threshold value. The SoC framework implementation might 234 choose to do something as follows:: 235 236 if (cur_temp > temp_high_thresh) { 237 /* Disable 1GHz if it was enabled */ 238 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); 239 dev_pm_opp_put(opp); 240 /* just error check */ 241 if (!IS_ERR(opp)) 242 ret = dev_pm_opp_disable(dev, 1000000000); 243 else 244 goto try_something_else; 245 } 246 2475. OPP Data Retrieval Functions 248=============================== 249Since OPP library abstracts away the OPP information, a set of functions to pull 250information from the OPP structure is necessary. Once an OPP pointer is 251retrieved using the search functions, the following functions can be used by SoC 252framework to retrieve the information represented inside the OPP layer. 253 254dev_pm_opp_get_voltage 255 Retrieve the voltage represented by the opp pointer. 256 Example: At a cpufreq transition to a different frequency, SoC 257 framework requires to set the voltage represented by the OPP using 258 the regulator framework to the Power Management chip providing the 259 voltage:: 260 261 soc_switch_to_freq_voltage(freq) 262 { 263 /* do things */ 264 opp = dev_pm_opp_find_freq_ceil(dev, &freq); 265 v = dev_pm_opp_get_voltage(opp); 266 dev_pm_opp_put(opp); 267 if (v) 268 regulator_set_voltage(.., v); 269 /* do other things */ 270 } 271 272dev_pm_opp_get_freq 273 Retrieve the freq represented by the opp pointer. 274 Example: Lets say the SoC framework uses a couple of helper functions 275 we could pass opp pointers instead of doing additional parameters to 276 handle quiet a bit of data parameters:: 277 278 soc_cpufreq_target(..) 279 { 280 /* do things.. */ 281 max_freq = ULONG_MAX; 282 max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); 283 requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); 284 if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) 285 r = soc_test_validity(max_opp, requested_opp); 286 dev_pm_opp_put(max_opp); 287 dev_pm_opp_put(requested_opp); 288 /* do other things */ 289 } 290 soc_test_validity(..) 291 { 292 if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) 293 return -EINVAL; 294 if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) 295 return -EINVAL; 296 /* do things.. */ 297 } 298 299dev_pm_opp_get_opp_count 300 Retrieve the number of available opps for a device 301 Example: Lets say a co-processor in the SoC needs to know the available 302 frequencies in a table, the main processor can notify as following:: 303 304 soc_notify_coproc_available_frequencies() 305 { 306 /* Do things */ 307 num_available = dev_pm_opp_get_opp_count(dev); 308 speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); 309 /* populate the table in increasing order */ 310 freq = 0; 311 while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { 312 speeds[i] = freq; 313 freq++; 314 i++; 315 dev_pm_opp_put(opp); 316 } 317 318 soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); 319 /* Do other things */ 320 } 321 3226. Data Structures 323================== 324Typically an SoC contains multiple voltage domains which are variable. Each 325domain is represented by a device pointer. The relationship to OPP can be 326represented as follows:: 327 328 SoC 329 |- device 1 330 | |- opp 1 (availability, freq, voltage) 331 | |- opp 2 .. 332 ... ... 333 | `- opp n .. 334 |- device 2 335 ... 336 `- device m 337 338OPP library maintains a internal list that the SoC framework populates and 339accessed by various functions as described above. However, the structures 340representing the actual OPPs and domains are internal to the OPP library itself 341to allow for suitable abstraction reusable across systems. 342 343struct dev_pm_opp 344 The internal data structure of OPP library which is used to 345 represent an OPP. In addition to the freq, voltage, availability 346 information, it also contains internal book keeping information required 347 for the OPP library to operate on. Pointer to this structure is 348 provided back to the users such as SoC framework to be used as a 349 identifier for OPP in the interactions with OPP layer. 350 351 WARNING: 352 The struct dev_pm_opp pointer should not be parsed or modified by the 353 users. The defaults of for an instance is populated by 354 dev_pm_opp_add, but the availability of the OPP can be modified 355 by dev_pm_opp_enable/disable functions. 356 357struct device 358 This is used to identify a domain to the OPP layer. The 359 nature of the device and its implementation is left to the user of 360 OPP library such as the SoC framework. 361 362Overall, in a simplistic view, the data structure operations is represented as 363following:: 364 365 Initialization / modification: 366 +-----+ /- dev_pm_opp_enable 367 dev_pm_opp_add --> | opp | <------- 368 | +-----+ \- dev_pm_opp_disable 369 \-------> domain_info(device) 370 371 Search functions: 372 /-- dev_pm_opp_find_freq_ceil ---\ +-----+ 373 domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | 374 \-- dev_pm_opp_find_freq_floor ---/ +-----+ 375 376 Retrieval functions: 377 +-----+ /- dev_pm_opp_get_voltage 378 | opp | <--- 379 +-----+ \- dev_pm_opp_get_freq 380 381 domain_info <- dev_pm_opp_get_opp_count 382