2 * Based on arch/arm/plat-omap/clock.c
4 * Copyright (C) 2004 - 2005 Nokia corporation
5 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
6 * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
7 * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
8 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 #include <linux/clk.h>
28 #include <linux/err.h>
29 #include <linux/errno.h>
30 #include <linux/init.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>
41 #include <mach/clock.h>
42 #include <mach/hardware.h>
44 static LIST_HEAD(clocks
);
45 static DEFINE_MUTEX(clocks_mutex
);
47 /*-------------------------------------------------------------------------
48 * Standard clock functions defined in include/linux/clk.h
49 *-------------------------------------------------------------------------*/
52 * All the code inside #ifndef CONFIG_COMMON_CLKDEV can be removed once all
53 * MXC architectures have switched to using clkdev.
55 #ifndef CONFIG_COMMON_CLKDEV
57 * Retrieve a clock by name.
59 * Note that we first try to use device id on the bus
60 * and clock name. If this fails, we try to use "<name>.<id>". If this fails,
61 * we try to use clock name only.
62 * The reference count to the clock's module owner ref count is incremented.
64 struct clk
*clk_get(struct device
*dev
, const char *id
)
66 struct clk
*p
, *clk
= ERR_PTR(-ENOENT
);
73 if (dev
== NULL
|| dev
->bus
!= &platform_bus_type
)
76 idno
= to_platform_device(dev
)->id
;
78 mutex_lock(&clocks_mutex
);
80 list_for_each_entry(p
, &clocks
, node
) {
82 strcmp(id
, p
->name
) == 0 && try_module_get(p
->owner
)) {
88 str
= strrchr(id
, '.');
92 idno
= simple_strtol(str
, NULL
, 10);
93 list_for_each_entry(p
, &clocks
, node
) {
95 strlen(p
->name
) == cnt
&&
96 strncmp(id
, p
->name
, cnt
) == 0 &&
97 try_module_get(p
->owner
)) {
104 list_for_each_entry(p
, &clocks
, node
) {
105 if (strcmp(id
, p
->name
) == 0 && try_module_get(p
->owner
)) {
111 printk(KERN_WARNING
"clk: Unable to get requested clock: %s\n", id
);
114 mutex_unlock(&clocks_mutex
);
118 EXPORT_SYMBOL(clk_get
);
121 static void __clk_disable(struct clk
*clk
)
123 if (clk
== NULL
|| IS_ERR(clk
))
126 __clk_disable(clk
->parent
);
127 __clk_disable(clk
->secondary
);
129 if (!(--clk
->usecount
) && clk
->disable
)
133 static int __clk_enable(struct clk
*clk
)
135 if (clk
== NULL
|| IS_ERR(clk
))
138 __clk_enable(clk
->parent
);
139 __clk_enable(clk
->secondary
);
141 if (clk
->usecount
++ == 0 && clk
->enable
)
147 /* This function increments the reference count on the clock and enables the
148 * clock if not already enabled. The parent clock tree is recursively enabled
150 int clk_enable(struct clk
*clk
)
154 if (clk
== NULL
|| IS_ERR(clk
))
157 mutex_lock(&clocks_mutex
);
158 ret
= __clk_enable(clk
);
159 mutex_unlock(&clocks_mutex
);
163 EXPORT_SYMBOL(clk_enable
);
165 /* This function decrements the reference count on the clock and disables
166 * the clock when reference count is 0. The parent clock tree is
167 * recursively disabled
169 void clk_disable(struct clk
*clk
)
171 if (clk
== NULL
|| IS_ERR(clk
))
174 mutex_lock(&clocks_mutex
);
176 mutex_unlock(&clocks_mutex
);
178 EXPORT_SYMBOL(clk_disable
);
180 /* Retrieve the *current* clock rate. If the clock itself
181 * does not provide a special calculation routine, ask
182 * its parent and so on, until one is able to return
185 unsigned long clk_get_rate(struct clk
*clk
)
187 if (clk
== NULL
|| IS_ERR(clk
))
191 return clk
->get_rate(clk
);
193 return clk_get_rate(clk
->parent
);
195 EXPORT_SYMBOL(clk_get_rate
);
197 #ifndef CONFIG_COMMON_CLKDEV
198 /* Decrement the clock's module reference count */
199 void clk_put(struct clk
*clk
)
201 if (clk
&& !IS_ERR(clk
))
202 module_put(clk
->owner
);
204 EXPORT_SYMBOL(clk_put
);
207 /* Round the requested clock rate to the nearest supported
208 * rate that is less than or equal to the requested rate.
209 * This is dependent on the clock's current parent.
211 long clk_round_rate(struct clk
*clk
, unsigned long rate
)
213 if (clk
== NULL
|| IS_ERR(clk
) || !clk
->round_rate
)
216 return clk
->round_rate(clk
, rate
);
218 EXPORT_SYMBOL(clk_round_rate
);
220 /* Set the clock to the requested clock rate. The rate must
221 * match a supported rate exactly based on what clk_round_rate returns
223 int clk_set_rate(struct clk
*clk
, unsigned long rate
)
227 if (clk
== NULL
|| IS_ERR(clk
) || clk
->set_rate
== NULL
|| rate
== 0)
230 mutex_lock(&clocks_mutex
);
231 ret
= clk
->set_rate(clk
, rate
);
232 mutex_unlock(&clocks_mutex
);
236 EXPORT_SYMBOL(clk_set_rate
);
238 /* Set the clock's parent to another clock source */
239 int clk_set_parent(struct clk
*clk
, struct clk
*parent
)
243 if (clk
== NULL
|| IS_ERR(clk
) || parent
== NULL
||
244 IS_ERR(parent
) || clk
->set_parent
== NULL
)
247 mutex_lock(&clocks_mutex
);
248 ret
= clk
->set_parent(clk
, parent
);
250 clk
->parent
= parent
;
251 mutex_unlock(&clocks_mutex
);
255 EXPORT_SYMBOL(clk_set_parent
);
257 /* Retrieve the clock's parent clock source */
258 struct clk
*clk_get_parent(struct clk
*clk
)
260 struct clk
*ret
= NULL
;
262 if (clk
== NULL
|| IS_ERR(clk
))
267 EXPORT_SYMBOL(clk_get_parent
);
269 #ifndef CONFIG_COMMON_CLKDEV
271 * Add a new clock to the clock tree.
273 int clk_register(struct clk
*clk
)
275 if (clk
== NULL
|| IS_ERR(clk
))
278 mutex_lock(&clocks_mutex
);
279 list_add(&clk
->node
, &clocks
);
280 mutex_unlock(&clocks_mutex
);
284 EXPORT_SYMBOL(clk_register
);
286 /* Remove a clock from the clock tree */
287 void clk_unregister(struct clk
*clk
)
289 if (clk
== NULL
|| IS_ERR(clk
))
292 mutex_lock(&clocks_mutex
);
293 list_del(&clk
->node
);
294 mutex_unlock(&clocks_mutex
);
296 EXPORT_SYMBOL(clk_unregister
);
298 #ifdef CONFIG_PROC_FS
299 static int mxc_clock_read_proc(char *page
, char **start
, off_t off
,
300 int count
, int *eof
, void *data
)
306 list_for_each_entry(clkp
, &clocks
, node
) {
307 p
+= sprintf(p
, "%s-%d:\t\t%lu, %d", clkp
->name
, clkp
->id
,
308 clk_get_rate(clkp
), clkp
->usecount
);
310 p
+= sprintf(p
, ", %s-%d\n", clkp
->parent
->name
,
313 p
+= sprintf(p
, "\n");
316 len
= (p
- page
) - off
;
320 *eof
= (len
<= count
) ? 1 : 0;
326 static int __init
mxc_setup_proc_entry(void)
328 struct proc_dir_entry
*res
;
330 res
= create_proc_read_entry("cpu/clocks", 0, NULL
,
331 mxc_clock_read_proc
, NULL
);
333 printk(KERN_ERR
"Failed to create proc/cpu/clocks\n");
339 late_initcall(mxc_setup_proc_entry
);
340 #endif /* CONFIG_PROC_FS */
344 * Get the resulting clock rate from a PLL register value and the input
345 * frequency. PLLs with this register layout can at least be found on
346 * MX1, MX21, MX27 and MX31
348 * mfi + mfn / (mfd + 1)
349 * f = 2 * f_ref * --------------------
352 unsigned long mxc_decode_pll(unsigned int reg_val
, u32 freq
)
356 unsigned int mfi
, mfn
, mfd
, pd
;
358 mfi
= (reg_val
>> 10) & 0xf;
359 mfn
= reg_val
& 0x3ff;
360 mfd
= (reg_val
>> 16) & 0x3ff;
361 pd
= (reg_val
>> 26) & 0xf;
363 mfi
= mfi
<= 5 ? 5 : mfi
;
367 /* On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
368 * 2's complements number
370 if (!cpu_is_mx1() && !cpu_is_mx21() && mfn
>= 0x200)
371 mfn_abs
= 0x400 - mfn
;
376 ll
= (unsigned long long)freq
* mfn_abs
;
380 if (!cpu_is_mx1() && !cpu_is_mx21() && mfn
>= 0x200)
383 ll
= (freq
* mfi
) + ll
;
This page took 0.056027 seconds and 5 git commands to generate.