From patchwork Mon Nov 7 11:24:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ritesh Harjani X-Patchwork-Id: 9414745 X-Patchwork-Delegate: sboyd@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0534660512 for ; Mon, 7 Nov 2016 11:25:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E802C28BBB for ; Mon, 7 Nov 2016 11:25:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DA28728BCC; Mon, 7 Nov 2016 11:25:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4709428BBB for ; Mon, 7 Nov 2016 11:25:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752250AbcKGLZk (ORCPT ); Mon, 7 Nov 2016 06:25:40 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:60180 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751296AbcKGLZj (ORCPT ); Mon, 7 Nov 2016 06:25:39 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id C01FB61281; Mon, 7 Nov 2016 11:25:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1478517938; bh=Uq65/FNcAqU6CWPSgEpuLEF84He5bllFdwdfFmAlpTo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TLk5UHWn7a2qZRclNSi+adzkGw7Wv/nhunh5qxI7CwPdCVTvJpbh3Wh+u7nHy8cNP Xd5441rrfKWHvftQtHm+ISaW5zqkP2RLP4PEkMsYKsiIpXvGcelT0li5Gtp4vfh9J+ VijQpPNEf/WSef3e/mkiDHSmlrJ8siYeKIO0k34Q= Received: from rharjani-linux.qualcomm.com (unknown [202.46.23.54]) (using TLSv1.1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: riteshh@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 47C3561258; Mon, 7 Nov 2016 11:25:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1478517937; bh=Uq65/FNcAqU6CWPSgEpuLEF84He5bllFdwdfFmAlpTo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HBvIYDxMxAQLQF212Zahx5vTH31eaFyopR4gRUDim7YXR3N4/dy/KMXiSnGJzkuDI eQHMl+3DERwQzfD9c968xwv5BuCnd5UiujptifvH6QhHU/WyDHtSKXbmhaYMIb8WOS CvTRWXtbASTM1bLnH1TcFl72MawF0J80Hgg8L+tg= DMARC-Filter: OpenDMARC Filter v1.3.1 smtp.codeaurora.org 47C3561258 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=pass smtp.mailfrom=riteshh@codeaurora.org From: Ritesh Harjani To: ulf.hansson@linaro.org, linux-mmc@vger.kernel.org, adrian.hunter@intel.com, shawn.lin@rock-chips.com, sboyd@codeaurora.org Cc: devicetree@vger.kernel.org, linux-clk@vger.kernel.org, david.brown@linaro.org, andy.gross@linaro.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org, alex.lemberg@sandisk.com, mateusz.nowak@intel.com, Yuliy.Izrailov@sandisk.com, asutoshd@codeaurora.org, kdorfman@codeaurora.org, david.griego@linaro.org, stummala@codeaurora.org, venkatg@codeaurora.org, rnayak@codeaurora.org, pramod.gurav@linaro.org Subject: [PATCH v6 02/14] clk: qcom: Add rcg ops to return floor value closest to the requested rate Date: Mon, 7 Nov 2016 16:54:25 +0530 Message-Id: <1478517877-23733-3-git-send-email-riteshh@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org> References: <1478517877-23733-1-git-send-email-riteshh@codeaurora.org> Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rajendra Nayak The default behaviour with clk_rcg2_ops is for the clk_round_rate()/clk_set_rate() to return/set a ceil clock rate closest to the requested rate by looking up the corresponding frequency table. However, we do have some instances (mainly sdcc on various platforms) of clients expecting a clk_set_rate() to set a floor value instead. Add a new clk_rcg2_floor_ops to handle this for such specific rcg instances Signed-off-by: Rajendra Nayak --- drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/clk-rcg2.c | 75 +++++++++++++++++++++++++++++++++++++++------ drivers/clk/qcom/common.c | 26 ++++++++++++++++ drivers/clk/qcom/common.h | 2 ++ 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index b904c33..1b3e8d2 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -173,6 +173,7 @@ struct clk_rcg2 { #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) extern const struct clk_ops clk_rcg2_ops; +extern const struct clk_ops clk_rcg2_floor_ops; extern const struct clk_ops clk_rcg2_shared_ops; extern const struct clk_ops clk_edp_pixel_ops; extern const struct clk_ops clk_byte_ops; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index a071bba..04433a6 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -47,6 +47,11 @@ #define N_REG 0xc #define D_REG 0x10 +enum { + FLOOR, + CEIL, +}; + static int clk_rcg2_is_enabled(struct clk_hw *hw) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); @@ -176,15 +181,25 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index) return calc_rate(parent_rate, m, n, mode, hid_div); } -static int _freq_tbl_determine_rate(struct clk_hw *hw, - const struct freq_tbl *f, struct clk_rate_request *req) +static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, + struct clk_rate_request *req, bool match) { unsigned long clk_flags, rate = req->rate; struct clk_hw *p; struct clk_rcg2 *rcg = to_clk_rcg2(hw); int index; - f = qcom_find_freq(f, rate); + switch (match) { + case FLOOR: + f = qcom_find_freq_floor(f, rate); + break; + case CEIL: + f = qcom_find_freq(f, rate); + break; + default: + return -EINVAL; + }; + if (!f) return -EINVAL; @@ -221,7 +236,15 @@ static int clk_rcg2_determine_rate(struct clk_hw *hw, { struct clk_rcg2 *rcg = to_clk_rcg2(hw); - return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req); + return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, CEIL); +} + +static int clk_rcg2_determine_floor_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR); } static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) @@ -265,12 +288,23 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) return update_config(rcg); } -static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) +static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, + bool match) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); const struct freq_tbl *f; - f = qcom_find_freq(rcg->freq_tbl, rate); + switch (match) { + case FLOOR: + f = qcom_find_freq_floor(rcg->freq_tbl, rate); + break; + case CEIL: + f = qcom_find_freq(rcg->freq_tbl, rate); + break; + default: + return -EINVAL; + }; + if (!f) return -EINVAL; @@ -280,13 +314,25 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - return __clk_rcg2_set_rate(hw, rate); + return __clk_rcg2_set_rate(hw, rate, CEIL); +} + +static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return __clk_rcg2_set_rate(hw, rate, FLOOR); } static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index) { - return __clk_rcg2_set_rate(hw, rate); + return __clk_rcg2_set_rate(hw, rate, CEIL); +} + +static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate, u8 index) +{ + return __clk_rcg2_set_rate(hw, rate, FLOOR); } const struct clk_ops clk_rcg2_ops = { @@ -300,6 +346,17 @@ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw, }; EXPORT_SYMBOL_GPL(clk_rcg2_ops); +const struct clk_ops clk_rcg2_floor_ops = { + .is_enabled = clk_rcg2_is_enabled, + .get_parent = clk_rcg2_get_parent, + .set_parent = clk_rcg2_set_parent, + .recalc_rate = clk_rcg2_recalc_rate, + .determine_rate = clk_rcg2_determine_floor_rate, + .set_rate = clk_rcg2_set_floor_rate, + .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent, +}; +EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); + static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); @@ -323,7 +380,7 @@ static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate) pr_err("%s: RCG did not turn on\n", name); /* set clock rate */ - ret = __clk_rcg2_set_rate(hw, rate); + ret = __clk_rcg2_set_rate(hw, rate, CEIL); if (ret) return ret; diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index fffcbaf..cf6b87f 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -46,6 +46,32 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) } EXPORT_SYMBOL_GPL(qcom_find_freq); +const +struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f, + unsigned long rate) +{ + int size = 0; + + if (!f) + return NULL; + + /* + * The freq table has entries in the ascending order of frequencies + * To find the floor for a given frequency, we need to do a reverse + * lookup of the table + */ + for (; f->freq; f++, size++) + ; + + for (f--; size; f--, size--) + if (rate >= f->freq) + return f; + + /* could not find any rates lower than *rate* */ + return NULL; +} +EXPORT_SYMBOL_GPL(qcom_find_freq_floor); + int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src) { int i, num_parents = clk_hw_get_num_parents(hw); diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index ae9bdeb..76886a1 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h @@ -34,6 +34,8 @@ struct qcom_cc_desc { extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate); +extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f, + unsigned long rate); extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src);