From 564889c1c02698d66db76764ee4e0a5e86903971 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 26 Jul 2010 16:34:34 -0600 Subject: OMAP: PM constraints: add return values; add requesting device param to omap_pm_set_max_dev_wakeup_lat() Add return values to the PM constraint functions. This allows the PM core to provide feedback to the caller if a constraint is not possible. Update the one upstream user of omap_pm_set_max_mpu_wakeup_lat() to add a compatibility wrapper, needed until the driver is changed. Update some of the documentation to conform more closely to kerneldoc style. Add an additional device parameter to omap_pm_set_max_dev_wakeup_lat() to identify the device requesting the constraint. This is so repeated calls to omap_pm_set_max_dev_wakeup_lat() with the same requesting device can override the device's previously-set constraint. Also, it allows the PM core to make a decision as to whether or not the constraint should be satisfied, based on the caller's identity. Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/omap-pm.h | 69 +++++++++++++++++-------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'arch/arm/plat-omap/include/plat/omap-pm.h') diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 3ee41d71149..3d468bafe91 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -1,8 +1,8 @@ /* * omap-pm.h - OMAP power management interface * - * Copyright (C) 2008-2009 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2008-2010 Texas Instruments, Inc. + * Copyright (C) 2008-2010 Nokia Corporation * Paul Walmsley * * Interface developed by (in alphabetical order): Karthik Dasu, Jouni @@ -89,7 +89,7 @@ void omap_pm_if_exit(void); * @t: maximum MPU wakeup latency in microseconds * * Request that the maximum interrupt latency for the MPU to be no - * greater than 't' microseconds. "Interrupt latency" in this case is + * greater than @t microseconds. "Interrupt latency" in this case is * defined as the elapsed time from the occurrence of a hardware or * timer interrupt to the time when the device driver's interrupt * service routine has been entered by the MPU. @@ -105,15 +105,19 @@ void omap_pm_if_exit(void); * elapsed from when a device driver enables a hardware device with * clk_enable(), to when the device is ready for register access or * other use. To control this device wakeup latency, use - * set_max_dev_wakeup_lat() + * omap_pm_set_max_dev_wakeup_lat() * - * Multiple calls to set_max_mpu_wakeup_lat() will replace the + * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the * previous t value. To remove the latency target for the MPU, call * with t = -1. * - * No return value. + * XXX This constraint will be deprecated soon in favor of the more + * general omap_pm_set_max_dev_wakeup_lat() + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); +int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); /** @@ -123,8 +127,8 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); * @r: minimum throughput (in KiB/s) * * Request that the minimum data throughput on the OCP interconnect - * attached to device 'dev' interconnect agent 'tbus_id' be no less - * than 'r' KiB/s. + * attached to device @dev interconnect agent @tbus_id be no less + * than @r KiB/s. * * It is expected that the OMAP PM or bus code will use this * information to set the interconnect clock to run at the lowest @@ -138,40 +142,44 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); * code will also need to add an minimum L3 interconnect speed * constraint, * - * Multiple calls to set_min_bus_tput() will replace the previous rate - * value for this device. To remove the interconnect throughput - * restriction for this device, call with r = 0. + * Multiple calls to omap_pm_set_min_bus_tput() will replace the + * previous rate value for this device. To remove the interconnect + * throughput restriction for this device, call with r = 0. * - * No return value. + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); /** * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency - * @dev: struct device * + * @req_dev: struct device * requesting the constraint, or NULL if none + * @dev: struct device * to set the constraint one * @t: maximum device wakeup latency in microseconds * - * Request that the maximum amount of time necessary for a device to - * become accessible after its clocks are enabled should be no greater - * than 't' microseconds. Specifically, this represents the time from - * when a device driver enables device clocks with clk_enable(), to - * when the register reads and writes on the device will succeed. - * This function should be called before clk_disable() is called, - * since the power state transition decision may be made during - * clk_disable(). + * Request that the maximum amount of time necessary for a device @dev + * to become accessible after its clocks are enabled should be no + * greater than @t microseconds. Specifically, this represents the + * time from when a device driver enables device clocks with + * clk_enable(), to when the register reads and writes on the device + * will succeed. This function should be called before clk_disable() + * is called, since the power state transition decision may be made + * during clk_disable(). * * It is intended that underlying PM code will use this information to * determine what power state to put the powerdomain enclosing this * device into. * - * Multiple calls to set_max_dev_wakeup_lat() will replace the - * previous wakeup latency values for this device. To remove the wakeup - * latency restriction for this device, call with t = -1. + * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the + * previous wakeup latency values for this device. To remove the + * wakeup latency restriction for this device, call with t = -1. * - * No return value. + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t); +int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, + long t); /** @@ -198,9 +206,10 @@ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t); * value for this device. To remove the maximum DMA latency for this * device, call with t = -1. * - * No return value. + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_max_sdma_lat(struct device *dev, long t); +int omap_pm_set_max_sdma_lat(struct device *dev, long t); /* -- cgit v1.2.3 From fb8ce14c7e16bd218decb3e1655c5d4ff08042f2 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 26 Jul 2010 16:34:34 -0600 Subject: 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 described the need and use-case for this constraint, and discussed the implementation - thanks, Imre. Signed-off-by: Paul Walmsley Cc: Imre Deak --- arch/arm/plat-omap/include/plat/omap-pm.h | 61 +++++++++++++++++++++++++++++++ arch/arm/plat-omap/omap-pm-noop.c | 27 ++++++++++++++ 2 files changed, 88 insertions(+) (limited to 'arch/arm/plat-omap/include/plat/omap-pm.h') diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 3d468bafe91..728fbb9dd54 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 @@ #include #include +#include #include "powerdomain.h" @@ -212,6 +213,66 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, int omap_pm_set_max_sdma_lat(struct device *dev, long t); +/** + * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev + * @dev: struct device * requesting the constraint + * @clk: struct clk * to set the minimum rate constraint on + * @r: minimum rate in Hz + * + * Request that the minimum clock rate on the device @dev's clk @clk + * be no less than @r Hz. + * + * It is expected that the OMAP PM code will use this information to + * find an OPP or clock setting that will satisfy this clock rate + * constraint, along with any other applicable system constraints on + * the clock rate or corresponding voltage, etc. + * + * omap_pm_set_min_clk_rate() differs from the clock code's + * clk_set_rate() in that it considers other constraints before taking + * any hardware action, and may change a system OPP rather than just a + * clock rate. clk_set_rate() is intended to be a low-level + * interface. + * + * omap_pm_set_min_clk_rate() is easily open to abuse. A better API + * would be something like "omap_pm_set_min_dev_performance()"; + * however, there is no easily-generalizable concept of performance + * that applies to all devices. Only a device (and possibly the + * device subsystem) has both the subsystem-specific knowledge, and + * the hardware IP block-specific knowledge, to translate a constraint + * on "touchscreen sampling accuracy" or "number of pixels or polygons + * rendered per second" to a clock rate. This translation can be + * dependent on the hardware IP block's revision, or firmware version, + * and the driver is the only code on the system that has this + * information and can know how to translate that into a clock rate. + * + * The intended use-case for this function is for userspace or other + * kernel code to communicate a particular performance requirement to + * a subsystem; then for the subsystem to communicate that requirement + * to something that is meaningful to the device driver; then for the + * device driver to convert that requirement to a clock rate, and to + * then call omap_pm_set_min_clk_rate(). + * + * Users of this function (such as device drivers) should not simply + * call this function with some high clock rate to ensure "high + * performance." Rather, the device driver should take a performance + * constraint from its subsystem, such as "render at least X polygons + * per second," and use some formula or table to convert that into a + * clock rate constraint given the hardware type and hardware + * revision. Device drivers or subsystems should not assume that they + * know how to make a power/performance tradeoff - some device use + * cases may tolerate a lower-fidelity device function for lower power + * consumption; others may demand a higher-fidelity device function, + * no matter what the power consumption. + * + * Multiple calls to omap_pm_set_min_clk_rate() will replace the + * previous rate value for the device @dev. To remove the minimum clock + * rate constraint for the device, call with r = 0. + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r); + /* * DSP Bridge-specific constraints */ diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index b0414f90c6e..e129ce80c53 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) return 0; } +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) +{ + if (!dev || !c || r < 0) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + } + + if (r == 0) + pr_debug("OMAP PM: remove min clk rate constraint: " + "dev %s\n", dev_name(dev)); + else + pr_debug("OMAP PM: add min clk rate constraint: " + "dev %s, rate = %ld Hz\n", dev_name(dev), r); + + /* + * Code in a real implementation should keep track of these + * constraints on the clock, and determine the highest minimum + * clock rate. It should iterate over each OPP and determine + * whether the OPP will result in a clock rate that would + * satisfy this constraint (and any other PM constraint in effect + * at that time). Once it finds the lowest-voltage OPP that + * meets those conditions, it should switch to it, or return + * an error if the code is not capable of doing so. + */ + + return 0; +} /* * DSP Bridge-specific constraints -- cgit v1.2.3