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