linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] clk: Add notifier support in clk_prepare/clk_unprepare
@ 2013-03-19 13:28 Bill Huang
  2013-03-19 17:01 ` Mike Turquette
  0 siblings, 1 reply; 13+ messages in thread
From: Bill Huang @ 2013-03-19 13:28 UTC (permalink / raw)
  To: linux-arm-kernel

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-04-02  9:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-19 13:28 [PATCH 1/1] clk: Add notifier support in clk_prepare/clk_unprepare Bill Huang
2013-03-19 17:01 ` 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

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).