cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

opp.rst (13991B)


      1==========================================
      2Operating 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
     161. Introduction
     17===============
     18
     191.1 What is an Operating Performance Point (OPP)?
     20-------------------------------------------------
     21
     22Complex SoCs of today consists of a multiple sub-modules working in conjunction.
     23In an operational system executing varied use cases, not all modules in the SoC
     24need to function at their highest performing frequency all the time. To
     25facilitate this, sub-modules in a SoC are grouped into domains, allowing some
     26domains to run at lower voltage and frequency while other domains run at
     27voltage/frequency pairs that are higher.
     28
     29The set of discrete tuples consisting of frequency and voltage pairs that
     30the device will support per domain are called Operating Performance Points or
     31OPPs.
     32
     33As an example:
     34
     35Let 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
     39We can represent these as three OPPs as the following {Hz, uV} tuples:
     40
     41- {300000000, 1000000}
     42- {800000000, 1200000}
     43- {1000000000, 1300000}
     44
     451.2 Operating Performance Points Library
     46----------------------------------------
     47
     48OPP library provides a set of helper functions to organize and query the OPP
     49information. The library is located in drivers/opp/ directory and the header
     50is located in include/linux/pm_opp.h. OPP library can be enabled by enabling
     51CONFIG_PM_OPP from power management menuconfig menu. Certain SoCs such as Texas
     52Instrument's OMAP framework allows to optionally boot at a certain OPP without
     53needing cpufreq.
     54
     55Typical 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
     61OPP layer expects each domain to be represented by a unique device pointer. SoC
     62framework registers a set of initial OPPs per device with the OPP layer. This
     63list is expected to be an optimally small number typically around 5 per device.
     64This initial list contains a set of OPPs that the framework expects to be safely
     65enabled by default in the system.
     66
     67Note on OPP Availability
     68^^^^^^^^^^^^^^^^^^^^^^^^
     69
     70As the system proceeds to operate, SoC framework may choose to make certain
     71OPPs available or not available on each device based on various external
     72factors. Example usage: Thermal management or other exceptional situations where
     73SoC framework might choose to disable a higher frequency OPP to safely continue
     74operations until that OPP could be re-enabled if possible.
     75
     76OPP library facilitates this concept in its implementation. The following
     77operational functions operate only on available opps:
     78dev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq,
     79dev_pm_opp_get_opp_count.
     80
     81dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer
     82which can then be used for dev_pm_opp_enable/disable functions to make an
     83opp available as required.
     84
     85WARNING: Users of OPP library should refresh their availability count using
     86get_opp_count if dev_pm_opp_enable/disable functions are invoked for a
     87device, the exact mechanism to trigger these or the notification mechanism
     88to other dependent subsystems such as cpufreq are left to the discretion of
     89the SoC specific framework which uses the OPP library. Similar care needs
     90to be taken care to refresh the cpufreq table in cases of these operations.
     91
     922. Initial OPP List Registration
     93================================
     94The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per
     95device. It is expected that the SoC framework will register the OPP entries
     96optimally- typical numbers range to be less than 5. The list generated by
     97registering the OPPs is maintained by OPP library throughout the device
     98operation. The SoC framework can subsequently control the availability of the
     99OPPs dynamically using the dev_pm_opp_enable / disable functions.
    100
    101dev_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
    1283. OPP Search Functions
    129=======================
    130High level framework such as cpufreq operates on frequencies. To map the
    131frequency back to the corresponding OPP, OPP library provides handy functions
    132to search the OPP list that OPP library internally manages. These search
    133functions return the matching pointer representing the opp if a match is
    134found, else returns error. These errors are expected to be handled by standard
    135error checks such as IS_ERR() and appropriate actions taken by the caller.
    136
    137Callers of these functions shall call dev_pm_opp_put() after they have used the
    138OPP. Otherwise the memory for the OPP will never get freed and result in
    139memleak.
    140
    141dev_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
    164dev_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
    175dev_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
    2014. OPP Availability Control Functions
    202=====================================
    203A default OPP list registered with the OPP library may not cater to all possible
    204situation. The OPP library provides a set of functions to modify the
    205availability of a OPP within the OPP list. This allows SoC frameworks to have
    206fine grained dynamic control of which sets of OPPs are operationally available.
    207These functions are intended to *temporarily* remove an OPP in conditions such
    208as thermal considerations (e.g. don't use OPPx until the temperature drops).
    209
    210WARNING:
    211	Do not use these functions in interrupt context.
    212
    213dev_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
    230dev_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
    2475. OPP Data Retrieval Functions
    248===============================
    249Since OPP library abstracts away the OPP information, a set of functions to pull
    250information from the dev_pm_opp structure is necessary. Once an OPP pointer is
    251retrieved using the search functions, the following functions can be used by SoC
    252framework to retrieve the information represented inside the OPP layer.
    253
    254dev_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
    272dev_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
    299dev_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 = kzalloc(sizeof(u32) * num_available, 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
    3226. Data Structures
    323==================
    324Typically an SoC contains multiple voltage domains which are variable. Each
    325domain is represented by a device pointer. The relationship to OPP can be
    326represented 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
    338OPP library maintains a internal list that the SoC framework populates and
    339accessed by various functions as described above. However, the structures
    340representing the actual OPPs and domains are internal to the OPP library itself
    341to allow for suitable abstraction reusable across systems.
    342
    343struct 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
    357struct 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
    362Overall, in a simplistic view, the data structure operations is represented as
    363following::
    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