All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laura Nao <laura.nao@collabora.com>
To: mturquette@baylibre.com, sboyd@kernel.org, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, matthias.bgg@gmail.com,
	angelogioacchino.delregno@collabora.com, p.zabel@pengutronix.de,
	richardcochran@gmail.com
Cc: guangjie.song@mediatek.com, wenst@chromium.org,
	linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-mediatek@lists.infradead.org, netdev@vger.kernel.org,
	kernel@collabora.com, Laura Nao <laura.nao@collabora.com>
Subject: [PATCH 07/30] clk: mediatek: clk-gate: Add ops for gates with HW voter
Date: Mon, 23 Jun 2025 12:29:17 +0200	[thread overview]
Message-ID: <20250623102940.214269-8-laura.nao@collabora.com> (raw)
In-Reply-To: <20250623102940.214269-1-laura.nao@collabora.com>

MT8196 use a HW voter for gate enable/disable control. Voting is
performed using set/clr regs, with a status bit used to verify the vote
state. Add new set of gate clock operations with support for voting via
set/clr regs.

Signed-off-by: Laura Nao <laura.nao@collabora.com>
---
 drivers/clk/mediatek/clk-gate.c | 77 +++++++++++++++++++++++++++++++--
 drivers/clk/mediatek/clk-gate.h |  3 ++
 2 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index 0375ccad4be3..426f3a25763d 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/dev_printk.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/printk.h>
@@ -12,14 +13,19 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
+#include "clk-mtk.h"
 #include "clk-gate.h"
 
 struct mtk_clk_gate {
 	struct clk_hw	hw;
 	struct regmap	*regmap;
+	struct regmap	*regmap_hwv;
 	int		set_ofs;
 	int		clr_ofs;
 	int		sta_ofs;
+	unsigned int	hwv_set_ofs;
+	unsigned int	hwv_clr_ofs;
+	unsigned int	hwv_sta_ofs;
 	u8		bit;
 };
 
@@ -100,6 +106,28 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
 	mtk_cg_clr_bit(hw);
 }
 
+static int mtk_cg_hwv_set_en(struct clk_hw *hw, bool enable)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 val;
+
+	regmap_write(cg->regmap_hwv, enable ? cg->hwv_set_ofs : cg->hwv_clr_ofs, BIT(cg->bit));
+
+	return regmap_read_poll_timeout_atomic(cg->regmap_hwv, cg->hwv_sta_ofs, val,
+					       val & BIT(cg->bit),
+					       0, MTK_WAIT_HWV_DONE_US);
+}
+
+static int mtk_cg_hwv_enable(struct clk_hw *hw)
+{
+	return mtk_cg_hwv_set_en(hw, true);
+}
+
+static void mtk_cg_hwv_disable(struct clk_hw *hw)
+{
+	mtk_cg_hwv_set_en(hw, false);
+}
+
 static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
 {
 	mtk_cg_clr_bit_no_setclr(hw);
@@ -124,6 +152,15 @@ static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
 	mtk_cg_clr_bit_no_setclr(hw);
 }
 
+static bool mtk_cg_uses_hwv(const struct clk_ops *ops)
+{
+	if (ops == &mtk_clk_gate_hwv_ops_setclr ||
+	    ops == &mtk_clk_gate_hwv_ops_setclr_inv)
+		return true;
+
+	return false;
+}
+
 const struct clk_ops mtk_clk_gate_ops_setclr = {
 	.is_enabled	= mtk_cg_bit_is_cleared,
 	.enable		= mtk_cg_enable,
@@ -138,6 +175,20 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
 };
 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr_inv);
 
