diff options
author | Alex Frid <afrid@nvidia.com> | 2011-06-11 23:23:50 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:47:09 -0800 |
commit | f1537051a8d40aacd5a3b75e09044a3b8c0ede27 (patch) | |
tree | 4787bfc05f770fe0998fa6a72a3fc5d32636518d | |
parent | 4e8c72b0280cba496c8397b80c363deebdd88717 (diff) |
ARM: tegra: clock: Add clock rate change notification
Original-Change-Id: I97434334a4214180a365d9709a331405da135669
Reviewed-on: http://git-master/r/36202
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Rebase-Id: R7bfea35bf7b2e083e594538e245e3b74e25d090a
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 40 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/clk.h | 4 |
3 files changed, 46 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 294c289b6a21..e508c65bd8e6 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -324,6 +324,13 @@ void clk_disable(struct clk *c) } EXPORT_SYMBOL(clk_disable); +static int clk_rate_change_notify(struct clk *c, unsigned long rate) +{ + if (!c->rate_change_nh) + return -ENOSYS; + return raw_notifier_call_chain(c->rate_change_nh, rate, NULL); +} + int clk_set_parent(struct clk *c, struct clk *parent) { int ret = 0; @@ -381,6 +388,9 @@ int clk_set_parent(struct clk *c, struct clk *parent) new_rate < old_rate) ret = tegra_dvfs_set_rate(c, new_rate); + if (new_rate != old_rate) + clk_rate_change_notify(c, new_rate); + out: if (disable) clk_disable_locked(c); @@ -448,6 +458,9 @@ int clk_set_rate_locked(struct clk *c, unsigned long rate) if (clk_is_auto_dvfs(c) && rate < old_rate && c->refcnt > 0) ret = tegra_dvfs_set_rate(c, rate); + if (rate != old_rate) + clk_rate_change_notify(c, rate); + out: if (disable) clk_disable_locked(c); @@ -766,6 +779,33 @@ out: return ret; } +int tegra_register_clk_rate_notifier(struct clk *c, struct notifier_block *nb) +{ + int ret; + unsigned long flags; + + if (!c->rate_change_nh) + return -ENOSYS; + + clk_lock_save(c, &flags); + ret = raw_notifier_chain_register(c->rate_change_nh, nb); + clk_unlock_restore(c, &flags); + return ret; +} + +void tegra_unregister_clk_rate_notifier( + struct clk *c, struct notifier_block *nb) +{ + unsigned long flags; + + if (!c->rate_change_nh) + return; + + clk_lock_save(c, &flags); + raw_notifier_chain_unregister(c->rate_change_nh, nb); + clk_unlock_restore(c, &flags); +} + #ifdef CONFIG_DEBUG_FS /* diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index e7d93a5634a5..a2a2fb814fb0 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -184,6 +184,8 @@ struct clk { } shared_bus_user; } u; + struct raw_notifier_head *rate_change_nh; + struct mutex mutex; spinlock_t spinlock; }; diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index 3cc13f4ab68c..2cc8b84d845e 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h @@ -24,6 +24,7 @@ struct clk; struct dvfs; +struct notifier_block; enum tegra_clk_ex_param { TEGRA_CLK_VI_INP_SEL, @@ -53,5 +54,8 @@ static inline void tegra_sdmmc_tap_delay(struct clk *c, int delay) #endif int tegra_dvfs_rail_disable_by_name(const char *reg_id); int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting); +int tegra_register_clk_rate_notifier(struct clk *c, struct notifier_block *nb); +void tegra_unregister_clk_rate_notifier( + struct clk *c, struct notifier_block *nb); #endif |