Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / arch / arm / mach-integrator / clock.c
1 /*
2  *  linux/arch/arm/mach-integrator/clock.c
3  *
4  *  Copyright (C) 2004 ARM Limited.
5  *  Written by Deep Blue Solutions Limited.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/list.h>
14 #include <linux/errno.h>
15 #include <linux/err.h>
16 #include <linux/string.h>
17 #include <linux/clk.h>
18 #include <linux/mutex.h>
19
20 #include <asm/hardware/icst525.h>
21
22 #include "clock.h"
23
24 static LIST_HEAD(clocks);
25 static DEFINE_MUTEX(clocks_mutex);
26
27 struct clk *clk_get(struct device *dev, const char *id)
28 {
29         struct clk *p, *clk = ERR_PTR(-ENOENT);
30
31         mutex_lock(&clocks_mutex);
32         list_for_each_entry(p, &clocks, node) {
33                 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
34                         clk = p;
35                         break;
36                 }
37         }
38         mutex_unlock(&clocks_mutex);
39
40         return clk;
41 }
42 EXPORT_SYMBOL(clk_get);
43
44 void clk_put(struct clk *clk)
45 {
46         module_put(clk->owner);
47 }
48 EXPORT_SYMBOL(clk_put);
49
50 int clk_enable(struct clk *clk)
51 {
52         return 0;
53 }
54 EXPORT_SYMBOL(clk_enable);
55
56 void clk_disable(struct clk *clk)
57 {
58 }
59 EXPORT_SYMBOL(clk_disable);
60
61 unsigned long clk_get_rate(struct clk *clk)
62 {
63         return clk->rate;
64 }
65 EXPORT_SYMBOL(clk_get_rate);
66
67 long clk_round_rate(struct clk *clk, unsigned long rate)
68 {
69         struct icst525_vco vco;
70
71         vco = icst525_khz_to_vco(clk->params, rate / 1000);
72         return icst525_khz(clk->params, vco) * 1000;
73 }
74 EXPORT_SYMBOL(clk_round_rate);
75
76 int clk_set_rate(struct clk *clk, unsigned long rate)
77 {
78         int ret = -EIO;
79         if (clk->setvco) {
80                 struct icst525_vco vco;
81
82                 vco = icst525_khz_to_vco(clk->params, rate / 1000);
83                 clk->rate = icst525_khz(clk->params, vco) * 1000;
84
85                 printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
86                         clk->name, vco.s, vco.r, vco.v);
87
88                 clk->setvco(clk, vco);
89                 ret = 0;
90         }
91         return 0;
92 }
93 EXPORT_SYMBOL(clk_set_rate);
94
95 /*
96  * These are fixed clocks.
97  */
98 static struct clk kmi_clk = {
99         .name   = "KMIREFCLK",
100         .rate   = 24000000,
101 };
102
103 static struct clk uart_clk = {
104         .name   = "UARTCLK",
105         .rate   = 14745600,
106 };
107
108 int clk_register(struct clk *clk)
109 {
110         mutex_lock(&clocks_mutex);
111         list_add(&clk->node, &clocks);
112         mutex_unlock(&clocks_mutex);
113         return 0;
114 }
115 EXPORT_SYMBOL(clk_register);
116
117 void clk_unregister(struct clk *clk)
118 {
119         mutex_lock(&clocks_mutex);
120         list_del(&clk->node);
121         mutex_unlock(&clocks_mutex);
122 }
123 EXPORT_SYMBOL(clk_unregister);
124
125 static int __init clk_init(void)
126 {
127         clk_register(&kmi_clk);
128         clk_register(&uart_clk);
129         return 0;
130 }
131 arch_initcall(clk_init);