[PATCH 05/11] clock: a733: implement support for mmc/uart

Yixun Lan dlan at gentoo.org
Sun Nov 16 15:43:56 CET 2025


Add clock initialization support to set UART/I2C/MMC clock frequency.

Signed-off-by: Yixun Lan <dlan at gentoo.org>

---
In this version, we create a dedicated clock_sun60i_a733.h file, maybe
we should further refactor the code to make it merged into exist
clock_sun50i_h6.h file.
---
 arch/arm/include/asm/arch-sunxi/clock.h            |   2 +
 .../arm/include/asm/arch-sunxi/clock_sun60i_a733.h | 179 +++++++++++++++++++++
 arch/arm/include/asm/arch-sunxi/cpu.h              |   2 +
 arch/arm/mach-sunxi/Makefile                       |   1 +
 arch/arm/mach-sunxi/clock_sun60i_a733.c            |  80 +++++++++
 5 files changed, 264 insertions(+)

diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index fcc8966cb0b..105c3804102 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -19,6 +19,8 @@
 #include <asm/arch/clock_sun8i_a83t.h>
 #elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
 #include <asm/arch/clock_sun50i_h6.h>
+#elif defined(CONFIG_MACH_SUN60I_A733)
+#include <asm/arch/clock_sun60i_a733.h>
 #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
       defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
 #include <asm/arch/clock_sun6i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun60i_a733.h b/arch/arm/include/asm/arch-sunxi/clock_sun60i_a733.h
