Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1375414 > unrolled thread

[PATCH v1] clk: Add clk_composite_set_rate_and_parent

Started byFinlye Xiao <finley.xiao@rock-chips.com>
First post2016-04-11 04:00 +0200
Last post2016-04-12 10:50 +0200
Articles 5 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v1] clk: Add clk_composite_set_rate_and_parent Finlye Xiao <finley.xiao@rock-chips.com> - 2016-04-11 04:00 +0200
    Re: [PATCH v1] clk: Add clk_composite_set_rate_and_parent Heiko Stuebner <heiko@sntech.de> - 2016-04-12 07:10 +0200
      Re: [PATCH v1] clk: Add clk_composite_set_rate_and_parent Stephen Boyd <sboyd@codeaurora.org> - 2016-04-14 02:50 +0200
        Re: [PATCH v1] clk: Add clk_composite_set_rate_and_parent Heiko Stübner <heiko@sntech.de> - 2016-04-14 07:00 +0200
    [PATCH v2] clk: Add clk_composite_set_rate_and_parent Finlye Xiao <finley.xiao@rock-chips.com> - 2016-04-12 10:50 +0200

#1375414 — [PATCH v1] clk: Add clk_composite_set_rate_and_parent

FromFinlye Xiao <finley.xiao@rock-chips.com>
Date2016-04-11 04:00 +0200
Subject[PATCH v1] clk: Add clk_composite_set_rate_and_parent
Message-ID<rmziV-6fG-7@gated-at.bofh.it>
From: Finley Xiao <finley.xiao@rock-chips.com>

Some of Rockchip's clocks should consider the priority of .set_parent
and .set_rate to prevent a too large temporary clock rate.

For example, the gpu clock can be parented to cpll(750MHz) and
usbphy_480m(480MHz), 375MHz comes from cpll and the div is set
to 2, 480MHz comes from usbphy_480m and the div is set to 1.

From the code, when change rate from 480MHz to 375MHz, it changes
the gpu's parent from USBPHY_480M to cpll first(.set_parent), but the
div value is still 1 and the gpu's rate will be 750MHz at the moment,
then it changes the div value from 1 to 2(.set_rate) and the gpu's
rate will be changed to 375MHz(480MHZ->750MHz->375MHz), here temporary
rate is 750MHz, the voltage which supply for 480MHz certainly can not
supply for 750MHz, so the gpu will crash.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
---
 drivers/clk/clk-composite.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 1f903e1f8..4d4b5ab 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -151,6 +151,33 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
 	return rate_ops->set_rate(rate_hw, rate, parent_rate);
 }
 
+static int clk_composite_set_rate_and_parent(struct clk_hw *hw,
+					     unsigned long rate,
+					     unsigned long parent_rate,
+					     u8 index)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk_hw *rate_hw = composite->rate_hw;
+	struct clk_hw *mux_hw = composite->mux_hw;
+	unsigned long temp_rate;
+
+	__clk_hw_set_clk(rate_hw, hw);
+	__clk_hw_set_clk(mux_hw, hw);
+
+	temp_rate = rate_ops->recalc_rate(rate_hw, parent_rate);
+	if (temp_rate > rate) {
+		rate_ops->set_rate(rate_hw, rate, parent_rate);
+		mux_ops->set_parent(mux_hw, index);
+	} else {
+		mux_ops->set_parent(mux_hw, index);
+		rate_ops->set_rate(rate_hw, rate, parent_rate);
+	}
+
+	return 0;
+}
+
 static int clk_composite_is_enabled(struct clk_hw *hw)
 {
 	struct clk_composite *composite = to_clk_composite(hw);
@@ -250,6 +277,12 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 		composite->rate_ops = rate_ops;
 	}
 
