Re: [PATCH v5 4/8] clk: sunxi-ng: a733: Add PLL clocks support

From: Chen-Yu Tsai

Date: Sun Oct 04 2026 - 06:12:21 EST


On Tue, Sep 29, 2026 at 7:28 PM Junhui Liu <junhui.liu@xxxxxxxxxxxxx> wrote:
>
> Add PLL clock support for the main CCU of the Allwinner A733 SoC. The
> structure is mostly similar to the sun55i, with the addition of a
> PLL_REF clock that normalizes the hardware-detected DCXO/hosc frequency
> (19.2MHz, 24MHz, or 26MHz) into a consistent 24MHz reference for all
> subsequent PLLs.
>
> Model the independently gated outputs of the peripheral, video, and DE
> PLLs as programmable-divider child clocks, with each output gate modeled
> separately. Follow the documented hierarchy for the derived peripheral
> PLL outputs.
>
> PLL_AUDIO0 uses SDM parameters from the vendor driver to provide a
> 22.5792MHz * 4 output. PLL_AUDIO1 provides fixed /2 and /5 outputs and
> does not expose fractional rates, but its SDM controls are modeled so
> that stale firmware settings can be disabled when an integer rate is
> programmed.
>
> Tested-by: Jerome Brunet <jbrunet@xxxxxxxxxxxx>
> Signed-off-by: Junhui Liu <junhui.liu@xxxxxxxxxxxxx>
> ---
> drivers/clk/sunxi-ng/Kconfig | 5 +
> drivers/clk/sunxi-ng/Makefile | 2 +
> drivers/clk/sunxi-ng/ccu-sun60i-a733.c | 582 +++++++++++++++++++++++++++++++++
> 3 files changed, 589 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index 202e793dc754..cffa83056934 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 SUN60I_A733_CCU
> + tristate "Support for the Allwinner A733 CCU"
> + default ARCH_SUNXI
> + depends on ARM64 || COMPILE_TEST
> +
> config SUN60I_A733_R_CCU
> tristate "Support for the Allwinner A733 PRCM CCU"
> default ARCH_SUNXI
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index d3702bdb7a23..3a39eb9287da 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_SUN60I_A733_CCU) += sun60i-a733-ccu.o
> obj-$(CONFIG_SUN60I_A733_R_CCU) += sun60i-a733-r-ccu.o
> obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
> obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
> @@ -65,6 +66,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
> +sun60i-a733-ccu-y += ccu-sun60i-a733.o
> sun60i-a733-r-ccu-y += ccu-sun60i-a733-r.o
> sun4i-a10-ccu-y += ccu-sun4i-a10.o
> sun5i-ccu-y += ccu-sun5i.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun60i-a733.c b/drivers/clk/sunxi-ng/ccu-sun60i-a733.c
> new file mode 100644
> index 000000000000..430a535919c6
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun60i-a733.c
> @@ -0,0 +1,582 @@

[...]

> +#define SUN60I_A733_PLL_VIDEO0_REG 0x120
> +static struct ccu_nm pll_video0_clk = {
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = SUN60I_A733_PLL_VIDEO0_REG,
> + .hw.init = CLK_HW_INIT_PARENTS_HW("pll-video0", pll_ref_hws,
> + &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video0_hws[] = {
> + &pll_video0_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_video0_4x_clk, "pll-video0-4x",
> + pll_video0_hws, SUN60I_A733_PLL_VIDEO0_REG,
> + 20, 3, BIT(27), 0);
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_video0_3x_clk, "pll-video0-3x",
> + pll_video0_hws, SUN60I_A733_PLL_VIDEO0_REG,
> + 16, 3, BIT(26), 0);

You probably want CLK_SET_RATE_PARENT on these child clks, otherwise their
consumers can't properly set any rate they need?

> +
> +#define SUN60I_A733_PLL_VIDEO1_REG 0x140
> +static struct ccu_nm pll_video1_clk = {
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = SUN60I_A733_PLL_VIDEO1_REG,
> + .hw.init = CLK_HW_INIT_PARENTS_HW("pll-video1", pll_ref_hws,
> + &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video1_hws[] = {
> + &pll_video1_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_video1_4x_clk, "pll-video1-4x",
> + pll_video1_hws, SUN60I_A733_PLL_VIDEO1_REG,
> + 20, 3, BIT(27), 0);
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_video1_3x_clk, "pll-video1-3x",
> + pll_video1_hws, SUN60I_A733_PLL_VIDEO1_REG,
> + 16, 3, BIT(26), 0);

Same for these two.

> +
> +#define SUN60I_A733_PLL_VIDEO2_REG 0x160
> +static struct ccu_nm pll_video2_clk = {
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = SUN60I_A733_PLL_VIDEO2_REG,
> + .hw.init = CLK_HW_INIT_PARENTS_HW("pll-video2", pll_ref_hws,
> + &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video2_hws[] = {
> + &pll_video2_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_video2_4x_clk, "pll-video2-4x",
> + pll_video2_hws, SUN60I_A733_PLL_VIDEO2_REG,
> + 20, 3, BIT(27), 0);
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_video2_3x_clk, "pll-video2-3x",
> + pll_video2_hws, SUN60I_A733_PLL_VIDEO2_REG,
> + 16, 3, BIT(26), 0);

And these two.

[...]

> +#define SUN60I_A733_PLL_DE_REG 0x2e0
> +static struct ccu_nm pll_de_clk = {
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 11),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = SUN60I_A733_PLL_DE_REG,
> + .hw.init = CLK_HW_INIT_PARENTS_HW("pll-de", pll_ref_hws,
> + &ccu_nm_ops,
> + CLK_SET_RATE_GATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_de_hws[] = {
> + &pll_de_clk.common.hw
> +};
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_de_4x_clk, "pll-de-4x", pll_de_hws,
> + SUN60I_A733_PLL_DE_REG,
> + 20, 3, BIT(27), 0);
> +static SUNXI_CCU_M_HWS_WITH_GATE(pll_de_3x_clk, "pll-de-3x", pll_de_hws,
> + SUN60I_A733_PLL_DE_REG,
> + 16, 3, BIT(26), 0);

Same here. Do you need CLK_SET_RATE_PARENT?

The rest looks fine.


ChenYu