Linux clock framework development
 help / color / mirror / Atom feed
* [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks
@ 2026-09-17 22:39 Andre Przywara
  2026-09-17 22:39 ` [PATCH v2 1/5] clk: sunxi-ng: generalise update bit Andre Przywara
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Andre Przywara @ 2026-09-17 22:39 UTC (permalink / raw)
  To: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-sunxi

Hi,

after a year (again?) an update to the A523 CPU clock series. I heeded
Chen-Yu's advice and generalised the update bit to cover both the "key"
use case and the now no longer fixed update bit (patch 1). I also
followed one of Krzysztof's suggestions around the binding headers.
For a changelog see below. Based on v7.3-rc1.
This clashes slightly with the already queued clock fixes from Junhui,
please let me know how I should play this.

==============================
This series adds support for the CPU clock controller in the Allwinner
A523/A527/T527 family of SoCs.

In contrast to all earlier Allwinner SoCs, this chip features a separate
CCU for the CPU clocks (one for each of the two clusters) and the DSU
clock.

Patches 1 and 2 add some slight enhancements to the sunxi-ng clock driver
framework, to generalise the update bit and allow clocks with just a
power-of-2 divider.
Patch 3 adds the binding document for the new CCU.
Patch 4 adds the actual clock driver, and patch 5 makes use of that by
adding the clock description to the SoC .dtsi.

Please have a look and test!

Cheers,
Andre

Changes in v2:
- rebase on v7.3-rc1
- cover CCU_FEATURE_KEY_FIELD in update bits generalisation
- explicitly include binding header in clock driver
- order clocks property before enable-method in DT nodes


Andre Przywara (5):
  clk: sunxi-ng: generalise update bit
  clk: sunxi-ng: mp: support clocks with just a shift register
  dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  clk: sunxi-ng: add support for the A523/T527 CPU CCU
  arm64: dts: allwinner: a523: add CPU clocks

 .../clock/allwinner,sun55i-a523-ccu.yaml      |  25 ++
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi |  22 ++
 drivers/clk/sunxi-ng/Kconfig                  |   5 +
 drivers/clk/sunxi-ng/Makefile                 |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c    | 340 ++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h    |  24 ++
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c        |  12 +-
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c          |   4 +-
 drivers/clk/sunxi-ng/ccu_common.h             |   8 +-
 drivers/clk/sunxi-ng/ccu_div.c                |   3 +-
 drivers/clk/sunxi-ng/ccu_gate.c               |   6 +-
 drivers/clk/sunxi-ng/ccu_mp.c                 |   6 +-
 drivers/clk/sunxi-ng/ccu_mp.h                 |   8 +-
 drivers/clk/sunxi-ng/ccu_mux.c                |   8 +-
 drivers/clk/sunxi-ng/ccu_nm.c                 |   1 +
 .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   |  13 +
 16 files changed, 456 insertions(+), 31 deletions(-)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h
 create mode 100644 include/dt-bindings/clock/sun55i-a523-cpu-ccu.h


base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
-- 
2.43.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/5] clk: sunxi-ng: generalise update bit
  2026-09-17 22:39 [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
@ 2026-09-17 22:39 ` Andre Przywara
  2026-09-21 15:47   ` Chen-Yu Tsai
  2026-09-17 22:39 ` [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register Andre Przywara
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Andre Przywara @ 2026-09-17 22:39 UTC (permalink / raw)
  To: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-sunxi

A few of the Allwinner A523 CCU clock registers introduced an "update" bit,
which must be set for changes to the other bits to take effect.
Of the three clocks where this was used, it was always bit 27, so we just
encoded this as a single bit feature flag.

Now the CPU PLL also features the update bit, but puts it at bit 26, so
this flag trick won't work anymore.

Add an "update_bit" field to the common sunxi clock struct, which takes a
bitmask, so we can encode any bit to use, even potentially multiple of
them. As uninitialised fields are set to 0, we can use this as a default
bitmask to set, so can OR this in unconditionally.
It turns out that the "update key" feature is doing something very
similar, so just convert it over to also use this same bitmask approach.

Change the existing update bit users to use this new encoding, and add
support for the ccu_nm clock on the way, since we will need it there
shortly.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 12 ++++++------
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c   |  4 ++--
 drivers/clk/sunxi-ng/ccu_common.h      |  8 +++-----
 drivers/clk/sunxi-ng/ccu_div.c         |  3 +--
 drivers/clk/sunxi-ng/ccu_gate.c        |  6 ++----
 drivers/clk/sunxi-ng/ccu_mp.h          |  8 +++++---
 drivers/clk/sunxi-ng/ccu_mux.c         |  8 +-------
 drivers/clk/sunxi-ng/ccu_nm.c          |  1 +
 8 files changed, 21 insertions(+), 29 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 20dad06b37ca3..35cddab0749b3 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -386,8 +386,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
 					    0, 0,		/* no P */
 					    24, 3,	/* mux */
 					    BIT(31),	/* gate */
-					    CLK_IS_CRITICAL,
-					    CCU_FEATURE_UPDATE_BIT);
+					    BIT(27),	/* update*/
+					    CLK_IS_CRITICAL, 0);
 
 static const struct clk_hw *mbus_hws[] = { &mbus_clk.common.hw };
 
@@ -590,8 +590,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
 					    0, 0,	/* no P */
 					    24, 3,	/* mux */
 					    BIT(31),	/* gate */
-					    CLK_SET_RATE_PARENT,
-					    CCU_FEATURE_UPDATE_BIT);
+					    BIT(27),	/* update */
+					    CLK_SET_RATE_PARENT, 0);
 
 static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
 			  BIT(0), 0);
@@ -609,8 +609,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
 					    0, 0,	/* no P */
 					    24, 3,	/* mux */
 					    BIT(31),	/* gate */
-					    CLK_IS_CRITICAL,
-					    CCU_FEATURE_UPDATE_BIT);
+					    BIT(27),	/* update*/
+					    CLK_IS_CRITICAL, 0);
 
 static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
 			  0x804, BIT(0), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 98ae10307f438..dde56529f281d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -214,7 +214,7 @@ static struct ccu_mux osc32k_clk = {
 	.mux	= _SUNXI_CCU_MUX(0, 1),
 	.common	= {
 		.reg		= LOSC_CTRL_REG,
-		.features	= CCU_FEATURE_KEY_FIELD,
+		.update_bits	= CCU_MUX_KEY_VALUE,
 		.hw.init	= &osc32k_init_data,
 	},
 };
@@ -280,7 +280,7 @@ static struct ccu_mux rtc_32k_clk = {
 	.mux	= _SUNXI_CCU_MUX(1, 1),
 	.common	= {
 		.reg		= LOSC_CTRL_REG,
-		.features	= CCU_FEATURE_KEY_FIELD,
+		.update_bits	= CCU_MUX_KEY_VALUE,
 		.hw.init	= &rtc_32k_init_data,
 	},
 };
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index d9dc24ad55039..e0ed861735beb 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -17,17 +17,14 @@
 #define CCU_FEATURE_LOCK_REG		BIT(5)
 #define CCU_FEATURE_MMC_TIMING_SWITCH	BIT(6)
 #define CCU_FEATURE_SIGMA_DELTA_MOD	BIT(7)
