diff options
Diffstat (limited to 'arch/arm/mach-omap2/cminst44xx.c')
-rw-r--r-- | arch/arm/mach-omap2/cminst44xx.c | 142 |
1 files changed, 141 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 1894015ff04b..7f9a464f01e9 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c | |||
@@ -2,8 +2,9 @@ | |||
2 | * OMAP4 CM instance functions | 2 | * OMAP4 CM instance functions |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009 Nokia Corporation |
5 | * Copyright (C) 2011 Texas Instruments, Inc. | 5 | * Copyright (C) 2008-2011 Texas Instruments, Inc. |
6 | * Paul Walmsley | 6 | * Paul Walmsley |
7 | * Rajendra Nayak <rnayak@ti.com> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
@@ -22,6 +23,7 @@ | |||
22 | 23 | ||
23 | #include "iomap.h" | 24 | #include "iomap.h" |
24 | #include "common.h" | 25 | #include "common.h" |
26 | #include "clockdomain.h" | ||
25 | #include "cm.h" | 27 | #include "cm.h" |
26 | #include "cm1_44xx.h" | 28 | #include "cm1_44xx.h" |
27 | #include "cm2_44xx.h" | 29 | #include "cm2_44xx.h" |
@@ -343,3 +345,141 @@ void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs, | |||
343 | v &= ~OMAP4430_MODULEMODE_MASK; | 345 | v &= ~OMAP4430_MODULEMODE_MASK; |
344 | omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs); | 346 | omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs); |
345 | } | 347 | } |
348 | |||
349 | /* | ||
350 | * Clockdomain low-level functions | ||
351 | */ | ||
352 | |||
353 | static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1, | ||
354 | struct clockdomain *clkdm2) | ||
355 | { | ||
356 | omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit), | ||
357 | clkdm1->prcm_partition, | ||
358 | clkdm1->cm_inst, clkdm1->clkdm_offs + | ||
359 | OMAP4_CM_STATICDEP); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1, | ||
364 | struct clockdomain *clkdm2) | ||
365 | { | ||
366 | omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit), | ||
367 | clkdm1->prcm_partition, | ||
368 | clkdm1->cm_inst, clkdm1->clkdm_offs + | ||
369 | OMAP4_CM_STATICDEP); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1, | ||
374 | struct clockdomain *clkdm2) | ||
375 | { | ||
376 | return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition, | ||
377 | clkdm1->cm_inst, | ||
378 | clkdm1->clkdm_offs + | ||
379 | OMAP4_CM_STATICDEP, | ||
380 | (1 << clkdm2->dep_bit)); | ||
381 | } | ||
382 | |||
383 | static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) | ||
384 | { | ||
385 | struct clkdm_dep *cd; | ||
386 | u32 mask = 0; | ||
387 | |||
388 | if (!clkdm->prcm_partition) | ||
389 | return 0; | ||
390 | |||
391 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { | ||
392 | if (!cd->clkdm) | ||
393 | continue; /* only happens if data is erroneous */ | ||
394 | |||
395 | mask |= 1 << cd->clkdm->dep_bit; | ||
396 | atomic_set(&cd->wkdep_usecount, 0); | ||
397 | } | ||
398 | |||
399 | omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, | ||
400 | clkdm->cm_inst, clkdm->clkdm_offs + | ||
401 | OMAP4_CM_STATICDEP); | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int omap4_clkdm_sleep(struct clockdomain *clkdm) | ||
406 | { | ||
407 | omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, | ||
408 | clkdm->cm_inst, clkdm->clkdm_offs); | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int omap4_clkdm_wakeup(struct clockdomain *clkdm) | ||
413 | { | ||
414 | omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, | ||
415 | clkdm->cm_inst, clkdm->clkdm_offs); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static void omap4_clkdm_allow_idle(struct clockdomain *clkdm) | ||
420 | { | ||
421 | omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, | ||
422 | clkdm->cm_inst, clkdm->clkdm_offs); | ||
423 | } | ||
424 | |||
425 | static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) | ||
426 | { | ||
427 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) | ||
428 | omap4_clkdm_wakeup(clkdm); | ||
429 | else | ||
430 | omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, | ||
431 | clkdm->cm_inst, | ||
432 | clkdm->clkdm_offs); | ||
433 | } | ||
434 | |||
435 | static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) | ||
436 | { | ||
437 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) | ||
438 | return omap4_clkdm_wakeup(clkdm); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) | ||
444 | { | ||
445 | bool hwsup = false; | ||
446 | |||
447 | if (!clkdm->prcm_partition) | ||
448 | return 0; | ||
449 | |||
450 | /* | ||
451 | * The CLKDM_MISSING_IDLE_REPORTING flag documentation has | ||
452 | * more details on the unpleasant problem this is working | ||
453 | * around | ||
454 | */ | ||
455 | if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING && | ||
456 | !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) { | ||
457 | omap4_clkdm_allow_idle(clkdm); | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, | ||
462 | clkdm->cm_inst, clkdm->clkdm_offs); | ||
463 | |||
464 | if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) | ||
465 | omap4_clkdm_sleep(clkdm); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | struct clkdm_ops omap4_clkdm_operations = { | ||
471 | .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, | ||
472 | .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep, | ||
473 | .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep, | ||
474 | .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps, | ||
475 | .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep, | ||
476 | .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep, | ||
477 | .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep, | ||
478 | .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps, | ||
479 | .clkdm_sleep = omap4_clkdm_sleep, | ||
480 | .clkdm_wakeup = omap4_clkdm_wakeup, | ||
481 | .clkdm_allow_idle = omap4_clkdm_allow_idle, | ||
482 | .clkdm_deny_idle = omap4_clkdm_deny_idle, | ||
483 | .clkdm_clk_enable = omap4_clkdm_clk_enable, | ||
484 | .clkdm_clk_disable = omap4_clkdm_clk_disable, | ||
485 | }; | ||