aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/clock.c')
-rw-r--r--arch/arm/mach-omap2/clock.c135
1 files changed, 91 insertions, 44 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
38u8 cpu_mask; 38u8 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 */
77static 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 */
83static 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 */
248void omap2_clk_disable(struct clk *clk) 249void 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 */
260int omap2_clk_enable(struct clk *clk) 286int 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
284err: 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
325oce_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);
328oce_err2:
329 if (clk->parent)
330 omap2_clk_disable(clk->parent);
331oce_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
333void omap2_clk_disable_unused(struct clk *clk) 379void 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}