-#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)
-#define CCU_FEATURE_IOSC_CALIBRATION	BIT(12)
+#define CCU_FEATURE_IOSC_CALIBRATION	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)
+#define CCU_MUX_KEY_VALUE		0x16aa0000
 
 struct device_node;
 
@@ -36,6 +33,7 @@ struct ccu_common {
 	u16		reg;
 	u16		lock_reg;
 	u32		prediv;
+	u32		update_bits;
 
 	unsigned long	min_rate;
 	unsigned long	max_rate;
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index c385e0160f13b..a6e81bac18d6e 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -119,8 +119,7 @@ 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;
+	reg |= cd->common.update_bits;
 
 	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 30673fe4e3c2c..532e661b5f4b1 100644
--- a/drivers/clk/sunxi-ng/ccu_gate.c
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -20,8 +20,7 @@ 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;
+	reg |= common->update_bits;
 	writel(reg & ~gate, common->base + common->reg);
 
 	spin_unlock_irqrestore(common->lock, flags);
@@ -46,8 +45,7 @@ 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;
+	reg |= common->update_bits;
 	writel(reg | gate, common->base + common->reg);
 
 	spin_unlock_irqrestore(common->lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index bb09c649bfa35..6ebb48438b5d4 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -131,7 +131,8 @@ struct ccu_mp {
 					     _mshift, _mwidth,		\
 					     _pshift, _pwidth,		\
 					     _muxshift, _muxwidth,	\
-					     _gate, _flags, _features)	\
+					     _gate, _key_update,	\
+					     _flags, _features)		\
 	struct ccu_mp _struct = {					\
 		.enable	= _gate,					\
 		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
@@ -140,6 +141,7 @@ struct ccu_mp {
 		.common	= {						\
 			.reg		= _reg,				\
 			.features	= _features,			\
+			.update_bits	= _key_update,			\
 			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
 								   _parents, \
 								   &ccu_mp_ops, \
@@ -156,7 +158,7 @@ struct ccu_mp {
 					     _reg, _mshift, _mwidth,	\
 					     _pshift, _pwidth,		\
 					     _muxshift, _muxwidth,	\
-					     _gate, _flags, 0)
+					     _gate, 0, _flags, 0)
 
 #define SUNXI_CCU_DUALDIV_MUX_GATE(_struct, _name, _parents, _reg,	\
 				   _mshift, _mwidth,			\
@@ -167,7 +169,7 @@ struct ccu_mp {
 					     _reg, _mshift, _mwidth,	\
 					     _pshift, _pwidth,		\
 					     _muxshift, _muxwidth,	\
-					     _gate, _flags,		\
+					     _gate, 0, _flags,		\
 					     CCU_FEATURE_DUAL_DIV)
 
 #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg,	\
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 4503c9780c39f..3bb2ba5e809a3 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -12,8 +12,6 @@
 #include "ccu_gate.h"
 #include "ccu_mux.h"
 
-#define CCU_MUX_KEY_VALUE		0x16aa0000
-
 static u16 ccu_mux_get_prediv(struct ccu_common *common,
 			      struct ccu_mux_internal *cm,
 			      int parent_index)
@@ -203,11 +201,7 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
 
 	reg = readl(common->base + common->reg);
 
-	/* 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 |= common->update_bits;
 
 	reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
 	writel(reg | (index << cm->shift), common->base + common->reg);
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index df01ed3b37a6b..80aad0650f348 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -219,6 +219,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	reg |= (_nm.n - nm->n.offset) << nm->n.shift;
 	reg |= (_nm.m - nm->m.offset) << nm->m.shift;
+	reg |= nm->common.update_bits;
 	writel(reg, nm->common.base + nm->common.reg);
 
 	spin_unlock_irqrestore(nm->common.lock, flags);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register
  2026-09-17 22:39 [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
  2026-09-17 22:39 ` [PATCH v2 1/5] clk: sunxi-ng: generalise update bit Andre Przywara
@ 2026-09-17 22:39 ` Andre Przywara
  2026-09-18  3:51   ` Chen-Yu Tsai
  2026-09-17 22:39 ` [PATCH v2 3/5] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Andre Przywara @ 2026-09-17 22:39 UTC (permalink / raw)
  To: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-sunxi

The "mp" clock models a mod clock with divider and a shift field. At
least one clock in the Allwinner A523 features just a power-of-2 divider
field, so support an initialisation of the clock without providing an
actual divider field.

Add a check whether the "width" field is 0, and skip the divider
handling in this case, as the GENMASK macro will not work with a zero
length.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/clk/sunxi-ng/ccu_mp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index 7cdb0eedc69b5..3896cb94bf733 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -236,9 +236,11 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
 	spin_lock_irqsave(cmp->common.lock, flags);
 
 	reg = readl(cmp->common.base + cmp->common.reg);
-	reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
+	if (cmp->m.width)
+		reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
 	reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
-	reg |= (m - cmp->m.offset) << cmp->m.shift;
+	if (cmp->m.width)
+		reg |= (m - cmp->m.offset) << cmp->m.shift;
 	if (shift)
 		reg |= ilog2(p) << cmp->p.shift;
 	else
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 3/5] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  2026-09-17 22:39 [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
  2026-09-17 22:39 ` [PATCH v2 1/5] clk: sunxi-ng: generalise update bit Andre Przywara
  2026-09-17 22:39 ` [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register Andre Przywara
@ 2026-09-17 22:39 ` Andre Przywara
  2026-09-17 22:46   ` sashiko-bot
  2026-09-17 22:39 ` [PATCH v2 4/5] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
  2026-09-17 22:39 ` [PATCH v2 5/5] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara
  4 siblings, 1 reply; 12+ messages in thread
From: Andre Przywara @ 2026-09-17 22:39 UTC (permalink / raw)
  To: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-sunxi

There are four clock controllers in the A523 SoC, but only three are
described in the DT binding so far.

Add a description for the CPU CCU, which provides separate clocks for
the two CPU clusters and the DSU interconnect.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 .../clock/allwinner,sun55i-a523-ccu.yaml      | 25 +++++++++++++++++++
 .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   | 13 ++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 include/dt-bindings/clock/sun55i-a523-cpu-ccu.h

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
index 58be701a720ea..98d47d2aabc48 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
@@ -19,6 +19,7 @@ properties:
   compatible:
     enum:
       - allwinner,sun55i-a523-ccu
+      - allwinner,sun55i-a523-cpu-ccu
       - allwinner,sun55i-a523-mcu-ccu
       - allwinner,sun55i-a523-r-ccu
 
@@ -64,6 +65,30 @@ allOf:
             - const: iosc
             - const: losc-fanout
 
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun55i-a523-cpu-ccu
+
+    then:
+      properties:
+        clocks:
+          items:
+            - description: High Frequency Oscillator (usually at 24MHz)
+            - description: Low Frequency Oscillator (usually at 32kHz)
+            - description: Internal Oscillator
+            - description: Peripherals PLL 0 (1200 MHz output)
+            - description: Peripherals PLL 0 (600 MHz output)
+
+        clock-names:
+          items:
+            - const: hosc
+            - const: losc
+            - const: iosc
+            - const: pll-periph0-2x
+            - const: pll-periph0-600m
+
   - if:
       properties:
         compatible:
diff --git a/include/dt-bindings/clock/sun55i-a523-cpu-ccu.h b/include/dt-bindings/clock/sun55i-a523-cpu-ccu.h
new file mode 100644
index 0000000000000..042f2310f64de
--- /dev/null
+++ b/include/dt-bindings/clock/sun55i-a523-cpu-ccu.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright 2025 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN55I_A523_CPU_CCU_H_
+#define _DT_BINDINGS_CLK_SUN55I_A523_CPU_CCU_H_
+
+#define CLK_CPU_L		7
+#define CLK_CPU_DSU		8
+#define CLK_CPU_B		9
+
+#endif /* _DT_BINDINGS_CLK_SUN55I_A523_CPU_CCU_H_ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 4/5] clk: sunxi-ng: add support for the A523/T527 CPU CCU
  2026-09-17 22:39 [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
                   ` (2 preceding siblings ...)
  2026-09-17 22:39 ` [PATCH v2 3/5] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
@ 2026-09-17 22:39 ` Andre Przywara
  2026-09-17 22:51   ` sashiko-bot
  2026-09-17 22:39 ` [PATCH v2 5/5] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara
  4 siblings, 1 reply; 12+ messages in thread
From: Andre Przywara @ 2026-09-17 22:39 UTC (permalink / raw)
  To: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-sunxi

The A523 contains a separate CCU block for the CPU PLLs. This includes
one CPU clock per cluster, plus the DSU PLL, which clocks the part that
connects the two clusters. There is also a "backup" PLL, which can be used
to clock the cores when the main PLLs are reprogrammed.
Those PLLs are then connected via MUXes to the two clusters and the DSU.

Describe those clocks and their relationship, to allow the kernel to
adjust the core frequency.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/clk/sunxi-ng/Kconfig               |   5 +
 drivers/clk/sunxi-ng/Makefile              |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c | 340 +++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h |  24 ++
 4 files changed, 371 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 6af2d020e03e9..c34af60139124 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -67,6 +67,11 @@ config SUN55I_A523_R_CCU
 	default ARCH_SUNXI
 	depends on ARM64 || COMPILE_TEST
 
+config SUN55I_A523_CPU_CCU
+	tristate "Support for the Allwinner A523/T527 CPU CCU"
+	default y
+	depends on ARM64 || COMPILE_TEST
+
 config SUN4I_A10_CCU
 	tristate "Support for the Allwinner A10/A20 CCU"
 	default ARCH_SUNXI
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index a1c4087d72417..309ff5a089ecf 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SUN50I_H616_CCU)	+= sun50i-h616-ccu.o
 obj-$(CONFIG_SUN55I_A523_CCU)	+= sun55i-a523-ccu.o
 obj-$(CONFIG_SUN55I_A523_MCU_CCU)	+= sun55i-a523-mcu-ccu.o
 obj-$(CONFIG_SUN55I_A523_R_CCU)	+= sun55i-a523-r-ccu.o
+obj-$(CONFIG_SUN55I_A523_CPU_CCU)	+= sun55i-a523-cpu-ccu.o
 obj-$(CONFIG_SUN4I_A10_CCU)	+= sun4i-a10-ccu.o
 obj-$(CONFIG_SUN5I_CCU)		+= sun5i-ccu.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= sun6i-a31-ccu.o
@@ -64,6 +65,7 @@ sun50i-h616-ccu-y		+= ccu-sun50i-h616.o
 sun55i-a523-ccu-y		+= ccu-sun55i-a523.o
 sun55i-a523-mcu-ccu-y		+= ccu-sun55i-a523-mcu.o
 sun55i-a523-r-ccu-y		+= ccu-sun55i-a523-r.o
+sun55i-a523-cpu-ccu-y		+= ccu-sun55i-a523-cpu.o
 sun4i-a10-ccu-y			+= ccu-sun4i-a10.o
 sun5i-ccu-y			+= ccu-sun5i.o
 sun6i-a31-ccu-y			+= ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
new file mode 100644
index 0000000000000..e505aefc92370
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023-2025 Arm Ltd.
+ *
+ * There are four PLLs: one for the little cluster (cores 0-3: PLL1), one for
+ * the "big" cluster (cores 4-7: PLL3), one for the DSU interconnect (probably
+ * its SCLK, driving the L3 cache: PLL2), and one undocumented "backup" PLL0,
+ * which can be used to drive either or both clusters, while the original PLLs
+ * are re-programmed (and re-lock).
+ * PLL[123] are the same, with a multiplier, a predivider, and two separate
+ * divider fields. For PLL1 and PLL3 there is an additional shift field, in
+ * the mux clock - although that applies only to the PLL, not the other sources.
+ * The two clusters and the DSU are connected to a mux clock each, selecting
+ * from various sources, including the PLL-PERIPH0-600M clock, again useful
+ * during DVFS operations:
+ *
+ *                           PLL-PERI0-600M (from the main CCU)
+ *                               |
+ *                       +-------+-----------+
+ *                      /         \           \
+ *            +------+ /  +------+ \  +------+ \  +------+
+ *            | PLL1 | |  | PLL0 | |  | PLL3 | |  | PLL2 |
+ *            +------+ |  +------+ |  +------+ |  +------+
+ *                \    |     ^     |    /      |     /
+ *                DIV  |    / \    |  DIV      |    /       (plus 24MHz,
+ *                  \  |   /   \   |  /        |   |              32KHz,
+ *                +---------+ +---------+   +---------+           16MHz,
+ *                 \ CPU-L /   \ CPU-B /     \  DSU  /       for each mux)
+ *                  \     /     \     /       \     /
+ *                   +---+       +---+         +---+
+ *                     |           |             |
+ *             +-------+-----------+-----DSU-----+----+
+ *             |   +---+---+   +---+---+              |
+ *             |   | cores |   | cores |              |
+ *             |   |  0-3  |   |  4-7  | +------------+
+ *             |   +-------+   +-------+ |  L3 cache  |
+ *             +-------------------------+------------+
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_nm.h"
+#include "ccu_mult.h"
+
+#include <dt-bindings/clock/sun55i-a523-cpu-ccu.h>
+#include "ccu-sun55i-a523-cpu.h"
+
+/*
+ * The 24 MHz oscillator, the root of most of the clock tree.
+ * .fw_name is the string used in the DT "clock-names" property, used to
+ * identify the corresponding clock in the "clocks" property.
+ */
+static const struct clk_parent_data osc24M[] = {
+	{ .fw_name = "hosc" }
+};
+
+/*
+ * Undocumented PLL, mux-able to both clusters, usable as an interim PLL
+ * during DVFS clock rate changes. Bits [23:16] and [4:2] are RAZ/WI, which
+ * looks like the DDR or VIDEO PLLs, and not like the other CPU PLLs.
+ * Bits [1:0] are not dividers, as they don't have any effect on the frequency.
+ */
+#define SUN55I_A523_PLL_CPU_0_REG		0x00
+
+static struct ccu_mult pll_cpu_0_clk = {
+	.enable	= BIT(27),
+	.lock	= BIT(28),
+	.mult	= _SUNXI_CCU_MULT(8, 8),
+	.common	= {
+		.reg		= 0x00,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-cpu-0", osc24M,
+							   &ccu_mult_ops,
+							   CLK_SET_RATE_UNGATE),
+	},
+};
+static const struct clk_parent_data pll_cpu_0_hws[] = {
+	{ .hw = &pll_cpu_0_clk.common.hw },
+};
+
+/*
+ * The PLLs are input * N / P / (M0 * M1). Model them as NM, by ignoring the
+ * predivider P and the only 2-bit wide M0, and fixing them to 1 in probe().
+ * Using NKMP wouldn't be better, because the "P" in there is a shift.
+ * The actual enable bit is bit 31, which we set once in probe, along with
+ * some other control bits, as the manual recommends to not touch them
+ * during runtime.
+ */
+#define SUN55I_A523_PLL_CPU_L_REG		0x04
+static struct ccu_nm pll_cpu_l_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 20, 108),
+	.m		= _SUNXI_CCU_DIV(0, 3),		/* M1 */
+	.common		= {
+		.reg		= 0x04,
+		.update_bits	= BIT(26),
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-cpu-l", osc24M,
+							   &ccu_nm_ops,
+							   CLK_SET_RATE_UNGATE |
+							   CLK_IS_CRITICAL),
+	},
+};
+static const struct clk_parent_data pll_cpu_l_hws[] = {
+	{ .hw = &pll_cpu_l_clk.common.hw },
+};
+
+#define SUN55I_A523_PLL_CPU_DSU_REG		0x08
+static struct ccu_nm pll_cpu_dsu_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 20, 108),
+	.m		= _SUNXI_CCU_DIV(0, 3),		/* M1 */
+	.common		= {
+		.reg		= 0x08,
+		.update_bits	= BIT(26),
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-cpu-dsu", osc24M,
+							   &ccu_nm_ops,
+							   CLK_SET_RATE_UNGATE |
+							   CLK_IS_CRITICAL),
+	},
+};
+static const struct clk_parent_data pll_cpu_dsu_hws[] = {
+	{ .hw = &pll_cpu_dsu_clk.common.hw },
+};
+
+#define SUN55I_A523_PLL_CPU_B_REG		0x0c
+static struct ccu_nm pll_cpu_b_clk = {
+	.enable		= BIT(27),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 20, 108),
+	.m		= _SUNXI_CCU_DIV(0, 3),		/* M1 */
+	.common		= {
+		.reg		= 0x0c,
+		.update_bits	= BIT(26),
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-cpu-b", osc24M,
+							   &ccu_nm_ops,
+							   CLK_SET_RATE_UNGATE |
+							   CLK_IS_CRITICAL),
+	},
+};
+static const struct clk_parent_data pll_cpu_b_hws[] = {
+	{ .hw = &pll_cpu_b_clk.common.hw },
+};
+
+static SUNXI_CCU_MP_DATA_WITH_MUX(pll_cpu_l_div_clk, "pll-cpu-l-div",
+				  pll_cpu_l_hws, 0x060,
+				  0, 0,		/* no M */
+				  16, 2,	/* P */
+				  0, 0,		/* no mux */
+				  CLK_SET_RATE_PARENT);		/* flags */
+static SUNXI_CCU_MP_DATA_WITH_MUX(pll_cpu_b_div_clk, "pll-cpu-b-div",
+				  pll_cpu_b_hws, 0x064,
+				  0, 0,		/* no M */
+				  16, 2,	/* P */
+				  0, 0,		/* no mux */
+				  CLK_SET_RATE_PARENT);		/* flags */
+static SUNXI_CCU_MP_DATA_WITH_MUX(pll_cpu_dsu_div_clk, "pll-cpu-dsu-div",
+				  pll_cpu_dsu_hws, 0x06c,
+				  0, 0,		/* no M */
+				  16, 2,	/* P */
+				  0, 0,		/* no mux */
+				  CLK_SET_RATE_PARENT);		/* flags */
+
+static const struct clk_parent_data cpu_l_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_cpu_l_div_clk.common.hw },
+	{ .fw_name = "pll-periph0-600M" },
+	{ .hw = &pll_cpu_0_clk.common.hw },
+};
+
+static SUNXI_CCU_MUX_DATA(cpu_l_clk, "cpu-l", cpu_l_parents, 0x60,
+			  24, 3,		/* mux */
+			  CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static const struct clk_parent_data cpu_b_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_cpu_b_div_clk.common.hw },
+	{ .fw_name = "pll-periph0-600M" },
+	{ .hw = &pll_cpu_0_clk.common.hw },
+};
+
+static SUNXI_CCU_MUX_DATA(cpu_b_clk, "cpu-b", cpu_b_parents, 0x64,
+			  24, 3,		/* mux */
+			  CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+/*
+ * Register 0x68 holds gate bits for the two cluster clocks and the DSU.
+ * We leave them alone in the kernel, that's something for TF-A or the SCP.
+ */
+
+static const struct clk_parent_data cpu_dsu_parents[] = {
+	{ .fw_name = "hosc" },
+	{ .fw_name = "losc" },
+	{ .fw_name = "iosc" },
+	{ .hw = &pll_cpu_dsu_div_clk.common.hw },
+	{ .fw_name = "pll-periph0-2x" },
+	{ .fw_name = "pll-periph0-600M" },
+};
+
+static SUNXI_CCU_MUX_DATA(cpu_dsu_clk, "cpu-dsu", cpu_dsu_parents, 0x6c,
+			  24, 3,		/* mux */
+			  CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static struct ccu_common *sun55i_a523_cpu_ccu_clks[] = {
+	&pll_cpu_0_clk.common,
+	&pll_cpu_l_clk.common,
+	&pll_cpu_b_clk.common,
+	&pll_cpu_dsu_clk.common,
+	&pll_cpu_l_div_clk.common,
+	&pll_cpu_b_div_clk.common,
+	&pll_cpu_dsu_div_clk.common,
+	&cpu_l_clk.common,
+	&cpu_b_clk.common,
+	&cpu_dsu_clk.common,
+};
+
+static struct clk_hw_onecell_data sun55i_a523_cpu_hw_clks = {
+	.hws	= {
+		[CLK_PLL_CPU_0]		= &pll_cpu_0_clk.common.hw,
+		[CLK_PLL_CPU_L]		= &pll_cpu_l_clk.common.hw,
+		[CLK_PLL_CPU_DSU]	= &pll_cpu_dsu_clk.common.hw,
+		[CLK_PLL_CPU_B]		= &pll_cpu_b_clk.common.hw,
+		[CLK_DIV_CPU_L]		= &pll_cpu_l_div_clk.common.hw,
+		[CLK_DIV_CPU_DSU]	= &pll_cpu_dsu_div_clk.common.hw,
+		[CLK_DIV_CPU_B]		= &pll_cpu_b_div_clk.common.hw,
+		[CLK_CPU_L]		= &cpu_l_clk.common.hw,
+		[CLK_CPU_DSU]		= &cpu_dsu_clk.common.hw,
+		[CLK_CPU_B]		= &cpu_b_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static const struct sunxi_ccu_desc sun55i_a523_cpu_ccu_desc = {
+	.ccu_clks	= sun55i_a523_cpu_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_cpu_ccu_clks),
+
+	.hw_clks	= &sun55i_a523_cpu_hw_clks,
+};
+
+static const u32 pll_regs[] = {
+	SUN55I_A523_PLL_CPU_0_REG,
+	SUN55I_A523_PLL_CPU_L_REG,
+	SUN55I_A523_PLL_CPU_DSU_REG,
+	SUN55I_A523_PLL_CPU_B_REG,
+};
+
+static struct ccu_mux_nb sun55i_a523_cpu_l_nb = {
+	.common		= &cpu_l_clk.common,
+	.cm		= &cpu_l_clk.mux,
+	.delay_us	= 1, /* manual doesn't really say */
+	.bypass_index	= 4, /* PLL_PERI0@600MHz, as recommended by manual */
+};
+static struct ccu_mux_nb sun55i_a523_cpu_b_nb = {
+	.common		= &cpu_b_clk.common,
+	.cm		= &cpu_b_clk.mux,
+	.delay_us	= 1, /* manual doesn't really say */
+	.bypass_index	= 4, /* PLL_PERI0@600MHz, as recommended by manual */
+};
+
+static int sun55i_a523_cpu_ccu_probe(struct platform_device *pdev)
+{
+	const struct sunxi_ccu_desc *desc;
+	void __iomem *reg;
+	int i, ret;
+	u32 val;
+
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc)
+		return -EINVAL;
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/*
+	 * The user manual recommends to keep the PLLs running, and just
+	 * gate their output if they are not needed, to avoid interference
+	 * with other PLLs, since they share a power domain.
+	 * To comply with this, we use this output gate as the CCF enable bit,
+	 * so we need to enable all PLLs here. Chances are the bootloader has
+	 * already enabled at least one PLL, so check if it's already running
+	 * and locked, before touching it.
+	 * We set the enable, the LDO and the lock bits, and clear dividers.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+		val = readl(reg + pll_regs[i]);
+		if ((val & GENMASK(31, 28)) != GENMASK(31, 28)) {
+			val |= BIT(31) | BIT(30) | BIT(29) | BIT(26);
+			val &= ~GENMASK(21, 16); /* covering PLL_P and PLL_M0 */
+			writel(val, reg + pll_regs[i]);
+		}
+	}
+
+	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
+	if (ret)
+		return ret;
+
+	/* Reparent CPU during CPU PLL rate changes */
+	ccu_mux_notifier_register(pll_cpu_l_clk.common.hw.clk,
+				  &sun55i_a523_cpu_l_nb);
+	ccu_mux_notifier_register(pll_cpu_b_clk.common.hw.clk,
+				  &sun55i_a523_cpu_b_nb);
+
+	return ret;
+}
+
+static const struct of_device_id sun55i_a523_cpu_ccu_ids[] = {
+	{
+		.compatible = "allwinner,sun55i-a523-cpu-ccu",
+		.data = &sun55i_a523_cpu_ccu_desc,
+	},
+	{ }
+};
+
+static struct platform_driver sun55i_a523_cpu_ccu_driver = {
+	.probe	= sun55i_a523_cpu_ccu_probe,
+	.driver	= {
+		.name			= "sun55i-a523-cpu-ccu",
+		.suppress_bind_attrs	= true,
+		.of_match_table		= sun55i_a523_cpu_ccu_ids,
+	},
+};
+module_platform_driver(sun55i_a523_cpu_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h
new file mode 100644
index 0000000000000..484343b2c4fa6
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2025 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN55I_A523_CPU_H
+#define _CCU_SUN55I_A523_CPU_H
+
+#include <dt-bindings/clock/sun55i-a523-cpu-ccu.h>
+
+/* The PLL clocks itself and the pure divider clocks are not exported. */
+
+#define CLK_PLL_CPU_0		0
+#define CLK_PLL_CPU_L		1
+#define CLK_PLL_CPU_DSU		2
+#define CLK_PLL_CPU_B		3
+
+#define CLK_DIV_CPU_L		4
+#define CLK_DIV_CPU_DSU		5
+#define CLK_DIV_CPU_B		6
+
+#define CLK_NUMBER	(CLK_CPU_B + 1)
+
+#endif /* _CCU_SUN55I_A523_CPU_H */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 5/5] arm64: dts: allwinner: a523: add CPU clocks
  2026-09-17 22:39 [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
                   ` (3 preceding siblings ...)
  2026-09-17 22:39 ` [PATCH v2 4/5] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
@ 2026-09-17 22:39 ` Andre Przywara
  2026-09-17 22:46   ` sashiko-bot
  4 siblings, 1 reply; 12+ messages in thread
From: Andre Przywara @ 2026-09-17 22:39 UTC (permalink / raw)
  To: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-sunxi

The Allwinner A523 family of SoCs feature a separate clock unit for the
CPU PLLs and muxes, including one for the DSU interconnect.

Add a DT node for the CPU clock controller, and list all the clocks from
the other CCUs that this controller needs.
Also list the clock source for each CPU: there is one clock for each
cluster of four cores, suffixed L and B, for little and big (although
all cores are of the same Cortex-A55 type).

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
index 85ef492ffeae7..29af21372aba2 100644
--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
@@ -6,6 +6,7 @@
 #include <dt-bindings/clock/sun55i-a523-ccu.h>
 #include <dt-bindings/clock/sun55i-a523-mcu-ccu.h>
 #include <dt-bindings/clock/sun55i-a523-r-ccu.h>
+#include <dt-bindings/clock/sun55i-a523-cpu-ccu.h>
 #include <dt-bindings/reset/sun55i-a523-ccu.h>
 #include <dt-bindings/reset/sun55i-a523-mcu-ccu.h>
 #include <dt-bindings/reset/sun55i-a523-r-ccu.h>
@@ -25,6 +26,7 @@ cpu0: cpu@0 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x000>;
+			clocks = <&cpu_ccu CLK_CPU_L>;
 			enable-method = "psci";
 		};
 
@@ -32,6 +34,7 @@ cpu1: cpu@100 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x100>;
+			clocks = <&cpu_ccu CLK_CPU_L>;
 			enable-method = "psci";
 		};
 
