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