Devicetree
 help / color / mirror / Atom feed
* [PATCH v3 0/4] arm64: allwinner: a523: Enable CPU clocks
@ 2026-09-25 22:51 Andre Przywara
  2026-09-25 22:51 ` [PATCH v3 1/4] clk: sunxi-ng: generalise update bit Andre Przywara
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Andre Przywara @ 2026-09-25 22:51 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,

an update for the A523 CPU clock series, aiming at eventually lifting
all A523 boards out of their current 768MHz misery ;-)
This addresses the comments on the list and from Sashiko, though I took
the freedom to ignore impossible scenarios (we cannot really remove this
clock module), and pathological corner cases (race condition between
registering the CCU and registering the clock notifiers).
Changes to mention are the usage of a new clock macro based on a divider
clock for the PLL dividers, and the rework of the PLL start routine. 
For a more complete changelog see below. Based on v7.3-rc1.

==============================
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.

Patch 1 adds some slight enhancement to the sunxi-ng clock driver
framework, to generalise the update bit.
Patch 2 adds the binding document for the new CCU.
Patch 3 adds the actual clock driver, and patch 4 makes use of that by
adding the clock description to the SoC .dtsi.

Please have a look and test!

Cheers,
Andre

Changes in v3:
- forbid #reset-cells in DT binding
- adjust top level comment to include DSU divider bits
- drop patch 2 in favour of using a div clock and a new macro
- describe PLL divider clocks using new divider clock macro
- rename 600MHz input clock name to match binding (lower case "m")
- add MUX notifier for DSU clock as well
- add new function to start CPU PLLs in a safer way
- add MODULE_DEVICE_TABLE
- drop unneeded (and now forbidden) #reset-cells from .dtsi
- only build driver for CONFIG_ARCH_SUNXI

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 (4):
  clk: sunxi-ng: generalise update bit
  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      |  38 +-
 .../arm64/boot/dts/allwinner/sun55i-a523.dtsi |  21 +
 drivers/clk/sunxi-ng/Kconfig                  |   5 +
 drivers/clk/sunxi-ng/Makefile                 |   2 +
 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c    | 378 ++++++++++++++++++
 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_div.h                |   5 +
 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 +
 .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   |  13 +
 16 files changed, 506 insertions(+), 30 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.46.4


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

* [PATCH v3 1/4] clk: sunxi-ng: generalise update bit
  2026-09-25 22:51 [PATCH v3 0/4] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
@ 2026-09-25 22:51 ` Andre Przywara
  2026-09-25 22:51 ` [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Andre Przywara @ 2026-09-25 22:51 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>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
---
 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.46.4


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

* [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  2026-09-25 22:51 [PATCH v3 0/4] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
  2026-09-25 22:51 ` [PATCH v3 1/4] clk: sunxi-ng: generalise update bit Andre Przywara
@ 2026-09-25 22:51 ` Andre Przywara
  2026-09-29  8:42   ` Krzysztof Kozlowski
  2026-09-25 22:51 ` [PATCH v3 3/4] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
  2026-09-25 22:51 ` [PATCH v3 4/4] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara
  3 siblings, 1 reply; 9+ messages in thread
From: Andre Przywara @ 2026-09-25 22:51 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      | 38 ++++++++++++++++++-
 .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   | 13 +++++++
 2 files changed, 50 insertions(+), 1 deletion(-)
 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..8d5481fb63ae8 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
 
@@ -35,12 +36,23 @@ properties:
 
 required:
   - "#clock-cells"
-  - "#reset-cells"
   - compatible
   - reg
   - clocks
   - clock-names
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: allwinner,sun55i-a523-cpu-ccu
+then:
+  properties:
+    "#reset-cells": false
+else:
+  required:
+    - "#reset-cells"
+
 allOf:
   - if:
       properties:
@@ -64,6 +76,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.46.4


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