@@ -39,6 +42,7 @@ cpu2: cpu@200 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x200>;
+			clocks = <&cpu_ccu CLK_CPU_L>;
 			enable-method = "psci";
 		};
 
@@ -46,6 +50,7 @@ cpu3: cpu@300 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x300>;
+			clocks = <&cpu_ccu CLK_CPU_L>;
 			enable-method = "psci";
 		};
 
@@ -53,6 +58,7 @@ cpu4: cpu@400 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x400>;
+			clocks = <&cpu_ccu CLK_CPU_B>;
 			enable-method = "psci";
 		};
 
@@ -60,6 +66,7 @@ cpu5: cpu@500 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x500>;
+			clocks = <&cpu_ccu CLK_CPU_B>;
 			enable-method = "psci";
 		};
 
@@ -67,6 +74,7 @@ cpu6: cpu@600 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x600>;
+			clocks = <&cpu_ccu CLK_CPU_B>;
 			enable-method = "psci";
 		};
 
@@ -74,6 +82,7 @@ cpu7: cpu@700 {
 			compatible = "arm,cortex-a55";
 			device_type = "cpu";
 			reg = <0x700>;
+			clocks = <&cpu_ccu CLK_CPU_B>;
 			enable-method = "psci";
 		};
 	};
@@ -1144,5 +1153,18 @@ npu: npu@7122000 {
 			resets = <&mcu_ccu RST_BUS_MCU_NPU>;
 			power-domains = <&ppu PD_NPU>;
 		};
