diff options
Diffstat (limited to 'arch/arm/plat-omap/clock.c')
-rw-r--r-- | arch/arm/plat-omap/clock.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 3c2bfc0efdaf..06485c193ee3 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/platform_device.h> | ||
24 | 25 | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <asm/semaphore.h> | 27 | #include <asm/semaphore.h> |
@@ -37,17 +38,37 @@ static struct clk_functions *arch_clock; | |||
37 | * Standard clock functions defined in include/linux/clk.h | 38 | * Standard clock functions defined in include/linux/clk.h |
38 | *-------------------------------------------------------------------------*/ | 39 | *-------------------------------------------------------------------------*/ |
39 | 40 | ||
41 | /* | ||
42 | * Returns a clock. Note that we first try to use device id on the bus | ||
43 | * and clock name. If this fails, we try to use clock name only. | ||
44 | */ | ||
40 | struct clk * clk_get(struct device *dev, const char *id) | 45 | struct clk * clk_get(struct device *dev, const char *id) |
41 | { | 46 | { |
42 | struct clk *p, *clk = ERR_PTR(-ENOENT); | 47 | struct clk *p, *clk = ERR_PTR(-ENOENT); |
48 | int idno; | ||
49 | |||
50 | if (dev == NULL || dev->bus != &platform_bus_type) | ||
51 | idno = -1; | ||
52 | else | ||
53 | idno = to_platform_device(dev)->id; | ||
43 | 54 | ||
44 | mutex_lock(&clocks_mutex); | 55 | mutex_lock(&clocks_mutex); |
56 | |||
57 | list_for_each_entry(p, &clocks, node) { | ||
58 | if (p->id == idno && | ||
59 | strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
60 | clk = p; | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | |||
45 | list_for_each_entry(p, &clocks, node) { | 65 | list_for_each_entry(p, &clocks, node) { |
46 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | 66 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { |
47 | clk = p; | 67 | clk = p; |
48 | break; | 68 | break; |
49 | } | 69 | } |
50 | } | 70 | } |
71 | |||
51 | mutex_unlock(&clocks_mutex); | 72 | mutex_unlock(&clocks_mutex); |
52 | 73 | ||
53 | return clk; | 74 | return clk; |
@@ -59,6 +80,9 @@ int clk_enable(struct clk *clk) | |||
59 | unsigned long flags; | 80 | unsigned long flags; |
60 | int ret = 0; | 81 | int ret = 0; |
61 | 82 | ||
83 | if (clk == NULL || IS_ERR(clk)) | ||
84 | return -EINVAL; | ||
85 | |||
62 | spin_lock_irqsave(&clockfw_lock, flags); | 86 | spin_lock_irqsave(&clockfw_lock, flags); |
63 | if (arch_clock->clk_enable) | 87 | if (arch_clock->clk_enable) |
64 | ret = arch_clock->clk_enable(clk); | 88 | ret = arch_clock->clk_enable(clk); |
@@ -72,6 +96,9 @@ void clk_disable(struct clk *clk) | |||
72 | { | 96 | { |
73 | unsigned long flags; | 97 | unsigned long flags; |
74 | 98 | ||
99 | if (clk == NULL || IS_ERR(clk)) | ||
100 | return; | ||
101 | |||
75 | spin_lock_irqsave(&clockfw_lock, flags); | 102 | spin_lock_irqsave(&clockfw_lock, flags); |
76 | if (arch_clock->clk_disable) | 103 | if (arch_clock->clk_disable) |
77 | arch_clock->clk_disable(clk); | 104 | arch_clock->clk_disable(clk); |
@@ -84,6 +111,9 @@ int clk_get_usecount(struct clk *clk) | |||
84 | unsigned long flags; | 111 | unsigned long flags; |
85 | int ret = 0; | 112 | int ret = 0; |
86 | 113 | ||
114 | if (clk == NULL || IS_ERR(clk)) | ||
115 | return 0; | ||
116 | |||
87 | spin_lock_irqsave(&clockfw_lock, flags); | 117 | spin_lock_irqsave(&clockfw_lock, flags); |
88 | ret = clk->usecount; | 118 | ret = clk->usecount; |
89 | spin_unlock_irqrestore(&clockfw_lock, flags); | 119 | spin_unlock_irqrestore(&clockfw_lock, flags); |
@@ -97,6 +127,9 @@ unsigned long clk_get_rate(struct clk *clk) | |||
97 | unsigned long flags; | 127 | unsigned long flags; |
98 | unsigned long ret = 0; | 128 | unsigned long ret = 0; |
99 | 129 | ||
130 | if (clk == NULL || IS_ERR(clk)) | ||
131 | return 0; | ||
132 | |||
100 | spin_lock_irqsave(&clockfw_lock, flags); | 133 | spin_lock_irqsave(&clockfw_lock, flags); |
101 | ret = clk->rate; | 134 | ret = clk->rate; |
102 | spin_unlock_irqrestore(&clockfw_lock, flags); | 135 | spin_unlock_irqrestore(&clockfw_lock, flags); |
@@ -121,6 +154,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
121 | unsigned long flags; | 154 | unsigned long flags; |
122 | long ret = 0; | 155 | long ret = 0; |
123 | 156 | ||
157 | if (clk == NULL || IS_ERR(clk)) | ||
158 | return ret; | ||
159 | |||
124 | spin_lock_irqsave(&clockfw_lock, flags); | 160 | spin_lock_irqsave(&clockfw_lock, flags); |
125 | if (arch_clock->clk_round_rate) | 161 | if (arch_clock->clk_round_rate) |
126 | ret = arch_clock->clk_round_rate(clk, rate); | 162 | ret = arch_clock->clk_round_rate(clk, rate); |
@@ -133,7 +169,10 @@ EXPORT_SYMBOL(clk_round_rate); | |||
133 | int clk_set_rate(struct clk *clk, unsigned long rate) | 169 | int clk_set_rate(struct clk *clk, unsigned long rate) |
134 | { | 170 | { |
135 | unsigned long flags; | 171 | unsigned long flags; |
136 | int ret = 0; | 172 | int ret = -EINVAL; |
173 | |||
174 | if (clk == NULL || IS_ERR(clk)) | ||
175 | return ret; | ||
137 | 176 | ||
138 | spin_lock_irqsave(&clockfw_lock, flags); | 177 | spin_lock_irqsave(&clockfw_lock, flags); |
139 | if (arch_clock->clk_set_rate) | 178 | if (arch_clock->clk_set_rate) |
@@ -147,7 +186,10 @@ EXPORT_SYMBOL(clk_set_rate); | |||
147 | int clk_set_parent(struct clk *clk, struct clk *parent) | 186 | int clk_set_parent(struct clk *clk, struct clk *parent) |
148 | { | 187 | { |
149 | unsigned long flags; | 188 | unsigned long flags; |
150 | int ret = 0; | 189 | int ret = -EINVAL; |
190 | |||
191 | if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) | ||
192 | return ret; | ||
151 | 193 | ||
152 | spin_lock_irqsave(&clockfw_lock, flags); | 194 | spin_lock_irqsave(&clockfw_lock, flags); |
153 | if (arch_clock->clk_set_parent) | 195 | if (arch_clock->clk_set_parent) |
@@ -163,6 +205,9 @@ struct clk *clk_get_parent(struct clk *clk) | |||
163 | unsigned long flags; | 205 | unsigned long flags; |
164 | struct clk * ret = NULL; | 206 | struct clk * ret = NULL; |
165 | 207 | ||
208 | if (clk == NULL || IS_ERR(clk)) | ||
209 | return ret; | ||
210 | |||
166 | spin_lock_irqsave(&clockfw_lock, flags); | 211 | spin_lock_irqsave(&clockfw_lock, flags); |
167 | if (arch_clock->clk_get_parent) | 212 | if (arch_clock->clk_get_parent) |
168 | ret = arch_clock->clk_get_parent(clk); | 213 | ret = arch_clock->clk_get_parent(clk); |
@@ -199,6 +244,9 @@ __setup("mpurate=", omap_clk_setup); | |||
199 | /* Used for clocks that always have same value as the parent clock */ | 244 | /* Used for clocks that always have same value as the parent clock */ |
200 | void followparent_recalc(struct clk *clk) | 245 | void followparent_recalc(struct clk *clk) |
201 | { | 246 | { |
247 | if (clk == NULL || IS_ERR(clk)) | ||
248 | return; | ||
249 | |||
202 | clk->rate = clk->parent->rate; | 250 | clk->rate = clk->parent->rate; |
203 | } | 251 | } |
204 | 252 | ||
@@ -207,6 +255,9 @@ void propagate_rate(struct clk * tclk) | |||
207 | { | 255 | { |
208 | struct clk *clkp; | 256 | struct clk *clkp; |
209 | 257 | ||
258 | if (tclk == NULL || IS_ERR(tclk)) | ||
259 | return; | ||
260 | |||
210 | list_for_each_entry(clkp, &clocks, node) { | 261 | list_for_each_entry(clkp, &clocks, node) { |
211 | if (likely(clkp->parent != tclk)) | 262 | if (likely(clkp->parent != tclk)) |
212 | continue; | 263 | continue; |
@@ -217,6 +268,9 @@ void propagate_rate(struct clk * tclk) | |||
217 | 268 | ||
218 | int clk_register(struct clk *clk) | 269 | int clk_register(struct clk *clk) |
219 | { | 270 | { |
271 | if (clk == NULL || IS_ERR(clk)) | ||
272 | return -EINVAL; | ||
273 | |||
220 | mutex_lock(&clocks_mutex); | 274 | mutex_lock(&clocks_mutex); |
221 | list_add(&clk->node, &clocks); | 275 | list_add(&clk->node, &clocks); |
222 | if (clk->init) | 276 | if (clk->init) |
@@ -229,6 +283,9 @@ EXPORT_SYMBOL(clk_register); | |||
229 | 283 | ||
230 | void clk_unregister(struct clk *clk) | 284 | void clk_unregister(struct clk *clk) |
231 | { | 285 | { |
286 | if (clk == NULL || IS_ERR(clk)) | ||
287 | return; | ||
288 | |||
232 | mutex_lock(&clocks_mutex); | 289 | mutex_lock(&clocks_mutex); |
233 | list_del(&clk->node); | 290 | list_del(&clk->node); |
234 | mutex_unlock(&clocks_mutex); | 291 | mutex_unlock(&clocks_mutex); |
@@ -239,6 +296,9 @@ void clk_deny_idle(struct clk *clk) | |||
239 | { | 296 | { |
240 | unsigned long flags; | 297 | unsigned long flags; |
241 | 298 | ||
299 | if (clk == NULL || IS_ERR(clk)) | ||
300 | return; | ||
301 | |||
242 | spin_lock_irqsave(&clockfw_lock, flags); | 302 | spin_lock_irqsave(&clockfw_lock, flags); |
243 | if (arch_clock->clk_deny_idle) | 303 | if (arch_clock->clk_deny_idle) |
244 | arch_clock->clk_deny_idle(clk); | 304 | arch_clock->clk_deny_idle(clk); |
@@ -250,6 +310,9 @@ void clk_allow_idle(struct clk *clk) | |||
250 | { | 310 | { |
251 | unsigned long flags; | 311 | unsigned long flags; |
252 | 312 | ||
313 | if (clk == NULL || IS_ERR(clk)) | ||
314 | return; | ||
315 | |||
253 | spin_lock_irqsave(&clockfw_lock, flags); | 316 | spin_lock_irqsave(&clockfw_lock, flags); |
254 | if (arch_clock->clk_allow_idle) | 317 | if (arch_clock->clk_allow_idle) |
255 | arch_clock->clk_allow_idle(clk); | 318 | arch_clock->clk_allow_idle(clk); |