From: bilhuang@nvidia.com (Bill Huang)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/1] clk: Add notifier support in clk_prepare/clk_unprepare
Date: Tue, 19 Mar 2013 06:28:32 -0700 [thread overview]
Message-ID: <1363699712-8124-1-git-send-email-bilhuang@nvidia.com> (raw)
Add notifier calls in clk_prepare and clk_unprepare so drivers which are
interested in knowing that clk_prepare/unprepare call can act accordingly.
The existing "clk_set_rate" notifier is not enough for normal DVFS
inplementation since clock might be enabled/disabled at runtime. Adding
these notifiers is useful on DVFS core which take clk_prepare as a hint
on that the notified clock might be enabled later so it can raise voltage
to a safe level before enabling the clock, and take clk_unprepare as a
hint that the clock has been disabled and is safe to lower the voltage.
The added notifier events are:
PRE_CLK_PREPARE
POST_CLK_PREPARE
ABORT_CLK_PREPARE
PRE_CLK_UNPREPARE
POST_CLK_UNPREPARE
Signed-off-by: Bill Huang <bilhuang@nvidia.com>
---
drivers/clk/clk.c | 88 ++++++++++++++++++++++++++++++---------------------
include/linux/clk.h | 5 +++
2 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ed87b24..ac07c6e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -516,6 +516,42 @@ struct clk *__clk_lookup(const char *name)
/*** clk api ***/
+/**
+ * __clk_notify - call clk notifier chain
+ * @clk: struct clk * that is changing rate
+ * @msg: clk notifier type (see include/linux/clk.h)
+ * @old_rate: old clk rate
+ * @new_rate: new clk rate
+ *
+ * Triggers a notifier call chain on the clk rate-change notification
+ * for 'clk'. Passes a pointer to the struct clk and the previous
+ * and current rates to the notifier callback. Intended to be called by
+ * internal clock code only. Returns NOTIFY_DONE from the last driver
+ * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
+ * a driver returns that.
+ */
+static int __clk_notify(struct clk *clk, unsigned long msg,
+ unsigned long old_rate, unsigned long new_rate)
+{
+ struct clk_notifier *cn;
+ struct clk_notifier_data cnd;
+ int ret = NOTIFY_DONE;
+
+ cnd.clk = clk;
+ cnd.old_rate = old_rate;
+ cnd.new_rate = new_rate;
+
+ list_for_each_entry(cn, &clk_notifier_list, node) {
+ if (cn->clk == clk) {
+ ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
+ &cnd);
+ break;
+ }
+ }
+
+ return ret;
+}
+
void __clk_unprepare(struct clk *clk)
{
if (!clk)
@@ -549,7 +585,14 @@ void __clk_unprepare(struct clk *clk)
void clk_unprepare(struct clk *clk)
{
mutex_lock(&prepare_lock);
+
+ if (clk->notifier_count)
+ __clk_notify(clk, PRE_CLK_UNPREPARE, clk->rate, clk->rate);
+
__clk_unprepare(clk);
+ if (clk->notifier_count)
+ __clk_notify(clk, POST_CLK_UNPREPARE, clk->rate, clk->rate);
+
mutex_unlock(&prepare_lock);
}
EXPORT_SYMBOL_GPL(clk_unprepare);
@@ -597,7 +640,16 @@ int clk_prepare(struct clk *clk)
int ret;
mutex_lock(&prepare_lock);
+
+ if (clk->notifier_count)
+ __clk_notify(clk, PRE_CLK_PREPARE, clk->rate, clk->rate);
+
ret = __clk_prepare(clk);
+ if (!ret && clk->notifier_count)
+ __clk_notify(clk, POST_CLK_PREPARE, clk->rate, clk->rate);
+ else if (clk->notifier_count)
+ __clk_notify(clk, ABORT_CLK_PREPARE, clk->rate, clk->rate);
+
mutex_unlock(&prepare_lock);
return ret;
@@ -749,42 +801,6 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
EXPORT_SYMBOL_GPL(clk_round_rate);
/**
- * __clk_notify - call clk notifier chain
- * @clk: struct clk * that is changing rate
- * @msg: clk notifier type (see include/linux/clk.h)
- * @old_rate: old clk rate
- * @new_rate: new clk rate
- *
- * Triggers a notifier call chain on the clk rate-change notification
- * for 'clk'. Passes a pointer to the struct clk and the previous
- * and current rates to the notifier callback. Intended to be called by
- * internal clock code only. Returns NOTIFY_DONE from the last driver
- * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
- * a driver returns that.
- */
-static int __clk_notify(struct clk *clk, unsigned long msg,
- unsigned long old_rate, unsigned long new_rate)
-{
- struct clk_notifier *cn;
- struct clk_notifier_data cnd;
- int ret = NOTIFY_DONE;
-
- cnd.clk = clk;
- cnd.old_rate = old_rate;
- cnd.new_rate = new_rate;
-
- list_for_each_entry(cn, &clk_notifier_list, node) {
- if (cn->clk == clk) {
- ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
- &cnd);
- break;
- }
- }
-
- return ret;
-}
-
-/**
* __clk_recalc_rates
* @clk: first clk in the subtree
* @msg: notification type (see include/linux/clk.h)
diff --git a/include/linux/clk.h b/include/linux/clk.h
index b3ac22d..41d567d 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -43,6 +43,11 @@ struct clk;
#define PRE_RATE_CHANGE BIT(0)
#define POST_RATE_CHANGE BIT(1)
#define ABORT_RATE_CHANGE BIT(2)
+#define PRE_CLK_PREPARE BIT(3)
+#define POST_CLK_PREPARE BIT(4)
+#define ABORT_CLK_PREPARE BIT(5)
+#define PRE_CLK_UNPREPARE BIT(6)
+#define POST_CLK_UNPREPARE BIT(7)
/**
* struct clk_notifier - associate a clk with a notifier
--
1.7.9.5
next reply other threads:[~2013-03-19 13:28 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-19 13:28 Bill Huang [this message]
2013-03-19 17:01 ` [PATCH 1/1] clk: Add notifier support in clk_prepare/clk_unprepare Mike Turquette
2013-03-20 2:55 ` Bill Huang
2013-03-20 3:31 ` Mike Turquette
2013-03-20 4:39 ` Bill Huang
2013-03-20 14:47 ` Mike Turquette
2013-03-20 21:06 ` Ulf Hansson
2013-03-21 22:36 ` Mike Turquette
2013-03-22 0:06 ` Colin Cross
2013-03-28 22:01 ` Mike Turquette
2013-03-28 22:24 ` Stephen Warren
2013-04-02 9:53 ` Peter De Schrijver
2013-03-21 1:03 ` Bill Huang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1363699712-8124-1-git-send-email-bilhuang@nvidia.com \
--to=bilhuang@nvidia.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).