+
+		cpu_ccu: clock-controller@8817000 {
+			compatible = "allwinner,sun55i-a523-cpu-ccu";
+			reg = <0x08817000 0x80>;
+			clocks = <&osc24M>, <&rtc CLK_OSC32K>,
+				 <&rtc CLK_IOSC>, <&ccu CLK_PLL_PERIPH0_2X>,
+				 <&ccu CLK_PLL_PERIPH0_600M>;
+			clock-names = "hosc", "losc",
+				      "iosc", "pll-periph0-2x",
+				      "pll-periph0-600M";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
 	};
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 3/5] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  2026-09-17 22:39 ` [PATCH v2 3/5] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
@ 2026-09-17 22:46   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-09-17 22:46 UTC (permalink / raw)
  To: Andre Przywara; +Cc: linux-clk, devicetree, robh, linux-sunxi, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] dt-bindings: clock: sun55i-a523-ccu: CPU CCU incorrectly requires #reset-cells
--

commit 6b88ed1238e42f9cf204f24c2d92453688b20a13
Author: Andre Przywara <andre.przywara@arm.com>

dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
    
There are four clock controllers in the A523 SoC, but only three are
described in the DT binding so far.
    
Add a description for the CPU CCU, which provides separate clocks for
the two CPU clusters and the DSU interconnect.

> diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> index 58be701a720ea..98d47d2aabc48 100644
> --- a/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> +++ b/Documentation/devicetree/bindings/clock/allwinner,sun55i-a523-ccu.yaml
> @@ -19,6 +19,7 @@ properties:
>    compatible:
>      enum:
>        - allwinner,sun55i-a523-ccu
> +      - allwinner,sun55i-a523-cpu-ccu

[Severity: Low]
Does the new sun55i-a523-cpu-ccu compatible string incorrectly inherit the
global #reset-cells requirement?

Looking at the binding, #reset-cells is globally required:

required:
  - "#clock-cells"
  - "#reset-cells"
  - compatible

Since the CPU CCU does not seem to provide resets, will this force device tree
nodes to include an unnecessary #reset-cells property to pass schema
validation?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917223913.1855301-1-andre.przywara@arm.com?part=3

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 5/5] arm64: dts: allwinner: a523: add CPU clocks
  2026-09-17 22:39 ` [PATCH v2 5/5] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara
