summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-06-11 23:23:50 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:47:09 -0800
commitf1537051a8d40aacd5a3b75e09044a3b8c0ede27 (patch)
tree4787bfc05f770fe0998fa6a72a3fc5d32636518d
parent4e8c72b0280cba496c8397b80c363deebdd88717 (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.c40
-rw-r--r--arch/arm/mach-tegra/clock.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/clk.h4
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