[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