From patchwork Tue Apr 12 08:43:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Finley Xiao X-Patchwork-Id: 8807941 Return-Path: X-Original-To: patchwork-linux-rockchip@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B8967C0553 for ; Tue, 12 Apr 2016 08:47:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E25E9202F8 for ; Tue, 12 Apr 2016 08:47:10 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 109FD202D1 for ; Tue, 12 Apr 2016 08:47:10 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aptyV-0000fa-Lo; Tue, 12 Apr 2016 08:47:07 +0000 Received: from regular1.263xmail.com ([211.150.99.132]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aptyK-0000ck-Sj; Tue, 12 Apr 2016 08:46:57 +0000 Received: from finley.xiao?rock-chips.com (unknown [192.168.167.231]) by regular1.263xmail.com (Postfix) with SMTP id E7BF18DEB; Tue, 12 Apr 2016 16:46:25 +0800 (CST) X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ABS-CHECKED: 4 X-ADDR-CHECKED: 0 X-KSVirus-check: 0 Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.263.net (Postfix) with ESMTP id 2B92B57ACA; Tue, 12 Apr 2016 16:45:49 +0800 (CST) X-RL-SENDER: finley.xiao@rock-chips.com X-FST-TO: mturquette@baylibre.com X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: finley.xiao@rock-chips.com X-UNIQUE-TAG: <2525620c14c27be6fff7f40902cfd16a> X-ATTACHMENT-NUM: 0 X-SENDER: xf@rock-chips.com X-DNS-TYPE: 0 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (Postfix) whith ESMTP id 23885VMU74R; Tue, 12 Apr 2016 16:46:23 +0800 (CST) From: Finlye Xiao To: mturquette@baylibre.com, sboyd@codeaurora.org, heiko@sntech.de Subject: [PATCH v2] clk: Add clk_composite_set_rate_and_parent Date: Tue, 12 Apr 2016 16:43:39 +0800 Message-Id: <1460450619-1118-1-git-send-email-finley.xiao@rock-chips.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1460339652-63498-1-git-send-email-finley.xiao@rock-chips.com> References: <1460339652-63498-1-git-send-email-finley.xiao@rock-chips.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160412_014657_430194_57A390AF X-CRM114-Status: UNSURE ( 9.59 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -2.6 (--) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: huangtao@rock-chips.com, zhengxing@rock-chips.com, xxx@rock-chips.com, zhangqing@rock-chips.com, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, Finley Xiao , zyw@rock-chips.com, jay.xu@rock-chips.com, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, wxt@rock-chips.com MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Finley Xiao 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 Reviewed-by: Heiko Stuebner --- 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) {