aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2010-07-26 18:34:34 -0400
committerPaul Walmsley <paul@pwsan.com>2010-07-26 18:34:34 -0400
commitfb8ce14c7e16bd218decb3e1655c5d4ff08042f2 (patch)
tree238f82e09f459654b99bac48771abdb10885936b /arch/arm/plat-omap
parent564889c1c02698d66db76764ee4e0a5e86903971 (diff)
OMAP: PM constraints: add omap_pm_set_min_clk_rate()
Add omap_pm_set_min_clk_rate(). This constraint is meant for use by device drivers to translate a certain device-specific performance constraint (e.g., "minimum polygons per second") to a clock rate for the driver's device, given the driver's intimate knowledge of the device hardware (e.g., device type, device hardware revision, firmware revision, etc.) From a general PM core perspective, clock rate is probably the closest general analog to "performance" that is available, but the exact mapping from a use-case-specific performance constraint to clock rate must be done by the driver. Drivers intended for upstream merging shouldn't hardcode specific clock rates in their code without basing those rates on some performance criteria requested through the driver's subsystem (ideally, from userspace). Imre Deak <imre.deak@nokia.com> described the need and use-case for this constraint, and discussed the implementation - thanks, Imre. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Imre Deak <imre.deak@nokia.com>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/include/plat/omap-pm.h61
-rw-r--r--arch/arm/plat-omap/omap-pm-noop.c27
2 files changed, 88 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 3d468bafe918..728fbb9dd549 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -16,6 +16,7 @@
16 16
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/cpufreq.h> 18#include <linux/cpufreq.h>
19#include <linux/clk.h>
19 20
20#include "powerdomain.h" 21#include "powerdomain.h"
21 22
@@ -212,6 +213,66 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
212int omap_pm_set_max_sdma_lat(struct device *dev, long t); 213int omap_pm_set_max_sdma_lat(struct device *dev, long t);
213 214
214 215
216/**
217 * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev
218 * @dev: struct device * requesting the constraint
219 * @clk: struct clk * to set the minimum rate constraint on
220 * @r: minimum rate in Hz
221 *
222 * Request that the minimum clock rate on the device @dev's clk @clk
223 * be no less than @r Hz.
224 *
225 * It is expected that the OMAP PM code will use this information to
226 * find an OPP or clock setting that will satisfy this clock rate
227 * constraint, along with any other applicable system constraints on
228 * the clock rate or corresponding voltage, etc.
229 *
230 * omap_pm_set_min_clk_rate() differs from the clock code's
231 * clk_set_rate() in that it considers other constraints before taking
232 * any hardware action, and may change a system OPP rather than just a
233 * clock rate. clk_set_rate() is intended to be a low-level
234 * interface.
235 *
236 * omap_pm_set_min_clk_rate() is easily open to abuse. A better API
237 * would be something like "omap_pm_set_min_dev_performance()";
238 * however, there is no easily-generalizable concept of performance
239 * that applies to all devices. Only a device (and possibly the
240 * device subsystem) has both the subsystem-specific knowledge, and
241 * the hardware IP block-specific knowledge, to translate a constraint
242 * on "touchscreen sampling accuracy" or "number of pixels or polygons
243 * rendered per second" to a clock rate. This translation can be
244 * dependent on the hardware IP block's revision, or firmware version,
245 * and the driver is the only code on the system that has this
246 * information and can know how to translate that into a clock rate.
247 *
248 * The intended use-case for this function is for userspace or other
249 * kernel code to communicate a particular performance requirement to
250 * a subsystem; then for the subsystem to communicate that requirement
251 * to something that is meaningful to the device driver; then for the
252 * device driver to convert that requirement to a clock rate, and to
253 * then call omap_pm_set_min_clk_rate().
254 *
255 * Users of this function (such as device drivers) should not simply
256 * call this function with some high clock rate to ensure "high
257 * performance." Rather, the device driver should take a performance
258 * constraint from its subsystem, such as "render at least X polygons
259 * per second," and use some formula or table to convert that into a
260 * clock rate constraint given the hardware type and hardware
261 * revision. Device drivers or subsystems should not assume that they
262 * know how to make a power/performance tradeoff - some device use
263 * cases may tolerate a lower-fidelity device function for lower power
264 * consumption; others may demand a higher-fidelity device function,
265 * no matter what the power consumption.
266 *
267 * Multiple calls to omap_pm_set_min_clk_rate() will replace the
268 * previous rate value for the device @dev. To remove the minimum clock
269 * rate constraint for the device, call with r = 0.
270 *
271 * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
272 * is not satisfiable, or 0 upon success.
273 */
274int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r);
275
215/* 276/*
216 * DSP Bridge-specific constraints 277 * DSP Bridge-specific constraints
217 */ 278 */
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index b0414f90c6e3..e129ce80c53b 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -149,6 +149,33 @@ int omap_pm_set_max_sdma_lat(struct device *dev, long t)
149 return 0; 149 return 0;
150} 150}
151 151
152int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r)
153{
154 if (!dev || !c || r < 0) {
155 WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
156 return -EINVAL;
157 }
158
159 if (r == 0)
160 pr_debug("OMAP PM: remove min clk rate constraint: "
161 "dev %s\n", dev_name(dev));
162 else
163 pr_debug("OMAP PM: add min clk rate constraint: "
164 "dev %s, rate = %ld Hz\n", dev_name(dev), r);
165
166 /*
167 * Code in a real implementation should keep track of these
168 * constraints on the clock, and determine the highest minimum
169 * clock rate. It should iterate over each OPP and determine
170 * whether the OPP will result in a clock rate that would
171 * satisfy this constraint (and any other PM constraint in effect
172 * at that time). Once it finds the lowest-voltage OPP that
173 * meets those conditions, it should switch to it, or return
174 * an error if the code is not capable of doing so.
175 */
176
177 return 0;
178}
152 179
153/* 180/*
154 * DSP Bridge-specific constraints 181 * DSP Bridge-specific constraints