blob: 34a31caa6f9d6a83cbc379014fdbe8b88ccd7395 [file] [log] [blame]
Russell King97d654f2006-03-15 15:54:37 +00001/*
2 * linux/arch/arm/mach-sa1100/clock.c
3 */
4#include <linux/module.h>
5#include <linux/kernel.h>
6#include <linux/list.h>
7#include <linux/errno.h>
8#include <linux/err.h>
9#include <linux/string.h>
10#include <linux/clk.h>
11#include <linux/spinlock.h>
12
13#include <asm/arch/pxa-regs.h>
14#include <asm/hardware.h>
Russell King97d654f2006-03-15 15:54:37 +000015
16struct clk {
17 struct list_head node;
18 unsigned long rate;
19 struct module *owner;
20 const char *name;
21 unsigned int enabled;
22 void (*enable)(void);
23 void (*disable)(void);
24};
25
26static LIST_HEAD(clocks);
Russell Kingf4b6a0a2007-05-15 16:49:02 +010027static DEFINE_MUTEX(clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000028static DEFINE_SPINLOCK(clocks_lock);
29
30struct clk *clk_get(struct device *dev, const char *id)
31{
32 struct clk *p, *clk = ERR_PTR(-ENOENT);
33
Russell Kingf4b6a0a2007-05-15 16:49:02 +010034 mutex_lock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000035 list_for_each_entry(p, &clocks, node) {
36 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
37 clk = p;
38 break;
39 }
40 }
Russell Kingf4b6a0a2007-05-15 16:49:02 +010041 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +000042
43 return clk;
44}
45EXPORT_SYMBOL(clk_get);
46
47void clk_put(struct clk *clk)
48{
49 module_put(clk->owner);
50}
51EXPORT_SYMBOL(clk_put);
52
53int clk_enable(struct clk *clk)
54{
55 unsigned long flags;
56
57 spin_lock_irqsave(&clocks_lock, flags);
58 if (clk->enabled++ == 0)
59 clk->enable();
60 spin_unlock_irqrestore(&clocks_lock, flags);
61 return 0;
62}
63EXPORT_SYMBOL(clk_enable);
64
65void clk_disable(struct clk *clk)
66{
67 unsigned long flags;
68
69 WARN_ON(clk->enabled == 0);
70
71 spin_lock_irqsave(&clocks_lock, flags);
72 if (--clk->enabled == 0)
73 clk->disable();
74 spin_unlock_irqrestore(&clocks_lock, flags);
75}
76EXPORT_SYMBOL(clk_disable);
77
78unsigned long clk_get_rate(struct clk *clk)
79{
80 return clk->rate;
81}
82EXPORT_SYMBOL(clk_get_rate);
83
84
85static void clk_gpio27_enable(void)
86{
87 pxa_gpio_mode(GPIO11_3_6MHz_MD);
88}
89
90static void clk_gpio27_disable(void)
91{
92}
93
94static struct clk clk_gpio27 = {
95 .name = "GPIO27_CLK",
96 .rate = 3686400,
97 .enable = clk_gpio27_enable,
98 .disable = clk_gpio27_disable,
99};
100
101int clk_register(struct clk *clk)
102{
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100103 mutex_lock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +0000104 list_add(&clk->node, &clocks);
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100105 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +0000106 return 0;
107}
108EXPORT_SYMBOL(clk_register);
109
110void clk_unregister(struct clk *clk)
111{
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100112 mutex_lock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +0000113 list_del(&clk->node);
Russell Kingf4b6a0a2007-05-15 16:49:02 +0100114 mutex_unlock(&clocks_mutex);
Russell King97d654f2006-03-15 15:54:37 +0000115}
116EXPORT_SYMBOL(clk_unregister);
117
118static int __init clk_init(void)
119{
120 clk_register(&clk_gpio27);
121 return 0;
122}
123arch_initcall(clk_init);