Pull bugzilla-5452 into release branch
[pandora-kernel.git] / arch / arm / plat-omap / clock.c
1 /*
2  *  linux/arch/arm/plat-omap/clock.c
3  *
4  *  Copyright (C) 2004 - 2005 Nokia corporation
5  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
6  *
7  *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 #include <linux/version.h>
14 #include <linux/config.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
20 #include <linux/err.h>
21 #include <linux/string.h>
22 #include <linux/clk.h>
23 #include <linux/mutex.h>
24 #include <linux/platform_device.h>
25
26 #include <asm/io.h>
27 #include <asm/semaphore.h>
28
29 #include <asm/arch/clock.h>
30
31 LIST_HEAD(clocks);
32 static DEFINE_MUTEX(clocks_mutex);
33 DEFINE_SPINLOCK(clockfw_lock);
34
35 static struct clk_functions *arch_clock;
36
37 /*-------------------------------------------------------------------------
38  * Standard clock functions defined in include/linux/clk.h
39  *-------------------------------------------------------------------------*/
40
41 /*
42  * Returns a clock. Note that we first try to use device id on the bus
43  * and clock name. If this fails, we try to use clock name only.
44  */
45 struct clk * clk_get(struct device *dev, const char *id)
46 {
47         struct clk *p, *clk = ERR_PTR(-ENOENT);
48         int idno;
49
50         if (dev == NULL || dev->bus != &platform_bus_type)
51                 idno = -1;
52         else
53                 idno = to_platform_device(dev)->id;
54
55         mutex_lock(&clocks_mutex);
56
57         list_for_each_entry(p, &clocks, node) {
58                 if (p->id == idno &&
59                     strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
60                         clk = p;
61                         goto found;
62                 }
63         }
64
65         list_for_each_entry(p, &clocks, node) {
66                 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
67                         clk = p;
68                         break;
69                 }
70         }
71
72 found:
73         mutex_unlock(&clocks_mutex);
74
75         return clk;
76 }
77 EXPORT_SYMBOL(clk_get);
78
79 int clk_enable(struct clk *clk)
80 {
81         unsigned long flags;
82         int ret = 0;
83
84         if (clk == NULL || IS_ERR(clk))
85                 return -EINVAL;
86
87         spin_lock_irqsave(&clockfw_lock, flags);
88         if (arch_clock->clk_enable)
89                 ret = arch_clock->clk_enable(clk);
90         spin_unlock_irqrestore(&clockfw_lock, flags);
91
92         return ret;
93 }
94 EXPORT_SYMBOL(clk_enable);
95
96 void clk_disable(struct clk *clk)
97 {
98         unsigned long flags;
99
100         if (clk == NULL || IS_ERR(clk))
101                 return;
102
103         spin_lock_irqsave(&clockfw_lock, flags);
104         if (arch_clock->clk_disable)
105                 arch_clock->clk_disable(clk);
106         spin_unlock_irqrestore(&clockfw_lock, flags);
107 }
108 EXPORT_SYMBOL(clk_disable);
109
110 int clk_get_usecount(struct clk *clk)
111 {
112         unsigned long flags;
113         int ret = 0;
114
115         if (clk == NULL || IS_ERR(clk))
116                 return 0;
117
118         spin_lock_irqsave(&clockfw_lock, flags);
119         ret = clk->usecount;
120         spin_unlock_irqrestore(&clockfw_lock, flags);
121
122         return ret;
123 }
124 EXPORT_SYMBOL(clk_get_usecount);
125
126 unsigned long clk_get_rate(struct clk *clk)
127 {
128         unsigned long flags;
129         unsigned long ret = 0;
130
131         if (clk == NULL || IS_ERR(clk))
132                 return 0;
133
134         spin_lock_irqsave(&clockfw_lock, flags);
135         ret = clk->rate;
136         spin_unlock_irqrestore(&clockfw_lock, flags);
137
138         return ret;
139 }
140 EXPORT_SYMBOL(clk_get_rate);
141
142 void clk_put(struct clk *clk)
143 {
144         if (clk && !IS_ERR(clk))
145                 module_put(clk->owner);
146 }
147 EXPORT_SYMBOL(clk_put);
148
149 /*-------------------------------------------------------------------------
150  * Optional clock functions defined in include/linux/clk.h
151  *-------------------------------------------------------------------------*/
152
153 long clk_round_rate(struct clk *clk, unsigned long rate)
154 {
155         unsigned long flags;
156         long ret = 0;
157
158         if (clk == NULL || IS_ERR(clk))
159                 return ret;
160
161         spin_lock_irqsave(&clockfw_lock, flags);
162         if (arch_clock->clk_round_rate)
163                 ret = arch_clock->clk_round_rate(clk, rate);
164         spin_unlock_irqrestore(&clockfw_lock, flags);
165
166         return ret;
167 }
168 EXPORT_SYMBOL(clk_round_rate);
169
170 int clk_set_rate(struct clk *clk, unsigned long rate)
171 {
172         unsigned long flags;
173         int ret = -EINVAL;
174
175         if (clk == NULL || IS_ERR(clk))
176                 return ret;
177
178         spin_lock_irqsave(&clockfw_lock, flags);
179         if (arch_clock->clk_set_rate)
180                 ret = arch_clock->clk_set_rate(clk, rate);
181         spin_unlock_irqrestore(&clockfw_lock, flags);
182
183         return ret;
184 }
185 EXPORT_SYMBOL(clk_set_rate);
186
187 int clk_set_parent(struct clk *clk, struct clk *parent)
188 {
189         unsigned long flags;
190         int ret = -EINVAL;
191
192         if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
193                 return ret;
194
195         spin_lock_irqsave(&clockfw_lock, flags);
196         if (arch_clock->clk_set_parent)
197                 ret =  arch_clock->clk_set_parent(clk, parent);
198         spin_unlock_irqrestore(&clockfw_lock, flags);
199
200         return ret;
201 }
202 EXPORT_SYMBOL(clk_set_parent);
203
204 struct clk *clk_get_parent(struct clk *clk)
205 {
206         unsigned long flags;
207         struct clk * ret = NULL;
208
209         if (clk == NULL || IS_ERR(clk))
210                 return ret;
211
212         spin_lock_irqsave(&clockfw_lock, flags);
213         if (arch_clock->clk_get_parent)
214                 ret = arch_clock->clk_get_parent(clk);
215         spin_unlock_irqrestore(&clockfw_lock, flags);
216
217         return ret;
218 }
219 EXPORT_SYMBOL(clk_get_parent);
220
221 /*-------------------------------------------------------------------------
222  * OMAP specific clock functions shared between omap1 and omap2
223  *-------------------------------------------------------------------------*/
224
225 unsigned int __initdata mpurate;
226
227 /*
228  * By default we use the rate set by the bootloader.
229  * You can override this with mpurate= cmdline option.
230  */
231 static int __init omap_clk_setup(char *str)
232 {
233         get_option(&str, &mpurate);
234
235         if (!mpurate)
236                 return 1;
237
238         if (mpurate < 1000)
239                 mpurate *= 1000000;
240
241         return 1;
242 }
243 __setup("mpurate=", omap_clk_setup);
244
245 /* Used for clocks that always have same value as the parent clock */
246 void followparent_recalc(struct clk *clk)
247 {
248         if (clk == NULL || IS_ERR(clk))
249                 return;
250
251         clk->rate = clk->parent->rate;
252 }
253
254 /* Propagate rate to children */
255 void propagate_rate(struct clk * tclk)
256 {
257         struct clk *clkp;
258
259         if (tclk == NULL || IS_ERR(tclk))
260                 return;
261
262         list_for_each_entry(clkp, &clocks, node) {
263                 if (likely(clkp->parent != tclk))
264                         continue;
265                 if (likely((u32)clkp->recalc))
266                         clkp->recalc(clkp);
267         }
268 }
269
270 int clk_register(struct clk *clk)
271 {
272         if (clk == NULL || IS_ERR(clk))
273                 return -EINVAL;
274
275         mutex_lock(&clocks_mutex);
276         list_add(&clk->node, &clocks);
277         if (clk->init)
278                 clk->init(clk);
279         mutex_unlock(&clocks_mutex);
280
281         return 0;
282 }
283 EXPORT_SYMBOL(clk_register);
284
285 void clk_unregister(struct clk *clk)
286 {
287         if (clk == NULL || IS_ERR(clk))
288                 return;
289
290         mutex_lock(&clocks_mutex);
291         list_del(&clk->node);
292         mutex_unlock(&clocks_mutex);
293 }
294 EXPORT_SYMBOL(clk_unregister);
295
296 void clk_deny_idle(struct clk *clk)
297 {
298         unsigned long flags;
299
300         if (clk == NULL || IS_ERR(clk))
301                 return;
302
303         spin_lock_irqsave(&clockfw_lock, flags);
304         if (arch_clock->clk_deny_idle)
305                 arch_clock->clk_deny_idle(clk);
306         spin_unlock_irqrestore(&clockfw_lock, flags);
307 }
308 EXPORT_SYMBOL(clk_deny_idle);
309
310 void clk_allow_idle(struct clk *clk)
311 {
312         unsigned long flags;
313
314         if (clk == NULL || IS_ERR(clk))
315                 return;
316
317         spin_lock_irqsave(&clockfw_lock, flags);
318         if (arch_clock->clk_allow_idle)
319                 arch_clock->clk_allow_idle(clk);
320         spin_unlock_irqrestore(&clockfw_lock, flags);
321 }
322 EXPORT_SYMBOL(clk_allow_idle);
323
324 /*-------------------------------------------------------------------------*/
325
326 int __init clk_init(struct clk_functions * custom_clocks)
327 {
328         if (!custom_clocks) {
329                 printk(KERN_ERR "No custom clock functions registered\n");
330                 BUG();
331         }
332
333         arch_clock = custom_clocks;
334
335         return 0;
336 }