diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-04-02 16:33:42 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-02 16:33:51 +0200 |
commit | 83f2f0ed715eb15a8e13c07df479d65bbc10d8d5 (patch) | |
tree | e47d7edefa210b328f8cfba43d170fc67d6e0671 /arch/sh/kernel/cpu/clock.c | |
parent | 3de46fda4c104deef17ec70f85361f5c6b84ce0e (diff) | |
parent | 4fe70410d9a219dabb47328effccae7e7f2a6e26 (diff) | |
download | linux-83f2f0ed715eb15a8e13c07df479d65bbc10d8d5.tar.bz2 |
Merge branch 'linus' into x86/urgent
Merge needed to go past commit 7ca43e756 (mm: use debug_kmap_atomic)
and fix it.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
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 @@ #include <linux/mutex.h> #include <linux/list.h> #include <linux/kref.h> +#include <linux/kobject.h> +#include <linux/sysdev.h> #include <linux/seq_file.h> #include <linux/err.h> #include <linux/platform_device.h> @@ -239,6 +241,35 @@ void clk_recalc_rate(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_recalc_rate); +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret = -EINVAL; + struct clk *old; + + if (!parent || !clk) + return ret; + + old = clk->parent; + if (likely(clk->ops && clk->ops->set_parent)) { + unsigned long flags; + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_parent(clk, parent); + spin_unlock_irqrestore(&clock_lock, flags); + clk->parent = (ret ? old : parent); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} +EXPORT_SYMBOL_GPL(clk_get_parent); + long clk_round_rate(struct clk *clk, unsigned long rate) { if (likely(clk->ops && clk->ops->round_rate)) { @@ -329,6 +360,70 @@ static int show_clocks(char *buf, char **start, off_t off, return p - buf; } +#ifdef CONFIG_PM +static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) +{ + static pm_message_t prev_state; + struct clk *clkp; + + switch (state.event) { + case PM_EVENT_ON: + /* Resumeing from hibernation */ + if (prev_state.event == PM_EVENT_FREEZE) { + list_for_each_entry(clkp, &clock_list, node) + if (likely(clkp->ops)) { + unsigned long rate = clkp->rate; + + if (likely(clkp->ops->set_parent)) + clkp->ops->set_parent(clkp, + clkp->parent); + if (likely(clkp->ops->set_rate)) + clkp->ops->set_rate(clkp, + rate, NO_CHANGE); + else if (likely(clkp->ops->recalc)) + clkp->ops->recalc(clkp); + } + } + break; + case PM_EVENT_FREEZE: + break; + case PM_EVENT_SUSPEND: + break; + } + + prev_state = state; + return 0; +} + +static int clks_sysdev_resume(struct sys_device *dev) +{ + return clks_sysdev_suspend(dev, PMSG_ON); +} + +static struct sysdev_class clks_sysdev_class = { + .name = "clks", +}; + +static struct sysdev_driver clks_sysdev_driver = { + .suspend = clks_sysdev_suspend, + .resume = clks_sysdev_resume, +}; + +static struct sys_device clks_sysdev_dev = { + .cls = &clks_sysdev_class, +}; + +static int __init clk_sysdev_init(void) +{ + sysdev_class_register(&clks_sysdev_class); + sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); + sysdev_register(&clks_sysdev_dev); + + return 0; +} +subsys_initcall(clk_sysdev_init); +#endif + int __init clk_init(void) { int i, ret = 0; |