summaryrefslogtreecommitdiff
path: root/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml
diff options
context:
space:
mode:
authorMichael Lauer <mickey@vanille-media.de>2008-08-12 13:29:28 +0000
committerMichael Lauer <mickey@vanille-media.de>2008-08-12 13:29:28 +0000
commit5013da3eac1b9eaa3e459e51868c972f35d13987 (patch)
tree16969aea9782c4712bea45c3e4b99cb54db2dfe2 /packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml
parent17749e1e129cdb3a6e4121cd70edb3ad2801e33f (diff)
parent5501bf760b33f3cdd0cccc5a413e5fd8540ad3c9 (diff)
merge of 'da96891a2ca8b58603eeace03f70b31bdb83f534'
and 'ff29d35506adb74555e6297276dcbf0d5adfba55'
Diffstat (limited to 'packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml')
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml894
1 files changed, 894 insertions, 0 deletions
diff --git a/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml b/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml
new file mode 100644
index 0000000000..48ff5da822
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml
@@ -0,0 +1,894 @@
+The interface provides device drivers, CPUFreq, and DSP Bridge with a
+means of controlling OMAP power management parameters that are not yet
+supported by the Linux PM PMQOS interface. Copious documentation and
+rationale is in the patch in Documentation/arm/OMAP/omap_pm and the
+interface header file, include/asm-arm/arch-omap/omap-pm.h.
+
+Signed-off-by: Paul Walmsley <paul@pwsan.com>
+---
+
+ Documentation/arm/OMAP/omap_pm | 185 +++++++++++++++++++++
+ arch/arm/mach-omap2/io.c | 4
+ arch/arm/plat-omap/Kconfig | 13 +
+ arch/arm/plat-omap/Makefile | 1
+ arch/arm/plat-omap/omap-pm-noop.c | 309 +++++++++++++++++++++++++++++++++++
+ include/asm-arm/arch-omap/omap-pm.h | 300 ++++++++++++++++++++++++++++++++++
+ 6 files changed, 812 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/arm/OMAP/omap_pm
+ create mode 100644 arch/arm/plat-omap/omap-pm-noop.c
+ create mode 100644 include/asm-arm/arch-omap/omap-pm.h
+
+diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
+new file mode 100644
+index 0000000..2ec2034
+--- /dev/null
++++ b/Documentation/arm/OMAP/omap_pm
+@@ -0,0 +1,185 @@
++
++Rationale: the OMAP PM interface
++================================
++
++
++Existing PM interfaces are currently not ideal for OMAP
++-------------------------------------------------------
++
++There are two PM interfaces in use with publicly-distributed OMAP
++Linux code: the TI Shared Resource Framework (SRF) and the Linux PM
++QoS parameters code. Neither interface is ideal for Linux OMAP code.
++
++TI Shared Resource Framework:
++
++The TI CDP 12.14 tree drivers currently use the TI Shared Resource
++Framework (SRF) to control chip power management. Use of the SRF
++allowed TI to get the drivers up and running quickly with considerable
++power savings; and the SRF provided debugging support. However, many
++of the SRF parameters are specified in OMAP-specific terms, such as
++target OPPs, rather than in terms of actual latency or throughput
++requirements. OPPs change depending on OMAP silicon revisions or OMAP
++types, and are meaningless for other architectures, so drivers shared
++between OMAP and other architectures would also have to #ifdef out the
++SRF constraints.
++
++Linux PM QoS parameters:
++
++In February 2008, the mainline Linux kernel added code that is
++somewhat similar to the SRF: the Linux PM QoS parameters code, located
++in kernel/pm_qos_params.c. (This code replaced the latency management
++code that was present in earlier kernels.) Ideally, OMAP drivers
++would be able to use this Linux PM QoS code directly, but the PM QoS
++code has some drawbacks:
++
++- It combines some power management parameters that should be kept
++ separate for maximum power savings on OMAP3. For example, in the PM
++ QoS code, CPU and system DMA wakeup latency are combined into one
++ parameter; but on OMAP3, these are distinct parameters. The Linux
++ PM QoS code also combines all network power management knobs into
++ two non-device-specific parameters. OMAP2/3 systems can have
++ different network devices with different power management
++ requirements - for example, a wired Ethernet interface may have
++ different latency and throughput constraints than a WiFi interface.
++
++- It does not yet cover all of the power management capabilities of
++ the OMAP3 architecture. It does not express latency constraints on
++ a per-device or per-powerdomain basis; it only covers
++ cpu_dma_latency and network throughput and latency, which would not
++ cover most of the OMAP3 devices.
++
++The result is that drivers using the current Linux PM QoS layer
++directly are unlikely to reach the same level of power efficiency as
++driver code using the Shared Resource Framework.
++
++To summarize, the SRF provides significant power savings, but
++expresses power constraints in an OMAP- and silicon-revision-specific
++way; and the PM QoS layer expresses PM constraints in a cross-platform
++manner (in terms of fundamental physical units), but does not support
++per-powerdomain constraints and does not cover many of the OMAP power
++management features.
++
++
++A medium-term alternative: the OMAP PM interface
++------------------------------------------------
++
++We need a way for driver code to express PM parameters which:
++
++- supports the range of power management parameters present in the TI SRF;
++
++- separates the drivers from the underlying PM parameter
++ implementation, whether it is the TI SRF or Linux PM QoS or Linux
++ latency framework or something else;
++
++- specifies PM parameters in terms of fundamental units, such as
++ latency and throughput, rather than units which are specific to OMAP
++ or to particular OMAP variants;
++
++- allows drivers which are shared with other architectures (e.g.,
++ DaVinci) to add these constraints in a way which won't affect non-OMAP
++ systems,
++
++- can be implemented immediately with minimal disruption of other
++ architectures.
++
++
++We therefore propose the OMAP PM interface, including the following
++four power management functions for driver code:
++
++1. Set the maximum MPU wakeup latency:
++ (*pdata->set_max_mpu_wakeup_lat)(struct device *dev, unsigned long t)
++
++2. Set the maximum device wakeup latency:
++ (*pdata->set_max_dev_wakeup_lat)(struct device *dev, unsigned long t)
++
++3. Set the maximum system DMA transfer start latency (CORE pwrdm):
++ (*pdata->set_max_sdma_lat)(struct device *dev, long t)
++
++4. Set the minimum bus throughput needed by a device:
++ (*pdata->set_min_bus_tput)(struct device *dev, u8 agent_id, unsigned long r)
++
++
++These functions are extensively documented in the OMAP PM interface header
++file, included in the patch.
++
++
++The OMAP PM layer is intended to be temporary
++---------------------------------------------
++
++The intention is that, in time, the Linux PM QoS layer should support
++the range of power management features present in OMAP3. As this
++happens, existing drivers using the OMAP PM interface can be modified
++to use the Linux PM QoS code; and the OMAP PM interface can disappear.
++
++
++Driver usage of the OMAP PM functions
++-------------------------------------
++
++As the 'pdata' in the above examples indicates, these functions are
++exposed to drivers through function pointers in driver .platform_data
++structures. The function pointers are initialized by the board-*.c
++files to point to the corresponding OMAP PM functions:
++.set_max_dev_wakeup_lat will point to
++omap_pm_set_max_dev_wakeup_lat(), etc. Other architectures which do
++not support these functions should leave these function pointers set
++to NULL. Drivers should use the following idiom:
++
++ if (pdata->set_max_dev_wakeup_lat)
++ (*pdata->set_max_dev_wakeup_lat)(dev, t);
++
++The most common usage of these functions will probably be to specify
++the maximum time from when an interrupt occurs, to when the device
++becomes accessible. To accomplish this, driver writers should use the
++set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
++latency, and the set_max_dev_wakeup_lat() function to constrain the
++device wakeup latency (from clk_enable() to accessibility). For
++example,
++
++ /* Limit MPU wakeup latency */
++ if (pdata->set_max_mpu_wakeup_lat)
++ (*pdata->set_max_mpu_wakeup_lat)(dev, tc);
++
++ /* Limit device powerdomain wakeup latency */
++ if (pdata->set_max_dev_wakeup_lat)
++ (*pdata->set_max_dev_wakeup_lat)(dev, td);
++
++ /* total wakeup latency in this example: (tc + td) */
++
++
++The PM parameters can be overwritten by calling the function again
++with the new value. The settings can be removed by calling the
++function with a t argument of -1 (except in the case of
++set_max_bus_tput(), which should be called with an r argument of 0).
++
++
++Other specialized interface functions
++-------------------------------------
++
++The four functions listed above are intended to be usable by any
++device driver. However, DSPBridge and CPUFreq have special
++requirements. DSPBridge expresses target DSP performance levels in
++terms of OPP IDs. CPUFreq expresses target MPU performance levels in
++terms of MPU frequency. The OMAP PM interface contains functions for
++these specialized cases to convert that input information (OPPs/MPU
++frequency) into the form that the underlying power management
++implementation needs:
++
++5. (*pdata->omap_pm_dsp_get_opp_table)(void)
++
++6. (*pdata->omap_pm_dsp_set_min_opp)(u8 opp_id)
++
++7. (*pdata->omap_pm_dsp_get_opp)(void)
++
++8. (*pdata->omap_pm_cpu_get_freq_table)(void)
++
++9. (*pdata->omap_pm_cpu_set_freq)(unsigned long f)
++
++10. (*pdata->omap_pm_cpu_get_freq)(void)
++
++
++There are also functions for use by the clockdomain layer to indicate
++that a powerdomain should wake up or be put to sleep:
++
++11. (*pdata->omap_pm_pwrdm_active)(struct powerdomain *pwrdm)
++
++12. (*pdata->omap_pm_pwrdm_inactive)(struct powerdomain *pwrdm)
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index 960c13f..ca790ac 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -247,4 +247,17 @@ config OMAP_SERIAL_WAKE
+
+ endmenu
+
++choice
++ prompt "OMAP PM layer selection"
++ depends on ARCH_OMAP
++ default OMAP_PM_NOOP
++
++config OMAP_PM_NONE
++ bool "No PM layer"
++
++config OMAP_PM_NOOP
++ bool "No-op/debug PM layer"
++
++endchoice
++
+ endif
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 93bbb64..d5453d5 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -29,3 +29,4 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o
+ # OMAP mailbox framework
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
+
++obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
+\ No newline at end of file
+diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
+new file mode 100644
+index 0000000..5ff7962
+--- /dev/null
++++ b/arch/arm/plat-omap/omap-pm-noop.c
+@@ -0,0 +1,309 @@
++/*
++ * omap-pm-noop.c - OMAP power management interface - dummy version
++ *
++ * This code implements the OMAP power management interface to
++ * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for
++ * debug/demonstration use, as it does nothing but printk() whenever a
++ * function is called (when DEBUG is defined, below)
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ * Copyright (C) 2008 Nokia Corporation
++ * Paul Walmsley
++ *
++ * Interface developed by (in alphabetical order):
++ * Karthik Dasu, Amish Lakhani, Tony Lindgren, Rajendra Nayak, Sakari
++ * Poussa, Veeramanikandan Raju, Igor Stoppa, Paul Walmsley, Richard
++ * Woodruff
++ */
++
++#undef DEBUG
++
++#include <linux/init.h>
++#include <linux/cpufreq.h>
++#include <linux/device.h>
++
++/* Interface documentation is in asm/arch/omap-pm.h */
++#include <asm/arch/omap-pm.h>
++
++#include <asm/arch/powerdomain.h>
++
++static struct omap_opp *dsp_opps;
++static struct omap_opp *mpu_opps;
++
++/*
++ * Device-driver-originated constraints (via board-*.c files)
++ */
++
++void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1)
++ pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
++ "dev %s\n", dev_name(dev));
++ else
++ pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++
++ /*
++ * For current Linux, this needs to map the MPU to a
++ * powerdomain, then go through the list of current max lat
++ * constraints on the MPU and find the smallest. If
++ * the latency constraint has changed, the code should
++ * recompute the state to enter for the next powerdomain
++ * state.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++}
++
++void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
++{
++ if (!dev || agent_id != OCP_INITIATOR_AGENT ||
++ agent_id != OCP_TARGET_AGENT) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (r == 0)
++ pr_debug("OMAP PM: remove min bus tput constraint: "
++ "dev %s for agent_id %d\n", dev_name(dev), agent_id);
++ else
++ pr_debug("OMAP PM: add min bus tput constraint: "
++ "dev %s for agent_id %d: rate %ld KiB\n",
++ dev_name(dev), agent_id, r);
++
++ /*
++ * This code should model the interconnect and compute the
++ * required clock frequency, convert that to a VDD2 OPP ID, then
++ * set the VDD2 OPP appropriately.
++ *
++ * TI CDP code can call constraint_set here on the VDD2 OPP.
++ */
++}
++
++void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1)
++ pr_debug("OMAP PM: remove max device latency constraint: "
++ "dev %s\n", dev_name(dev));
++ else
++ pr_debug("OMAP PM: add max device latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++
++ /*
++ * For current Linux, this needs to map the device to a
++ * powerdomain, then go through the list of current max lat
++ * constraints on that powerdomain and find the smallest. If
++ * the latency constraint has changed, the code should
++ * recompute the state to enter for the next powerdomain
++ * state. Conceivably, this code should also determine
++ * whether to actually disable the device clocks or not,
++ * depending on how long it takes to re-enable the clocks.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++}
++
++void omap_pm_set_max_sdma_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1)
++ pr_debug("OMAP PM: remove max DMA latency constraint: "
++ "dev %s\n", dev_name(dev));
++ else
++ pr_debug("OMAP PM: add max DMA latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++
++ /*
++ * For current Linux PM QOS params, this code should scan the
++ * list of maximum CPU and DMA latencies and select the
++ * smallest, then set cpu_dma_latency pm_qos_param
++ * accordingly.
++ *
++ * For future Linux PM QOS params, with separate CPU and DMA
++ * latency params, this code should just set the dma_latency param.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++
++}
++
++
++/*
++ * DSP Bridge-specific constraints
++ */
++
++const struct omap_opp *omap_pm_dsp_get_opp_table(void)
++{
++ pr_debug("OMAP PM: DSP request for OPP table\n");
++
++ /*
++ * Return DSP frequency table here: The final item in the
++ * array should have .rate = .opp_id = 0.
++ */
++
++ return NULL;
++}
++
++void omap_pm_dsp_set_min_opp(u8 opp_id)
++{
++ if (opp_id == 0) {
++ WARN_ON(1);
++ return;
++ }
++
++ pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
++
++ /*
++ *
++ * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
++ * can just test to see which is higher, the CPU's desired OPP
++ * ID or the DSP's desired OPP ID, and use whichever is
++ * highest.
++ *
++ * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
++ * rate is keyed on MPU speed, not the OPP ID. So we need to
++ * map the OPP ID to the MPU speed for use with clk_set_rate()
++ * if it is higher than the current OPP clock rate.
++ *
++ */
++}
++
++
++u8 omap_pm_dsp_get_opp(void)
++{
++ pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
++
++ /*
++ * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
++ *
++ * CDP12.14+:
++ * Call clk_get_rate() on the OPP custom clock, map that to an
++ * OPP ID using the tables defined in board-*.c/chip-*.c files.
++ */
++
++ return 0;
++}
++
++/*
++ * CPUFreq-originated constraint
++ *
++ * In the future, this should be handled by custom OPP clocktype
++ * functions.
++ */
++
++struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void)
++{
++ pr_debug("OMAP PM: CPUFreq request for frequency table\n");
++
++ /*
++ * Return CPUFreq frequency table here: loop over
++ * all VDD1 clkrates, pull out the mpu_ck frequencies, build
++ * table
++ */
++
++ return NULL;
++}
++
++void omap_pm_cpu_set_freq(unsigned long f)
++{
++ if (f == 0) {
++ WARN_ON(1);
++ return;
++ }
++
++ pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
++ f);
++
++ /*
++ * For l-o dev tree, determine whether MPU freq or DSP OPP id
++ * freq is higher. Find the OPP ID corresponding to the
++ * higher frequency. Call clk_round_rate() and clk_set_rate()
++ * on the OPP custom clock.
++ *
++ * CDP should just be able to set the VDD1 OPP clock rate here.
++ */
++}
++
++unsigned long omap_pm_cpu_get_freq(void)
++{
++ pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
++
++ /*
++ * Call clk_get_rate() on the mpu_ck.
++ */
++
++ return 0;
++}
++
++/*
++ * Powerdomain usecounting hooks
++ */
++
++void omap_pm_pwrdm_active(struct powerdomain *pwrdm)
++{
++ if (!pwrdm) {
++ WARN_ON(1);
++ return;
++ };
++
++ pr_debug("OMAP PM: powerdomain %s is becoming active\n", pwrdm->name);
++
++ /*
++ * CDP code apparently will need these for the enable_power_domain()
++ * and disable_power_domain() functions.
++ */
++}
++
++void omap_pm_pwrdm_inactive(struct powerdomain *pwrdm)
++{
++ if (!pwrdm) {
++ WARN_ON(1);
++ return;
++ };
++
++ pr_debug("OMAP PM: powerdomain %s is becoming inactive\n",
++ pwrdm->name);
++
++ /*
++ * CDP code apparently will need these for the enable_power_domain()
++ * and disable_power_domain() functions.
++ */
++}
++
++/*
++ * Should be called before clk framework since clk fw will call
++ * omap_pm_pwrdm_{in,}active()
++ */
++int __init omap_pm_if_early_init(void)
++{
++ return 0;
++}
++
++/* Must be called after clock framework is initialized */
++int __init omap_pm_if_init(struct omap_opp *mpu_opp_table,
++ struct omap_opp *dsp_opp_table)
++{
++ mpu_opps = mpu_opp_table;
++ dsp_opps = dsp_opp_table;
++ return 0;
++}
++
++void omap_pm_if_exit(void)
++{
++ /* Deallocate CPUFreq frequency table here */
++}
++
+diff --git a/include/asm-arm/arch-omap/omap-pm.h b/include/asm-arm/arch-omap/omap-pm.h
+new file mode 100644
+index 0000000..d272dba
+--- /dev/null
++++ b/include/asm-arm/arch-omap/omap-pm.h
+@@ -0,0 +1,300 @@
++/*
++ * omap-pm.h - OMAP power management interface
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ * Copyright (C) 2008 Nokia Corporation
++ * Paul Walmsley
++ *
++ * Interface developed by (in alphabetical order): Karthik Dasu, Jouni
++ * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa,
++ * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley,
++ * Richard Woodruff
++ */
++
++#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H
++#define ASM_ARM_ARCH_OMAP_OMAP_PM_H
++
++#include <linux/device.h>
++#include <linux/cpufreq.h>
++
++#include "powerdomain.h"
++
++/**
++ * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
++ * @rate: target clock rate
++ * @opp_id: OPP ID
++ * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
++ *
++ * Operating performance point data. Can vary by OMAP chip and board.
++ */
++struct omap_opp {
++ unsigned long rate;
++ u8 opp_id;
++ u16 min_vdd;
++};
++
++/*
++ * agent_id values for use with omap_pm_set_min_bus_tput():
++ *
++ * OCP_INITIATOR_AGENT is only valid for devices that can act as
++ * initiators -- it represents the device's L3 interconnect
++ * connection. OCP_TARGET_AGENT represents the device's L4
++ * interconnect connection.
++ */
++#define OCP_TARGET_AGENT 1
++#define OCP_INITIATOR_AGENT 2
++
++/**
++ * omap_pm_if_early_init - OMAP PM init code called before clock fw init
++ *
++ * Initialize anything that must be configured before the clock
++ * framework starts. The "_if_" is to avoid name collisions with the
++ * PM idle-loop code.
++ */
++int __init omap_pm_if_early_init(void);
++
++/**
++ * omap_pm_if_init - OMAP PM init code called after clock fw init
++ * @mpu_opp_table: array ptr to struct omap_opp for MPU
++ * @dsp_opp_table: array ptr to struct omap_opp for DSP
++ *
++ * The main initialization code. OPP tables are passed in here. The
++ * "_if_" is to avoid name collisions with the PM idle-loop code.
++ */
++int __init omap_pm_if_init(struct omap_opp *mpu_opp_table,
++ struct omap_opp *dsp_opp_table);
++
++/**
++ * omap_pm_if_exit - OMAP PM exit code
++ *
++ * Exit code; currently unused. The "_if_" is to avoid name
++ * collisions with the PM idle-loop code.
++ */
++void omap_pm_if_exit(void);
++
++/*
++ * Device-driver-originated constraints (via board-*.c files, platform_data)
++ */
++
++
++/**
++ * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
++ * @dev: struct device * requesting the constraint
++ * @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
++ * 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.
++ *
++ * It is intended that underlying PM code will use this information to
++ * determine what power state to put the MPU powerdomain into, and
++ * possibly the CORE powerdomain as well, since interrupt handling
++ * code currently runs from SDRAM. Advanced PM or board*.c code may
++ * also configure interrupt controller priorities, OCP bus priorities,
++ * CPU speed(s), etc.
++ *
++ * This function will not affect device wakeup latency, e.g., time
++ * 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()
++ *
++ * Multiple calls to 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.
++ */
++void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
++
++
++/**
++ * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
++ * @dev: struct device * requesting the constraint
++ * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT)
++ * @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.
++ *
++ * It is expected that the OMAP PM or bus code will use this
++ * information to set the interconnect clock to run at the lowest
++ * possible speed that satisfies all current system users. The PM or
++ * bus code will adjust the estimate based on its model of the bus, so
++ * device driver authors should attempt to specify an accurate
++ * quantity for their device use case, and let the PM or bus code
++ * overestimate the numbers as necessary to handle request/response
++ * latency, other competing users on the system, etc. On OMAP2/3, if
++ * a driver requests a minimum L4 interconnect speed constraint, the
++ * 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.
++ *
++ * No return value.
++ */
++void 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 *
++ * @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().
++ *
++ * 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.
++ *
++ * No return value.
++ */
++void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t);
++
++
++/**
++ * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency
++ * @dev: struct device *
++ * @t: maximum DMA transfer start latency in microseconds
++ *
++ * Request that the maximum system DMA transfer start latency for this
++ * device 'dev' should be no greater than 't' microseconds. "DMA
++ * transfer start latency" here is defined as the elapsed time from
++ * when a device (e.g., McBSP) requests that a system DMA transfer
++ * start or continue, to the time at which data starts to flow into
++ * that device from the system DMA controller.
++ *
++ * It is intended that underlying PM code will use this information to
++ * determine what power state to put the CORE powerdomain into.
++ *
++ * Since system DMA transfers may not involve the MPU, this function
++ * will not affect MPU wakeup latency. Use set_max_cpu_lat() to do
++ * so. Similarly, this function will not affect device wakeup latency
++ * -- use set_max_dev_wakeup_lat() to affect that.
++ *
++ * Multiple calls to set_max_sdma_lat() will replace the previous t
++ * value for this device. To remove the maximum DMA latency for this
++ * device, call with t = -1.
++ *
++ * No return value.
++ */
++void omap_pm_set_max_sdma_lat(struct device *dev, long t);
++
++
++/*
++ * DSP Bridge-specific constraints
++ */
++
++/**
++ * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table
++ *
++ * Intended for use by DSPBridge. Returns an array of OPP->DSP clock
++ * frequency entries. The final item in the array should have .rate =
++ * .opp_id = 0.
++ */
++const struct omap_opp *omap_pm_dsp_get_opp_table(void);
++
++/**
++ * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge
++ * @opp_id: target DSP OPP ID
++ *
++ * Set a minimum OPP ID for the DSP. This is intended to be called
++ * only from the DSP Bridge MPU-side driver. Unfortunately, the only
++ * information that code receives from the DSP/BIOS load estimator is the
++ * target OPP ID; hence, this interface. No return value.
++ */
++void omap_pm_dsp_set_min_opp(u8 opp_id);
++
++/**
++ * omap_pm_dsp_get_opp - report the current DSP OPP ID
++ *
++ * Report the current OPP for the DSP. Since on OMAP3, the DSP and
++ * MPU share a single voltage domain, the OPP ID returned back may
++ * represent a higher DSP speed than the OPP requested via
++ * omap_pm_dsp_set_min_opp().
++ *
++ * Returns the current VDD1 OPP ID, or 0 upon error.
++ */
++u8 omap_pm_dsp_get_opp(void);
++
++
++/*
++ * CPUFreq-originated constraint
++ *
++ * In the future, this should be handled by custom OPP clocktype
++ * functions.
++ */
++
++/**
++ * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr
++ *
++ * Provide a frequency table usable by CPUFreq for the current chip/board.
++ * Returns a pointer to a struct cpufreq_frequency_table array or NULL
++ * upon error.
++ */
++struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void);
++
++/**
++ * omap_pm_cpu_set_freq - set the current minimum MPU frequency
++ * @f: MPU frequency in Hz
++ *
++ * Set the current minimum CPU frequency. The actual CPU frequency
++ * used could end up higher if the DSP requested a higher OPP.
++ * Intended to be called by plat-omap/cpu_omap.c:omap_target(). No
++ * return value.
++ */
++void omap_pm_cpu_set_freq(unsigned long f);
++
++/**
++ * omap_pm_cpu_get_freq - report the current CPU frequency
++ *
++ * Returns the current MPU frequency, or 0 upon error.
++ */
++unsigned long omap_pm_cpu_get_freq(void);
++
++
++/*
++ * Powerdomain usecounting hooks
++ */
++
++/**
++ * omap_pm_pwrdm_active - indicate that a power domain has become active
++ * @pwrdm: struct powerdomain *
++ *
++ * Notify the OMAP PM layer that the power domain 'pwrdm' has become active,
++ * presumably due to a device driver enabling an underlying clock. This
++ * function is intended to be called by a clockdomain node in the clock
++ * framework. No return value.
++ */
++void omap_pm_pwrdm_active(struct powerdomain *pwrdm);
++
++
++/**
++ * omap_pm_pwrdm_inactive - indicate that a power domain has become inactive
++ * @pwrdm: struct powerdomain *
++ *
++ * Notify the OMAP PM layer that the power domain 'pwrdm' has become
++ * inactive, presumably due to a device driver disabling an underlying
++ * clock. This function is intended to be called by a clockdomain
++ * node in the clock framework. No return value.
++ */
++void omap_pm_pwrdm_inactive(struct powerdomain *pwrdm);
++
++
++#endif
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
+--- /tmp/io.c 2008-08-11 15:29:32.000000000 +0200
++++ git/arch/arm/mach-omap2/io.c 2008-08-11 15:30:20.083198000 +0200
+@@ -38,6 +38,8 @@
+ #include <asm/arch/clockdomain.h>
+ #include "clockdomains.h"
+
++#include <asm/arch/omap-pm.h>
++
+ /*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+@@ -197,9 +199,11 @@
+ void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+ {
+ omap2_mux_init();
++ omap_pm_if_early_init();
+ pwrdm_init(powerdomains_omap);
+ clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
+ omap2_clk_init();
++ omap_pm_if_init(NULL, NULL);
+ omap2_sdrc_init(sp);
+ gpmc_init();
+ }