@ 2026-09-17 22:46   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-09-17 22:46 UTC (permalink / raw)
  To: Andre Przywara; +Cc: linux-clk, linux-sunxi, robh, conor+dt, devicetree

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] dt: sun55i-a523: incorrect #reset-cells in cpu_ccu
- [Low] dt: sun55i-a523: clock-names mismatch pll-periph0-600M
--

commit e064b2e2cf12882a6bab40a91b6eb61a493b3e06
Author: Andre Przywara <andre.przywara@arm.com>

arm64: dts: allwinner: a523: add CPU clocks

The Allwinner A523 family of SoCs feature a separate clock unit for the CPU
PLLs and muxes. This patch adds a DT node for the CPU clock controller and
lists the required clocks and sources for each CPU.

> diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> index 85ef492ffeae7..29af21372aba2 100644
> --- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi

[ ... ]

> @@ -1144,5 +1153,18 @@ npu: npu@7122000 {
>  			resets = <&mcu_ccu RST_BUS_MCU_NPU>;
>  			power-domains = <&ppu PD_NPU>;
>  		};
> +
> +		cpu_ccu: clock-controller@8817000 {
> +			compatible = "allwinner,sun55i-a523-cpu-ccu";
> +			reg = <0x08817000 0x80>;
> +			clocks = <&osc24M>, <&rtc CLK_OSC32K>,
> +				 <&rtc CLK_IOSC>, <&ccu CLK_PLL_PERIPH0_2X>,
> +				 <&ccu CLK_PLL_PERIPH0_600M>;
> +			clock-names = "hosc", "losc",
> +				      "iosc", "pll-periph0-2x",
> +				      "pll-periph0-600M";

[Severity: Low]
Will this clock name cause a validation regression during dtbs_check?

In the cpu_ccu node of arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi, the
device tree uses pll-periph0-600M. This matches the driver, but the YAML
binding strictly expects pll-periph0-600m.

This case mismatch will fail validation when running make dtbs_check.

> +			#clock-cells = <1>;
> +			#reset-cells = <1>;

[Severity: Low]
Does this introduce a regression in the DT description by erroneously declaring
cpu_ccu as a reset controller provider?

The #reset-cells = <1> property in the cpu_ccu node describes it as a reset
controller, but the hardware and driver do not provide resets.

This appears to be satisfying a flawed YAML binding that erroneously mandates
it globally for all compatibles.

> +		};
>  	};
>  };

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917223913.1855301-1-andre.przywara@arm.com?part=5

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 4/5] clk: sunxi-ng: add support for the A523/T527 CPU CCU
  2026-09-17 22:39 ` [PATCH v2 4/5] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
@ 2026-09-17 22:51   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-09-17 22:51 UTC (permalink / raw)
  To: Andre Przywara; +Cc: devicetree, linux-sunxi, conor+dt, linux-clk, robh

Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [High] clk: sunxi-ng: probe modifies active CPU PLL dividers without reparenting
- [High] clk: sunxi-ng: missing mux notifier for DSU PLL rate changes
- [High] clk: sunxi-ng: UAF on module unload due to unregistered notifiers
- [Medium] kconfig: SUN55I_A523_CPU_CCU inappropriately uses default y
- [Medium] clk: sunxi-ng: modeling non-existent divider for DSU mux
- [Medium] clk: sunxi-ng: probe enables PLLs without polling the lock bit
- [Medium] clk: sunxi-ng: ignored return values from ccu_mux_notifier_register()
- [Medium] clk: sunxi-ng: race condition exposing clocks before notifiers are attached
- [Medium] clk: sunxi-ng: missing MODULE_DEVICE_TABLE breaks module autoloading
--

commit 719a9a0732629f9d936e50d92e8a19aea0aef6c5
Author: Andre Przywara <andre.przywara@arm.com>

clk: sunxi-ng: add support for the A523/T527 CPU CCU

This commit adds support for the Allwinner A523/T527 CPU CCU, managing the 
clock controllers for the CPU clusters and the DSU. It defines the PLLs 
used to drive the core frequencies and their relations, allowing the kernel 
to adjust the core frequency dynamically.

> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index 6af2d020e03e9..c34af60139124 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -67,6 +67,11 @@ config SUN55I_A523_R_CCU
>  	default ARCH_SUNXI
>  	depends on ARM64 || COMPILE_TEST
>  
> +config SUN55I_A523_CPU_CCU
> +	tristate "Support for the Allwinner A523/T527 CPU CCU"
> +	default y
> +	depends on ARM64 || COMPILE_TEST

[Severity: Medium]
Is it intended to use "default y" here? 

Normally, SoC-specific drivers follow the subsystem convention of 
"default ARCH_SUNXI". This will unconditionally enable the driver on all 
ARM64 builds, causing defconfig pollution on arm64 multi-platform builds.

[ ... ]

> diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
> new file mode 100644
> index 0000000000000..e505aefc92370
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c

[ ... ]

> +static SUNXI_CCU_MP_DATA_WITH_MUX(pll_cpu_l_div_clk, "pll-cpu-l-div",
> +				  pll_cpu_l_hws, 0x060,
> +				  0, 0,		/* no M */
> +				  16, 2,	/* P */
> +				  0, 0,		/* no mux */
> +				  CLK_SET_RATE_PARENT);		/* flags */
> +static SUNXI_CCU_MP_DATA_WITH_MUX(pll_cpu_b_div_clk, "pll-cpu-b-div",
> +				  pll_cpu_b_hws, 0x064,
> +				  0, 0,		/* no M */
> +				  16, 2,	/* P */
> +				  0, 0,		/* no mux */
> +				  CLK_SET_RATE_PARENT);		/* flags */
> +static SUNXI_CCU_MP_DATA_WITH_MUX(pll_cpu_dsu_div_clk, "pll-cpu-dsu-div",
> +				  pll_cpu_dsu_hws, 0x06c,
> +				  0, 0,		/* no M */
> +				  16, 2,	/* P */
> +				  0, 0,		/* no mux */
> +				  CLK_SET_RATE_PARENT);		/* flags */

[Severity: Medium]
Is it correct to model a P divider here extracting bits 17:16 for the DSU?

The block comment at the top of the file explicitly states "For PLL1 and PLL3
there is an additional shift field... although that applies only to the PLL...",
which implies it does not exist for the DSU (PLL2). Manipulating a non-existent
hardware field could cause issues in frequency calculations.

[ ... ]

> +static int sun55i_a523_cpu_ccu_probe(struct platform_device *pdev)
> +{
> +	const struct sunxi_ccu_desc *desc;
> +	void __iomem *reg;
> +	int i, ret;
> +	u32 val;
> +
> +	desc = of_device_get_match_data(&pdev->dev);
> +	if (!desc)
> +		return -EINVAL;
> +
> +	reg = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(reg))
> +		return PTR_ERR(reg);
> +
> +	/*
> +	 * The user manual recommends to keep the PLLs running, and just
> +	 * gate their output if they are not needed, to avoid interference
> +	 * with other PLLs, since they share a power domain.
> +	 * To comply with this, we use this output gate as the CCF enable bit,
> +	 * so we need to enable all PLLs here. Chances are the bootloader has
> +	 * already enabled at least one PLL, so check if it's already running
> +	 * and locked, before touching it.
> +	 * We set the enable, the LDO and the lock bits, and clear dividers.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> +		val = readl(reg + pll_regs[i]);
> +		if ((val & GENMASK(31, 28)) != GENMASK(31, 28)) {
> +			val |= BIT(31) | BIT(30) | BIT(29) | BIT(26);
> +			val &= ~GENMASK(21, 16); /* covering PLL_P and PLL_M0 */

[Severity: High]
Could modifying these dividers cause a hardware crash? 

If the bootloader leaves the PLL active but misses a control bit (e.g., bit 30),
this code instantly clears the P and M0 dividers. Modifying active dividers 
without first reparenting the CPU clock to a bypass might hang the system. 
Also, if the bootloader setup completely matches the lock mask, this block is 
skipped, leaving P and M0 uncleared, but the software CCF model blindly 
assumes they are 1.

> +			writel(val, reg + pll_regs[i]);
> +		}

[Severity: Medium]
Does this code need to poll the lock bit (BIT(28)) before proceeding?

The code sets BIT(31) to physically enable the PLLs in the CCU but doesn't
wait for the hardware lock to assert. The CCF enable op only toggles the output
gate, which could silently pass an unlocked PLL to a CPU core.

> +	}
> +
> +	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
> +	if (ret)
> +		return ret;
> +
> +	/* Reparent CPU during CPU PLL rate changes */
> +	ccu_mux_notifier_register(pll_cpu_l_clk.common.hw.clk,
> +				  &sun55i_a523_cpu_l_nb);

[Severity: Medium]
Is there a race condition exposing clocks before the notifiers are attached?

devm_sunxi_ccu_probe() registers the clocks globally, making them accessible.
Since the reparenting notifiers are attached after this step, a fast consumer
could modify the frequency before the reparenting protection is active.

[Severity: Medium]
Is it safe to ignore the return values of ccu_mux_notifier_register()?

If the internal memory allocation fails, a subsequent cpufreq rate change
could attempt to scale the PLL without reparenting, which could lock up
the CPU.

[Severity: High]
Since this module registers static notifiers, could it cause a use-after-free
on module unload?

There doesn't appear to be a .remove callback to call
clk_notifier_unregister(). If the module is unloaded, the CCF notifier list
would retain dangling pointers.

> +	ccu_mux_notifier_register(pll_cpu_b_clk.common.hw.clk,
> +				  &sun55i_a523_cpu_b_nb);

[Severity: High]
Should there be a mux notifier registered for the DSU PLL as well?

If a DVFS rate change forces the DSU clock to relock, it could output an
unstable clock. CPU clusters are protected by the dynamic reparenting
notifiers above, but the DSU seems to be missing its corresponding notifier.

> +
> +	return ret;
> +}
> +
> +static const struct of_device_id sun55i_a523_cpu_ccu_ids[] = {
> +	{
> +		.compatible = "allwinner,sun55i-a523-cpu-ccu",
> +		.data = &sun55i_a523_cpu_ccu_desc,
> +	},
> +	{ }
> +};

[Severity: Medium]
Is this missing a MODULE_DEVICE_TABLE(of, sun55i_a523_cpu_ccu_ids) declaration?

Compiling the driver as a tristate module without exporting the device ID table
prevents the module alias from being emitted, breaking udev autoloading.

> +
> +static struct platform_driver sun55i_a523_cpu_ccu_driver = {
> +	.probe	= sun55i_a523_cpu_ccu_probe,
> +	.driver	= {
> +		.name			= "sun55i-a523-cpu-ccu",
> +		.suppress_bind_attrs	= true,
> +		.of_match_table		= sun55i_a523_cpu_ccu_ids,
> +	},
> +};

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917223913.1855301-1-andre.przywara@arm.com?part=4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register
  2026-09-17 22:39 ` [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register Andre Przywara
@ 2026-09-18  3:51   ` Chen-Yu Tsai
  2026-09-24  6:54     ` Andre Przywara
  0 siblings, 1 reply; 12+ messages in thread
From: Chen-Yu Tsai @ 2026-09-18  3:51 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
	linux-clk, devicetree, linux-arm-kernel, linux-sunxi

On Fri, Sep 18, 2026 at 6:39 AM Andre Przywara <andre.przywara@arm.com> wrote:
>
> The "mp" clock models a mod clock with divider and a shift field. At
> least one clock in the Allwinner A523 features just a power-of-2 divider
> field, so support an initialisation of the clock without providing an
> actual divider field.

Please just use the single divider clock type instead. It properly supports
power-of-2 dividers.

ChenYu

> Add a check whether the "width" field is 0, and skip the divider
> handling in this case, as the GENMASK macro will not work with a zero
> length.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  drivers/clk/sunxi-ng/ccu_mp.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> index 7cdb0eedc69b5..3896cb94bf733 100644
> --- a/drivers/clk/sunxi-ng/ccu_mp.c
> +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> @@ -236,9 +236,11 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
>         spin_lock_irqsave(cmp->common.lock, flags);
>
>         reg = readl(cmp->common.base + cmp->common.reg);
> -       reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
> +       if (cmp->m.width)
> +               reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
>         reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> -       reg |= (m - cmp->m.offset) << cmp->m.shift;
> +       if (cmp->m.width)
> +               reg |= (m - cmp->m.offset) << cmp->m.shift;
>         if (shift)
>                 reg |= ilog2(p) << cmp->p.shift;
>         else
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 1/5] clk: sunxi-ng: generalise update bit
  2026-09-17 22:39 ` [PATCH v2 1/5] clk: sunxi-ng: generalise update bit Andre Przywara
@ 2026-09-21 15:47   ` Chen-Yu Tsai
  0 siblings, 0 replies; 12+ messages in thread
