aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-rw-r--r--arch/sh/include/asm/clock.h2
-rw-r--r--arch/sh/kernel/cpu/clock.c71
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c11
3 files changed, 53 insertions, 31 deletions
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index e9fced9bd8f..5de72eef972 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -10,7 +10,7 @@ struct clk;
10 10
11struct clk_ops { 11struct clk_ops {
12 void (*init)(struct clk *clk); 12 void (*init)(struct clk *clk);
13 void (*enable)(struct clk *clk); 13 int (*enable)(struct clk *clk);
14 void (*disable)(struct clk *clk); 14 void (*disable)(struct clk *clk);
15 unsigned long (*recalc)(struct clk *clk); 15 unsigned long (*recalc)(struct clk *clk);
16 int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id); 16 int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index c683be5ba8b..e027fe5898d 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
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index f777d00d4af..1c41db41de7 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -472,9 +472,9 @@ static int sh7722_siu_start_stop(struct clk *clk, int enable)
472 return 0; 472 return 0;
473} 473}
474 474
475static void sh7722_siu_enable(struct clk *clk) 475static int sh7722_siu_enable(struct clk *clk)
476{ 476{
477 sh7722_siu_start_stop(clk, 1); 477 return sh7722_siu_start_stop(clk, 1);
478} 478}
479 479
480static void sh7722_siu_disable(struct clk *clk) 480static void sh7722_siu_disable(struct clk *clk)
@@ -491,12 +491,13 @@ static struct clk_ops sh7722_siu_clk_ops = {
491 491
492#endif /* CONFIG_CPU_SUBTYPE_SH7343 */ 492#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
493 493
494static void sh7722_video_enable(struct clk *clk) 494static int sh7722_video_enable(struct clk *clk)
495{ 495{
496 unsigned long r; 496 unsigned long r;
497 497
498 r = ctrl_inl(VCLKCR); 498 r = ctrl_inl(VCLKCR);
499 ctrl_outl( r & ~(1<<8), VCLKCR); 499 ctrl_outl( r & ~(1<<8), VCLKCR);
500 return 0;
500} 501}
501 502
502static void sh7722_video_disable(struct clk *clk) 503static void sh7722_video_disable(struct clk *clk)
@@ -630,9 +631,9 @@ static int sh7722_mstpcr_start_stop(struct clk *clk, int enable)
630 return 0; 631 return 0;
631} 632}
632 633
633static void sh7722_mstpcr_enable(struct clk *clk) 634static int sh7722_mstpcr_enable(struct clk *clk)
634{ 635{
635 sh7722_mstpcr_start_stop(clk, 1); 636 return sh7722_mstpcr_start_stop(clk, 1);
636} 637}
637 638
638static void sh7722_mstpcr_disable(struct clk *clk) 639static void sh7722_mstpcr_disable(struct clk *clk)