Commit e16b9b71 authored by Andre Przywara's avatar Andre Przywara Committed by Chen-Yu Tsai
Browse files

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: default avatarAndre Przywara <andre.przywara@arm.com>
Reviewed-by: default avatarJernej Skrabec <jernej.skrabec@gmail.com>
Link: https://patch.msgid.link/20250307002628.10684-4-andre.przywara@arm.com


Signed-off-by: default avatarChen-Yu Tsai <wens@csie.org>
parent cdbb9d0d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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 {
+2 −0
Original line number Diff line number Diff line
@@ -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);
+4 −0
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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);