1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/clk.h>
28#include <linux/err.h>
29#include <linux/errno.h>
30#include <linux/init.h>
31#include <linux/io.h>
32#include <linux/kernel.h>
33#include <linux/list.h>
34#include <linux/module.h>
35#include <linux/mutex.h>
36#include <linux/platform_device.h>
37#include <linux/proc_fs.h>
38#include <linux/semaphore.h>
39#include <linux/string.h>
40
41#include <mach/clock.h>
42#include <mach/hardware.h>
43
44static LIST_HEAD(clocks);
45static DEFINE_MUTEX(clocks_mutex);
46
47
48
49
50
51static void __clk_disable(struct clk *clk)
52{
53 if (clk == NULL || IS_ERR(clk))
54 return;
55
56 __clk_disable(clk->parent);
57 __clk_disable(clk->secondary);
58
59 if (!(--clk->usecount) && clk->disable)
60 clk->disable(clk);
61}
62
63static int __clk_enable(struct clk *clk)
64{
65 if (clk == NULL || IS_ERR(clk))
66 return -EINVAL;
67
68 __clk_enable(clk->parent);
69 __clk_enable(clk->secondary);
70
71 if (clk->usecount++ == 0 && clk->enable)
72 clk->enable(clk);
73
74 return 0;
75}
76
77
78
79
80int clk_enable(struct clk *clk)
81{
82 int ret = 0;
83
84 if (clk == NULL || IS_ERR(clk))
85 return -EINVAL;
86
87 mutex_lock(&clocks_mutex);
88 ret = __clk_enable(clk);
89 mutex_unlock(&clocks_mutex);
90
91 return ret;
92}
93EXPORT_SYMBOL(clk_enable);
94
95
96
97
98
99void clk_disable(struct clk *clk)
100{
101 if (clk == NULL || IS_ERR(clk))
102 return;
103
104 mutex_lock(&clocks_mutex);
105 __clk_disable(clk);
106 mutex_unlock(&clocks_mutex);
107}
108EXPORT_SYMBOL(clk_disable);
109
110
111
112
113
114
115unsigned long clk_get_rate(struct clk *clk)
116{
117 if (clk == NULL || IS_ERR(clk))
118 return 0UL;
119
120 if (clk->get_rate)
121 return clk->get_rate(clk);
122
123 return clk_get_rate(clk->parent);
124}
125EXPORT_SYMBOL(clk_get_rate);
126
127
128
129
130
131long clk_round_rate(struct clk *clk, unsigned long rate)
132{
133 if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
134 return 0;
135
136 return clk->round_rate(clk, rate);
137}
138EXPORT_SYMBOL(clk_round_rate);
139
140
141
142
143int clk_set_rate(struct clk *clk, unsigned long rate)
144{
145 int ret = -EINVAL;
146
147 if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
148 return ret;
149
150 mutex_lock(&clocks_mutex);
151 ret = clk->set_rate(clk, rate);
152 mutex_unlock(&clocks_mutex);
153
154 return ret;
155}
156EXPORT_SYMBOL(clk_set_rate);
157
158
159int clk_set_parent(struct clk *clk, struct clk *parent)
160{
161 int ret = -EINVAL;
162
163 if (clk == NULL || IS_ERR(clk) || parent == NULL ||
164 IS_ERR(parent) || clk->set_parent == NULL)
165 return ret;
166
167 mutex_lock(&clocks_mutex);
168 ret = clk->set_parent(clk, parent);
169 if (ret == 0)
170 clk->parent = parent;
171 mutex_unlock(&clocks_mutex);
172
173 return ret;
174}
175EXPORT_SYMBOL(clk_set_parent);
176
177
178struct clk *clk_get_parent(struct clk *clk)
179{
180 struct clk *ret = NULL;
181
182 if (clk == NULL || IS_ERR(clk))
183 return ret;
184
185 return clk->parent;
186}
187EXPORT_SYMBOL(clk_get_parent);
188
189
190
191
192
193
194
195
196
197
198unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq)
199{
200 long long ll;
201 int mfn_abs;
202 unsigned int mfi, mfn, mfd, pd;
203
204 mfi = (reg_val >> 10) & 0xf;
205 mfn = reg_val & 0x3ff;
206 mfd = (reg_val >> 16) & 0x3ff;
207 pd = (reg_val >> 26) & 0xf;
208
209 mfi = mfi <= 5 ? 5 : mfi;
210
211 mfn_abs = mfn;
212
213
214
215
216 if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
217 mfn_abs = 0x400 - mfn;
218
219 freq *= 2;
220 freq /= pd + 1;
221
222 ll = (unsigned long long)freq * mfn_abs;
223
224 do_div(ll, mfd + 1);
225
226 if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
227 ll = -ll;
228
229 ll = (freq * mfi) + ll;
230
231 return ll;
232}
233