Received: by 10.223.185.116 with SMTP id b49csp6531928wrg; Thu, 8 Mar 2018 08:57:43 -0800 (PST) X-Google-Smtp-Source: AG47ELt0NWq/pXv/NvHnwtgZpfAFxv4tVf/Q10MqknbVhTkptj7vZHUMk0NHrJaqKr5kk+Y7jXpj X-Received: by 2002:a17:902:599b:: with SMTP id p27-v6mr23675234pli.289.1520528263490; Thu, 08 Mar 2018 08:57:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520528263; cv=none; d=google.com; s=arc-20160816; b=cmt8dxfJSsKKlytrdm6l6m3f2EaURawQImesBnQK0p9reivXFrPCZGoW+bZfo2Hrs3 AZX/xxSQI9AvuTvvB3G4VHRXpDSd06eCq/zczcXJqO4TLGgTqxoNZ9eP+NEYvGY1oRhH cb/YHVh0wYTflZ2B7X1AnTa1c/SCkrmoevoho6mHYpk9Aw1e/wToJK1IWXvNQbpY8I6j R03DnuIA/rp1G+1qnj2O5GR/tv9Kuh6scnmnKH7wytvwrcB+vYZ6DTu4MFCgVO/5fld6 lJe3UPHdLPq4Cw1/O6odbPWNam0X7kT5e2E+2EGv3XNix7gWvbfnu0Ilgkm3h0nXOPb7 A4+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=ZZtcuFu9dCXAvCEXxuH8Gtvm+2q3UtErPQQuDCPP2t0=; b=xxtg9B/uIMLfYo7nkTtcKy6xnUg9Rjd5YtTYiySbOo6G6OLC1njAYZxN20w0eC21nZ iEIFkNIsioaQLF7PSdax9NMFraJWLGPw/CyzmDpmFmeqQXx5RRy0aoWR4c3A3Ze32slo 6ldFV6wM0hupgK3I9MoApcas/Nw3ChjtChQ/eLZXFlNuywIezvGnkQ+mjbJr6Og+BxJs QMWaZjFIUBUbXIxubNQgbjaoI7dsOvAdOCYMEJCxPV2hhJDOzigQOH0HSk/zwpyHW6EU Xox5KMDXCiWw23JwZo61lFvzLHGP0csZA0kCNSqrHRTnKEilQvNAPQlK6s94CpyaiPQo QhNw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 91-v6si15099219ple.541.2018.03.08.08.57.29; Thu, 08 Mar 2018 08:57:43 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754665AbeCHQz7 (ORCPT + 99 others); Thu, 8 Mar 2018 11:55:59 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:12982 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935911AbeCHQzB (ORCPT ); Thu, 8 Mar 2018 11:55:01 -0500 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w28GsKVw022879; Thu, 8 Mar 2018 17:54:20 +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 2gk84909rf-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Thu, 08 Mar 2018 17:54:20 +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 26F7D42; Thu, 8 Mar 2018 16:54:19 +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 DC5A55095; Thu, 8 Mar 2018 16:54:18 +0000 (GMT) Received: from localhost (10.75.127.47) by SFHDAG4NODE2.st.com (10.75.127.11) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Thu, 8 Mar 2018 17:54:18 +0100 From: To: , Rob Herring , Mark Rutland , Lee Jones , Maxime Coquelin , Alexandre Torgue , Michael Turquette , Stephen Boyd , Gabriel Fernandez CC: , , , , , , Loic PALLARDY , benjamin GAIGNARD Subject: [PATCH v2 03/12] clk: stm32mp1: add MP1 gate for hse/hsi/csi oscillators Date: Thu, 8 Mar 2018 17:53:56 +0100 Message-ID: <1520528045-18330-4-git-send-email-gabriel.fernandez@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520528045-18330-1-git-send-email-gabriel.fernandez@st.com> References: <1520528045-18330-1-git-send-email-gabriel.fernandez@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.75.127.47] X-ClientProxiedBy: SFHDAG7NODE1.st.com (10.75.127.19) To SFHDAG4NODE2.st.com (10.75.127.11) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2018-03-08_10:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Gabriel Fernandez MP1 Gate is a gate with a set and a clear register. Signed-off-by: Gabriel Fernandez --- drivers/clk/clk-stm32mp1.c | 143 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 6261a92..56b738e 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -140,6 +140,11 @@ struct div_cfg { const struct clk_div_table *table; }; +struct stm32_gate_cfg { + struct gate_cfg *gate; + const struct clk_ops *ops; +}; + static struct clk_hw * _clk_hw_register_gate(struct device *dev, struct clk_hw_onecell_data *clk_data, @@ -191,6 +196,112 @@ struct div_cfg { lock); } +/* MP1 Gate clock with set & clear registers */ + +static int mp1_gate_clk_enable(struct clk_hw *hw) +{ + if (!clk_gate_ops.is_enabled(hw)) + clk_gate_ops.enable(hw); + + return 0; +} + +static void mp1_gate_clk_disable(struct clk_hw *hw) +{ + struct clk_gate *gate = to_clk_gate(hw); + unsigned long flags = 0; + + if (clk_gate_ops.is_enabled(hw)) { + spin_lock_irqsave(gate->lock, flags); + writel_relaxed(BIT(gate->bit_idx), gate->reg + RCC_CLR); + spin_unlock_irqrestore(gate->lock, flags); + } +} + +const struct clk_ops mp1_gate_clk_ops = { + .enable = mp1_gate_clk_enable, + .disable = mp1_gate_clk_disable, + .is_enabled = clk_gate_is_enabled, +}; + +static struct clk_hw * +_get_stm32_gate(void __iomem *base, + const struct stm32_gate_cfg *cfg, spinlock_t *lock) +{ + struct clk_gate *gate; + struct clk_hw *gate_hw; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->reg = cfg->gate->reg_off + base; + gate->bit_idx = cfg->gate->bit_idx; + gate->flags = cfg->gate->gate_flags; + gate->lock = lock; + gate_hw = &gate->hw; + + return gate_hw; +} + +static struct clk_hw * +clk_stm32_register_gate_ops(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *base, + const struct stm32_gate_cfg *cfg, + spinlock_t *lock) +{ + struct clk_init_data init = { NULL }; + struct clk_gate *gate; + struct clk_hw *hw; + int ret; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = flags; + + init.ops = &clk_gate_ops; + + if (cfg->ops) + init.ops = cfg->ops; + + hw = _get_stm32_gate(base, cfg, lock); + if (IS_ERR(hw)) + return ERR_PTR(-ENOMEM); + + hw->init = &init; + + ret = clk_hw_register(dev, hw); + if (ret) { + kfree(gate); + hw = ERR_PTR(ret); + } + + return hw; +} + +static struct clk_hw * +_clk_stm32_register_gate(struct device *dev, + struct clk_hw_onecell_data *clk_data, + void __iomem *base, spinlock_t *lock, + const struct clock_config *cfg) +{ + return clk_stm32_register_gate_ops(dev, + cfg->name, + cfg->parent_name, + cfg->flags, + base, + cfg->cfg, + lock); +} + #define GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\ {\ .id = _id,\ @@ -239,12 +350,44 @@ struct div_cfg { DIV_TABLE(_id, _name, _parent, _flags, _offset, _shift, _width,\ _div_flags, NULL) +/* STM32 GATE */ +#define STM32_GATE(_id, _name, _parent, _flags, _gate)\ +{\ + .id = _id,\ + .name = _name,\ + .parent_name = _parent,\ + .flags = _flags,\ + .cfg = (struct stm32_gate_cfg *) {_gate},\ + .func = _clk_stm32_register_gate,\ +} + +#define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _ops)\ + (&(struct stm32_gate_cfg) {\ + &(struct gate_cfg) {\ + .reg_off = _gate_offset,\ + .bit_idx = _gate_bit_idx,\ + .gate_flags = _gate_flags,\ + },\ + .ops = _ops,\ + }) + +#define _GATE_MP1(_gate_offset, _gate_bit_idx, _gate_flags)\ + _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\ + &mp1_gate_clk_ops)\ + +#define GATE_MP1(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\ + STM32_GATE(_id, _name, _parent, _flags,\ + _GATE_MP1(_offset, _bit_idx, _gate_flags)) + static const struct clock_config stm32mp1_clock_cfg[] = { /* Oscillator divider */ DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY), /* External / Internal Oscillators */ + GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0), + GATE_MP1(CK_CSI, "ck_csi", "clk-csi", 0, RCC_OCENSETR, 4, 0), + GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0), GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0), GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0), -- 1.9.1