aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-sa1100/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-sa1100/clock.c')
-rw-r--r--arch/arm/mach-sa1100/clock.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
new file mode 100644
index 000000000000..b1e8fd766c1a
--- /dev/null
+++ b/arch/arm/mach-sa1100/clock.c
@@ -0,0 +1,132 @@
1/*
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/hardware.h>
14#include <asm/semaphore.h>
15
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);
27static DECLARE_MUTEX(clocks_sem);
28static 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
34 down(&clocks_sem);
35 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 }
41 up(&clocks_sem);
42
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 /*
88 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
89 * (SA-1110 Developer's Manual, section 9.1.2.1)
90 */
91 GAFR |= GPIO_32_768kHz;
92 GPDR |= GPIO_32_768kHz;
93 TUCR = TUCR_3_6864MHz;
94}
95
96static void clk_gpio27_disable(void)
97{
98 TUCR = 0;
99 GPDR &= ~GPIO_32_768kHz;
100 GAFR &= ~GPIO_32_768kHz;
101}
102
103static struct clk clk_gpio27 = {
104 .name = "GPIO27_CLK",
105 .rate = 3686400,
106 .enable = clk_gpio27_enable,
107 .disable = clk_gpio27_disable,
108};
109
110int clk_register(struct clk *clk)
111{
112 down(&clocks_sem);
113 list_add(&clk->node, &clocks);
114 up(&clocks_sem);
115 return 0;
116}
117EXPORT_SYMBOL(clk_register);
118
119void clk_unregister(struct clk *clk)
120{
121 down(&clocks_sem);
122 list_del(&clk->node);
123 up(&clocks_sem);
124}
125EXPORT_SYMBOL(clk_unregister);
126
127static int __init clk_init(void)
128{
129 clk_register(&clk_gpio27);
130 return 0;
131}
132arch_initcall(clk_init);