diff options
author | Paul Walmsley <paul@pwsan.com> | 2010-02-23 00:09:38 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-02-24 19:45:16 -0500 |
commit | 30962d9d0c74f6b00a7dece200fa08392b62817d (patch) | |
tree | 72c1e60fd4f42c244fb8fe9c68f8e3d95a880edb /arch/arm/mach-omap2 | |
parent | 4d30e82c26b7212021b9a5ab57760d9b8a3075fe (diff) |
OMAP2+ clock: revise omap2_clk_{disable,enable}()
Simplify the code in the omap2_clk_disable() and omap2_clk_enable()
functions, reducing levels of indentation. This makes the code easier
to read. Add some additional debugging pr_debug()s here also to help
others understand what is going on.
Revise the omap2_clk_disable() logic so that it now attempts to
disable the clock's clockdomain before recursing up the clock tree.
Simultaneously, ensure that omap2_clk_enable() is called on parent
clocks first, before enabling the clockdomain. This ensures that a
parent clock's clockdomain is enabled before the child clock's
clockdomain. These sequences should be the inverse of each other.
Revise the omap2_clk_enable() logic so that it now cleans up after
itself upon encountering an error. Previously, an error enabling a
parent clock could have resulted in inconsistent usecounts on the
enclosing clockdomain.
Remove the trivial _omap2_clk_disable() and _omap2_clk_enable() static
functions, and replace it with the clkops calls that they were
executing.
For all this to work, the clockdomain omap2_clkdm_clk_enable() and
omap2_clkdm_clk_disable() code must not return an error on clockdomains
without CLKSTCTRL registers; so modify those functions to simply return 0
in that case.
While here, add some basic kerneldoc documentation on both functions,
and get rid of some old non-CodingStyle-compliant comments that have
existed since the dawn of time (at least, the OMAP clock framework's
time).
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Richard Woodruff <r-woodruff2@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-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) || |