From: Chen-Yu Tsai @ 2026-09-21 15:47 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
	linux-clk, devicetree, linux-arm-kernel, linux-sunxi

On Fri, Sep 18, 2026 at 6:39 AM Andre Przywara <andre.przywara@arm.com> wrote:
>
> A few of the Allwinner A523 CCU clock registers introduced an "update" bit,
> which must be set for changes to the other bits to take effect.
> Of the three clocks where this was used, it was always bit 27, so we just
> encoded this as a single bit feature flag.
>
> Now the CPU PLL also features the update bit, but puts it at bit 26, so
> this flag trick won't work anymore.
>
> Add an "update_bit" field to the common sunxi clock struct, which takes a
> bitmask, so we can encode any bit to use, even potentially multiple of
> them. As uninitialised fields are set to 0, we can use this as a default
> bitmask to set, so can OR this in unconditionally.
> It turns out that the "update key" feature is doing something very
> similar, so just convert it over to also use this same bitmask approach.
>
> Change the existing update bit users to use this new encoding, and add
> support for the ccu_nm clock on the way, since we will need it there
> shortly.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register
  2026-09-18  3:51   ` Chen-Yu Tsai
@ 2026-09-24  6:54     ` Andre Przywara
  0 siblings, 0 replies; 12+ messages in thread