new file mode 100644
index 00000000000..819a5c6cf8d
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun60i_a733.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Allwinner A733 clock register definitions
+ */
+
+#ifndef _SUNXI_CLOCK_SUN60I_A733_H
+#define _SUNXI_CLOCK_SUN60I_A733_H
+
+#ifndef __ASSEMBLY__
+#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			0x0a0 /* PLL_PERI0_CTRL_REG */
+
+#define CCU_H6_CPU_AXI_CFG		0x500
+#define CCU_H6_PSI_AHB1_AHB2_CFG	0x510
+#define CCU_H6_AHB3_CFG			0x51c
+#define CCU_H6_APB1_CFG			0x520
+#define CCU_H6_APB2_CFG			0x524
+#define CCU_H6_MBUS_CFG			0x540
+#define CCU_H6_DRAM_CLK_CFG		0x800
+#define CCU_H6_DRAM_GATE_RESET		0x80c
+#define CCU_MMC0_CLK_CFG		0x830
+#define CCU_MMC1_CLK_CFG		0x834
+#define CCU_MMC2_CLK_CFG		0x838
+#define CCU_H6_MMC_GATE_RESET		0x84c
+#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
+
+/* A733 MISC offsets */
+#define CCU_A733_APB0_CFG			0x510
+#define CCU_A733_APB1_CFG			0x518
+#define CCU_A733_APB_UART_CLK_CFG	0x538
+#define CCU_A733_UART_GATE_RESET	0xe00
+
+/* PLL bit fields */
+#define CCM_PLL_CTRL_EN			BIT(31)
+#define CCM_PLL_LDO_EN			BIT(30)
+#define CCM_PLL_LOCK_EN			BIT(29)
+#define CCM_PLL_LOCK			BIT(28)
+#define CCM_PLL_OUT_EN			BIT(27)
+#define CCM_PLL1_UPDATE			BIT(26)
+#define CCM_PLL1_CTRL_P(p)		((p) << 16)
+#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)
+#define CCM_PLL5_CTRL_DIV2(div0)	((div0) << 1)
+
+/* pll6 bit field */
+#define CCM_PLL6_CTRL_P0_SHIFT		20
+#define CCM_PLL6_CTRL_P0_MASK		(0x7 << CCM_PLL6_CTRL_P0_SHIFT)
+#define CCM_PLL6_CTRL_N_SHIFT		8
+#define CCM_PLL6_CTRL_N_MASK		(0xff << CCM_PLL6_CTRL_N_SHIFT)
+#define CCM_PLL6_CTRL_DIV1_SHIFT	0
+#define CCM_PLL6_CTRL_DIV1_MASK		(0x1 << CCM_PLL6_CTRL_DIV1_SHIFT)
+#define CCM_PLL6_CTRL_DIV2_SHIFT	1
+#define CCM_PLL6_CTRL_DIV2_MASK		(0x1 << CCM_PLL6_CTRL_DIV2_SHIFT)
+
+/* cpu_axi bit field*/
+#define CCM_CPU_AXI_MUX_MASK		(0x3 << 24)
+#define CCM_CPU_AXI_MUX_OSC24M		(0x0 << 24)
+#define CCM_CPU_AXI_MUX_PLL_CPUX	(0x3 << 24)
+#define CCM_CPU_AXI_APB_MASK		0x300
+#define CCM_CPU_AXI_AXI_MASK		0x3
+#define CCM_CPU_AXI_DEFAULT_FACTORS	0x301
+
+#ifdef CONFIG_MACH_SUN50I_H6				/* H6 */
+
+#define CCM_PLL6_DEFAULT		0xa0006300
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000102
+#define CCM_AHB3_DEFAULT		0x03000002
+#define CCM_APB1_DEFAULT		0x03000102
+
+#elif CONFIG_MACH_SUN50I_H616				/* H616 */
+
+#define CCM_PLL6_DEFAULT		0xa8003100
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002
+#define CCM_AHB3_DEFAULT		0x03000002
+#define CCM_APB1_DEFAULT		0x03000102
+
+#elif CONFIG_MACH_SUN8I_R528				/* R528 */
+
+#define CCM_PLL6_DEFAULT		0xe8216300
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002
+#define CCM_APB1_DEFAULT		0x03000102
+
+#elif CONFIG_MACH_SUN55I_A523				/* A523 */
+
+#define CCM_PLL6_DEFAULT		0xe8116310	    /* 1200 MHz */
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002	    /* 200 MHz */
+#define CCM_APB1_DEFAULT		0x03000005	    /* APB0 really */
+#define CCM_APB2_DEFAULT		0x03000005	    /* APB1 really */
+
+#elif CONFIG_MACH_SUN60I_A733				/* A733 */
+
+#define CCM_PLL6_DEFAULT		0xe8116310	    /* 1200 MHz */
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002	    /* 200 MHz */
+#define CCM_APB1_DEFAULT		0x03000005	    /* APB0 really */
+#define CCM_APB2_DEFAULT		0x03000005	    /* APB1 really */
+
+#endif
+
+/* apb2 bit field */
+#define APB2_CLK_SRC_OSC24M		(0x0 << 24)
+#define APB2_CLK_SRC_OSC32K		(0x1 << 24)
+#define APB2_CLK_SRC_PSI		(0x2 << 24)
+#define APB2_CLK_SRC_PLL6		(0x3 << 24)
+#define APB2_CLK_SRC_MASK		(0x3 << 24)
+#define APB2_CLK_RATE_N_1		(0x0 << 8)
+#define APB2_CLK_RATE_N_2		(0x1 << 8)
+#define APB2_CLK_RATE_N_4		(0x2 << 8)
+#define APB2_CLK_RATE_N_8		(0x3 << 8)
+#define APB2_CLK_RATE_N_MASK		(3 << 8)
+#define APB2_CLK_RATE_M(m)		(((m) - 1) << 0)
+#define APB2_CLK_RATE_M_MASK            (3 << 0)
+
+/* MBUS clock bit field */
+#define MBUS_ENABLE			BIT(31)
+#define MBUS_RESET			BIT(30)
+#define MBUS_UPDATE			BIT(27)
+#define MBUS_CLK_SRC_MASK		GENMASK(25, 24)
+#define MBUS_CLK_SRC_OSCM24		(0 << 24)
+#define MBUS_CLK_SRC_PLL6X2		(1 << 24)
+#define MBUS_CLK_SRC_PLL5		(2 << 24)
+#define MBUS_CLK_SRC_PLL6X4		(3 << 24)
+#define MBUS_CLK_M(m)			(((m) - 1) << 0)
+
+/* Module gate/reset shift*/
+#define RESET_SHIFT			(16)
+#define GATE_SHIFT			(0)
+
+/* DRAM clock bit field */
+#define DRAM_CLK_ENABLE			BIT(31)
+#define DRAM_MOD_RESET			BIT(30)
+#define DRAM_CLK_UPDATE			BIT(27)
+#define DRAM_CLK_SRC_MASK		GENMASK(25, 24)
+#define DRAM_CLK_SRC_PLL5		(0 << 24)
+#define DRAM_CLK_M_MASK			(0x1f)
+#define DRAM_CLK_M(m)			(((m) - 1) << 0)
+
+/* MMC clock bit field */
+#define CCM_MMC_CTRL_M(x)		((x) - 1)
+#define CCM_MMC_CTRL_N(x)		((x) << 8)
+#define CCM_MMC_CTRL_OSCM24		(0x0 << 24)
+#define CCM_MMC_CTRL_PLL6		(0x1 << 24)
+#define CCM_MMC_CTRL_PLL_PERIPH2X2	(0x2 << 24)
+#define CCM_MMC_CTRL_ENABLE		(0x1 << 31)
+/* H6 doesn't have these delays */
+#define CCM_MMC_CTRL_OCLK_DLY(a)	((void)(a), 0)
+#define CCM_MMC_CTRL_SCLK_DLY(a)	((void)(a), 0)
+
+#ifndef __ASSEMBLY__
+void clock_set_pll1(unsigned int hz);
+unsigned int clock_get_pll6(void);
+#endif
+
+#endif /* _SUNXI_CLOCK_SUN60I_A733_H */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index 768c6572d6b..3fd247e75a7 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -12,6 +12,8 @@
 #include <asm/arch/cpu_sun50i_h6.h>
 #elif defined(CONFIG_SUNXI_GEN_NCAT2)
 #include <asm/arch/cpu_sunxi_ncat2.h>
