From patchwork Fri Feb 2 14:03:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel FERNANDEZ X-Patchwork-Id: 10196893 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 08AF960362 for ; Fri, 2 Feb 2018 14:21:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EAEC128E71 for ; Fri, 2 Feb 2018 14:21:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DEE2B28E74; Fri, 2 Feb 2018 14:21:25 +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=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 383CD28E71 for ; Fri, 2 Feb 2018 14:21:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=HK0EAG+4urBk/FUdCLsTYhR73wyjlMev6a14MaAI2i0=; b=jLVtlECla/wjVV cET3jPyKVlUcOhiDAHfqUeQ7YldY3KbsKca8fKt75aB5qzrBp51Z8aY0J/uYRaghF88Ku6vd4DDMM 8aUZRngx66Aarjr+PGMw9PWj0vsTgQSQ5QGGBbWgShu1NI1a2AMixBAjnyZ0NNiOBxZtYK+qI6Iak H+7uaaBFfncbBmWXqX2j6m1Pyhd5i5cAijJ6LUlspqGn5Amv0zFfWnAaKkouMtYdVWxK8IaEePMeF 9XYuqp60SYymd4MSR+zpoKmUIgkVIY7DgjgdOvJVZGi01Qotlonf1ZJLxpiLeqSfcEfQBa/LpU12p b4acTExdURGk3tjbXLhA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1ehcDS-00065H-B6; Fri, 02 Feb 2018 14:21:22 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1ehcCl-0005Ez-JO for linux-arm-kernel@bombadil.infradead.org; Fri, 02 Feb 2018 14:20:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:CC:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=qNjncnuG1IQ2FulPEUOh+1Y0zQhM76WAWHWWSmcLCCs=; b=ERc92Rd90jYH6I/XJE44/JAnn hRkJtBQ7n2Ox8O3wn/6V9QCQQsBeYOvkK7btTAsN9Mr/D/bxKtC417PC+NmWLqtai7sVlQ7ENGQpD vCyFzP3I2x7AZ9KQRJwcjFRgpMK5MdgEErK19yNcgl6mPdTIRlGl/RsKP8PEVqb4FiLlDvSQpIT8a wYcfo5dL6FBCSGEh0tOuSnwHpHEPsDlwfW1y1IB+GlPBs5tGgn8k5e3YZmBhJidy9Spw+xep5MKQ1 7jyzXWyHxh+HBDPOfOP+LgUlJm0/5Mwi7+S3FuXRtGLpw4X0Wwp4rGjyi/k5tUzZIyTWP2LowzFnY 2kVVu+CFw==; Received: from mx07-00178001.pphosted.com ([62.209.51.94]) by casper.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1ehbxB-0000Zq-4s for linux-arm-kernel@lists.infradead.org; Fri, 02 Feb 2018 14:04:44 +0000 Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w12E4Gc6015293; Fri, 2 Feb 2018 15:04:16 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2fvb1x4r98-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 02 Feb 2018 15:04:16 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id F1D4031; Fri, 2 Feb 2018 14:04:14 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag4node2.st.com [10.75.127.11]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id C54525228; Fri, 2 Feb 2018 14:04:14 +0000 (GMT) Received: from localhost (10.75.127.49) by SFHDAG4NODE2.st.com (10.75.127.11) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 2 Feb 2018 15:04:14 +0100 From: To: Rob Herring , Mark Rutland , Lee Jones , Maxime Coquelin , Alexandre Torgue , Michael Turquette , Stephen Boyd , Gabriel Fernandez Subject: [PATCH 07/14] clk: stm32mp1: add Post-dividers for PLL Date: Fri, 2 Feb 2018 15:03:35 +0100 Message-ID: <1517580222-23301-8-git-send-email-gabriel.fernandez@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1517580222-23301-1-git-send-email-gabriel.fernandez@st.com> References: <1517580222-23301-1-git-send-email-gabriel.fernandez@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.49] X-ClientProxiedBy: SFHDAG6NODE3.st.com (10.75.127.18) To SFHDAG4NODE2.st.com (10.75.127.11) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-02-02_04:, , signatures=0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180202_140433_433927_A91B9BC6 X-CRM114-Status: GOOD ( 15.66 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, olivier.bideau@st.com, linux-kernel@vger.kernel.org, gabriel.fernandez.st@gmail.com, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Gabriel Fernandez Each PLL has 3 outputs with post-dividers. pll1_p is dedicated for Cortex-A7 pll1_q is not connected pll1_r is not connected pll2_p is dedicated for AXI pll2_q is dedicated for GPU pll2_r is dedicated for DDR pll3_p is dedicated for mcu pll3_q is for Peripheral Kernel Clock pll3_r is for Peripheral Kernel Clock pll4_p is for Peripheral Kernel Clock pll4_q is for Peripheral Kernel Clock pll4_r is for Peripheral Kernel Clock Signed-off-by: Gabriel Fernandez --- drivers/clk/clk-stm32mp1.c | 257 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 33f0d09..15cd488 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -377,6 +377,147 @@ struct mux_cfg { u32 *table; }; +/* STM32 Composite clock */ +struct composite_cfg { + struct gate_cfg *gate; + struct mux_cfg *mux; + struct div_cfg *div; + const struct clk_ops *mux_ops; + const struct clk_ops *div_ops; + const struct clk_ops *gate_ops; +}; + +static struct clk_mux *_get_cmux(void __iomem *reg, u8 shift, u8 width, + u32 flags, u32 *table, spinlock_t *lock) +{ + struct clk_mux *mux; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux->reg = reg; + mux->shift = shift; + mux->mask = (1 << width) - 1; + mux->flags = flags; + mux->lock = lock; + mux->table = table; + + return mux; +} + +static struct clk_divider *_get_cdiv(void __iomem *reg, u8 shift, u8 width, + u32 flags, + const struct clk_div_table *table, + spinlock_t *lock) +{ + struct clk_divider *div; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + + if (!div) + return ERR_PTR(-ENOMEM); + + div->reg = reg; + div->shift = shift; + div->width = width; + div->flags = flags; + div->lock = lock; + div->table = table; + + return div; +} + +static struct clk_gate *_get_cgate(void __iomem *reg, u8 bit_idx, u32 flags, + spinlock_t *lock) +{ + struct clk_gate *gate; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->flags = flags; + gate->lock = lock; + + return gate; +} + +static struct clk_hw * +clk_stm_register_composite(struct device *dev, + const char *name, const char * const *parent_names, + int num_parents, void __iomem *base, + const struct composite_cfg *cfg, + unsigned long flags, spinlock_t *lock) +{ + struct clk_mux *mux = NULL; + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + const struct clk_ops *mux_ops, *div_ops, *gate_ops; + struct clk_hw *hw; + struct clk_hw *mux_hw; + struct clk_hw *div_hw; + struct clk_hw *gate_hw; + + mux_hw = NULL; + div_hw = NULL; + gate_hw = NULL; + mux_ops = NULL; + div_ops = NULL; + gate_ops = NULL; + + if (cfg->mux) { + mux = _get_cmux(base + cfg->mux->reg_off, + cfg->mux->shift, + cfg->mux->width, + cfg->mux->mux_flags, + cfg->mux->table, + lock); + + if (!IS_ERR(mux)) { + mux_hw = &mux->hw; + mux_ops = cfg->mux_ops ? + cfg->mux_ops : &clk_mux_ops; + } + } + + if (cfg->div) { + div = _get_cdiv(base + cfg->div->reg_off, + cfg->div->shift, + cfg->div->width, + cfg->div->div_flags, + cfg->div->table, + lock); + + if (!IS_ERR(div)) { + div_hw = &div->hw; + div_ops = cfg->div_ops ? + cfg->div_ops : &clk_divider_ops; + } + } + + if (cfg->gate) { + gate = _get_cgate(base + cfg->gate->reg_off, + cfg->gate->bit_idx, + cfg->gate->gate_flags, + lock); + + if (!IS_ERR(gate)) { + gate_hw = &gate->hw; + gate_ops = cfg->gate_ops ? + cfg->gate_ops : &clk_gate_ops; + } + } + + hw = clk_hw_register_composite(dev, name, parent_names, num_parents, + mux_hw, mux_ops, div_hw, div_ops, + gate_hw, gate_ops, flags); + + return hw; +} + static struct clk_hw * _clk_hw_register_gate(struct device *dev, struct clk_hw_onecell_data *clk_data, @@ -442,6 +583,17 @@ struct mux_cfg { mux_cfg->width, mux_cfg->mux_flags, lock); } +static struct clk_hw * +_clk_stm_register_composite(struct device *dev, + struct clk_hw_onecell_data *clk_data, + void __iomem *base, spinlock_t *lock, + const struct clock_config *cfg) +{ + return clk_stm_register_composite(dev, cfg->name, cfg->parent_names, + cfg->num_parents, base, cfg->cfg, + cfg->flags, lock); +} + /* MP1 Gate clock with set & clear registers */ static int mp1_gate_clk_enable(struct clk_hw *hw) @@ -779,6 +931,76 @@ struct clk_hw *_clk_register_pll(struct device *dev, .func = _clk_hw_register_mux,\ } +#define COMPOSITE(_id, _name, _parents, _flags, _cfg)\ +{\ + .id = _id,\ + .name = _name,\ + .parent_names = _parents,\ + .num_parents = ARRAY_SIZE(_parents),\ + .flags = _flags,\ + .cfg = &(struct composite_cfg)_cfg,\ + .func = _clk_stm_register_composite,\ +} + +#define PARENT(_parent) ((const char *[]) { _parent}) + +#define _NO_MUX .mux = NULL, .mux_ops = NULL +#define _NO_DIV .div = NULL, .div_ops = NULL +#define _NO_GATE .gate = NULL, .gate_ops = NULL + +#define _GATE_OPS(_offset, _bit_idx, _gate_flags, _gate_ops) \ + .gate = &(struct gate_cfg) {\ + .reg_off = _offset,\ + .bit_idx = _bit_idx,\ + },\ + .gate_ops = _gate_ops + +#define _GATE(_offset, _bit_idx, _gate_flags)\ + _GATE_OPS(_offset, _bit_idx, _gate_flags, NULL) + +#define _DIV_TABLE_OPS(_offset, _shift, _width, _div_flags, _div_table,\ + _div_ops)\ + .div = &(struct div_cfg) {\ + .reg_off = _offset,\ + .shift = _shift,\ + .width = _width,\ + .div_flags = _div_flags,\ + .table = _div_table,\ + },\ + .div_ops = _div_ops + +#define _DIV_TABLE(_offset, _shift, _width, _div_flags, _div_table)\ + _DIV_TABLE_OPS(_offset, _shift, _width, _div_flags,\ + _div_table, NULL) + +#define _DIV_OPS(_offset, _shift, _width, _div_flags, _div_ops)\ + _DIV_TABLE_OPS(_offset, _shift, _width, _div_flags, NULL, _div_ops) + +#define _DIV(_offset, _shift, _width, _div_flags)\ + _DIV_OPS(_offset, _shift, _width, _div_flags, NULL) + +#define _MUX(_offset, _shift, _width, _mux_flags)\ + .mux = &(struct mux_cfg) {\ + .reg_off = _offset,\ + .shift = _shift,\ + .width = _width,\ + .mux_flags = _mux_flags,\ + .table = NULL,\ + },\ + .mux_ops = NULL + +#define _GATEDIV(_gate_offset,\ + _bit_idx,\ + _div_offset,\ + _div_shift,\ + _div_width,\ + _div_table)\ +{\ + _DIV_TABLE(_div_offset, _div_shift, _div_width, 0, _div_table),\ + _GATE(_gate_offset, _bit_idx, 0),\ + _NO_MUX,\ +} + #define MP1_GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\ {\ .id = _id,\ @@ -834,6 +1056,41 @@ struct clk_hw *_clk_register_pll(struct device *dev, PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR), PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR), PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR), + + /* ODF */ + COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0, + _GATEDIV(RCC_PLL1CR, 4, + RCC_PLL1CFGR2, 0, 7, NULL)), + + COMPOSITE(PLL2_P, "pll2_p", PARENT("pll2"), 0, + _GATEDIV(RCC_PLL2CR, 4, + RCC_PLL2CFGR2, 0, 7, NULL)), + COMPOSITE(PLL2_Q, "pll2_q", PARENT("pll2"), 0, + _GATEDIV(RCC_PLL2CR, 5, + RCC_PLL2CFGR2, 8, 7, NULL)), + COMPOSITE(PLL2_R, "pll2_r", PARENT("pll2"), CLK_IS_CRITICAL, + _GATEDIV(RCC_PLL2CR, 6, + RCC_PLL2CFGR2, 16, 7, NULL)), + + COMPOSITE(PLL3_P, "pll3_p", PARENT("pll3"), 0, + _GATEDIV(RCC_PLL3CR, 4, + RCC_PLL3CFGR2, 0, 7, NULL)), + COMPOSITE(PLL3_Q, "pll3_q", PARENT("pll3"), 0, + _GATEDIV(RCC_PLL3CR, 5, + RCC_PLL3CFGR2, 8, 7, NULL)), + COMPOSITE(PLL3_R, "pll3_r", PARENT("pll3"), 0, + _GATEDIV(RCC_PLL3CR, 6, + RCC_PLL3CFGR2, 16, 7, NULL)), + + COMPOSITE(PLL4_P, "pll4_p", PARENT("pll4"), 0, + _GATEDIV(RCC_PLL4CR, 4, + RCC_PLL4CFGR2, 0, 7, NULL)), + COMPOSITE(PLL4_Q, "pll4_q", PARENT("pll4"), 0, + _GATEDIV(RCC_PLL4CR, 5, + RCC_PLL4CFGR2, 8, 7, NULL)), + COMPOSITE(PLL4_R, "pll4_r", PARENT("pll4"), 0, + _GATEDIV(RCC_PLL4CR, 6, + RCC_PLL4CFGR2, 16, 7, NULL)), }; struct stm32_clock_match_data {