xref: /linux/Documentation/power/opp.rst (revision 9ac3ebae)
1151f4e2bSMauro Carvalho Chehab==========================================
2151f4e2bSMauro Carvalho ChehabOperating Performance Points (OPP) Library
3151f4e2bSMauro Carvalho Chehab==========================================
4151f4e2bSMauro Carvalho Chehab
5151f4e2bSMauro Carvalho Chehab(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
6151f4e2bSMauro Carvalho Chehab
7151f4e2bSMauro Carvalho Chehab.. Contents
8151f4e2bSMauro Carvalho Chehab
9151f4e2bSMauro Carvalho Chehab  1. Introduction
10151f4e2bSMauro Carvalho Chehab  2. Initial OPP List Registration
11151f4e2bSMauro Carvalho Chehab  3. OPP Search Functions
12151f4e2bSMauro Carvalho Chehab  4. OPP Availability Control Functions
13151f4e2bSMauro Carvalho Chehab  5. OPP Data Retrieval Functions
14151f4e2bSMauro Carvalho Chehab  6. Data Structures
15151f4e2bSMauro Carvalho Chehab
16151f4e2bSMauro Carvalho Chehab1. Introduction
17151f4e2bSMauro Carvalho Chehab===============
18151f4e2bSMauro Carvalho Chehab
19151f4e2bSMauro Carvalho Chehab1.1 What is an Operating Performance Point (OPP)?
20151f4e2bSMauro Carvalho Chehab-------------------------------------------------
21151f4e2bSMauro Carvalho Chehab
22151f4e2bSMauro Carvalho ChehabComplex SoCs of today consists of a multiple sub-modules working in conjunction.
23151f4e2bSMauro Carvalho ChehabIn an operational system executing varied use cases, not all modules in the SoC
24151f4e2bSMauro Carvalho Chehabneed to function at their highest performing frequency all the time. To
25151f4e2bSMauro Carvalho Chehabfacilitate this, sub-modules in a SoC are grouped into domains, allowing some
26151f4e2bSMauro Carvalho Chehabdomains to run at lower voltage and frequency while other domains run at
27151f4e2bSMauro Carvalho Chehabvoltage/frequency pairs that are higher.
28151f4e2bSMauro Carvalho Chehab
29151f4e2bSMauro Carvalho ChehabThe set of discrete tuples consisting of frequency and voltage pairs that
30151f4e2bSMauro Carvalho Chehabthe device will support per domain are called Operating Performance Points or
31151f4e2bSMauro Carvalho ChehabOPPs.
32151f4e2bSMauro Carvalho Chehab
33151f4e2bSMauro Carvalho ChehabAs an example:
34151f4e2bSMauro Carvalho Chehab
35151f4e2bSMauro Carvalho ChehabLet us consider an MPU device which supports the following:
36151f4e2bSMauro Carvalho Chehab{300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V},
37151f4e2bSMauro Carvalho Chehab{1GHz at minimum voltage of 1.3V}
38151f4e2bSMauro Carvalho Chehab
39151f4e2bSMauro Carvalho ChehabWe can represent these as three OPPs as the following {Hz, uV} tuples:
40151f4e2bSMauro Carvalho Chehab
41151f4e2bSMauro Carvalho Chehab- {300000000, 1000000}
42151f4e2bSMauro Carvalho Chehab- {800000000, 1200000}
43151f4e2bSMauro Carvalho Chehab- {1000000000, 1300000}
44151f4e2bSMauro Carvalho Chehab
45151f4e2bSMauro Carvalho Chehab1.2 Operating Performance Points Library
46151f4e2bSMauro Carvalho Chehab----------------------------------------
47151f4e2bSMauro Carvalho Chehab
48151f4e2bSMauro Carvalho ChehabOPP library provides a set of helper functions to organize and query the OPP
4927a84f76SYue Huinformation. The library is located in drivers/opp/ directory and the header
50151f4e2bSMauro Carvalho Chehabis located in include/linux/pm_opp.h. OPP library can be enabled by enabling
51489a00efSTang YizhouCONFIG_PM_OPP from power management menuconfig menu. Certain SoCs such as Texas
52489a00efSTang YizhouInstrument's OMAP framework allows to optionally boot at a certain OPP without
53489a00efSTang Yizhouneeding cpufreq.
54151f4e2bSMauro Carvalho Chehab
55151f4e2bSMauro Carvalho ChehabTypical usage of the OPP library is as follows::
56151f4e2bSMauro Carvalho Chehab
57151f4e2bSMauro Carvalho Chehab (users)	-> registers a set of default OPPs		-> (library)
58151f4e2bSMauro Carvalho Chehab SoC framework	-> modifies on required cases certain OPPs	-> OPP layer
59151f4e2bSMauro Carvalho Chehab		-> queries to search/retrieve information	->
60151f4e2bSMauro Carvalho Chehab
61151f4e2bSMauro Carvalho ChehabOPP layer expects each domain to be represented by a unique device pointer. SoC
62151f4e2bSMauro Carvalho Chehabframework registers a set of initial OPPs per device with the OPP layer. This
63151f4e2bSMauro Carvalho Chehablist is expected to be an optimally small number typically around 5 per device.
64151f4e2bSMauro Carvalho ChehabThis initial list contains a set of OPPs that the framework expects to be safely
65151f4e2bSMauro Carvalho Chehabenabled by default in the system.
66151f4e2bSMauro Carvalho Chehab
67151f4e2bSMauro Carvalho ChehabNote on OPP Availability
68151f4e2bSMauro Carvalho Chehab^^^^^^^^^^^^^^^^^^^^^^^^
69151f4e2bSMauro Carvalho Chehab
70151f4e2bSMauro Carvalho ChehabAs the system proceeds to operate, SoC framework may choose to make certain
71151f4e2bSMauro Carvalho ChehabOPPs available or not available on each device based on various external
72151f4e2bSMauro Carvalho Chehabfactors. Example usage: Thermal management or other exceptional situations where
73151f4e2bSMauro Carvalho ChehabSoC framework might choose to disable a higher frequency OPP to safely continue
74151f4e2bSMauro Carvalho Chehaboperations until that OPP could be re-enabled if possible.
75151f4e2bSMauro Carvalho Chehab
761992b66dSBjorn HelgaasOPP library facilitates this concept in its implementation. The following
77151f4e2bSMauro Carvalho Chehaboperational functions operate only on available opps:
78489a00efSTang Yizhoudev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq,
79489a00efSTang Yizhoudev_pm_opp_get_opp_count.
80151f4e2bSMauro Carvalho Chehab
811992b66dSBjorn Helgaasdev_pm_opp_find_freq_exact is meant to be used to find the opp pointer
821992b66dSBjorn Helgaaswhich can then be used for dev_pm_opp_enable/disable functions to make an
831992b66dSBjorn Helgaasopp available as required.
84151f4e2bSMauro Carvalho Chehab
85151f4e2bSMauro Carvalho ChehabWARNING: Users of OPP library should refresh their availability count using
861992b66dSBjorn Helgaasget_opp_count if dev_pm_opp_enable/disable functions are invoked for a
871992b66dSBjorn Helgaasdevice, the exact mechanism to trigger these or the notification mechanism
881992b66dSBjorn Helgaasto other dependent subsystems such as cpufreq are left to the discretion of
891992b66dSBjorn Helgaasthe SoC specific framework which uses the OPP library. Similar care needs
901992b66dSBjorn Helgaasto be taken care to refresh the cpufreq table in cases of these operations.
91151f4e2bSMauro Carvalho Chehab
92151f4e2bSMauro Carvalho Chehab2. Initial OPP List Registration
93151f4e2bSMauro Carvalho Chehab================================
94151f4e2bSMauro Carvalho ChehabThe SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per
95151f4e2bSMauro Carvalho Chehabdevice. It is expected that the SoC framework will register the OPP entries
96151f4e2bSMauro Carvalho Chehaboptimally- typical numbers range to be less than 5. The list generated by
97151f4e2bSMauro Carvalho Chehabregistering the OPPs is maintained by OPP library throughout the device
98151f4e2bSMauro Carvalho Chehaboperation. The SoC framework can subsequently control the availability of the
99151f4e2bSMauro Carvalho ChehabOPPs dynamically using the dev_pm_opp_enable / disable functions.
100151f4e2bSMauro Carvalho Chehab
101151f4e2bSMauro Carvalho Chehabdev_pm_opp_add
102151f4e2bSMauro Carvalho Chehab	Add a new OPP for a specific domain represented by the device pointer.
103151f4e2bSMauro Carvalho Chehab	The OPP is defined using the frequency and voltage. Once added, the OPP
1041992b66dSBjorn Helgaas	is assumed to be available and control of its availability can be done
1051992b66dSBjorn Helgaas	with the dev_pm_opp_enable/disable functions. OPP library
106489a00efSTang Yizhou	internally stores and manages this information in the dev_pm_opp struct.
1071992b66dSBjorn Helgaas	This function may be used by SoC framework to define a optimal list
1081992b66dSBjorn Helgaas	as per the demands of SoC usage environment.
109151f4e2bSMauro Carvalho Chehab
110151f4e2bSMauro Carvalho Chehab	WARNING:
111151f4e2bSMauro Carvalho Chehab		Do not use this function in interrupt context.
112151f4e2bSMauro Carvalho Chehab
113151f4e2bSMauro Carvalho Chehab	Example::
114151f4e2bSMauro Carvalho Chehab
115151f4e2bSMauro Carvalho Chehab	 soc_pm_init()
116151f4e2bSMauro Carvalho Chehab	 {
117151f4e2bSMauro Carvalho Chehab		/* Do things */
118151f4e2bSMauro Carvalho Chehab		r = dev_pm_opp_add(mpu_dev, 1000000, 900000);
119151f4e2bSMauro Carvalho Chehab		if (!r) {
120151f4e2bSMauro Carvalho Chehab			pr_err("%s: unable to register mpu opp(%d)\n", r);
121151f4e2bSMauro Carvalho Chehab			goto no_cpufreq;
122151f4e2bSMauro Carvalho Chehab		}
123151f4e2bSMauro Carvalho Chehab		/* Do cpufreq things */
124151f4e2bSMauro Carvalho Chehab	 no_cpufreq:
125151f4e2bSMauro Carvalho Chehab		/* Do remaining things */
126151f4e2bSMauro Carvalho Chehab	 }
127151f4e2bSMauro Carvalho Chehab
128151f4e2bSMauro Carvalho Chehab3. OPP Search Functions
129151f4e2bSMauro Carvalho Chehab=======================
130151f4e2bSMauro Carvalho ChehabHigh level framework such as cpufreq operates on frequencies. To map the
131151f4e2bSMauro Carvalho Chehabfrequency back to the corresponding OPP, OPP library provides handy functions
132151f4e2bSMauro Carvalho Chehabto search the OPP list that OPP library internally manages. These search
133151f4e2bSMauro Carvalho Chehabfunctions return the matching pointer representing the opp if a match is
134151f4e2bSMauro Carvalho Chehabfound, else returns error. These errors are expected to be handled by standard
135151f4e2bSMauro Carvalho Chehaberror checks such as IS_ERR() and appropriate actions taken by the caller.
136151f4e2bSMauro Carvalho Chehab
137151f4e2bSMauro Carvalho ChehabCallers of these functions shall call dev_pm_opp_put() after they have used the
138151f4e2bSMauro Carvalho ChehabOPP. Otherwise the memory for the OPP will never get freed and result in
139151f4e2bSMauro Carvalho Chehabmemleak.
140151f4e2bSMauro Carvalho Chehab
141151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_exact
142151f4e2bSMauro Carvalho Chehab	Search for an OPP based on an *exact* frequency and
143151f4e2bSMauro Carvalho Chehab	availability. This function is especially useful to enable an OPP which
144151f4e2bSMauro Carvalho Chehab	is not available by default.
145151f4e2bSMauro Carvalho Chehab	Example: In a case when SoC framework detects a situation where a
146151f4e2bSMauro Carvalho Chehab	higher frequency could be made available, it can use this function to
147151f4e2bSMauro Carvalho Chehab	find the OPP prior to call the dev_pm_opp_enable to actually make
148151f4e2bSMauro Carvalho Chehab	it available::
149151f4e2bSMauro Carvalho Chehab
150151f4e2bSMauro Carvalho Chehab	 opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
151151f4e2bSMauro Carvalho Chehab	 dev_pm_opp_put(opp);
152151f4e2bSMauro Carvalho Chehab	 /* dont operate on the pointer.. just do a sanity check.. */
153151f4e2bSMauro Carvalho Chehab	 if (IS_ERR(opp)) {
154151f4e2bSMauro Carvalho Chehab		pr_err("frequency not disabled!\n");
155151f4e2bSMauro Carvalho Chehab		/* trigger appropriate actions.. */
156151f4e2bSMauro Carvalho Chehab	 } else {
157151f4e2bSMauro Carvalho Chehab		dev_pm_opp_enable(dev,1000000000);
158151f4e2bSMauro Carvalho Chehab	 }
159151f4e2bSMauro Carvalho Chehab
160151f4e2bSMauro Carvalho Chehab	NOTE:
161151f4e2bSMauro Carvalho Chehab	  This is the only search function that operates on OPPs which are
162151f4e2bSMauro Carvalho Chehab	  not available.
163151f4e2bSMauro Carvalho Chehab
164151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_floor
165151f4e2bSMauro Carvalho Chehab	Search for an available OPP which is *at most* the
166151f4e2bSMauro Carvalho Chehab	provided frequency. This function is useful while searching for a lesser
167151f4e2bSMauro Carvalho Chehab	match OR operating on OPP information in the order of decreasing
168151f4e2bSMauro Carvalho Chehab	frequency.
169151f4e2bSMauro Carvalho Chehab	Example: To find the highest opp for a device::
170151f4e2bSMauro Carvalho Chehab
171151f4e2bSMauro Carvalho Chehab	 freq = ULONG_MAX;
172151f4e2bSMauro Carvalho Chehab	 opp = dev_pm_opp_find_freq_floor(dev, &freq);
173151f4e2bSMauro Carvalho Chehab	 dev_pm_opp_put(opp);
174151f4e2bSMauro Carvalho Chehab
175151f4e2bSMauro Carvalho Chehabdev_pm_opp_find_freq_ceil
176151f4e2bSMauro Carvalho Chehab	Search for an available OPP which is *at least* the
177151f4e2bSMauro Carvalho Chehab	provided frequency. This function is useful while searching for a
178151f4e2bSMauro Carvalho Chehab	higher match OR operating on OPP information in the order of increasing
179151f4e2bSMauro Carvalho Chehab	frequency.
180151f4e2bSMauro Carvalho Chehab	Example 1: To find the lowest opp for a device::
181151f4e2bSMauro Carvalho Chehab
182151f4e2bSMauro Carvalho Chehab	 freq = 0;
183151f4e2bSMauro Carvalho Chehab	 opp = dev_pm_opp_find_freq_ceil(dev, &freq);
184151f4e2bSMauro Carvalho Chehab	 dev_pm_opp_put(opp);
185151f4e2bSMauro Carvalho Chehab
186151f4e2bSMauro Carvalho Chehab	Example 2: A simplified implementation of a SoC cpufreq_driver->target::
187151f4e2bSMauro Carvalho Chehab
188151f4e2bSMauro Carvalho Chehab	 soc_cpufreq_target(..)
189151f4e2bSMauro Carvalho Chehab	 {
190151f4e2bSMauro Carvalho Chehab		/* Do stuff like policy checks etc. */
191151f4e2bSMauro Carvalho Chehab		/* Find the best frequency match for the req */
192151f4e2bSMauro Carvalho Chehab		opp = dev_pm_opp_find_freq_ceil(dev, &freq);
193151f4e2bSMauro Carvalho Chehab		dev_pm_opp_put(opp);
194151f4e2bSMauro Carvalho Chehab		if (!IS_ERR(opp))
195151f4e2bSMauro Carvalho Chehab			soc_switch_to_freq_voltage(freq);
196151f4e2bSMauro Carvalho Chehab		else
197151f4e2bSMauro Carvalho Chehab			/* do something when we can't satisfy the req */
198151f4e2bSMauro Carvalho Chehab		/* do other stuff */
199151f4e2bSMauro Carvalho Chehab	 }
200151f4e2bSMauro Carvalho Chehab
201151f4e2bSMauro Carvalho Chehab4. OPP Availability Control Functions
202151f4e2bSMauro Carvalho Chehab=====================================
203151f4e2bSMauro Carvalho ChehabA default OPP list registered with the OPP library may not cater to all possible
204151f4e2bSMauro Carvalho Chehabsituation. The OPP library provides a set of functions to modify the
205151f4e2bSMauro Carvalho Chehabavailability of a OPP within the OPP list. This allows SoC frameworks to have
206151f4e2bSMauro Carvalho Chehabfine grained dynamic control of which sets of OPPs are operationally available.
207151f4e2bSMauro Carvalho ChehabThese functions are intended to *temporarily* remove an OPP in conditions such
208151f4e2bSMauro Carvalho Chehabas thermal considerations (e.g. don't use OPPx until the temperature drops).
209151f4e2bSMauro Carvalho Chehab
210151f4e2bSMauro Carvalho ChehabWARNING:
211151f4e2bSMauro Carvalho Chehab	Do not use these functions in interrupt context.
212151f4e2bSMauro Carvalho Chehab
213151f4e2bSMauro Carvalho Chehabdev_pm_opp_enable
214151f4e2bSMauro Carvalho Chehab	Make a OPP available for operation.
215151f4e2bSMauro Carvalho Chehab	Example: Lets say that 1GHz OPP is to be made available only if the
216151f4e2bSMauro Carvalho Chehab	SoC temperature is lower than a certain threshold. The SoC framework
217151f4e2bSMauro Carvalho Chehab	implementation might choose to do something as follows::
218151f4e2bSMauro Carvalho Chehab
219151f4e2bSMauro Carvalho Chehab	 if (cur_temp < temp_low_thresh) {
220151f4e2bSMauro Carvalho Chehab		/* Enable 1GHz if it was disabled */
221151f4e2bSMauro Carvalho Chehab		opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
222151f4e2bSMauro Carvalho Chehab		dev_pm_opp_put(opp);
223151f4e2bSMauro Carvalho Chehab		/* just error check */
224151f4e2bSMauro Carvalho Chehab		if (!IS_ERR(opp))
225151f4e2bSMauro Carvalho Chehab			ret = dev_pm_opp_enable(dev, 1000000000);
226151f4e2bSMauro Carvalho Chehab		else
227151f4e2bSMauro Carvalho Chehab			goto try_something_else;
228151f4e2bSMauro Carvalho Chehab	 }
229151f4e2bSMauro Carvalho Chehab
230151f4e2bSMauro Carvalho Chehabdev_pm_opp_disable
231151f4e2bSMauro Carvalho Chehab	Make an OPP to be not available for operation
232151f4e2bSMauro Carvalho Chehab	Example: Lets say that 1GHz OPP is to be disabled if the temperature
233151f4e2bSMauro Carvalho Chehab	exceeds a threshold value. The SoC framework implementation might
234151f4e2bSMauro Carvalho Chehab	choose to do something as follows::
235151f4e2bSMauro Carvalho Chehab
236151f4e2bSMauro Carvalho Chehab	 if (cur_temp > temp_high_thresh) {
237151f4e2bSMauro Carvalho Chehab		/* Disable 1GHz if it was enabled */
238151f4e2bSMauro Carvalho Chehab		opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true);
239151f4e2bSMauro Carvalho Chehab		dev_pm_opp_put(opp);
240151f4e2bSMauro Carvalho Chehab		/* just error check */
241151f4e2bSMauro Carvalho Chehab		if (!IS_ERR(opp))
242151f4e2bSMauro Carvalho Chehab			ret = dev_pm_opp_disable(dev, 1000000000);
243151f4e2bSMauro Carvalho Chehab		else
244151f4e2bSMauro Carvalho Chehab			goto try_something_else;
245151f4e2bSMauro Carvalho Chehab	 }
246151f4e2bSMauro Carvalho Chehab
247151f4e2bSMauro Carvalho Chehab5. OPP Data Retrieval Functions
248151f4e2bSMauro Carvalho Chehab===============================
249151f4e2bSMauro Carvalho ChehabSince OPP library abstracts away the OPP information, a set of functions to pull
250489a00efSTang Yizhouinformation from the dev_pm_opp structure is necessary. Once an OPP pointer is
251151f4e2bSMauro Carvalho Chehabretrieved using the search functions, the following functions can be used by SoC
252151f4e2bSMauro Carvalho Chehabframework to retrieve the information represented inside the OPP layer.
253151f4e2bSMauro Carvalho Chehab
254151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_voltage
255151f4e2bSMauro Carvalho Chehab	Retrieve the voltage represented by the opp pointer.
256151f4e2bSMauro Carvalho Chehab	Example: At a cpufreq transition to a different frequency, SoC
257151f4e2bSMauro Carvalho Chehab	framework requires to set the voltage represented by the OPP using
258151f4e2bSMauro Carvalho Chehab	the regulator framework to the Power Management chip providing the
259151f4e2bSMauro Carvalho Chehab	voltage::
260151f4e2bSMauro Carvalho Chehab
261151f4e2bSMauro Carvalho Chehab	 soc_switch_to_freq_voltage(freq)
262151f4e2bSMauro Carvalho Chehab	 {
263151f4e2bSMauro Carvalho Chehab		/* do things */
264151f4e2bSMauro Carvalho Chehab		opp = dev_pm_opp_find_freq_ceil(dev, &freq);
265151f4e2bSMauro Carvalho Chehab		v = dev_pm_opp_get_voltage(opp);
266151f4e2bSMauro Carvalho Chehab		dev_pm_opp_put(opp);
267151f4e2bSMauro Carvalho Chehab		if (v)
268151f4e2bSMauro Carvalho Chehab			regulator_set_voltage(.., v);
269151f4e2bSMauro Carvalho Chehab		/* do other things */
270151f4e2bSMauro Carvalho Chehab	 }
271151f4e2bSMauro Carvalho Chehab
272151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_freq
273151f4e2bSMauro Carvalho Chehab	Retrieve the freq represented by the opp pointer.
274151f4e2bSMauro Carvalho Chehab	Example: Lets say the SoC framework uses a couple of helper functions
275151f4e2bSMauro Carvalho Chehab	we could pass opp pointers instead of doing additional parameters to
276151f4e2bSMauro Carvalho Chehab	handle quiet a bit of data parameters::
277151f4e2bSMauro Carvalho Chehab
278151f4e2bSMauro Carvalho Chehab	 soc_cpufreq_target(..)
279151f4e2bSMauro Carvalho Chehab	 {
280151f4e2bSMauro Carvalho Chehab		/* do things.. */
281151f4e2bSMauro Carvalho Chehab		 max_freq = ULONG_MAX;
282151f4e2bSMauro Carvalho Chehab		 max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq);
283151f4e2bSMauro Carvalho Chehab		 requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq);
284151f4e2bSMauro Carvalho Chehab		 if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
285151f4e2bSMauro Carvalho Chehab			r = soc_test_validity(max_opp, requested_opp);
286151f4e2bSMauro Carvalho Chehab		 dev_pm_opp_put(max_opp);
287151f4e2bSMauro Carvalho Chehab		 dev_pm_opp_put(requested_opp);
288151f4e2bSMauro Carvalho Chehab		/* do other things */
289151f4e2bSMauro Carvalho Chehab	 }
290151f4e2bSMauro Carvalho Chehab	 soc_test_validity(..)
291151f4e2bSMauro Carvalho Chehab	 {
292151f4e2bSMauro Carvalho Chehab		 if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp))
293151f4e2bSMauro Carvalho Chehab			 return -EINVAL;
294151f4e2bSMauro Carvalho Chehab		 if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp))
295151f4e2bSMauro Carvalho Chehab			 return -EINVAL;
296151f4e2bSMauro Carvalho Chehab		/* do things.. */
297151f4e2bSMauro Carvalho Chehab	 }
298151f4e2bSMauro Carvalho Chehab
299151f4e2bSMauro Carvalho Chehabdev_pm_opp_get_opp_count
300151f4e2bSMauro Carvalho Chehab	Retrieve the number of available opps for a device
301151f4e2bSMauro Carvalho Chehab	Example: Lets say a co-processor in the SoC needs to know the available
302151f4e2bSMauro Carvalho Chehab	frequencies in a table, the main processor can notify as following::
303151f4e2bSMauro Carvalho Chehab
304151f4e2bSMauro Carvalho Chehab	 soc_notify_coproc_available_frequencies()
305151f4e2bSMauro Carvalho Chehab	 {
306151f4e2bSMauro Carvalho Chehab		/* Do things */
307151f4e2bSMauro Carvalho Chehab		num_available = dev_pm_opp_get_opp_count(dev);
308*9ac3ebaeSErick Archer		speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL);
309151f4e2bSMauro Carvalho Chehab		/* populate the table in increasing order */
310151f4e2bSMauro Carvalho Chehab		freq = 0;
311151f4e2bSMauro Carvalho Chehab		while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) {
312151f4e2bSMauro Carvalho Chehab			speeds[i] = freq;
313151f4e2bSMauro Carvalho Chehab			freq++;
314151f4e2bSMauro Carvalho Chehab			i++;
315151f4e2bSMauro Carvalho Chehab			dev_pm_opp_put(opp);
316151f4e2bSMauro Carvalho Chehab		}
317151f4e2bSMauro Carvalho Chehab
318151f4e2bSMauro Carvalho Chehab		soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
319151f4e2bSMauro Carvalho Chehab		/* Do other things */
320151f4e2bSMauro Carvalho Chehab	 }
321151f4e2bSMauro Carvalho Chehab
322151f4e2bSMauro Carvalho Chehab6. Data Structures
323151f4e2bSMauro Carvalho Chehab==================
324151f4e2bSMauro Carvalho ChehabTypically an SoC contains multiple voltage domains which are variable. Each
325151f4e2bSMauro Carvalho Chehabdomain is represented by a device pointer. The relationship to OPP can be
326151f4e2bSMauro Carvalho Chehabrepresented as follows::
327151f4e2bSMauro Carvalho Chehab
328151f4e2bSMauro Carvalho Chehab  SoC
329151f4e2bSMauro Carvalho Chehab   |- device 1
330151f4e2bSMauro Carvalho Chehab   |	|- opp 1 (availability, freq, voltage)
331151f4e2bSMauro Carvalho Chehab   |	|- opp 2 ..
332151f4e2bSMauro Carvalho Chehab   ...	...
333151f4e2bSMauro Carvalho Chehab   |	`- opp n ..
334151f4e2bSMauro Carvalho Chehab   |- device 2
335151f4e2bSMauro Carvalho Chehab   ...
336151f4e2bSMauro Carvalho Chehab   `- device m
337151f4e2bSMauro Carvalho Chehab
338151f4e2bSMauro Carvalho ChehabOPP library maintains a internal list that the SoC framework populates and
339151f4e2bSMauro Carvalho Chehabaccessed by various functions as described above. However, the structures
340151f4e2bSMauro Carvalho Chehabrepresenting the actual OPPs and domains are internal to the OPP library itself
341151f4e2bSMauro Carvalho Chehabto allow for suitable abstraction reusable across systems.
342151f4e2bSMauro Carvalho Chehab
343151f4e2bSMauro Carvalho Chehabstruct dev_pm_opp
344151f4e2bSMauro Carvalho Chehab	The internal data structure of OPP library which is used to
345151f4e2bSMauro Carvalho Chehab	represent an OPP. In addition to the freq, voltage, availability
346151f4e2bSMauro Carvalho Chehab	information, it also contains internal book keeping information required
347151f4e2bSMauro Carvalho Chehab	for the OPP library to operate on.  Pointer to this structure is
348151f4e2bSMauro Carvalho Chehab	provided back to the users such as SoC framework to be used as a
349151f4e2bSMauro Carvalho Chehab	identifier for OPP in the interactions with OPP layer.
350151f4e2bSMauro Carvalho Chehab
351151f4e2bSMauro Carvalho Chehab	WARNING:
352151f4e2bSMauro Carvalho Chehab	  The struct dev_pm_opp pointer should not be parsed or modified by the
353151f4e2bSMauro Carvalho Chehab	  users. The defaults of for an instance is populated by
354151f4e2bSMauro Carvalho Chehab	  dev_pm_opp_add, but the availability of the OPP can be modified
355151f4e2bSMauro Carvalho Chehab	  by dev_pm_opp_enable/disable functions.
356151f4e2bSMauro Carvalho Chehab
357151f4e2bSMauro Carvalho Chehabstruct device
358151f4e2bSMauro Carvalho Chehab	This is used to identify a domain to the OPP layer. The
3591992b66dSBjorn Helgaas	nature of the device and its implementation is left to the user of
360151f4e2bSMauro Carvalho Chehab	OPP library such as the SoC framework.
361151f4e2bSMauro Carvalho Chehab
362151f4e2bSMauro Carvalho ChehabOverall, in a simplistic view, the data structure operations is represented as
363151f4e2bSMauro Carvalho Chehabfollowing::
364151f4e2bSMauro Carvalho Chehab
365151f4e2bSMauro Carvalho Chehab  Initialization / modification:
366151f4e2bSMauro Carvalho Chehab              +-----+        /- dev_pm_opp_enable
367151f4e2bSMauro Carvalho Chehab  dev_pm_opp_add --> | opp | <-------
368151f4e2bSMauro Carvalho Chehab    |         +-----+        \- dev_pm_opp_disable
369151f4e2bSMauro Carvalho Chehab    \-------> domain_info(device)
370151f4e2bSMauro Carvalho Chehab
371151f4e2bSMauro Carvalho Chehab  Search functions:
372151f4e2bSMauro Carvalho Chehab               /-- dev_pm_opp_find_freq_ceil  ---\   +-----+
373151f4e2bSMauro Carvalho Chehab  domain_info<---- dev_pm_opp_find_freq_exact -----> | opp |
374151f4e2bSMauro Carvalho Chehab               \-- dev_pm_opp_find_freq_floor ---/   +-----+
375151f4e2bSMauro Carvalho Chehab
376151f4e2bSMauro Carvalho Chehab  Retrieval functions:
377151f4e2bSMauro Carvalho Chehab  +-----+     /- dev_pm_opp_get_voltage
378151f4e2bSMauro Carvalho Chehab  | opp | <---
379151f4e2bSMauro Carvalho Chehab  +-----+     \- dev_pm_opp_get_freq
380151f4e2bSMauro Carvalho Chehab
381151f4e2bSMauro Carvalho Chehab  domain_info <- dev_pm_opp_get_opp_count
382