aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/clock.c')
-rw-r--r--arch/sh/kernel/cpu/clock.c63
1 files changed, 35 insertions, 28 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 1dc896483b59..f54769f455b1 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -19,7 +19,6 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/mutex.h> 20#include <linux/mutex.h>
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/kref.h>
23#include <linux/kobject.h> 22#include <linux/kobject.h>
24#include <linux/sysdev.h> 23#include <linux/sysdev.h>
25#include <linux/seq_file.h> 24#include <linux/seq_file.h>
@@ -27,7 +26,6 @@
27#include <linux/platform_device.h> 26#include <linux/platform_device.h>
28#include <linux/proc_fs.h> 27#include <linux/proc_fs.h>
29#include <asm/clock.h> 28#include <asm/clock.h>
30#include <asm/timer.h>
31 29
32static LIST_HEAD(clock_list); 30static LIST_HEAD(clock_list);
33static DEFINE_SPINLOCK(clock_lock); 31static DEFINE_SPINLOCK(clock_lock);
@@ -90,7 +88,7 @@ static void propagate_rate(struct clk *clk)
90 } 88 }
91} 89}
92 90
93static int __clk_enable(struct clk *clk) 91static void __clk_init(struct clk *clk)
94{ 92{
95 /* 93 /*
96 * See if this is the first time we're enabling the clock, some 94 * See if this is the first time we're enabling the clock, some
@@ -99,17 +97,34 @@ static int __clk_enable(struct clk *clk)
99 * changes and the clock needs to hunt for the proper set of 97 * changes and the clock needs to hunt for the proper set of
100 * divisors to use before it can effectively recalc. 98 * divisors to use before it can effectively recalc.
101 */ 99 */
102 if (unlikely(atomic_read(&clk->kref.refcount) == 1)) 100
101 if (clk->flags & CLK_NEEDS_INIT) {
103 if (clk->ops && clk->ops->init) 102 if (clk->ops && clk->ops->init)
104 clk->ops->init(clk); 103 clk->ops->init(clk);
105 104
106 kref_get(&clk->kref); 105 clk->flags &= ~CLK_NEEDS_INIT;
106 }
107}
108
109static int __clk_enable(struct clk *clk)
110{
111 if (!clk)
112 return -EINVAL;
107 113
114 clk->usecount++;
115
116 /* nothing to do if always enabled */
108 if (clk->flags & CLK_ALWAYS_ENABLED) 117 if (clk->flags & CLK_ALWAYS_ENABLED)
109 return 0; 118 return 0;
110 119
111 if (likely(clk->ops && clk->ops->enable)) 120 if (clk->usecount == 1) {
112 clk->ops->enable(clk); 121 __clk_init(clk);
122
123 __clk_enable(clk->parent);
124
125 if (clk->ops && clk->ops->enable)
126 clk->ops->enable(clk);
127 }
113 128
114 return 0; 129 return 0;
115} 130}
@@ -119,11 +134,6 @@ int clk_enable(struct clk *clk)
119 unsigned long flags; 134 unsigned long flags;
120 int ret; 135 int ret;
121 136
122 if (!clk)
123 return -EINVAL;
124
125 clk_enable(clk->parent);
126
127 spin_lock_irqsave(&clock_lock, flags); 137 spin_lock_irqsave(&clock_lock, flags);
128 ret = __clk_enable(clk); 138 ret = __clk_enable(clk);
129 spin_unlock_irqrestore(&clock_lock, flags); 139 spin_unlock_irqrestore(&clock_lock, flags);
@@ -132,21 +142,23 @@ int clk_enable(struct clk *clk)
132} 142}
133EXPORT_SYMBOL_GPL(clk_enable); 143EXPORT_SYMBOL_GPL(clk_enable);
134 144
135static void clk_kref_release(struct kref *kref)
136{
137 /* Nothing to do */
138}
139
140static void __clk_disable(struct clk *clk) 145static void __clk_disable(struct clk *clk)
141{ 146{
142 int count = kref_put(&clk->kref, clk_kref_release); 147 if (!clk)
148 return;
149
150 clk->usecount--;
151
152 WARN_ON(clk->usecount < 0);
143 153
144 if (clk->flags & CLK_ALWAYS_ENABLED) 154 if (clk->flags & CLK_ALWAYS_ENABLED)
145 return; 155 return;
146 156
147 if (!count) { /* count reaches zero, disable the clock */ 157 if (clk->usecount == 0) {
148 if (likely(clk->ops && clk->ops->disable)) 158 if (likely(clk->ops && clk->ops->disable))
149 clk->ops->disable(clk); 159 clk->ops->disable(clk);
160
161 __clk_disable(clk->parent);
150 } 162 }
151} 163}
152 164
@@ -154,14 +166,9 @@ void clk_disable(struct clk *clk)
154{ 166{
155 unsigned long flags; 167 unsigned long flags;
156 168
157 if (!clk)
158 return;
159
160 spin_lock_irqsave(&clock_lock, flags); 169 spin_lock_irqsave(&clock_lock, flags);
161 __clk_disable(clk); 170 __clk_disable(clk);
162 spin_unlock_irqrestore(&clock_lock, flags); 171 spin_unlock_irqrestore(&clock_lock, flags);
163
164 clk_disable(clk->parent);
165} 172}
166EXPORT_SYMBOL_GPL(clk_disable); 173EXPORT_SYMBOL_GPL(clk_disable);
167 174
@@ -170,14 +177,14 @@ int clk_register(struct clk *clk)
170 mutex_lock(&clock_list_sem); 177 mutex_lock(&clock_list_sem);
171 178
172 list_add(&clk->node, &clock_list); 179 list_add(&clk->node, &clock_list);
173 kref_init(&clk->kref); 180 clk->usecount = 0;
181 clk->flags |= CLK_NEEDS_INIT;
174 182
175 mutex_unlock(&clock_list_sem); 183 mutex_unlock(&clock_list_sem);
176 184
177 if (clk->flags & CLK_ALWAYS_ENABLED) { 185 if (clk->flags & CLK_ALWAYS_ENABLED) {
186 __clk_init(clk);
178 pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name); 187 pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
179 if (clk->ops && clk->ops->init)
180 clk->ops->init(clk);
181 if (clk->ops && clk->ops->enable) 188 if (clk->ops && clk->ops->enable)
182 clk->ops->enable(clk); 189 clk->ops->enable(clk);
183 pr_debug( "Enabled."); 190 pr_debug( "Enabled.");
@@ -353,7 +360,7 @@ static int show_clocks(char *buf, char **start, off_t off,
353 p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name, 360 p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name,
354 rate / 1000000, (rate % 1000000) / 10000, 361 rate / 1000000, (rate % 1000000) / 10000,
355 ((clk->flags & CLK_ALWAYS_ENABLED) || 362 ((clk->flags & CLK_ALWAYS_ENABLED) ||
356 (atomic_read(&clk->kref.refcount) != 1)) ? 363 clk->usecount > 0) ?
357 "enabled" : "disabled"); 364 "enabled" : "disabled");
358 } 365 }
359 366