diff options
Diffstat (limited to 'arch/arm/plat-mxc/clock.c')
-rw-r--r-- | arch/arm/plat-mxc/clock.c | 170 |
1 files changed, 9 insertions, 161 deletions
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c index 92e13566cd4f..9e8fbd57495c 100644 --- a/arch/arm/plat-mxc/clock.c +++ b/arch/arm/plat-mxc/clock.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/string.h> | 39 | #include <linux/string.h> |
40 | 40 | ||
41 | #include <mach/clock.h> | 41 | #include <mach/clock.h> |
42 | #include <mach/hardware.h> | ||
42 | 43 | ||
43 | static LIST_HEAD(clocks); | 44 | static LIST_HEAD(clocks); |
44 | static DEFINE_MUTEX(clocks_mutex); | 45 | static DEFINE_MUTEX(clocks_mutex); |
@@ -47,76 +48,6 @@ static DEFINE_MUTEX(clocks_mutex); | |||
47 | * Standard clock functions defined in include/linux/clk.h | 48 | * Standard clock functions defined in include/linux/clk.h |
48 | *-------------------------------------------------------------------------*/ | 49 | *-------------------------------------------------------------------------*/ |
49 | 50 | ||
50 | /* | ||
51 | * All the code inside #ifndef CONFIG_COMMON_CLKDEV can be removed once all | ||
52 | * MXC architectures have switched to using clkdev. | ||
53 | */ | ||
54 | #ifndef CONFIG_COMMON_CLKDEV | ||
55 | /* | ||
56 | * Retrieve a clock by name. | ||
57 | * | ||
58 | * Note that we first try to use device id on the bus | ||
59 | * and clock name. If this fails, we try to use "<name>.<id>". If this fails, | ||
60 | * we try to use clock name only. | ||
61 | * The reference count to the clock's module owner ref count is incremented. | ||
62 | */ | ||
63 | struct clk *clk_get(struct device *dev, const char *id) | ||
64 | { | ||
65 | struct clk *p, *clk = ERR_PTR(-ENOENT); | ||
66 | int idno; | ||
67 | const char *str; | ||
68 | |||
69 | if (id == NULL) | ||
70 | return clk; | ||
71 | |||
72 | if (dev == NULL || dev->bus != &platform_bus_type) | ||
73 | idno = -1; | ||
74 | else | ||
75 | idno = to_platform_device(dev)->id; | ||
76 | |||
77 | mutex_lock(&clocks_mutex); | ||
78 | |||
79 | list_for_each_entry(p, &clocks, node) { | ||
80 | if (p->id == idno && | ||
81 | strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
82 | clk = p; | ||
83 | goto found; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | str = strrchr(id, '.'); | ||
88 | if (str) { | ||
89 | int cnt = str - id; | ||
90 | str++; | ||
91 | idno = simple_strtol(str, NULL, 10); | ||
92 | list_for_each_entry(p, &clocks, node) { | ||
93 | if (p->id == idno && | ||
94 | strlen(p->name) == cnt && | ||
95 | strncmp(id, p->name, cnt) == 0 && | ||
96 | try_module_get(p->owner)) { | ||
97 | clk = p; | ||
98 | goto found; | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | list_for_each_entry(p, &clocks, node) { | ||
104 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
105 | clk = p; | ||
106 | goto found; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | printk(KERN_WARNING "clk: Unable to get requested clock: %s\n", id); | ||
111 | |||
112 | found: | ||
113 | mutex_unlock(&clocks_mutex); | ||
114 | |||
115 | return clk; | ||
116 | } | ||
117 | EXPORT_SYMBOL(clk_get); | ||
118 | #endif | ||
119 | |||
120 | static void __clk_disable(struct clk *clk) | 51 | static void __clk_disable(struct clk *clk) |
121 | { | 52 | { |
122 | if (clk == NULL || IS_ERR(clk)) | 53 | if (clk == NULL || IS_ERR(clk)) |
@@ -193,16 +124,6 @@ unsigned long clk_get_rate(struct clk *clk) | |||
193 | } | 124 | } |
194 | EXPORT_SYMBOL(clk_get_rate); | 125 | EXPORT_SYMBOL(clk_get_rate); |
195 | 126 | ||
196 | #ifndef CONFIG_COMMON_CLKDEV | ||
197 | /* Decrement the clock's module reference count */ | ||
198 | void clk_put(struct clk *clk) | ||
199 | { | ||
200 | if (clk && !IS_ERR(clk)) | ||
201 | module_put(clk->owner); | ||
202 | } | ||
203 | EXPORT_SYMBOL(clk_put); | ||
204 | #endif | ||
205 | |||
206 | /* Round the requested clock rate to the nearest supported | 127 | /* Round the requested clock rate to the nearest supported |
207 | * rate that is less than or equal to the requested rate. | 128 | * rate that is less than or equal to the requested rate. |
208 | * This is dependent on the clock's current parent. | 129 | * This is dependent on the clock's current parent. |
@@ -265,80 +186,6 @@ struct clk *clk_get_parent(struct clk *clk) | |||
265 | } | 186 | } |
266 | EXPORT_SYMBOL(clk_get_parent); | 187 | EXPORT_SYMBOL(clk_get_parent); |
267 | 188 | ||
268 | #ifndef CONFIG_COMMON_CLKDEV | ||
269 | /* | ||
270 | * Add a new clock to the clock tree. | ||
271 | */ | ||
272 | int clk_register(struct clk *clk) | ||
273 | { | ||
274 | if (clk == NULL || IS_ERR(clk)) | ||
275 | return -EINVAL; | ||
276 | |||
277 | mutex_lock(&clocks_mutex); | ||
278 | list_add(&clk->node, &clocks); | ||
279 | mutex_unlock(&clocks_mutex); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | EXPORT_SYMBOL(clk_register); | ||
284 | |||
285 | /* Remove a clock from the clock tree */ | ||
286 | void clk_unregister(struct clk *clk) | ||
287 | { | ||
288 | if (clk == NULL || IS_ERR(clk)) | ||
289 | return; | ||
290 | |||
291 | mutex_lock(&clocks_mutex); | ||
292 | list_del(&clk->node); | ||
293 | mutex_unlock(&clocks_mutex); | ||
294 | } | ||
295 | EXPORT_SYMBOL(clk_unregister); | ||
296 | |||
297 | #ifdef CONFIG_PROC_FS | ||
298 | static int mxc_clock_read_proc(char *page, char **start, off_t off, | ||
299 | int count, int *eof, void *data) | ||
300 | { | ||
301 | struct clk *clkp; | ||
302 | char *p = page; | ||
303 | int len; | ||
304 | |||
305 | list_for_each_entry(clkp, &clocks, node) { | ||
306 | p += sprintf(p, "%s-%d:\t\t%lu, %d", clkp->name, clkp->id, | ||
307 | clk_get_rate(clkp), clkp->usecount); | ||
308 | if (clkp->parent) | ||
309 | p += sprintf(p, ", %s-%d\n", clkp->parent->name, | ||
310 | clkp->parent->id); | ||
311 | else | ||
312 | p += sprintf(p, "\n"); | ||
313 | } | ||
314 | |||
315 | len = (p - page) - off; | ||
316 | if (len < 0) | ||
317 | len = 0; | ||
318 | |||
319 | *eof = (len <= count) ? 1 : 0; | ||
320 | *start = page + off; | ||
321 | |||
322 | return len; | ||
323 | } | ||
324 | |||
325 | static int __init mxc_setup_proc_entry(void) | ||
326 | { | ||
327 | struct proc_dir_entry *res; | ||
328 | |||
329 | res = create_proc_read_entry("cpu/clocks", 0, NULL, | ||
330 | mxc_clock_read_proc, NULL); | ||
331 | if (!res) { | ||
332 | printk(KERN_ERR "Failed to create proc/cpu/clocks\n"); | ||
333 | return -ENOMEM; | ||
334 | } | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | late_initcall(mxc_setup_proc_entry); | ||
339 | #endif /* CONFIG_PROC_FS */ | ||
340 | #endif | ||
341 | |||
342 | /* | 189 | /* |
343 | * Get the resulting clock rate from a PLL register value and the input | 190 | * Get the resulting clock rate from a PLL register value and the input |
344 | * frequency. PLLs with this register layout can at least be found on | 191 | * frequency. PLLs with this register layout can at least be found on |
@@ -363,12 +210,11 @@ unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq) | |||
363 | 210 | ||
364 | mfn_abs = mfn; | 211 | mfn_abs = mfn; |
365 | 212 | ||
366 | #if !defined CONFIG_ARCH_MX1 && !defined CONFIG_ARCH_MX21 | 213 | /* On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit |
367 | if (mfn >= 0x200) { | 214 | * 2's complements number |
368 | mfn |= 0xFFFFFE00; | 215 | */ |
369 | mfn_abs = -mfn; | 216 | if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200) |
370 | } | 217 | mfn_abs = 0x400 - mfn; |
371 | #endif | ||
372 | 218 | ||
373 | freq *= 2; | 219 | freq *= 2; |
374 | freq /= pd + 1; | 220 | freq /= pd + 1; |
@@ -376,8 +222,10 @@ unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq) | |||
376 | ll = (unsigned long long)freq * mfn_abs; | 222 | ll = (unsigned long long)freq * mfn_abs; |
377 | 223 | ||
378 | do_div(ll, mfd + 1); | 224 | do_div(ll, mfd + 1); |
379 | if (mfn < 0) | 225 | |
226 | if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200) | ||
380 | ll = -ll; | 227 | ll = -ll; |
228 | |||
381 | ll = (freq * mfi) + ll; | 229 | ll = (freq * mfi) + ll; |
382 | 230 | ||
383 | return ll; | 231 | return ll; |