diff options
Diffstat (limited to 'arch/arm/mach-omap2/clockdomain.c')
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4c3ce9cfd948..0e7d501865b6 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/limits.h> | 24 | #include <linux/limits.h> |
25 | #include <linux/err.h> | ||
25 | 26 | ||
26 | #include <linux/io.h> | 27 | #include <linux/io.h> |
27 | 28 | ||
@@ -71,16 +72,13 @@ static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep) | |||
71 | if (!omap_chip_is(autodep->omap_chip)) | 72 | if (!omap_chip_is(autodep->omap_chip)) |
72 | return; | 73 | return; |
73 | 74 | ||
74 | pwrdm = pwrdm_lookup(autodep->pwrdm_name); | 75 | pwrdm = pwrdm_lookup(autodep->pwrdm.name); |
75 | if (!pwrdm) { | 76 | if (!pwrdm) { |
76 | pr_debug("clockdomain: _autodep_lookup: powerdomain %s " | 77 | pr_err("clockdomain: autodeps: powerdomain %s does not exist\n", |
77 | "does not exist\n", autodep->pwrdm_name); | 78 | autodep->pwrdm.name); |
78 | WARN_ON(1); | 79 | pwrdm = ERR_PTR(-ENOENT); |
79 | return; | ||
80 | } | 80 | } |
81 | autodep->pwrdm = pwrdm; | 81 | autodep->pwrdm.ptr = pwrdm; |
82 | |||
83 | return; | ||
84 | } | 82 | } |
85 | 83 | ||
86 | /* | 84 | /* |
@@ -95,16 +93,19 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm) | |||
95 | { | 93 | { |
96 | struct clkdm_pwrdm_autodep *autodep; | 94 | struct clkdm_pwrdm_autodep *autodep; |
97 | 95 | ||
98 | for (autodep = autodeps; autodep->pwrdm_name; autodep++) { | 96 | for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) { |
99 | if (!autodep->pwrdm) | 97 | if (IS_ERR(autodep->pwrdm.ptr)) |
98 | continue; | ||
99 | |||
100 | if (!omap_chip_is(autodep->omap_chip)) | ||
100 | continue; | 101 | continue; |
101 | 102 | ||
102 | pr_debug("clockdomain: adding %s sleepdep/wkdep for " | 103 | pr_debug("clockdomain: adding %s sleepdep/wkdep for " |
103 | "pwrdm %s\n", autodep->pwrdm_name, | 104 | "pwrdm %s\n", autodep->pwrdm.ptr->name, |
104 | clkdm->pwrdm->name); | 105 | clkdm->pwrdm.ptr->name); |
105 | 106 | ||
106 | pwrdm_add_sleepdep(clkdm->pwrdm, autodep->pwrdm); | 107 | pwrdm_add_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); |
107 | pwrdm_add_wkdep(clkdm->pwrdm, autodep->pwrdm); | 108 | pwrdm_add_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); |
108 | } | 109 | } |
109 | } | 110 | } |
110 | 111 | ||
@@ -120,16 +121,19 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) | |||
120 | { | 121 | { |
121 | struct clkdm_pwrdm_autodep *autodep; | 122 | struct clkdm_pwrdm_autodep *autodep; |
122 | 123 | ||
123 | for (autodep = autodeps; autodep->pwrdm_name; autodep++) { | 124 | for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) { |
124 | if (!autodep->pwrdm) | 125 | if (IS_ERR(autodep->pwrdm.ptr)) |
126 | continue; | ||
127 | |||
128 | if (!omap_chip_is(autodep->omap_chip)) | ||
125 | continue; | 129 | continue; |
126 | 130 | ||
127 | pr_debug("clockdomain: removing %s sleepdep/wkdep for " | 131 | pr_debug("clockdomain: removing %s sleepdep/wkdep for " |
128 | "pwrdm %s\n", autodep->pwrdm_name, | 132 | "pwrdm %s\n", autodep->pwrdm.ptr->name, |
129 | clkdm->pwrdm->name); | 133 | clkdm->pwrdm.ptr->name); |
130 | 134 | ||
131 | pwrdm_del_sleepdep(clkdm->pwrdm, autodep->pwrdm); | 135 | pwrdm_del_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); |
132 | pwrdm_del_wkdep(clkdm->pwrdm, autodep->pwrdm); | 136 | pwrdm_del_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); |
133 | } | 137 | } |
134 | } | 138 | } |
135 | 139 | ||
@@ -179,7 +183,7 @@ void clkdm_init(struct clockdomain **clkdms, | |||
179 | 183 | ||
180 | autodeps = init_autodeps; | 184 | autodeps = init_autodeps; |
181 | if (autodeps) | 185 | if (autodeps) |
182 | for (autodep = autodeps; autodep->pwrdm_name; autodep++) | 186 | for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) |
183 | _autodep_lookup(autodep); | 187 | _autodep_lookup(autodep); |
184 | } | 188 | } |
185 | 189 | ||
@@ -202,20 +206,20 @@ int clkdm_register(struct clockdomain *clkdm) | |||
202 | if (!omap_chip_is(clkdm->omap_chip)) | 206 | if (!omap_chip_is(clkdm->omap_chip)) |
203 | return -EINVAL; | 207 | return -EINVAL; |
204 | 208 | ||
205 | pwrdm = pwrdm_lookup(clkdm->pwrdm_name); | 209 | pwrdm = pwrdm_lookup(clkdm->pwrdm.name); |
206 | if (!pwrdm) { | 210 | if (!pwrdm) { |
207 | pr_debug("clockdomain: clkdm_register %s: powerdomain %s " | 211 | pr_err("clockdomain: %s: powerdomain %s does not exist\n", |
208 | "does not exist\n", clkdm->name, clkdm->pwrdm_name); | 212 | clkdm->name, clkdm->pwrdm.name); |
209 | return -EINVAL; | 213 | return -EINVAL; |
210 | } | 214 | } |
211 | clkdm->pwrdm = pwrdm; | 215 | clkdm->pwrdm.ptr = pwrdm; |
212 | 216 | ||
213 | mutex_lock(&clkdm_mutex); | 217 | mutex_lock(&clkdm_mutex); |
214 | /* Verify that the clockdomain is not already registered */ | 218 | /* Verify that the clockdomain is not already registered */ |
215 | if (_clkdm_lookup(clkdm->name)) { | 219 | if (_clkdm_lookup(clkdm->name)) { |
216 | ret = -EEXIST; | 220 | ret = -EEXIST; |
217 | goto cr_unlock; | 221 | goto cr_unlock; |
218 | }; | 222 | } |
219 | 223 | ||
220 | list_add(&clkdm->node, &clkdm_list); | 224 | list_add(&clkdm->node, &clkdm_list); |
221 | 225 | ||
@@ -242,7 +246,7 @@ int clkdm_unregister(struct clockdomain *clkdm) | |||
242 | if (!clkdm) | 246 | if (!clkdm) |
243 | return -EINVAL; | 247 | return -EINVAL; |
244 | 248 | ||
245 | pwrdm_del_clkdm(clkdm->pwrdm, clkdm); | 249 | pwrdm_del_clkdm(clkdm->pwrdm.ptr, clkdm); |
246 | 250 | ||
247 | mutex_lock(&clkdm_mutex); | 251 | mutex_lock(&clkdm_mutex); |
248 | list_del(&clkdm->node); | 252 | list_del(&clkdm->node); |
@@ -327,7 +331,7 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) | |||
327 | if (!clkdm) | 331 | if (!clkdm) |
328 | return NULL; | 332 | return NULL; |
329 | 333 | ||
330 | return clkdm->pwrdm; | 334 | return clkdm->pwrdm.ptr; |
331 | } | 335 | } |
332 | 336 | ||
333 | 337 | ||
@@ -348,7 +352,7 @@ static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm) | |||
348 | if (!clkdm) | 352 | if (!clkdm) |
349 | return -EINVAL; | 353 | return -EINVAL; |
350 | 354 | ||
351 | v = cm_read_mod_reg(clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); | 355 | v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); |
352 | v &= clkdm->clktrctrl_mask; | 356 | v &= clkdm->clktrctrl_mask; |
353 | v >>= __ffs(clkdm->clktrctrl_mask); | 357 | v >>= __ffs(clkdm->clktrctrl_mask); |
354 | 358 | ||
@@ -380,7 +384,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) | |||
380 | if (cpu_is_omap24xx()) { | 384 | if (cpu_is_omap24xx()) { |
381 | 385 | ||
382 | cm_set_mod_reg_bits(OMAP24XX_FORCESTATE, | 386 | cm_set_mod_reg_bits(OMAP24XX_FORCESTATE, |
383 | clkdm->pwrdm->prcm_offs, PM_PWSTCTRL); | 387 | clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL); |
384 | 388 | ||
385 | } else if (cpu_is_omap34xx()) { | 389 | } else if (cpu_is_omap34xx()) { |
386 | 390 | ||
@@ -388,7 +392,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) | |||
388 | __ffs(clkdm->clktrctrl_mask)); | 392 | __ffs(clkdm->clktrctrl_mask)); |
389 | 393 | ||
390 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, | 394 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, |
391 | clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); | 395 | clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); |
392 | 396 | ||
393 | } else { | 397 | } else { |
394 | BUG(); | 398 | BUG(); |
@@ -422,7 +426,7 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) | |||
422 | if (cpu_is_omap24xx()) { | 426 | if (cpu_is_omap24xx()) { |
423 | 427 | ||
424 | cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE, | 428 | cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE, |
425 | clkdm->pwrdm->prcm_offs, PM_PWSTCTRL); | 429 | clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL); |
426 | 430 | ||
427 | } else if (cpu_is_omap34xx()) { | 431 | } else if (cpu_is_omap34xx()) { |
428 | 432 | ||
@@ -430,7 +434,7 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) | |||
430 | __ffs(clkdm->clktrctrl_mask)); | 434 | __ffs(clkdm->clktrctrl_mask)); |
431 | 435 | ||
432 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, | 436 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, |
433 | clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); | 437 | clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); |
434 | 438 | ||
435 | } else { | 439 | } else { |
436 | BUG(); | 440 | BUG(); |
@@ -478,7 +482,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) | |||
478 | 482 | ||
479 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, | 483 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, |
480 | v << __ffs(clkdm->clktrctrl_mask), | 484 | v << __ffs(clkdm->clktrctrl_mask), |
481 | clkdm->pwrdm->prcm_offs, | 485 | clkdm->pwrdm.ptr->prcm_offs, |
482 | CM_CLKSTCTRL); | 486 | CM_CLKSTCTRL); |
483 | } | 487 | } |
484 | 488 | ||
@@ -516,7 +520,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) | |||
516 | 520 | ||
517 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, | 521 | cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, |
518 | v << __ffs(clkdm->clktrctrl_mask), | 522 | v << __ffs(clkdm->clktrctrl_mask), |
519 | clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); | 523 | clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); |
520 | 524 | ||
521 | if (atomic_read(&clkdm->usecount) > 0) | 525 | if (atomic_read(&clkdm->usecount) > 0) |
522 | _clkdm_del_autodeps(clkdm); | 526 | _clkdm_del_autodeps(clkdm); |
@@ -567,6 +571,8 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) | |||
567 | else | 571 | else |
568 | omap2_clkdm_wakeup(clkdm); | 572 | omap2_clkdm_wakeup(clkdm); |
569 | 573 | ||
574 | pwrdm_wait_transition(clkdm->pwrdm.ptr); | ||
575 | |||
570 | return 0; | 576 | return 0; |
571 | } | 577 | } |
572 | 578 | ||