* [PATCH v3 3/4] clk: sunxi-ng: add support for the A523/T527 CPU CCU
  2026-09-25 22:51 [PATCH v3 0/4] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
  2026-09-25 22:51 ` [PATCH v3 1/4] clk: sunxi-ng: generalise update bit Andre Przywara
  2026-09-25 22:51 ` [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
@ 2026-09-25 22:51 ` Andre Przywara
  2026-09-25 23:06   ` sashiko-bot
  2026-09-25 22:51 ` [PATCH v3 4/4] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara
  3 siblings, 1 reply; 9+ messages in thread
From: Andre Przywara @ 2026-09-25 22:51 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 | 378 +++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.h |  24 ++
 drivers/clk/sunxi-ng/ccu_div.h             |   5 +
 5 files changed, 414 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..b2d8efa231cf2 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 ARCH_SUNXI
+	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..ef1b05b2a9b58
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
@@ -0,0 +1,378 @@
+// 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 till 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      |   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/iopoll.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 },
+};
+
+/*
+ * These are just the divider parts of the CPU clocks, even when the mux
+ * field is in the same register. As the divider only applied to the CPU
+ * clocks, this has to be handled separately.
+ */
+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);
+static SUNXI_CCU_P_DATA(pll_cpu_b_div_clk, "pll-cpu-b-div",
+			pll_cpu_b_hws, 0x064,
+			16, 2,				/* P */
+			CLK_SET_RATE_PARENT);
+static SUNXI_CCU_P_DATA(pll_cpu_dsu_div_clk, "pll-cpu-dsu-div",
+			pll_cpu_dsu_hws, 0x06c,
+			16, 2,				/* P */
+			CLK_SET_RATE_PARENT);
+
+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 struct ccu_mux_nb sun55i_a523_cpu_dsu_nb = {
+	.common		= &cpu_dsu_clk.common,
+	.cm		= &cpu_dsu_clk.mux,
+	.delay_us	= 1, /* manual doesn't really say */
+	.bypass_index	= 5, /* PLL_PERI0@600MHz, as recommended by manual */
+};
+
+static int sun55i_a523_start_pll(void __iomem *reg)
+{
+	u32 val = readl(reg);
+
+	/* check if the bootloader had the PLL already running and locked */
+	if ((val & GENMASK(31, 28)) == GENMASK(31, 28)) {
+		/* If the dividers are already set to 1 (encoded as 0) ... */
+		if (!(val & GENMASK(21, 16)))
+			return 0;
+
+		/*
+		 * The PLL is already running, but the P and M0 dividers are
+		 * not programmed to 1, which we assume in our formula above.
+		 * If we just clear them, the frequency jumps up by at least
+		 * a factor of 2, probably crashing the system.
+		 * So we need TODO:
+		 * - remux the consumer (a different register!)
+		 * - gate the PLL
+		 * - set the factor to match M0==P==1
+		 * - ungate the PLL
+		 * - wait for the PLL to lock
+		 * - remux
+		 * For now just be a diva: U-Boot does the right thing already.
+		 */
+		return -EEXIST;
+	}
+
+	/* set the enable, the LDO and the lock bits, and clear dividers */
+	val |= BIT(31) | BIT(30) | BIT(29) | BIT(26);
+	val &= ~GENMASK(21, 16); /* covering PLL_P and PLL_M0 */
+	writel(val, reg);
+
+	/* wait for the lock bit */
+	return readl_relaxed_poll_timeout(reg, val, val & BIT(28), 100, 70000);
+}
+
+static int sun55i_a523_cpu_ccu_probe(struct platform_device *pdev)
+{
+	const struct sunxi_ccu_desc *desc;
+	void __iomem *reg;
+	int i, ret;
+
+	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.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+		ret = sun55i_a523_start_pll(reg + pll_regs[i]);
+		if (ret)
+			return ret;
+	}
+
+	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
+	if (ret)
+		return ret;
+
+	/* Reparent CPUs/DSU during 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);
+	ccu_mux_notifier_register(pll_cpu_dsu_clk.common.hw.clk,
+				  &sun55i_a523_cpu_dsu_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,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun55i_a523_cpu_ccu_ids);
+
+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 */
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index a30a92780a051..e5a15857a0547 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -292,6 +292,11 @@ struct ccu_div {
 		},							\
 	}
 
+#define SUNXI_CCU_P_DATA(_struct, _name, _parents, _reg,		\
+			 _pshift, _pwidth, _flags)			\
+	SUNXI_CCU_P_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+				       _pshift, _pwidth, 0, 0, 0, _flags)
+
 static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
 {
 	struct ccu_common *common = hw_to_ccu_common(hw);
-- 
2.46.4


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

* [PATCH v3 4/4] arm64: dts: allwinner: a523: add CPU clocks
  2026-09-25 22:51 [PATCH v3 0/4] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
                   ` (2 preceding siblings ...)
  2026-09-25 22:51 ` [PATCH v3 3/4] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
@ 2026-09-25 22:51 ` Andre Przywara
  3 siblings, 0 replies; 9+ messages in thread
From: Andre Przywara @ 2026-09-25 22:51 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 | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
index 85ef492ffeae7..d8aa13af3935e 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,17 @@ 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>;
+		};
 	};
 };
