]> Pileus Git - ~andy/linux/blob - arch/arm/mach-sa1100/clock.c
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[~andy/linux] / arch / arm / mach-sa1100 / clock.c
1 /*
2  *  linux/arch/arm/mach-sa1100/clock.c
3  */
4 #include <linux/module.h>
5 #include <linux/kernel.h>
6 #include <linux/device.h>
7 #include <linux/list.h>
8 #include <linux/errno.h>
9 #include <linux/err.h>
10 #include <linux/string.h>
11 #include <linux/clk.h>
12 #include <linux/spinlock.h>
13 #include <linux/mutex.h>
14 #include <linux/io.h>
15 #include <linux/clkdev.h>
16
17 #include <mach/hardware.h>
18
19 struct clkops {
20         void                    (*enable)(struct clk *);
21         void                    (*disable)(struct clk *);
22         unsigned long           (*getrate)(struct clk *);
23 };
24
25 struct clk {
26         const struct clkops     *ops;
27         unsigned long           rate;
28         unsigned int            enabled;
29 };
30
31 #define INIT_CLKREG(_clk, _devname, _conname)           \
32         {                                               \
33                 .clk            = _clk,                 \
34                 .dev_id         = _devname,             \
35                 .con_id         = _conname,             \
36         }
37
38 #define DEFINE_CLK(_name, _ops, _rate)                  \
39 struct clk clk_##_name = {                              \
40                 .ops    = _ops,                         \
41                 .rate   = _rate,                        \
42         }
43
44 static DEFINE_SPINLOCK(clocks_lock);
45
46 static void clk_gpio27_enable(struct clk *clk)
47 {
48         /*
49          * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
50          * (SA-1110 Developer's Manual, section 9.1.2.1)
51          */
52         GAFR |= GPIO_32_768kHz;
53         GPDR |= GPIO_32_768kHz;
54         TUCR = TUCR_3_6864MHz;
55 }
56
57 static void clk_gpio27_disable(struct clk *clk)
58 {
59         TUCR = 0;
60         GPDR &= ~GPIO_32_768kHz;
61         GAFR &= ~GPIO_32_768kHz;
62 }
63
64 int clk_enable(struct clk *clk)
65 {
66         unsigned long flags;
67
68         spin_lock_irqsave(&clocks_lock, flags);
69         if (clk->enabled++ == 0)
70                 clk->ops->enable(clk);
71         spin_unlock_irqrestore(&clocks_lock, flags);
72
73         return 0;
74 }
75 EXPORT_SYMBOL(clk_enable);
76
77 void clk_disable(struct clk *clk)
78 {
79         unsigned long flags;
80
81         WARN_ON(clk->enabled == 0);
82
83         spin_lock_irqsave(&clocks_lock, flags);
84         if (--clk->enabled == 0)
85                 clk->ops->disable(clk);
86         spin_unlock_irqrestore(&clocks_lock, flags);
87 }
88 EXPORT_SYMBOL(clk_disable);
89
90 unsigned long clk_get_rate(struct clk *clk)
91 {
92         unsigned long rate;
93
94         rate = clk->rate;
95         if (clk->ops->getrate)
96                 rate = clk->ops->getrate(clk);
97
98         return rate;
99 }
100 EXPORT_SYMBOL(clk_get_rate);
101
102 const struct clkops clk_gpio27_ops = {
103         .enable         = clk_gpio27_enable,
104         .disable        = clk_gpio27_disable,
105 };
106
107 static void clk_dummy_enable(struct clk *clk) { }
108 static void clk_dummy_disable(struct clk *clk) { }
109
110 const struct clkops clk_dummy_ops = {
111         .enable         = clk_dummy_enable,
112         .disable        = clk_dummy_disable,
113 };
114
115 static DEFINE_CLK(gpio27, &clk_gpio27_ops, 3686400);
116 static DEFINE_CLK(dummy, &clk_dummy_ops, 0);
117
118 static struct clk_lookup sa11xx_clkregs[] = {
119         INIT_CLKREG(&clk_gpio27, "sa1111.0", NULL),
120         INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
121 };
122
123 static int __init sa11xx_clk_init(void)
124 {
125         clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
126         return 0;
127 }
128
129 postcore_initcall(sa11xx_clk_init);