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