diff options
| -rw-r--r-- | Documentation/power/00-INDEX | 2 | ||||
| -rw-r--r-- | Documentation/power/opp.txt | 375 | ||||
| -rw-r--r-- | drivers/base/power/Makefile | 1 | ||||
| -rw-r--r-- | drivers/base/power/opp.c | 628 | ||||
| -rw-r--r-- | include/linux/opp.h | 105 | ||||
| -rw-r--r-- | kernel/power/Kconfig | 14 |
6 files changed, 1125 insertions, 0 deletions
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX index fb742c213c9e..45e9d4a91284 100644 --- a/Documentation/power/00-INDEX +++ b/Documentation/power/00-INDEX | |||
| @@ -14,6 +14,8 @@ interface.txt | |||
| 14 | - Power management user interface in /sys/power | 14 | - Power management user interface in /sys/power |
| 15 | notifiers.txt | 15 | notifiers.txt |
| 16 | - Registering suspend notifiers in device drivers | 16 | - Registering suspend notifiers in device drivers |
| 17 | opp.txt | ||
| 18 | - Operating Performance Point library | ||
| 17 | pci.txt | 19 | pci.txt |
| 18 | - How the PCI Subsystem Does Power Management | 20 | - How the PCI Subsystem Does Power Management |
| 19 | pm_qos_interface.txt | 21 | pm_qos_interface.txt |
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt new file mode 100644 index 000000000000..44d87ad3cea9 --- /dev/null +++ b/Documentation/power/opp.txt | |||
| @@ -0,0 +1,375 @@ | |||
| 1 | *=============* | ||
| 2 | * 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. Cpufreq Table Generation | ||
| 15 | 7. Data Structures | ||
| 16 | |||
| 17 | 1. Introduction | ||
| 18 | =============== | ||
| 19 | Complex SoCs of today consists of a multiple sub-modules working in conjunction. | ||
| 20 | In an operational system executing varied use cases, not all modules in the SoC | ||
| 21 | need to function at their highest performing frequency all the time. To | ||
| 22 | facilitate this, sub-modules in a SoC are grouped into domains, allowing some | ||
| 23 | domains to run at lower voltage and frequency while other domains are loaded | ||
| 24 | more. The set of discrete tuples consisting of frequency and voltage pairs that | ||
| 25 | the device will support per domain are called Operating Performance Points or | ||
| 26 | OPPs. | ||
| 27 | |||
| 28 | OPP library provides a set of helper functions to organize and query the OPP | ||
| 29 | information. The library is located in drivers/base/power/opp.c and the header | ||
| 30 | is located in include/linux/opp.h. OPP library can be enabled by enabling | ||
| 31 | CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on | ||
| 32 | CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to | ||
| 33 | optionally boot at a certain OPP without needing cpufreq. | ||
| 34 | |||
| 35 | Typical usage of the OPP library is as follows: | ||
| 36 | (users) -> registers a set of default OPPs -> (library) | ||
| 37 | SoC framework -> modifies on required cases certain OPPs -> OPP layer | ||
| 38 | -> queries to search/retrieve information -> | ||
| 39 | |||
| 40 | OPP layer expects each domain to be represented by a unique device pointer. SoC | ||
| 41 | framework registers a set of initial OPPs per device with the OPP layer. This | ||
| 42 | list is expected to be an optimally small number typically around 5 per device. | ||
| 43 | This initial list contains a set of OPPs that the framework expects to be safely | ||
| 44 | enabled by default in the system. | ||
| 45 | |||
| 46 | Note on OPP Availability: | ||
| 47 | ------------------------ | ||
| 48 | As the system proceeds to operate, SoC framework may choose to make certain | ||
| 49 | OPPs available or not available on each device based on various external | ||
| 50 | factors. Example usage: Thermal management or other exceptional situations where | ||
| 51 | SoC framework might choose to disable a higher frequency OPP to safely continue | ||
| 52 | operations until that OPP could be re-enabled if possible. | ||
| 53 | |||
| 54 | OPP library facilitates this concept in it's implementation. The following | ||
| 55 | operational functions operate only on available opps: | ||
| 56 | opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count | ||
| 57 | and opp_init_cpufreq_table | ||
| 58 | |||
| 59 | opp_find_freq_exact is meant to be used to find the opp pointer which can then | ||
| 60 | be used for opp_enable/disable functions to make an opp available as required. | ||
| 61 | |||
| 62 | WARNING: Users of OPP library should refresh their availability count using | ||
| 63 | get_opp_count if opp_enable/disable functions are invoked for a device, the | ||
| 64 | exact mechanism to trigger these or the notification mechanism to other | ||
| 65 | dependent subsystems such as cpufreq are left to the discretion of the SoC | ||
| 66 | specific framework which uses the OPP library. Similar care needs to be taken | ||
| 67 | care to refresh the cpufreq table in cases of these operations. | ||
| 68 | |||
| 69 | WARNING on OPP List locking mechanism: | ||
| 70 | ------------------------------------------------- | ||
| 71 | OPP library uses RCU for exclusivity. RCU allows the query functions to operate | ||
| 72 | in multiple contexts and this synchronization mechanism is optimal for a read | ||
| 73 | intensive operations on data structure as the OPP library caters to. | ||
| 74 | |||
| 75 | To ensure that the data retrieved are sane, the users such as SoC framework | ||
| 76 | should ensure that the section of code operating on OPP queries are locked | ||
| 77 | using RCU read locks. The opp_find_freq_{exact,ceil,floor}, | ||
| 78 | opp_get_{voltage, freq, opp_count} fall into this category. | ||
| 79 | |||
| 80 | opp_{add,enable,disable} are updaters which use mutex and implement it's own | ||
| 81 | RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses | ||
| 82 | mutex to implment RCU updater strategy. These functions should *NOT* be called | ||
| 83 | under RCU locks and other contexts that prevent blocking functions in RCU or | ||
| 84 | mutex operations from working. | ||
| 85 | |||
| 86 | 2. Initial OPP List Registration | ||
| 87 | ================================ | ||
| 88 | The SoC implementation calls opp_add function iteratively to add OPPs per | ||
| 89 | device. It is expected that the SoC framework will register the OPP entries | ||
| 90 | optimally- typical numbers range to be less than 5. The list generated by | ||
| 91 | registering the OPPs is maintained by OPP library throughout the device | ||
| 92 | operation. The SoC framework can subsequently control the availability of the | ||
| 93 | OPPs dynamically using the opp_enable / disable functions. | ||
| 94 | |||
| 95 | opp_add - Add a new OPP for a specific domain represented by the device pointer. | ||
| 96 | The OPP is defined using the frequency and voltage. Once added, the OPP | ||
| 97 | is assumed to be available and control of it's availability can be done | ||
| 98 | with the opp_enable/disable functions. OPP library internally stores | ||
| 99 | and manages this information in the opp struct. This function may be | ||
| 100 | used by SoC framework to define a optimal list as per the demands of | ||
| 101 | SoC usage environment. | ||
| 102 | |||
| 103 | WARNING: Do not use this function in interrupt context. | ||
| 104 | |||
| 105 | Example: | ||
| 106 | soc_pm_init() | ||
| 107 | { | ||
| 108 | /* Do things */ | ||
| 109 | r = opp_add(mpu_dev, 1000000, 900000); | ||
| 110 | if (!r) { | ||
| 111 | pr_err("%s: unable to register mpu opp(%d)\n", r); | ||
| 112 | goto no_cpufreq; | ||
| 113 | } | ||
| 114 | /* Do cpufreq things */ | ||
| 115 | no_cpufreq: | ||
| 116 | /* Do remaining things */ | ||
| 117 | } | ||
| 118 | |||
| 119 | 3. OPP Search Functions | ||
| 120 | ======================= | ||
| 121 | High level framework such as cpufreq operates on frequencies. To map the | ||
| 122 | frequency back to the corresponding OPP, OPP library provides handy functions | ||
| 123 | to search the OPP list that OPP library internally manages. These search | ||
| 124 | functions return the matching pointer representing the opp if a match is | ||
| 125 | found, else returns error. These errors are expected to be handled by standard | ||
| 126 | error checks such as IS_ERR() and appropriate actions taken by the caller. | ||
| 127 | |||
| 128 | opp_find_freq_exact - Search for an OPP based on an *exact* frequency and | ||
| 129 | availability. This function is especially useful to enable an OPP which | ||
| 130 | is not available by default. | ||
| 131 | Example: In a case when SoC framework detects a situation where a | ||
| 132 | higher frequency could be made available, it can use this function to | ||
| 133 | find the OPP prior to call the opp_enable to actually make it available. | ||
| 134 | rcu_read_lock(); | ||
| 135 | opp = opp_find_freq_exact(dev, 1000000000, false); | ||
| 136 | rcu_read_unlock(); | ||
| 137 | /* dont operate on the pointer.. just do a sanity check.. */ | ||
| 138 | if (IS_ERR(opp)) { | ||
| 139 | pr_err("frequency not disabled!\n"); | ||
| 140 | /* trigger appropriate actions.. */ | ||
| 141 | } else { | ||
| 142 | opp_enable(dev,1000000000); | ||
| 143 | } | ||
| 144 | |||
| 145 | NOTE: This is the only search function that operates on OPPs which are | ||
| 146 | not available. | ||
| 147 | |||
| 148 | opp_find_freq_floor - Search for an available OPP which is *at most* the | ||
| 149 | provided frequency. This function is useful while searching for a lesser | ||
| 150 | match OR operating on OPP information in the order of decreasing | ||
| 151 | frequency. | ||
| 152 | Example: To find the highest opp for a device: | ||
| 153 | freq = ULONG_MAX; | ||
| 154 | rcu_read_lock(); | ||
| 155 | opp_find_freq_floor(dev, &freq); | ||
| 156 | rcu_read_unlock(); | ||
| 157 | |||
| 158 | opp_find_freq_ceil - Search for an available OPP which is *at least* the | ||
| 159 | provided frequency. This function is useful while searching for a | ||
| 160 | higher match OR operating on OPP information in the order of increasing | ||
| 161 | frequency. | ||
| 162 | Example 1: To find the lowest opp for a device: | ||
| 163 | freq = 0; | ||
| 164 | rcu_read_lock(); | ||
| 165 | opp_find_freq_ceil(dev, &freq); | ||
| 166 | rcu_read_unlock(); | ||
| 167 | Example 2: A simplified implementation of a SoC cpufreq_driver->target: | ||
| 168 | soc_cpufreq_target(..) | ||
| 169 | { | ||
| 170 | /* Do stuff like policy checks etc. */ | ||
| 171 | /* Find the best frequency match for the req */ | ||
| 172 | rcu_read_lock(); | ||
| 173 | opp = opp_find_freq_ceil(dev, &freq); | ||
| 174 | rcu_read_unlock(); | ||
| 175 | if (!IS_ERR(opp)) | ||
| 176 | soc_switch_to_freq_voltage(freq); | ||
| 177 | else | ||
| 178 | /* do something when we cant satisfy the req */ | ||
| 179 | /* do other stuff */ | ||
| 180 | } | ||
| 181 | |||
| 182 | 4. OPP Availability Control Functions | ||
| 183 | ===================================== | ||
| 184 | A default OPP list registered with the OPP library may not cater to all possible | ||
| 185 | situation. The OPP library provides a set of functions to modify the | ||
| 186 | availability of a OPP within the OPP list. This allows SoC frameworks to have | ||
| 187 | fine grained dynamic control of which sets of OPPs are operationally available. | ||
| 188 | These functions are intended to *temporarily* remove an OPP in conditions such | ||
| 189 | as thermal considerations (e.g. don't use OPPx until the temperature drops). | ||
| 190 | |||
| 191 | WARNING: Do not use these functions in interrupt context. | ||
| 192 | |||
| 193 | opp_enable - Make a OPP available for operation. | ||
| 194 | Example: Lets say that 1GHz OPP is to be made available only if the | ||
| 195 | SoC temperature is lower than a certain threshold. The SoC framework | ||
| 196 | implementation might choose to do something as follows: | ||
| 197 | if (cur_temp < temp_low_thresh) { | ||
| 198 | /* Enable 1GHz if it was disabled */ | ||
| 199 | rcu_read_lock(); | ||
| 200 | opp = opp_find_freq_exact(dev, 1000000000, false); | ||
| 201 | rcu_read_unlock(); | ||
| 202 | /* just error check */ | ||
| 203 | if (!IS_ERR(opp)) | ||
| 204 | ret = opp_enable(dev, 1000000000); | ||
| 205 | else | ||
| 206 | goto try_something_else; | ||
| 207 | } | ||
| 208 | |||
| 209 | opp_disable - Make an OPP to be not available for operation | ||
| 210 | Example: Lets say that 1GHz OPP is to be disabled if the temperature | ||
| 211 | exceeds a threshold value. The SoC framework implementation might | ||
| 212 | choose to do something as follows: | ||
| 213 | if (cur_temp > temp_high_thresh) { | ||
| 214 | /* Disable 1GHz if it was enabled */ | ||
| 215 | rcu_read_lock(); | ||
| 216 | opp = opp_find_freq_exact(dev, 1000000000, true); | ||
| 217 | rcu_read_unlock(); | ||
| 218 | /* just error check */ | ||
| 219 | if (!IS_ERR(opp)) | ||
| 220 | ret = opp_disable(dev, 1000000000); | ||
| 221 | else | ||
| 222 | goto try_something_else; | ||
| 223 | } | ||
| 224 | |||
| 225 | 5. OPP Data Retrieval Functions | ||
| 226 | =============================== | ||
| 227 | Since OPP library abstracts away the OPP information, a set of functions to pull | ||
| 228 | information from the OPP structure is necessary. Once an OPP pointer is | ||
| 229 | retrieved using the search functions, the following functions can be used by SoC | ||
| 230 | framework to retrieve the information represented inside the OPP layer. | ||
| 231 | |||
| 232 | opp_get_voltage - Retrieve the voltage represented by the opp pointer. | ||
| 233 | Example: At a cpufreq transition to a different frequency, SoC | ||
| 234 | framework requires to set the voltage represented by the OPP using | ||
| 235 | the regulator framework to the Power Management chip providing the | ||
| 236 | voltage. | ||
| 237 | soc_switch_to_freq_voltage(freq) | ||
| 238 | { | ||
| 239 | /* do things */ | ||
| 240 | rcu_read_lock(); | ||
| 241 | opp = opp_find_freq_ceil(dev, &freq); | ||
| 242 | v = opp_get_voltage(opp); | ||
| 243 | rcu_read_unlock(); | ||
| 244 | if (v) | ||
| 245 | regulator_set_voltage(.., v); | ||
| 246 | /* do other things */ | ||
| 247 | } | ||
| 248 | |||
| 249 | opp_get_freq - Retrieve the freq represented by the opp pointer. | ||
| 250 | Example: Lets say the SoC framework uses a couple of helper functions | ||
| 251 | we could pass opp pointers instead of doing additional parameters to | ||
| 252 | handle quiet a bit of data parameters. | ||
| 253 | soc_cpufreq_target(..) | ||
| 254 | { | ||
| 255 | /* do things.. */ | ||
| 256 | max_freq = ULONG_MAX; | ||
| 257 | rcu_read_lock(); | ||
| 258 | max_opp = opp_find_freq_floor(dev,&max_freq); | ||
| 259 | requested_opp = opp_find_freq_ceil(dev,&freq); | ||
| 260 | if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) | ||
| 261 | r = soc_test_validity(max_opp, requested_opp); | ||
| 262 | rcu_read_unlock(); | ||
| 263 | /* do other things */ | ||
| 264 | } | ||
| 265 | soc_test_validity(..) | ||
| 266 | { | ||
| 267 | if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp)) | ||
| 268 | return -EINVAL; | ||
| 269 | if(opp_get_freq(max_opp) < opp_get_freq(requested_opp)) | ||
| 270 | return -EINVAL; | ||
| 271 | /* do things.. */ | ||
| 272 | } | ||
| 273 | |||
| 274 | opp_get_opp_count - Retrieve the number of available opps for a device | ||
| 275 | Example: Lets say a co-processor in the SoC needs to know the available | ||
| 276 | frequencies in a table, the main processor can notify as following: | ||
| 277 | soc_notify_coproc_available_frequencies() | ||
| 278 | { | ||
| 279 | /* Do things */ | ||
| 280 | rcu_read_lock(); | ||
| 281 | num_available = opp_get_opp_count(dev); | ||
| 282 | speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); | ||
| 283 | /* populate the table in increasing order */ | ||
| 284 | freq = 0; | ||
| 285 | while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) { | ||
| 286 | speeds[i] = freq; | ||
| 287 | freq++; | ||
| 288 | i++; | ||
| 289 | } | ||
| 290 | rcu_read_unlock(); | ||
| 291 | |||
| 292 | soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); | ||
| 293 | /* Do other things */ | ||
| 294 | } | ||
| 295 | |||
| 296 | 6. Cpufreq Table Generation | ||
| 297 | =========================== | ||
| 298 | opp_init_cpufreq_table - cpufreq framework typically is initialized with | ||
| 299 | cpufreq_frequency_table_cpuinfo which is provided with the list of | ||
| 300 | frequencies that are available for operation. This function provides | ||
| 301 | a ready to use conversion routine to translate the OPP layer's internal | ||
| 302 | information about the available frequencies into a format readily | ||
| 303 | providable to cpufreq. | ||
| 304 | |||
| 305 | WARNING: Do not use this function in interrupt context. | ||
| 306 | |||
| 307 | Example: | ||
| 308 | soc_pm_init() | ||
| 309 | { | ||
| 310 | /* Do things */ | ||
| 311 | r = opp_init_cpufreq_table(dev, &freq_table); | ||
| 312 | if (!r) | ||
| 313 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
| 314 | /* Do other things */ | ||
| 315 | } | ||
| 316 | |||
| 317 | NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in | ||
| 318 | addition to CONFIG_PM as power management feature is required to | ||
| 319 | dynamically scale voltage and frequency in a system. | ||
| 320 | |||
| 321 | 7. Data Structures | ||
| 322 | ================== | ||
| 323 | Typically an SoC contains multiple voltage domains which are variable. Each | ||
| 324 | domain is represented by a device pointer. The relationship to OPP can be | ||
| 325 | represented as follows: | ||
| 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 | |||
| 336 | OPP library maintains a internal list that the SoC framework populates and | ||
| 337 | accessed by various functions as described above. However, the structures | ||
| 338 | representing the actual OPPs and domains are internal to the OPP library itself | ||
| 339 | to allow for suitable abstraction reusable across systems. | ||
| 340 | |||
| 341 | struct opp - The internal data structure of OPP library which is used to | ||
| 342 | represent an OPP. In addition to the freq, voltage, availability | ||
| 343 | information, it also contains internal book keeping information required | ||
| 344 | for the OPP library to operate on. Pointer to this structure is | ||
| 345 | provided back to the users such as SoC framework to be used as a | ||
| 346 | identifier for OPP in the interactions with OPP layer. | ||
| 347 | |||
| 348 | WARNING: The struct opp pointer should not be parsed or modified by the | ||
| 349 | users. The defaults of for an instance is populated by opp_add, but the | ||
| 350 | availability of the OPP can be modified by opp_enable/disable functions. | ||
| 351 | |||
| 352 | struct device - This is used to identify a domain to the OPP layer. The | ||
| 353 | nature of the device and it's implementation is left to the user of | ||
| 354 | OPP library such as the SoC framework. | ||
| 355 | |||
| 356 | Overall, in a simplistic view, the data structure operations is represented as | ||
| 357 | following: | ||
| 358 | |||
| 359 | Initialization / modification: | ||
| 360 | +-----+ /- opp_enable | ||
| 361 | opp_add --> | opp | <------- | ||
| 362 | | +-----+ \- opp_disable | ||
| 363 | \-------> domain_info(device) | ||
| 364 | |||
| 365 | Search functions: | ||
| 366 | /-- opp_find_freq_ceil ---\ +-----+ | ||
| 367 | domain_info<---- opp_find_freq_exact -----> | opp | | ||
| 368 | \-- opp_find_freq_floor ---/ +-----+ | ||
| 369 | |||
| 370 | Retrieval functions: | ||
| 371 | +-----+ /- opp_get_voltage | ||
| 372 | | opp | <--- | ||
| 373 | +-----+ \- opp_get_freq | ||
| 374 | |||
| 375 | domain_info <- opp_get_opp_count | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index cbccf9a3cee4..abe46edfe5b4 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
| @@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o | |||
| 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o | 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o |
| 4 | obj-$(CONFIG_PM_OPS) += generic_ops.o | 4 | obj-$(CONFIG_PM_OPS) += generic_ops.o |
| 5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o | 5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o |
| 6 | obj-$(CONFIG_PM_OPP) += opp.o | ||
| 6 | 7 | ||
| 7 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG | 8 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
| 8 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG | 9 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG |
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c new file mode 100644 index 000000000000..2bb9b4cf59d7 --- /dev/null +++ b/drivers/base/power/opp.c | |||
| @@ -0,0 +1,628 @@ | |||
| 1 | /* | ||
| 2 | * Generic OPP Interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009-2010 Texas Instruments Incorporated. | ||
| 5 | * Nishanth Menon | ||
| 6 | * Romit Dasgupta | ||
| 7 | * Kevin Hilman | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/cpufreq.h> | ||
| 20 | #include <linux/list.h> | ||
| 21 | #include <linux/rculist.h> | ||
| 22 | #include <linux/rcupdate.h> | ||
| 23 | #include <linux/opp.h> | ||
| 24 | |||
| 25 | /* | ||
| 26 | * Internal data structure organization with the OPP layer library is as | ||
| 27 | * follows: | ||
| 28 | * dev_opp_list (root) | ||
| 29 | * |- device 1 (represents voltage domain 1) | ||
| 30 | * | |- opp 1 (availability, freq, voltage) | ||
| 31 | * | |- opp 2 .. | ||
| 32 | * ... ... | ||
| 33 | * | `- opp n .. | ||
| 34 | * |- device 2 (represents the next voltage domain) | ||
| 35 | * ... | ||
| 36 | * `- device m (represents mth voltage domain) | ||
| 37 | * device 1, 2.. are represented by dev_opp structure while each opp | ||
| 38 | * is represented by the opp structure. | ||
| 39 | */ | ||
| 40 | |||
| 41 | /** | ||
| 42 | * struct opp - Generic OPP description structure | ||
| 43 | * @node: opp list node. The nodes are maintained throughout the lifetime | ||
| 44 | * of boot. It is expected only an optimal set of OPPs are | ||
| 45 | * added to the library by the SoC framework. | ||
| 46 | * RCU usage: opp list is traversed with RCU locks. node | ||
| 47 | * modification is possible realtime, hence the modifications | ||
| 48 | * are protected by the dev_opp_list_lock for integrity. | ||
| 49 | * IMPORTANT: the opp nodes should be maintained in increasing | ||
| 50 | * order. | ||
| 51 | * @available: true/false - marks if this OPP as available or not | ||
| 52 | * @rate: Frequency in hertz | ||
| 53 | * @u_volt: Nominal voltage in microvolts corresponding to this OPP | ||
| 54 | * @dev_opp: points back to the device_opp struct this opp belongs to | ||
| 55 | * | ||
| 56 | * This structure stores the OPP information for a given device. | ||
| 57 | */ | ||
| 58 | struct opp { | ||
| 59 | struct list_head node; | ||
| 60 | |||
| 61 | bool available; | ||
| 62 | unsigned long rate; | ||
| 63 | unsigned long u_volt; | ||
| 64 | |||
| 65 | struct device_opp *dev_opp; | ||
| 66 | }; | ||
| 67 | |||
| 68 | /** | ||
| 69 | * struct device_opp - Device opp structure | ||
| 70 | * @node: list node - contains the devices with OPPs that | ||
| 71 | * have been registered. Nodes once added are not modified in this | ||
| 72 | * list. | ||
| 73 | * RCU usage: nodes are not modified in the list of device_opp, | ||
| 74 | * however addition is possible and is secured by dev_opp_list_lock | ||
| 75 | * @dev: device pointer | ||
| 76 | * @opp_list: list of opps | ||
| 77 | * | ||
| 78 | * This is an internal data structure maintaining the link to opps attached to | ||
| 79 | * a device. This structure is not meant to be shared to users as it is | ||
| 80 | * meant for book keeping and private to OPP library | ||
| 81 | */ | ||
| 82 | struct device_opp { | ||
| 83 | struct list_head node; | ||
| 84 | |||
| 85 | struct device *dev; | ||
| 86 | struct list_head opp_list; | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * The root of the list of all devices. All device_opp structures branch off | ||
| 91 | * from here, with each device_opp containing the list of opp it supports in | ||
| 92 | * various states of availability. | ||
| 93 | */ | ||
| 94 | static LIST_HEAD(dev_opp_list); | ||
| 95 | /* Lock to allow exclusive modification to the device and opp lists */ | ||
| 96 | static DEFINE_MUTEX(dev_opp_list_lock); | ||
| 97 | |||
| 98 | /** | ||
| 99 | * find_device_opp() - find device_opp struct using device pointer | ||
| 100 | * @dev: device pointer used to lookup device OPPs | ||
| 101 | * | ||
| 102 | * Search list of device OPPs for one containing matching device. Does a RCU | ||
| 103 | * reader operation to grab the pointer needed. | ||
| 104 | * | ||
| 105 | * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or | ||
| 106 | * -EINVAL based on type of error. | ||
| 107 | * | ||
| 108 | * Locking: This function must be called under rcu_read_lock(). device_opp | ||
| 109 | * is a RCU protected pointer. This means that device_opp is valid as long | ||
| 110 | * as we are under RCU lock. | ||
| 111 | */ | ||
| 112 | static struct device_opp *find_device_opp(struct device *dev) | ||
| 113 | { | ||
| 114 | struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV); | ||
| 115 | |||
| 116 | if (unlikely(IS_ERR_OR_NULL(dev))) { | ||
| 117 | pr_err("%s: Invalid parameters\n", __func__); | ||
| 118 | return ERR_PTR(-EINVAL); | ||
| 119 | } | ||
| 120 | |||
| 121 | list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) { | ||
| 122 | if (tmp_dev_opp->dev == dev) { | ||
| 123 | dev_opp = tmp_dev_opp; | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | return dev_opp; | ||
| 129 | } | ||
| 130 | |||
| 131 | /** | ||
| 132 | * opp_get_voltage() - Gets the voltage corresponding to an available opp | ||
| 133 | * @opp: opp for which voltage has to be returned for | ||
| 134 | * | ||
| 135 | * Return voltage in micro volt corresponding to the opp, else | ||
| 136 | * return 0 | ||
| 137 | * | ||
| 138 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
| 139 | * protected pointer. This means that opp which could have been fetched by | ||
| 140 | * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are | ||
| 141 | * under RCU lock. The pointer returned by the opp_find_freq family must be | ||
| 142 | * used in the same section as the usage of this function with the pointer | ||
| 143 | * prior to unlocking with rcu_read_unlock() to maintain the integrity of the | ||
| 144 | * pointer. | ||
| 145 | */ | ||
| 146 | unsigned long opp_get_voltage(struct opp *opp) | ||
| 147 | { | ||
| 148 | struct opp *tmp_opp; | ||
| 149 | unsigned long v = 0; | ||
| 150 | |||
| 151 | tmp_opp = rcu_dereference(opp); | ||
| 152 | if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) | ||
| 153 | pr_err("%s: Invalid parameters\n", __func__); | ||
| 154 | else | ||
| 155 | v = tmp_opp->u_volt; | ||
| 156 | |||
| 157 | return v; | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * opp_get_freq() - Gets the frequency corresponding to an available opp | ||
| 162 | * @opp: opp for which frequency has to be returned for | ||
| 163 | * | ||
| 164 | * Return frequency in hertz corresponding to the opp, else | ||
| 165 | * return 0 | ||
| 166 | * | ||
| 167 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
| 168 | * protected pointer. This means that opp which could have been fetched by | ||
| 169 | * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are | ||
| 170 | * under RCU lock. The pointer returned by the opp_find_freq family must be | ||
| 171 | * used in the same section as the usage of this function with the pointer | ||
| 172 | * prior to unlocking with rcu_read_unlock() to maintain the integrity of the | ||
| 173 | * pointer. | ||
| 174 | */ | ||
| 175 | unsigned long opp_get_freq(struct opp *opp) | ||
| 176 | { | ||
| 177 | struct opp *tmp_opp; | ||
| 178 | unsigned long f = 0; | ||
| 179 | |||
| 180 | tmp_opp = rcu_dereference(opp); | ||
| 181 | if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) | ||
| 182 | pr_err("%s: Invalid parameters\n", __func__); | ||
| 183 | else | ||
| 184 | f = tmp_opp->rate; | ||
| 185 | |||
| 186 | return f; | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * opp_get_opp_count() - Get number of opps available in the opp list | ||
| 191 | * @dev: device for which we do this operation | ||
| 192 | * | ||
| 193 | * This function returns the number of available opps if there are any, | ||
| 194 | * else returns 0 if none or the corresponding error value. | ||
| 195 | * | ||
| 196 | * Locking: This function must be called under rcu_read_lock(). This function | ||
| 197 | * internally references two RCU protected structures: device_opp and opp which | ||
| 198 | * are safe as long as we are under a common RCU locked section. | ||
| 199 | */ | ||
| 200 | int opp_get_opp_count(struct device *dev) | ||
| 201 | { | ||
| 202 | struct device_opp *dev_opp; | ||
| 203 | struct opp *temp_opp; | ||
| 204 | int count = 0; | ||
| 205 | |||
| 206 | dev_opp = find_device_opp(dev); | ||
| 207 | if (IS_ERR(dev_opp)) { | ||
| 208 | int r = PTR_ERR(dev_opp); | ||
| 209 | dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r); | ||
| 210 | return r; | ||
| 211 | } | ||
| 212 | |||
| 213 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
| 214 | if (temp_opp->available) | ||
| 215 | count++; | ||
| 216 | } | ||
| 217 | |||
| 218 | return count; | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * opp_find_freq_exact() - search for an exact frequency | ||
| 223 | * @dev: device for which we do this operation | ||
| 224 | * @freq: frequency to search for | ||
| 225 | * @is_available: true/false - match for available opp | ||
| 226 | * | ||
| 227 | * Searches for exact match in the opp list and returns pointer to the matching | ||
| 228 | * opp if found, else returns ERR_PTR in case of error and should be handled | ||
| 229 | * using IS_ERR. | ||
| 230 | * | ||
| 231 | * Note: available is a modifier for the search. if available=true, then the | ||
| 232 | * match is for exact matching frequency and is available in the stored OPP | ||
| 233 | * table. if false, the match is for exact frequency which is not available. | ||
| 234 | * | ||
| 235 | * This provides a mechanism to enable an opp which is not available currently | ||
| 236 | * or the opposite as well. | ||
| 237 | * | ||
| 238 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
| 239 | * protected pointer. The reason for the same is that the opp pointer which is | ||
| 240 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
| 241 | * under the locked area. The pointer returned must be used prior to unlocking | ||
| 242 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
| 243 | */ | ||
| 244 | struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, | ||
| 245 | bool available) | ||
| 246 | { | ||
| 247 | struct device_opp *dev_opp; | ||
| 248 | struct opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
| 249 | |||
| 250 | dev_opp = find_device_opp(dev); | ||
| 251 | if (IS_ERR(dev_opp)) { | ||
| 252 | int r = PTR_ERR(dev_opp); | ||
| 253 | dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r); | ||
| 254 | return ERR_PTR(r); | ||
| 255 | } | ||
| 256 | |||
| 257 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
| 258 | if (temp_opp->available == available && | ||
| 259 | temp_opp->rate == freq) { | ||
| 260 | opp = temp_opp; | ||
| 261 | break; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | return opp; | ||
| 266 | } | ||
| 267 | |||
| 268 | /** | ||
| 269 | * opp_find_freq_ceil() - Search for an rounded ceil freq | ||
| 270 | * @dev: device for which we do this operation | ||
| 271 | * @freq: Start frequency | ||
| 272 | * | ||
| 273 | * Search for the matching ceil *available* OPP from a starting freq | ||
| 274 | * for a device. | ||
| 275 | * | ||
| 276 | * Returns matching *opp and refreshes *freq accordingly, else returns | ||
| 277 | * ERR_PTR in case of error and should be handled using IS_ERR. | ||
| 278 | * | ||
| 279 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
| 280 | * protected pointer. The reason for the same is that the opp pointer which is | ||
| 281 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
| 282 | * under the locked area. The pointer returned must be used prior to unlocking | ||
| 283 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
| 284 | */ | ||
| 285 | struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq) | ||
| 286 | { | ||
| 287 | struct device_opp *dev_opp; | ||
| 288 | struct opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
| 289 | |||
| 290 | if (!dev || !freq) { | ||
| 291 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); | ||
| 292 | return ERR_PTR(-EINVAL); | ||
| 293 | } | ||
| 294 | |||
| 295 | dev_opp = find_device_opp(dev); | ||
| 296 | if (IS_ERR(dev_opp)) | ||
| 297 | return opp; | ||
| 298 | |||
| 299 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
| 300 | if (temp_opp->available && temp_opp->rate >= *freq) { | ||
| 301 | opp = temp_opp; | ||
| 302 | *freq = opp->rate; | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | return opp; | ||
| 308 | } | ||
| 309 | |||
| 310 | /** | ||
| 311 | * opp_find_freq_floor() - Search for a rounded floor freq | ||
| 312 | * @dev: device for which we do this operation | ||
| 313 | * @freq: Start frequency | ||
| 314 | * | ||
| 315 | * Search for the matching floor *available* OPP from a starting freq | ||
| 316 | * for a device. | ||
| 317 | * | ||
| 318 | * Returns matching *opp and refreshes *freq accordingly, else returns | ||
| 319 | * ERR_PTR in case of error and should be handled using IS_ERR. | ||
| 320 | * | ||
| 321 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
| 322 | * protected pointer. The reason for the same is that the opp pointer which is | ||
| 323 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
| 324 | * under the locked area. The pointer returned must be used prior to unlocking | ||
| 325 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
| 326 | */ | ||
| 327 | struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq) | ||
| 328 | { | ||
| 329 | struct device_opp *dev_opp; | ||
| 330 | struct opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
| 331 | |||
| 332 | if (!dev || !freq) { | ||
| 333 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); | ||
| 334 | return ERR_PTR(-EINVAL); | ||
| 335 | } | ||
| 336 | |||
| 337 | dev_opp = find_device_opp(dev); | ||
| 338 | if (IS_ERR(dev_opp)) | ||
| 339 | return opp; | ||
| 340 | |||
| 341 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
| 342 | if (temp_opp->available) { | ||
| 343 | /* go to the next node, before choosing prev */ | ||
| 344 | if (temp_opp->rate > *freq) | ||
| 345 | break; | ||
| 346 | else | ||
| 347 | opp = temp_opp; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | if (!IS_ERR(opp)) | ||
| 351 | *freq = opp->rate; | ||
| 352 | |||
| 353 | return opp; | ||
| 354 | } | ||
| 355 | |||
| 356 | /** | ||
| 357 | * opp_add() - Add an OPP table from a table definitions | ||
| 358 | * @dev: device for which we do this operation | ||
| 359 | * @freq: Frequency in Hz for this OPP | ||
| 360 | * @u_volt: Voltage in uVolts for this OPP | ||
| 361 | * | ||
| 362 | * This function adds an opp definition to the opp list and returns status. | ||
| 363 | * The opp is made available by default and it can be controlled using | ||
| 364 | * opp_enable/disable functions. | ||
| 365 | * | ||
| 366 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
| 367 | * Hence this function internally uses RCU updater strategy with mutex locks | ||
| 368 | * to keep the integrity of the internal data structures. Callers should ensure | ||
| 369 | * that this function is *NOT* called under RCU protection or in contexts where | ||
| 370 | * mutex cannot be locked. | ||
| 371 | */ | ||
| 372 | int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) | ||
| 373 | { | ||
| 374 | struct device_opp *dev_opp = NULL; | ||
| 375 | struct opp *opp, *new_opp; | ||
| 376 | struct list_head *head; | ||
| 377 | |||
| 378 | /* allocate new OPP node */ | ||
| 379 | new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL); | ||
| 380 | if (!new_opp) { | ||
| 381 | dev_warn(dev, "%s: Unable to create new OPP node\n", __func__); | ||
| 382 | return -ENOMEM; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* Hold our list modification lock here */ | ||
| 386 | mutex_lock(&dev_opp_list_lock); | ||
| 387 | |||
| 388 | /* Check for existing list for 'dev' */ | ||
| 389 | dev_opp = find_device_opp(dev); | ||
| 390 | if (IS_ERR(dev_opp)) { | ||
| 391 | /* | ||
| 392 | * Allocate a new device OPP table. In the infrequent case | ||
| 393 | * where a new device is needed to be added, we pay this | ||
| 394 | * penalty. | ||
| 395 | */ | ||
| 396 | dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL); | ||
| 397 | if (!dev_opp) { | ||
| 398 | mutex_unlock(&dev_opp_list_lock); | ||
| 399 | kfree(new_opp); | ||
| 400 | dev_warn(dev, | ||
| 401 | "%s: Unable to create device OPP structure\n", | ||
| 402 | __func__); | ||
| 403 | return -ENOMEM; | ||
| 404 | } | ||
| 405 | |||
| 406 | dev_opp->dev = dev; | ||
| 407 | INIT_LIST_HEAD(&dev_opp->opp_list); | ||
| 408 | |||
| 409 | /* Secure the device list modification */ | ||
| 410 | list_add_rcu(&dev_opp->node, &dev_opp_list); | ||
| 411 | } | ||
| 412 | |||
| 413 | /* populate the opp table */ | ||
| 414 | new_opp->dev_opp = dev_opp; | ||
| 415 | new_opp->rate = freq; | ||
| 416 | new_opp->u_volt = u_volt; | ||
| 417 | new_opp->available = true; | ||
| 418 | |||
| 419 | /* Insert new OPP in order of increasing frequency */ | ||
| 420 | head = &dev_opp->opp_list; | ||
| 421 | list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) { | ||
| 422 | if (new_opp->rate < opp->rate) | ||
| 423 | break; | ||
| 424 | else | ||
| 425 | head = &opp->node; | ||
| 426 | } | ||
| 427 | |||
| 428 | list_add_rcu(&new_opp->node, head); | ||
| 429 | mutex_unlock(&dev_opp_list_lock); | ||
| 430 | |||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | |||
| 434 | /** | ||
| 435 | * opp_set_availability() - helper to set the availability of an opp | ||
| 436 | * @dev: device for which we do this operation | ||
| 437 | * @freq: OPP frequency to modify availability | ||
| 438 | * @availability_req: availability status requested for this opp | ||
| 439 | * | ||
| 440 | * Set the availability of an OPP with an RCU operation, opp_{enable,disable} | ||
| 441 | * share a common logic which is isolated here. | ||
| 442 | * | ||
| 443 | * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the | ||
| 444 | * copy operation, returns 0 if no modifcation was done OR modification was | ||
| 445 | * successful. | ||
| 446 | * | ||
| 447 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
| 448 | * Hence this function internally uses RCU updater strategy with mutex locks to | ||
| 449 | * keep the integrity of the internal data structures. Callers should ensure | ||
| 450 | * that this function is *NOT* called under RCU protection or in contexts where | ||
| 451 | * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||
| 452 | */ | ||
| 453 | static int opp_set_availability(struct device *dev, unsigned long freq, | ||
| 454 | bool availability_req) | ||
| 455 | { | ||
| 456 | struct device_opp *tmp_dev_opp, *dev_opp = NULL; | ||
| 457 | struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); | ||
| 458 | int r = 0; | ||
| 459 | |||
| 460 | /* keep the node allocated */ | ||
| 461 | new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL); | ||
| 462 | if (!new_opp) { | ||
| 463 | dev_warn(dev, "%s: Unable to create OPP\n", __func__); | ||
| 464 | return -ENOMEM; | ||
| 465 | } | ||
| 466 | |||
| 467 | mutex_lock(&dev_opp_list_lock); | ||
| 468 | |||
| 469 | /* Find the device_opp */ | ||
| 470 | list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) { | ||
| 471 | if (dev == tmp_dev_opp->dev) { | ||
| 472 | dev_opp = tmp_dev_opp; | ||
| 473 | break; | ||
| 474 | } | ||
| 475 | } | ||
| 476 | if (IS_ERR(dev_opp)) { | ||
| 477 | r = PTR_ERR(dev_opp); | ||
| 478 | dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); | ||
| 479 | goto unlock; | ||
| 480 | } | ||
| 481 | |||
| 482 | /* Do we have the frequency? */ | ||
| 483 | list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) { | ||
| 484 | if (tmp_opp->rate == freq) { | ||
| 485 | opp = tmp_opp; | ||
| 486 | break; | ||
| 487 | } | ||
| 488 | } | ||
| 489 | if (IS_ERR(opp)) { | ||
| 490 | r = PTR_ERR(opp); | ||
| 491 | goto unlock; | ||
| 492 | } | ||
| 493 | |||
| 494 | /* Is update really needed? */ | ||
| 495 | if (opp->available == availability_req) | ||
| 496 | goto unlock; | ||
| 497 | /* copy the old data over */ | ||
| 498 | *new_opp = *opp; | ||
| 499 | |||
| 500 | /* plug in new node */ | ||
| 501 | new_opp->available = availability_req; | ||
| 502 | |||
| 503 | list_replace_rcu(&opp->node, &new_opp->node); | ||
| 504 | mutex_unlock(&dev_opp_list_lock); | ||
| 505 | synchronize_rcu(); | ||
| 506 | |||
| 507 | /* clean up old opp */ | ||
| 508 | new_opp = opp; | ||
| 509 | goto out; | ||
| 510 | |||
| 511 | unlock: | ||
| 512 | mutex_unlock(&dev_opp_list_lock); | ||
| 513 | out: | ||
| 514 | kfree(new_opp); | ||
| 515 | return r; | ||
| 516 | } | ||
| 517 | |||
| 518 | /** | ||
| 519 | * opp_enable() - Enable a specific OPP | ||
| 520 | * @dev: device for which we do this operation | ||
| 521 | * @freq: OPP frequency to enable | ||
| 522 | * | ||
| 523 | * Enables a provided opp. If the operation is valid, this returns 0, else the | ||
| 524 | * corresponding error value. It is meant to be used for users an OPP available | ||
| 525 | * after being temporarily made unavailable with opp_disable. | ||
| 526 | * | ||
| 527 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
| 528 | * Hence this function indirectly uses RCU and mutex locks to keep the | ||
| 529 | * integrity of the internal data structures. Callers should ensure that | ||
| 530 | * this function is *NOT* called under RCU protection or in contexts where | ||
| 531 | * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||
| 532 | */ | ||
| 533 | int opp_enable(struct device *dev, unsigned long freq) | ||
| 534 | { | ||
| 535 | return opp_set_availability(dev, freq, true); | ||
| 536 | } | ||
| 537 | |||
| 538 | /** | ||
| 539 | * opp_disable() - Disable a specific OPP | ||
| 540 | * @dev: device for which we do this operation | ||
| 541 | * @freq: OPP frequency to disable | ||
| 542 | * | ||
| 543 | * Disables a provided opp. If the operation is valid, this returns | ||
| 544 | * 0, else the corresponding error value. It is meant to be a temporary | ||
| 545 | * control by users to make this OPP not available until the circumstances are | ||
| 546 | * right to make it available again (with a call to opp_enable). | ||
| 547 | * | ||
| 548 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
| 549 | * Hence this function indirectly uses RCU and mutex locks to keep the | ||
| 550 | * integrity of the internal data structures. Callers should ensure that | ||
| 551 | * this function is *NOT* called under RCU protection or in contexts where | ||
| 552 | * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||
| 553 | */ | ||
| 554 | int opp_disable(struct device *dev, unsigned long freq) | ||
| 555 | { | ||
| 556 | return opp_set_availability(dev, freq, false); | ||
| 557 | } | ||
| 558 | |||
| 559 | #ifdef CONFIG_CPU_FREQ | ||
| 560 | /** | ||
| 561 | * opp_init_cpufreq_table() - create a cpufreq table for a device | ||
| 562 | * @dev: device for which we do this operation | ||
| 563 | * @table: Cpufreq table returned back to caller | ||
| 564 | * | ||
| 565 | * Generate a cpufreq table for a provided device- this assumes that the | ||
| 566 | * opp list is already initialized and ready for usage. | ||
| 567 | * | ||
| 568 | * This function allocates required memory for the cpufreq table. It is | ||
| 569 | * expected that the caller does the required maintenance such as freeing | ||
| 570 | * the table as required. | ||
| 571 | * | ||
| 572 | * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM | ||
| 573 | * if no memory available for the operation (table is not populated), returns 0 | ||
| 574 | * if successful and table is populated. | ||
| 575 | * | ||
| 576 | * WARNING: It is important for the callers to ensure refreshing their copy of | ||
| 577 | * the table if any of the mentioned functions have been invoked in the interim. | ||
| 578 | * | ||
| 579 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
| 580 | * To simplify the logic, we pretend we are updater and hold relevant mutex here | ||
| 581 | * Callers should ensure that this function is *NOT* called under RCU protection | ||
| 582 | * or in contexts where mutex locking cannot be used. | ||
| 583 | */ | ||
| 584 | int opp_init_cpufreq_table(struct device *dev, | ||
| 585 | struct cpufreq_frequency_table **table) | ||
| 586 | { | ||
| 587 | struct device_opp *dev_opp; | ||
| 588 | struct opp *opp; | ||
| 589 | struct cpufreq_frequency_table *freq_table; | ||
| 590 | int i = 0; | ||
| 591 | |||
| 592 | /* Pretend as if I am an updater */ | ||
| 593 | mutex_lock(&dev_opp_list_lock); | ||
| 594 | |||
| 595 | dev_opp = find_device_opp(dev); | ||
| 596 | if (IS_ERR(dev_opp)) { | ||
| 597 | int r = PTR_ERR(dev_opp); | ||
| 598 | mutex_unlock(&dev_opp_list_lock); | ||
| 599 | dev_err(dev, "%s: Device OPP not found (%d)\n", __func__, r); | ||
| 600 | return r; | ||
| 601 | } | ||
| 602 | |||
| 603 | freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * | ||
| 604 | (opp_get_opp_count(dev) + 1), GFP_KERNEL); | ||
| 605 | if (!freq_table) { | ||
| 606 | mutex_unlock(&dev_opp_list_lock); | ||
| 607 | dev_warn(dev, "%s: Unable to allocate frequency table\n", | ||
| 608 | __func__); | ||
| 609 | return -ENOMEM; | ||
| 610 | } | ||
| 611 | |||
| 612 | list_for_each_entry(opp, &dev_opp->opp_list, node) { | ||
| 613 | if (opp->available) { | ||
| 614 | freq_table[i].index = i; | ||
| 615 | freq_table[i].frequency = opp->rate / 1000; | ||
| 616 | i++; | ||
| 617 | } | ||
| 618 | } | ||
| 619 | mutex_unlock(&dev_opp_list_lock); | ||
| 620 | |||
| 621 | freq_table[i].index = i; | ||
| 622 | freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
| 623 | |||
| 624 | *table = &freq_table[0]; | ||
| 625 | |||
| 626 | return 0; | ||
| 627 | } | ||
| 628 | #endif /* CONFIG_CPU_FREQ */ | ||
diff --git a/include/linux/opp.h b/include/linux/opp.h new file mode 100644 index 000000000000..5449945d589f --- /dev/null +++ b/include/linux/opp.h | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | /* | ||
| 2 | * Generic OPP Interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009-2010 Texas Instruments Incorporated. | ||
| 5 | * Nishanth Menon | ||
| 6 | * Romit Dasgupta | ||
| 7 | * Kevin Hilman | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef __LINUX_OPP_H__ | ||
| 15 | #define __LINUX_OPP_H__ | ||
| 16 | |||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/cpufreq.h> | ||
| 19 | |||
| 20 | struct opp; | ||
| 21 | |||
| 22 | #if defined(CONFIG_PM_OPP) | ||
| 23 | |||
| 24 | unsigned long opp_get_voltage(struct opp *opp); | ||
| 25 | |||
| 26 | unsigned long opp_get_freq(struct opp *opp); | ||
| 27 | |||
| 28 | int opp_get_opp_count(struct device *dev); | ||
| 29 | |||
| 30 | struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, | ||
| 31 | bool available); | ||
| 32 | |||
| 33 | struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq); | ||
| 34 | |||
| 35 | struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq); | ||
| 36 | |||
| 37 | int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt); | ||
| 38 | |||
| 39 | int opp_enable(struct device *dev, unsigned long freq); | ||
| 40 | |||
| 41 | int opp_disable(struct device *dev, unsigned long freq); | ||
| 42 | |||
| 43 | #else | ||
| 44 | static inline unsigned long opp_get_voltage(struct opp *opp) | ||
| 45 | { | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | static inline unsigned long opp_get_freq(struct opp *opp) | ||
| 50 | { | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | static inline int opp_get_opp_count(struct device *dev) | ||
| 55 | { | ||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | static inline struct opp *opp_find_freq_exact(struct device *dev, | ||
| 60 | unsigned long freq, bool available) | ||
| 61 | { | ||
| 62 | return ERR_PTR(-EINVAL); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline struct opp *opp_find_freq_floor(struct device *dev, | ||
| 66 | unsigned long *freq) | ||
| 67 | { | ||
| 68 | return ERR_PTR(-EINVAL); | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline struct opp *opp_find_freq_ceil(struct device *dev, | ||
| 72 | unsigned long *freq) | ||
| 73 | { | ||
| 74 | return ERR_PTR(-EINVAL); | ||
| 75 | } | ||
| 76 | |||
| 77 | static inline int opp_add(struct device *dev, unsigned long freq, | ||
| 78 | unsigned long u_volt) | ||
| 79 | { | ||
| 80 | return -EINVAL; | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline int opp_enable(struct device *dev, unsigned long freq) | ||
| 84 | { | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static inline int opp_disable(struct device *dev, unsigned long freq) | ||
| 89 | { | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | #endif /* CONFIG_PM */ | ||
| 93 | |||
| 94 | #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP) | ||
| 95 | int opp_init_cpufreq_table(struct device *dev, | ||
| 96 | struct cpufreq_frequency_table **table); | ||
| 97 | #else | ||
| 98 | static inline int opp_init_cpufreq_table(struct device *dev, | ||
| 99 | struct cpufreq_frequency_table **table) | ||
| 100 | { | ||
| 101 | return -EINVAL; | ||
| 102 | } | ||
| 103 | #endif /* CONFIG_CPU_FREQ */ | ||
| 104 | |||
| 105 | #endif /* __LINUX_OPP_H__ */ | ||
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index e45894c696ee..29bff6117abc 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
| @@ -245,3 +245,17 @@ config PM_OPS | |||
| 245 | bool | 245 | bool |
| 246 | depends on PM_SLEEP || PM_RUNTIME | 246 | depends on PM_SLEEP || PM_RUNTIME |
| 247 | default y | 247 | default y |
| 248 | |||
| 249 | config PM_OPP | ||
| 250 | bool "Operating Performance Point (OPP) Layer library" | ||
| 251 | depends on PM | ||
| 252 | ---help--- | ||
| 253 | SOCs have a standard set of tuples consisting of frequency and | ||
| 254 | voltage pairs that the device will support per voltage domain. This | ||
| 255 | is called Operating Performance Point or OPP. The actual definitions | ||
| 256 | of OPP varies over silicon within the same family of devices. | ||
| 257 | |||
| 258 | OPP layer organizes the data internally using device pointers | ||
| 259 | representing individual voltage domains and provides SOC | ||
| 260 | implementations a ready to use framework to manage OPPs. | ||
| 261 | For more information, read <file:Documentation/power/opp.txt> | ||
