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>
24 #include <asm/semaphore.h>
25 #include <asm/hardware/clock.h>
27 #include <asm/arch/clock.h>
30 static DECLARE_MUTEX(clocks_sem);
31 DEFINE_SPINLOCK(clockfw_lock);
33 static struct clk_functions *arch_clock;
35 /*-------------------------------------------------------------------------
36 * Standard clock functions defined in asm/hardware/clock.h
37 *-------------------------------------------------------------------------*/
39 struct clk * clk_get(struct device *dev, const char *id)
41 struct clk *p, *clk = ERR_PTR(-ENOENT);
44 list_for_each_entry(p, &clocks, node) {
45 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
54 EXPORT_SYMBOL(clk_get);
56 int clk_enable(struct clk *clk)
61 spin_lock_irqsave(&clockfw_lock, flags);
63 ret = clk->enable(clk);
64 else if (arch_clock->clk_enable)
65 ret = arch_clock->clk_enable(clk);
67 printk(KERN_ERR "Could not enable clock %s\n", clk->name);
68 spin_unlock_irqrestore(&clockfw_lock, flags);
72 EXPORT_SYMBOL(clk_enable);
74 void clk_disable(struct clk *clk)
78 spin_lock_irqsave(&clockfw_lock, flags);
81 else if (arch_clock->clk_disable)
82 arch_clock->clk_disable(clk);
84 printk(KERN_ERR "Could not disable clock %s\n", clk->name);
85 spin_unlock_irqrestore(&clockfw_lock, flags);
87 EXPORT_SYMBOL(clk_disable);
89 int clk_use(struct clk *clk)
94 spin_lock_irqsave(&clockfw_lock, flags);
95 if (arch_clock->clk_use)
96 ret = arch_clock->clk_use(clk);
97 spin_unlock_irqrestore(&clockfw_lock, flags);
101 EXPORT_SYMBOL(clk_use);
103 void clk_unuse(struct clk *clk)
107 spin_lock_irqsave(&clockfw_lock, flags);
108 if (arch_clock->clk_unuse)
109 arch_clock->clk_unuse(clk);
110 spin_unlock_irqrestore(&clockfw_lock, flags);
112 EXPORT_SYMBOL(clk_unuse);
114 int clk_get_usecount(struct clk *clk)
119 spin_lock_irqsave(&clockfw_lock, flags);
121 spin_unlock_irqrestore(&clockfw_lock, flags);
125 EXPORT_SYMBOL(clk_get_usecount);
127 unsigned long clk_get_rate(struct clk *clk)
130 unsigned long ret = 0;
132 spin_lock_irqsave(&clockfw_lock, flags);
134 spin_unlock_irqrestore(&clockfw_lock, flags);
138 EXPORT_SYMBOL(clk_get_rate);
140 void clk_put(struct clk *clk)
142 if (clk && !IS_ERR(clk))
143 module_put(clk->owner);
145 EXPORT_SYMBOL(clk_put);
147 /*-------------------------------------------------------------------------
148 * Optional clock functions defined in asm/hardware/clock.h
149 *-------------------------------------------------------------------------*/
151 long clk_round_rate(struct clk *clk, unsigned long rate)
156 spin_lock_irqsave(&clockfw_lock, flags);
157 if (arch_clock->clk_round_rate)
158 ret = arch_clock->clk_round_rate(clk, rate);
159 spin_unlock_irqrestore(&clockfw_lock, flags);
163 EXPORT_SYMBOL(clk_round_rate);
165 int clk_set_rate(struct clk *clk, unsigned long rate)
170 spin_lock_irqsave(&clockfw_lock, flags);
171 if (arch_clock->clk_set_rate)
172 ret = arch_clock->clk_set_rate(clk, rate);
173 spin_unlock_irqrestore(&clockfw_lock, flags);
177 EXPORT_SYMBOL(clk_set_rate);
179 int clk_set_parent(struct clk *clk, struct clk *parent)
184 spin_lock_irqsave(&clockfw_lock, flags);
185 if (arch_clock->clk_set_parent)
186 ret = arch_clock->clk_set_parent(clk, parent);
187 spin_unlock_irqrestore(&clockfw_lock, flags);
191 EXPORT_SYMBOL(clk_set_parent);
193 struct clk *clk_get_parent(struct clk *clk)
196 struct clk * ret = NULL;
198 spin_lock_irqsave(&clockfw_lock, flags);
199 if (arch_clock->clk_get_parent)
200 ret = arch_clock->clk_get_parent(clk);
201 spin_unlock_irqrestore(&clockfw_lock, flags);
205 EXPORT_SYMBOL(clk_get_parent);
207 /*-------------------------------------------------------------------------
208 * OMAP specific clock functions shared between omap1 and omap2
209 *-------------------------------------------------------------------------*/
211 unsigned int __initdata mpurate;
214 * By default we use the rate set by the bootloader.
215 * You can override this with mpurate= cmdline option.
217 static int __init omap_clk_setup(char *str)
219 get_option(&str, &mpurate);
229 __setup("mpurate=", omap_clk_setup);
231 /* Used for clocks that always have same value as the parent clock */
232 void followparent_recalc(struct clk *clk)
234 clk->rate = clk->parent->rate;
237 /* Propagate rate to children */
238 void propagate_rate(struct clk * tclk)
242 list_for_each_entry(clkp, &clocks, node) {
243 if (likely(clkp->parent != tclk))
245 if (likely((u32)clkp->recalc))
250 int clk_register(struct clk *clk)
253 list_add(&clk->node, &clocks);
260 EXPORT_SYMBOL(clk_register);
262 void clk_unregister(struct clk *clk)
265 list_del(&clk->node);
268 EXPORT_SYMBOL(clk_unregister);
270 void clk_deny_idle(struct clk *clk)
274 spin_lock_irqsave(&clockfw_lock, flags);
275 if (arch_clock->clk_deny_idle)
276 arch_clock->clk_deny_idle(clk);
277 spin_unlock_irqrestore(&clockfw_lock, flags);
279 EXPORT_SYMBOL(clk_deny_idle);
281 void clk_allow_idle(struct clk *clk)
285 spin_lock_irqsave(&clockfw_lock, flags);
286 if (arch_clock->clk_allow_idle)
287 arch_clock->clk_allow_idle(clk);
288 spin_unlock_irqrestore(&clockfw_lock, flags);
290 EXPORT_SYMBOL(clk_allow_idle);
292 /*-------------------------------------------------------------------------*/
294 int __init clk_init(struct clk_functions * custom_clocks)
296 if (!custom_clocks) {
297 printk(KERN_ERR "No custom clock functions registered\n");
301 arch_clock = custom_clocks;