[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250307002628.10684-4-andre.przywara@arm.com>
Date: Fri, 7 Mar 2025 00:26:17 +0000
From: Andre Przywara <andre.przywara@....com>
To: Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>,
Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Chen-Yu Tsai <wens@...e.org>,
Jernej Skrabec <jernej.skrabec@...il.com>,
Samuel Holland <samuel@...lland.org>
Cc: Philipp Zabel <p.zabel@...gutronix.de>,
linux-clk@...r.kernel.org,
devicetree@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-sunxi@...ts.linux.dev,
linux-kernel@...r.kernel.org
Subject: [PATCH v4 03/14] clk: sunxi-ng: Add support for update bit
Some clocks in the Allwinner A523 SoC contain an "update bit" (bit 27),
which must be set to apply any register changes, namely the mux
selector, the divider and the gate bit.
Add a new CCU feature bit to mark those clocks, and set bit 27 whenever
we are applying any changes.
Signed-off-by: Andre Przywara <andre.przywara@....com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@...il.com>
---
drivers/clk/sunxi-ng/ccu_common.h | 4 ++++
drivers/clk/sunxi-ng/ccu_div.c | 2 ++
drivers/clk/sunxi-ng/ccu_gate.c | 4 ++++
drivers/clk/sunxi-ng/ccu_mux.c | 2 ++
4 files changed, 12 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 50fd268329671..bbec283b9d993 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -20,10 +20,14 @@
#define CCU_FEATURE_KEY_FIELD BIT(8)
#define CCU_FEATURE_CLOSEST_RATE BIT(9)
#define CCU_FEATURE_DUAL_DIV BIT(10)
+#define CCU_FEATURE_UPDATE_BIT BIT(11)
/* MMC timing mode switch bit */
#define CCU_MMC_NEW_TIMING_MODE BIT(30)
+/* Some clocks need this bit to actually apply register changes */
+#define CCU_SUNXI_UPDATE_BIT BIT(27)
+
struct device_node;
struct ccu_common {
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 7f4691f09e01f..916d6da6d8a3b 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -106,6 +106,8 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
reg = readl(cd->common.base + cd->common.reg);
reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
+ if (cd->common.features & CCU_FEATURE_UPDATE_BIT)
+ reg |= CCU_SUNXI_UPDATE_BIT;
writel(reg | (val << cd->div.shift),
cd->common.base + cd->common.reg);
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
index ac52fd6bff677..474a9e8831f87 100644
--- a/drivers/clk/sunxi-ng/ccu_gate.c
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -20,6 +20,8 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
spin_lock_irqsave(common->lock, flags);
reg = readl(common->base + common->reg);
+ if (common->features & CCU_FEATURE_UPDATE_BIT)
+ reg |= CCU_SUNXI_UPDATE_BIT;
writel(reg & ~gate, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags);
@@ -44,6 +46,8 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
spin_lock_irqsave(common->lock, flags);
reg = readl(common->base + common->reg);
+ if (common->features & CCU_FEATURE_UPDATE_BIT)
+ reg |= CCU_SUNXI_UPDATE_BIT;
writel(reg | gate, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index d7ffbdeee9e04..74f9e98a5d355 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -197,6 +197,8 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
/* The key field always reads as zero. */
if (common->features & CCU_FEATURE_KEY_FIELD)
reg |= CCU_MUX_KEY_VALUE;
+ if (common->features & CCU_FEATURE_UPDATE_BIT)
+ reg |= CCU_SUNXI_UPDATE_BIT;
reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
writel(reg | (index << cm->shift), common->base + common->reg);
--
2.46.3
Powered by blists - more mailing lists