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 it's 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, dev_pm_opp_get_opp_count 79 80dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then 81be used for dev_pm_opp_enable/disable functions to make an opp available as required. 82 83WARNING: Users of OPP library should refresh their availability count using 84get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the 85exact mechanism to trigger these or the notification mechanism to other 86dependent subsystems such as cpufreq are left to the discretion of the SoC 87specific framework which uses the OPP library. Similar care needs to be taken 88care to refresh the cpufreq table in cases of these operations. 89 902. Initial OPP List Registration 91================================ 92The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per 93device. It is expected that the SoC framework will register the OPP entries 94optimally- typical numbers range to be less than 5. The list generated by 95registering the OPPs is maintained by OPP library throughout the device 96operation. The SoC framework can subsequently control the availability of the 97OPPs dynamically using the dev_pm_opp_enable / disable functions. 98 99dev_pm_opp_add 100 Add a new OPP for a specific domain represented by the device pointer. 101 The OPP is defined using the frequency and voltage. Once added, the OPP 102 is assumed to be available and control of it's availability can be done 103 with the dev_pm_opp_enable/disable functions. OPP library internally stores 104 and manages this information in the opp struct. This function may be 105 used by SoC framework to define a optimal list as per the demands of 106 SoC usage environment. 107 108 WARNING: 109 Do not use this function in interrupt context. 110 111 Example:: 112 113 soc_pm_init() 114 { 115 /* Do things */ 116 r = dev_pm_opp_add(mpu_dev, 1000000, 900000); 117 if (!r) { 118 pr_err("%s: unable to register mpu opp(%d)\n", r); 119 goto no_cpufreq; 120 } 121 /* Do cpufreq things */ 122 no_cpufreq: 123 /* Do remaining things */ 124 } 125 1263. OPP Search Functions 127======================= 128High level framework such as cpufreq operates on frequencies. To map the 129frequency back to the corresponding OPP, OPP library provides handy functions 130to search the OPP list that OPP library internally manages. These search 131functions return the matching pointer representing the opp if a match is 132found, else returns error. These errors are expected to be handled by standard 133error checks such as IS_ERR() and appropriate actions taken by the caller. 134 135Callers of these functions shall call dev_pm_opp_put() after they have used the 136OPP. Otherwise the memory for the OPP will never get freed and result in 137memleak. 138 139dev_pm_opp_find_freq_exact 140 Search for an OPP based on an *exact* frequency and 141 availability. This function is especially useful to enable an OPP which 142 is not available by default. 143 Example: In a case when SoC framework detects a situation where a 144 higher frequency could be made available, it can use this function to 145 find the OPP prior to call the dev_pm_opp_enable to actually make 146 it available:: 147 148 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 149 dev_pm_opp_put(opp); 150 /* dont operate on the pointer.. just do a sanity check.. */ 151 if (IS_ERR(opp)) { 152 pr_err("frequency not disabled!\n"); 153 /* trigger appropriate actions.. */ 154 } else { 155 dev_pm_opp_enable(dev,1000000000); 156 } 157 158 NOTE: 159 This is the only search function that operates on OPPs which are 160 not available. 161 162dev_pm_opp_find_freq_floor 163 Search for an available OPP which is *at most* the 164 provided frequency. This function is useful while searching for a lesser 165 match OR operating on OPP information in the order of decreasing 166 frequency. 167 Example: To find the highest opp for a device:: 168 169 freq = ULONG_MAX; 170 opp = dev_pm_opp_find_freq_floor(dev, &freq); 171 dev_pm_opp_put(opp); 172 173dev_pm_opp_find_freq_ceil 174 Search for an available OPP which is *at least* the 175 provided frequency. This function is useful while searching for a 176 higher match OR operating on OPP information in the order of increasing 177 frequency. 178 Example 1: To find the lowest opp for a device:: 179 180 freq = 0; 181 opp = dev_pm_opp_find_freq_ceil(dev, &freq); 182 dev_pm_opp_put(opp); 183 184 Example 2: A simplified implementation of a SoC cpufreq_driver->target:: 185 186 soc_cpufreq_target(..) 187 { 188 /* Do stuff like policy checks etc. */ 189 /* Find the best frequency match for the req */ 190 opp = dev_pm_opp_find_freq_ceil(dev, &freq); 191 dev_pm_opp_put(opp); 192 if (!IS_ERR(opp)) 193 soc_switch_to_freq_voltage(freq); 194 else 195 /* do something when we can't satisfy the req */ 196 /* do other stuff */ 197 } 198 1994. OPP Availability Control Functions 200===================================== 201A default OPP list registered with the OPP library may not cater to all possible 202situation. The OPP library provides a set of functions to modify the 203availability of a OPP within the OPP list. This allows SoC frameworks to have 204fine grained dynamic control of which sets of OPPs are operationally available. 205These functions are intended to *temporarily* remove an OPP in conditions such 206as thermal considerations (e.g. don't use OPPx until the temperature drops). 207 208WARNING: 209 Do not use these functions in interrupt context. 210 211dev_pm_opp_enable 212 Make a OPP available for operation. 213 Example: Lets say that 1GHz OPP is to be made available only if the 214 SoC temperature is lower than a certain threshold. The SoC framework 215 implementation might choose to do something as follows:: 216 217 if (cur_temp < temp_low_thresh) { 218 /* Enable 1GHz if it was disabled */ 219 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 220 dev_pm_opp_put(opp); 221 /* just error check */ 222 if (!IS_ERR(opp)) 223 ret = dev_pm_opp_enable(dev, 1000000000); 224 else 225 goto try_something_else; 226 } 227 228dev_pm_opp_disable 229 Make an OPP to be not available for operation 230 Example: Lets say that 1GHz OPP is to be disabled if the temperature 231 exceeds a threshold value. The SoC framework implementation might 232 choose to do something as follows:: 233 234 if (cur_temp > temp_high_thresh) { 235 /* Disable 1GHz if it was enabled */ 236 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); 237 dev_pm_opp_put(opp); 238 /* just error check */ 239 if (!IS_ERR(opp)) 240 ret = dev_pm_opp_disable(dev, 1000000000); 241 else 242 goto try_something_else; 243 } 244 2455. OPP Data Retrieval Functions 246=============================== 247Since OPP library abstracts away the OPP information, a set of functions to pull 248information from the OPP structure is necessary. Once an OPP pointer is 249retrieved using the search functions, the following functions can be used by SoC 250framework to retrieve the information represented inside the OPP layer. 251 252dev_pm_opp_get_voltage 253 Retrieve the voltage represented by the opp pointer. 254 Example: At a cpufreq transition to a different frequency, SoC 255 framework requires to set the voltage represented by the OPP using 256 the regulator framework to the Power Management chip providing the 257 voltage:: 258 259 soc_switch_to_freq_voltage(freq) 260 { 261 /* do things */ 262 opp = dev_pm_opp_find_freq_ceil(dev, &freq); 263 v = dev_pm_opp_get_voltage(opp); 264 dev_pm_opp_put(opp); 265 if (v) 266 regulator_set_voltage(.., v); 267 /* do other things */ 268 } 269 270dev_pm_opp_get_freq 271 Retrieve the freq represented by the opp pointer. 272 Example: Lets say the SoC framework uses a couple of helper functions 273 we could pass opp pointers instead of doing additional parameters to 274 handle quiet a bit of data parameters:: 275 276 soc_cpufreq_target(..) 277 { 278 /* do things.. */ 279 max_freq = ULONG_MAX; 280 max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); 281 requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); 282 if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) 283 r = soc_test_validity(max_opp, requested_opp); 284 dev_pm_opp_put(max_opp); 285 dev_pm_opp_put(requested_opp); 286 /* do other things */ 287 } 288 soc_test_validity(..) 289 { 290 if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) 291 return -EINVAL; 292 if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) 293 return -EINVAL; 294 /* do things.. */ 295 } 296 297dev_pm_opp_get_opp_count 298 Retrieve the number of available opps for a device 299 Example: Lets say a co-processor in the SoC needs to know the available 300 frequencies in a table, the main processor can notify as following:: 301 302 soc_notify_coproc_available_frequencies() 303 { 304 /* Do things */ 305 num_available = dev_pm_opp_get_opp_count(dev); 306 speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); 307 /* populate the table in increasing order */ 308 freq = 0; 309 while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { 310 speeds[i] = freq; 311 freq++; 312 i++; 313 dev_pm_opp_put(opp); 314 } 315 316 soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); 317 /* Do other things */ 318 } 319 3206. Data Structures 321================== 322Typically an SoC contains multiple voltage domains which are variable. Each 323domain is represented by a device pointer. The relationship to OPP can be 324represented as follows:: 325 326 SoC 327 |- device 1 328 | |- opp 1 (availability, freq, voltage) 329 | |- opp 2 .. 330 ... ... 331 | `- opp n .. 332 |- device 2 333 ... 334 `- device m 335 336OPP library maintains a internal list that the SoC framework populates and 337accessed by various functions as described above. However, the structures 338representing the actual OPPs and domains are internal to the OPP library itself 339to allow for suitable abstraction reusable across systems. 340 341struct dev_pm_opp 342 The internal data structure of OPP library which is used to 343 represent an OPP. In addition to the freq, voltage, availability 344 information, it also contains internal book keeping information required 345 for the OPP library to operate on. Pointer to this structure is 346 provided back to the users such as SoC framework to be used as a 347 identifier for OPP in the interactions with OPP layer. 348 349 WARNING: 350 The struct dev_pm_opp pointer should not be parsed or modified by the 351 users. The defaults of for an instance is populated by 352 dev_pm_opp_add, but the availability of the OPP can be modified 353 by dev_pm_opp_enable/disable functions. 354 355struct device 356 This is used to identify a domain to the OPP layer. The 357 nature of the device and it's implementation is left to the user of 358 OPP library such as the SoC framework. 359 360Overall, in a simplistic view, the data structure operations is represented as 361following:: 362 363 Initialization / modification: 364 +-----+ /- dev_pm_opp_enable 365 dev_pm_opp_add --> | opp | <------- 366 | +-----+ \- dev_pm_opp_disable 367 \-------> domain_info(device) 368 369 Search functions: 370 /-- dev_pm_opp_find_freq_ceil ---\ +-----+ 371 domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | 372 \-- dev_pm_opp_find_freq_floor ---/ +-----+ 373 374 Retrieval functions: 375 +-----+ /- dev_pm_opp_get_voltage 376 | opp | <--- 377 +-----+ \- dev_pm_opp_get_freq 378 379 domain_info <- dev_pm_opp_get_opp_count 380