+#elif defined(CONFIG_MACH_SUN60I_A733)
+#include <asm/arch/cpu_sunxi_a733.h>
 #else
 #include <asm/arch/cpu_sun4i.h>
 #endif
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 9c79b55abf3..8e37e3315ca 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -25,6 +25,7 @@ endif
 obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
 obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
 obj-$(CONFIG_SUNXI_GEN_NCAT2)	+= clock_sun50i_h6.o
+obj-$(CONFIG_MACH_SUN60I_A733)	+= clock_sun60i_a733.o
 ifndef CONFIG_ARM64
 obj-y	+= timer.o
 endif
diff --git a/arch/arm/mach-sunxi/clock_sun60i_a733.c b/arch/arm/mach-sunxi/clock_sun60i_a733.c
new file mode 100644
index 00000000000..9e07ccefc32
--- /dev/null
+++ b/arch/arm/mach-sunxi/clock_sun60i_a733.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clock.h>
+#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)
+{
+}
+
+void clock_init_uart(void)
+{
+	void *const ccm = (void *)SUNXI_CCM_BASE;
+
+	/* uart clock source is apb2 */
+	writel(APB2_CLK_SRC_OSC24M |
+	       APB2_CLK_RATE_N_1 |
+	       APB2_CLK_RATE_M(1),
+	       ccm + CCU_A733_APB1_CFG);
+
+	/* uart clock source */
+	writel(APB2_CLK_SRC_OSC24M |
+	       APB2_CLK_RATE_N_1 |
+	       APB2_CLK_RATE_M(1),
+	       ccm + CCU_A733_APB_UART_CLK_CFG);
+
+	/* open the clock for uart */
+	setbits_le32(ccm + CCU_A733_UART_GATE_RESET,
+		     1 << (CONFIG_CONS_INDEX - 1));
+
+	/* deassert uart reset */
+	setbits_le32(ccm + CCU_A733_UART_GATE_RESET,
+		     1 << (RESET_SHIFT + CONFIG_CONS_INDEX - 1));
+}
+
+void clock_set_pll1(unsigned int clk)
+{
+	/* Do not support clocks < 288MHz as they need factor P */
+	if (clk < 288000000)
+		clk = 288000000;
+
+	clk /= 24000000;
+}
+
+int clock_twi_onoff(int port, int state)
+{
+	return 0;
+}
+#endif /* CONFIG_XPL_BUILD */
+
+/* PLL_PERIPH0 clock, used by the MMC driver */
+unsigned int clock_get_pll6(void)
+{
+	void *const ccm = (void *)SUNXI_CCM_BASE;
+	u32 rval = readl(ccm + CCU_H6_PLL6_CFG);
+	int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
+	int div1, m;
+
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) || IS_ENABLED(CONFIG_MACH_SUN60I_A733)) {
+		div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
+			CCM_PLL6_CTRL_P0_SHIFT) + 1;
+		m = ((rval >> 1) & 1) + 1;
+	} else {
+		div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+			CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+		if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+			m = 4;
+		else
+			m = 2;
+	}
+
+	return 24000000U * n / m / div1;
+}

-- 
2.51.2



More information about the U-Boot mailing list