summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2025-03-07 00:26:17 +0000
committerChen-Yu Tsai <wens@csie.org>2025-03-12 11:58:09 +0800
commite16b9b71f40f603d5cbdcf02007c05ee03cb2be7 (patch)
tree02724782b5507a753d5c23d064153caabf98f7b8
parentcdbb9d0d09db4cd09d23fec02d3b458664bc3d38 (diff)
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@arm.com> Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Link: https://patch.msgid.link/20250307002628.10684-4-andre.przywara@arm.com Signed-off-by: Chen-Yu Tsai <wens@csie.org>
-rw-r--r--drivers/clk/sunxi-ng/ccu_common.h4
-rw-r--r--drivers/clk/sunxi-ng/ccu_div.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_gate.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu_mux.c2
4 files changed, 12 insertions, 0 deletions
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 50fd26832967..bbec283b9d99 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 7f4691f09e01..916d6da6d8a3 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 ac52fd6bff67..474a9e8831f8 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 d7ffbdeee9e0..74f9e98a5d35 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);