From: Andre Przywara @ 2026-09-24  6:54 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
	linux-clk, devicetree, linux-arm-kernel, linux-sunxi

On Fri, 18 Sep 2026 11:51:19 +0800
Chen-Yu Tsai <wens@kernel.org> wrote:

Hi,

> On Fri, Sep 18, 2026 at 6:39 AM Andre Przywara <andre.przywara@arm.com> wrote:
> >
> > The "mp" clock models a mod clock with divider and a shift field. At
> > least one clock in the Allwinner A523 features just a power-of-2 divider
> > field, so support an initialisation of the clock without providing an
> > actual divider field.
> 
> Please just use the single divider clock type instead. It properly supports
> power-of-2 dividers.

Ah, indeed, there is SUNXI_CCU_P_DATA_WITH_MUX_GATE now, will drop this
patch then.

So when using that macro it looks like this:
static SUNXI_CCU_P_DATA_WITH_MUX_GATE(pll_cpu_l_div_clk, "pll-cpu-l-div",
                                      pll_cpu_l_hws, 0x060,
                                      16, 2,                    /* P */
                                      0, 0,                     /* no mux */
                                      0,                        /* no gate */
                                      CLK_SET_RATE_PARENT);     /* flags */

There are still some unused bits, does that look OK or shall I add a
macro that allows to skip mux and gate?
static SUNXI_CCU_P_DATA(pll_cpu_l_div_clk, "pll-cpu-l-div",
			pll_cpu_l_hws, 0x60,
			16, 2,			/* P */
			CLK_SET_RATE_PARENT);	/* flags */

