diff options
| -rw-r--r-- | arch/arm/mach-omap2/clock.c | 135 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 10 |
2 files changed, 99 insertions, 46 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index d1f115d0edad..a6d0b34b7990 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
| @@ -37,9 +37,9 @@ | |||
| 37 | 37 | ||
| 38 | u8 cpu_mask; | 38 | u8 cpu_mask; |
| 39 | 39 | ||
| 40 | /*------------------------------------------------------------------------- | 40 | /* |
| 41 | * OMAP2/3/4 specific clock functions | 41 | * OMAP2+ specific clock functions |
| 42 | *-------------------------------------------------------------------------*/ | 42 | */ |
| 43 | 43 | ||
| 44 | /* Private functions */ | 44 | /* Private functions */ |
| 45 | 45 | ||
| @@ -71,20 +71,6 @@ static void _omap2_module_wait_ready(struct clk *clk) | |||
| 71 | clk->name); | 71 | clk->name); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /* Enables clock without considering parent dependencies or use count | ||
| 75 | * REVISIT: Maybe change this to use clk->enable like on omap1? | ||
| 76 | */ | ||
| 77 | static int _omap2_clk_enable(struct clk *clk) | ||
| 78 | { | ||
| 79 | return clk->ops->enable(clk); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* Disables clock without considering parent dependencies or use count */ | ||
| 83 | static void _omap2_clk_disable(struct clk *clk) | ||
| 84 | { | ||
| 85 | clk->ops->disable(clk); | ||
| 86 | } | ||
| 87 | |||
| 88 | /* Public functions */ | 74 | /* Public functions */ |
| 89 | 75 | ||
| 90 | /** | 76 | /** |
| @@ -245,46 +231,106 @@ const struct clkops clkops_omap2_dflt = { | |||
| 245 | .disable = omap2_dflt_clk_disable, | 231 | .disable = omap2_dflt_clk_disable, |
| 246 | }; | 232 | }; |
| 247 | 233 | ||
| 234 | /** | ||
| 235 | * omap2_clk_disable - disable a clock, if the system is not using it | ||
| 236 | * @clk: struct clk * to disable | ||
| 237 | * | ||
| 238 | * Decrements the usecount on struct clk @clk. If there are no users | ||
| 239 | * left, call the clkops-specific clock disable function to disable it | ||
| 240 | * in hardware. If the clock is part of a clockdomain (which they all | ||
| 241 | * should be), request that the clockdomain be disabled. (It too has | ||
| 242 | * a usecount, and so will not be disabled in the hardware until it no | ||
| 243 | * longer has any users.) If the clock has a parent clock (most of | ||
| 244 | * them do), then call ourselves, recursing on the parent clock. This | ||
| 245 | * can cause an entire branch of the clock tree to be powered off by | ||
| 246 | * simply disabling one clock. Intended to be called with the clockfw_lock | ||
| 247 | * spinlock held. No return value. | ||
| 248 | */ | ||
| 248 | void omap2_clk_disable(struct clk *clk) | 249 | void omap2_clk_disable(struct clk *clk) |
| 249 | { | 250 | { |
| 250 | if (clk->usecount > 0 && !(--clk->usecount)) { | 251 | if (clk->usecount == 0) { |
| 251 | _omap2_clk_disable(clk); | 252 | WARN(1, "clock: %s: omap2_clk_disable() called, but usecount " |
| 252 | if (clk->parent) | 253 | "already 0?", clk->name); |
| 253 | omap2_clk_disable(clk->parent); | 254 | return; |
| 254 | if (clk->clkdm) | ||
| 255 | omap2_clkdm_clk_disable(clk->clkdm, clk); | ||
| 256 | |||
| 257 | } | 255 | } |
| 256 | |||
| 257 | pr_debug("clock: %s: decrementing usecount\n", clk->name); | ||
| 258 | |||
| 259 | clk->usecount--; | ||
| 260 | |||
| 261 | if (clk->usecount > 0) | ||
| 262 | return; | ||
| 263 | |||
| 264 | pr_debug("clock: %s: disabling in hardware\n", clk->name); | ||
| 265 | |||
| 266 | clk->ops->disable(clk); | ||
| 267 | |||
| 268 | if (clk->clkdm) | ||
| 269 | omap2_clkdm_clk_disable(clk->clkdm, clk); | ||
| 270 | |||
| 271 | if (clk->parent) | ||
| 272 | omap2_clk_disable(clk->parent); | ||
| 258 | } | 273 | } |
| 259 | 274 | ||
| 275 | /** | ||
| 276 | * omap2_clk_enable - request that the system enable a clock | ||
| 277 | * @clk: struct clk * to enable | ||
| 278 | * | ||
| 279 | * Increments the usecount on struct clk @clk. If there were no users | ||
| 280 | * previously, then recurse up the clock tree, enabling all of the | ||
| 281 | * clock's parents and all of the parent clockdomains, and finally, | ||
| 282 | * enabling @clk's clockdomain, and @clk itself. Intended to be | ||
| 283 | * called with the clockfw_lock spinlock held. Returns 0 upon success | ||
| 284 | * or a negative error code upon failure. | ||
| 285 | */ | ||
| 260 | int omap2_clk_enable(struct clk *clk) | 286 | int omap2_clk_enable(struct clk *clk) |
| 261 | { | 287 | { |
| 262 | int ret = 0; | 288 | int ret; |
| 263 | 289 | ||
| 264 | if (clk->usecount++ == 0) { | 290 | pr_debug("clock: %s: incrementing usecount\n", clk->name); |
| 265 | if (clk->clkdm) | ||
| 266 | omap2_clkdm_clk_enable(clk->clkdm, clk); | ||
| 267 | 291 | ||
| 268 | if (clk->parent) { | 292 | clk->usecount++; |
| 269 | ret = omap2_clk_enable(clk->parent); | 293 | |
| 270 | if (ret) | 294 | if (clk->usecount > 1) |
| 271 | goto err; | 295 | return 0; |
| 272 | } | ||
| 273 | 296 | ||
| 274 | ret = _omap2_clk_enable(clk); | 297 | pr_debug("clock: %s: enabling in hardware\n", clk->name); |
| 298 | |||
| 299 | if (clk->parent) { | ||
| 300 | ret = omap2_clk_enable(clk->parent); | ||
| 275 | if (ret) { | 301 | if (ret) { |
| 276 | if (clk->parent) | 302 | WARN(1, "clock: %s: could not enable parent %s: %d\n", |
| 277 | omap2_clk_disable(clk->parent); | 303 | clk->name, clk->parent->name, ret); |
| 304 | goto oce_err1; | ||
| 305 | } | ||
| 306 | } | ||
| 278 | 307 | ||
| 279 | goto err; | 308 | if (clk->clkdm) { |
| 309 | ret = omap2_clkdm_clk_enable(clk->clkdm, clk); | ||
| 310 | if (ret) { | ||
| 311 | WARN(1, "clock: %s: could not enable clockdomain %s: " | ||
| 312 | "%d\n", clk->name, clk->clkdm->name, ret); | ||
| 313 | goto oce_err2; | ||
| 280 | } | 314 | } |
| 281 | } | 315 | } |
| 282 | return ret; | ||
| 283 | 316 | ||
| 284 | err: | 317 | ret = clk->ops->enable(clk); |
| 318 | if (ret) { | ||
| 319 | WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret); | ||
| 320 | goto oce_err3; | ||
| 321 | } | ||
| 322 | |||
| 323 | return 0; | ||
| 324 | |||
| 325 | oce_err3: | ||
| 285 | if (clk->clkdm) | 326 | if (clk->clkdm) |
| 286 | omap2_clkdm_clk_disable(clk->clkdm, clk); | 327 | omap2_clkdm_clk_disable(clk->clkdm, clk); |
| 328 | oce_err2: | ||
| 329 | if (clk->parent) | ||
| 330 | omap2_clk_disable(clk->parent); | ||
| 331 | oce_err1: | ||
| 287 | clk->usecount--; | 332 | clk->usecount--; |
| 333 | |||
| 288 | return ret; | 334 | return ret; |
| 289 | } | 335 | } |
| 290 | 336 | ||
| @@ -325,9 +371,9 @@ const struct clkops clkops_omap3_noncore_dpll_ops = { | |||
| 325 | #endif | 371 | #endif |
| 326 | 372 | ||
| 327 | 373 | ||
| 328 | /*------------------------------------------------------------------------- | 374 | /* |
| 329 | * Omap2 clock reset and init functions | 375 | * OMAP2+ clock reset and init functions |
| 330 | *-------------------------------------------------------------------------*/ | 376 | */ |
| 331 | 377 | ||
| 332 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 378 | #ifdef CONFIG_OMAP_RESET_CLOCKS |
| 333 | void omap2_clk_disable_unused(struct clk *clk) | 379 | void omap2_clk_disable_unused(struct clk *clk) |
| @@ -344,8 +390,9 @@ void omap2_clk_disable_unused(struct clk *clk) | |||
| 344 | if (cpu_is_omap34xx()) { | 390 | if (cpu_is_omap34xx()) { |
| 345 | omap2_clk_enable(clk); | 391 | omap2_clk_enable(clk); |
| 346 | omap2_clk_disable(clk); | 392 | omap2_clk_disable(clk); |
| 347 | } else | 393 | } else { |
| 348 | _omap2_clk_disable(clk); | 394 | clk->ops->disable(clk); |
| 395 | } | ||
| 349 | if (clk->clkdm != NULL) | 396 | if (clk->clkdm != NULL) |
| 350 | pwrdm_clkdm_state_switch(clk->clkdm); | 397 | pwrdm_clkdm_state_switch(clk->clkdm); |
| 351 | } | 398 | } |
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index b26d30a14303..b87ad66f083e 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c | |||
| @@ -978,7 +978,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) | |||
| 978 | * downstream clocks for debugging purposes? | 978 | * downstream clocks for debugging purposes? |
| 979 | */ | 979 | */ |
| 980 | 980 | ||
| 981 | if (!clkdm || !clk || !clkdm->clkstctrl_reg) | 981 | if (!clkdm || !clk) |
| 982 | return -EINVAL; | 982 | return -EINVAL; |
| 983 | 983 | ||
| 984 | if (atomic_inc_return(&clkdm->usecount) > 1) | 984 | if (atomic_inc_return(&clkdm->usecount) > 1) |
| @@ -989,6 +989,9 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) | |||
| 989 | pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, | 989 | pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, |
| 990 | clk->name); | 990 | clk->name); |
| 991 | 991 | ||
| 992 | if (!clkdm->clkstctrl_reg) | ||
| 993 | return 0; | ||
| 994 | |||
| 992 | v = omap2_clkdm_clktrctrl_read(clkdm); | 995 | v = omap2_clkdm_clktrctrl_read(clkdm); |
| 993 | 996 | ||
| 994 | if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || | 997 | if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || |
| @@ -1030,7 +1033,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) | |||
| 1030 | * downstream clocks for debugging purposes? | 1033 | * downstream clocks for debugging purposes? |
| 1031 | */ | 1034 | */ |
| 1032 | 1035 | ||
| 1033 | if (!clkdm || !clk || !clkdm->clkstctrl_reg) | 1036 | if (!clkdm || !clk) |
| 1034 | return -EINVAL; | 1037 | return -EINVAL; |
| 1035 | 1038 | ||
| 1036 | #ifdef DEBUG | 1039 | #ifdef DEBUG |
| @@ -1048,6 +1051,9 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) | |||
| 1048 | pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, | 1051 | pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, |
| 1049 | clk->name); | 1052 | clk->name); |
| 1050 | 1053 | ||
| 1054 | if (!clkdm->clkstctrl_reg) | ||
| 1055 | return 0; | ||
| 1056 | |||
| 1051 | v = omap2_clkdm_clktrctrl_read(clkdm); | 1057 | v = omap2_clkdm_clktrctrl_read(clkdm); |
| 1052 | 1058 | ||
| 1053 | if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || | 1059 | if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || |
