aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2008-08-19 04:08:44 -0400
committerTony Lindgren <tony@atomide.com>2008-08-19 04:08:44 -0400
commit8420bb13630032097be911a039cb64b5f62c01da (patch)
treeefd387d9fec6d82dbec44e8d296ddf7fa5ed86c1 /arch/arm
parentd459bfe01f523983a822de8c2d3fe0bd2f2c194e (diff)
ARM: OMAP2: Clockdomain: Connect clockdomain code to powerdomain code
Thie patch adds code to the powerdomain layer to track the clockdomains associated with each powerdomain. It also modifies the clockdomain code to register clockdomains with their corresponding powerdomain when the clockdomain is registered. Signed-off-by: Paul Walmsley <paul@pwsan.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/clockdomain.c4
-rw-r--r--arch/arm/mach-omap2/powerdomain.c136
-rw-r--r--arch/arm/plat-omap/include/mach/powerdomain.h16
3 files changed, 156 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index f867d8f1d0e9..b6ff5aa4726e 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -219,6 +219,8 @@ int clkdm_register(struct clockdomain *clkdm)
219 219
220 list_add(&clkdm->node, &clkdm_list); 220 list_add(&clkdm->node, &clkdm_list);
221 221
222 pwrdm_add_clkdm(pwrdm, clkdm);
223
222 pr_debug("clockdomain: registered %s\n", clkdm->name); 224 pr_debug("clockdomain: registered %s\n", clkdm->name);
223 ret = 0; 225 ret = 0;
224 226
@@ -240,6 +242,8 @@ int clkdm_unregister(struct clockdomain *clkdm)
240 if (!clkdm) 242 if (!clkdm)
241 return -EINVAL; 243 return -EINVAL;
242 244
245 pwrdm_del_clkdm(clkdm->pwrdm, clkdm);
246
243 mutex_lock(&clkdm_mutex); 247 mutex_lock(&clkdm_mutex);
244 list_del(&clkdm->node); 248 list_del(&clkdm->node);
245 mutex_unlock(&clkdm_mutex); 249 mutex_unlock(&clkdm_mutex);
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 1ec003832ef8..9a803492b28f 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -33,6 +33,7 @@
33 33
34#include <mach/cpu.h> 34#include <mach/cpu.h>
35#include <mach/powerdomain.h> 35#include <mach/powerdomain.h>
36#include <mach/clockdomain.h>
36 37
37/* pwrdm_list contains all registered struct powerdomains */ 38/* pwrdm_list contains all registered struct powerdomains */
38static LIST_HEAD(pwrdm_list); 39static LIST_HEAD(pwrdm_list);
@@ -237,6 +238,141 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
237} 238}
238 239
239/** 240/**
241 * pwrdm_add_clkdm - add a clockdomain to a powerdomain
242 * @pwrdm: struct powerdomain * to add the clockdomain to
243 * @clkdm: struct clockdomain * to associate with a powerdomain
244 *
245 * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'. This
246 * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if
247 * presented with invalid pointers; -ENOMEM if memory could not be allocated;
248 * or 0 upon success.
249 */
250int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
251{
252 unsigned long flags;
253 int i;
254 int ret = -EINVAL;
255
256 if (!pwrdm || !clkdm)
257 return -EINVAL;
258
259 pr_debug("powerdomain: associating clockdomain %s with powerdomain "
260 "%s\n", clkdm->name, pwrdm->name);
261
262 write_lock_irqsave(&pwrdm_rwlock, flags);
263
264 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
265 if (!pwrdm->pwrdm_clkdms[i])
266 break;
267#ifdef DEBUG
268 if (pwrdm->pwrdm_clkdms[i] == clkdm) {
269 ret = -EINVAL;
270 goto pac_exit;
271 }
272#endif
273 }
274
275 if (i == PWRDM_MAX_CLKDMS) {
276 pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
277 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
278 WARN_ON(1);
279 ret = -ENOMEM;
280 goto pac_exit;
281 }
282
283 pwrdm->pwrdm_clkdms[i] = clkdm;
284
285 ret = 0;
286
287pac_exit:
288 write_unlock_irqrestore(&pwrdm_rwlock, flags);
289
290 return ret;
291}
292
293/**
294 * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
295 * @pwrdm: struct powerdomain * to add the clockdomain to
296 * @clkdm: struct clockdomain * to associate with a powerdomain
297 *
298 * Dissociate the clockdomain 'clkdm' from the powerdomain
299 * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
300 * -ENOENT if the clkdm was not associated with the powerdomain, or 0
301 * upon success.
302 */
303int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
304{
305 unsigned long flags;
306 int ret = -EINVAL;
307 int i;
308
309 if (!pwrdm || !clkdm)
310 return -EINVAL;
311
312 pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
313 "%s\n", clkdm->name, pwrdm->name);
314
315 write_lock_irqsave(&pwrdm_rwlock, flags);
316
317 for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
318 if (pwrdm->pwrdm_clkdms[i] == clkdm)
319 break;
320
321 if (i == PWRDM_MAX_CLKDMS) {
322 pr_debug("powerdomain: clkdm %s not associated with pwrdm "
323 "%s ?!\n", clkdm->name, pwrdm->name);
324 ret = -ENOENT;
325 goto pdc_exit;
326 }
327
328 pwrdm->pwrdm_clkdms[i] = NULL;
329
330 ret = 0;
331
332pdc_exit:
333 write_unlock_irqrestore(&pwrdm_rwlock, flags);
334
335 return ret;
336}
337
338/**
339 * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
340 * @pwrdm: struct powerdomain * to iterate over
341 * @fn: callback function *
342 *
343 * Call the supplied function for each clockdomain in the powerdomain
344 * 'pwrdm'. The callback function can return anything but 0 to bail
345 * out early from the iterator. The callback function is called with
346 * the pwrdm_rwlock held for reading, so no powerdomain structure
347 * manipulation functions should be called from the callback, although
348 * hardware powerdomain control functions are fine. Returns -EINVAL
349 * if presented with invalid pointers; or passes along the last return
350 * value of the callback function, which should be 0 for success or
351 * anything else to indicate failure.
352 */
353int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
354 int (*fn)(struct powerdomain *pwrdm,
355 struct clockdomain *clkdm))
356{
357 unsigned long flags;
358 int ret = 0;
359 int i;
360
361 if (!fn)
362 return -EINVAL;
363
364 read_lock_irqsave(&pwrdm_rwlock, flags);
365
366 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
367 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
368
369 read_unlock_irqrestore(&pwrdm_rwlock, flags);
370
371 return ret;
372}
373
374
375/**
240 * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1 376 * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
241 * @pwrdm1: wake this struct powerdomain * up (dependent) 377 * @pwrdm1: wake this struct powerdomain * up (dependent)
242 * @pwrdm2: when this struct powerdomain * wakes up (source) 378 * @pwrdm2: when this struct powerdomain * wakes up (source)
diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h
index c8f52c6f8b7e..5fa666fa9be8 100644
--- a/arch/arm/plat-omap/include/mach/powerdomain.h
+++ b/arch/arm/plat-omap/include/mach/powerdomain.h
@@ -44,9 +44,16 @@
44 */ 44 */
45#define PWRDM_MAX_MEM_BANKS 4 45#define PWRDM_MAX_MEM_BANKS 4
46 46
47/*
48 * Maximum number of clockdomains that can be associated with a powerdomain.
49 * CORE powerdomain is probably the worst case.
50 */
51#define PWRDM_MAX_CLKDMS 3
52
47/* XXX A completely arbitrary number. What is reasonable here? */ 53/* XXX A completely arbitrary number. What is reasonable here? */
48#define PWRDM_TRANSITION_BAILOUT 100000 54#define PWRDM_TRANSITION_BAILOUT 100000
49 55
56struct clockdomain;
50struct powerdomain; 57struct powerdomain;
51 58
52/* Encodes dependencies between powerdomains - statically defined */ 59/* Encodes dependencies between powerdomains - statically defined */
@@ -98,6 +105,9 @@ struct powerdomain {
98 /* Possible memory bank pwrstates when pwrdm is ON */ 105 /* Possible memory bank pwrstates when pwrdm is ON */
99 const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS]; 106 const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
100 107
108 /* Clockdomains in this powerdomain */
109 struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
110
101 struct list_head node; 111 struct list_head node;
102 112
103}; 113};
@@ -111,6 +121,12 @@ struct powerdomain *pwrdm_lookup(const char *name);
111 121
112int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)); 122int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm));
113 123
124int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
125int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
126int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
127 int (*fn)(struct powerdomain *pwrdm,
128 struct clockdomain *clkdm));
129
114int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); 130int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
115int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); 131int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
116int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); 132int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);