+	if (mux_hw && mux_ops && rate_hw && rate_ops) {
+		if (mux_ops->set_parent && rate_ops->set_rate)
+			clk_composite_ops->set_rate_and_parent =
+			clk_composite_set_rate_and_parent;
+	}
+
 	if (gate_hw && gate_ops) {
 		if (!gate_ops->is_enabled || !gate_ops->enable ||
 		    !gate_ops->disable) {
-- 
1.9.1

[toc] | [next] | [standalone]


#1376460

FromHeiko Stuebner <heiko@sntech.de>
Date2016-04-12 07:10 +0200
Message-ID<rmYKm-1Bq-1@gated-at.bofh.it>
In reply to#1375414
Hi Finley,

Am Montag, 11. April 2016, 09:54:12 schrieb Finlye Xiao:
> From: Finley Xiao <finley.xiao@rock-chips.com>
> 
> Some of Rockchip's clocks should consider the priority of .set_parent
> and .set_rate to prevent a too large temporary clock rate.
> 
> For example, the gpu clock can be parented to cpll(750MHz) and
> usbphy_480m(480MHz), 375MHz comes from cpll and the div is set
> to 2, 480MHz comes from usbphy_480m and the div is set to 1.
> 
> From the code, when change rate from 480MHz to 375MHz, it changes
> the gpu's parent from USBPHY_480M to cpll first(.set_parent), but the
> div value is still 1 and the gpu's rate will be 750MHz at the moment,
> then it changes the div value from 1 to 2(.set_rate) and the gpu's
> rate will be changed to 375MHz(480MHZ->750MHz->375MHz), here temporary
> rate is 750MHz, the voltage which supply for 480MHz certainly can not
> supply for 750MHz, so the gpu will crash.

We did talk about this internally and while we refined the actual code 
change, it seems I forgot to look at the commit message itself.

This behaviour (and the wish to not overflow a target clock rate) should be 
the same on all socs, so the commit message is quite a bit to Rockchip 
specific. I think I would go with something like:

----------- 8< ------------
When changing the clock-rate, currently a new parent is set first and a 
divider adapted thereafter. This may result in the clock-rate overflowing
its target rate for a short time if the new parent has a higher rate than
the old parent.

While this often doesn't produce negative effects, it can affect components
in a voltage-scaling environment, like the GPU on the rk3399 socs, where the
voltage than simply is to low for the temporarily to high clock rate.

For general clock hirarchies this may need more extensive adaptions to
the common clock-framework, but at least for composite clocks having
both parent and rate settings it is easy to create a short-term solution to
make sure the clock-rate does not overflow the target.
----------- 8< ------------

But of course feel free to extend or change that as you wish ;-) .


> 
> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>

I remember having clocks not overflow their target rate came up in some ELC 
talk last week (probably in Stephens Qualcomm-kernel-talk) and a general 
solution might need some changes closer to the core.

But at least for composite clocks where we can control the rate+parent 
process easily, Finley's change is a nice low-hanging fruit which at least 
improves behaviour for those clock-types in the short term, so

Reviewed-by: Heiko Stuebner <heiko@sntech.de>


Heiko

[toc] | [prev] | [next] | [standalone]


#1378374

FromStephen Boyd <sboyd@codeaurora.org>
Date2016-04-14 02:50 +0200
Message-ID<rnDDP-1uB-13@gated-at.bofh.it>
In reply to#1376460
On 04/12, Heiko Stuebner wrote:
> 
> I remember having clocks not overflow their target rate came up in some ELC 
> talk last week (probably in Stephens Qualcomm-kernel-talk) and a general 
> solution might need some changes closer to the core.

Yep. It's on the list. Hopefully coordinated clk rate changes
will help here. Composite clks are sort of already coordinated
rates in a minor form though.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

[toc] | [prev] | [next] | [standalone]


#1378478

FromHeiko Stübner <heiko@sntech.de>
Date2016-04-14 07:00 +0200
Message-ID<rnHxM-4xJ-9@gated-at.bofh.it>
In reply to#1378374
Am Mittwoch, 13. April 2016, 17:43:31 schrieb Stephen Boyd:
> On 04/12, Heiko Stuebner wrote:
> > I remember having clocks not overflow their target rate came up in some
> > ELC
> > talk last week (probably in Stephens Qualcomm-kernel-talk) and a general
> > solution might need some changes closer to the core.
> 
> Yep. It's on the list. Hopefully coordinated clk rate changes
> will help here. Composite clks are sort of already coordinated
> rates in a minor form though.

Which is why I hope we can land this (meaning v2 from tuesday) in the 
meantime, as it fixes an issue we're seeing on the rk3399 and shouldn't affect 
any part of the core clock-framework ;-) .


Heiko

[toc] | [prev] | [next] | [standalone]


#1376566 — [PATCH v2] clk: Add clk_composite_set_rate_and_parent

FromFinlye Xiao <finley.xiao@rock-chips.com>
Date2016-04-12 10:50 +0200
Subject[PATCH v2] clk: Add clk_composite_set_rate_and_parent
Message-ID<rn2bg-49J-5@gated-at.bofh.it>
In reply to#1375414
From: Finley Xiao <finley.xiao@rock-chips.com>

When changing the clock-rate, currently a new parent is set first and a
divider adapted thereafter. This may result in the clock-rate overflowing
its target rate for a short time if the new parent has a higher rate than
the old parent.

While this often doesn't produce negative effects, it can affect components
in a voltage-scaling environment, like the GPU on the rk3399 socs, where
the voltage than simply is to low for the temporarily to high clock rate.

For general clock hirarchies this may need more extensive adaptions to
the common clock-framework, but at least for composite clocks having
both parent and rate settings it is easy to create a short-term solution to
make sure the clock-rate does not overflow the target.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
---
v1->v2:
- change the commit message

 drivers/clk/clk-composite.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 1f903e1f8..4d4b5ab 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -151,6 +151,33 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
 	return rate_ops->set_rate(rate_hw, rate, parent_rate);
 }
 
+static int clk_composite_set_rate_and_parent(struct clk_hw *hw,
+					     unsigned long rate,
+					     unsigned long parent_rate,
+					     u8 index)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk_hw *rate_hw = composite->rate_hw;
+	struct clk_hw *mux_hw = composite->mux_hw;
+	unsigned long temp_rate;
+
+	__clk_hw_set_clk(rate_hw, hw);
+	__clk_hw_set_clk(mux_hw, hw);
+
+	temp_rate = rate_ops->recalc_rate(rate_hw, parent_rate);
+	if (temp_rate > rate) {
+		rate_ops->set_rate(rate_hw, rate, parent_rate);
+		mux_ops->set_parent(mux_hw, index);
+	} else {
+		mux_ops->set_parent(mux_hw, index);
+		rate_ops->set_rate(rate_hw, rate, parent_rate);
+	}
+
+	return 0;
+}
+
 static int clk_composite_is_enabled(struct clk_hw *hw)
 {
 	struct clk_composite *composite = to_clk_composite(hw);
@@ -250,6 +277,12 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 		composite->rate_ops = rate_ops;
 	}
 
+	if (mux_hw && mux_ops && rate_hw && rate_ops) {
+		if (mux_ops->set_parent && rate_ops->set_rate)
+			clk_composite_ops->set_rate_and_parent =
+			clk_composite_set_rate_and_parent;
+	}
+
 	if (gate_hw && gate_ops) {
 		if (!gate_ops->is_enabled || !gate_ops->enable ||
 		    !gate_ops->disable) {
-- 
1.9.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web