diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 5d6519d2367..5881ab88573 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -13,6 +13,7 @@
 #include <linux/bitops.h>
 #endif
 
+/* Main CCU register offsets */
 #define CCU_H6_PLL1_CFG			0x000
 #define CCU_H6_PLL5_CFG			0x010
 #define CCU_H6_PLL6_CFG			0x020
@@ -31,6 +32,14 @@
 #define CCU_H6_UART_GATE_RESET		0x90c
 #define CCU_H6_I2C_GATE_RESET		0x91c
 
+/* A523 CPU PLL offsets */
+#define CPC_CPUA_PLL_CTRL		0x04
+#define CPC_DSU_PLL_CTRL		0x08
+#define CPC_CPUB_PLL_CTRL		0x0c
+#define CPC_CPUA_CLK_REG		0x60
+#define CPC_CPUB_CLK_REG		0x64
+#define CPC_DSU_CLK_REG			0x6c
+
 /* PLL bit fields */
 #define CCM_PLL_CTRL_EN			BIT(31)
 #define CCM_PLL_LDO_EN			BIT(30)
@@ -42,6 +51,14 @@
 #define CCM_PLL1_CTRL_N_MASK		GENMASK(15, 8)
 #define CCM_PLL1_CTRL_N(n)		(((n) - 1) << 8)
 
+/* A523 CPU clock fields */
+#define CPU_CLK_SRC_HOSC		(0 << 24)
+#define CPU_CLK_SRC_CPUPLL		(3 << 24)
+#define CPU_CLK_CTRL_P(p)		((p) << 16)
+#define CPU_CLK_APB_DIV(n)		(((n) - 1) << 8)
+#define CPU_CLK_PERI_DIV(m1)		(((m1) - 1) << 2)
+#define CPU_CLK_AXI_DIV(m)		(((m) - 1) << 0)
+
 /* pll5 bit field */
 #define CCM_PLL5_CTRL_N(n)		(((n) - 1) << 8)
 #define CCM_PLL5_CTRL_DIV1(div1)	((div1) << 0)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
index 908a582ae0f..c04ddb3f1d4 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
@@ -30,6 +30,8 @@
 
 #define SUNXI_CPUCFG_BASE		0x09010000
 
+#define SUNXI_CPU_PLL_CFG_BASE		0x08817000
+
 #ifndef __ASSEMBLY__
 void sunxi_board_init(void);
 void sunxi_reset(void);
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 84064c4ed86..3a4399a9c6c 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -6,6 +6,10 @@
 #include <asm/arch/prcm.h>
 #include <linux/delay.h>
 
+#ifndef SUNXI_CPU_PLL_CFG_BASE
+#define SUNXI_CPU_PLL_CFG_BASE 0
+#endif
+
 #ifdef CONFIG_XPL_BUILD
 void clock_init_safe(void)
 {
@@ -120,6 +124,37 @@ static void clock_set_pll(u32 *reg, unsigned int n)
 	}
 }
 
+/* Program the PLLs for both clusters plus the DSU. */
+static void clock_a523_set_cpu_plls(unsigned int n_factor)
+{
+	void *const cpc = (void *)SUNXI_CPU_PLL_CFG_BASE;
+	u32 val;
+
+	val = CPU_CLK_SRC_HOSC | CPU_CLK_CTRL_P(0) |
+	       CPU_CLK_APB_DIV(4) | CPU_CLK_PERI_DIV(2) |
+	       CPU_CLK_AXI_DIV(2);
+
+	/* Switch CPU clock source to 24MHz HOSC while changing the PLL */
+	writel(val, cpc + CPC_CPUA_CLK_REG);
+	writel(val, cpc + CPC_CPUB_CLK_REG);
+	udelay(20);
+	writel(CPU_CLK_SRC_HOSC | CPU_CLK_CTRL_P(0),
+	       cpc + CPC_DSU_CLK_REG);
+	udelay(20);
+
+	clock_set_pll(cpc + CPC_CPUA_PLL_CTRL, n_factor);
+	clock_set_pll(cpc + CPC_CPUB_PLL_CTRL, n_factor);
+	clock_set_pll(cpc + CPC_DSU_PLL_CTRL, n_factor);
+
+	/* Switch CPU clock source to the CPU PLL */
+	clrsetbits_le32(cpc + CPC_CPUA_CLK_REG, CPU_CLK_SRC_HOSC,
+			CPU_CLK_SRC_CPUPLL);
+	clrsetbits_le32(cpc + CPC_CPUB_CLK_REG, CPU_CLK_SRC_HOSC,
+			CPU_CLK_SRC_CPUPLL);
+	clrsetbits_le32(cpc + CPC_DSU_CLK_REG, CPU_CLK_SRC_HOSC,
+			CPU_CLK_SRC_CPUPLL);
+}
+
 static void clock_h6_set_cpu_pll(unsigned int n_factor)
 {
 	void *const ccm = (void *)SUNXI_CCM_BASE;
@@ -148,7 +183,10 @@ void clock_set_pll1(unsigned int clk)
 
 	clk /= 24000000;
 
-	clock_h6_set_cpu_pll(clk);
+	if (IS_ENABLED(CONFIG_MACH_SUN55I_A523))
+		clock_a523_set_cpu_plls(clk);
+	else
+		clock_h6_set_cpu_pll(clk);
 }
 
 int clock_twi_onoff(int port, int state)
