diff options
Diffstat (limited to 'arch/sh/kernel/cpu/clock.c')
-rw-r--r-- | arch/sh/kernel/cpu/clock.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 7b17137536d6..1dc896483b59 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/kref.h> | 22 | #include <linux/kref.h> |
23 | #include <linux/kobject.h> | ||
24 | #include <linux/sysdev.h> | ||
23 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
24 | #include <linux/err.h> | 26 | #include <linux/err.h> |
25 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
@@ -239,6 +241,35 @@ void clk_recalc_rate(struct clk *clk) | |||
239 | } | 241 | } |
240 | EXPORT_SYMBOL_GPL(clk_recalc_rate); | 242 | EXPORT_SYMBOL_GPL(clk_recalc_rate); |
241 | 243 | ||
244 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
245 | { | ||
246 | int ret = -EINVAL; | ||
247 | struct clk *old; | ||
248 | |||
249 | if (!parent || !clk) | ||
250 | return ret; | ||
251 | |||
252 | old = clk->parent; | ||
253 | if (likely(clk->ops && clk->ops->set_parent)) { | ||
254 | unsigned long flags; | ||
255 | spin_lock_irqsave(&clock_lock, flags); | ||
256 | ret = clk->ops->set_parent(clk, parent); | ||
257 | spin_unlock_irqrestore(&clock_lock, flags); | ||
258 | clk->parent = (ret ? old : parent); | ||
259 | } | ||
260 | |||
261 | if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) | ||
262 | propagate_rate(clk); | ||
263 | return ret; | ||
264 | } | ||
265 | EXPORT_SYMBOL_GPL(clk_set_parent); | ||
266 | |||
267 | struct clk *clk_get_parent(struct clk *clk) | ||
268 | { | ||
269 | return clk->parent; | ||
270 | } | ||
271 | EXPORT_SYMBOL_GPL(clk_get_parent); | ||
272 | |||
242 | long clk_round_rate(struct clk *clk, unsigned long rate) | 273 | long clk_round_rate(struct clk *clk, unsigned long rate) |
243 | { | 274 | { |
244 | if (likely(clk->ops && clk->ops->round_rate)) { | 275 | if (likely(clk->ops && clk->ops->round_rate)) { |
@@ -329,6 +360,70 @@ static int show_clocks(char *buf, char **start, off_t off, | |||
329 | return p - buf; | 360 | return p - buf; |
330 | } | 361 | } |
331 | 362 | ||
363 | #ifdef CONFIG_PM | ||
364 | static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) | ||
365 | { | ||
366 | static pm_message_t prev_state; | ||
367 | struct clk *clkp; | ||
368 | |||
369 | switch (state.event) { | ||
370 | case PM_EVENT_ON: | ||
371 | /* Resumeing from hibernation */ | ||
372 | if (prev_state.event == PM_EVENT_FREEZE) { | ||
373 | list_for_each_entry(clkp, &clock_list, node) | ||
374 | if (likely(clkp->ops)) { | ||
375 | unsigned long rate = clkp->rate; | ||
376 | |||
377 | if (likely(clkp->ops->set_parent)) | ||
378 | clkp->ops->set_parent(clkp, | ||
379 | clkp->parent); | ||
380 | if (likely(clkp->ops->set_rate)) | ||
381 | clkp->ops->set_rate(clkp, | ||
382 | rate, NO_CHANGE); | ||
383 | else if (likely(clkp->ops->recalc)) | ||
384 | clkp->ops->recalc(clkp); | ||
385 | } | ||
386 | } | ||
387 | break; | ||
388 | case PM_EVENT_FREEZE: | ||
389 | break; | ||
390 | case PM_EVENT_SUSPEND: | ||
391 | break; | ||
392 | } | ||
393 | |||
394 | prev_state = state; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int clks_sysdev_resume(struct sys_device *dev) | ||
399 | { | ||
400 | return clks_sysdev_suspend(dev, PMSG_ON); | ||
401 | } | ||
402 | |||
403 | static struct sysdev_class clks_sysdev_class = { | ||
404 | .name = "clks", | ||
405 | }; | ||
406 | |||
407 | static struct sysdev_driver clks_sysdev_driver = { | ||
408 | .suspend = clks_sysdev_suspend, | ||
409 | .resume = clks_sysdev_resume, | ||
410 | }; | ||
411 | |||
412 | static struct sys_device clks_sysdev_dev = { | ||
413 | .cls = &clks_sysdev_class, | ||
414 | }; | ||
415 | |||
416 | static int __init clk_sysdev_init(void) | ||
417 | { | ||
418 | sysdev_class_register(&clks_sysdev_class); | ||
419 | sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); | ||
420 | sysdev_register(&clks_sysdev_dev); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | subsys_initcall(clk_sysdev_init); | ||
425 | #endif | ||
426 | |||
332 | int __init clk_init(void) | 427 | int __init clk_init(void) |
333 | { | 428 | { |
334 | int i, ret = 0; | 429 | int i, ret = 0; |