aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/clockdomain.c96
-rw-r--r--arch/arm/mach-omap2/clockdomain.h6
-rw-r--r--arch/arm/mach-omap2/cm3xxx.c6
-rw-r--r--arch/arm/mach-omap2/cminst44xx.c2
-rw-r--r--arch/arm/mach-omap2/pm-debug.c6
-rw-r--r--arch/arm/mach-omap2/pm.c3
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.c3
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 */
568int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 572int 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 */
583int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 601int 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 */
660int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 692int 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 */
677int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 723int 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 {
91struct clkdm_dep { 91struct 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
210static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm) 210static 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
111int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) 111int __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 */
213int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) 214int 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,