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 4927a84f76SYue 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 51489a00efSTang YizhouCONFIG_PM_OPP from power management menuconfig menu. Certain SoCs such as Texas 52489a00efSTang YizhouInstrument's OMAP framework allows to optionally boot at a certain OPP without 53489a00efSTang Yizhouneeding 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 761992b66dSBjorn HelgaasOPP library facilitates this concept in its implementation. The following 77151f4e2bSMauro Carvalho Chehaboperational functions operate only on available opps: 78489a00efSTang Yizhoudev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, 79489a00efSTang Yizhoudev_pm_opp_get_opp_count. 80151f4e2bSMauro Carvalho Chehab 811992b66dSBjorn Helgaasdev_pm_opp_find_freq_exact is meant to be used to find the opp pointer 821992b66dSBjorn Helgaaswhich can then be used for dev_pm_opp_enable/disable functions to make an 831992b66dSBjorn Helgaasopp available as required. 84151f4e2bSMauro Carvalho Chehab 85151f4e2bSMauro Carvalho ChehabWARNING: Users of OPP library should refresh their availability count using 861992b66dSBjorn Helgaasget_opp_count if dev_pm_opp_enable/disable functions are invoked for a 871992b66dSBjorn Helgaasdevice, the exact mechanism to trigger these or the notification mechanism 881992b66dSBjorn Helgaasto other dependent subsystems such as cpufreq are left to the discretion of 891992b66dSBjorn Helgaasthe SoC specific framework which uses the OPP library. Similar care needs 901992b66dSBjorn Helgaasto be taken care to refresh the cpufreq table in cases of these operations. 91151f4e2bSMauro Carvalho Chehab 92151f4e2bSMauro Carvalho Chehab2. Initial OPP List Registration 93151f4e2bSMauro Carvalho Chehab================================ 94151f4e2bSMauro Carvalho ChehabThe SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per 95151f4e2bSMauro Carvalho Chehabdevice. It is expected that the SoC framework will register the OPP entries 96151f4e2bSMauro Carvalho Chehaboptimally- typical numbers range to be less than 5. The list generated by 97151f4e2bSMauro Carvalho Chehabregistering the OPPs is maintained by OPP library throughout the device 98151f4e2bSMauro Carvalho Chehaboperation. The SoC framework can subsequently control the availability of the 99151f4e2bSMauro Carvalho ChehabOPPs dynamically using the dev_pm_opp_enable / disable functions. 100151f4e2bSMauro Carvalho Chehab 101151f4e2bSMauro Carvalho Chehabdev_pm_opp_add 102151f4e2bSMauro Carvalho Chehab Add a new OPP for a specific domain represented by the device pointer. 103151f4e2bSMauro Carvalho Chehab The OPP is defined using the frequency and voltage. Once added, the OPP 1041992b66dSBjorn Helgaas is assumed to be available and control of its availability can be done 1051992b66dSBjorn Helgaas with the dev_pm_opp_enable/disable functions. OPP library 106489a00efSTang Yizhou internally stores and manages this information in the dev_pm_opp struct. 1071992b66dSBjorn Helgaas This function may be used by SoC framework to define a optimal list 1081992b66dSBjorn Helgaas as per the demands of SoC usage environment. 109151f4e2bSMauro Carvalho Chehab 110151f4e2bSMauro Carvalho Chehab WARNING: 111151f4e2bSMauro Carvalho Chehab Do not use this function in interrupt context. 112151f4e2bSMauro Carvalho Chehab 113151f4e2bSMauro Carvalho Chehab Example:: 114151f4e2bSMauro Carvalho Chehab 115151f4e2bSMauro Carvalho Chehab soc_pm_init() 116151f4e2bSMauro Carvalho Chehab { 117151f4e2bSMauro Carvalho Chehab /* Do things */ 118151f4e2bSMauro Carvalho Chehab r = dev_pm_opp_add(mpu_dev, 1000000, 900000); 119151f4e2bSMauro Carvalho Chehab if (!r) { 120151f4e2bSMauro Carvalho Chehab pr_err("%s: unable to register mpu opp(%d)\n", r); 121151f4e2bSMauro Carvalho Chehab goto no_cpufreq; 122151f4e2bSMauro Carvalho Chehab } 123151f4e2bSMauro Carvalho Chehab /* Do cpufreq things */ 124151f4e2bSMauro Carvalho Chehab no_cpufreq: 125151f4e2bSMauro Carvalho Chehab /* Do remaining things */ 126151f4e2bSMauro Carvalho Chehab } 127151f4e2bSMauro Carvalho Chehab 128151f4e2bSMauro Carvalho Chehab3. OPP Search Functions 129151f4e2bSMauro Carvalho Chehab======================= 130151f4e2bSMauro Carvalho ChehabHigh level framework such as cpufreq operates on frequencies. To map the 131151f4e2bSMauro Carvalho Chehabfrequency back to the corresponding OPP, OPP library provides handy functions 132151f4e2bSMauro Carvalho Chehabto search the OPP list that OPP library internally manages. These search 133151f4e2bSMauro Carvalho Chehabfunctions return the matching pointer representing the opp if a match is 134151f4e2bSMauro Carvalho Chehabfound, else returns error. These errors are expected to be handled by standard 135151f4e2bSMauro Carvalho Chehaberror checks such as IS_ERR() and appropriate actions taken by the caller. 136151f4e2bSMauro Carvalho Chehab 137151f4e2bSMauro Carvalho ChehabCallers of these functions shall call dev_pm_opp_put() after they have used the 138151f4e2bSMauro Carvalho ChehabOPP. Otherwise the memory for the OPP will never get freed and result in 139151f4e2bSMauro Carvalho Chehabmemleak. 140151f4e2bSMauro Carvalho Chehab 141151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_exact 142151f4e2bSMauro Carvalho Chehab Search for an OPP based on an *exact* frequency and 143151f4e2bSMauro Carvalho Chehab availability. This function is especially useful to enable an OPP which 144151f4e2bSMauro Carvalho Chehab is not available by default. 145151f4e2bSMauro Carvalho Chehab Example: In a case when SoC framework detects a situation where a 146151f4e2bSMauro Carvalho Chehab higher frequency could be made available, it can use this function to 147151f4e2bSMauro Carvalho Chehab find the OPP prior to call the dev_pm_opp_enable to actually make 148151f4e2bSMauro Carvalho Chehab it available:: 149151f4e2bSMauro Carvalho Chehab 150151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 151151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 152151f4e2bSMauro Carvalho Chehab /* dont operate on the pointer.. just do a sanity check.. */ 153151f4e2bSMauro Carvalho Chehab if (IS_ERR(opp)) { 154151f4e2bSMauro Carvalho Chehab pr_err("frequency not disabled!\n"); 155151f4e2bSMauro Carvalho Chehab /* trigger appropriate actions.. */ 156151f4e2bSMauro Carvalho Chehab } else { 157151f4e2bSMauro Carvalho Chehab dev_pm_opp_enable(dev,1000000000); 158151f4e2bSMauro Carvalho Chehab } 159151f4e2bSMauro Carvalho Chehab 160151f4e2bSMauro Carvalho Chehab NOTE: 161151f4e2bSMauro Carvalho Chehab This is the only search function that operates on OPPs which are 162151f4e2bSMauro Carvalho Chehab not available. 163151f4e2bSMauro Carvalho Chehab 164151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_floor 165151f4e2bSMauro Carvalho Chehab Search for an available OPP which is *at most* the 166151f4e2bSMauro Carvalho Chehab provided frequency. This function is useful while searching for a lesser 167151f4e2bSMauro Carvalho Chehab match OR operating on OPP information in the order of decreasing 168151f4e2bSMauro Carvalho Chehab frequency. 169151f4e2bSMauro Carvalho Chehab Example: To find the highest opp for a device:: 170151f4e2bSMauro Carvalho Chehab 171151f4e2bSMauro Carvalho Chehab freq = ULONG_MAX; 172151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_floor(dev, &freq); 173151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 174151f4e2bSMauro Carvalho Chehab 175151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_ceil 176151f4e2bSMauro Carvalho Chehab Search for an available OPP which is *at least* the 177151f4e2bSMauro Carvalho Chehab provided frequency. This function is useful while searching for a 178151f4e2bSMauro Carvalho Chehab higher match OR operating on OPP information in the order of increasing 179151f4e2bSMauro Carvalho Chehab frequency. 180151f4e2bSMauro Carvalho Chehab Example 1: To find the lowest opp for a device:: 181151f4e2bSMauro Carvalho Chehab 182151f4e2bSMauro Carvalho Chehab freq = 0; 183151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_ceil(dev, &freq); 184151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 185151f4e2bSMauro Carvalho Chehab 186151f4e2bSMauro Carvalho Chehab Example 2: A simplified implementation of a SoC cpufreq_driver->target:: 187151f4e2bSMauro Carvalho Chehab 188151f4e2bSMauro Carvalho Chehab soc_cpufreq_target(..) 189151f4e2bSMauro Carvalho Chehab { 190151f4e2bSMauro Carvalho Chehab /* Do stuff like policy checks etc. */ 191151f4e2bSMauro Carvalho Chehab /* Find the best frequency match for the req */ 192151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_ceil(dev, &freq); 193151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 194151f4e2bSMauro Carvalho Chehab if (!IS_ERR(opp)) 195151f4e2bSMauro Carvalho Chehab soc_switch_to_freq_voltage(freq); 196151f4e2bSMauro Carvalho Chehab else 197151f4e2bSMauro Carvalho Chehab /* do something when we can't satisfy the req */ 198151f4e2bSMauro Carvalho Chehab /* do other stuff */ 199151f4e2bSMauro Carvalho Chehab } 200151f4e2bSMauro Carvalho Chehab 201151f4e2bSMauro Carvalho Chehab4. OPP Availability Control Functions 202151f4e2bSMauro Carvalho Chehab===================================== 203151f4e2bSMauro Carvalho ChehabA default OPP list registered with the OPP library may not cater to all possible 204151f4e2bSMauro Carvalho Chehabsituation. The OPP library provides a set of functions to modify the 205151f4e2bSMauro Carvalho Chehabavailability of a OPP within the OPP list. This allows SoC frameworks to have 206151f4e2bSMauro Carvalho Chehabfine grained dynamic control of which sets of OPPs are operationally available. 207151f4e2bSMauro Carvalho ChehabThese functions are intended to *temporarily* remove an OPP in conditions such 208151f4e2bSMauro Carvalho Chehabas thermal considerations (e.g. don't use OPPx until the temperature drops). 209151f4e2bSMauro Carvalho Chehab 210151f4e2bSMauro Carvalho ChehabWARNING: 211151f4e2bSMauro Carvalho Chehab Do not use these functions in interrupt context. 212151f4e2bSMauro Carvalho Chehab 213151f4e2bSMauro Carvalho Chehabdev_pm_opp_enable 214151f4e2bSMauro Carvalho Chehab Make a OPP available for operation. 215151f4e2bSMauro Carvalho Chehab Example: Lets say that 1GHz OPP is to be made available only if the 216151f4e2bSMauro Carvalho Chehab SoC temperature is lower than a certain threshold. The SoC framework 217151f4e2bSMauro Carvalho Chehab implementation might choose to do something as follows:: 218151f4e2bSMauro Carvalho Chehab 219151f4e2bSMauro Carvalho Chehab if (cur_temp < temp_low_thresh) { 220151f4e2bSMauro Carvalho Chehab /* Enable 1GHz if it was disabled */ 221151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); 222151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 223151f4e2bSMauro Carvalho Chehab /* just error check */ 224151f4e2bSMauro Carvalho Chehab if (!IS_ERR(opp)) 225151f4e2bSMauro Carvalho Chehab ret = dev_pm_opp_enable(dev, 1000000000); 226151f4e2bSMauro Carvalho Chehab else 227151f4e2bSMauro Carvalho Chehab goto try_something_else; 228151f4e2bSMauro Carvalho Chehab } 229151f4e2bSMauro Carvalho Chehab 230151f4e2bSMauro Carvalho Chehabdev_pm_opp_disable 231151f4e2bSMauro Carvalho Chehab Make an OPP to be not available for operation 232151f4e2bSMauro Carvalho Chehab Example: Lets say that 1GHz OPP is to be disabled if the temperature 233151f4e2bSMauro Carvalho Chehab exceeds a threshold value. The SoC framework implementation might 234151f4e2bSMauro Carvalho Chehab choose to do something as follows:: 235151f4e2bSMauro Carvalho Chehab 236151f4e2bSMauro Carvalho Chehab if (cur_temp > temp_high_thresh) { 237151f4e2bSMauro Carvalho Chehab /* Disable 1GHz if it was enabled */ 238151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); 239151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 240151f4e2bSMauro Carvalho Chehab /* just error check */ 241151f4e2bSMauro Carvalho Chehab if (!IS_ERR(opp)) 242151f4e2bSMauro Carvalho Chehab ret = dev_pm_opp_disable(dev, 1000000000); 243151f4e2bSMauro Carvalho Chehab else 244151f4e2bSMauro Carvalho Chehab goto try_something_else; 245151f4e2bSMauro Carvalho Chehab } 246151f4e2bSMauro Carvalho Chehab 247151f4e2bSMauro Carvalho Chehab5. OPP Data Retrieval Functions 248151f4e2bSMauro Carvalho Chehab=============================== 249151f4e2bSMauro Carvalho ChehabSince OPP library abstracts away the OPP information, a set of functions to pull 250489a00efSTang Yizhouinformation from the dev_pm_opp structure is necessary. Once an OPP pointer is 251151f4e2bSMauro Carvalho Chehabretrieved using the search functions, the following functions can be used by SoC 252151f4e2bSMauro Carvalho Chehabframework to retrieve the information represented inside the OPP layer. 253151f4e2bSMauro Carvalho Chehab 254151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_voltage 255151f4e2bSMauro Carvalho Chehab Retrieve the voltage represented by the opp pointer. 256151f4e2bSMauro Carvalho Chehab Example: At a cpufreq transition to a different frequency, SoC 257151f4e2bSMauro Carvalho Chehab framework requires to set the voltage represented by the OPP using 258151f4e2bSMauro Carvalho Chehab the regulator framework to the Power Management chip providing the 259151f4e2bSMauro Carvalho Chehab voltage:: 260151f4e2bSMauro Carvalho Chehab 261151f4e2bSMauro Carvalho Chehab soc_switch_to_freq_voltage(freq) 262151f4e2bSMauro Carvalho Chehab { 263151f4e2bSMauro Carvalho Chehab /* do things */ 264151f4e2bSMauro Carvalho Chehab opp = dev_pm_opp_find_freq_ceil(dev, &freq); 265151f4e2bSMauro Carvalho Chehab v = dev_pm_opp_get_voltage(opp); 266151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 267151f4e2bSMauro Carvalho Chehab if (v) 268151f4e2bSMauro Carvalho Chehab regulator_set_voltage(.., v); 269151f4e2bSMauro Carvalho Chehab /* do other things */ 270151f4e2bSMauro Carvalho Chehab } 271151f4e2bSMauro Carvalho Chehab 272151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_freq 273151f4e2bSMauro Carvalho Chehab Retrieve the freq represented by the opp pointer. 274151f4e2bSMauro Carvalho Chehab Example: Lets say the SoC framework uses a couple of helper functions 275151f4e2bSMauro Carvalho Chehab we could pass opp pointers instead of doing additional parameters to 276151f4e2bSMauro Carvalho Chehab handle quiet a bit of data parameters:: 277151f4e2bSMauro Carvalho Chehab 278151f4e2bSMauro Carvalho Chehab soc_cpufreq_target(..) 279151f4e2bSMauro Carvalho Chehab { 280151f4e2bSMauro Carvalho Chehab /* do things.. */ 281151f4e2bSMauro Carvalho Chehab max_freq = ULONG_MAX; 282151f4e2bSMauro Carvalho Chehab max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); 283151f4e2bSMauro Carvalho Chehab requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); 284151f4e2bSMauro Carvalho Chehab if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) 285151f4e2bSMauro Carvalho Chehab r = soc_test_validity(max_opp, requested_opp); 286151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(max_opp); 287151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(requested_opp); 288151f4e2bSMauro Carvalho Chehab /* do other things */ 289151f4e2bSMauro Carvalho Chehab } 290151f4e2bSMauro Carvalho Chehab soc_test_validity(..) 291151f4e2bSMauro Carvalho Chehab { 292151f4e2bSMauro Carvalho Chehab if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) 293151f4e2bSMauro Carvalho Chehab return -EINVAL; 294151f4e2bSMauro Carvalho Chehab if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) 295151f4e2bSMauro Carvalho Chehab return -EINVAL; 296151f4e2bSMauro Carvalho Chehab /* do things.. */ 297151f4e2bSMauro Carvalho Chehab } 298151f4e2bSMauro Carvalho Chehab 299151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_opp_count 300151f4e2bSMauro Carvalho Chehab Retrieve the number of available opps for a device 301151f4e2bSMauro Carvalho Chehab Example: Lets say a co-processor in the SoC needs to know the available 302151f4e2bSMauro Carvalho Chehab frequencies in a table, the main processor can notify as following:: 303151f4e2bSMauro Carvalho Chehab 304151f4e2bSMauro Carvalho Chehab soc_notify_coproc_available_frequencies() 305151f4e2bSMauro Carvalho Chehab { 306151f4e2bSMauro Carvalho Chehab /* Do things */ 307151f4e2bSMauro Carvalho Chehab num_available = dev_pm_opp_get_opp_count(dev); 308*9ac3ebaeSErick Archer speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); 309151f4e2bSMauro Carvalho Chehab /* populate the table in increasing order */ 310151f4e2bSMauro Carvalho Chehab freq = 0; 311151f4e2bSMauro Carvalho Chehab while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { 312151f4e2bSMauro Carvalho Chehab speeds[i] = freq; 313151f4e2bSMauro Carvalho Chehab freq++; 314151f4e2bSMauro Carvalho Chehab i++; 315151f4e2bSMauro Carvalho Chehab dev_pm_opp_put(opp); 316151f4e2bSMauro Carvalho Chehab } 317151f4e2bSMauro Carvalho Chehab 318151f4e2bSMauro Carvalho Chehab soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); 319151f4e2bSMauro Carvalho Chehab /* Do other things */ 320151f4e2bSMauro Carvalho Chehab } 321151f4e2bSMauro Carvalho Chehab 322151f4e2bSMauro Carvalho Chehab6. Data Structures 323151f4e2bSMauro Carvalho Chehab================== 324151f4e2bSMauro Carvalho ChehabTypically an SoC contains multiple voltage domains which are variable. Each 325151f4e2bSMauro Carvalho Chehabdomain is represented by a device pointer. The relationship to OPP can be 326151f4e2bSMauro Carvalho Chehabrepresented as follows:: 327151f4e2bSMauro Carvalho Chehab 328151f4e2bSMauro Carvalho Chehab SoC 329151f4e2bSMauro Carvalho Chehab |- device 1 330151f4e2bSMauro Carvalho Chehab | |- opp 1 (availability, freq, voltage) 331151f4e2bSMauro Carvalho Chehab | |- opp 2 .. 332151f4e2bSMauro Carvalho Chehab ... ... 333151f4e2bSMauro Carvalho Chehab | `- opp n .. 334151f4e2bSMauro Carvalho Chehab |- device 2 335151f4e2bSMauro Carvalho Chehab ... 336151f4e2bSMauro Carvalho Chehab `- device m 337151f4e2bSMauro Carvalho Chehab 338151f4e2bSMauro Carvalho ChehabOPP library maintains a internal list that the SoC framework populates and 339151f4e2bSMauro Carvalho Chehabaccessed by various functions as described above. However, the structures 340151f4e2bSMauro Carvalho Chehabrepresenting the actual OPPs and domains are internal to the OPP library itself 341151f4e2bSMauro Carvalho Chehabto allow for suitable abstraction reusable across systems. 342151f4e2bSMauro Carvalho Chehab 343151f4e2bSMauro Carvalho Chehabstruct dev_pm_opp 344151f4e2bSMauro Carvalho Chehab The internal data structure of OPP library which is used to 345151f4e2bSMauro Carvalho Chehab represent an OPP. In addition to the freq, voltage, availability 346151f4e2bSMauro Carvalho Chehab information, it also contains internal book keeping information required 347151f4e2bSMauro Carvalho Chehab for the OPP library to operate on. Pointer to this structure is 348151f4e2bSMauro Carvalho Chehab provided back to the users such as SoC framework to be used as a 349151f4e2bSMauro Carvalho Chehab identifier for OPP in the interactions with OPP layer. 350151f4e2bSMauro Carvalho Chehab 351151f4e2bSMauro Carvalho Chehab WARNING: 352151f4e2bSMauro Carvalho Chehab The struct dev_pm_opp pointer should not be parsed or modified by the 353151f4e2bSMauro Carvalho Chehab users. The defaults of for an instance is populated by 354151f4e2bSMauro Carvalho Chehab dev_pm_opp_add, but the availability of the OPP can be modified 355151f4e2bSMauro Carvalho Chehab by dev_pm_opp_enable/disable functions. 356151f4e2bSMauro Carvalho Chehab 357151f4e2bSMauro Carvalho Chehabstruct device 358151f4e2bSMauro Carvalho Chehab This is used to identify a domain to the OPP layer. The 3591992b66dSBjorn Helgaas nature of the device and its implementation is left to the user of 360151f4e2bSMauro Carvalho Chehab OPP library such as the SoC framework. 361151f4e2bSMauro Carvalho Chehab 362151f4e2bSMauro Carvalho ChehabOverall, in a simplistic view, the data structure operations is represented as 363151f4e2bSMauro Carvalho Chehabfollowing:: 364151f4e2bSMauro Carvalho Chehab 365151f4e2bSMauro Carvalho Chehab Initialization / modification: 366151f4e2bSMauro Carvalho Chehab +-----+ /- dev_pm_opp_enable 367151f4e2bSMauro Carvalho Chehab dev_pm_opp_add --> | opp | <------- 368151f4e2bSMauro Carvalho Chehab | +-----+ \- dev_pm_opp_disable 369151f4e2bSMauro Carvalho Chehab \-------> domain_info(device) 370151f4e2bSMauro Carvalho Chehab 371151f4e2bSMauro Carvalho Chehab Search functions: 372151f4e2bSMauro Carvalho Chehab /-- dev_pm_opp_find_freq_ceil ---\ +-----+ 373151f4e2bSMauro Carvalho Chehab domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | 374151f4e2bSMauro Carvalho Chehab \-- dev_pm_opp_find_freq_floor ---/ +-----+ 375151f4e2bSMauro Carvalho Chehab 376151f4e2bSMauro Carvalho Chehab Retrieval functions: 377151f4e2bSMauro Carvalho Chehab +-----+ /- dev_pm_opp_get_voltage 378151f4e2bSMauro Carvalho Chehab | opp | <--- 379151f4e2bSMauro Carvalho Chehab +-----+ \- dev_pm_opp_get_freq 380151f4e2bSMauro Carvalho Chehab 381151f4e2bSMauro Carvalho Chehab domain_info <- dev_pm_opp_get_opp_count 382