Back to home page

OSCL-LXR

 
 

    


0001 ==========================================
0002 Operating Performance Points (OPP) Library
0003 ==========================================
0004 
0005 (C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
0006 
0007 .. Contents
0008 
0009   1. Introduction
0010   2. Initial OPP List Registration
0011   3. OPP Search Functions
0012   4. OPP Availability Control Functions
0013   5. OPP Data Retrieval Functions
0014   6. Data Structures
0015 
0016 1. Introduction
0017 ===============
0018 
0019 1.1 What is an Operating Performance Point (OPP)?
0020 -------------------------------------------------
0021 
0022 Complex SoCs of today consists of a multiple sub-modules working in conjunction.
0023 In an operational system executing varied use cases, not all modules in the SoC
0024 need to function at their highest performing frequency all the time. To
0025 facilitate this, sub-modules in a SoC are grouped into domains, allowing some
0026 domains to run at lower voltage and frequency while other domains run at
0027 voltage/frequency pairs that are higher.
0028 
0029 The set of discrete tuples consisting of frequency and voltage pairs that
0030 the device will support per domain are called Operating Performance Points or
0031 OPPs.
0032 
0033 As an example:
0034 
0035 Let us consider an MPU device which supports the following:
0036 {300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V},
0037 {1GHz at minimum voltage of 1.3V}
0038 
0039 We can represent these as three OPPs as the following {Hz, uV} tuples:
0040 
0041 - {300000000, 1000000}
0042 - {800000000, 1200000}
0043 - {1000000000, 1300000}
0044 
0045 1.2 Operating Performance Points Library
0046 ----------------------------------------
0047 
0048 OPP library provides a set of helper functions to organize and query the OPP
0049 information. The library is located in drivers/opp/ directory and the header
0050 is located in include/linux/pm_opp.h. OPP library can be enabled by enabling
0051 CONFIG_PM_OPP from power management menuconfig menu. Certain SoCs such as Texas
0052 Instrument's OMAP framework allows to optionally boot at a certain OPP without
0053 needing cpufreq.
0054 
0055 Typical usage of the OPP library is as follows::
0056 
0057  (users)        -> registers a set of default OPPs              -> (library)
0058  SoC framework  -> modifies on required cases certain OPPs      -> OPP layer
0059                 -> queries to search/retrieve information       ->
0060 
0061 OPP layer expects each domain to be represented by a unique device pointer. SoC
0062 framework registers a set of initial OPPs per device with the OPP layer. This
0063 list is expected to be an optimally small number typically around 5 per device.
0064 This initial list contains a set of OPPs that the framework expects to be safely
0065 enabled by default in the system.
0066 
0067 Note on OPP Availability
0068 ^^^^^^^^^^^^^^^^^^^^^^^^
0069 
0070 As the system proceeds to operate, SoC framework may choose to make certain
0071 OPPs available or not available on each device based on various external
0072 factors. Example usage: Thermal management or other exceptional situations where
0073 SoC framework might choose to disable a higher frequency OPP to safely continue
0074 operations until that OPP could be re-enabled if possible.
0075 
0076 OPP library facilitates this concept in its implementation. The following
0077 operational functions operate only on available opps:
0078 dev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq,
0079 dev_pm_opp_get_opp_count.
0080 
0081 dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer
0082 which can then be used for dev_pm_opp_enable/disable functions to make an
0083 opp available as required.
0084 
0085 WARNING: Users of OPP library should refresh their availability count using
0086 get_opp_count if dev_pm_opp_enable/disable functions are invoked for a
0087 device, the exact mechanism to trigger these or the notification mechanism
0088 to other dependent subsystems such as cpufreq are left to the discretion of
0089 the SoC specific framework which uses the OPP library. Similar care needs
0090 to be taken care to refresh the cpufreq table in cases of these operations.
0091 
0092 2. Initial OPP List Registration
0093 ================================
0094 The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per
0095 device. It is expected that the SoC framework will register the OPP entries
0096 optimally- typical numbers range to be less than 5. The list generated by
0097 registering the OPPs is maintained by OPP library throughout the device
0098 operation. The SoC framework can subsequently control the availability of the
0099 OPPs dynamically using the dev_pm_opp_enable / disable functions.
0100 
0101 dev_pm_opp_add
0102         Add a new OPP for a specific domain represented by the device pointer.
0103         The OPP is defined using the frequency and voltage. Once added, the OPP
0104         is assumed to be available and control of its availability can be done
0105         with the dev_pm_opp_enable/disable functions. OPP library
0106         internally stores and manages this information in the dev_pm_opp struct.
0107         This function may be used by SoC framework to define a optimal list
0108         as per the demands of SoC usage environment.
0109 
0110         WARNING:
0111                 Do not use this function in interrupt context.
0112 
0113         Example::
0114 
0115          soc_pm_init()
0116          {
0117                 /* Do things */
0118                 r = dev_pm_opp_add(mpu_dev, 1000000, 900000);
0119                 if (!r) {
0120                         pr_err("%s: unable to register mpu opp(%d)\n", r);
0121                         goto no_cpufreq;
0122                 }
0123                 /* Do cpufreq things */
0124          no_cpufreq:
0125                 /* Do remaining things */
0126          }
0127 
0128 3. OPP Search Functions
0129 =======================
0130 High level framework such as cpufreq operates on frequencies. To map the
0131 frequency back to the corresponding OPP, OPP library provides handy functions
0132 to search the OPP list that OPP library internally manages. These search
0133 functions return the matching pointer representing the opp if a match is
0134 found, else returns error. These errors are expected to be handled by standard
0135 error checks such as IS_ERR() and appropriate actions taken by the caller.
0136 
0137 Callers of these functions shall call dev_pm_opp_put() after they have used the
0138 OPP. Otherwise the memory for the OPP will never get freed and result in
0139 memleak.
0140 
0141 dev_pm_opp_find_freq_exact
0142         Search for an OPP based on an *exact* frequency and
0143         availability. This function is especially useful to enable an OPP which
0144         is not available by default.
0145         Example: In a case when SoC framework detects a situation where a
0146         higher frequency could be made available, it can use this function to
0147         find the OPP prior to call the dev_pm_opp_enable to actually make
0148         it available::
0149 
0150          opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
0151          dev_pm_opp_put(opp);
0152          /* dont operate on the pointer.. just do a sanity check.. */
0153          if (IS_ERR(opp)) {
0154                 pr_err("frequency not disabled!\n");
0155                 /* trigger appropriate actions.. */
0156          } else {
0157                 dev_pm_opp_enable(dev,1000000000);
0158          }
0159 
0160         NOTE:
0161           This is the only search function that operates on OPPs which are
0162           not available.
0163 
0164 dev_pm_opp_find_freq_floor
0165         Search for an available OPP which is *at most* the
0166         provided frequency. This function is useful while searching for a lesser
0167         match OR operating on OPP information in the order of decreasing
0168         frequency.
0169         Example: To find the highest opp for a device::
0170 
0171          freq = ULONG_MAX;
0172          opp = dev_pm_opp_find_freq_floor(dev, &freq);
0173          dev_pm_opp_put(opp);
0174 
0175 dev_pm_opp_find_freq_ceil
0176         Search for an available OPP which is *at least* the
0177         provided frequency. This function is useful while searching for a
0178         higher match OR operating on OPP information in the order of increasing
0179         frequency.
0180         Example 1: To find the lowest opp for a device::
0181 
0182          freq = 0;
0183          opp = dev_pm_opp_find_freq_ceil(dev, &freq);
0184          dev_pm_opp_put(opp);
0185 
0186         Example 2: A simplified implementation of a SoC cpufreq_driver->target::
0187 
0188          soc_cpufreq_target(..)
0189          {
0190                 /* Do stuff like policy checks etc. */
0191                 /* Find the best frequency match for the req */
0192                 opp = dev_pm_opp_find_freq_ceil(dev, &freq);
0193                 dev_pm_opp_put(opp);
0194                 if (!IS_ERR(opp))
0195                         soc_switch_to_freq_voltage(freq);
0196                 else
0197                         /* do something when we can't satisfy the req */
0198                 /* do other stuff */
0199          }
0200 
0201 4. OPP Availability Control Functions
0202 =====================================
0203 A default OPP list registered with the OPP library may not cater to all possible
0204 situation. The OPP library provides a set of functions to modify the
0205 availability of a OPP within the OPP list. This allows SoC frameworks to have
0206 fine grained dynamic control of which sets of OPPs are operationally available.
0207 These functions are intended to *temporarily* remove an OPP in conditions such
0208 as thermal considerations (e.g. don't use OPPx until the temperature drops).
0209 
0210 WARNING:
0211         Do not use these functions in interrupt context.
0212 
0213 dev_pm_opp_enable
0214         Make a OPP available for operation.
0215         Example: Lets say that 1GHz OPP is to be made available only if the
0216         SoC temperature is lower than a certain threshold. The SoC framework
0217         implementation might choose to do something as follows::
0218 
0219          if (cur_temp < temp_low_thresh) {
0220                 /* Enable 1GHz if it was disabled */
0221                 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
0222                 dev_pm_opp_put(opp);
0223                 /* just error check */
0224                 if (!IS_ERR(opp))
0225                         ret = dev_pm_opp_enable(dev, 1000000000);
0226                 else
0227                         goto try_something_else;
0228          }
0229 
0230 dev_pm_opp_disable
0231         Make an OPP to be not available for operation
0232         Example: Lets say that 1GHz OPP is to be disabled if the temperature
0233         exceeds a threshold value. The SoC framework implementation might
0234         choose to do something as follows::
0235 
0236          if (cur_temp > temp_high_thresh) {
0237                 /* Disable 1GHz if it was enabled */
0238                 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true);
0239                 dev_pm_opp_put(opp);
0240                 /* just error check */
0241                 if (!IS_ERR(opp))
0242                         ret = dev_pm_opp_disable(dev, 1000000000);
0243                 else
0244                         goto try_something_else;
0245          }
0246 
0247 5. OPP Data Retrieval Functions
0248 ===============================
0249 Since OPP library abstracts away the OPP information, a set of functions to pull
0250 information from the dev_pm_opp structure is necessary. Once an OPP pointer is
0251 retrieved using the search functions, the following functions can be used by SoC
0252 framework to retrieve the information represented inside the OPP layer.
0253 
0254 dev_pm_opp_get_voltage
0255         Retrieve the voltage represented by the opp pointer.
0256         Example: At a cpufreq transition to a different frequency, SoC
0257         framework requires to set the voltage represented by the OPP using
0258         the regulator framework to the Power Management chip providing the
0259         voltage::
0260 
0261          soc_switch_to_freq_voltage(freq)
0262          {
0263                 /* do things */
0264                 opp = dev_pm_opp_find_freq_ceil(dev, &freq);
0265                 v = dev_pm_opp_get_voltage(opp);
0266                 dev_pm_opp_put(opp);
0267                 if (v)
0268                         regulator_set_voltage(.., v);
0269                 /* do other things */
0270          }
0271 
0272 dev_pm_opp_get_freq
0273         Retrieve the freq represented by the opp pointer.
0274         Example: Lets say the SoC framework uses a couple of helper functions
0275         we could pass opp pointers instead of doing additional parameters to
0276         handle quiet a bit of data parameters::
0277 
0278          soc_cpufreq_target(..)
0279          {
0280                 /* do things.. */
0281                  max_freq = ULONG_MAX;
0282                  max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq);
0283                  requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq);
0284                  if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
0285                         r = soc_test_validity(max_opp, requested_opp);
0286                  dev_pm_opp_put(max_opp);
0287                  dev_pm_opp_put(requested_opp);
0288                 /* do other things */
0289          }
0290          soc_test_validity(..)
0291          {
0292                  if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp))
0293                          return -EINVAL;
0294                  if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp))
0295                          return -EINVAL;
0296                 /* do things.. */
0297          }
0298 
0299 dev_pm_opp_get_opp_count
0300         Retrieve the number of available opps for a device
0301         Example: Lets say a co-processor in the SoC needs to know the available
0302         frequencies in a table, the main processor can notify as following::
0303 
0304          soc_notify_coproc_available_frequencies()
0305          {
0306                 /* Do things */
0307                 num_available = dev_pm_opp_get_opp_count(dev);
0308                 speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
0309                 /* populate the table in increasing order */
0310                 freq = 0;
0311                 while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) {
0312                         speeds[i] = freq;
0313                         freq++;
0314                         i++;
0315                         dev_pm_opp_put(opp);
0316                 }
0317 
0318                 soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
0319                 /* Do other things */
0320          }
0321 
0322 6. Data Structures
0323 ==================
0324 Typically an SoC contains multiple voltage domains which are variable. Each
0325 domain is represented by a device pointer. The relationship to OPP can be
0326 represented as follows::
0327 
0328   SoC
0329    |- device 1
0330    |    |- opp 1 (availability, freq, voltage)
0331    |    |- opp 2 ..
0332    ...  ...
0333    |    `- opp n ..
0334    |- device 2
0335    ...
0336    `- device m
0337 
0338 OPP library maintains a internal list that the SoC framework populates and
0339 accessed by various functions as described above. However, the structures
0340 representing the actual OPPs and domains are internal to the OPP library itself
0341 to allow for suitable abstraction reusable across systems.
0342 
0343 struct dev_pm_opp
0344         The internal data structure of OPP library which is used to
0345         represent an OPP. In addition to the freq, voltage, availability
0346         information, it also contains internal book keeping information required
0347         for the OPP library to operate on.  Pointer to this structure is
0348         provided back to the users such as SoC framework to be used as a
0349         identifier for OPP in the interactions with OPP layer.
0350 
0351         WARNING:
0352           The struct dev_pm_opp pointer should not be parsed or modified by the
0353           users. The defaults of for an instance is populated by
0354           dev_pm_opp_add, but the availability of the OPP can be modified
0355           by dev_pm_opp_enable/disable functions.
0356 
0357 struct device
0358         This is used to identify a domain to the OPP layer. The
0359         nature of the device and its implementation is left to the user of
0360         OPP library such as the SoC framework.
0361 
0362 Overall, in a simplistic view, the data structure operations is represented as
0363 following::
0364 
0365   Initialization / modification:
0366               +-----+        /- dev_pm_opp_enable
0367   dev_pm_opp_add --> | opp | <-------
0368     |         +-----+        \- dev_pm_opp_disable
0369     \-------> domain_info(device)
0370 
0371   Search functions:
0372                /-- dev_pm_opp_find_freq_ceil  ---\   +-----+
0373   domain_info<---- dev_pm_opp_find_freq_exact -----> | opp |
0374                \-- dev_pm_opp_find_freq_floor ---/   +-----+
0375 
0376   Retrieval functions:
0377   +-----+     /- dev_pm_opp_get_voltage
0378   | opp | <---
0379   +-----+     \- dev_pm_opp_get_freq
0380 
0381   domain_info <- dev_pm_opp_get_opp_count