From patchwork Thu Nov 30 13:40:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory CLEMENT X-Patchwork-Id: 10084935 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 6A8506035E for ; Thu, 30 Nov 2017 13:41:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F8DC29FBD for ; Thu, 30 Nov 2017 13:41:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5430029FC2; Thu, 30 Nov 2017 13:41:37 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 C7D0329FBD for ; Thu, 30 Nov 2017 13:41:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752499AbdK3NlL (ORCPT ); Thu, 30 Nov 2017 08:41:11 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:33384 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752071AbdK3NlK (ORCPT ); Thu, 30 Nov 2017 08:41:10 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 7969A2094D; Thu, 30 Nov 2017 14:41:08 +0100 (CET) Received: from localhost (242.171.71.37.rev.sfr.net [37.71.171.242]) by mail.free-electrons.com (Postfix) with ESMTPSA id 5DE5B207CA; Thu, 30 Nov 2017 14:40:49 +0100 (CET) From: Gregory CLEMENT To: Stephen Boyd , Mike Turquette , linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Jason Cooper , Andrew Lunn , Sebastian Hesselbarth , Gregory CLEMENT , Thomas Petazzoni , linux-arm-kernel@lists.infradead.org, Antoine Tenart , =?UTF-8?q?Miqu=C3=A8l=20Raynal?= , Nadav Haklai , Victor Gu , Marcin Wojtas , Wilson Ding , Hua Jing , Neta Zur Hershkovits Subject: [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS Date: Thu, 30 Nov 2017 14:40:28 +0100 Message-Id: <20171130134029.20751-3-gregory.clement@free-electrons.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171130134029.20751-1-gregory.clement@free-electrons.com> References: <20171130134029.20751-1-gregory.clement@free-electrons.com> 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 When DVFS will be enabled then the cpu clk will use a different set of register at run time. That means that we won't be able to use the common callback and need to use our own ones. This patch prepares this change by switching on our own set of callbacks without modifying the behavior of the clocks. Signed-off-by: Gregory CLEMENT --- drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c index 6dae21ced18a..ef725ec73c93 100644 --- a/drivers/clk/mvebu/armada-37xx-periph.c +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -46,7 +46,17 @@ struct clk_double_div { u8 shift2; }; +struct clk_pm_cpu { + struct clk_hw hw; + void __iomem *reg_mux; + u8 shift_mux; + u32 mask_mux; + void __iomem *reg_div; + u8 shift_div; +}; + #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) +#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw) struct clk_periph_data { const char *name; @@ -55,6 +65,7 @@ struct clk_periph_data { struct clk_hw *mux_hw; struct clk_hw *rate_hw; struct clk_hw *gate_hw; + struct clk_hw *muxrate_hw; bool is_double_div; }; @@ -81,6 +92,7 @@ static const struct clk_div_table clk_table2[] = { }; static const struct clk_ops clk_double_div_ops; +static const struct clk_ops clk_pm_cpu_ops; #define PERIPH_GATE(_name, _bit) \ struct clk_gate gate_##_name = { \ @@ -122,6 +134,18 @@ struct clk_divider rate_##_name = { \ } \ }; +#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \ +struct clk_pm_cpu muxrate_##_name = { \ + .reg_mux = (void *)TBG_SEL, \ + .mask_mux = 3, \ + .shift_mux = _shift1, \ + .reg_div = (void *)_reg, \ + .shift_div = _shift2, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_pm_cpu_ops, \ + } \ +}; + #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\ static PERIPH_GATE(_name, _bit); \ static PERIPH_MUX(_name, _shift); \ @@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1, _table); static PERIPH_GATE(_name, _bit); \ static PERIPH_DIV(_name, _reg, _shift, _table); -#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \ -static PERIPH_MUX(_name, _shift); \ -static PERIPH_DIV(_name, _reg, _shift_div, _table); - #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\ static PERIPH_MUX(_name, _shift); \ static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); @@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); .rate_hw = &rate_##_name.hw, \ } -#define REF_CLK_MUX_DIV(_name) \ +#define REF_CLK_PM_CPU(_name) \ { .name = #_name, \ .parent_names = (const char *[]){ "TBG-A-P", \ "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ .num_parents = 4, \ - .mux_hw = &mux_##_name.hw, \ - .rate_hw = &rate_##_name.hw, \ + .muxrate_hw = &muxrate_##_name.hw, \ } #define REF_CLK_MUX_DD(_name) \ @@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV_SEL0, DIV_SEL0, 15, 12); PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6); PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6); PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); -PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); +static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28); static struct clk_periph_data data_nb[] = { REF_CLK_FULL_DD(mmc), @@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[] = { REF_CLK_FULL(trace), REF_CLK_FULL(counter), REF_CLK_FULL_DD(eip97), - REF_CLK_MUX_DIV(cpu), + REF_CLK_PM_CPU(cpu), { }, }; @@ -297,6 +316,37 @@ static const struct clk_ops clk_double_div_ops = { .recalc_rate = clk_double_div_recalc_rate, }; +static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) +{ + struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); + int num_parents = clk_hw_get_num_parents(hw); + u32 val; + + val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; + val &= pm_cpu->mask_mux; + + if (val >= num_parents) + return -EINVAL; + + return val; +} + +static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); + unsigned int div; + + div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); + + return DIV_ROUND_UP_ULL((u64)parent_rate, div); +} + +static const struct clk_ops clk_pm_cpu_ops = { + .get_parent = clk_pm_cpu_get_parent, + .recalc_rate = clk_pm_cpu_recalc_rate, +}; + static const struct of_device_id armada_3700_periph_clock_of_match[] = { { .compatible = "marvell,armada-3700-periph-clock-nb", .data = data_nb, }, @@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data, } } + if (data->muxrate_hw) { + struct clk_pm_cpu *pmcpu_clk; + struct clk_hw *muxrate_hw = data->muxrate_hw; + + pmcpu_clk = to_clk_pm_cpu(muxrate_hw); + pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; + pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div; + + mux_hw = muxrate_hw; + rate_hw = muxrate_hw; + mux_ops = muxrate_hw->init->ops; + rate_ops = muxrate_hw->init->ops; + } + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, data->num_parents, mux_hw, mux_ops, rate_hw, rate_ops,