[ARM] 5039/1: S3C244X: Rename SDI device if running on S3C244X.
[deliverable/linux.git] / arch / arm / plat-omap / clock.c
CommitLineData
1da177e4 1/*
b9158556 2 * linux/arch/arm/plat-omap/clock.c
1da177e4 3 *
1a8bfa1e 4 * Copyright (C) 2004 - 2005 Nokia corporation
1da177e4
LT
5 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
6 *
1a8bfa1e
TL
7 * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
8 *
1da177e4
LT
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 */
1a8bfa1e 13#include <linux/version.h>
1da177e4 14#include <linux/kernel.h>
1a8bfa1e
TL
15#include <linux/init.h>
16#include <linux/module.h>
1da177e4
LT
17#include <linux/list.h>
18#include <linux/errno.h>
19#include <linux/err.h>
4e57b681 20#include <linux/string.h>
f8ce2547 21#include <linux/clk.h>
00431707 22#include <linux/mutex.h>
b824efae 23#include <linux/platform_device.h>
1da177e4 24
bb13b5fd 25#include <asm/io.h>
1da177e4 26
1a8bfa1e 27#include <asm/arch/clock.h>
1da177e4 28
7df3450e 29static LIST_HEAD(clocks);
00431707 30static DEFINE_MUTEX(clocks_mutex);
7df3450e 31static DEFINE_SPINLOCK(clockfw_lock);
1da177e4 32
1a8bfa1e 33static struct clk_functions *arch_clock;
1da177e4 34
0ce33563
JY
35#ifdef CONFIG_PM_DEBUG
36
37static void print_parents(struct clk *clk)
38{
39 struct clk *p;
40 int printed = 0;
41
42 list_for_each_entry(p, &clocks, node) {
43 if (p->parent == clk && p->usecount) {
44 if (!clk->usecount && !printed) {
45 printk("MISMATCH: %s\n", clk->name);
46 printed = 1;
47 }
48 printk("\t%-15s\n", p->name);
49 }
50 }
51}
52
53void clk_print_usecounts(void)
54{
55 unsigned long flags;
56 struct clk *p;
57
58 spin_lock_irqsave(&clockfw_lock, flags);
59 list_for_each_entry(p, &clocks, node) {
60 if (p->usecount)
61 printk("%-15s: %d\n", p->name, p->usecount);
62 print_parents(p);
63
64 }
65 spin_unlock_irqrestore(&clockfw_lock, flags);
66}
67
68#endif
69
1a8bfa1e 70/*-------------------------------------------------------------------------
f07adc59 71 * Standard clock functions defined in include/linux/clk.h
1a8bfa1e 72 *-------------------------------------------------------------------------*/
1da177e4 73
b824efae
TL
74/*
75 * Returns a clock. Note that we first try to use device id on the bus
76 * and clock name. If this fails, we try to use clock name only.
77 */
1a8bfa1e 78struct clk * clk_get(struct device *dev, const char *id)
1da177e4
LT
79{
80 struct clk *p, *clk = ERR_PTR(-ENOENT);
b824efae
TL
81 int idno;
82
83 if (dev == NULL || dev->bus != &platform_bus_type)
84 idno = -1;
85 else
86 idno = to_platform_device(dev)->id;
1da177e4 87
00431707 88 mutex_lock(&clocks_mutex);
b824efae
TL
89
90 list_for_each_entry(p, &clocks, node) {
91 if (p->id == idno &&
92 strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
93 clk = p;
67d4d835 94 goto found;
b824efae
TL
95 }
96 }
97
1da177e4
LT
98 list_for_each_entry(p, &clocks, node) {
99 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
100 clk = p;
101 break;
102 }
103 }
b824efae 104
67d4d835 105found:
00431707 106 mutex_unlock(&clocks_mutex);
1da177e4
LT
107
108 return clk;
109}
110EXPORT_SYMBOL(clk_get);
111
1da177e4
LT
112int clk_enable(struct clk *clk)
113{
114 unsigned long flags;
1a8bfa1e 115 int ret = 0;
1da177e4 116
b824efae
TL
117 if (clk == NULL || IS_ERR(clk))
118 return -EINVAL;
119
1da177e4 120 spin_lock_irqsave(&clockfw_lock, flags);
f07adc59 121 if (arch_clock->clk_enable)
1a8bfa1e 122 ret = arch_clock->clk_enable(clk);
1da177e4 123 spin_unlock_irqrestore(&clockfw_lock, flags);
1a8bfa1e 124
1da177e4
LT
125 return ret;
126}
127EXPORT_SYMBOL(clk_enable);
128
1da177e4
LT
129void clk_disable(struct clk *clk)
130{
131 unsigned long flags;
132
b824efae
TL
133 if (clk == NULL || IS_ERR(clk))
134 return;
135
1da177e4 136 spin_lock_irqsave(&clockfw_lock, flags);
7cf95774
TL
137 if (clk->usecount == 0) {
138 printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
139 clk->name);
140 WARN_ON(1);
141 goto out;
142 }
143
f07adc59 144 if (arch_clock->clk_disable)
1a8bfa1e 145 arch_clock->clk_disable(clk);
7cf95774
TL
146
147out:
1da177e4
LT
148 spin_unlock_irqrestore(&clockfw_lock, flags);
149}
150EXPORT_SYMBOL(clk_disable);
151
1da177e4
LT
152int clk_get_usecount(struct clk *clk)
153{
1a8bfa1e
TL
154 unsigned long flags;
155 int ret = 0;
1da177e4 156
b824efae
TL
157 if (clk == NULL || IS_ERR(clk))
158 return 0;
159
1a8bfa1e
TL
160 spin_lock_irqsave(&clockfw_lock, flags);
161 ret = clk->usecount;
162 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4 163
1a8bfa1e 164 return ret;
1da177e4 165}
1a8bfa1e 166EXPORT_SYMBOL(clk_get_usecount);
1da177e4 167
1a8bfa1e 168unsigned long clk_get_rate(struct clk *clk)
1da177e4 169{
1a8bfa1e
TL
170 unsigned long flags;
171 unsigned long ret = 0;
1da177e4 172
b824efae
TL
173 if (clk == NULL || IS_ERR(clk))
174 return 0;
175
1a8bfa1e
TL
176 spin_lock_irqsave(&clockfw_lock, flags);
177 ret = clk->rate;
178 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4 179
1a8bfa1e 180 return ret;
1da177e4 181}
1a8bfa1e 182EXPORT_SYMBOL(clk_get_rate);
1da177e4 183
1a8bfa1e 184void clk_put(struct clk *clk)
bb13b5fd 185{
1a8bfa1e
TL
186 if (clk && !IS_ERR(clk))
187 module_put(clk->owner);
bb13b5fd 188}
1a8bfa1e 189EXPORT_SYMBOL(clk_put);
bb13b5fd 190
1a8bfa1e 191/*-------------------------------------------------------------------------
f07adc59 192 * Optional clock functions defined in include/linux/clk.h
1a8bfa1e 193 *-------------------------------------------------------------------------*/
bb13b5fd 194
1da177e4
LT
195long clk_round_rate(struct clk *clk, unsigned long rate)
196{
1a8bfa1e
TL
197 unsigned long flags;
198 long ret = 0;
1da177e4 199
b824efae
TL
200 if (clk == NULL || IS_ERR(clk))
201 return ret;
202
1a8bfa1e
TL
203 spin_lock_irqsave(&clockfw_lock, flags);
204 if (arch_clock->clk_round_rate)
205 ret = arch_clock->clk_round_rate(clk, rate);
206 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4 207
1a8bfa1e 208 return ret;
1da177e4
LT
209}
210EXPORT_SYMBOL(clk_round_rate);
211
1a8bfa1e 212int clk_set_rate(struct clk *clk, unsigned long rate)
1da177e4 213{
1a8bfa1e 214 unsigned long flags;
b824efae
TL
215 int ret = -EINVAL;
216
217 if (clk == NULL || IS_ERR(clk))
218 return ret;
bb13b5fd 219
1a8bfa1e
TL
220 spin_lock_irqsave(&clockfw_lock, flags);
221 if (arch_clock->clk_set_rate)
222 ret = arch_clock->clk_set_rate(clk, rate);
223 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4 224
1a8bfa1e 225 return ret;
1da177e4 226}
1a8bfa1e 227EXPORT_SYMBOL(clk_set_rate);
1da177e4 228
1a8bfa1e 229int clk_set_parent(struct clk *clk, struct clk *parent)
1da177e4 230{
1a8bfa1e 231 unsigned long flags;
b824efae
TL
232 int ret = -EINVAL;
233
234 if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
235 return ret;
1da177e4 236
1a8bfa1e
TL
237 spin_lock_irqsave(&clockfw_lock, flags);
238 if (arch_clock->clk_set_parent)
239 ret = arch_clock->clk_set_parent(clk, parent);
240 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4 241
1a8bfa1e 242 return ret;
1da177e4 243}
1a8bfa1e 244EXPORT_SYMBOL(clk_set_parent);
1da177e4 245
1a8bfa1e 246struct clk *clk_get_parent(struct clk *clk)
1da177e4 247{
1a8bfa1e
TL
248 unsigned long flags;
249 struct clk * ret = NULL;
1da177e4 250
b824efae
TL
251 if (clk == NULL || IS_ERR(clk))
252 return ret;
253
1a8bfa1e
TL
254 spin_lock_irqsave(&clockfw_lock, flags);
255 if (arch_clock->clk_get_parent)
256 ret = arch_clock->clk_get_parent(clk);
257 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4
LT
258
259 return ret;
260}
1a8bfa1e 261EXPORT_SYMBOL(clk_get_parent);
1da177e4 262
1a8bfa1e
TL
263/*-------------------------------------------------------------------------
264 * OMAP specific clock functions shared between omap1 and omap2
265 *-------------------------------------------------------------------------*/
1da177e4 266
1a8bfa1e 267unsigned int __initdata mpurate;
1da177e4 268
1a8bfa1e
TL
269/*
270 * By default we use the rate set by the bootloader.
271 * You can override this with mpurate= cmdline option.
272 */
273static int __init omap_clk_setup(char *str)
1da177e4 274{
1a8bfa1e 275 get_option(&str, &mpurate);
1da177e4 276
1a8bfa1e
TL
277 if (!mpurate)
278 return 1;
1da177e4 279
1a8bfa1e
TL
280 if (mpurate < 1000)
281 mpurate *= 1000000;
1da177e4 282
1a8bfa1e 283 return 1;
1da177e4 284}
1a8bfa1e 285__setup("mpurate=", omap_clk_setup);
1da177e4 286
1a8bfa1e
TL
287/* Used for clocks that always have same value as the parent clock */
288void followparent_recalc(struct clk *clk)
1da177e4 289{
b824efae
TL
290 if (clk == NULL || IS_ERR(clk))
291 return;
292
1a8bfa1e 293 clk->rate = clk->parent->rate;
b1465bf7
ID
294 if (unlikely(clk->flags & RATE_PROPAGATES))
295 propagate_rate(clk);
1da177e4
LT
296}
297
1a8bfa1e
TL
298/* Propagate rate to children */
299void propagate_rate(struct clk * tclk)
1da177e4 300{
1a8bfa1e 301 struct clk *clkp;
1da177e4 302
b824efae
TL
303 if (tclk == NULL || IS_ERR(tclk))
304 return;
305
1a8bfa1e
TL
306 list_for_each_entry(clkp, &clocks, node) {
307 if (likely(clkp->parent != tclk))
308 continue;
309 if (likely((u32)clkp->recalc))
310 clkp->recalc(clkp);
311 }
1da177e4
LT
312}
313
6b8858a9
PW
314/**
315 * recalculate_root_clocks - recalculate and propagate all root clocks
316 *
317 * Recalculates all root clocks (clocks with no parent), which if the
318 * clock's .recalc is set correctly, should also propagate their rates.
319 * Called at init.
320 */
321void recalculate_root_clocks(void)
322{
323 struct clk *clkp;
324
325 list_for_each_entry(clkp, &clocks, node) {
326 if (unlikely(!clkp->parent) && likely((u32)clkp->recalc))
327 clkp->recalc(clkp);
328 }
329}
330
1da177e4
LT
331int clk_register(struct clk *clk)
332{
b824efae
TL
333 if (clk == NULL || IS_ERR(clk))
334 return -EINVAL;
335
00431707 336 mutex_lock(&clocks_mutex);
1da177e4
LT
337 list_add(&clk->node, &clocks);
338 if (clk->init)
339 clk->init(clk);
00431707 340 mutex_unlock(&clocks_mutex);
1a8bfa1e 341
1da177e4
LT
342 return 0;
343}
344EXPORT_SYMBOL(clk_register);
345
346void clk_unregister(struct clk *clk)
347{
b824efae
TL
348 if (clk == NULL || IS_ERR(clk))
349 return;
350
00431707 351 mutex_lock(&clocks_mutex);
1da177e4 352 list_del(&clk->node);
00431707 353 mutex_unlock(&clocks_mutex);
1da177e4
LT
354}
355EXPORT_SYMBOL(clk_unregister);
356
1a8bfa1e 357void clk_deny_idle(struct clk *clk)
bb13b5fd 358{
1a8bfa1e
TL
359 unsigned long flags;
360
b824efae
TL
361 if (clk == NULL || IS_ERR(clk))
362 return;
363
1a8bfa1e
TL
364 spin_lock_irqsave(&clockfw_lock, flags);
365 if (arch_clock->clk_deny_idle)
366 arch_clock->clk_deny_idle(clk);
367 spin_unlock_irqrestore(&clockfw_lock, flags);
bb13b5fd 368}
1a8bfa1e 369EXPORT_SYMBOL(clk_deny_idle);
1da177e4 370
1a8bfa1e 371void clk_allow_idle(struct clk *clk)
1da177e4 372{
1a8bfa1e 373 unsigned long flags;
1da177e4 374
b824efae
TL
375 if (clk == NULL || IS_ERR(clk))
376 return;
377
1a8bfa1e
TL
378 spin_lock_irqsave(&clockfw_lock, flags);
379 if (arch_clock->clk_allow_idle)
380 arch_clock->clk_allow_idle(clk);
381 spin_unlock_irqrestore(&clockfw_lock, flags);
1da177e4 382}
1a8bfa1e 383EXPORT_SYMBOL(clk_allow_idle);
bb13b5fd 384
6b8858a9
PW
385void clk_enable_init_clocks(void)
386{
387 struct clk *clkp;
388
389 list_for_each_entry(clkp, &clocks, node) {
390 if (clkp->flags & ENABLE_ON_INIT)
391 clk_enable(clkp);
392 }
393}
394EXPORT_SYMBOL(clk_enable_init_clocks);
395
396#ifdef CONFIG_CPU_FREQ
397void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
398{
399 unsigned long flags;
400
401 spin_lock_irqsave(&clockfw_lock, flags);
402 if (arch_clock->clk_init_cpufreq_table)
403 arch_clock->clk_init_cpufreq_table(table);
404 spin_unlock_irqrestore(&clockfw_lock, flags);
405}
406EXPORT_SYMBOL(clk_init_cpufreq_table);
407#endif
408
1a8bfa1e 409/*-------------------------------------------------------------------------*/
bb13b5fd 410
90afd5cb
TL
411#ifdef CONFIG_OMAP_RESET_CLOCKS
412/*
413 * Disable any unused clocks left on by the bootloader
414 */
415static int __init clk_disable_unused(void)
416{
417 struct clk *ck;
418 unsigned long flags;
419
420 list_for_each_entry(ck, &clocks, node) {
421 if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
422 ck->enable_reg == 0)
423 continue;
424
425 spin_lock_irqsave(&clockfw_lock, flags);
426 if (arch_clock->clk_disable_unused)
427 arch_clock->clk_disable_unused(ck);
428 spin_unlock_irqrestore(&clockfw_lock, flags);
429 }
430
431 return 0;
432}
433late_initcall(clk_disable_unused);
434#endif
435
1a8bfa1e 436int __init clk_init(struct clk_functions * custom_clocks)
bb13b5fd 437{
1a8bfa1e
TL
438 if (!custom_clocks) {
439 printk(KERN_ERR "No custom clock functions registered\n");
440 BUG();
bb13b5fd
TL
441 }
442
1a8bfa1e
TL
443 arch_clock = custom_clocks;
444
bb13b5fd
TL
445 return 0;
446}
6b8858a9 447
This page took 0.358378 seconds and 5 git commands to generate.