Cheers,
Andre


> 
> ChenYu
> 
> > Add a check whether the "width" field is 0, and skip the divider
> > handling in this case, as the GENMASK macro will not work with a zero
> > length.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  drivers/clk/sunxi-ng/ccu_mp.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> > index 7cdb0eedc69b5..3896cb94bf733 100644
> > --- a/drivers/clk/sunxi-ng/ccu_mp.c
> > +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> > @@ -236,9 +236,11 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
> >         spin_lock_irqsave(cmp->common.lock, flags);
> >
> >         reg = readl(cmp->common.base + cmp->common.reg);
> > -       reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
> > +       if (cmp->m.width)
> > +               reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
> >         reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> > -       reg |= (m - cmp->m.offset) << cmp->m.shift;
> > +       if (cmp->m.width)
> > +               reg |= (m - cmp->m.offset) << cmp->m.shift;
> >         if (shift)
> >                 reg |= ilog2(p) << cmp->p.shift;
> >         else
> > --
> > 2.43.0
> >
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-09-24  6:59 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-17 22:39 [PATCH v2 0/5] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
2026-09-17 22:39 ` [PATCH v2 1/5] clk: sunxi-ng: generalise update bit Andre Przywara
2026-09-21 15:47   ` Chen-Yu Tsai
2026-09-17 22:39 ` [PATCH v2 2/5] clk: sunxi-ng: mp: support clocks with just a shift register Andre Przywara
2026-09-18  3:51   ` Chen-Yu Tsai
2026-09-24  6:54     ` Andre Przywara
2026-09-17 22:39 ` [PATCH v2 3/5] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
2026-09-17 22:46   ` sashiko-bot
2026-09-17 22:39 ` [PATCH v2 4/5] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
2026-09-17 22:51   ` sashiko-bot
2026-09-17 22:39 ` [PATCH v2 5/5] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara
2026-09-17 22:46   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox