aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/clock.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-05-11 16:30:10 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-05-11 16:30:10 -0400
commitae891a4264c91246c0b4c22be68b9838747ae48d (patch)
tree18da25fbd0322f6d2f4288dbf741609e53ae297e /arch/sh/kernel/cpu/clock.c
parent154502e160e02dee7b00ec2149762ae5d48e0bb4 (diff)
sh: clkfwk: Fix up the clk_enable() error path.
There are a couple of instances where a clk_enable() can fail, which the SH-Mobile code presently handles, but doesn't get reported all the way back up. This fixes up the return type so the errors make it all the way down to the drivers. Additionally, we now also error out properly if the parent enable fails. Prep work for aggressively turning off unused clocks on boot. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/cpu/clock.c')
-rw-r--r--arch/sh/kernel/cpu/clock.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index c683be5ba8b2..e027fe5898d6 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -93,57 +93,78 @@ void propagate_rate(struct clk *tclk)
93 } 93 }
94} 94}
95 95
96static int __clk_enable(struct clk *clk) 96static void __clk_disable(struct clk *clk)
97{ 97{
98 if (clk->usecount++ == 0) { 98 if (clk->usecount == 0) {
99 if (clk->parent) 99 printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
100 __clk_enable(clk->parent); 100 clk->name);
101 101 WARN_ON(1);
102 if (clk->ops && clk->ops->enable) 102 return;
103 clk->ops->enable(clk);
104 } 103 }
105 104
106 return 0; 105 if (!(--clk->usecount)) {
106 if (likely(clk->ops && clk->ops->disable))
107 clk->ops->disable(clk);
108 if (likely(clk->parent))
109 __clk_disable(clk->parent);
110 }
107} 111}
108 112
109int clk_enable(struct clk *clk) 113void clk_disable(struct clk *clk)
110{ 114{
111 unsigned long flags; 115 unsigned long flags;
112 int ret;
113 116
114 if (!clk) 117 if (!clk)
115 return -EINVAL; 118 return;
116 119
117 spin_lock_irqsave(&clock_lock, flags); 120 spin_lock_irqsave(&clock_lock, flags);
118 ret = __clk_enable(clk); 121 __clk_disable(clk);
119 spin_unlock_irqrestore(&clock_lock, flags); 122 spin_unlock_irqrestore(&clock_lock, flags);
120
121 return ret;
122} 123}
123EXPORT_SYMBOL_GPL(clk_enable); 124EXPORT_SYMBOL_GPL(clk_disable);
124 125
125static void __clk_disable(struct clk *clk) 126static int __clk_enable(struct clk *clk)
126{ 127{
127 if (clk->usecount > 0 && !(--clk->usecount)) { 128 int ret = 0;
128 if (likely(clk->ops && clk->ops->disable)) 129
129 clk->ops->disable(clk); 130 if (clk->usecount++ == 0) {
130 if (likely(clk->parent)) 131 if (clk->parent) {
131 __clk_disable(clk->parent); 132 ret = __clk_enable(clk->parent);
133 if (unlikely(ret))
134 goto err;
135 }
136
137 if (clk->ops && clk->ops->enable) {
138 ret = clk->ops->enable(clk);
139 if (ret) {
140 if (clk->parent)
141 __clk_disable(clk->parent);
142 goto err;
143 }
144 }
132 } 145 }
146
147 return ret;
148err:
149 clk->usecount--;
150 return ret;
133} 151}
134 152
135void clk_disable(struct clk *clk) 153int clk_enable(struct clk *clk)
136{ 154{
137 unsigned long flags; 155 unsigned long flags;
156 int ret;
138 157
139 if (!clk) 158 if (!clk)
140 return; 159 return -EINVAL;
141 160
142 spin_lock_irqsave(&clock_lock, flags); 161 spin_lock_irqsave(&clock_lock, flags);
143 __clk_disable(clk); 162 ret = __clk_enable(clk);
144 spin_unlock_irqrestore(&clock_lock, flags); 163 spin_unlock_irqrestore(&clock_lock, flags);
164
165 return ret;
145} 166}
146EXPORT_SYMBOL_GPL(clk_disable); 167EXPORT_SYMBOL_GPL(clk_enable);
147 168
148static LIST_HEAD(root_clks); 169static LIST_HEAD(root_clks);
149 170