aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2013-01-26 02:58:17 -0500
committerPaul Walmsley <paul@pwsan.com>2013-01-29 16:59:58 -0500
commit92493870196f52c743330db7b545b54b2abfda82 (patch)
treef4861c754544226fbba2f5756eb701a71ba82062
parent65958fb6ca7b7e504caf852e492fe554224de1ba (diff)
ARM: OMAP2+: clockdomain: convert existing atomic usecounts into spinlock-protected shorts/ints
The atomic usecounts seem to be confusing, and are no longer needed since the operations that they are attached to really should take place under lock. Replace the atomic counters with simple integers, protected by the enclosing powerdomain spinlock. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Kevin Hilman <khilman@deeprootsystems.com>
-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,