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