diff options
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 96 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cm3xxx.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cminst44xx.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm-debug.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx_3xxx.c | 3 |
7 files changed, 92 insertions, 30 deletions
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index ab194753eb7a..2da3b5ec010c 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c | |||
@@ -210,7 +210,8 @@ static int _clkdm_add_wkdep(struct clockdomain *clkdm1, | |||
210 | return ret; | 210 | return ret; |
211 | } | 211 | } |
212 | 212 | ||
213 | if (atomic_inc_return(&cd->wkdep_usecount) == 1) { | 213 | cd->wkdep_usecount++; |
214 | if (cd->wkdep_usecount == 1) { | ||
214 | pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n", | 215 | pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n", |
215 | clkdm1->name, clkdm2->name); | 216 | clkdm1->name, clkdm2->name); |
216 | 217 | ||
@@ -252,7 +253,8 @@ static int _clkdm_del_wkdep(struct clockdomain *clkdm1, | |||
252 | return ret; | 253 | return ret; |
253 | } | 254 | } |
254 | 255 | ||
255 | if (atomic_dec_return(&cd->wkdep_usecount) == 0) { | 256 | cd->wkdep_usecount--; |
257 | if (cd->wkdep_usecount == 0) { | ||
256 | pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n", | 258 | pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n", |
257 | clkdm1->name, clkdm2->name); | 259 | clkdm1->name, clkdm2->name); |
258 | 260 | ||
@@ -296,7 +298,8 @@ static int _clkdm_add_sleepdep(struct clockdomain *clkdm1, | |||
296 | return ret; | 298 | return ret; |
297 | } | 299 | } |
298 | 300 | ||
299 | if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { | 301 | cd->sleepdep_usecount++; |
302 | if (cd->sleepdep_usecount == 1) { | ||
300 | pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n", | 303 | pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n", |
301 | clkdm1->name, clkdm2->name); | 304 | clkdm1->name, clkdm2->name); |
302 | 305 | ||
@@ -340,7 +343,8 @@ static int _clkdm_del_sleepdep(struct clockdomain *clkdm1, | |||
340 | return ret; | 343 | return ret; |
341 | } | 344 | } |
342 | 345 | ||
343 | if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { | 346 | cd->sleepdep_usecount--; |
347 | if (cd->sleepdep_usecount == 0) { | ||
344 | pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n", | 348 | pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n", |
345 | clkdm1->name, clkdm2->name); | 349 | clkdm1->name, clkdm2->name); |
346 | 350 | ||
@@ -567,7 +571,21 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) | |||
567 | */ | 571 | */ |
568 | int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 572 | int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
569 | { | 573 | { |
570 | return _clkdm_add_wkdep(clkdm1, clkdm2); | 574 | struct clkdm_dep *cd; |
575 | int ret; | ||
576 | |||
577 | if (!clkdm1 || !clkdm2) | ||
578 | return -EINVAL; | ||
579 | |||
580 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | ||
581 | if (IS_ERR(cd)) | ||
582 | return PTR_ERR(cd); | ||
583 | |||
584 | pwrdm_lock(cd->clkdm->pwrdm.ptr); | ||
585 | ret = _clkdm_add_wkdep(clkdm1, clkdm2); | ||
586 | pwrdm_unlock(cd->clkdm->pwrdm.ptr); | ||
587 | |||
588 | return ret; | ||
571 | } | 589 | } |
572 | 590 | ||
573 | /** | 591 | /** |
@@ -582,7 +600,21 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
582 | */ | 600 | */ |
583 | int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 601 | int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
584 | { | 602 | { |
585 | return _clkdm_del_wkdep(clkdm1, clkdm2); | 603 | struct clkdm_dep *cd; |
604 | int ret; | ||
605 | |||
606 | if (!clkdm1 || !clkdm2) | ||
607 | return -EINVAL; | ||
608 | |||
609 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | ||
610 | if (IS_ERR(cd)) | ||
611 | return PTR_ERR(cd); | ||
612 | |||
613 | pwrdm_lock(cd->clkdm->pwrdm.ptr); | ||
614 | ret = _clkdm_del_wkdep(clkdm1, clkdm2); | ||
615 | pwrdm_unlock(cd->clkdm->pwrdm.ptr); | ||
616 | |||
617 | return ret; | ||
586 | } | 618 | } |
587 | 619 | ||
588 | /** | 620 | /** |
@@ -620,7 +652,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
620 | return ret; | 652 | return ret; |
621 | } | 653 | } |
622 | 654 | ||
623 | /* XXX It's faster to return the atomic wkdep_usecount */ | 655 | /* XXX It's faster to return the wkdep_usecount */ |
624 | return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2); | 656 | return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2); |
625 | } | 657 | } |
626 | 658 | ||
@@ -659,7 +691,21 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | |||
659 | */ | 691 | */ |
660 | int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 692 | int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
661 | { | 693 | { |
662 | return _clkdm_add_sleepdep(clkdm1, clkdm2); | 694 | struct clkdm_dep *cd; |
695 | int ret; | ||
696 | |||
697 | if (!clkdm1 || !clkdm2) | ||
698 | return -EINVAL; | ||
699 | |||
700 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | ||
701 | if (IS_ERR(cd)) | ||
702 | return PTR_ERR(cd); | ||
703 | |||
704 | pwrdm_lock(cd->clkdm->pwrdm.ptr); | ||
705 | ret = _clkdm_add_sleepdep(clkdm1, clkdm2); | ||
706 | pwrdm_unlock(cd->clkdm->pwrdm.ptr); | ||
707 | |||
708 | return ret; | ||
663 | } | 709 | } |
664 | 710 | ||
665 | /** | 711 | /** |
@@ -676,7 +722,21 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
676 | */ | 722 | */ |
677 | int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | 723 | int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) |
678 | { | 724 | { |
679 | return _clkdm_del_sleepdep(clkdm1, clkdm2); | 725 | struct clkdm_dep *cd; |
726 | int ret; | ||
727 | |||
728 | if (!clkdm1 || !clkdm2) | ||
729 | return -EINVAL; | ||
730 | |||
731 | cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); | ||
732 | if (IS_ERR(cd)) | ||
733 | return PTR_ERR(cd); | ||
734 | |||
735 | pwrdm_lock(cd->clkdm->pwrdm.ptr); | ||
736 | ret = _clkdm_del_sleepdep(clkdm1, clkdm2); | ||
737 | pwrdm_unlock(cd->clkdm->pwrdm.ptr); | ||
738 | |||
739 | return ret; | ||
680 | } | 740 | } |
681 | 741 | ||
682 | /** | 742 | /** |
@@ -716,7 +776,7 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) | |||
716 | return ret; | 776 | return ret; |
717 | } | 777 | } |
718 | 778 | ||
719 | /* XXX It's faster to return the atomic sleepdep_usecount */ | 779 | /* XXX It's faster to return the sleepdep_usecount */ |
720 | return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2); | 780 | return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2); |
721 | } | 781 | } |
722 | 782 | ||
@@ -1063,7 +1123,8 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) | |||
1063 | * should be called for every clock instance or hwmod that is | 1123 | * should be called for every clock instance or hwmod that is |
1064 | * enabled, so the clkdm can be force woken up. | 1124 | * enabled, so the clkdm can be force woken up. |
1065 | */ | 1125 | */ |
1066 | if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) { | 1126 | clkdm->usecount++; |
1127 | if (clkdm->usecount > 1 && autodeps) { | ||
1067 | pwrdm_unlock(clkdm->pwrdm.ptr); | 1128 | pwrdm_unlock(clkdm->pwrdm.ptr); |
1068 | return 0; | 1129 | return 0; |
1069 | } | 1130 | } |
@@ -1125,17 +1186,17 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) | |||
1125 | pwrdm_lock(clkdm->pwrdm.ptr); | 1186 | pwrdm_lock(clkdm->pwrdm.ptr); |
1126 | 1187 | ||
1127 | /* corner case: disabling unused clocks */ | 1188 | /* corner case: disabling unused clocks */ |
1128 | if ((__clk_get_enable_count(clk) == 0) && | 1189 | if ((__clk_get_enable_count(clk) == 0) && clkdm->usecount == 0) |
1129 | (atomic_read(&clkdm->usecount) == 0)) | ||
1130 | goto ccd_exit; | 1190 | goto ccd_exit; |
1131 | 1191 | ||
1132 | if (atomic_read(&clkdm->usecount) == 0) { | 1192 | if (clkdm->usecount == 0) { |
1133 | pwrdm_unlock(clkdm->pwrdm.ptr); | 1193 | pwrdm_unlock(clkdm->pwrdm.ptr); |
1134 | WARN_ON(1); /* underflow */ | 1194 | WARN_ON(1); /* underflow */ |
1135 | return -ERANGE; | 1195 | return -ERANGE; |
1136 | } | 1196 | } |
1137 | 1197 | ||
1138 | if (atomic_dec_return(&clkdm->usecount) > 0) { | 1198 | clkdm->usecount--; |
1199 | if (clkdm->usecount > 0) { | ||
1139 | pwrdm_unlock(clkdm->pwrdm.ptr); | 1200 | pwrdm_unlock(clkdm->pwrdm.ptr); |
1140 | return 0; | 1201 | return 0; |
1141 | } | 1202 | } |
@@ -1213,13 +1274,14 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) | |||
1213 | 1274 | ||
1214 | pwrdm_lock(clkdm->pwrdm.ptr); | 1275 | pwrdm_lock(clkdm->pwrdm.ptr); |
1215 | 1276 | ||
1216 | if (atomic_read(&clkdm->usecount) == 0) { | 1277 | if (clkdm->usecount == 0) { |
1217 | pwrdm_unlock(clkdm->pwrdm.ptr); | 1278 | pwrdm_unlock(clkdm->pwrdm.ptr); |
1218 | WARN_ON(1); /* underflow */ | 1279 | WARN_ON(1); /* underflow */ |
1219 | return -ERANGE; | 1280 | return -ERANGE; |
1220 | } | 1281 | } |
1221 | 1282 | ||
1222 | if (atomic_dec_return(&clkdm->usecount) > 0) { | 1283 | clkdm->usecount--; |
1284 | if (clkdm->usecount > 0) { | ||
1223 | pwrdm_unlock(clkdm->pwrdm.ptr); | 1285 | pwrdm_unlock(clkdm->pwrdm.ptr); |
1224 | return 0; | 1286 | return 0; |
1225 | } | 1287 | } |
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 50c3cd8bd706..2da37656a693 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h | |||
@@ -91,8 +91,8 @@ struct clkdm_autodep { | |||
91 | struct clkdm_dep { | 91 | struct clkdm_dep { |
92 | const char *clkdm_name; | 92 | const char *clkdm_name; |
93 | struct clockdomain *clkdm; | 93 | struct clockdomain *clkdm; |
94 | atomic_t wkdep_usecount; | 94 | s16 wkdep_usecount; |
95 | atomic_t sleepdep_usecount; | 95 | s16 sleepdep_usecount; |
96 | }; | 96 | }; |
97 | 97 | ||
98 | /* Possible flags for struct clockdomain._flags */ | 98 | /* Possible flags for struct clockdomain._flags */ |
@@ -136,7 +136,7 @@ struct clockdomain { | |||
136 | const u16 clkdm_offs; | 136 | const u16 clkdm_offs; |
137 | struct clkdm_dep *wkdep_srcs; | 137 | struct clkdm_dep *wkdep_srcs; |
138 | struct clkdm_dep *sleepdep_srcs; | 138 | struct clkdm_dep *sleepdep_srcs; |
139 | atomic_t usecount; | 139 | int usecount; |
140 | struct list_head node; | 140 | struct list_head node; |
141 | }; | 141 | }; |
142 | 142 | ||
diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index b94af4cb9dd9..9061c307d915 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c | |||
@@ -186,7 +186,7 @@ static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) | |||
186 | continue; /* only happens if data is erroneous */ | 186 | continue; /* only happens if data is erroneous */ |
187 | 187 | ||
188 | mask |= 1 << cd->clkdm->dep_bit; | 188 | mask |= 1 << cd->clkdm->dep_bit; |
189 | atomic_set(&cd->sleepdep_usecount, 0); | 189 | cd->sleepdep_usecount = 0; |
190 | } | 190 | } |
191 | omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | 191 | omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, |
192 | OMAP3430_CM_SLEEPDEP); | 192 | OMAP3430_CM_SLEEPDEP); |
@@ -209,7 +209,7 @@ static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm) | |||
209 | 209 | ||
210 | static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm) | 210 | static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm) |
211 | { | 211 | { |
212 | if (atomic_read(&clkdm->usecount) > 0) | 212 | if (clkdm->usecount > 0) |
213 | clkdm_add_autodeps(clkdm); | 213 | clkdm_add_autodeps(clkdm); |
214 | 214 | ||
215 | omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | 215 | omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, |
@@ -221,7 +221,7 @@ static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm) | |||
221 | omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | 221 | omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, |
222 | clkdm->clktrctrl_mask); | 222 | clkdm->clktrctrl_mask); |
223 | 223 | ||
224 | if (atomic_read(&clkdm->usecount) > 0) | 224 | if (clkdm->usecount > 0) |
225 | clkdm_del_autodeps(clkdm); | 225 | clkdm_del_autodeps(clkdm); |
226 | } | 226 | } |
227 | 227 | ||
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 7f9a464f01e9..f0290f5566fe 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c | |||
@@ -393,7 +393,7 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) | |||
393 | continue; /* only happens if data is erroneous */ | 393 | continue; /* only happens if data is erroneous */ |
394 | 394 | ||
395 | mask |= 1 << cd->clkdm->dep_bit; | 395 | mask |= 1 << cd->clkdm->dep_bit; |
396 | atomic_set(&cd->wkdep_usecount, 0); | 396 | cd->wkdep_usecount = 0; |
397 | } | 397 | } |
398 | 398 | ||
399 | omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, | 399 | omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, |
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index e2c291f52f92..6db89ae92389 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c | |||
@@ -83,10 +83,8 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) | |||
83 | strncmp(clkdm->name, "dpll", 4) == 0) | 83 | strncmp(clkdm->name, "dpll", 4) == 0) |
84 | return 0; | 84 | return 0; |
85 | 85 | ||
86 | seq_printf(s, "%s->%s (%d)", clkdm->name, | 86 | seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name, |
87 | clkdm->pwrdm.ptr->name, | 87 | clkdm->usecount); |
88 | atomic_read(&clkdm->usecount)); | ||
89 | seq_printf(s, "\n"); | ||
90 | 88 | ||
91 | return 0; | 89 | return 0; |
92 | } | 90 | } |
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 48d6d5d2c926..88586d15004a 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c | |||
@@ -110,11 +110,12 @@ static void __init omap2_init_processor_devices(void) | |||
110 | 110 | ||
111 | int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) | 111 | int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) |
112 | { | 112 | { |
113 | /* XXX The usecount test is racy */ | ||
113 | if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) && | 114 | if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) && |
114 | !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)) | 115 | !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)) |
115 | clkdm_allow_idle(clkdm); | 116 | clkdm_allow_idle(clkdm); |
116 | else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && | 117 | else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && |
117 | atomic_read(&clkdm->usecount) == 0) | 118 | clkdm->usecount == 0) |
118 | clkdm_sleep(clkdm); | 119 | clkdm_sleep(clkdm); |
119 | return 0; | 120 | return 0; |
120 | } | 121 | } |
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index a3e121f94a86..947f6adfed0c 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c | |||
@@ -210,6 +210,7 @@ int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, | |||
210 | PM_WKDEP, (1 << clkdm2->dep_bit)); | 210 | PM_WKDEP, (1 << clkdm2->dep_bit)); |
211 | } | 211 | } |
212 | 212 | ||
213 | /* XXX Caller must hold the clkdm's powerdomain lock */ | ||
213 | int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | 214 | int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) |
214 | { | 215 | { |
215 | struct clkdm_dep *cd; | 216 | struct clkdm_dep *cd; |
@@ -221,7 +222,7 @@ int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | |||
221 | 222 | ||
222 | /* PRM accesses are slow, so minimize them */ | 223 | /* PRM accesses are slow, so minimize them */ |
223 | mask |= 1 << cd->clkdm->dep_bit; | 224 | mask |= 1 << cd->clkdm->dep_bit; |
224 | atomic_set(&cd->wkdep_usecount, 0); | 225 | cd->wkdep_usecount = 0; |
225 | } | 226 | } |
226 | 227 | ||
227 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | 228 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, |