From patchwork Mon Jan 25 13:15:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 8108581 Return-Path: X-Original-To: patchwork-linux-arm@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 3EDF0BEEE5 for ; Mon, 25 Jan 2016 13:19:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5736A202F0 for ; Mon, 25 Jan 2016 13:19:19 +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 7B2C0202EB for ; Mon, 25 Jan 2016 13:19:18 +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 1aNh1i-0006yN-L6; Mon, 25 Jan 2016 13:17:50 +0000 Received: from smtp.csie.ntu.edu.tw ([140.112.30.61]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aNh0h-0006Dt-GX for linux-arm-kernel@lists.infradead.org; Mon, 25 Jan 2016 13:16:54 +0000 Received: from wens.csie.org (mirror2.csie.ntu.edu.tw [140.112.30.76]) (Authenticated sender: b93043) by smtp.csie.ntu.edu.tw (Postfix) with ESMTPSA id 7CC4221B8D; Mon, 25 Jan 2016 21:16:04 +0800 (CST) Received: by wens.csie.org (Postfix, from userid 1000) id 05F685F8B4; Mon, 25 Jan 2016 21:16:04 +0800 (CST) From: Chen-Yu Tsai To: Maxime Ripard , Michael Turquette , Stephen Boyd Subject: [PATCH RFC 07/11] clk: sunxi: factors: Support custom formulas Date: Mon, 25 Jan 2016 21:15:43 +0800 Message-Id: <1453727747-23307-8-git-send-email-wens@csie.org> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1453727747-23307-1-git-send-email-wens@csie.org> References: <1453727747-23307-1-git-send-email-wens@csie.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160125_051648_356129_00E2BA0C X-CRM114-Status: GOOD ( 13.15 ) X-Spam-Score: -4.2 (----) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Vishnu Patekar , Chen-Yu Tsai , linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.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 Some clocks cannot be modelled using the standard factors clk formula, such as clocks with special pre-dividers on one parent, or clocks with all power-of-two dividers. Add support for a custom .recalc callback for factors clk. Also pass the current parent index to the .get_factor and .recalc callbacks. Signed-off-by: Chen-Yu Tsai --- drivers/clk/sunxi/clk-factors.c | 30 ++++++++++++++++++++++++++++-- drivers/clk/sunxi/clk-factors.h | 3 +++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 47b7d918b74c..ac259305d5d5 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -63,6 +63,26 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE) p = FACTOR_GET(config->pshift, config->pwidth, reg); + if (factors->recalc) { + struct factors_request factors_req = { + .parent_rate = parent_rate, + .n = n, + .k = k, + .m = m, + .p = p, + }; + + /* get mux details from mux clk structure */ + if (factors->mux) + factors_req.parent_index = + (reg >> factors->mux->shift) & + factors->mux->mask; + + factors->recalc(&factors_req); + + return factors_req.rate; + } + /* Calculate the rate */ rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1); @@ -87,6 +107,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, static int clk_factors_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { + struct clk_factors *factors = to_clk_factors(hw); struct clk_hw *parent, *best_parent = NULL; int i, num_parents; unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; @@ -94,6 +115,10 @@ static int clk_factors_determine_rate(struct clk_hw *hw, /* find the parent that can help provide the fastest rate <= rate */ num_parents = clk_hw_get_num_parents(hw); for (i = 0; i < num_parents; i++) { + struct factors_request factors_req = { + .rate = req->rate, + .parent_index = i, + }; parent = clk_hw_get_parent_by_index(hw, i); if (!parent) continue; @@ -102,8 +127,9 @@ static int clk_factors_determine_rate(struct clk_hw *hw, else parent_rate = clk_hw_get_rate(parent); - child_rate = clk_factors_round_rate(hw, req->rate, - &parent_rate); + factors_req.parent_rate = parent_rate; + factors->get_factors(&factors_req); + child_rate = factors_req.rate; if (child_rate <= req->rate && child_rate > best_child_rate) { best_parent = parent; diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index f09d7c214533..a44a865a6b9e 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h @@ -22,6 +22,7 @@ struct clk_factors_config { struct factors_request { unsigned long rate; unsigned long parent_rate; + u8 parent_index; u8 n; u8 k; u8 m; @@ -34,6 +35,7 @@ struct factors_data { int muxmask; const struct clk_factors_config *table; void (*getter)(struct factors_request *req); + void (*recalc)(struct factors_request *req); const char *name; }; @@ -42,6 +44,7 @@ struct clk_factors { void __iomem *reg; const struct clk_factors_config *config; void (*get_factors)(struct factors_request *req); + void (*recalc)(struct factors_request *req); spinlock_t *lock; /* for cleanup */ struct clk_mux *mux;