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

Andre Przywara andre.przywara at arm.com
Tue Nov 18 02:05:27 CET 2025


On Sun, 16 Nov 2025 14:43:56 +0000
Yixun Lan <dlan at gentoo.org> wrote:

Hi,

> 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

This new file looks like mostly a copy of clock_sun50i_h6.h. Can you
please merge both, and define differently just the very few register
offsets that actually differ? This includes clock_sun50i_h6.c and
clock_sun60i_a733.c.

Cheers,
Andre

> @@ -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;
> +}
> 



More information about the U-Boot mailing list