linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dong Aisheng <aisheng.dong@nxp.com>
To: <linux-clk@vger.kernel.org>
Cc: <linux-kernel@vger.kernel.org>, <sboyd@codeaurora.org>,
	<mturquette@baylibre.com>, <shawnguo@kernel.org>,
	<linux-arm-kernel@lists.infradead.org>, <tglx@linutronix.de>,
	<aisheng.dong@nxp.com>, <stefan@agner.ch>,
	<l.stach@pengutronix.de>, <cyrille.pitchen@atmel.com>,
	<manabian@gmail.com>, <anson.huang@nxp.com>
Subject: [PATCH RFC 2/7] clk: add set_rate_hw and set_rate_done
Date: Wed, 29 Jun 2016 21:52:10 +0800	[thread overview]
Message-ID: <1467208335-29876-3-git-send-email-aisheng.dong@nxp.com> (raw)
In-Reply-To: <1467208335-29876-1-git-send-email-aisheng.dong@nxp.com>

Introduce set_rate_hw and set_rate_done to support setting rate
in early kernel booting where we still can't schedule.

Change the rate of this clock hw. This callback is intended
to do the hw part setting of @set_rate work. It should
cooperate with @set_rate_done callback to do the whole
set rate work. The clock core will check @set_rate_done in
either sleep or polling way according to system state to
decide whether the whole set rate work is done.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
 drivers/clk/clk.c            | 32 ++++++++++++++++++++++++++++++--
 include/linux/clk-provider.h | 15 +++++++++++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 7dcb34c75a9f..0d031b280c9a 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1471,8 +1471,10 @@ static void clk_change_rate(struct clk_core *core)
 	struct hlist_node *tmp;
 	unsigned long old_rate;
 	unsigned long best_parent_rate = 0;
+	unsigned long timeout;
 	bool skip_set_rate = false;
 	struct clk_core *old_parent;
+	int ret;
 
 	old_rate = core->rate;
 
@@ -1509,8 +1511,34 @@ static void clk_change_rate(struct clk_core *core)
 
 	trace_clk_set_rate(core, core->new_rate);
 
-	if (!skip_set_rate && core->ops->set_rate)
-		core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
+	if (!skip_set_rate) {
+		if (core->ops->set_rate) {
+			core->ops->set_rate(core->hw, core->new_rate,
+					    best_parent_rate);
+		} else if (core->ops->set_rate_hw) {
+			ret = core->ops->set_rate_hw(core->hw, core->new_rate,
+						     best_parent_rate);
+			if (!ret && core->ops->set_rate_done) {
+				timeout = jiffies + msecs_to_jiffies(10);
+				while (!core->ops->set_rate_done(core->hw)) {
+					if (time_after(jiffies, timeout)) {
+						pr_err("%s: clock %s set rate timeout\n",
+							__func__, core->name);
+						break;
+					}
+					if (system_state == SYSTEM_BOOTING)
+						/*
+						 * Busy loop as we can't
+						 * schedule in early boot
+						 */
+						continue;
+					else
+						usleep_range(core->delay_min,
+							     core->delay_max);
+				}
+			}
+		}
+	}
 
 	trace_clk_set_rate_complete(core, core->new_rate);
 
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b37174360f1c..3dcb99ad6bd2 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -162,6 +162,18 @@ struct clk_rate_request {
  *		which is likely helpful for most .set_rate implementation.
  *		Returns 0 on success, -EERROR otherwise.
  *
+ * @set_rate_hw: Change the rate of this clock hw. This callback is intended
+ *		to do the hw part setting of @set_rate work. It should
+ *		cooperate with @set_rate_done callback to do the whole
+ *		set rate work. The clock core will check @set_rate_done in
+ *		either sleep or polling way according to system state to
+ *		decide whether the whole set rate work is done. Optional
+ *		if @set_rate is used. This function must not sleep.
+ *
+ * @set_rate_done: Queries the hardware to determine if the clock hw is
+ *		prepared. Optional, if this op is not set then the set rate
+ *		simply return. This function must not sleep.
+ *
  * @set_rate_and_parent: Change the rate and the parent of this clock. The
  *		requested rate is specified by the second argument, which
  *		should typically be the return of .round_rate call.  The
@@ -234,6 +246,9 @@ struct clk_ops {
 	u8		(*get_parent)(struct clk_hw *hw);
 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
 				    unsigned long parent_rate);
+	int		(*set_rate_hw)(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate);
+	int		(*set_rate_done)(struct clk_hw *hw);
 	int		(*set_rate_and_parent)(struct clk_hw *hw,
 				    unsigned long rate,
 				    unsigned long parent_rate, u8 index);
-- 
1.9.1

  parent reply	other threads:[~2016-06-29 13:52 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-29 13:52 [PATCH RFC 0/7] support clk setting during kernel early boot Dong Aisheng
2016-06-29 13:52 ` [PATCH RFC 1/7] clk: add prepare_hw and prepare_done support Dong Aisheng
2016-07-05 19:53   ` Grygorii Strashko
2016-06-29 13:52 ` Dong Aisheng [this message]
2016-06-29 13:52 ` [PATCH RFC 3/7] clk: add set_parent_hw and set_parent_done Dong Aisheng
2016-06-29 13:52 ` [PATCH RFC 4/7] PM: add SYSTEM_SUSPEND system_state Dong Aisheng
2016-06-29 13:52 ` [PATCH RFC 5/7] clk: use polling way for SYSTEM_SUSPEND state too Dong Aisheng
2016-06-29 13:52 ` [PATCH RFC 6/7] clk: imx: pllv3: convert to prepare_hw and set_rate_hw Dong Aisheng
2016-07-02 20:30   ` Fabio Estevam
2016-06-29 13:52 ` [PATCH RFC 7/7] clk: imx: clk-busy: convert to set_rate_hw and set_parent_hw Dong Aisheng
2016-07-02  1:12 ` [PATCH RFC 0/7] support clk setting during kernel early boot Stephen Boyd
2016-07-02 23:12   ` Stefan Agner
2016-07-03 12:05     ` Fabio Estevam

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=1467208335-29876-3-git-send-email-aisheng.dong@nxp.com \
    --to=aisheng.dong@nxp.com \
    --cc=anson.huang@nxp.com \
    --cc=cyrille.pitchen@atmel.com \
    --cc=l.stach@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=manabian@gmail.com \
    --cc=mturquette@baylibre.com \
    --cc=sboyd@codeaurora.org \
    --cc=shawnguo@kernel.org \
    --cc=stefan@agner.ch \
    --cc=tglx@linutronix.de \
    /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).