-- 
2.46.4


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

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

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] clk: sunxi-ng: race condition exposes clock provider before notifiers are active
--

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

clk: sunxi-ng: add support for the A523/T527 CPU CCU
    
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.

> 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..ef1b05b2a9b58
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-cpu.c
> @@ -0,0 +1,378 @@

[ ... ]

> +static int sun55i_a523_cpu_ccu_probe(struct platform_device *pdev)
> +{
> +	const struct sunxi_ccu_desc *desc;
> +	void __iomem *reg;
> +	int i, ret;

[ ... ]

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

[Severity: Medium]
Could this expose the clock provider before the notifiers are registered?

If devm_sunxi_ccu_probe() publishes the clock provider globally, and the
thread is preempted immediately after it returns, could deferred probe
workqueues run asynchronously and probe a consumer?

If a consumer like cpufreq then calls clk_set_rate() before the subsequent
ccu_mux_notifier_register() calls are executed, would the PLL relock
without reparenting the CPU, potentially leading to a system crash?

> +	ccu_mux_notifier_register(pll_cpu_b_clk.common.hw.clk,
> +				  &sun55i_a523_cpu_b_nb);
> +	ccu_mux_notifier_register(pll_cpu_dsu_clk.common.hw.clk,
> +				  &sun55i_a523_cpu_dsu_nb);
> +
> +	return ret;
> +}

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

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

