From patchwork Thu Feb 24 16:01:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel FERNANDEZ X-Patchwork-Id: 12758832 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3B8EFC433F5 for ; Thu, 24 Feb 2022 16:04:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=4EcZQ0qNq9ZBXh+ZDAbazk1Pep9caKY03955G0L4S2k=; b=bgxYPM6M4A4YNw p9cf2yYpX0SevBJO4nsgYQXt/h4G0aabi6dRvc8roeA87tUtdBLALSoXtEHxQgsSm+WEDvGVYWfbi 5lVM+/RODeSndeiVrjZ9JjnRwNo3Tb2nRSBi46TRS1Vff6ukPqz2jIg9YvlPXXP2y+gMVflJ2jEHO BNAqT4NP+jEXzT9IFJufTsBQTduqUiqM/SWQGzHV2ByXzCZ04uOSZPKMkXTyo+waSBjZz+gFT2hqP /DgF6/9itKkM9DOXBXxa1ifLmRz4e2jM9idSEuqSHBtWKXmDeDum3Jsr9+aa8IkV+O0nMAAzjCBfw LUnmkgV1nACjxEMZ0iZA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nNGaV-001RL9-9E; Thu, 24 Feb 2022 16:03:27 +0000 Received: from mx08-00178001.pphosted.com ([91.207.212.93] helo=mx07-00178001.pphosted.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nNGZT-001QyV-P5 for linux-arm-kernel@lists.infradead.org; Thu, 24 Feb 2022 16:02:28 +0000 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with ESMTP id 21OCTEnC032636; Thu, 24 Feb 2022 17:02:12 +0100 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=selector1; bh=BwCNzsJ9PxyLQNaGsXq+tfOpWqHh+TR8gmKWBgTxFsc=; b=X6Q5shjcvNfQDeu4XRCJ5AVCrbZ2/Ef8QInNbjjQZQdmGCItBTdczRssz5FfFbL8C3uI v9V8MfPmq3zNcGxRketd8ZkZGeFo+OfE7kv8ARK3GN6LHsB/2JAtDIOXSanOP/IDsidN BQzHtwlhOUAO0WP7eUJlaCegNhdfwl42vo7FVn2hf1pHvB3fFMlTWmbGcjOvaKcBPeCL BJZtwxCw7fwK7J0H/aDBw6ydaWGg8xgAbLZPotSuReuE+dwRzwca5lBblkqgwUfAXCqo UGAng3tX/+1QvW1HIyAtvf06rrOF82Eyj2Cpga7K9B4vEF4VhdQXHKcvlU4bXl8OP15q aA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3ee5x03699-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 24 Feb 2022 17:02:12 +0100 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 87027100034; Thu, 24 Feb 2022 17:02:11 +0100 (CET) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 7420D22A6FC; Thu, 24 Feb 2022 17:02:11 +0100 (CET) Received: from localhost (10.75.127.50) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.26; Thu, 24 Feb 2022 17:02:10 +0100 From: To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Maxime Coquelin , Alexandre Torgue , Philipp Zabel , Gabriel Fernandez CC: , , , , Subject: [PATCH 04/13] clk: stm32mp13: add stm32_gate management Date: Thu, 24 Feb 2022 17:01:32 +0100 Message-ID: <20220224160141.455881-5-gabriel.fernandez@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220224160141.455881-1-gabriel.fernandez@foss.st.com> References: <20220224160141.455881-1-gabriel.fernandez@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.50] X-ClientProxiedBy: SFHDAG2NODE3.st.com (10.75.127.6) To SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-02-24_03,2022-02-24_01,2022-02-23_01 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220224_080224_167991_C6B38115 X-CRM114-Status: GOOD ( 20.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Gabriel Fernandez Just to introduce management of a stm32 gate clock. Change-Id: I9c823f2742e8680bc131adcb854ad50ee66e682b Signed-off-by: Gabriel Fernandez --- drivers/clk/stm32/clk-stm32-core.c | 124 +++++++++++++++++++++++++++++ drivers/clk/stm32/clk-stm32-core.h | 37 +++++++++ drivers/clk/stm32/clk-stm32mp13.c | 6 ++ 3 files changed, 167 insertions(+) diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c index f34659625aff..91eae0386e5e 100644 --- a/drivers/clk/stm32/clk-stm32-core.c +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -92,6 +92,109 @@ int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, return 0; } +void clk_stm32_endisable_gate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id, int enable) +{ + const struct stm32_gate_cfg *gate = &data->gates[gate_id]; + void __iomem *addr = base + gate->offset; + + if (enable) { + if (data->gate_cpt[gate_id]++ > 0) + return; + + if (gate->set_clr != 0) + writel(BIT(gate->bit_idx), addr); + else + writel(readl(addr) | BIT(gate->bit_idx), addr); + } else { + if (--data->gate_cpt[gate_id] > 0) + return; + + if (gate->set_clr != 0) + writel(BIT(gate->bit_idx), addr + gate->set_clr); + else + writel(readl(addr) & ~BIT(gate->bit_idx), addr); + } +} + +void clk_stm32_disable_unused_gate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id) +{ + const struct stm32_gate_cfg *gate = &data->gates[gate_id]; + void __iomem *addr = base + gate->offset; + + if (data->gate_cpt[gate_id] > 0) + return; + + if (gate->set_clr != 0) + writel(BIT(gate->bit_idx), addr + gate->set_clr); + else + writel(readl(addr) & ~BIT(gate->bit_idx), addr); +} + +int clk_stm32_is_enabled_gate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id) +{ + const struct stm32_gate_cfg *gate = &data->gates[gate_id]; + + return (readl(base + gate->offset) & BIT(gate->bit_idx)) != 0; +} + +void clk_stm32_gate_endisable(struct clk_hw *hw, int enable) +{ + struct clk_stm32_gate *gate = to_clk_stm32_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(gate->lock, flags); + + clk_stm32_endisable_gate(gate->base, gate->clock_data, + gate->gate_id, enable); + + spin_unlock_irqrestore(gate->lock, flags); +} + +int clk_stm32_gate_enable(struct clk_hw *hw) +{ + clk_stm32_gate_endisable(hw, 1); + + return 0; +} + +void clk_stm32_gate_disable(struct clk_hw *hw) +{ + clk_stm32_gate_endisable(hw, 0); +} + +int clk_stm32_gate_is_enabled(struct clk_hw *hw) +{ + struct clk_stm32_gate *gate = to_clk_stm32_gate(hw); + + return clk_stm32_is_enabled_gate(gate->base, gate->clock_data, + gate->gate_id); +} + +void clk_stm32_gate_disable_unused(struct clk_hw *hw) +{ + struct clk_stm32_gate *gate = to_clk_stm32_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(gate->lock, flags); + + clk_stm32_disable_unused_gate(gate->base, gate->clock_data, gate->gate_id); + + spin_unlock_irqrestore(gate->lock, flags); +} + +const struct clk_ops clk_stm32_gate_ops = { + .enable = clk_stm32_gate_enable, + .disable = clk_stm32_gate_disable, + .is_enabled = clk_stm32_gate_is_enabled, + .disable_unused = clk_stm32_gate_disable_unused, +}; + u8 clk_stm32_get_parent_mux(void __iomem *base, struct clk_stm32_clock_data *data, u16 mux_id) @@ -150,6 +253,27 @@ const struct clk_ops clk_stm32_mux_ops = { .set_parent = clk_stm32_mux_set_parent, }; +struct clk_hw *clk_stm32_gate_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg) +{ + struct clk_stm32_gate *gate = cfg->clock_cfg; + struct clk_hw *hw = &gate->hw; + int err; + + gate->base = base; + gate->lock = lock; + gate->clock_data = data->clock_data; + + err = clk_hw_register(dev, hw); + if (err) + return ERR_PTR(err); + + return hw; +} + struct clk_hw *clk_stm32_mux_register(struct device *dev, const struct stm32_rcc_match_data *data, void __iomem *base, diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h index 7c9f503d3388..1b4a73556512 100644 --- a/drivers/clk/stm32/clk-stm32-core.h +++ b/drivers/clk/stm32/clk-stm32-core.h @@ -84,6 +84,16 @@ int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, #define DIV_NO_RDY 0xFF /* Definition of clock structure */ +struct clk_stm32_gate { + u16 gate_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw) + struct clk_stm32_mux { u16 mux_id; struct clk_hw hw; @@ -95,6 +105,22 @@ struct clk_stm32_mux { #define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw) /* Clock ops */ +void clk_stm32_endisable_gate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id, int enable); +void clk_stm32_disable_unused_gate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id); +int clk_stm32_is_enabled_gate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id); + +void clk_stm32_gate_endisable(struct clk_hw *hw, int enable); +int clk_stm32_gate_enable(struct clk_hw *hw); +void clk_stm32_gate_disable(struct clk_hw *hw); +int clk_stm32_gate_is_enabled(struct clk_hw *hw); +void clk_stm32_gate_disable_unused(struct clk_hw *hw); + u8 clk_stm32_get_parent_mux(void __iomem *base, struct clk_stm32_clock_data *data, u16 mux_id); @@ -105,9 +131,16 @@ int clk_stm32_set_parent_mux(void __iomem *base, u8 clk_stm32_mux_get_parent(struct clk_hw *hw); int clk_stm32_mux_set_parent(struct clk_hw *hw, u8 index); +extern const struct clk_ops clk_stm32_gate_ops; extern const struct clk_ops clk_stm32_mux_ops; /* Clock registering */ +struct clk_hw *clk_stm32_gate_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + struct clk_hw *clk_stm32_mux_register(struct device *dev, const struct stm32_rcc_match_data *data, void __iomem *base, @@ -121,6 +154,10 @@ struct clk_hw *clk_stm32_mux_register(struct device *dev, .func = (_register),\ } +#define STM32_GATE_CFG(_binding, _clk)\ + STM32_CLOCK_CFG(_binding, &(_clk), struct clk_stm32_gate *,\ + &clk_stm32_gate_register) + #define STM32_MUX_CFG(_binding, _clk)\ STM32_CLOCK_CFG(_binding, &(_clk), struct clk_stm32_mux *,\ &clk_stm32_mux_register) diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c index 89d4e039e4e6..24c0c9ff3602 100644 --- a/drivers/clk/stm32/clk-stm32mp13.c +++ b/drivers/clk/stm32/clk-stm32mp13.c @@ -410,8 +410,14 @@ static struct clk_stm32_mux ck_ker_eth1 = { CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), }; +static struct clk_stm32_gate eth1ck_k = { + .gate_id = GATE_ETH1CK, + .hw.init = CLK_HW_INIT_HW("eth1ck_k", &ck_ker_eth1.hw, &clk_stm32_gate_ops, 0), +}; + static const struct clock_config stm32mp13_clock_cfg[] = { STM32_MUX_CFG(NO_ID, ck_ker_eth1), + STM32_GATE_CFG(ETH1CK_K, eth1ck_k), }; u16 stm32mp13_cpt_gate[GATE_NB];