ARM: OMAP: unwrap strings
[cascardo/linux.git] / arch / arm / mach-omap2 / clockdomain.c
1 /*
2  * OMAP2/3/4 clockdomain framework functions
3  *
4  * Copyright (C) 2008-2011 Texas Instruments, Inc.
5  * Copyright (C) 2008-2011 Nokia Corporation
6  *
7  * Written by Paul Walmsley and Jouni Högander
8  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14 #undef DEBUG
15
16 #include <linux/kernel.h>
17 #include <linux/device.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
21 #include <linux/delay.h>
22 #include <linux/clk.h>
23 #include <linux/limits.h>
24 #include <linux/err.h>
25
26 #include <linux/io.h>
27
28 #include <linux/bitops.h>
29
30 #include <plat/clock.h>
31 #include "clockdomain.h"
32
33 /* clkdm_list contains all registered struct clockdomains */
34 static LIST_HEAD(clkdm_list);
35
36 /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
37 static struct clkdm_autodep *autodeps;
38
39 static struct clkdm_ops *arch_clkdm;
40
41 /* Private functions */
42
43 static struct clockdomain *_clkdm_lookup(const char *name)
44 {
45         struct clockdomain *clkdm, *temp_clkdm;
46
47         if (!name)
48                 return NULL;
49
50         clkdm = NULL;
51
52         list_for_each_entry(temp_clkdm, &clkdm_list, node) {
53                 if (!strcmp(name, temp_clkdm->name)) {
54                         clkdm = temp_clkdm;
55                         break;
56                 }
57         }
58
59         return clkdm;
60 }
61
62 /**
63  * _clkdm_register - register a clockdomain
64  * @clkdm: struct clockdomain * to register
65  *
66  * Adds a clockdomain to the internal clockdomain list.
67  * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
68  * already registered by the provided name, or 0 upon success.
69  */
70 static int _clkdm_register(struct clockdomain *clkdm)
71 {
72         struct powerdomain *pwrdm;
73
74         if (!clkdm || !clkdm->name)
75                 return -EINVAL;
76
77         pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
78         if (!pwrdm) {
79                 pr_err("clockdomain: %s: powerdomain %s does not exist\n",
80                         clkdm->name, clkdm->pwrdm.name);
81                 return -EINVAL;
82         }
83         clkdm->pwrdm.ptr = pwrdm;
84
85         /* Verify that the clockdomain is not already registered */
86         if (_clkdm_lookup(clkdm->name))
87                 return -EEXIST;
88
89         list_add(&clkdm->node, &clkdm_list);
90
91         pwrdm_add_clkdm(pwrdm, clkdm);
92
93         spin_lock_init(&clkdm->lock);
94
95         pr_debug("clockdomain: registered %s\n", clkdm->name);
96
97         return 0;
98 }
99
100 /* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */
101 static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
102                                             struct clkdm_dep *deps)
103 {
104         struct clkdm_dep *cd;
105
106         if (!clkdm || !deps)
107                 return ERR_PTR(-EINVAL);
108
109         for (cd = deps; cd->clkdm_name; cd++) {
110                 if (!cd->clkdm && cd->clkdm_name)
111                         cd->clkdm = _clkdm_lookup(cd->clkdm_name);
112
113                 if (cd->clkdm == clkdm)
114                         break;
115         }
116
117         if (!cd->clkdm_name)
118                 return ERR_PTR(-ENOENT);
119
120         return cd;
121 }
122
123 /*
124  * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store
125  * @autodep: struct clkdm_autodep * to resolve
126  *
127  * Resolve autodep clockdomain names to clockdomain pointers via
128  * clkdm_lookup() and store the pointers in the autodep structure.  An
129  * "autodep" is a clockdomain sleep/wakeup dependency that is
130  * automatically added and removed whenever clocks in the associated
131  * clockdomain are enabled or disabled (respectively) when the
132  * clockdomain is in hardware-supervised mode.  Meant to be called
133  * once at clockdomain layer initialization, since these should remain
134  * fixed for a particular architecture.  No return value.
135  *
136  * XXX autodeps are deprecated and should be removed at the earliest
137  * opportunity
138  */
139 static void _autodep_lookup(struct clkdm_autodep *autodep)
140 {
141         struct clockdomain *clkdm;
142
143         if (!autodep)
144                 return;
145
146         clkdm = clkdm_lookup(autodep->clkdm.name);
147         if (!clkdm) {
148                 pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
149                          autodep->clkdm.name);
150                 clkdm = ERR_PTR(-ENOENT);
151         }
152         autodep->clkdm.ptr = clkdm;
153 }
154
155 /*
156  * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
157  * @clkdm: struct clockdomain *
158  *
159  * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
160  * in hardware-supervised mode.  Meant to be called from clock framework
161  * when a clock inside clockdomain 'clkdm' is enabled.  No return value.
162  *
163  * XXX autodeps are deprecated and should be removed at the earliest
164  * opportunity
165  */
166 void _clkdm_add_autodeps(struct clockdomain *clkdm)
167 {
168         struct clkdm_autodep *autodep;
169
170         if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
171                 return;
172
173         for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
174                 if (IS_ERR(autodep->clkdm.ptr))
175                         continue;
176
177                 pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
178                          clkdm->name, autodep->clkdm.ptr->name);
179
180                 clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
181                 clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
182         }
183 }
184
185 /*
186  * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
187  * @clkdm: struct clockdomain *
188  *
189  * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
190  * in hardware-supervised mode.  Meant to be called from clock framework
191  * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
192  *
193  * XXX autodeps are deprecated and should be removed at the earliest
194  * opportunity
195  */
196 void _clkdm_del_autodeps(struct clockdomain *clkdm)
197 {
198         struct clkdm_autodep *autodep;
199
200         if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
201                 return;
202
203         for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
204                 if (IS_ERR(autodep->clkdm.ptr))
205                         continue;
206
207                 pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
208                          clkdm->name, autodep->clkdm.ptr->name);
209
210                 clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
211                 clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
212         }
213 }
214
215 /**
216  * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
217  * @clkdm: clockdomain that we are resolving dependencies for
218  * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
219  *
220  * Iterates through @clkdm_deps, looking up the struct clockdomain named by
221  * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
222  * No return value.
223  */
224 static void _resolve_clkdm_deps(struct clockdomain *clkdm,
225                                 struct clkdm_dep *clkdm_deps)
226 {
227         struct clkdm_dep *cd;
228
229         for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
230                 if (cd->clkdm)
231                         continue;
232                 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
233
234                 WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
235                      clkdm->name, cd->clkdm_name);
236         }
237 }
238
239 /* Public functions */
240
241 /**
242  * clkdm_register_platform_funcs - register clockdomain implementation fns
243  * @co: func pointers for arch specific implementations
244  *
245  * Register the list of function pointers used to implement the
246  * clockdomain functions on different OMAP SoCs.  Should be called
247  * before any other clkdm_register*() function.  Returns -EINVAL if
248  * @co is null, -EEXIST if platform functions have already been
249  * registered, or 0 upon success.
250  */
251 int clkdm_register_platform_funcs(struct clkdm_ops *co)
252 {
253         if (!co)
254                 return -EINVAL;
255
256         if (arch_clkdm)
257                 return -EEXIST;
258
259         arch_clkdm = co;
260
261         return 0;
262 };
263
264 /**
265  * clkdm_register_clkdms - register SoC clockdomains
266  * @cs: pointer to an array of struct clockdomain to register
267  *
268  * Register the clockdomains available on a particular OMAP SoC.  Must
269  * be called after clkdm_register_platform_funcs().  May be called
270  * multiple times.  Returns -EACCES if called before
271  * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
272  * null; or 0 upon success.
273  */
274 int clkdm_register_clkdms(struct clockdomain **cs)
275 {
276         struct clockdomain **c = NULL;
277
278         if (!arch_clkdm)
279                 return -EACCES;
280
281         if (!cs)
282                 return -EINVAL;
283
284         for (c = cs; *c; c++)
285                 _clkdm_register(*c);
286
287         return 0;
288 }
289
290 /**
291  * clkdm_register_autodeps - register autodeps (if required)
292  * @ia: pointer to a static array of struct clkdm_autodep to register
293  *
294  * Register clockdomain "automatic dependencies."  These are
295  * clockdomain wakeup and sleep dependencies that are automatically
296  * added whenever the first clock inside a clockdomain is enabled, and
297  * removed whenever the last clock inside a clockdomain is disabled.
298  * These are currently only used on OMAP3 devices, and are deprecated,
299  * since they waste energy.  However, until the OMAP2/3 IP block
300  * enable/disable sequence can be converted to match the OMAP4
301  * sequence, they are needed.
302  *
303  * Must be called only after all of the SoC clockdomains are
304  * registered, since the function will resolve autodep clockdomain
305  * names into clockdomain pointers.
306  *
307  * The struct clkdm_autodep @ia array must be static, as this function
308  * does not copy the array elements.
309  *
310  * Returns -EACCES if called before any clockdomains have been
311  * registered, -EINVAL if called with a null @ia argument, -EEXIST if
312  * autodeps have already been registered, or 0 upon success.
313  */
314 int clkdm_register_autodeps(struct clkdm_autodep *ia)
315 {
316         struct clkdm_autodep *a = NULL;
317
318         if (list_empty(&clkdm_list))
319                 return -EACCES;
320
321         if (!ia)
322                 return -EINVAL;
323
324         if (autodeps)
325                 return -EEXIST;
326
327         autodeps = ia;
328         for (a = autodeps; a->clkdm.ptr; a++)
329                 _autodep_lookup(a);
330
331         return 0;
332 }
333
334 /**
335  * clkdm_complete_init - set up the clockdomain layer
336  *
337  * Put all clockdomains into software-supervised mode; PM code should
338  * later enable hardware-supervised mode as appropriate.  Must be
339  * called after clkdm_register_clkdms().  Returns -EACCES if called
340  * before clkdm_register_clkdms(), or 0 upon success.
341  */
342 int clkdm_complete_init(void)
343 {
344         struct clockdomain *clkdm;
345
346         if (list_empty(&clkdm_list))
347                 return -EACCES;
348
349         list_for_each_entry(clkdm, &clkdm_list, node) {
350                 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
351                         clkdm_wakeup(clkdm);
352                 else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
353                         clkdm_deny_idle(clkdm);
354
355                 _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
356                 clkdm_clear_all_wkdeps(clkdm);
357
358                 _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
359                 clkdm_clear_all_sleepdeps(clkdm);
360         }
361
362         return 0;
363 }
364
365 /**
366  * clkdm_lookup - look up a clockdomain by name, return a pointer
367  * @name: name of clockdomain
368  *
369  * Find a registered clockdomain by its name @name.  Returns a pointer
370  * to the struct clockdomain if found, or NULL otherwise.
371  */
372 struct clockdomain *clkdm_lookup(const char *name)
373 {
374         struct clockdomain *clkdm, *temp_clkdm;
375
376         if (!name)
377                 return NULL;
378
379         clkdm = NULL;
380
381         list_for_each_entry(temp_clkdm, &clkdm_list, node) {
382                 if (!strcmp(name, temp_clkdm->name)) {
383                         clkdm = temp_clkdm;
384                         break;
385                 }
386         }
387
388         return clkdm;
389 }
390
391 /**
392  * clkdm_for_each - call function on each registered clockdomain
393  * @fn: callback function *
394  *
395  * Call the supplied function @fn for each registered clockdomain.
396  * The callback function @fn can return anything but 0 to bail
397  * out early from the iterator.  The callback function is called with
398  * the clkdm_mutex held, so no clockdomain structure manipulation
399  * functions should be called from the callback, although hardware
400  * clockdomain control functions are fine.  Returns the last return
401  * value of the callback function, which should be 0 for success or
402  * anything else to indicate failure; or -EINVAL if the function pointer
403  * is null.
404  */
405 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
406                         void *user)
407 {
408         struct clockdomain *clkdm;
409         int ret = 0;
410
411         if (!fn)
412                 return -EINVAL;
413
414         list_for_each_entry(clkdm, &clkdm_list, node) {
415                 ret = (*fn)(clkdm, user);
416                 if (ret)
417                         break;
418         }
419
420         return ret;
421 }
422
423
424 /**
425  * clkdm_get_pwrdm - return a ptr to the pwrdm that this clkdm resides in
426  * @clkdm: struct clockdomain *
427  *
428  * Return a pointer to the struct powerdomain that the specified clockdomain
429  * @clkdm exists in, or returns NULL if @clkdm is NULL.
430  */
431 struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
432 {
433         if (!clkdm)
434                 return NULL;
435
436         return clkdm->pwrdm.ptr;
437 }
438
439
440 /* Hardware clockdomain control */
441
442 /**
443  * clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1
444  * @clkdm1: wake this struct clockdomain * up (dependent)
445  * @clkdm2: when this struct clockdomain * wakes up (source)
446  *
447  * When the clockdomain represented by @clkdm2 wakes up, wake up
448  * @clkdm1. Implemented in hardware on the OMAP, this feature is
449  * designed to reduce wakeup latency of the dependent clockdomain @clkdm1.
450  * Returns -EINVAL if presented with invalid clockdomain pointers,
451  * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon
452  * success.
453  */
454 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
455 {
456         struct clkdm_dep *cd;
457         int ret = 0;
458
459         if (!clkdm1 || !clkdm2)
460                 return -EINVAL;
461
462         cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
463         if (IS_ERR(cd))
464                 ret = PTR_ERR(cd);
465
466         if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
467                 ret = -EINVAL;
468
469         if (ret) {
470                 pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
471                          clkdm1->name, clkdm2->name);
472                 return ret;
473         }
474
475         if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
476                 pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
477                          clkdm1->name, clkdm2->name);
478
479                 ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
480         }
481
482         return ret;
483 }
484
485 /**
486  * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1
487  * @clkdm1: wake this struct clockdomain * up (dependent)
488  * @clkdm2: when this struct clockdomain * wakes up (source)
489  *
490  * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2
491  * wakes up.  Returns -EINVAL if presented with invalid clockdomain
492  * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or
493  * 0 upon success.
494  */
495 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
496 {
497         struct clkdm_dep *cd;
498         int ret = 0;
499
500         if (!clkdm1 || !clkdm2)
501                 return -EINVAL;
502
503         cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
504         if (IS_ERR(cd))
505                 ret = PTR_ERR(cd);
506
507         if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
508                 ret = -EINVAL;
509
510         if (ret) {
511                 pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
512                          clkdm1->name, clkdm2->name);
513                 return ret;
514         }
515
516         if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
517                 pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
518                          clkdm1->name, clkdm2->name);
519
520                 ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
521         }
522
523         return ret;
524 }
525
526 /**
527  * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1
528  * @clkdm1: wake this struct clockdomain * up (dependent)
529  * @clkdm2: when this struct clockdomain * wakes up (source)
530  *
531  * Return 1 if a hardware wakeup dependency exists wherein @clkdm1 will be
532  * awoken when @clkdm2 wakes up; 0 if dependency is not set; -EINVAL
533  * if either clockdomain pointer is invalid; or -ENOENT if the hardware
534  * is incapable.
535  *
536  * REVISIT: Currently this function only represents software-controllable
537  * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
538  * yet handled here.
539  */
540 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
541 {
542         struct clkdm_dep *cd;
543         int ret = 0;
544
545         if (!clkdm1 || !clkdm2)
546                 return -EINVAL;
547
548         cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
549         if (IS_ERR(cd))
550                 ret = PTR_ERR(cd);
551
552         if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
553                 ret = -EINVAL;
554
555         if (ret) {
556                 pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
557                          clkdm1->name, clkdm2->name);
558                 return ret;
559         }
560
561         /* XXX It's faster to return the atomic wkdep_usecount */
562         return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
563 }
564
565 /**
566  * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm
567  * @clkdm: struct clockdomain * to remove all wakeup dependencies from
568  *
569  * Remove all inter-clockdomain wakeup dependencies that could cause
570  * @clkdm to wake.  Intended to be used during boot to initialize the
571  * PRCM to a known state, after all clockdomains are put into swsup idle
572  * and woken up.  Returns -EINVAL if @clkdm pointer is invalid, or
573  * 0 upon success.
574  */
575 int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
576 {
577         if (!clkdm)
578                 return -EINVAL;
579
580         if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
581                 return -EINVAL;
582
583         return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
584 }
585
586 /**
587  * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
588  * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
589  * @clkdm2: when this struct clockdomain * is active (source)
590  *
591  * Prevent @clkdm1 from automatically going inactive (and then to
592  * retention or off) if @clkdm2 is active.  Returns -EINVAL if
593  * presented with invalid clockdomain pointers or called on a machine
594  * that does not support software-configurable hardware sleep
595  * dependencies, -ENOENT if the specified dependency cannot be set in
596  * hardware, or 0 upon success.
597  */
598 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
599 {
600         struct clkdm_dep *cd;
601         int ret = 0;
602
603         if (!clkdm1 || !clkdm2)
604                 return -EINVAL;
605
606         cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
607         if (IS_ERR(cd))
608                 ret = PTR_ERR(cd);
609
610         if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
611                 ret = -EINVAL;
612
613         if (ret) {
614                 pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
615                          clkdm1->name, clkdm2->name);
616                 return ret;
617         }
618
619         if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
620                 pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
621                          clkdm1->name, clkdm2->name);
622
623                 ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
624         }
625
626         return ret;
627 }
628
629 /**
630  * clkdm_del_sleepdep - remove a sleep dependency from clkdm2 to clkdm1
631  * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
632  * @clkdm2: when this struct clockdomain * is active (source)
633  *
634  * Allow @clkdm1 to automatically go inactive (and then to retention or
635  * off), independent of the activity state of @clkdm2.  Returns -EINVAL
636  * if presented with invalid clockdomain pointers or called on a machine
637  * that does not support software-configurable hardware sleep dependencies,
638  * -ENOENT if the specified dependency cannot be cleared in hardware, or
639  * 0 upon success.
640  */
641 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
642 {
643         struct clkdm_dep *cd;
644         int ret = 0;
645
646         if (!clkdm1 || !clkdm2)
647                 return -EINVAL;
648
649         cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
650         if (IS_ERR(cd))
651                 ret = PTR_ERR(cd);
652
653         if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
654                 ret = -EINVAL;
655
656         if (ret) {
657                 pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
658                          clkdm1->name, clkdm2->name);
659                 return ret;
660         }
661
662         if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
663                 pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
664                          clkdm1->name, clkdm2->name);
665
666                 ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
667         }
668
669         return ret;
670 }
671
672 /**
673  * clkdm_read_sleepdep - read sleep dependency state from clkdm2 to clkdm1
674  * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
675  * @clkdm2: when this struct clockdomain * is active (source)
676  *
677  * Return 1 if a hardware sleep dependency exists wherein @clkdm1 will
678  * not be allowed to automatically go inactive if @clkdm2 is active;
679  * 0 if @clkdm1's automatic power state inactivity transition is independent
680  * of @clkdm2's; -EINVAL if either clockdomain pointer is invalid or called
681  * on a machine that does not support software-configurable hardware sleep
682  * dependencies; or -ENOENT if the hardware is incapable.
683  *
684  * REVISIT: Currently this function only represents software-controllable
685  * sleep dependencies.  Sleep dependencies fixed in hardware are not
686  * yet handled here.
687  */
688 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
689 {
690         struct clkdm_dep *cd;
691         int ret = 0;
692
693         if (!clkdm1 || !clkdm2)
694                 return -EINVAL;
695
696         cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
697         if (IS_ERR(cd))
698                 ret = PTR_ERR(cd);
699
700         if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
701                 ret = -EINVAL;
702
703         if (ret) {
704                 pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
705                          clkdm1->name, clkdm2->name);
706                 return ret;
707         }
708
709         /* XXX It's faster to return the atomic sleepdep_usecount */
710         return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
711 }
712
713 /**
714  * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm
715  * @clkdm: struct clockdomain * to remove all sleep dependencies from
716  *
717  * Remove all inter-clockdomain sleep dependencies that could prevent
718  * @clkdm from idling.  Intended to be used during boot to initialize the
719  * PRCM to a known state, after all clockdomains are put into swsup idle
720  * and woken up.  Returns -EINVAL if @clkdm pointer is invalid, or
721  * 0 upon success.
722  */
723 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
724 {
725         if (!clkdm)
726                 return -EINVAL;
727
728         if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
729                 return -EINVAL;
730
731         return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
732 }
733
734 /**
735  * clkdm_sleep - force clockdomain sleep transition
736  * @clkdm: struct clockdomain *
737  *
738  * Instruct the CM to force a sleep transition on the specified
739  * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if
740  * clockdomain does not support software-initiated sleep; 0 upon
741  * success.
742  */
743 int clkdm_sleep(struct clockdomain *clkdm)
744 {
745         int ret;
746         unsigned long flags;
747
748         if (!clkdm)
749                 return -EINVAL;
750
751         if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
752                 pr_debug("clockdomain: %s does not support forcing sleep via software\n",
753                          clkdm->name);
754                 return -EINVAL;
755         }
756
757         if (!arch_clkdm || !arch_clkdm->clkdm_sleep)
758                 return -EINVAL;
759
760         pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
761
762         spin_lock_irqsave(&clkdm->lock, flags);
763         clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
764         ret = arch_clkdm->clkdm_sleep(clkdm);
765         spin_unlock_irqrestore(&clkdm->lock, flags);
766         return ret;
767 }
768
769 /**
770  * clkdm_wakeup - force clockdomain wakeup transition
771  * @clkdm: struct clockdomain *
772  *
773  * Instruct the CM to force a wakeup transition on the specified
774  * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if the
775  * clockdomain does not support software-controlled wakeup; 0 upon
776  * success.
777  */
778 int clkdm_wakeup(struct clockdomain *clkdm)
779 {
780         int ret;
781         unsigned long flags;
782
783         if (!clkdm)
784                 return -EINVAL;
785
786         if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
787                 pr_debug("clockdomain: %s does not support forcing wakeup via software\n",
788                          clkdm->name);
789                 return -EINVAL;
790         }
791
792         if (!arch_clkdm || !arch_clkdm->clkdm_wakeup)
793                 return -EINVAL;
794
795         pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
796
797         spin_lock_irqsave(&clkdm->lock, flags);
798         clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
799         ret = arch_clkdm->clkdm_wakeup(clkdm);
800         ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
801         spin_unlock_irqrestore(&clkdm->lock, flags);
802         return ret;
803 }
804
805 /**
806  * clkdm_allow_idle - enable hwsup idle transitions for clkdm
807  * @clkdm: struct clockdomain *
808  *
809  * Allow the hardware to automatically switch the clockdomain @clkdm into
810  * active or idle states, as needed by downstream clocks.  If the
811  * clockdomain has any downstream clocks enabled in the clock
812  * framework, wkdep/sleepdep autodependencies are added; this is so
813  * device drivers can read and write to the device.  No return value.
814  */
815 void clkdm_allow_idle(struct clockdomain *clkdm)
816 {
817         unsigned long flags;
818
819         if (!clkdm)
820                 return;
821
822         if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
823                 pr_debug("clock: %s: automatic idle transitions cannot be enabled\n",
824                          clkdm->name);
825                 return;
826         }
827
828         if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
829                 return;
830
831         pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
832                  clkdm->name);
833
834         spin_lock_irqsave(&clkdm->lock, flags);
835         clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
836         arch_clkdm->clkdm_allow_idle(clkdm);
837         pwrdm_state_switch(clkdm->pwrdm.ptr);
838         spin_unlock_irqrestore(&clkdm->lock, flags);
839 }
840
841 /**
842  * clkdm_deny_idle - disable hwsup idle transitions for clkdm
843  * @clkdm: struct clockdomain *
844  *
845  * Prevent the hardware from automatically switching the clockdomain
846  * @clkdm into inactive or idle states.  If the clockdomain has
847  * downstream clocks enabled in the clock framework, wkdep/sleepdep
848  * autodependencies are removed.  No return value.
849  */
850 void clkdm_deny_idle(struct clockdomain *clkdm)
851 {
852         unsigned long flags;
853
854         if (!clkdm)
855                 return;
856
857         if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
858                 pr_debug("clockdomain: %s: automatic idle transitions cannot be disabled\n",
859                          clkdm->name);
860                 return;
861         }
862
863         if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
864                 return;
865
866         pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
867                  clkdm->name);
868
869         spin_lock_irqsave(&clkdm->lock, flags);
870         clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
871         arch_clkdm->clkdm_deny_idle(clkdm);
872         pwrdm_state_switch(clkdm->pwrdm.ptr);
873         spin_unlock_irqrestore(&clkdm->lock, flags);
874 }
875
876 /**
877  * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled?
878  * @clkdm: struct clockdomain *
879  *
880  * Returns true if clockdomain @clkdm currently has
881  * hardware-supervised idle enabled, or false if it does not or if
882  * @clkdm is NULL.  It is only valid to call this function after
883  * clkdm_init() has been called.  This function does not actually read
884  * bits from the hardware; it instead tests an in-memory flag that is
885  * changed whenever the clockdomain code changes the auto-idle mode.
886  */
887 bool clkdm_in_hwsup(struct clockdomain *clkdm)
888 {
889         bool ret;
890         unsigned long flags;
891
892         if (!clkdm)
893                 return false;
894
895         spin_lock_irqsave(&clkdm->lock, flags);
896         ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
897         spin_unlock_irqrestore(&clkdm->lock, flags);
898
899         return ret;
900 }
901
902 /* Clockdomain-to-clock/hwmod framework interface code */
903
904 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
905 {
906         unsigned long flags;
907
908         if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
909                 return -EINVAL;
910
911         /*
912          * For arch's with no autodeps, clkcm_clk_enable
913          * should be called for every clock instance or hwmod that is
914          * enabled, so the clkdm can be force woken up.
915          */
916         if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
917                 return 0;
918
919         spin_lock_irqsave(&clkdm->lock, flags);
920         arch_clkdm->clkdm_clk_enable(clkdm);
921         pwrdm_state_switch(clkdm->pwrdm.ptr);
922         spin_unlock_irqrestore(&clkdm->lock, flags);
923
924         pr_debug("clockdomain: %s: enabled\n", clkdm->name);
925
926         return 0;
927 }
928
929 static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
930 {
931         unsigned long flags;
932
933         if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
934                 return -EINVAL;
935
936         if (atomic_read(&clkdm->usecount) == 0) {
937                 WARN_ON(1); /* underflow */
938                 return -ERANGE;
939         }
940
941         if (atomic_dec_return(&clkdm->usecount) > 0)
942                 return 0;
943
944         spin_lock_irqsave(&clkdm->lock, flags);
945         arch_clkdm->clkdm_clk_disable(clkdm);
946         pwrdm_state_switch(clkdm->pwrdm.ptr);
947         spin_unlock_irqrestore(&clkdm->lock, flags);
948
949         pr_debug("clockdomain: %s: disabled\n", clkdm->name);
950
951         return 0;
952 }
953
954 /**
955  * clkdm_clk_enable - add an enabled downstream clock to this clkdm
956  * @clkdm: struct clockdomain *
957  * @clk: struct clk * of the enabled downstream clock
958  *
959  * Increment the usecount of the clockdomain @clkdm and ensure that it
960  * is awake before @clk is enabled.  Intended to be called by
961  * clk_enable() code.  If the clockdomain is in software-supervised
962  * idle mode, force the clockdomain to wake.  If the clockdomain is in
963  * hardware-supervised idle mode, add clkdm-pwrdm autodependencies, to
964  * ensure that devices in the clockdomain can be read from/written to
965  * by on-chip processors.  Returns -EINVAL if passed null pointers;
966  * returns 0 upon success or if the clockdomain is in hwsup idle mode.
967  */
968 int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
969 {
970         /*
971          * XXX Rewrite this code to maintain a list of enabled
972          * downstream clocks for debugging purposes?
973          */
974
975         if (!clk)
976                 return -EINVAL;
977
978         return _clkdm_clk_hwmod_enable(clkdm);
979 }
980
981 /**
982  * clkdm_clk_disable - remove an enabled downstream clock from this clkdm
983  * @clkdm: struct clockdomain *
984  * @clk: struct clk * of the disabled downstream clock
985  *
986  * Decrement the usecount of this clockdomain @clkdm when @clk is
987  * disabled.  Intended to be called by clk_disable() code.  If the
988  * clockdomain usecount goes to 0, put the clockdomain to sleep
989  * (software-supervised mode) or remove the clkdm autodependencies
990  * (hardware-supervised mode).  Returns -EINVAL if passed null
991  * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0
992  * upon success or if the clockdomain is in hwsup idle mode.
993  */
994 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
995 {
996         /*
997          * XXX Rewrite this code to maintain a list of enabled
998          * downstream clocks for debugging purposes?
999          */
1000
1001         if (!clk)
1002                 return -EINVAL;
1003
1004         return _clkdm_clk_hwmod_disable(clkdm);
1005 }
1006
1007 /**
1008  * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
1009  * @clkdm: struct clockdomain *
1010  * @oh: struct omap_hwmod * of the enabled downstream hwmod
1011  *
1012  * Increment the usecount of the clockdomain @clkdm and ensure that it
1013  * is awake before @oh is enabled. Intended to be called by
1014  * module_enable() code.
1015  * If the clockdomain is in software-supervised idle mode, force the
1016  * clockdomain to wake.  If the clockdomain is in hardware-supervised idle
1017  * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the
1018  * clockdomain can be read from/written to by on-chip processors.
1019  * Returns -EINVAL if passed null pointers;
1020  * returns 0 upon success or if the clockdomain is in hwsup idle mode.
1021  */
1022 int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
1023 {
1024         /* The clkdm attribute does not exist yet prior OMAP4 */
1025         if (cpu_is_omap24xx() || cpu_is_omap34xx())
1026                 return 0;
1027
1028         /*
1029          * XXX Rewrite this code to maintain a list of enabled
1030          * downstream hwmods for debugging purposes?
1031          */
1032
1033         if (!oh)
1034                 return -EINVAL;
1035
1036         return _clkdm_clk_hwmod_enable(clkdm);
1037 }
1038
1039 /**
1040  * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
1041  * @clkdm: struct clockdomain *
1042  * @oh: struct omap_hwmod * of the disabled downstream hwmod
1043  *
1044  * Decrement the usecount of this clockdomain @clkdm when @oh is
1045  * disabled. Intended to be called by module_disable() code.
1046  * If the clockdomain usecount goes to 0, put the clockdomain to sleep
1047  * (software-supervised mode) or remove the clkdm autodependencies
1048  * (hardware-supervised mode).
1049  * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount
1050  * underflows; or returns 0 upon success or if the clockdomain is in hwsup
1051  * idle mode.
1052  */
1053 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
1054 {
1055         /* The clkdm attribute does not exist yet prior OMAP4 */
1056         if (cpu_is_omap24xx() || cpu_is_omap34xx())
1057                 return 0;
1058
1059         /*
1060          * XXX Rewrite this code to maintain a list of enabled
1061          * downstream hwmods for debugging purposes?
1062          */
1063
1064         if (!oh)
1065                 return -EINVAL;
1066
1067         return _clkdm_clk_hwmod_disable(clkdm);
1068 }
1069