* Re: [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  2026-09-25 22:51 ` [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
@ 2026-09-29  8:42   ` Krzysztof Kozlowski
  2026-10-04 22:50     ` Andre Przywara
  0 siblings, 1 reply; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-29  8:42 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, linux-clk, devicetree, linux-arm-kernel,
	linux-sunxi

On Sat, Sep 26, 2026 at 12:51:10AM +0200, Andre Przywara wrote:
> 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      | 38 ++++++++++++++++++-
>  .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   | 13 +++++++
>  2 files changed, 50 insertions(+), 1 deletion(-)
>  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..8d5481fb63ae8 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
>  
> @@ -35,12 +36,23 @@ properties:
>  
>  required:
>    - "#clock-cells"
> -  - "#reset-cells"
>    - compatible
>    - reg
>    - clocks
>    - clock-names
>  
> +if:

This goes to the allOf block.

> +  properties:
> +    compatible:
> +      contains:
> +        const: allwinner,sun55i-a523-cpu-ccu
> +then:
> +  properties:
> +    "#reset-cells": false
> +else:
> +  required:
> +    - "#reset-cells"
> +
>  allOf:
>    - if:
>        properties:
> @@ -64,6 +76,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

Filename should match compatible.

> @@ -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

Indices start from 0 or 1

Best regards,
Krzysztof


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

* Re: [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  2026-09-29  8:42   ` Krzysztof Kozlowski
@ 2026-10-04 22:50     ` Andre Przywara
  2026-10-06 16:03       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 9+ messages in thread
From: Andre Przywara @ 2026-10-04 22:50 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, linux-clk, devicetree, linux-arm-kernel,
	linux-sunxi

On Tue, 29 Sep 2026 10:42:29 +0200
Krzysztof Kozlowski <krzk@kernel.org> wrote:

Hi Krzysztof,

thanks for the review!

> On Sat, Sep 26, 2026 at 12:51:10AM +0200, Andre Przywara wrote:
> > 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      | 38 ++++++++++++++++++-
> >  .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   | 13 +++++++
> >  2 files changed, 50 insertions(+), 1 deletion(-)
> >  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..8d5481fb63ae8 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
> >  
> > @@ -35,12 +36,23 @@ properties:
> >  
> >  required:
> >    - "#clock-cells"
> > -  - "#reset-cells"
> >    - compatible
> >    - reg
> >    - clocks
> >    - clock-names
> >  
> > +if:
> 
> This goes to the allOf block.

OK.

> > +  properties:
> > +    compatible:
> > +      contains:
> > +        const: allwinner,sun55i-a523-cpu-ccu
> > +then:
> > +  properties:
> > +    "#reset-cells": false
> > +else:
> > +  required:
> > +    - "#reset-cells"
> > +
> >  allOf:
> >    - if:
> >        properties:
> > @@ -64,6 +76,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
> 
> Filename should match compatible.

Is that a new requirement? We never did this for the Allwinner clock or
reset bindings, all headers are named like sun<x>i-<soc>-<name>-ccu.h.
And I think especially since we have sun55i-a523-mcu-ccu.h and
sun55i-a523-r-ccu.h, I think we should stay consistent, at least for
the existing SoCs.

> > @@ -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
> 
> Indices start from 0 or 1

This is also something very common for Allwinner clocks: the CCU has
clocks that are not exposed to the DT, because they are internal
clocks we need to model the clock tree. We number them logically,
and often the basic clocks are not exposed. See sun50i-a64-ccu.h,
sun50i-h616-ccu.h, sun8i-h3-ccu.h, to just name a few (there are many
more). The other clocks are named in the internal headers, in the
clock driver directory.

Cheers,
Andre

 
> 
> Best regards,
> Krzysztof
> 
> 


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

* Re: [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller
  2026-10-04 22:50     ` Andre Przywara
@ 2026-10-06 16:03       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-10-06 16:03 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Stephen Boyd, Brian Masney, Jerome Brunet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, linux-clk, devicetree, linux-arm-kernel,
	linux-sunxi

On 05/10/2026 00:50, Andre Przywara wrote:
> On Tue, 29 Sep 2026 10:42:29 +0200
> Krzysztof Kozlowski <krzk@kernel.org> wrote:
> 
> Hi Krzysztof,
> 
> thanks for the review!
> 
>> On Sat, Sep 26, 2026 at 12:51:10AM +0200, Andre Przywara wrote:
>>> 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      | 38 ++++++++++++++++++-
>>>  .../dt-bindings/clock/sun55i-a523-cpu-ccu.h   | 13 +++++++
>>>  2 files changed, 50 insertions(+), 1 deletion(-)
>>>  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..8d5481fb63ae8 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
>>>  
>>> @@ -35,12 +36,23 @@ properties:
>>>  
>>>  required:
>>>    - "#clock-cells"
>>> -  - "#reset-cells"
>>>    - compatible
>>>    - reg
>>>    - clocks
>>>    - clock-names
>>>  
>>> +if:
>>
>> This goes to the allOf block.
> 
> OK.
> 
>>> +  properties:
>>> +    compatible:
>>> +      contains:
>>> +        const: allwinner,sun55i-a523-cpu-ccu
>>> +then:
>>> +  properties:
>>> +    "#reset-cells": false
>>> +else:
>>> +  required:
>>> +    - "#reset-cells"
>>> +
>>>  allOf:
>>>    - if:
>>>        properties:
>>> @@ -64,6 +76,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
>>
>> Filename should match compatible.
> 
> Is that a new requirement? We never did this for the Allwinner clock or
> reset bindings, all headers are named like sun<x>i-<soc>-<name>-ccu.h.

I say EXACTLY the same thing for ~4 years, so yes. New requirement since
4 years. Allwinner for sure received same feedback already.

> And I think especially since we have sun55i-a523-mcu-ccu.h and
> sun55i-a523-r-ccu.h, I think we should stay consistent, at least for
> the existing SoCs.
> 
>>> @@ -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
>>
>> Indices start from 0 or 1
> 
> This is also something very common for Allwinner clocks: the CCU has
> clocks that are not exposed to the DT, because they are internal
> clocks we need to model the clock tree. We number them logically,

They are not ABI thus do not create impression they should be and you
prepare some placeholder for them.

These are not IDs of your clocks in the hardware. This is only the ABI.

Again, same feedback I repeat for 4 years.

Best regards,
Krzysztof

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

end of thread, other threads:[~2026-10-06 16:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-25 22:51 [PATCH v3 0/4] arm64: allwinner: a523: Enable CPU clocks Andre Przywara
2026-09-25 22:51 ` [PATCH v3 1/4] clk: sunxi-ng: generalise update bit Andre Przywara
2026-09-25 22:51 ` [PATCH v3 2/4] dt-bindings: clock: sun55i-a523-ccu: Add A523 CPU CCU clock controller Andre Przywara
2026-09-29  8:42   ` Krzysztof Kozlowski
2026-10-04 22:50     ` Andre Przywara
2026-10-06 16:03       ` Krzysztof Kozlowski
2026-09-25 22:51 ` [PATCH v3 3/4] clk: sunxi-ng: add support for the A523/T527 CPU CCU Andre Przywara
2026-09-25 23:06   ` sashiko-bot
2026-09-25 22:51 ` [PATCH v3 4/4] arm64: dts: allwinner: a523: add CPU clocks Andre Przywara

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