diff options
author | Francesco VIRLINZI <francesco.virlinzi@st.com> | 2009-03-11 03:42:05 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-03-11 04:18:50 -0400 |
commit | 4a55026fd7a08074676e87932578ff9e327e82a3 (patch) | |
tree | 1440f7034dcc4c18e1d82fbc53ebf82509d066c5 | |
parent | d680c76eccd9222031ee30dcee5fdedba2467610 (diff) |
sh: clkfwk: Add resume from hibernation support.
This patch adds PM support to the clock framework.
With this, resume from hibernation is properly supported.
Signed-off-by: Francesco Virlinzi <francesco.virlinzi@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/kernel/cpu/clock.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 332a1798547c..3209a8740fa4 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> |
@@ -358,6 +360,68 @@ static int show_clocks(char *buf, char **start, off_t off, | |||
358 | return p - buf; | 360 | return p - buf; |
359 | } | 361 | } |
360 | 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 | if (likely(clkp->ops->set_parent)) | ||
376 | clkp->ops->set_parent(clkp, | ||
377 | clkp->parent); | ||
378 | if (likely(clkp->ops->set_rate)) | ||
379 | clkp->ops->set_rate(clkp, | ||
380 | clkp->rate, NO_CHANGE); | ||
381 | else if (likely(clkp->ops->recalc)) | ||
382 | clkp->ops->recalc(clkp); | ||
383 | } | ||
384 | } | ||
385 | break; | ||
386 | case PM_EVENT_FREEZE: | ||
387 | break; | ||
388 | case PM_EVENT_SUSPEND: | ||
389 | break; | ||
390 | } | ||
391 | |||
392 | prev_state = state; | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static int clks_sysdev_resume(struct sys_device *dev) | ||
397 | { | ||
398 | return clks_sysdev_suspend(dev, PMSG_ON); | ||
399 | } | ||
400 | |||
401 | static struct sysdev_class clks_sysdev_class = { | ||
402 | .name = "clks", | ||
403 | }; | ||
404 | |||
405 | static struct sysdev_driver clks_sysdev_driver = { | ||
406 | .suspend = clks_sysdev_suspend, | ||
407 | .resume = clks_sysdev_resume, | ||
408 | }; | ||
409 | |||
410 | static struct sys_device clks_sysdev_dev = { | ||
411 | .cls = &clks_sysdev_class, | ||
412 | }; | ||
413 | |||
414 | static int __init clk_sysdev_init(void) | ||
415 | { | ||
416 | sysdev_class_register(&clks_sysdev_class); | ||
417 | sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); | ||
418 | sysdev_register(&clks_sysdev_dev); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | subsys_initcall(clk_sysdev_init); | ||
423 | #endif | ||
424 | |||
361 | int __init clk_init(void) | 425 | int __init clk_init(void) |
362 | { | 426 | { |
363 | int i, ret = 0; | 427 | int i, ret = 0; |