summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 e9fced9bd8f5..5de72eef9724 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -10,7 +10,7 @@ struct clk;
struct clk_ops {
void (*init)(struct clk *clk);
- void (*enable)(struct clk *clk);
+ int (*enable)(struct clk *clk);
void (*disable)(struct clk *clk);
unsigned long (*recalc)(struct clk *clk);
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 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)
}
}
-static int __clk_enable(struct clk *clk)
+static void __clk_disable(struct clk *clk)
{
- if (clk->usecount++ == 0) {
- if (clk->parent)
- __clk_enable(clk->parent);
-
- if (clk->ops && clk->ops->enable)
- clk->ops->enable(clk);
+ if (clk->usecount == 0) {
+ printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
+ clk->name);
+ WARN_ON(1);
+ return;
}
- return 0;
+ if (!(--clk->usecount)) {
+ if (likely(clk->ops && clk->ops->disable))
+ clk->ops->disable(clk);
+ if (likely(clk->parent))
+ __clk_disable(clk->parent);
+ }
}
-int clk_enable(struct clk *clk)
+void clk_disable(struct clk *clk)
{
unsigned long flags;
- int ret;
if (!clk)
- return -EINVAL;
+ return;
spin_lock_irqsave(&clock_lock, flags);
- ret = __clk_enable(clk);
+ __clk_disable(clk);
spin_unlock_irqrestore(&clock_lock, flags);
-
- return ret;
}
-EXPORT_SYMBOL_GPL(clk_enable);
+EXPORT_SYMBOL_GPL(clk_disable);
-static void __clk_disable(struct clk *clk)
+static int __clk_enable(struct clk *clk)
{
- if (clk->usecount > 0 && !(--clk->usecount)) {
- if (likely(clk->ops && clk->ops->disable))
- clk->ops->disable(clk);
- if (likely(clk->parent))
- __clk_disable(clk->parent);
+ int ret = 0;
+
+ if (clk->usecount++ == 0) {
+ if (clk->parent) {
+ ret = __clk_enable(clk->parent);
+ if (unlikely(ret))
+ goto err;
+ }
+
+ if (clk->ops && clk->ops->enable) {
+ ret = clk->ops->enable(clk);
+ if (ret) {
+ if (clk->parent)
+ __clk_disable(clk->parent);
+ goto err;
+ }
+ }
}
+
+ return ret;
+err:
+ clk->usecount--;
+ return ret;
}
-void clk_disable(struct clk *clk)
+int clk_enable(struct clk *clk)
{
unsigned long flags;
+ int ret;
if (!clk)
- return;
+ return -EINVAL;
spin_lock_irqsave(&clock_lock, flags);
- __clk_disable(clk);
+ ret = __clk_enable(clk);
spin_unlock_irqrestore(&clock_lock, flags);
+
+ return ret;
}
-EXPORT_SYMBOL_GPL(clk_disable);
+EXPORT_SYMBOL_GPL(clk_enable);
static LIST_HEAD(root_clks);
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index f777d00d4af6..1c41db41de7e 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)
return 0;
}
-static void sh7722_siu_enable(struct clk *clk)
+static int sh7722_siu_enable(struct clk *clk)
{
- sh7722_siu_start_stop(clk, 1);
+ return sh7722_siu_start_stop(clk, 1);
}
static void sh7722_siu_disable(struct clk *clk)
@@ -491,12 +491,13 @@ static struct clk_ops sh7722_siu_clk_ops = {
#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
-static void sh7722_video_enable(struct clk *clk)
+static int sh7722_video_enable(struct clk *clk)
{
unsigned long r;
r = ctrl_inl(VCLKCR);
ctrl_outl( r & ~(1<<8), VCLKCR);
+ return 0;
}
static void sh7722_video_disable(struct clk *clk)
@@ -630,9 +631,9 @@ static int sh7722_mstpcr_start_stop(struct clk *clk, int enable)
return 0;
}
-static void sh7722_mstpcr_enable(struct clk *clk)
+static int sh7722_mstpcr_enable(struct clk *clk)
{
- sh7722_mstpcr_start_stop(clk, 1);
+ return sh7722_mstpcr_start_stop(clk, 1);
}
static void sh7722_mstpcr_disable(struct clk *clk)