+const struct clk_ops mtk_clk_gate_hwv_ops_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_hwv_enable,
+	.disable	= mtk_cg_hwv_disable,
+};
+EXPORT_SYMBOL_GPL(mtk_clk_gate_hwv_ops_setclr);
+
+const struct clk_ops mtk_clk_gate_hwv_ops_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_hwv_enable,
+	.disable	= mtk_cg_hwv_disable,
+};
+EXPORT_SYMBOL_GPL(mtk_clk_gate_hwv_ops_setclr_inv);
+
 const struct clk_ops mtk_clk_gate_ops_no_setclr = {
 	.is_enabled	= mtk_cg_bit_is_cleared,
 	.enable		= mtk_cg_enable_no_setclr,
@@ -153,8 +204,9 @@ const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv);
 
 static struct clk_hw *mtk_clk_register_gate(struct device *dev,
-						const struct mtk_gate *gate,
-						struct regmap *regmap)
+					    const struct mtk_gate *gate,
+					    struct regmap *regmap,
+					    struct regmap *regmap_hwv)
 {
 	struct mtk_clk_gate *cg;
 	int ret;
@@ -169,11 +221,22 @@ static struct clk_hw *mtk_clk_register_gate(struct device *dev,
 	init.parent_names = gate->parent_name ? &gate->parent_name : NULL;
 	init.num_parents = gate->parent_name ? 1 : 0;
 	init.ops = gate->ops;
+	if (mtk_cg_uses_hwv(init.ops) && !regmap_hwv) {
+		dev_err(dev, "regmap not found for hardware voter clocks\n");
+		return ERR_PTR(-ENXIO);
+	}
 
 	cg->regmap = regmap;
+	cg->regmap_hwv = regmap_hwv;
 	cg->set_ofs = gate->regs->set_ofs;
 	cg->clr_ofs = gate->regs->clr_ofs;
 	cg->sta_ofs = gate->regs->sta_ofs;
+	if (gate->hwv_regs) {
+		cg->hwv_set_ofs = gate->hwv_regs->set_ofs;
+		cg->hwv_clr_ofs = gate->hwv_regs->clr_ofs;
+		cg->hwv_sta_ofs = gate->hwv_regs->sta_ofs;
+	}
+
 	cg->bit = gate->shift;
 
 	cg->hw.init = &init;
@@ -206,6 +269,7 @@ int mtk_clk_register_gates(struct device *dev, struct device_node *node,
 	int i;
 	struct clk_hw *hw;
 	struct regmap *regmap;
+	struct regmap *regmap_hwv;
 
 	if (!clk_data)
 		return -ENOMEM;
@@ -216,6 +280,13 @@ int mtk_clk_register_gates(struct device *dev, struct device_node *node,
 		return PTR_ERR(regmap);
 	}
 
+	regmap_hwv = mtk_clk_get_hwv_regmap(node);
+	if (IS_ERR(regmap_hwv)) {
+		pr_err("Cannot find hardware voter regmap for %pOF: %pe\n",
+		       node, regmap_hwv);
+		return PTR_ERR(regmap_hwv);
+	}
+
 	for (i = 0; i < num; i++) {
 		const struct mtk_gate *gate = &clks[i];
 
@@ -225,7 +296,7 @@ int mtk_clk_register_gates(struct device *dev, struct device_node *node,
 			continue;
 		}
 
-		hw = mtk_clk_register_gate(dev, gate, regmap);
+		hw = mtk_clk_register_gate(dev, gate, regmap, regmap_hwv);
 
 		if (IS_ERR(hw)) {
 			pr_err("Failed to register clk %s: %pe\n", gate->name,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index 1a46b4c56fc5..4f05b9855dae 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -19,6 +19,8 @@ extern const struct clk_ops mtk_clk_gate_ops_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
 extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_hwv_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_hwv_ops_setclr_inv;
 
 struct mtk_gate_regs {
 	u32 sta_ofs;
@@ -31,6 +33,7 @@ struct mtk_gate {
 	const char *name;
 	const char *parent_name;
 	const struct mtk_gate_regs *regs;
+	const struct mtk_gate_regs *hwv_regs;
 	int shift;
 	const struct clk_ops *ops;
 	unsigned long flags;
-- 
2.39.5



  parent reply	other threads:[~2025-06-23 12:51 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-23 10:29 [PATCH 00/30] Add support for MT8196 clock controllers Laura Nao
2025-06-23 10:29 ` [PATCH 01/30] clk: mediatek: clk-pll: Add set/clr regs for shared PLL enable control Laura Nao
2025-06-23 10:29 ` [PATCH 02/30] clk: mediatek: clk-pll: Add ops for PLLs using set/clr regs and FENC Laura Nao
2025-06-23 10:29 ` [PATCH 03/30] clk: mediatek: clk-mux: Add ops for mux gates with set/clr/upd " Laura Nao
2025-06-23 10:29 ` [PATCH 04/30] clk: mediatek: clk-mtk: Introduce mtk_clk_get_hwv_regmap() Laura Nao
2025-06-23 10:29 ` [PATCH 05/30] clk: mediatek: clk-mux: Add ops for mux gates with HW voter and FENC Laura Nao
2025-06-23 10:29 ` [PATCH 06/30] clk: mediatek: clk-gate: Refactor mtk_clk_register_gate to use mtk_gate struct Laura Nao
2025-06-23 10:29 ` Laura Nao [this message]
2025-06-23 10:29 ` [PATCH 08/30] clk: mediatek: clk-mtk: Add MUX_DIV_GATE macro Laura Nao
2025-06-23 10:29 ` [PATCH 09/30] dt-bindings: clock: mediatek: Describe MT8196 peripheral clock controllers Laura Nao
2025-06-23 12:12   ` Krzysztof Kozlowski
2025-06-23 12:28     ` AngeloGioacchino Del Regno
2025-06-23 10:29 ` [PATCH 10/30] clk: mediatek: Add MT8196 apmixedsys clock support Laura Nao
2025-06-23 10:29 ` [PATCH 11/30] clk: mediatek: Add MT8196 topckgen " Laura Nao
2025-06-23 10:29 ` [PATCH 12/30] clk: mediatek: Add MT8196 topckgen2 " Laura Nao
2025-06-23 10:29 ` [PATCH 13/30] clk: mediatek: Add MT8196 vlpckgen " Laura Nao
2025-06-23 10:29 ` [PATCH 14/30] clk: mediatek: Add MT8196 peripheral " Laura Nao
2025-06-23 10:29 ` [PATCH 15/30] clk: mediatek: Add MT8196 ufssys " Laura Nao
2025-06-23 10:29 ` [PATCH 16/30] clk: mediatek: Add MT8196 pextpsys " Laura Nao
2025-06-23 10:29 ` [PATCH 17/30] clk: mediatek: Add MT8196 adsp " Laura Nao
2025-06-23 10:29 ` [PATCH 18/30] clk: mediatek: Add MT8196 I2C " Laura Nao
2025-06-23 10:29 ` [PATCH 19/30] clk: mediatek: Add MT8196 mcu " Laura Nao
2025-06-23 10:29 ` [PATCH 20/30] clk: mediatek: Add MT8196 mdpsys " Laura Nao
2025-06-23 10:29 ` [PATCH 21/30] clk: mediatek: Add MT8196 mfg " Laura Nao
2025-06-23 10:29 ` [PATCH 22/30] clk: mediatek: Add MT8196 disp0 " Laura Nao
2025-06-23 10:29 ` [PATCH 23/30] clk: mediatek: Add MT8196 disp1 " Laura Nao
2025-06-23 10:29 ` [PATCH 24/30] clk: mediatek: Add MT8196 disp-ao " Laura Nao
2025-06-24  6:40   ` kernel test robot
2025-06-23 10:29 ` [PATCH 25/30] clk: mediatek: Add MT8196 ovl0 " Laura Nao
2025-06-23 10:29 ` [PATCH 26/30] clk: mediatek: Add MT8196 ovl1 " Laura Nao
2025-06-23 10:29 ` [PATCH 27/30] clk: mediatek: Add MT8196 vdecsys " Laura Nao
2025-06-23 10:29 ` [PATCH 28/30] clk: mediatek: Add MT8196 vencsys " Laura Nao
2025-06-23 10:29 ` [PATCH 29/30] dt-bindings: reset: Add MediaTek MT8196 Reset Controller binding Laura Nao
2025-06-23 12:13   ` Krzysztof Kozlowski
2025-06-23 12:22     ` AngeloGioacchino Del Regno
2025-06-23 10:29 ` [PATCH 30/30] clk: mediatek: mt8196: Add UFS and PEXTP0/1 reset controllers Laura Nao
2025-06-23 12:14   ` Krzysztof Kozlowski
2025-06-23 12:33     ` AngeloGioacchino Del Regno
2025-06-23 11:34 ` [PATCH 00/30] Add support for MT8196 clock controllers AngeloGioacchino Del Regno

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250623102940.214269-8-laura.nao@collabora.com \
    --to=laura.nao@collabora.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=guangjie.song@mediatek.com \
    --cc=kernel@collabora.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=matthias.bgg@gmail.com \
    --cc=mturquette@baylibre.com \
    --cc=netdev@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=richardcochran@gmail.com \
    --cc=robh@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=wenst@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.