diff options
author | Rajendra Nayak <rnayak@ti.com> | 2011-02-25 18:06:47 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2011-02-25 18:06:47 -0500 |
commit | 4aef7a2a5aad52b60ac1a2f3cee055b8271b70d5 (patch) | |
tree | ee1714e1dd13d9beecd886ba40e9ebea169faf53 /arch | |
parent | 32d4034eea9c5c2b2edc365e1a0787c8f5b84c3c (diff) |
OMAP: clockdomain: Arch specific funcs to handle deps
Define the following architecture specific funtions for omap2/3
.clkdm_add_wkdep
.clkdm_del_wkdep
.clkdm_read_wkdep
.clkdm_clear_all_wkdeps
.clkdm_add_sleepdep
.clkdm_del_sleepdep
.clkdm_read_sleepdep
.clkdm_clear_all_sleepdeps
Convert the platform-independent framework to call these functions.
With this also move the clkdm lookups for all wkdep_srcs and
sleepdep_srcs at clkdm_init.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[paul@pwsan.com: fixed loop termination conditions in omap*_clkdm_clear_all_*();
thanks to Kevin Hilman for finding and helping fix those bugs; also
avoid re-resolving clockdomains during init; abstracted out clkdm_dep walk]
Cc: Kevin Hilman <khilman@ti.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 177 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 130 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-omap2/io.c | 6 |
6 files changed, 246 insertions, 84 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index ee72a9787bf1..759d9ebd79c6 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -102,8 +102,10 @@ obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common) \ | |||
102 | 102 | ||
103 | # PRCM clockdomain control | 103 | # PRCM clockdomain control |
104 | obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \ | 104 | obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \ |
105 | clockdomain2xxx_3xxx.o \ | ||
105 | clockdomains2xxx_3xxx_data.o | 106 | clockdomains2xxx_3xxx_data.o |
106 | obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \ | 107 | obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \ |
108 | clockdomain2xxx_3xxx.o \ | ||
107 | clockdomains2xxx_3xxx_data.o | 109 | clockdomains2xxx_3xxx_data.o |
108 | obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \ | 110 | obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \ |
109 | clockdomains44xx_data.o | 111 | clockdomains44xx_data.o |
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index f70b06ae8664..895c153c18e0 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c | |||
@@ -287,6 +287,32 @@ static void _disable_hwsup(struct clockdomain *clkdm) | |||
287 | BUG(); | 287 | BUG(); |
288 | } | 288 | } |
289 | 289 | ||
290 | /** | ||
291 | * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms | ||
292 | * @clkdm: clockdomain that we are resolving dependencies for | ||
293 | * @clkdm_deps: ptr to array of struct clkdm_deps to resolve | ||
294 | * | ||
295 | * Iterates through @clkdm_deps, looking up the struct clockdomain named by | ||
296 | * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep. | ||
297 | * No return value. | ||
298 | */ | ||
299 | static void _resolve_clkdm_deps(struct clockdomain *clkdm, | ||
300 | struct clkdm_dep *clkdm_deps) | ||
301 | { | ||
302 | struct clkdm_dep *cd; | ||
303 | |||
304 | for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) { | ||
305 | if (!omap_chip_is(cd->omap_chip)) | ||
306 | continue; | ||
307 | if (cd->clkdm) | ||
308 | continue; | ||
309 | cd->clkdm = _clkdm_lookup(cd->clkdm_name); | ||
310 | |||
311 | WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen", | ||
312 | clkdm->name, cd->clkdm_name); | ||
313 | } | ||
314 | } | ||
315 | |||
290 | /* Public functions */ | 316 | /* Public functions */ |
291 | 317 | ||
292 | /** | 318 | /** |
@@ -333,7 +359,10 @@ void clkdm_init(struct clockdomain **clkdms, | |||
333 | else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO) | 359 | else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO) |
334 | omap2_clkdm_deny_idle(clkdm); | 360 | omap2_clkdm_deny_idle(clkdm); |
335 | 361 | ||
362 | _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs); | ||
336 | clkdm_clear_all_wkdeps(clkdm); | 363 | clkdm_clear_all_wkdeps(clkdm); |
364 | |||
365 | _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs); | ||
337 | clkdm_clear_all_sleepdeps(clkdm); | 366 | clkdm_clear_all_sleepdeps(clkdm); |
338 | } | 367 | } |
339 | } | 368 | } |
@@ -430,6 +459,7 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) | |||
430 | int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 459 | int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
431 | { | 460 | { |
432 | struct clkdm_dep *cd; | 461 | struct clkdm_dep *cd; |
462 | int ret = 0; | ||
433 | 463 | ||
434 | if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { | 464 | if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { |
435 | pr_err("clockdomain: %s/%s: %s: not yet implemented\n", | 465 | pr_err("clockdomain: %s/%s: %s: not yet implemented\n", |
@@ -441,21 +471,26 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
441 | return -EINVAL; | 471 | return -EINVAL; |
442 | 472 | ||
443 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | 473 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); |
444 | if (IS_ERR(cd)) { | 474 | if (IS_ERR(cd)) |
475 | ret = PTR_ERR(cd); | ||
476 | |||
477 | if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep) | ||
478 | ret = -EINVAL; | ||
479 | |||
480 | if (ret) { | ||
445 | pr_debug("clockdomain: hardware cannot set/clear wake up of " | 481 | pr_debug("clockdomain: hardware cannot set/clear wake up of " |
446 | "%s when %s wakes up\n", clkdm1->name, clkdm2->name); | 482 | "%s when %s wakes up\n", clkdm1->name, clkdm2->name); |
447 | return PTR_ERR(cd); | 483 | return ret; |
448 | } | 484 | } |
449 | 485 | ||
450 | if (atomic_inc_return(&cd->wkdep_usecount) == 1) { | 486 | if (atomic_inc_return(&cd->wkdep_usecount) == 1) { |
451 | pr_debug("clockdomain: hardware will wake up %s when %s wakes " | 487 | pr_debug("clockdomain: hardware will wake up %s when %s wakes " |
452 | "up\n", clkdm1->name, clkdm2->name); | 488 | "up\n", clkdm1->name, clkdm2->name); |
453 | 489 | ||
454 | omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), | 490 | ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2); |
455 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
456 | } | 491 | } |
457 | 492 | ||
458 | return 0; | 493 | return ret; |
459 | } | 494 | } |
460 | 495 | ||
461 | /** | 496 | /** |
@@ -471,6 +506,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
471 | int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 506 | int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
472 | { | 507 | { |
473 | struct clkdm_dep *cd; | 508 | struct clkdm_dep *cd; |
509 | int ret = 0; | ||
474 | 510 | ||
475 | if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { | 511 | if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { |
476 | pr_err("clockdomain: %s/%s: %s: not yet implemented\n", | 512 | pr_err("clockdomain: %s/%s: %s: not yet implemented\n", |
@@ -482,21 +518,26 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
482 | return -EINVAL; | 518 | return -EINVAL; |
483 | 519 | ||
484 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | 520 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); |
485 | if (IS_ERR(cd)) { | 521 | if (IS_ERR(cd)) |
522 | ret = PTR_ERR(cd); | ||
523 | |||
524 | if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep) | ||
525 | ret = -EINVAL; | ||
526 | |||
527 | if (ret) { | ||
486 | pr_debug("clockdomain: hardware cannot set/clear wake up of " | 528 | pr_debug("clockdomain: hardware cannot set/clear wake up of " |
487 | "%s when %s wakes up\n", clkdm1->name, clkdm2->name); | 529 | "%s when %s wakes up\n", clkdm1->name, clkdm2->name); |
488 | return PTR_ERR(cd); | 530 | return ret; |
489 | } | 531 | } |
490 | 532 | ||
491 | if (atomic_dec_return(&cd->wkdep_usecount) == 0) { | 533 | if (atomic_dec_return(&cd->wkdep_usecount) == 0) { |
492 | pr_debug("clockdomain: hardware will no longer wake up %s " | 534 | pr_debug("clockdomain: hardware will no longer wake up %s " |
493 | "after %s wakes up\n", clkdm1->name, clkdm2->name); | 535 | "after %s wakes up\n", clkdm1->name, clkdm2->name); |
494 | 536 | ||
495 | omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | 537 | ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2); |
496 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
497 | } | 538 | } |
498 | 539 | ||
499 | return 0; | 540 | return ret; |
500 | } | 541 | } |
501 | 542 | ||
502 | /** | 543 | /** |
@@ -516,6 +557,7 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
516 | int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 557 | int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
517 | { | 558 | { |
518 | struct clkdm_dep *cd; | 559 | struct clkdm_dep *cd; |
560 | int ret = 0; | ||
519 | 561 | ||
520 | if (!clkdm1 || !clkdm2) | 562 | if (!clkdm1 || !clkdm2) |
521 | return -EINVAL; | 563 | return -EINVAL; |
@@ -527,15 +569,20 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
527 | } | 569 | } |
528 | 570 | ||
529 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | 571 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); |
530 | if (IS_ERR(cd)) { | 572 | if (IS_ERR(cd)) |
573 | ret = PTR_ERR(cd); | ||
574 | |||
575 | if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep) | ||
576 | ret = -EINVAL; | ||
577 | |||
578 | if (ret) { | ||
531 | pr_debug("clockdomain: hardware cannot set/clear wake up of " | 579 | pr_debug("clockdomain: hardware cannot set/clear wake up of " |
532 | "%s when %s wakes up\n", clkdm1->name, clkdm2->name); | 580 | "%s when %s wakes up\n", clkdm1->name, clkdm2->name); |
533 | return PTR_ERR(cd); | 581 | return ret; |
534 | } | 582 | } |
535 | 583 | ||
536 | /* XXX It's faster to return the atomic wkdep_usecount */ | 584 | /* XXX It's faster to return the atomic wkdep_usecount */ |
537 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, | 585 | return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2); |
538 | (1 << clkdm2->dep_bit)); | ||
539 | } | 586 | } |
540 | 587 | ||
541 | /** | 588 | /** |
@@ -550,9 +597,6 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
550 | */ | 597 | */ |
551 | int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | 598 | int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) |
552 | { | 599 | { |
553 | struct clkdm_dep *cd; | ||
554 | u32 mask = 0; | ||
555 | |||
556 | if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { | 600 | if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { |
557 | pr_err("clockdomain: %s: %s: not yet implemented\n", | 601 | pr_err("clockdomain: %s: %s: not yet implemented\n", |
558 | clkdm->name, __func__); | 602 | clkdm->name, __func__); |
@@ -562,21 +606,10 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | |||
562 | if (!clkdm) | 606 | if (!clkdm) |
563 | return -EINVAL; | 607 | return -EINVAL; |
564 | 608 | ||
565 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { | 609 | if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps) |
566 | if (!omap_chip_is(cd->omap_chip)) | 610 | return -EINVAL; |
567 | continue; | ||
568 | |||
569 | if (!cd->clkdm && cd->clkdm_name) | ||
570 | cd->clkdm = _clkdm_lookup(cd->clkdm_name); | ||
571 | |||
572 | /* PRM accesses are slow, so minimize them */ | ||
573 | mask |= 1 << cd->clkdm->dep_bit; | ||
574 | atomic_set(&cd->wkdep_usecount, 0); | ||
575 | } | ||
576 | |||
577 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
578 | 611 | ||
579 | return 0; | 612 | return arch_clkdm->clkdm_clear_all_wkdeps(clkdm); |
580 | } | 613 | } |
581 | 614 | ||
582 | /** | 615 | /** |
@@ -594,31 +627,33 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | |||
594 | int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 627 | int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
595 | { | 628 | { |
596 | struct clkdm_dep *cd; | 629 | struct clkdm_dep *cd; |
597 | 630 | int ret = 0; | |
598 | if (!cpu_is_omap34xx()) | ||
599 | return -EINVAL; | ||
600 | 631 | ||
601 | if (!clkdm1 || !clkdm2) | 632 | if (!clkdm1 || !clkdm2) |
602 | return -EINVAL; | 633 | return -EINVAL; |
603 | 634 | ||
604 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); | 635 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); |
605 | if (IS_ERR(cd)) { | 636 | if (IS_ERR(cd)) |
637 | ret = PTR_ERR(cd); | ||
638 | |||
639 | if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep) | ||
640 | ret = -EINVAL; | ||
641 | |||
642 | if (ret) { | ||
606 | pr_debug("clockdomain: hardware cannot set/clear sleep " | 643 | pr_debug("clockdomain: hardware cannot set/clear sleep " |
607 | "dependency affecting %s from %s\n", clkdm1->name, | 644 | "dependency affecting %s from %s\n", clkdm1->name, |
608 | clkdm2->name); | 645 | clkdm2->name); |
609 | return PTR_ERR(cd); | 646 | return ret; |
610 | } | 647 | } |
611 | 648 | ||
612 | if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { | 649 | if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { |
613 | pr_debug("clockdomain: will prevent %s from sleeping if %s " | 650 | pr_debug("clockdomain: will prevent %s from sleeping if %s " |
614 | "is active\n", clkdm1->name, clkdm2->name); | 651 | "is active\n", clkdm1->name, clkdm2->name); |
615 | 652 | ||
616 | omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), | 653 | ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2); |
617 | clkdm1->pwrdm.ptr->prcm_offs, | ||
618 | OMAP3430_CM_SLEEPDEP); | ||
619 | } | 654 | } |
620 | 655 | ||
621 | return 0; | 656 | return ret; |
622 | } | 657 | } |
623 | 658 | ||
624 | /** | 659 | /** |
@@ -636,19 +671,23 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
636 | int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 671 | int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
637 | { | 672 | { |
638 | struct clkdm_dep *cd; | 673 | struct clkdm_dep *cd; |
639 | 674 | int ret = 0; | |
640 | if (!cpu_is_omap34xx()) | ||
641 | return -EINVAL; | ||
642 | 675 | ||
643 | if (!clkdm1 || !clkdm2) | 676 | if (!clkdm1 || !clkdm2) |
644 | return -EINVAL; | 677 | return -EINVAL; |
645 | 678 | ||
646 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); | 679 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); |
647 | if (IS_ERR(cd)) { | 680 | if (IS_ERR(cd)) |
681 | ret = PTR_ERR(cd); | ||
682 | |||
683 | if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep) | ||
684 | ret = -EINVAL; | ||
685 | |||
686 | if (ret) { | ||
648 | pr_debug("clockdomain: hardware cannot set/clear sleep " | 687 | pr_debug("clockdomain: hardware cannot set/clear sleep " |
649 | "dependency affecting %s from %s\n", clkdm1->name, | 688 | "dependency affecting %s from %s\n", clkdm1->name, |
650 | clkdm2->name); | 689 | clkdm2->name); |
651 | return PTR_ERR(cd); | 690 | return ret; |
652 | } | 691 | } |
653 | 692 | ||
654 | if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { | 693 | if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { |
@@ -656,12 +695,10 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
656 | "sleeping if %s is active\n", clkdm1->name, | 695 | "sleeping if %s is active\n", clkdm1->name, |
657 | clkdm2->name); | 696 | clkdm2->name); |
658 | 697 | ||
659 | omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | 698 | ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2); |
660 | clkdm1->pwrdm.ptr->prcm_offs, | ||
661 | OMAP3430_CM_SLEEPDEP); | ||
662 | } | 699 | } |
663 | 700 | ||
664 | return 0; | 701 | return ret; |
665 | } | 702 | } |
666 | 703 | ||
667 | /** | 704 | /** |
@@ -683,25 +720,27 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
683 | int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 720 | int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
684 | { | 721 | { |
685 | struct clkdm_dep *cd; | 722 | struct clkdm_dep *cd; |
686 | 723 | int ret = 0; | |
687 | if (!cpu_is_omap34xx()) | ||
688 | return -EINVAL; | ||
689 | 724 | ||
690 | if (!clkdm1 || !clkdm2) | 725 | if (!clkdm1 || !clkdm2) |
691 | return -EINVAL; | 726 | return -EINVAL; |
692 | 727 | ||
693 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); | 728 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); |
694 | if (IS_ERR(cd)) { | 729 | if (IS_ERR(cd)) |
730 | ret = PTR_ERR(cd); | ||
731 | |||
732 | if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep) | ||
733 | ret = -EINVAL; | ||
734 | |||
735 | if (ret) { | ||
695 | pr_debug("clockdomain: hardware cannot set/clear sleep " | 736 | pr_debug("clockdomain: hardware cannot set/clear sleep " |
696 | "dependency affecting %s from %s\n", clkdm1->name, | 737 | "dependency affecting %s from %s\n", clkdm1->name, |
697 | clkdm2->name); | 738 | clkdm2->name); |
698 | return PTR_ERR(cd); | 739 | return ret; |
699 | } | 740 | } |
700 | 741 | ||
701 | /* XXX It's faster to return the atomic sleepdep_usecount */ | 742 | /* XXX It's faster to return the atomic sleepdep_usecount */ |
702 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | 743 | return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2); |
703 | OMAP3430_CM_SLEEPDEP, | ||
704 | (1 << clkdm2->dep_bit)); | ||
705 | } | 744 | } |
706 | 745 | ||
707 | /** | 746 | /** |
@@ -716,31 +755,13 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
716 | */ | 755 | */ |
717 | int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) | 756 | int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) |
718 | { | 757 | { |
719 | struct clkdm_dep *cd; | ||
720 | u32 mask = 0; | ||
721 | |||
722 | if (!cpu_is_omap34xx()) | ||
723 | return -EINVAL; | ||
724 | |||
725 | if (!clkdm) | 758 | if (!clkdm) |
726 | return -EINVAL; | 759 | return -EINVAL; |
727 | 760 | ||
728 | for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { | 761 | if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps) |
729 | if (!omap_chip_is(cd->omap_chip)) | 762 | return -EINVAL; |
730 | continue; | ||
731 | |||
732 | if (!cd->clkdm && cd->clkdm_name) | ||
733 | cd->clkdm = _clkdm_lookup(cd->clkdm_name); | ||
734 | |||
735 | /* PRM accesses are slow, so minimize them */ | ||
736 | mask |= 1 << cd->clkdm->dep_bit; | ||
737 | atomic_set(&cd->sleepdep_usecount, 0); | ||
738 | } | ||
739 | |||
740 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | ||
741 | OMAP3430_CM_SLEEPDEP); | ||
742 | 763 | ||
743 | return 0; | 764 | return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm); |
744 | } | 765 | } |
745 | 766 | ||
746 | /** | 767 | /** |
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 71ad265cf133..90b6d6a50862 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h | |||
@@ -176,7 +176,11 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm); | |||
176 | int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); | 176 | int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); |
177 | int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); | 177 | int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); |
178 | 178 | ||
179 | extern void __init omap2_clockdomains_init(void); | 179 | extern void __init omap2xxx_clockdomains_init(void); |
180 | extern void __init omap3xxx_clockdomains_init(void); | ||
180 | extern void __init omap44xx_clockdomains_init(void); | 181 | extern void __init omap44xx_clockdomains_init(void); |
181 | 182 | ||
183 | extern struct clkdm_ops omap2_clkdm_operations; | ||
184 | extern struct clkdm_ops omap3_clkdm_operations; | ||
185 | |||
182 | #endif | 186 | #endif |
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c new file mode 100644 index 000000000000..a1fd6fd5a466 --- /dev/null +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * OMAP2 and OMAP3 clockdomain control | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2008-2010 Nokia Corporation | ||
6 | * | ||
7 | * Derived from mach-omap2/clockdomain.c written by Paul Walmsley | ||
8 | * Rajendra Nayak <rnayak@ti.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | #include <plat/prcm.h> | ||
17 | #include "prm.h" | ||
18 | #include "prm2xxx_3xxx.h" | ||
19 | #include "cm.h" | ||
20 | #include "cm2xxx_3xxx.h" | ||
21 | #include "cm-regbits-24xx.h" | ||
22 | #include "cm-regbits-34xx.h" | ||
23 | #include "clockdomain.h" | ||
24 | |||
25 | static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1, | ||
26 | struct clockdomain *clkdm2) | ||
27 | { | ||
28 | omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), | ||
29 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1, | ||
34 | struct clockdomain *clkdm2) | ||
35 | { | ||
36 | omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | ||
37 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, | ||
42 | struct clockdomain *clkdm2) | ||
43 | { | ||
44 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | ||
45 | PM_WKDEP, (1 << clkdm2->dep_bit)); | ||
46 | } | ||
47 | |||
48 | static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | ||
49 | { | ||
50 | struct clkdm_dep *cd; | ||
51 | u32 mask = 0; | ||
52 | |||
53 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { | ||
54 | if (!omap_chip_is(cd->omap_chip)) | ||
55 | continue; | ||
56 | if (!cd->clkdm) | ||
57 | continue; /* only happens if data is erroneous */ | ||
58 | |||
59 | /* PRM accesses are slow, so minimize them */ | ||
60 | mask |= 1 << cd->clkdm->dep_bit; | ||
61 | atomic_set(&cd->wkdep_usecount, 0); | ||
62 | } | ||
63 | |||
64 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | ||
65 | PM_WKDEP); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1, | ||
70 | struct clockdomain *clkdm2) | ||
71 | { | ||
72 | omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), | ||
73 | clkdm1->pwrdm.ptr->prcm_offs, | ||
74 | OMAP3430_CM_SLEEPDEP); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1, | ||
79 | struct clockdomain *clkdm2) | ||
80 | { | ||
81 | omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | ||
82 | clkdm1->pwrdm.ptr->prcm_offs, | ||
83 | OMAP3430_CM_SLEEPDEP); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1, | ||
88 | struct clockdomain *clkdm2) | ||
89 | { | ||
90 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | ||
91 | OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit)); | ||
92 | } | ||
93 | |||
94 | static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) | ||
95 | { | ||
96 | struct clkdm_dep *cd; | ||
97 | u32 mask = 0; | ||
98 | |||
99 | for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { | ||
100 | if (!omap_chip_is(cd->omap_chip)) | ||
101 | continue; | ||
102 | if (!cd->clkdm) | ||
103 | continue; /* only happens if data is erroneous */ | ||
104 | |||
105 | /* PRM accesses are slow, so minimize them */ | ||
106 | mask |= 1 << cd->clkdm->dep_bit; | ||
107 | atomic_set(&cd->sleepdep_usecount, 0); | ||
108 | } | ||
109 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | ||
110 | OMAP3430_CM_SLEEPDEP); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | struct clkdm_ops omap2_clkdm_operations = { | ||
115 | .clkdm_add_wkdep = omap2_clkdm_add_wkdep, | ||
116 | .clkdm_del_wkdep = omap2_clkdm_del_wkdep, | ||
117 | .clkdm_read_wkdep = omap2_clkdm_read_wkdep, | ||
118 | .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, | ||
119 | }; | ||
120 | |||
121 | struct clkdm_ops omap3_clkdm_operations = { | ||
122 | .clkdm_add_wkdep = omap2_clkdm_add_wkdep, | ||
123 | .clkdm_del_wkdep = omap2_clkdm_del_wkdep, | ||
124 | .clkdm_read_wkdep = omap2_clkdm_read_wkdep, | ||
125 | .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, | ||
126 | .clkdm_add_sleepdep = omap3_clkdm_add_sleepdep, | ||
127 | .clkdm_del_sleepdep = omap3_clkdm_del_sleepdep, | ||
128 | .clkdm_read_sleepdep = omap3_clkdm_read_sleepdep, | ||
129 | .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps, | ||
130 | }; | ||
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c index e2a959eab312..ffdfe54f3264 100644 --- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c | |||
@@ -854,7 +854,12 @@ static struct clockdomain *clockdomains_omap2[] __initdata = { | |||
854 | NULL, | 854 | NULL, |
855 | }; | 855 | }; |
856 | 856 | ||
857 | void __init omap2_clockdomains_init(void) | 857 | void __init omap2xxx_clockdomains_init(void) |
858 | { | 858 | { |
859 | clkdm_init(clockdomains_omap2, clkdm_autodeps, NULL); | 859 | clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations); |
860 | } | ||
861 | |||
862 | void __init omap3xxx_clockdomains_init(void) | ||
863 | { | ||
864 | clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations); | ||
860 | } | 865 | } |
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index b8b49e4ae928..03f71ec3cd82 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c | |||
@@ -357,15 +357,15 @@ void __init omap2_init_common_infrastructure(void) | |||
357 | 357 | ||
358 | if (cpu_is_omap242x()) { | 358 | if (cpu_is_omap242x()) { |
359 | omap2xxx_powerdomains_init(); | 359 | omap2xxx_powerdomains_init(); |
360 | omap2_clockdomains_init(); | 360 | omap2xxx_clockdomains_init(); |
361 | omap2420_hwmod_init(); | 361 | omap2420_hwmod_init(); |
362 | } else if (cpu_is_omap243x()) { | 362 | } else if (cpu_is_omap243x()) { |
363 | omap2xxx_powerdomains_init(); | 363 | omap2xxx_powerdomains_init(); |
364 | omap2_clockdomains_init(); | 364 | omap2xxx_clockdomains_init(); |
365 | omap2430_hwmod_init(); | 365 | omap2430_hwmod_init(); |
366 | } else if (cpu_is_omap34xx()) { | 366 | } else if (cpu_is_omap34xx()) { |
367 | omap3xxx_powerdomains_init(); | 367 | omap3xxx_powerdomains_init(); |
368 | omap2_clockdomains_init(); | 368 | omap3xxx_clockdomains_init(); |
369 | omap3xxx_hwmod_init(); | 369 | omap3xxx_hwmod_init(); |
370 | } else if (cpu_is_omap44xx()) { | 370 | } else if (cpu_is_omap44xx()) { |
371 | omap44xx_powerdomains_init(); | 371 | omap44xx_powerdomains_init(); |