2 * linux/arch/arm/plat-omap/clock.c
4 * Copyright (C) 2004 - 2005 Nokia corporation
5 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
7 * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
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.
13 #include <linux/version.h>
14 #include <linux/config.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
20 #include <linux/err.h>
21 #include <linux/string.h>
22 #include <linux/clk.h>
23 #include <linux/mutex.h>
26 #include <asm/semaphore.h>
28 #include <asm/arch/clock.h>
31 static DEFINE_MUTEX(clocks_mutex
);
32 DEFINE_SPINLOCK(clockfw_lock
);
34 static struct clk_functions
*arch_clock
;
36 /*-------------------------------------------------------------------------
37 * Standard clock functions defined in include/linux/clk.h
38 *-------------------------------------------------------------------------*/
40 struct clk
* clk_get(struct device
*dev
, const char *id
)
42 struct clk
*p
, *clk
= ERR_PTR(-ENOENT
);
44 mutex_lock(&clocks_mutex
);
45 list_for_each_entry(p
, &clocks
, node
) {
46 if (strcmp(id
, p
->name
) == 0 && try_module_get(p
->owner
)) {
51 mutex_unlock(&clocks_mutex
);
55 EXPORT_SYMBOL(clk_get
);
57 int clk_enable(struct clk
*clk
)
62 spin_lock_irqsave(&clockfw_lock
, flags
);
63 if (arch_clock
->clk_enable
)
64 ret
= arch_clock
->clk_enable(clk
);
65 spin_unlock_irqrestore(&clockfw_lock
, flags
);
69 EXPORT_SYMBOL(clk_enable
);
71 void clk_disable(struct clk
*clk
)
75 spin_lock_irqsave(&clockfw_lock
, flags
);
76 if (arch_clock
->clk_disable
)
77 arch_clock
->clk_disable(clk
);
78 spin_unlock_irqrestore(&clockfw_lock
, flags
);
80 EXPORT_SYMBOL(clk_disable
);
82 int clk_get_usecount(struct clk
*clk
)
87 spin_lock_irqsave(&clockfw_lock
, flags
);
89 spin_unlock_irqrestore(&clockfw_lock
, flags
);
93 EXPORT_SYMBOL(clk_get_usecount
);
95 unsigned long clk_get_rate(struct clk
*clk
)
98 unsigned long ret
= 0;
100 spin_lock_irqsave(&clockfw_lock
, flags
);
102 spin_unlock_irqrestore(&clockfw_lock
, flags
);
106 EXPORT_SYMBOL(clk_get_rate
);
108 void clk_put(struct clk
*clk
)
110 if (clk
&& !IS_ERR(clk
))
111 module_put(clk
->owner
);
113 EXPORT_SYMBOL(clk_put
);
115 /*-------------------------------------------------------------------------
116 * Optional clock functions defined in include/linux/clk.h
117 *-------------------------------------------------------------------------*/
119 long clk_round_rate(struct clk
*clk
, unsigned long rate
)
124 spin_lock_irqsave(&clockfw_lock
, flags
);
125 if (arch_clock
->clk_round_rate
)
126 ret
= arch_clock
->clk_round_rate(clk
, rate
);
127 spin_unlock_irqrestore(&clockfw_lock
, flags
);
131 EXPORT_SYMBOL(clk_round_rate
);
133 int clk_set_rate(struct clk
*clk
, unsigned long rate
)
138 spin_lock_irqsave(&clockfw_lock
, flags
);
139 if (arch_clock
->clk_set_rate
)
140 ret
= arch_clock
->clk_set_rate(clk
, rate
);
141 spin_unlock_irqrestore(&clockfw_lock
, flags
);
145 EXPORT_SYMBOL(clk_set_rate
);
147 int clk_set_parent(struct clk
*clk
, struct clk
*parent
)
152 spin_lock_irqsave(&clockfw_lock
, flags
);
153 if (arch_clock
->clk_set_parent
)
154 ret
= arch_clock
->clk_set_parent(clk
, parent
);
155 spin_unlock_irqrestore(&clockfw_lock
, flags
);
159 EXPORT_SYMBOL(clk_set_parent
);
161 struct clk
*clk_get_parent(struct clk
*clk
)
164 struct clk
* ret
= NULL
;
166 spin_lock_irqsave(&clockfw_lock
, flags
);
167 if (arch_clock
->clk_get_parent
)
168 ret
= arch_clock
->clk_get_parent(clk
);
169 spin_unlock_irqrestore(&clockfw_lock
, flags
);
173 EXPORT_SYMBOL(clk_get_parent
);
175 /*-------------------------------------------------------------------------
176 * OMAP specific clock functions shared between omap1 and omap2
177 *-------------------------------------------------------------------------*/
179 unsigned int __initdata mpurate
;
182 * By default we use the rate set by the bootloader.
183 * You can override this with mpurate= cmdline option.
185 static int __init
omap_clk_setup(char *str
)
187 get_option(&str
, &mpurate
);
197 __setup("mpurate=", omap_clk_setup
);
199 /* Used for clocks that always have same value as the parent clock */
200 void followparent_recalc(struct clk
*clk
)
202 clk
->rate
= clk
->parent
->rate
;
205 /* Propagate rate to children */
206 void propagate_rate(struct clk
* tclk
)
210 list_for_each_entry(clkp
, &clocks
, node
) {
211 if (likely(clkp
->parent
!= tclk
))
213 if (likely((u32
)clkp
->recalc
))
218 int clk_register(struct clk
*clk
)
220 mutex_lock(&clocks_mutex
);
221 list_add(&clk
->node
, &clocks
);
224 mutex_unlock(&clocks_mutex
);
228 EXPORT_SYMBOL(clk_register
);
230 void clk_unregister(struct clk
*clk
)
232 mutex_lock(&clocks_mutex
);
233 list_del(&clk
->node
);
234 mutex_unlock(&clocks_mutex
);
236 EXPORT_SYMBOL(clk_unregister
);
238 void clk_deny_idle(struct clk
*clk
)
242 spin_lock_irqsave(&clockfw_lock
, flags
);
243 if (arch_clock
->clk_deny_idle
)
244 arch_clock
->clk_deny_idle(clk
);
245 spin_unlock_irqrestore(&clockfw_lock
, flags
);
247 EXPORT_SYMBOL(clk_deny_idle
);
249 void clk_allow_idle(struct clk
*clk
)
253 spin_lock_irqsave(&clockfw_lock
, flags
);
254 if (arch_clock
->clk_allow_idle
)
255 arch_clock
->clk_allow_idle(clk
);
256 spin_unlock_irqrestore(&clockfw_lock
, flags
);
258 EXPORT_SYMBOL(clk_allow_idle
);
260 /*-------------------------------------------------------------------------*/
262 int __init
clk_init(struct clk_functions
* custom_clocks
)
264 if (!custom_clocks
) {
265 printk(KERN_ERR
"No custom clock functions registered\n");
269 arch_clock
= custom_clocks
;