1151f4e2bSMauro Carvalho Chehab========================================== 2151f4e2bSMauro Carvalho ChehabOperating Performance Points (OPP) Library 3151f4e2bSMauro Carvalho Chehab========================================== 4151f4e2bSMauro Carvalho Chehab 5151f4e2bSMauro Carvalho Chehab(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated 6151f4e2bSMauro Carvalho Chehab 7151f4e2bSMauro Carvalho Chehab.. Contents 8151f4e2bSMauro Carvalho Chehab 9151f4e2bSMauro Carvalho Chehab 1. Introduction 10151f4e2bSMauro Carvalho Chehab 2. Initial OPP List Registration 11151f4e2bSMauro Carvalho Chehab 3. OPP Search Functions 12151f4e2bSMauro Carvalho Chehab 4. OPP Availability Control Functions 13151f4e2bSMauro Carvalho Chehab 5. OPP Data Retrieval Functions 14151f4e2bSMauro Carvalho Chehab 6. Data Structures 15151f4e2bSMauro Carvalho Chehab 16151f4e2bSMauro Carvalho Chehab1. Introduction 17151f4e2bSMauro Carvalho Chehab=============== 18151f4e2bSMauro Carvalho Chehab 19151f4e2bSMauro Carvalho Chehab1.1 What is an Operating Performance Point (OPP)? 20151f4e2bSMauro Carvalho Chehab------------------------------------------------- 21151f4e2bSMauro Carvalho Chehab 22151f4e2bSMauro Carvalho ChehabComplex SoCs of today consists of a multiple sub-modules working in conjunction. 23151f4e2bSMauro Carvalho ChehabIn an operational system executing varied use cases, not all modules in the SoC 24151f4e2bSMauro Carvalho Chehabneed to function at their highest performing frequency all the time. To 25151f4e2bSMauro Carvalho Chehabfacilitate this, sub-modules in a SoC are grouped into domains, allowing some 26151f4e2bSMauro Carvalho Chehabdomains to run at lower voltage and frequency while other domains run at 27151f4e2bSMauro Carvalho Chehabvoltage/frequency pairs that are higher. 28151f4e2bSMauro Carvalho Chehab 29151f4e2bSMauro Carvalho ChehabThe set of discrete tuples consisting of frequency and voltage pairs that 30151f4e2bSMauro Carvalho Chehabthe device will support per domain are called Operating Performance Points or 31151f4e2bSMauro Carvalho ChehabOPPs. 32151f4e2bSMauro Carvalho Chehab 33151f4e2bSMauro Carvalho ChehabAs an example: 34151f4e2bSMauro Carvalho Chehab 35151f4e2bSMauro Carvalho ChehabLet us consider an MPU device which supports the following: 36151f4e2bSMauro Carvalho Chehab{300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V}, 37151f4e2bSMauro Carvalho Chehab{1GHz at minimum voltage of 1.3V} 38151f4e2bSMauro Carvalho Chehab 39151f4e2bSMauro Carvalho ChehabWe can represent these as three OPPs as the following {Hz, uV} tuples: 40151f4e2bSMauro Carvalho Chehab 41151f4e2bSMauro Carvalho Chehab- {300000000, 1000000} 42151f4e2bSMauro Carvalho Chehab- {800000000, 1200000} 43151f4e2bSMauro Carvalho Chehab- {1000000000, 1300000} 44151f4e2bSMauro Carvalho Chehab 45151f4e2bSMauro Carvalho Chehab1.2 Operating Performance Points Library 46151f4e2bSMauro Carvalho Chehab---------------------------------------- 47151f4e2bSMauro Carvalho Chehab 48151f4e2bSMauro Carvalho ChehabOPP library provides a set of helper functions to organize and query the OPP 49*27a84f76SYue Huinformation. The library is located in drivers/opp/ directory and the header 50151f4e2bSMauro Carvalho Chehabis located in include/linux/pm_opp.h. OPP library can be enabled by enabling 51151f4e2bSMauro Carvalho ChehabCONFIG_PM_OPP from power management menuconfig menu. OPP library depends on 52151f4e2bSMauro Carvalho ChehabCONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to 53151f4e2bSMauro Carvalho Chehaboptionally boot at a certain OPP without needing cpufreq. 54151f4e2bSMauro Carvalho Chehab 55151f4e2bSMauro Carvalho ChehabTypical usage of the OPP library is as follows:: 56151f4e2bSMauro Carvalho Chehab 57151f4e2bSMauro Carvalho Chehab (users) -> registers a set of default OPPs -> (library) 58151f4e2bSMauro Carvalho Chehab SoC framework -> modifies on required cases certain OPPs -> OPP layer 59151f4e2bSMauro Carvalho Chehab -> queries to search/retrieve information -> 60151f4e2bSMauro Carvalho Chehab 61151f4e2bSMauro Carvalho ChehabOPP layer expects each domain to be represented by a unique device pointer. SoC 62151f4e2bSMauro Carvalho Chehabframework registers a set of initial OPPs per device with the OPP layer. This 63151f4e2bSMauro Carvalho Chehablist is expected to be an optimally small number typically around 5 per device. 64151f4e2bSMauro Carvalho ChehabThis initial list contains a set of OPPs that the framework expects to be safely 65151f4e2bSMauro Carvalho Chehabenabled by default in the system. 66151f4e2bSMauro Carvalho Chehab 67151f4e2bSMauro Carvalho ChehabNote on OPP Availability 68151f4e2bSMauro Carvalho Chehab^^^^^^^^^^^^^^^^^^^^^^^^ 69151f4e2bSMauro Carvalho Chehab 70151f4e2bSMauro Carvalho ChehabAs the system proceeds to operate, SoC framework may choose to make certain 71151f4e2bSMauro Carvalho ChehabOPPs available or not available on each device based on various external 72151f4e2bSMauro Carvalho Chehabfactors. Example usage: Thermal management or other exceptional situations where 73151f4e2bSMauro Carvalho ChehabSoC framework might choose to disable a higher frequency OPP to safely continue 74151f4e2bSMauro Carvalho Chehaboperations until that OPP could be re-enabled if possible. 75151f4e2bSMauro Carvalho Chehab 76151f4e2bSMauro Carvalho ChehabOPP library facilitates this concept in it's implementation. The following 77151f4e2bSMauro Carvalho Chehaboperational functions operate only on available opps: 78151f4e2bSMauro Carvalho Chehabopp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count 79151f4e2bSMauro Carvalho Chehab 80151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then 81151f4e2bSMauro Carvalho Chehabbe used for dev_pm_opp_enable/disable functions to make an opp available as required. 82151f4e2bSMauro Carvalho Chehab 83151f4e2bSMauro Carvalho ChehabWARNING: Users of OPP library should refresh their availability count using 84151f4e2bSMauro Carvalho Chehabget_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the 85151f4e2bSMauro Carvalho Chehabexact mechanism to trigger these or the notification mechanism to other 86151f4e2bSMauro Carvalho Chehabdependent subsystems such as cpufreq are left to the discretion of the SoC 87151f4e2bSMauro Carvalho Chehabspecific framework which uses the OPP library. Similar care needs to be taken 88151f4e2bSMauro Carvalho Chehabcare to refresh the cpufreq table in cases of these operations. 89151f4e2bSMauro Carvalho Chehab 90151f4e2bSMauro Carvalho Chehab2. Initial OPP List Registration 91151f4e2bSMauro Carvalho Chehab================================ 92151f4e2bSMauro Carvalho ChehabThe SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per 93151f4e2bSMauro Carvalho Chehabdevice. It is expected that the SoC framework will register the OPP entries 94151f4e2bSMauro Carvalho Chehaboptimally- typical numbers range to be less than 5. The list generated by 95151f4e2bSMauro Carvalho Chehabregistering the OPPs is maintained by OPP library throughout the device 96151f4e2bSMauro Carvalho Chehaboperation. The SoC framework can subsequently control the availability of the 97151f4e2bSMauro Carvalho ChehabOPPs dynamically using the dev_pm_opp_enable / disable functions. 98151f4e2bSMauro Carvalho Chehab 99151f4e2bSMauro Carvalho Chehabdev_pm_opp_add 100151f4e2bSMauro Carvalho Chehab Add a new OPP for a specific domain represented by the device pointer. 101151f4e2bSMauro Carvalho Chehab The OPP is defined using the frequency and voltage. Once added, the OPP 102151f4e2bSMauro Carvalho Chehab is assumed to be available and control of it's availability can be done 103151f4e2bSMauro Carvalho Chehab with the dev_pm_opp_enable/disable functions. OPP library internally stores 104151f4e2bSMauro Carvalho Chehab and manages this information in the opp struct. This function may be 105151f4e2bSMauro Carvalho Chehab used by SoC framework to define a optimal list as per the demands of 106151f4e2bSMauro Carvalho Chehab SoC usage environment. 107151f4e2bSMauro Carvalho Chehab 108151f4e2bSMauro Carvalho Chehab WARNING: 109151f4e2bSMauro Carvalho Chehab Do not use this function in interrupt context. 110151f4e2bSMauro Carvalho Chehab 111151f4e2bSMauro Carvalho Chehab Example:: 112151f4e2bSMauro Carvalho Chehab 113151f4e2bSMauro Carvalho Chehab soc_pm_init() 114151f4e2bSMauro Carvalho Chehab { 115151f4e2bSMauro Carvalho Chehab /* Do things */ 116151f4e2bSMauro Carvalho Chehab r = dev_pm_opp_add(mpu_dev, 1000000, 900000); 117151f4e2bSMauro Carvalho Chehab if (!r) { 118151f4e2bSMauro Carvalho Chehab pr_err("%s: unable to register mpu opp(%d)\n", r); 119151f4e2bSMauro Carvalho Chehab goto no_cpufreq; 120151f4e2bSMauro Carvalho Chehab } 121151f4e2bSMauro Carvalho Chehab /* Do cpufreq things */ 122151f4e2bSMauro Carvalho Chehab no_cpufreq: 123151f4e2bSMauro Carvalho Chehab /* Do remaining things */ 124151f4e2bSMauro Carvalho Chehab } 125151f4e2bSMauro Carvalho Chehab 126151f4e2bSMauro Carvalho Chehab3. OPP Search Functions 127151f4e2bSMauro Carvalho Chehab======================= 128151f4e2bSMauro Carvalho ChehabHigh level framework such as cpufreq operates on frequencies. To map the 129151f4e2bSMauro Carvalho Chehabfrequency back to the corresponding OPP, OPP library provides handy functions 130151f4e2bSMauro Carvalho Chehabto search the OPP list that OPP library internally manages. These search 131151f4e2bSMauro Carvalho Chehabfunctions return the matching pointer representing the opp if a match is 132151f4e2bSMauro Carvalho Chehabfound, else returns error. These errors are expected to be handled by standard 133151f4e2bSMauro Carvalho Chehaberror checks such as IS_ERR() and appropriate actions taken by the caller. 134151f4e2bSMauro Carvalho Chehab 135151f4e2bSMauro Carvalho ChehabCallers of these functions shall call dev_pm_opp_put() after they have used the 136151f4e2bSMauro Carvalho ChehabOPP. Otherwise the memory for the OPP will never get freed and result in 137151f4e2bSMauro Carvalho Chehabmemleak. 138151f4e2bSMauro Carvalho Chehab 139151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_exact 140151f4e2bSMauro Carvalho Chehab Search for an OPP based on an *exact* frequency and 141151f4e2bSMauro Carvalho Chehab availability. This function is especially useful to enable an OPP which 142151f4e2bSMauro Carvalho Chehab is not available by default. 143151f4e2bSMauro Carvalho Chehab Example: In a case when SoC framework detects a situation where a 144151f4e2bSMauro Carvalho Chehab higher frequency could be made available, it can use this function to 145151f4e2bSMauro Carvalho Chehab find the OPP prior to call the dev_pm_opp_enable to actually make 146151f4e2bSMauro Carvalho Chehab it available:: 147151f4e2bSMauro Carvalho Chehab 148151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 149151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 150151f4e2bSMauro Carvalho Chehab /* dont operate on the pointer.. just do a sanity check.. */ 151151f4e2bSMauro Carvalho Chehab if (IS_ERR(opp)) { 152151f4e2bSMauro Carvalho Chehab pr_err("frequency not disabled!\n"); 153151f4e2bSMauro Carvalho Chehab /* trigger appropriate actions.. */ 154151f4e2bSMauro Carvalho Chehab } else { 155151f4e2bSMauro Carvalho Chehab dev_pm_opp_enable(dev,1000000000); 156151f4e2bSMauro Carvalho Chehab } 157151f4e2bSMauro Carvalho Chehab 158151f4e2bSMauro Carvalho Chehab NOTE: 159151f4e2bSMauro Carvalho Chehab This is the only search function that operates on OPPs which are 160151f4e2bSMauro Carvalho Chehab not available. 161151f4e2bSMauro Carvalho Chehab 162151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_floor 163151f4e2bSMauro Carvalho Chehab Search for an available OPP which is *at most* the 164151f4e2bSMauro Carvalho Chehab provided frequency. This function is useful while searching for a lesser 165151f4e2bSMauro Carvalho Chehab match OR operating on OPP information in the order of decreasing 166151f4e2bSMauro Carvalho Chehab frequency. 167151f4e2bSMauro Carvalho Chehab Example: To find the highest opp for a device:: 168151f4e2bSMauro Carvalho Chehab 169151f4e2bSMauro Carvalho Chehab freq = ULONG_MAX; 170151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_floor(dev, &freq); 171151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 172151f4e2bSMauro Carvalho Chehab 173151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_ceil 174151f4e2bSMauro Carvalho Chehab Search for an available OPP which is *at least* the 175151f4e2bSMauro Carvalho Chehab provided frequency. This function is useful while searching for a 176151f4e2bSMauro Carvalho Chehab higher match OR operating on OPP information in the order of increasing 177151f4e2bSMauro Carvalho Chehab frequency. 178151f4e2bSMauro Carvalho Chehab Example 1: To find the lowest opp for a device:: 179151f4e2bSMauro Carvalho Chehab 180151f4e2bSMauro Carvalho Chehab freq = 0; 181151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_ceil(dev, &freq); 182151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 183151f4e2bSMauro Carvalho Chehab 184151f4e2bSMauro Carvalho Chehab Example 2: A simplified implementation of a SoC cpufreq_driver->target:: 185151f4e2bSMauro Carvalho Chehab 186151f4e2bSMauro Carvalho Chehab soc_cpufreq_target(..) 187151f4e2bSMauro Carvalho Chehab { 188151f4e2bSMauro Carvalho Chehab /* Do stuff like policy checks etc. */ 189151f4e2bSMauro Carvalho Chehab /* Find the best frequency match for the req */ 190151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_ceil(dev, &freq); 191151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 192151f4e2bSMauro Carvalho Chehab if (!IS_ERR(opp)) 193151f4e2bSMauro Carvalho Chehab soc_switch_to_freq_voltage(freq); 194151f4e2bSMauro Carvalho Chehab else 195151f4e2bSMauro Carvalho Chehab /* do something when we can't satisfy the req */ 196151f4e2bSMauro Carvalho Chehab /* do other stuff */ 197151f4e2bSMauro Carvalho Chehab } 198151f4e2bSMauro Carvalho Chehab 199151f4e2bSMauro Carvalho Chehab4. OPP Availability Control Functions 200151f4e2bSMauro Carvalho Chehab===================================== 201151f4e2bSMauro Carvalho ChehabA default OPP list registered with the OPP library may not cater to all possible 202151f4e2bSMauro Carvalho Chehabsituation. The OPP library provides a set of functions to modify the 203151f4e2bSMauro Carvalho Chehabavailability of a OPP within the OPP list. This allows SoC frameworks to have 204151f4e2bSMauro Carvalho Chehabfine grained dynamic control of which sets of OPPs are operationally available. 205151f4e2bSMauro Carvalho ChehabThese functions are intended to *temporarily* remove an OPP in conditions such 206151f4e2bSMauro Carvalho Chehabas thermal considerations (e.g. don't use OPPx until the temperature drops). 207151f4e2bSMauro Carvalho Chehab 208151f4e2bSMauro Carvalho ChehabWARNING: 209151f4e2bSMauro Carvalho Chehab Do not use these functions in interrupt context. 210151f4e2bSMauro Carvalho Chehab 211151f4e2bSMauro Carvalho Chehabdev_pm_opp_enable 212151f4e2bSMauro Carvalho Chehab Make a OPP available for operation. 213151f4e2bSMauro Carvalho Chehab Example: Lets say that 1GHz OPP is to be made available only if the 214151f4e2bSMauro Carvalho Chehab SoC temperature is lower than a certain threshold. The SoC framework 215151f4e2bSMauro Carvalho Chehab implementation might choose to do something as follows:: 216151f4e2bSMauro Carvalho Chehab 217151f4e2bSMauro Carvalho Chehab if (cur_temp < temp_low_thresh) { 218151f4e2bSMauro Carvalho Chehab /* Enable 1GHz if it was disabled */ 219151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 220151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 221151f4e2bSMauro Carvalho Chehab /* just error check */ 222151f4e2bSMauro Carvalho Chehab if (!IS_ERR(opp)) 223151f4e2bSMauro Carvalho Chehab ret = dev_pm_opp_enable(dev, 1000000000); 224151f4e2bSMauro Carvalho Chehab else 225151f4e2bSMauro Carvalho Chehab goto try_something_else; 226151f4e2bSMauro Carvalho Chehab } 227151f4e2bSMauro Carvalho Chehab 228151f4e2bSMauro Carvalho Chehabdev_pm_opp_disable 229151f4e2bSMauro Carvalho Chehab Make an OPP to be not available for operation 230151f4e2bSMauro Carvalho Chehab Example: Lets say that 1GHz OPP is to be disabled if the temperature 231151f4e2bSMauro Carvalho Chehab exceeds a threshold value. The SoC framework implementation might 232151f4e2bSMauro Carvalho Chehab choose to do something as follows:: 233151f4e2bSMauro Carvalho Chehab 234151f4e2bSMauro Carvalho Chehab if (cur_temp > temp_high_thresh) { 235151f4e2bSMauro Carvalho Chehab /* Disable 1GHz if it was enabled */ 236151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); 237151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 238151f4e2bSMauro Carvalho Chehab /* just error check */ 239151f4e2bSMauro Carvalho Chehab if (!IS_ERR(opp)) 240151f4e2bSMauro Carvalho Chehab ret = dev_pm_opp_disable(dev, 1000000000); 241151f4e2bSMauro Carvalho Chehab else 242151f4e2bSMauro Carvalho Chehab goto try_something_else; 243151f4e2bSMauro Carvalho Chehab } 244151f4e2bSMauro Carvalho Chehab 245151f4e2bSMauro Carvalho Chehab5. OPP Data Retrieval Functions 246151f4e2bSMauro Carvalho Chehab=============================== 247151f4e2bSMauro Carvalho ChehabSince OPP library abstracts away the OPP information, a set of functions to pull 248151f4e2bSMauro Carvalho Chehabinformation from the OPP structure is necessary. Once an OPP pointer is 249151f4e2bSMauro Carvalho Chehabretrieved using the search functions, the following functions can be used by SoC 250151f4e2bSMauro Carvalho Chehabframework to retrieve the information represented inside the OPP layer. 251151f4e2bSMauro Carvalho Chehab 252151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_voltage 253151f4e2bSMauro Carvalho Chehab Retrieve the voltage represented by the opp pointer. 254151f4e2bSMauro Carvalho Chehab Example: At a cpufreq transition to a different frequency, SoC 255151f4e2bSMauro Carvalho Chehab framework requires to set the voltage represented by the OPP using 256151f4e2bSMauro Carvalho Chehab the regulator framework to the Power Management chip providing the 257151f4e2bSMauro Carvalho Chehab voltage:: 258151f4e2bSMauro Carvalho Chehab 259151f4e2bSMauro Carvalho Chehab soc_switch_to_freq_voltage(freq) 260151f4e2bSMauro Carvalho Chehab { 261151f4e2bSMauro Carvalho Chehab /* do things */ 262151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_ceil(dev, &freq); 263151f4e2bSMauro Carvalho Chehab v = dev_pm_opp_get_voltage(opp); 264151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 265151f4e2bSMauro Carvalho Chehab if (v) 266151f4e2bSMauro Carvalho Chehab regulator_set_voltage(.., v); 267151f4e2bSMauro Carvalho Chehab /* do other things */ 268151f4e2bSMauro Carvalho Chehab } 269151f4e2bSMauro Carvalho Chehab 270151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_freq 271151f4e2bSMauro Carvalho Chehab Retrieve the freq represented by the opp pointer. 272151f4e2bSMauro Carvalho Chehab Example: Lets say the SoC framework uses a couple of helper functions 273151f4e2bSMauro Carvalho Chehab we could pass opp pointers instead of doing additional parameters to 274151f4e2bSMauro Carvalho Chehab handle quiet a bit of data parameters:: 275151f4e2bSMauro Carvalho Chehab 276151f4e2bSMauro Carvalho Chehab soc_cpufreq_target(..) 277151f4e2bSMauro Carvalho Chehab { 278151f4e2bSMauro Carvalho Chehab /* do things.. */ 279151f4e2bSMauro Carvalho Chehab max_freq = ULONG_MAX; 280151f4e2bSMauro Carvalho Chehab max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); 281151f4e2bSMauro Carvalho Chehab requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); 282151f4e2bSMauro Carvalho Chehab if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) 283151f4e2bSMauro Carvalho Chehab r = soc_test_validity(max_opp, requested_opp); 284151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(max_opp); 285151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(requested_opp); 286151f4e2bSMauro Carvalho Chehab /* do other things */ 287151f4e2bSMauro Carvalho Chehab } 288151f4e2bSMauro Carvalho Chehab soc_test_validity(..) 289151f4e2bSMauro Carvalho Chehab { 290151f4e2bSMauro Carvalho Chehab if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) 291151f4e2bSMauro Carvalho Chehab return -EINVAL; 292151f4e2bSMauro Carvalho Chehab if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) 293151f4e2bSMauro Carvalho Chehab return -EINVAL; 294151f4e2bSMauro Carvalho Chehab /* do things.. */ 295151f4e2bSMauro Carvalho Chehab } 296151f4e2bSMauro Carvalho Chehab 297151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_opp_count 298151f4e2bSMauro Carvalho Chehab Retrieve the number of available opps for a device 299151f4e2bSMauro Carvalho Chehab Example: Lets say a co-processor in the SoC needs to know the available 300151f4e2bSMauro Carvalho Chehab frequencies in a table, the main processor can notify as following:: 301151f4e2bSMauro Carvalho Chehab 302151f4e2bSMauro Carvalho Chehab soc_notify_coproc_available_frequencies() 303151f4e2bSMauro Carvalho Chehab { 304151f4e2bSMauro Carvalho Chehab /* Do things */ 305151f4e2bSMauro Carvalho Chehab num_available = dev_pm_opp_get_opp_count(dev); 306151f4e2bSMauro Carvalho Chehab speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); 307151f4e2bSMauro Carvalho Chehab /* populate the table in increasing order */ 308151f4e2bSMauro Carvalho Chehab freq = 0; 309151f4e2bSMauro Carvalho Chehab while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { 310151f4e2bSMauro Carvalho Chehab speeds[i] = freq; 311151f4e2bSMauro Carvalho Chehab freq++; 312151f4e2bSMauro Carvalho Chehab i++; 313151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 314151f4e2bSMauro Carvalho Chehab } 315151f4e2bSMauro Carvalho Chehab 316151f4e2bSMauro Carvalho Chehab soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); 317151f4e2bSMauro Carvalho Chehab /* Do other things */ 318151f4e2bSMauro Carvalho Chehab } 319151f4e2bSMauro Carvalho Chehab 320151f4e2bSMauro Carvalho Chehab6. Data Structures 321151f4e2bSMauro Carvalho Chehab================== 322151f4e2bSMauro Carvalho ChehabTypically an SoC contains multiple voltage domains which are variable. Each 323151f4e2bSMauro Carvalho Chehabdomain is represented by a device pointer. The relationship to OPP can be 324151f4e2bSMauro Carvalho Chehabrepresented as follows:: 325151f4e2bSMauro Carvalho Chehab 326151f4e2bSMauro Carvalho Chehab SoC 327151f4e2bSMauro Carvalho Chehab |- device 1 328151f4e2bSMauro Carvalho Chehab | |- opp 1 (availability, freq, voltage) 329151f4e2bSMauro Carvalho Chehab | |- opp 2 .. 330151f4e2bSMauro Carvalho Chehab ... ... 331151f4e2bSMauro Carvalho Chehab | `- opp n .. 332151f4e2bSMauro Carvalho Chehab |- device 2 333151f4e2bSMauro Carvalho Chehab ... 334151f4e2bSMauro Carvalho Chehab `- device m 335151f4e2bSMauro Carvalho Chehab 336151f4e2bSMauro Carvalho ChehabOPP library maintains a internal list that the SoC framework populates and 337151f4e2bSMauro Carvalho Chehabaccessed by various functions as described above. However, the structures 338151f4e2bSMauro Carvalho Chehabrepresenting the actual OPPs and domains are internal to the OPP library itself 339151f4e2bSMauro Carvalho Chehabto allow for suitable abstraction reusable across systems. 340151f4e2bSMauro Carvalho Chehab 341151f4e2bSMauro Carvalho Chehabstruct dev_pm_opp 342151f4e2bSMauro Carvalho Chehab The internal data structure of OPP library which is used to 343151f4e2bSMauro Carvalho Chehab represent an OPP. In addition to the freq, voltage, availability 344151f4e2bSMauro Carvalho Chehab information, it also contains internal book keeping information required 345151f4e2bSMauro Carvalho Chehab for the OPP library to operate on. Pointer to this structure is 346151f4e2bSMauro Carvalho Chehab provided back to the users such as SoC framework to be used as a 347151f4e2bSMauro Carvalho Chehab identifier for OPP in the interactions with OPP layer. 348151f4e2bSMauro Carvalho Chehab 349151f4e2bSMauro Carvalho Chehab WARNING: 350151f4e2bSMauro Carvalho Chehab The struct dev_pm_opp pointer should not be parsed or modified by the 351151f4e2bSMauro Carvalho Chehab users. The defaults of for an instance is populated by 352151f4e2bSMauro Carvalho Chehab dev_pm_opp_add, but the availability of the OPP can be modified 353151f4e2bSMauro Carvalho Chehab by dev_pm_opp_enable/disable functions. 354151f4e2bSMauro Carvalho Chehab 355151f4e2bSMauro Carvalho Chehabstruct device 356151f4e2bSMauro Carvalho Chehab This is used to identify a domain to the OPP layer. The 357151f4e2bSMauro Carvalho Chehab nature of the device and it's implementation is left to the user of 358151f4e2bSMauro Carvalho Chehab OPP library such as the SoC framework. 359151f4e2bSMauro Carvalho Chehab 360151f4e2bSMauro Carvalho ChehabOverall, in a simplistic view, the data structure operations is represented as 361151f4e2bSMauro Carvalho Chehabfollowing:: 362151f4e2bSMauro Carvalho Chehab 363151f4e2bSMauro Carvalho Chehab Initialization / modification: 364151f4e2bSMauro Carvalho Chehab +-----+ /- dev_pm_opp_enable 365151f4e2bSMauro Carvalho Chehab dev_pm_opp_add --> | opp | <------- 366151f4e2bSMauro Carvalho Chehab | +-----+ \- dev_pm_opp_disable 367151f4e2bSMauro Carvalho Chehab \-------> domain_info(device) 368151f4e2bSMauro Carvalho Chehab 369151f4e2bSMauro Carvalho Chehab Search functions: 370151f4e2bSMauro Carvalho Chehab /-- dev_pm_opp_find_freq_ceil ---\ +-----+ 371151f4e2bSMauro Carvalho Chehab domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | 372151f4e2bSMauro Carvalho Chehab \-- dev_pm_opp_find_freq_floor ---/ +-----+ 373151f4e2bSMauro Carvalho Chehab 374151f4e2bSMauro Carvalho Chehab Retrieval functions: 375151f4e2bSMauro Carvalho Chehab +-----+ /- dev_pm_opp_get_voltage 376151f4e2bSMauro Carvalho Chehab | opp | <--- 377151f4e2bSMauro Carvalho Chehab +-----+ \- dev_pm_opp_get_freq 378151f4e2bSMauro Carvalho Chehab 379151f4e2bSMauro Carvalho Chehab domain_info <- dev_pm_opp_get_opp_count 380