aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clockdomain.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/clockdomain.c')
-rw-r--r--arch/arm/mach-omap2/clockdomain.c149
1 files changed, 102 insertions, 47 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8f0890685d7b..8480ee4344ea 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -73,9 +73,6 @@ static int _clkdm_register(struct clockdomain *clkdm)
73 if (!clkdm || !clkdm->name) 73 if (!clkdm || !clkdm->name)
74 return -EINVAL; 74 return -EINVAL;
75 75
76 if (!omap_chip_is(clkdm->omap_chip))
77 return -EINVAL;
78
79 pwrdm = pwrdm_lookup(clkdm->pwrdm.name); 76 pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
80 if (!pwrdm) { 77 if (!pwrdm) {
81 pr_err("clockdomain: %s: powerdomain %s does not exist\n", 78 pr_err("clockdomain: %s: powerdomain %s does not exist\n",
@@ -105,13 +102,10 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
105{ 102{
106 struct clkdm_dep *cd; 103 struct clkdm_dep *cd;
107 104
108 if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip)) 105 if (!clkdm || !deps)
109 return ERR_PTR(-EINVAL); 106 return ERR_PTR(-EINVAL);
110 107
111 for (cd = deps; cd->clkdm_name; cd++) { 108 for (cd = deps; cd->clkdm_name; cd++) {
112 if (!omap_chip_is(cd->omap_chip))
113 continue;
114
115 if (!cd->clkdm && cd->clkdm_name) 109 if (!cd->clkdm && cd->clkdm_name)
116 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 110 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
117 111
@@ -148,9 +142,6 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
148 if (!autodep) 142 if (!autodep)
149 return; 143 return;
150 144
151 if (!omap_chip_is(autodep->omap_chip))
152 return;
153
154 clkdm = clkdm_lookup(autodep->clkdm.name); 145 clkdm = clkdm_lookup(autodep->clkdm.name);
155 if (!clkdm) { 146 if (!clkdm) {
156 pr_err("clockdomain: autodeps: clockdomain %s does not exist\n", 147 pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
@@ -182,9 +173,6 @@ void _clkdm_add_autodeps(struct clockdomain *clkdm)
182 if (IS_ERR(autodep->clkdm.ptr)) 173 if (IS_ERR(autodep->clkdm.ptr))
183 continue; 174 continue;
184 175
185 if (!omap_chip_is(autodep->omap_chip))
186 continue;
187
188 pr_debug("clockdomain: adding %s sleepdep/wkdep for " 176 pr_debug("clockdomain: adding %s sleepdep/wkdep for "
189 "clkdm %s\n", autodep->clkdm.ptr->name, 177 "clkdm %s\n", autodep->clkdm.ptr->name,
190 clkdm->name); 178 clkdm->name);
@@ -216,9 +204,6 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm)
216 if (IS_ERR(autodep->clkdm.ptr)) 204 if (IS_ERR(autodep->clkdm.ptr))
217 continue; 205 continue;
218 206
219 if (!omap_chip_is(autodep->omap_chip))
220 continue;
221
222 pr_debug("clockdomain: removing %s sleepdep/wkdep for " 207 pr_debug("clockdomain: removing %s sleepdep/wkdep for "
223 "clkdm %s\n", autodep->clkdm.ptr->name, 208 "clkdm %s\n", autodep->clkdm.ptr->name,
224 clkdm->name); 209 clkdm->name);
@@ -243,8 +228,6 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
243 struct clkdm_dep *cd; 228 struct clkdm_dep *cd;
244 229
245 for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) { 230 for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
246 if (!omap_chip_is(cd->omap_chip))
247 continue;
248 if (cd->clkdm) 231 if (cd->clkdm)
249 continue; 232 continue;
250 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 233 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
@@ -257,43 +240,113 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
257/* Public functions */ 240/* Public functions */
258 241
259/** 242/**
260 * clkdm_init - set up the clockdomain layer 243 * clkdm_register_platform_funcs - register clockdomain implementation fns
261 * @clkdms: optional pointer to an array of clockdomains to register 244 * @co: func pointers for arch specific implementations
262 * @init_autodeps: optional pointer to an array of autodeps to register 245 *
263 * @custom_funcs: func pointers for arch specific implementations 246 * Register the list of function pointers used to implement the
264 * 247 * clockdomain functions on different OMAP SoCs. Should be called
265 * Set up internal state. If a pointer to an array of clockdomains 248 * before any other clkdm_register*() function. Returns -EINVAL if
266 * @clkdms was supplied, loop through the list of clockdomains, 249 * @co is null, -EEXIST if platform functions have already been
267 * register all that are available on the current platform. Similarly, 250 * registered, or 0 upon success.
268 * if a pointer to an array of clockdomain autodependencies 251 */
269 * @init_autodeps was provided, register those. No return value. 252int clkdm_register_platform_funcs(struct clkdm_ops *co)
253{
254 if (!co)
255 return -EINVAL;
256
257 if (arch_clkdm)
258 return -EEXIST;
259
260 arch_clkdm = co;
261
262 return 0;
263};
264
265/**
266 * clkdm_register_clkdms - register SoC clockdomains
267 * @cs: pointer to an array of struct clockdomain to register
268 *
269 * Register the clockdomains available on a particular OMAP SoC. Must
270 * be called after clkdm_register_platform_funcs(). May be called
271 * multiple times. Returns -EACCES if called before
272 * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
273 * null; or 0 upon success.
270 */ 274 */
271void clkdm_init(struct clockdomain **clkdms, 275int clkdm_register_clkdms(struct clockdomain **cs)
272 struct clkdm_autodep *init_autodeps,
273 struct clkdm_ops *custom_funcs)
274{ 276{
275 struct clockdomain **c = NULL; 277 struct clockdomain **c = NULL;
276 struct clockdomain *clkdm;
277 struct clkdm_autodep *autodep = NULL;
278 278
279 if (!custom_funcs) 279 if (!arch_clkdm)
280 WARN(1, "No custom clkdm functions registered\n"); 280 return -EACCES;
281 else 281
282 arch_clkdm = custom_funcs; 282 if (!cs)
283 return -EINVAL;
284
285 for (c = cs; *c; c++)
286 _clkdm_register(*c);
287
288 return 0;
289}
290
291/**
292 * clkdm_register_autodeps - register autodeps (if required)
293 * @ia: pointer to a static array of struct clkdm_autodep to register
294 *
295 * Register clockdomain "automatic dependencies." These are
296 * clockdomain wakeup and sleep dependencies that are automatically
297 * added whenever the first clock inside a clockdomain is enabled, and
298 * removed whenever the last clock inside a clockdomain is disabled.
299 * These are currently only used on OMAP3 devices, and are deprecated,
300 * since they waste energy. However, until the OMAP2/3 IP block
301 * enable/disable sequence can be converted to match the OMAP4
302 * sequence, they are needed.
303 *
304 * Must be called only after all of the SoC clockdomains are
305 * registered, since the function will resolve autodep clockdomain
306 * names into clockdomain pointers.
307 *
308 * The struct clkdm_autodep @ia array must be static, as this function
309 * does not copy the array elements.
310 *
311 * Returns -EACCES if called before any clockdomains have been
312 * registered, -EINVAL if called with a null @ia argument, -EEXIST if
313 * autodeps have already been registered, or 0 upon success.
314 */
315int clkdm_register_autodeps(struct clkdm_autodep *ia)
316{
317 struct clkdm_autodep *a = NULL;
283 318
284 if (clkdms) 319 if (list_empty(&clkdm_list))
285 for (c = clkdms; *c; c++) 320 return -EACCES;
286 _clkdm_register(*c); 321
322 if (!ia)
323 return -EINVAL;
287 324
288 autodeps = init_autodeps;
289 if (autodeps) 325 if (autodeps)
290 for (autodep = autodeps; autodep->clkdm.ptr; autodep++) 326 return -EEXIST;
291 _autodep_lookup(autodep); 327
328 autodeps = ia;
329 for (a = autodeps; a->clkdm.ptr; a++)
330 _autodep_lookup(a);
331
332 return 0;
333}
334
335/**
336 * clkdm_complete_init - set up the clockdomain layer
337 *
338 * Put all clockdomains into software-supervised mode; PM code should
339 * later enable hardware-supervised mode as appropriate. Must be
340 * called after clkdm_register_clkdms(). Returns -EACCES if called
341 * before clkdm_register_clkdms(), or 0 upon success.
342 */
343int clkdm_complete_init(void)
344{
345 struct clockdomain *clkdm;
346
347 if (list_empty(&clkdm_list))
348 return -EACCES;
292 349
293 /*
294 * Put all clockdomains into software-supervised mode; PM code
295 * should later enable hardware-supervised mode as appropriate
296 */
297 list_for_each_entry(clkdm, &clkdm_list, node) { 350 list_for_each_entry(clkdm, &clkdm_list, node) {
298 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) 351 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
299 clkdm_wakeup(clkdm); 352 clkdm_wakeup(clkdm);
@@ -306,6 +359,8 @@ void clkdm_init(struct clockdomain **clkdms,
306 _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs); 359 _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
307 clkdm_clear_all_sleepdeps(clkdm); 360 clkdm_clear_all_sleepdeps(clkdm);
308 } 361 }
362
363 return 0;
309} 364}
310 365
311/** 366/**