diff options
author | Tony Lindgren <tony@atomide.com> | 2010-08-04 01:46:24 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2010-08-04 01:46:24 -0400 |
commit | 331d919af416b9b92428947ef8c535a3e24c6b31 (patch) | |
tree | 1f58dfe4ea6ed130f7b970f07cd7589864e9cbad /arch/arm/plat-omap | |
parent | 047b51fb208c716294b4682c904df8a3ad8b6a69 (diff) | |
parent | fb8ce14c7e16bd218decb3e1655c5d4ff08042f2 (diff) |
Merge branch 'for_2.6.36' of git://git.pwsan.com/linux-2.6 into omap-for-linus
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/plat-omap/i2c.c | 12 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/clock.h | 130 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/common.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap-pm.h | 130 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap_device.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap_hwmod.h | 14 | ||||
-rw-r--r-- | arch/arm/plat-omap/omap-pm-noop.c | 61 | ||||
-rw-r--r-- | arch/arm/plat-omap/omap_device.c | 33 |
9 files changed, 311 insertions, 76 deletions
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 98f01910c2cf..9405831b746a 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o | |||
15 | # omap_device support (OMAP2+ only at the moment) | 15 | # omap_device support (OMAP2+ only at the moment) |
16 | obj-$(CONFIG_ARCH_OMAP2) += omap_device.o | 16 | obj-$(CONFIG_ARCH_OMAP2) += omap_device.o |
17 | obj-$(CONFIG_ARCH_OMAP3) += omap_device.o | 17 | obj-$(CONFIG_ARCH_OMAP3) += omap_device.o |
18 | obj-$(CONFIG_ARCH_OMAP4) += omap_device.o | ||
18 | 19 | ||
19 | obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o | 20 | obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o |
20 | obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o | 21 | obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o |
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index eec2b4993c69..a5ce4f0aad35 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c | |||
@@ -138,6 +138,16 @@ static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) | |||
138 | return platform_device_register(pdev); | 138 | return platform_device_register(pdev); |
139 | } | 139 | } |
140 | 140 | ||
141 | /* | ||
142 | * XXX This function is a temporary compatibility wrapper - only | ||
143 | * needed until the I2C driver can be converted to call | ||
144 | * omap_pm_set_max_dev_wakeup_lat() and handle a return code. | ||
145 | */ | ||
146 | static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) | ||
147 | { | ||
148 | omap_pm_set_max_mpu_wakeup_lat(dev, t); | ||
149 | } | ||
150 | |||
141 | static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) | 151 | static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) |
142 | { | 152 | { |
143 | struct resource *res; | 153 | struct resource *res; |
@@ -168,7 +178,7 @@ static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) | |||
168 | struct omap_i2c_bus_platform_data *pd; | 178 | struct omap_i2c_bus_platform_data *pd; |
169 | 179 | ||
170 | pd = pdev->dev.platform_data; | 180 | pd = pdev->dev.platform_data; |
171 | pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat; | 181 | pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; |
172 | } | 182 | } |
173 | 183 | ||
174 | return platform_device_register(pdev); | 184 | return platform_device_register(pdev); |
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index dfc472ca0cc4..fef4696dcf67 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h | |||
@@ -19,6 +19,22 @@ struct module; | |||
19 | struct clk; | 19 | struct clk; |
20 | struct clockdomain; | 20 | struct clockdomain; |
21 | 21 | ||
22 | /** | ||
23 | * struct clkops - some clock function pointers | ||
24 | * @enable: fn ptr that enables the current clock in hardware | ||
25 | * @disable: fn ptr that enables the current clock in hardware | ||
26 | * @find_idlest: function returning the IDLEST register for the clock's IP blk | ||
27 | * @find_companion: function returning the "companion" clk reg for the clock | ||
28 | * | ||
29 | * A "companion" clk is an accompanying clock to the one being queried | ||
30 | * that must be enabled for the IP module connected to the clock to | ||
31 | * become accessible by the hardware. Neither @find_idlest nor | ||
32 | * @find_companion should be needed; that information is IP | ||
33 | * block-specific; the hwmod code has been created to handle this, but | ||
34 | * until hwmod data is ready and drivers have been converted to use PM | ||
35 | * runtime calls in place of clk_enable()/clk_disable(), @find_idlest and | ||
36 | * @find_companion must, unfortunately, remain. | ||
37 | */ | ||
22 | struct clkops { | 38 | struct clkops { |
23 | int (*enable)(struct clk *); | 39 | int (*enable)(struct clk *); |
24 | void (*disable)(struct clk *); | 40 | void (*disable)(struct clk *); |
@@ -30,12 +46,45 @@ struct clkops { | |||
30 | 46 | ||
31 | #ifdef CONFIG_ARCH_OMAP2PLUS | 47 | #ifdef CONFIG_ARCH_OMAP2PLUS |
32 | 48 | ||
49 | /* struct clksel_rate.flags possibilities */ | ||
50 | #define RATE_IN_242X (1 << 0) | ||
51 | #define RATE_IN_243X (1 << 1) | ||
52 | #define RATE_IN_3XXX (1 << 2) /* rates common to all OMAP3 */ | ||
53 | #define RATE_IN_3430ES2 (1 << 3) /* 3430ES2 rates only */ | ||
54 | #define RATE_IN_36XX (1 << 4) | ||
55 | #define RATE_IN_4430 (1 << 5) | ||
56 | |||
57 | #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) | ||
58 | #define RATE_IN_3430ES2PLUS (RATE_IN_3430ES2 | RATE_IN_36XX) | ||
59 | |||
60 | /** | ||
61 | * struct clksel_rate - register bitfield values corresponding to clk divisors | ||
62 | * @val: register bitfield value (shifted to bit 0) | ||
63 | * @div: clock divisor corresponding to @val | ||
64 | * @flags: (see "struct clksel_rate.flags possibilities" above) | ||
65 | * | ||
66 | * @val should match the value of a read from struct clk.clksel_reg | ||
67 | * AND'ed with struct clk.clksel_mask, shifted right to bit 0. | ||
68 | * | ||
69 | * @div is the divisor that should be applied to the parent clock's rate | ||
70 | * to produce the current clock's rate. | ||
71 | * | ||
72 | * XXX @flags probably should be replaced with an struct omap_chip. | ||
73 | */ | ||
33 | struct clksel_rate { | 74 | struct clksel_rate { |
34 | u32 val; | 75 | u32 val; |
35 | u8 div; | 76 | u8 div; |
36 | u8 flags; | 77 | u8 flags; |
37 | }; | 78 | }; |
38 | 79 | ||
80 | /** | ||
81 | * struct clksel - available parent clocks, and a pointer to their divisors | ||
82 | * @parent: struct clk * to a possible parent clock | ||
83 | * @rates: available divisors for this parent clock | ||
84 | * | ||
85 | * A struct clksel is always associated with one or more struct clks | ||
86 | * and one or more struct clksel_rates. | ||
87 | */ | ||
39 | struct clksel { | 88 | struct clksel { |
40 | struct clk *parent; | 89 | struct clk *parent; |
41 | const struct clksel_rate *rates; | 90 | const struct clksel_rate *rates; |
@@ -116,6 +165,60 @@ struct dpll_data { | |||
116 | 165 | ||
117 | #endif | 166 | #endif |
118 | 167 | ||
168 | /* struct clk.flags possibilities */ | ||
169 | #define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ | ||
170 | #define CLOCK_IDLE_CONTROL (1 << 1) | ||
171 | #define CLOCK_NO_IDLE_PARENT (1 << 2) | ||
172 | #define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ | ||
173 | #define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ | ||
174 | |||
175 | /** | ||
176 | * struct clk - OMAP struct clk | ||
177 | * @node: list_head connecting this clock into the full clock list | ||
178 | * @ops: struct clkops * for this clock | ||
179 | * @name: the name of the clock in the hardware (used in hwmod data and debug) | ||
180 | * @parent: pointer to this clock's parent struct clk | ||
181 | * @children: list_head connecting to the child clks' @sibling list_heads | ||
182 | * @sibling: list_head connecting this clk to its parent clk's @children | ||
183 | * @rate: current clock rate | ||
184 | * @enable_reg: register to write to enable the clock (see @enable_bit) | ||
185 | * @recalc: fn ptr that returns the clock's current rate | ||
186 | * @set_rate: fn ptr that can change the clock's current rate | ||
187 | * @round_rate: fn ptr that can round the clock's current rate | ||
188 | * @init: fn ptr to do clock-specific initialization | ||
189 | * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) | ||
190 | * @usecount: number of users that have requested this clock to be enabled | ||
191 | * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div | ||
192 | * @flags: see "struct clk.flags possibilities" above | ||
193 | * @clksel_reg: for clksel clks, register va containing src/divisor select | ||
194 | * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector | ||
195 | * @clksel: for clksel clks, pointer to struct clksel for this clock | ||
196 | * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock | ||
197 | * @clkdm_name: clockdomain name that this clock is contained in | ||
198 | * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime | ||
199 | * @rate_offset: bitshift for rate selection bitfield (OMAP1 only) | ||
200 | * @src_offset: bitshift for source selection bitfield (OMAP1 only) | ||
201 | * | ||
202 | * XXX @rate_offset, @src_offset should probably be removed and OMAP1 | ||
203 | * clock code converted to use clksel. | ||
204 | * | ||
205 | * XXX @usecount is poorly named. It should be "enable_count" or | ||
206 | * something similar. "users" in the description refers to kernel | ||
207 | * code (core code or drivers) that have called clk_enable() and not | ||
208 | * yet called clk_disable(); the usecount of parent clocks is also | ||
209 | * incremented by the clock code when clk_enable() is called on child | ||
210 | * clocks and decremented by the clock code when clk_disable() is | ||
211 | * called on child clocks. | ||
212 | * | ||
213 | * XXX @clkdm, @usecount, @children, @sibling should be marked for | ||
214 | * internal use only. | ||
215 | * | ||
216 | * @children and @sibling are used to optimize parent-to-child clock | ||
217 | * tree traversals. (child-to-parent traversals use @parent.) | ||
218 | * | ||
219 | * XXX The notion of the clock's current rate probably needs to be | ||
220 | * separated from the clock's target rate. | ||
221 | */ | ||
119 | struct clk { | 222 | struct clk { |
120 | struct list_head node; | 223 | struct list_head node; |
121 | const struct clkops *ops; | 224 | const struct clkops *ops; |
@@ -129,8 +232,8 @@ struct clk { | |||
129 | int (*set_rate)(struct clk *, unsigned long); | 232 | int (*set_rate)(struct clk *, unsigned long); |
130 | long (*round_rate)(struct clk *, unsigned long); | 233 | long (*round_rate)(struct clk *, unsigned long); |
131 | void (*init)(struct clk *); | 234 | void (*init)(struct clk *); |
132 | __u8 enable_bit; | 235 | u8 enable_bit; |
133 | __s8 usecount; | 236 | s8 usecount; |
134 | u8 fixed_div; | 237 | u8 fixed_div; |
135 | u8 flags; | 238 | u8 flags; |
136 | #ifdef CONFIG_ARCH_OMAP2PLUS | 239 | #ifdef CONFIG_ARCH_OMAP2PLUS |
@@ -141,8 +244,8 @@ struct clk { | |||
141 | const char *clkdm_name; | 244 | const char *clkdm_name; |
142 | struct clockdomain *clkdm; | 245 | struct clockdomain *clkdm; |
143 | #else | 246 | #else |
144 | __u8 rate_offset; | 247 | u8 rate_offset; |
145 | __u8 src_offset; | 248 | u8 src_offset; |
146 | #endif | 249 | #endif |
147 | #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) | 250 | #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) |
148 | struct dentry *dent; /* For visible tree hierarchy */ | 251 | struct dentry *dent; /* For visible tree hierarchy */ |
@@ -188,23 +291,4 @@ extern const struct clkops clkops_null; | |||
188 | 291 | ||
189 | extern struct clk dummy_ck; | 292 | extern struct clk dummy_ck; |
190 | 293 | ||
191 | /* Clock flags */ | ||
192 | #define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ | ||
193 | #define CLOCK_IDLE_CONTROL (1 << 1) | ||
194 | #define CLOCK_NO_IDLE_PARENT (1 << 2) | ||
195 | #define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ | ||
196 | #define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ | ||
197 | |||
198 | /* Clksel_rate flags */ | ||
199 | #define RATE_IN_242X (1 << 0) | ||
200 | #define RATE_IN_243X (1 << 1) | ||
201 | #define RATE_IN_3XXX (1 << 2) /* rates common to all OMAP3 */ | ||
202 | #define RATE_IN_3430ES2 (1 << 3) /* 3430ES2 rates only */ | ||
203 | #define RATE_IN_36XX (1 << 4) | ||
204 | #define RATE_IN_4430 (1 << 5) | ||
205 | |||
206 | #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) | ||
207 | |||
208 | #define RATE_IN_3430ES2PLUS (RATE_IN_3430ES2 | RATE_IN_36XX) | ||
209 | |||
210 | #endif | 294 | #endif |
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index d265018f5e6b..fe83e901ba6c 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h | |||
@@ -87,4 +87,8 @@ void omap2_set_globals_uart(struct omap_globals *); | |||
87 | } \ | 87 | } \ |
88 | }) | 88 | }) |
89 | 89 | ||
90 | extern struct device *omap2_get_mpuss_device(void); | ||
91 | extern struct device *omap2_get_dsp_device(void); | ||
92 | extern struct device *omap2_get_l3_device(void); | ||
93 | |||
90 | #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ | 94 | #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ |
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 3ee41d711492..728fbb9dd549 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 @@ | |||
1 | /* | 1 | /* |
2 | * omap-pm.h - OMAP power management interface | 2 | * omap-pm.h - OMAP power management interface |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Texas Instruments, Inc. | 4 | * Copyright (C) 2008-2010 Texas Instruments, Inc. |
5 | * Copyright (C) 2008-2009 Nokia Corporation | 5 | * Copyright (C) 2008-2010 Nokia Corporation |
6 | * Paul Walmsley | 6 | * Paul Walmsley |
7 | * | 7 | * |
8 | * Interface developed by (in alphabetical order): Karthik Dasu, Jouni | 8 | * Interface developed by (in alphabetical order): Karthik Dasu, Jouni |
@@ -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 | ||
@@ -89,7 +90,7 @@ void omap_pm_if_exit(void); | |||
89 | * @t: maximum MPU wakeup latency in microseconds | 90 | * @t: maximum MPU wakeup latency in microseconds |
90 | * | 91 | * |
91 | * Request that the maximum interrupt latency for the MPU to be no | 92 | * Request that the maximum interrupt latency for the MPU to be no |
92 | * greater than 't' microseconds. "Interrupt latency" in this case is | 93 | * greater than @t microseconds. "Interrupt latency" in this case is |
93 | * defined as the elapsed time from the occurrence of a hardware or | 94 | * defined as the elapsed time from the occurrence of a hardware or |
94 | * timer interrupt to the time when the device driver's interrupt | 95 | * timer interrupt to the time when the device driver's interrupt |
95 | * service routine has been entered by the MPU. | 96 | * service routine has been entered by the MPU. |
@@ -105,15 +106,19 @@ void omap_pm_if_exit(void); | |||
105 | * elapsed from when a device driver enables a hardware device with | 106 | * elapsed from when a device driver enables a hardware device with |
106 | * clk_enable(), to when the device is ready for register access or | 107 | * clk_enable(), to when the device is ready for register access or |
107 | * other use. To control this device wakeup latency, use | 108 | * other use. To control this device wakeup latency, use |
108 | * set_max_dev_wakeup_lat() | 109 | * omap_pm_set_max_dev_wakeup_lat() |
109 | * | 110 | * |
110 | * Multiple calls to set_max_mpu_wakeup_lat() will replace the | 111 | * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the |
111 | * previous t value. To remove the latency target for the MPU, call | 112 | * previous t value. To remove the latency target for the MPU, call |
112 | * with t = -1. | 113 | * with t = -1. |
113 | * | 114 | * |
114 | * No return value. | 115 | * XXX This constraint will be deprecated soon in favor of the more |
116 | * general omap_pm_set_max_dev_wakeup_lat() | ||
117 | * | ||
118 | * Returns -EINVAL for an invalid argument, -ERANGE if the constraint | ||
119 | * is not satisfiable, or 0 upon success. | ||
115 | */ | 120 | */ |
116 | void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); | 121 | int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); |
117 | 122 | ||
118 | 123 | ||
119 | /** | 124 | /** |
@@ -123,8 +128,8 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); | |||
123 | * @r: minimum throughput (in KiB/s) | 128 | * @r: minimum throughput (in KiB/s) |
124 | * | 129 | * |
125 | * Request that the minimum data throughput on the OCP interconnect | 130 | * Request that the minimum data throughput on the OCP interconnect |
126 | * attached to device 'dev' interconnect agent 'tbus_id' be no less | 131 | * attached to device @dev interconnect agent @tbus_id be no less |
127 | * than 'r' KiB/s. | 132 | * than @r KiB/s. |
128 | * | 133 | * |
129 | * It is expected that the OMAP PM or bus code will use this | 134 | * It is expected that the OMAP PM or bus code will use this |
130 | * information to set the interconnect clock to run at the lowest | 135 | * information to set the interconnect clock to run at the lowest |
@@ -138,40 +143,44 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); | |||
138 | * code will also need to add an minimum L3 interconnect speed | 143 | * code will also need to add an minimum L3 interconnect speed |
139 | * constraint, | 144 | * constraint, |
140 | * | 145 | * |
141 | * Multiple calls to set_min_bus_tput() will replace the previous rate | 146 | * Multiple calls to omap_pm_set_min_bus_tput() will replace the |
142 | * value for this device. To remove the interconnect throughput | 147 | * previous rate value for this device. To remove the interconnect |
143 | * restriction for this device, call with r = 0. | 148 | * throughput restriction for this device, call with r = 0. |
144 | * | 149 | * |
145 | * No return value. | 150 | * Returns -EINVAL for an invalid argument, -ERANGE if the constraint |
151 | * is not satisfiable, or 0 upon success. | ||
146 | */ | 152 | */ |
147 | void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); | 153 | int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); |
148 | 154 | ||
149 | 155 | ||
150 | /** | 156 | /** |
151 | * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency | 157 | * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency |
152 | * @dev: struct device * | 158 | * @req_dev: struct device * requesting the constraint, or NULL if none |
159 | * @dev: struct device * to set the constraint one | ||
153 | * @t: maximum device wakeup latency in microseconds | 160 | * @t: maximum device wakeup latency in microseconds |
154 | * | 161 | * |
155 | * Request that the maximum amount of time necessary for a device to | 162 | * Request that the maximum amount of time necessary for a device @dev |
156 | * become accessible after its clocks are enabled should be no greater | 163 | * to become accessible after its clocks are enabled should be no |
157 | * than 't' microseconds. Specifically, this represents the time from | 164 | * greater than @t microseconds. Specifically, this represents the |
158 | * when a device driver enables device clocks with clk_enable(), to | 165 | * time from when a device driver enables device clocks with |
159 | * when the register reads and writes on the device will succeed. | 166 | * clk_enable(), to when the register reads and writes on the device |
160 | * This function should be called before clk_disable() is called, | 167 | * will succeed. This function should be called before clk_disable() |
161 | * since the power state transition decision may be made during | 168 | * is called, since the power state transition decision may be made |
162 | * clk_disable(). | 169 | * during clk_disable(). |
163 | * | 170 | * |
164 | * It is intended that underlying PM code will use this information to | 171 | * It is intended that underlying PM code will use this information to |
165 | * determine what power state to put the powerdomain enclosing this | 172 | * determine what power state to put the powerdomain enclosing this |
166 | * device into. | 173 | * device into. |
167 | * | 174 | * |
168 | * Multiple calls to set_max_dev_wakeup_lat() will replace the | 175 | * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the |
169 | * previous wakeup latency values for this device. To remove the wakeup | 176 | * previous wakeup latency values for this device. To remove the |
170 | * latency restriction for this device, call with t = -1. | 177 | * wakeup latency restriction for this device, call with t = -1. |
171 | * | 178 | * |
172 | * No return value. | 179 | * Returns -EINVAL for an invalid argument, -ERANGE if the constraint |
180 | * is not satisfiable, or 0 upon success. | ||
173 | */ | 181 | */ |
174 | void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t); | 182 | int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, |
183 | long t); | ||
175 | 184 | ||
176 | 185 | ||
177 | /** | 186 | /** |
@@ -198,10 +207,71 @@ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t); | |||
198 | * value for this device. To remove the maximum DMA latency for this | 207 | * value for this device. To remove the maximum DMA latency for this |
199 | * device, call with t = -1. | 208 | * device, call with t = -1. |
200 | * | 209 | * |
201 | * No return value. | 210 | * Returns -EINVAL for an invalid argument, -ERANGE if the constraint |
211 | * is not satisfiable, or 0 upon success. | ||
202 | */ | 212 | */ |
203 | void omap_pm_set_max_sdma_lat(struct device *dev, long t); | 213 | int omap_pm_set_max_sdma_lat(struct device *dev, long t); |
214 | |||
204 | 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 | */ | ||
274 | int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r); | ||
205 | 275 | ||
206 | /* | 276 | /* |
207 | * DSP Bridge-specific constraints | 277 | * DSP Bridge-specific constraints |
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 3694b622c4ac..25cd9ac3b095 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h | |||
@@ -101,6 +101,8 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, | |||
101 | int omap_device_register(struct omap_device *od); | 101 | int omap_device_register(struct omap_device *od); |
102 | int omap_early_device_register(struct omap_device *od); | 102 | int omap_early_device_register(struct omap_device *od); |
103 | 103 | ||
104 | void __iomem *omap_device_get_rt_va(struct omap_device *od); | ||
105 | |||
104 | /* OMAP PM interface */ | 106 | /* OMAP PM interface */ |
105 | int omap_device_align_pm_lat(struct platform_device *pdev, | 107 | int omap_device_align_pm_lat(struct platform_device *pdev, |
106 | u32 new_wakeup_lat_limit); | 108 | u32 new_wakeup_lat_limit); |
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 0eccc09ac4a9..a4e508dfaba2 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * omap_hwmod macros, structures | 2 | * omap_hwmod macros, structures |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009-2010 Nokia Corporation |
5 | * Paul Walmsley | 5 | * Paul Walmsley |
6 | * | 6 | * |
7 | * Created in collaboration with (alphabetical order): Benoît Cousson, | 7 | * Created in collaboration with (alphabetical order): Benoît Cousson, |
@@ -419,7 +419,7 @@ struct omap_hwmod_class { | |||
419 | * @slaves: ptr to array of OCP ifs that this hwmod can respond on | 419 | * @slaves: ptr to array of OCP ifs that this hwmod can respond on |
420 | * @dev_attr: arbitrary device attributes that can be passed to the driver | 420 | * @dev_attr: arbitrary device attributes that can be passed to the driver |
421 | * @_sysc_cache: internal-use hwmod flags | 421 | * @_sysc_cache: internal-use hwmod flags |
422 | * @_rt_va: cached register target start address (internal use) | 422 | * @_mpu_rt_va: cached register target start address (internal use) |
423 | * @_mpu_port_index: cached MPU register target slave ID (internal use) | 423 | * @_mpu_port_index: cached MPU register target slave ID (internal use) |
424 | * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6) | 424 | * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6) |
425 | * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift | 425 | * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift |
@@ -460,7 +460,7 @@ struct omap_hwmod { | |||
460 | struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */ | 460 | struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */ |
461 | void *dev_attr; | 461 | void *dev_attr; |
462 | u32 _sysc_cache; | 462 | u32 _sysc_cache; |
463 | void __iomem *_rt_va; | 463 | void __iomem *_mpu_rt_va; |
464 | struct list_head node; | 464 | struct list_head node; |
465 | u16 flags; | 465 | u16 flags; |
466 | u8 _mpu_port_index; | 466 | u8 _mpu_port_index; |
@@ -482,11 +482,14 @@ int omap_hwmod_init(struct omap_hwmod **ohs); | |||
482 | int omap_hwmod_register(struct omap_hwmod *oh); | 482 | int omap_hwmod_register(struct omap_hwmod *oh); |
483 | int omap_hwmod_unregister(struct omap_hwmod *oh); | 483 | int omap_hwmod_unregister(struct omap_hwmod *oh); |
484 | struct omap_hwmod *omap_hwmod_lookup(const char *name); | 484 | struct omap_hwmod *omap_hwmod_lookup(const char *name); |
485 | int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)); | 485 | int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), |
486 | int omap_hwmod_late_init(void); | 486 | void *data); |
487 | int omap_hwmod_late_init(u8 skip_setup_idle); | ||
487 | 488 | ||
488 | int omap_hwmod_enable(struct omap_hwmod *oh); | 489 | int omap_hwmod_enable(struct omap_hwmod *oh); |
490 | int _omap_hwmod_enable(struct omap_hwmod *oh); | ||
489 | int omap_hwmod_idle(struct omap_hwmod *oh); | 491 | int omap_hwmod_idle(struct omap_hwmod *oh); |
492 | int _omap_hwmod_idle(struct omap_hwmod *oh); | ||
490 | int omap_hwmod_shutdown(struct omap_hwmod *oh); | 493 | int omap_hwmod_shutdown(struct omap_hwmod *oh); |
491 | 494 | ||
492 | int omap_hwmod_enable_clocks(struct omap_hwmod *oh); | 495 | int omap_hwmod_enable_clocks(struct omap_hwmod *oh); |
@@ -504,6 +507,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh); | |||
504 | int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res); | 507 | int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res); |
505 | 508 | ||
506 | struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh); | 509 | struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh); |
510 | void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh); | ||
507 | 511 | ||
508 | int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh, | 512 | int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh, |
509 | struct omap_hwmod *init_oh); | 513 | struct omap_hwmod *init_oh); |
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index 186bca82cfab..e129ce80c53b 100644 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ b/arch/arm/plat-omap/omap-pm-noop.c | |||
@@ -34,11 +34,11 @@ struct omap_opp *l3_opps; | |||
34 | * Device-driver-originated constraints (via board-*.c files) | 34 | * Device-driver-originated constraints (via board-*.c files) |
35 | */ | 35 | */ |
36 | 36 | ||
37 | void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) | 37 | int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) |
38 | { | 38 | { |
39 | if (!dev || t < -1) { | 39 | if (!dev || t < -1) { |
40 | WARN_ON(1); | 40 | WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); |
41 | return; | 41 | return -EINVAL; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | if (t == -1) | 44 | if (t == -1) |
@@ -58,14 +58,16 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) | |||
58 | * | 58 | * |
59 | * TI CDP code can call constraint_set here. | 59 | * TI CDP code can call constraint_set here. |
60 | */ | 60 | */ |
61 | |||
62 | return 0; | ||
61 | } | 63 | } |
62 | 64 | ||
63 | void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) | 65 | int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) |
64 | { | 66 | { |
65 | if (!dev || (agent_id != OCP_INITIATOR_AGENT && | 67 | if (!dev || (agent_id != OCP_INITIATOR_AGENT && |
66 | agent_id != OCP_TARGET_AGENT)) { | 68 | agent_id != OCP_TARGET_AGENT)) { |
67 | WARN_ON(1); | 69 | WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); |
68 | return; | 70 | return -EINVAL; |
69 | }; | 71 | }; |
70 | 72 | ||
71 | if (r == 0) | 73 | if (r == 0) |
@@ -83,13 +85,16 @@ void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) | |||
83 | * | 85 | * |
84 | * TI CDP code can call constraint_set here on the VDD2 OPP. | 86 | * TI CDP code can call constraint_set here on the VDD2 OPP. |
85 | */ | 87 | */ |
88 | |||
89 | return 0; | ||
86 | } | 90 | } |
87 | 91 | ||
88 | void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t) | 92 | int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, |
93 | long t) | ||
89 | { | 94 | { |
90 | if (!dev || t < -1) { | 95 | if (!req_dev || !dev || t < -1) { |
91 | WARN_ON(1); | 96 | WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); |
92 | return; | 97 | return -EINVAL; |
93 | }; | 98 | }; |
94 | 99 | ||
95 | if (t == -1) | 100 | if (t == -1) |
@@ -111,13 +116,15 @@ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t) | |||
111 | * | 116 | * |
112 | * TI CDP code can call constraint_set here. | 117 | * TI CDP code can call constraint_set here. |
113 | */ | 118 | */ |
119 | |||
120 | return 0; | ||
114 | } | 121 | } |
115 | 122 | ||
116 | void omap_pm_set_max_sdma_lat(struct device *dev, long t) | 123 | int omap_pm_set_max_sdma_lat(struct device *dev, long t) |
117 | { | 124 | { |
118 | if (!dev || t < -1) { | 125 | if (!dev || t < -1) { |
119 | WARN_ON(1); | 126 | WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); |
120 | return; | 127 | return -EINVAL; |
121 | }; | 128 | }; |
122 | 129 | ||
123 | if (t == -1) | 130 | if (t == -1) |
@@ -139,8 +146,36 @@ void omap_pm_set_max_sdma_lat(struct device *dev, long t) | |||
139 | * TI CDP code can call constraint_set here. | 146 | * TI CDP code can call constraint_set here. |
140 | */ | 147 | */ |
141 | 148 | ||
149 | return 0; | ||
142 | } | 150 | } |
143 | 151 | ||
152 | int 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 | } | ||
144 | 179 | ||
145 | /* | 180 | /* |
146 | * DSP Bridge-specific constraints | 181 | * DSP Bridge-specific constraints |
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index f899603051ac..ea0d659fcb1c 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * omap_device implementation | 2 | * omap_device implementation |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009-2010 Nokia Corporation |
5 | * Paul Walmsley, Kevin Hilman | 5 | * Paul Walmsley, Kevin Hilman |
6 | * | 6 | * |
7 | * Developed in collaboration with (alphabetical order): Benoit | 7 | * Developed in collaboration with (alphabetical order): Benoit |
@@ -90,8 +90,11 @@ | |||
90 | #define USE_WAKEUP_LAT 0 | 90 | #define USE_WAKEUP_LAT 0 |
91 | #define IGNORE_WAKEUP_LAT 1 | 91 | #define IGNORE_WAKEUP_LAT 1 |
92 | 92 | ||
93 | 93 | /* | |
94 | #define OMAP_DEVICE_MAGIC 0xf00dcafe | 94 | * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device |
95 | * obtained via container_of() is in fact a struct omap_device | ||
96 | */ | ||
97 | #define OMAP_DEVICE_MAGIC 0xf00dcafe | ||
95 | 98 | ||
96 | /* Private functions */ | 99 | /* Private functions */ |
97 | 100 | ||
@@ -359,7 +362,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, | |||
359 | struct omap_device *od; | 362 | struct omap_device *od; |
360 | char *pdev_name2; | 363 | char *pdev_name2; |
361 | struct resource *res = NULL; | 364 | struct resource *res = NULL; |
362 | int res_count; | 365 | int i, res_count; |
363 | struct omap_hwmod **hwmods; | 366 | struct omap_hwmod **hwmods; |
364 | 367 | ||
365 | if (!ohs || oh_cnt == 0 || !pdev_name) | 368 | if (!ohs || oh_cnt == 0 || !pdev_name) |
@@ -416,6 +419,9 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, | |||
416 | else | 419 | else |
417 | ret = omap_device_register(od); | 420 | ret = omap_device_register(od); |
418 | 421 | ||
422 | for (i = 0; i < oh_cnt; i++) | ||
423 | hwmods[i]->od = od; | ||
424 | |||
419 | if (ret) | 425 | if (ret) |
420 | goto odbs_exit4; | 426 | goto odbs_exit4; |
421 | 427 | ||
@@ -652,6 +658,25 @@ struct powerdomain *omap_device_get_pwrdm(struct omap_device *od) | |||
652 | return omap_hwmod_get_pwrdm(od->hwmods[0]); | 658 | return omap_hwmod_get_pwrdm(od->hwmods[0]); |
653 | } | 659 | } |
654 | 660 | ||
661 | /** | ||
662 | * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base | ||
663 | * @od: struct omap_device * | ||
664 | * | ||
665 | * Return the MPU's virtual address for the base of the hwmod, from | ||
666 | * the ioremap() that the hwmod code does. Only valid if there is one | ||
667 | * hwmod associated with this device. Returns NULL if there are zero | ||
668 | * or more than one hwmods associated with this omap_device; | ||
669 | * otherwise, passes along the return value from | ||
670 | * omap_hwmod_get_mpu_rt_va(). | ||
671 | */ | ||
672 | void __iomem *omap_device_get_rt_va(struct omap_device *od) | ||
673 | { | ||
674 | if (od->hwmods_cnt != 1) | ||
675 | return NULL; | ||
676 | |||
677 | return omap_hwmod_get_mpu_rt_va(od->hwmods[0]); | ||
678 | } | ||
679 | |||
655 | /* | 680 | /* |
656 | * Public functions intended for use in omap_device_pm_latency | 681 | * Public functions intended for use in omap_device_pm_latency |
657 | * .activate_func and .deactivate_func function pointers | 682 | * .activate_func and .deactivate_func function pointers |