~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/power/opp.rst

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php