Commit | Line | Data |
---|---|---|
97d654f8 RK |
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> | |
a6dba20c RK |
12 | #include <linux/platform_device.h> |
13 | #include <linux/delay.h> | |
97d654f8 | 14 | |
0b0a9df6 | 15 | #include <asm/arch/pxa2xx-regs.h> |
a683b14d | 16 | #include <asm/arch/pxa2xx-gpio.h> |
97d654f8 | 17 | #include <asm/hardware.h> |
97d654f8 | 18 | |
a6dba20c RK |
19 | #include "devices.h" |
20 | #include "generic.h" | |
21 | #include "clock.h" | |
97d654f8 RK |
22 | |
23 | static LIST_HEAD(clocks); | |
f4b6a0a4 | 24 | static DEFINE_MUTEX(clocks_mutex); |
97d654f8 RK |
25 | static DEFINE_SPINLOCK(clocks_lock); |
26 | ||
a0dd005d RK |
27 | static struct clk *clk_lookup(struct device *dev, const char *id) |
28 | { | |
29 | struct clk *p; | |
30 | ||
31 | list_for_each_entry(p, &clocks, node) | |
32 | if (strcmp(id, p->name) == 0 && p->dev == dev) | |
33 | return p; | |
34 | ||
35 | return NULL; | |
36 | } | |
37 | ||
97d654f8 RK |
38 | struct clk *clk_get(struct device *dev, const char *id) |
39 | { | |
40 | struct clk *p, *clk = ERR_PTR(-ENOENT); | |
41 | ||
f4b6a0a4 | 42 | mutex_lock(&clocks_mutex); |
a0dd005d RK |
43 | p = clk_lookup(dev, id); |
44 | if (!p) | |
45 | p = clk_lookup(NULL, id); | |
46 | if (p) | |
47 | clk = p; | |
f4b6a0a4 | 48 | mutex_unlock(&clocks_mutex); |
97d654f8 RK |
49 | |
50 | return clk; | |
51 | } | |
52 | EXPORT_SYMBOL(clk_get); | |
53 | ||
54 | void clk_put(struct clk *clk) | |
55 | { | |
97d654f8 RK |
56 | } |
57 | EXPORT_SYMBOL(clk_put); | |
58 | ||
59 | int clk_enable(struct clk *clk) | |
60 | { | |
61 | unsigned long flags; | |
62 | ||
63 | spin_lock_irqsave(&clocks_lock, flags); | |
64 | if (clk->enabled++ == 0) | |
a6dba20c | 65 | clk->ops->enable(clk); |
97d654f8 | 66 | spin_unlock_irqrestore(&clocks_lock, flags); |
a6dba20c RK |
67 | |
68 | if (clk->delay) | |
69 | udelay(clk->delay); | |
70 | ||
97d654f8 RK |
71 | return 0; |
72 | } | |
73 | EXPORT_SYMBOL(clk_enable); | |
74 | ||
75 | void clk_disable(struct clk *clk) | |
76 | { | |
77 | unsigned long flags; | |
78 | ||
79 | WARN_ON(clk->enabled == 0); | |
80 | ||
81 | spin_lock_irqsave(&clocks_lock, flags); | |
82 | if (--clk->enabled == 0) | |
a6dba20c | 83 | clk->ops->disable(clk); |
97d654f8 RK |
84 | spin_unlock_irqrestore(&clocks_lock, flags); |
85 | } | |
86 | EXPORT_SYMBOL(clk_disable); | |
87 | ||
88 | unsigned long clk_get_rate(struct clk *clk) | |
89 | { | |
a6dba20c RK |
90 | unsigned long rate; |
91 | ||
92 | rate = clk->rate; | |
93 | if (clk->ops->getrate) | |
94 | rate = clk->ops->getrate(clk); | |
95 | ||
96 | return rate; | |
97d654f8 RK |
97 | } |
98 | EXPORT_SYMBOL(clk_get_rate); | |
99 | ||
100 | ||
a6dba20c | 101 | static void clk_gpio27_enable(struct clk *clk) |
97d654f8 RK |
102 | { |
103 | pxa_gpio_mode(GPIO11_3_6MHz_MD); | |
104 | } | |
105 | ||
a6dba20c | 106 | static void clk_gpio27_disable(struct clk *clk) |
97d654f8 RK |
107 | { |
108 | } | |
109 | ||
a6dba20c | 110 | static const struct clkops clk_gpio27_ops = { |
97d654f8 RK |
111 | .enable = clk_gpio27_enable, |
112 | .disable = clk_gpio27_disable, | |
113 | }; | |
114 | ||
a6dba20c RK |
115 | |
116 | void clk_cken_enable(struct clk *clk) | |
97d654f8 | 117 | { |
a6dba20c | 118 | CKEN |= 1 << clk->cken; |
97d654f8 | 119 | } |
97d654f8 | 120 | |
a6dba20c | 121 | void clk_cken_disable(struct clk *clk) |
97d654f8 | 122 | { |
a6dba20c RK |
123 | CKEN &= ~(1 << clk->cken); |
124 | } | |
125 | ||
126 | const struct clkops clk_cken_ops = { | |
127 | .enable = clk_cken_enable, | |
128 | .disable = clk_cken_disable, | |
129 | }; | |
130 | ||
131 | static struct clk common_clks[] = { | |
132 | { | |
133 | .name = "GPIO27_CLK", | |
134 | .ops = &clk_gpio27_ops, | |
135 | .rate = 3686400, | |
136 | }, | |
137 | }; | |
138 | ||
139 | void clks_register(struct clk *clks, size_t num) | |
140 | { | |
141 | int i; | |
142 | ||
f4b6a0a4 | 143 | mutex_lock(&clocks_mutex); |
a6dba20c RK |
144 | for (i = 0; i < num; i++) |
145 | list_add(&clks[i].node, &clocks); | |
f4b6a0a4 | 146 | mutex_unlock(&clocks_mutex); |
97d654f8 | 147 | } |
97d654f8 RK |
148 | |
149 | static int __init clk_init(void) | |
150 | { | |
a6dba20c | 151 | clks_register(common_clks, ARRAY_SIZE(common_clks)); |
97d654f8 RK |
152 | return 0; |
153 | } | |
154 | arch_initcall(clk_init); |