diff options
Diffstat (limited to 'arch/arm/mach-omap2/clockdomain.c')
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 220 |
1 files changed, 124 insertions, 96 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 6fb61b1a0d46..e20b98636ab4 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | #undef DEBUG | 14 | #undef DEBUG |
15 | 15 | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/device.h> | 17 | #include <linux/device.h> |
19 | #include <linux/list.h> | 18 | #include <linux/list.h> |
@@ -27,13 +26,16 @@ | |||
27 | 26 | ||
28 | #include <linux/bitops.h> | 27 | #include <linux/bitops.h> |
29 | 28 | ||
30 | #include "prm.h" | 29 | #include "prm2xxx_3xxx.h" |
31 | #include "prm-regbits-24xx.h" | 30 | #include "prm-regbits-24xx.h" |
32 | #include "cm.h" | 31 | #include "cm2xxx_3xxx.h" |
32 | #include "cm-regbits-24xx.h" | ||
33 | #include "cminst44xx.h" | ||
34 | #include "prcm44xx.h" | ||
33 | 35 | ||
34 | #include <plat/clock.h> | 36 | #include <plat/clock.h> |
35 | #include <plat/powerdomain.h> | 37 | #include "powerdomain.h" |
36 | #include <plat/clockdomain.h> | 38 | #include "clockdomain.h" |
37 | #include <plat/prcm.h> | 39 | #include <plat/prcm.h> |
38 | 40 | ||
39 | /* clkdm_list contains all registered struct clockdomains */ | 41 | /* clkdm_list contains all registered struct clockdomains */ |
@@ -141,6 +143,9 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm, | |||
141 | * clockdomain is in hardware-supervised mode. Meant to be called | 143 | * clockdomain is in hardware-supervised mode. Meant to be called |
142 | * once at clockdomain layer initialization, since these should remain | 144 | * once at clockdomain layer initialization, since these should remain |
143 | * fixed for a particular architecture. No return value. | 145 | * fixed for a particular architecture. No return value. |
146 | * | ||
147 | * XXX autodeps are deprecated and should be removed at the earliest | ||
148 | * opportunity | ||
144 | */ | 149 | */ |
145 | static void _autodep_lookup(struct clkdm_autodep *autodep) | 150 | static void _autodep_lookup(struct clkdm_autodep *autodep) |
146 | { | 151 | { |
@@ -168,6 +173,9 @@ static void _autodep_lookup(struct clkdm_autodep *autodep) | |||
168 | * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' | 173 | * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' |
169 | * in hardware-supervised mode. Meant to be called from clock framework | 174 | * in hardware-supervised mode. Meant to be called from clock framework |
170 | * when a clock inside clockdomain 'clkdm' is enabled. No return value. | 175 | * when a clock inside clockdomain 'clkdm' is enabled. No return value. |
176 | * | ||
177 | * XXX autodeps are deprecated and should be removed at the earliest | ||
178 | * opportunity | ||
171 | */ | 179 | */ |
172 | static void _clkdm_add_autodeps(struct clockdomain *clkdm) | 180 | static void _clkdm_add_autodeps(struct clockdomain *clkdm) |
173 | { | 181 | { |
@@ -199,6 +207,9 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm) | |||
199 | * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' | 207 | * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' |
200 | * in hardware-supervised mode. Meant to be called from clock framework | 208 | * in hardware-supervised mode. Meant to be called from clock framework |
201 | * when a clock inside clockdomain 'clkdm' is disabled. No return value. | 209 | * when a clock inside clockdomain 'clkdm' is disabled. No return value. |
210 | * | ||
211 | * XXX autodeps are deprecated and should be removed at the earliest | ||
212 | * opportunity | ||
202 | */ | 213 | */ |
203 | static void _clkdm_del_autodeps(struct clockdomain *clkdm) | 214 | static void _clkdm_del_autodeps(struct clockdomain *clkdm) |
204 | { | 215 | { |
@@ -223,39 +234,56 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) | |||
223 | } | 234 | } |
224 | } | 235 | } |
225 | 236 | ||
226 | /* | 237 | /** |
227 | * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit | 238 | * _enable_hwsup - place a clockdomain into hardware-supervised idle |
228 | * @clkdm: struct clockdomain * | 239 | * @clkdm: struct clockdomain * |
229 | * @enable: int 0 to disable, 1 to enable | ||
230 | * | 240 | * |
231 | * Internal helper for actually switching the bit that controls hwsup | 241 | * Place the clockdomain into hardware-supervised idle mode. No return |
232 | * idle transitions for clkdm. | 242 | * value. |
243 | * | ||
244 | * XXX Should this return an error if the clockdomain does not support | ||
245 | * hardware-supervised idle mode? | ||
233 | */ | 246 | */ |
234 | static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) | 247 | static void _enable_hwsup(struct clockdomain *clkdm) |
235 | { | 248 | { |
236 | u32 bits, v; | 249 | if (cpu_is_omap24xx()) |
237 | 250 | omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | |
238 | if (cpu_is_omap24xx()) { | 251 | clkdm->clktrctrl_mask); |
239 | if (enable) | 252 | else if (cpu_is_omap34xx()) |
240 | bits = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; | 253 | omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, |
241 | else | 254 | clkdm->clktrctrl_mask); |
242 | bits = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; | 255 | else if (cpu_is_omap44xx()) |
243 | } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { | 256 | return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, |
244 | if (enable) | 257 | clkdm->cm_inst, |
245 | bits = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; | 258 | clkdm->clkdm_offs); |
246 | else | 259 | else |
247 | bits = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; | ||
248 | } else { | ||
249 | BUG(); | 260 | BUG(); |
250 | } | 261 | } |
251 | |||
252 | bits = bits << __ffs(clkdm->clktrctrl_mask); | ||
253 | |||
254 | v = __raw_readl(clkdm->clkstctrl_reg); | ||
255 | v &= ~(clkdm->clktrctrl_mask); | ||
256 | v |= bits; | ||
257 | __raw_writel(v, clkdm->clkstctrl_reg); | ||
258 | 262 | ||
263 | /** | ||
264 | * _disable_hwsup - place a clockdomain into software-supervised idle | ||
265 | * @clkdm: struct clockdomain * | ||
266 | * | ||
267 | * Place the clockdomain @clkdm into software-supervised idle mode. | ||
268 | * No return value. | ||
269 | * | ||
270 | * XXX Should this return an error if the clockdomain does not support | ||
271 | * software-supervised idle mode? | ||
272 | */ | ||
273 | static void _disable_hwsup(struct clockdomain *clkdm) | ||
274 | { | ||
275 | if (cpu_is_omap24xx()) | ||
276 | omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
277 | clkdm->clktrctrl_mask); | ||
278 | else if (cpu_is_omap34xx()) | ||
279 | omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
280 | clkdm->clktrctrl_mask); | ||
281 | else if (cpu_is_omap44xx()) | ||
282 | return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, | ||
283 | clkdm->cm_inst, | ||
284 | clkdm->clkdm_offs); | ||
285 | else | ||
286 | BUG(); | ||
259 | } | 287 | } |
260 | 288 | ||
261 | /* Public functions */ | 289 | /* Public functions */ |
@@ -409,7 +437,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
409 | pr_debug("clockdomain: hardware will wake up %s when %s wakes " | 437 | pr_debug("clockdomain: hardware will wake up %s when %s wakes " |
410 | "up\n", clkdm1->name, clkdm2->name); | 438 | "up\n", clkdm1->name, clkdm2->name); |
411 | 439 | ||
412 | prm_set_mod_reg_bits((1 << clkdm2->dep_bit), | 440 | omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), |
413 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | 441 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); |
414 | } | 442 | } |
415 | 443 | ||
@@ -444,7 +472,7 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
444 | pr_debug("clockdomain: hardware will no longer wake up %s " | 472 | pr_debug("clockdomain: hardware will no longer wake up %s " |
445 | "after %s wakes up\n", clkdm1->name, clkdm2->name); | 473 | "after %s wakes up\n", clkdm1->name, clkdm2->name); |
446 | 474 | ||
447 | prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | 475 | omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), |
448 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | 476 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); |
449 | } | 477 | } |
450 | 478 | ||
@@ -480,7 +508,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
480 | } | 508 | } |
481 | 509 | ||
482 | /* XXX It's faster to return the atomic wkdep_usecount */ | 510 | /* XXX It's faster to return the atomic wkdep_usecount */ |
483 | return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, | 511 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, |
484 | (1 << clkdm2->dep_bit)); | 512 | (1 << clkdm2->dep_bit)); |
485 | } | 513 | } |
486 | 514 | ||
@@ -514,7 +542,7 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | |||
514 | atomic_set(&cd->wkdep_usecount, 0); | 542 | atomic_set(&cd->wkdep_usecount, 0); |
515 | } | 543 | } |
516 | 544 | ||
517 | prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP); | 545 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP); |
518 | 546 | ||
519 | return 0; | 547 | return 0; |
520 | } | 548 | } |
@@ -553,7 +581,7 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
553 | pr_debug("clockdomain: will prevent %s from sleeping if %s " | 581 | pr_debug("clockdomain: will prevent %s from sleeping if %s " |
554 | "is active\n", clkdm1->name, clkdm2->name); | 582 | "is active\n", clkdm1->name, clkdm2->name); |
555 | 583 | ||
556 | cm_set_mod_reg_bits((1 << clkdm2->dep_bit), | 584 | omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), |
557 | clkdm1->pwrdm.ptr->prcm_offs, | 585 | clkdm1->pwrdm.ptr->prcm_offs, |
558 | OMAP3430_CM_SLEEPDEP); | 586 | OMAP3430_CM_SLEEPDEP); |
559 | } | 587 | } |
@@ -596,7 +624,7 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
596 | "sleeping if %s is active\n", clkdm1->name, | 624 | "sleeping if %s is active\n", clkdm1->name, |
597 | clkdm2->name); | 625 | clkdm2->name); |
598 | 626 | ||
599 | cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | 627 | omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), |
600 | clkdm1->pwrdm.ptr->prcm_offs, | 628 | clkdm1->pwrdm.ptr->prcm_offs, |
601 | OMAP3430_CM_SLEEPDEP); | 629 | OMAP3430_CM_SLEEPDEP); |
602 | } | 630 | } |
@@ -639,7 +667,7 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
639 | } | 667 | } |
640 | 668 | ||
641 | /* XXX It's faster to return the atomic sleepdep_usecount */ | 669 | /* XXX It's faster to return the atomic sleepdep_usecount */ |
642 | return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | 670 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, |
643 | OMAP3430_CM_SLEEPDEP, | 671 | OMAP3430_CM_SLEEPDEP, |
644 | (1 << clkdm2->dep_bit)); | 672 | (1 << clkdm2->dep_bit)); |
645 | } | 673 | } |
@@ -677,35 +705,13 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) | |||
677 | atomic_set(&cd->sleepdep_usecount, 0); | 705 | atomic_set(&cd->sleepdep_usecount, 0); |
678 | } | 706 | } |
679 | 707 | ||
680 | prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | 708 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, |
681 | OMAP3430_CM_SLEEPDEP); | 709 | OMAP3430_CM_SLEEPDEP); |
682 | 710 | ||
683 | return 0; | 711 | return 0; |
684 | } | 712 | } |
685 | 713 | ||
686 | /** | 714 | /** |
687 | * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode | ||
688 | * @clkdm: struct clkdm * of a clockdomain | ||
689 | * | ||
690 | * Return the clockdomain @clkdm current state transition mode from the | ||
691 | * corresponding domain CM_CLKSTCTRL register. Returns -EINVAL if @clkdm | ||
692 | * is NULL or the current mode upon success. | ||
693 | */ | ||
694 | static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm) | ||
695 | { | ||
696 | u32 v; | ||
697 | |||
698 | if (!clkdm) | ||
699 | return -EINVAL; | ||
700 | |||
701 | v = __raw_readl(clkdm->clkstctrl_reg); | ||
702 | v &= clkdm->clktrctrl_mask; | ||
703 | v >>= __ffs(clkdm->clktrctrl_mask); | ||
704 | |||
705 | return v; | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * omap2_clkdm_sleep - force clockdomain sleep transition | 715 | * omap2_clkdm_sleep - force clockdomain sleep transition |
710 | * @clkdm: struct clockdomain * | 716 | * @clkdm: struct clockdomain * |
711 | * | 717 | * |
@@ -729,18 +735,19 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) | |||
729 | 735 | ||
730 | if (cpu_is_omap24xx()) { | 736 | if (cpu_is_omap24xx()) { |
731 | 737 | ||
732 | cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, | 738 | omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, |
733 | clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); | 739 | clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); |
734 | 740 | ||
735 | } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { | 741 | } else if (cpu_is_omap34xx()) { |
742 | |||
743 | omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, | ||
744 | clkdm->clktrctrl_mask); | ||
736 | 745 | ||
737 | u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP << | 746 | } else if (cpu_is_omap44xx()) { |
738 | __ffs(clkdm->clktrctrl_mask)); | ||
739 | 747 | ||
740 | u32 v = __raw_readl(clkdm->clkstctrl_reg); | 748 | omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition, |
741 | v &= ~(clkdm->clktrctrl_mask); | 749 | clkdm->cm_inst, |
742 | v |= bits; | 750 | clkdm->clkdm_offs); |
743 | __raw_writel(v, clkdm->clkstctrl_reg); | ||
744 | 751 | ||
745 | } else { | 752 | } else { |
746 | BUG(); | 753 | BUG(); |
@@ -773,18 +780,19 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) | |||
773 | 780 | ||
774 | if (cpu_is_omap24xx()) { | 781 | if (cpu_is_omap24xx()) { |
775 | 782 | ||
776 | cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, | 783 | omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, |
777 | clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); | 784 | clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); |
778 | 785 | ||
779 | } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { | 786 | } else if (cpu_is_omap34xx()) { |
780 | 787 | ||
781 | u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP << | 788 | omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs, |
782 | __ffs(clkdm->clktrctrl_mask)); | 789 | clkdm->clktrctrl_mask); |
783 | 790 | ||
784 | u32 v = __raw_readl(clkdm->clkstctrl_reg); | 791 | } else if (cpu_is_omap44xx()) { |
785 | v &= ~(clkdm->clktrctrl_mask); | 792 | |
786 | v |= bits; | 793 | omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, |
787 | __raw_writel(v, clkdm->clkstctrl_reg); | 794 | clkdm->cm_inst, |
795 | clkdm->clkdm_offs); | ||
788 | 796 | ||
789 | } else { | 797 | } else { |
790 | BUG(); | 798 | BUG(); |
@@ -829,7 +837,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) | |||
829 | _clkdm_add_autodeps(clkdm); | 837 | _clkdm_add_autodeps(clkdm); |
830 | } | 838 | } |
831 | 839 | ||
832 | _omap2_clkdm_set_hwsup(clkdm, 1); | 840 | _enable_hwsup(clkdm); |
833 | 841 | ||
834 | pwrdm_clkdm_state_switch(clkdm); | 842 | pwrdm_clkdm_state_switch(clkdm); |
835 | } | 843 | } |
@@ -857,7 +865,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) | |||
857 | pr_debug("clockdomain: disabling automatic idle transitions for %s\n", | 865 | pr_debug("clockdomain: disabling automatic idle transitions for %s\n", |
858 | clkdm->name); | 866 | clkdm->name); |
859 | 867 | ||
860 | _omap2_clkdm_set_hwsup(clkdm, 0); | 868 | _disable_hwsup(clkdm); |
861 | 869 | ||
862 | /* | 870 | /* |
863 | * XXX This should be removed once TI adds wakeup/sleep | 871 | * XXX This should be removed once TI adds wakeup/sleep |
@@ -891,7 +899,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) | |||
891 | */ | 899 | */ |
892 | int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) | 900 | int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) |
893 | { | 901 | { |
894 | int v; | 902 | bool hwsup = false; |
895 | 903 | ||
896 | /* | 904 | /* |
897 | * XXX Rewrite this code to maintain a list of enabled | 905 | * XXX Rewrite this code to maintain a list of enabled |
@@ -909,17 +917,27 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) | |||
909 | pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, | 917 | pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, |
910 | clk->name); | 918 | clk->name); |
911 | 919 | ||
912 | if (!clkdm->clkstctrl_reg) | 920 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
913 | return 0; | ||
914 | 921 | ||
915 | v = omap2_clkdm_clktrctrl_read(clkdm); | 922 | if (!clkdm->clktrctrl_mask) |
923 | return 0; | ||
916 | 924 | ||
917 | if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || | 925 | hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, |
918 | (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { | 926 | clkdm->clktrctrl_mask); |
927 | |||
928 | } else if (cpu_is_omap44xx()) { | ||
929 | |||
930 | hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, | ||
931 | clkdm->cm_inst, | ||
932 | clkdm->clkdm_offs); | ||
933 | |||
934 | } | ||
935 | |||
936 | if (hwsup) { | ||
919 | /* Disable HW transitions when we are changing deps */ | 937 | /* Disable HW transitions when we are changing deps */ |
920 | _omap2_clkdm_set_hwsup(clkdm, 0); | 938 | _disable_hwsup(clkdm); |
921 | _clkdm_add_autodeps(clkdm); | 939 | _clkdm_add_autodeps(clkdm); |
922 | _omap2_clkdm_set_hwsup(clkdm, 1); | 940 | _enable_hwsup(clkdm); |
923 | } else { | 941 | } else { |
924 | omap2_clkdm_wakeup(clkdm); | 942 | omap2_clkdm_wakeup(clkdm); |
925 | } | 943 | } |
@@ -946,7 +964,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) | |||
946 | */ | 964 | */ |
947 | int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) | 965 | int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) |
948 | { | 966 | { |
949 | int v; | 967 | bool hwsup = false; |
950 | 968 | ||
951 | /* | 969 | /* |
952 | * XXX Rewrite this code to maintain a list of enabled | 970 | * XXX Rewrite this code to maintain a list of enabled |
@@ -971,17 +989,27 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) | |||
971 | pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, | 989 | pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, |
972 | clk->name); | 990 | clk->name); |
973 | 991 | ||
974 | if (!clkdm->clkstctrl_reg) | 992 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
975 | return 0; | ||
976 | 993 | ||
977 | v = omap2_clkdm_clktrctrl_read(clkdm); | 994 | if (!clkdm->clktrctrl_mask) |
995 | return 0; | ||
996 | |||
997 | hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
998 | clkdm->clktrctrl_mask); | ||
999 | |||
1000 | } else if (cpu_is_omap44xx()) { | ||
1001 | |||
1002 | hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, | ||
1003 | clkdm->cm_inst, | ||
1004 | clkdm->clkdm_offs); | ||
1005 | |||
1006 | } | ||
978 | 1007 | ||
979 | if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || | 1008 | if (hwsup) { |
980 | (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { | ||
981 | /* Disable HW transitions when we are changing deps */ | 1009 | /* Disable HW transitions when we are changing deps */ |
982 | _omap2_clkdm_set_hwsup(clkdm, 0); | 1010 | _disable_hwsup(clkdm); |
983 | _clkdm_del_autodeps(clkdm); | 1011 | _clkdm_del_autodeps(clkdm); |
984 | _omap2_clkdm_set_hwsup(clkdm, 1); | 1012 | _enable_hwsup(clkdm); |
985 | } else { | 1013 | } else { |
986 | omap2_clkdm_sleep(clkdm); | 1014 | omap2_clkdm_sleep(clkdm); |
987 | } | 1015 | } |