lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <a680b539e815f2e38f23126fede76591.sboyd@kernel.org>
Date: Thu, 19 Sep 2024 16:08:32 -0700
From: Stephen Boyd <sboyd@...nel.org>
To: Conor Dooley <conor+dt@...nel.org>, Haylen Chu <heylenay@...look.com>, Krzysztof Kozlowski <krzk+dt@...nel.org>, Michael Turquette <mturquette@...libre.com>, Rob Herring <robh@...nel.org>
Cc: linux-riscv@...ts.infradead.org, linux-clk@...r.kernel.org, devicetree@...r.kernel.org, linux-kernel@...r.kernel.org, Inochi Amaoto <inochiama@...look.com>, Chen Wang <unicornxdotw@...mail.com>, Jisheng Zhang <jszhang@...nel.org>, Haylen Chu <heylenay@...look.com>
Subject: Re: [PATCH v2 3/3] clk: spacemit: Add clock support for Spacemit K1 SoC

Quoting Haylen Chu (2024-09-16 15:23:10)
> diff --git a/drivers/clk/spacemit/ccu-k1.c b/drivers/clk/spacemit/ccu-k1.c
> new file mode 100644
> index 000000000000..ef6c8bc50a98
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu-k1.c
> @@ -0,0 +1,1341 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenay@...look.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_pll.h"
> +#include "ccu_mix.h"
> +#include "ccu_ddn.h"
> +
> +#include <dt-bindings/clock/spacemit,k1-ccu.h>
> +
> +/*     APBS register offset    */
> +/*     pll1    */
> +#define APB_SPARE1_REG                 0x100
> +#define APB_SPARE2_REG                 0x104
> +#define APB_SPARE3_REG                 0x108
> +/*     pll2    */
> +#define APB_SPARE7_REG                 0x118
> +#define APB_SPARE8_REG                 0x11c
> +#define APB_SPARE9_REG                 0x120
> +/*     pll3    */
> +#define APB_SPARE10_REG                        0x124
> +#define APB_SPARE11_REG                        0x128
> +#define APB_SPARE12_REG                        0x12c
> +
> +/* MPMU register offset */
> +#define MPMU_POSR                      0x10
> +#define POSR_PLL1_LOCK                 BIT(27)
> +#define POSR_PLL2_LOCK                 BIT(28)
> +#define POSR_PLL3_LOCK                 BIT(29)
> +
> +#define MPMU_WDTPCR                    0x200
> +#define MPMU_RIPCCR                    0x210
> +#define MPMU_ACGR                      0x1024
> +#define MPMU_SUCCR                     0x14
> +#define MPMU_ISCCR                     0x44
> +#define MPMU_SUCCR_1                   0x10b0
> +#define MPMU_APBCSCR                   0x1050
> +
> +/* APBC register offset */
> +#define APBC_UART1_CLK_RST             0x0
> +#define APBC_UART2_CLK_RST             0x4
> +#define APBC_GPIO_CLK_RST              0x8
> +#define APBC_PWM0_CLK_RST              0xc
> +#define APBC_PWM1_CLK_RST              0x10
> +#define APBC_PWM2_CLK_RST              0x14
> +#define APBC_PWM3_CLK_RST              0x18
> +#define APBC_TWSI8_CLK_RST             0x20
> +#define APBC_UART3_CLK_RST             0x24
> +#define APBC_RTC_CLK_RST               0x28
> +#define APBC_TWSI0_CLK_RST             0x2c
> +#define APBC_TWSI1_CLK_RST             0x30
> +#define APBC_TIMERS1_CLK_RST           0x34
> +#define APBC_TWSI2_CLK_RST             0x38
> +#define APBC_AIB_CLK_RST               0x3c
> +#define APBC_TWSI4_CLK_RST             0x40
> +#define APBC_TIMERS2_CLK_RST           0x44
> +#define APBC_ONEWIRE_CLK_RST           0x48
> +#define APBC_TWSI5_CLK_RST             0x4c
> +#define APBC_DRO_CLK_RST               0x58
> +#define APBC_IR_CLK_RST                        0x5c
> +#define APBC_TWSI6_CLK_RST             0x60
> +#define APBC_COUNTER_CLK_SEL           0x64
> +#define APBC_TWSI7_CLK_RST             0x68
> +#define APBC_TSEN_CLK_RST              0x6c
> +#define APBC_UART4_CLK_RST             0x70
> +#define APBC_UART5_CLK_RST             0x74
> +#define APBC_UART6_CLK_RST             0x78
> +#define APBC_SSP3_CLK_RST              0x7c
> +#define APBC_SSPA0_CLK_RST             0x80
> +#define APBC_SSPA1_CLK_RST             0x84
> +#define APBC_IPC_AP2AUD_CLK_RST                0x90
> +#define APBC_UART7_CLK_RST             0x94
> +#define APBC_UART8_CLK_RST             0x98
> +#define APBC_UART9_CLK_RST             0x9c
> +#define APBC_CAN0_CLK_RST              0xa0
> +#define APBC_PWM4_CLK_RST              0xa8
> +#define APBC_PWM5_CLK_RST              0xac
> +#define APBC_PWM6_CLK_RST              0xb0
> +#define APBC_PWM7_CLK_RST              0xb4
> +#define APBC_PWM8_CLK_RST              0xb8
> +#define APBC_PWM9_CLK_RST              0xbc
> +#define APBC_PWM10_CLK_RST             0xc0
> +#define APBC_PWM11_CLK_RST             0xc4
> +#define APBC_PWM12_CLK_RST             0xc8
> +#define APBC_PWM13_CLK_RST             0xcc
> +#define APBC_PWM14_CLK_RST             0xd0
> +#define APBC_PWM15_CLK_RST             0xd4
> +#define APBC_PWM16_CLK_RST             0xd8
> +#define APBC_PWM17_CLK_RST             0xdc
> +#define APBC_PWM18_CLK_RST             0xe0
> +#define APBC_PWM19_CLK_RST             0xe4
> +
> +/* APMU register offset */
> +#define APMU_CCI550_CLK_CTRL           0x300
> +#define APMU_CPU_C0_CLK_CTRL           0x38C
> +#define APMU_CPU_C1_CLK_CTRL           0x390
> +#define APMU_JPG_CLK_RES_CTRL          0x20
> +#define APMU_CSI_CCIC2_CLK_RES_CTRL    0x24
> +#define APMU_ISP_CLK_RES_CTRL          0x38
> +#define APMU_LCD_CLK_RES_CTRL1         0x44
> +#define APMU_LCD_SPI_CLK_RES_CTRL      0x48
> +#define APMU_LCD_CLK_RES_CTRL2         0x4c
> +#define APMU_CCIC_CLK_RES_CTRL         0x50
> +#define APMU_SDH0_CLK_RES_CTRL         0x54
> +#define APMU_SDH1_CLK_RES_CTRL         0x58
> +#define APMU_USB_CLK_RES_CTRL          0x5c
> +#define APMU_QSPI_CLK_RES_CTRL         0x60
> +#define APMU_USB_CLK_RES_CTRL          0x5c
> +#define APMU_DMA_CLK_RES_CTRL          0x64
> +#define APMU_AES_CLK_RES_CTRL          0x68
> +#define APMU_VPU_CLK_RES_CTRL          0xa4
> +#define APMU_GPU_CLK_RES_CTRL          0xcc
> +#define APMU_SDH2_CLK_RES_CTRL         0xe0
> +#define APMU_PMUA_MC_CTRL              0xe8
> +#define APMU_PMU_CC2_AP                        0x100
> +#define APMU_PMUA_EM_CLK_RES_CTRL      0x104
> +#define APMU_AUDIO_CLK_RES_CTRL                0x14c
> +#define APMU_HDMI_CLK_RES_CTRL         0x1B8
> +#define APMU_CCI550_CLK_CTRL           0x300
> +#define APMU_ACLK_CLK_CTRL             0x388
> +#define APMU_CPU_C0_CLK_CTRL           0x38C
> +#define APMU_CPU_C1_CLK_CTRL           0x390
> +#define APMU_PCIE_CLK_RES_CTRL_0       0x3cc
> +#define APMU_PCIE_CLK_RES_CTRL_1       0x3d4
> +#define APMU_PCIE_CLK_RES_CTRL_2       0x3dc
> +#define APMU_EMAC0_CLK_RES_CTRL                0x3e4
> +#define APMU_EMAC1_CLK_RES_CTRL                0x3ec
> +
> +/*     APBS clocks start       */
> +
> +/* Frequency of pll{1,2} should not be updated at runtime */
> +static const struct ccu_pll_rate_tbl pll1_rate_tbl[] = {
> +       CCU_PLL_RATE(2457600000UL, 0x64, 0xdd, 0x50, 0x00, 0x33, 0x0ccccd),
> +};
> +
> +static const struct ccu_pll_rate_tbl pll2_rate_tbl[] = {
> +       CCU_PLL_RATE(3000000000UL, 0x66, 0xdd, 0x50, 0x00, 0x3f, 0xe00000),
> +};
> +
> +static const struct ccu_pll_rate_tbl pll3_rate_tbl[] = {
> +       CCU_PLL_RATE(3000000000UL, 0x66, 0xdd, 0x50, 0x00, 0x3f, 0xe00000),
> +       CCU_PLL_RATE(3200000000UL, 0x67, 0xdd, 0x50, 0x00, 0x43, 0xeaaaab),
> +       CCU_PLL_RATE(2457600000UL, 0x64, 0xdd, 0x50, 0x00, 0x33, 0x0ccccd),
> +};
> +
> +static CCU_PLL_DEFINE(pll1, "pll1", pll1_rate_tbl,
> +                     APB_SPARE1_REG, APB_SPARE2_REG, APB_SPARE3_REG,
> +                     MPMU_POSR, POSR_PLL1_LOCK, 0);
> +static CCU_PLL_DEFINE(pll2, "pll2", pll2_rate_tbl,
> +                     APB_SPARE7_REG, APB_SPARE8_REG, APB_SPARE9_REG,
> +                     MPMU_POSR, POSR_PLL2_LOCK, 0);
> +static CCU_PLL_DEFINE(pll3, "pll3", pll3_rate_tbl,
> +                     APB_SPARE10_REG, APB_SPARE11_REG, APB_SPARE12_REG,
> +                     MPMU_POSR, POSR_PLL3_LOCK, 0);
> +
> +static CCU_GATE_FACTOR_DEFINE(pll1_d2, "pll1_d2", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(1), BIT(1), 0, 2, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d3, "pll1_d3", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(2), BIT(2), 0, 3, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d4, "pll1_d4", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(3), BIT(3), 0, 4, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d5, "pll1_d5", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(4), BIT(4), 0, 5, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d6, "pll1_d6", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(5), BIT(5), 0, 6, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d7, "pll1_d7", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(6), BIT(6), 0, 7, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d8, "pll1_d8", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(7), BIT(7), 0, 8, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d11_223p4, "pll1_d11_223p4",
> +                             "pll1", APB_SPARE2_REG,
> +                             BIT(15), BIT(15), 0, 11, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d13_189, "pll1_d13_189", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(16), BIT(16), 0, 13, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d23_106p8, "pll1_d23_106p8",
> +                             "pll1", APB_SPARE2_REG,
> +                             BIT(20), BIT(20), 0, 23, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d64_38p4, "pll1_d64_38p4", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(0), BIT(0), 0, 64, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_aud_245p7, "pll1_aud_245p7",
> +                             "pll1", APB_SPARE2_REG,
> +                             BIT(10), BIT(10), 0, 10, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_aud_24p5, "pll1_aud_24p5", "pll1",
> +                             APB_SPARE2_REG,
> +                             BIT(11), BIT(11), 0, 100, 1, 0);
> +
> +static CCU_GATE_FACTOR_DEFINE(pll2_d1, "pll2_d1", "pll2", APB_SPARE8_REG,
> +                             BIT(0), BIT(0), 0, 1, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d2, "pll2_d2", "pll2", APB_SPARE8_REG,
> +                             BIT(1), BIT(1), 0, 2, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d3, "pll2_d3", "pll2", APB_SPARE8_REG,
> +                             BIT(2), BIT(2), 0, 3, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d4, "pll2_d4", "pll2", APB_SPARE8_REG,
> +                             BIT(3), BIT(3), 0, 4, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d5, "pll2_d5", "pll2", APB_SPARE8_REG,
> +                             BIT(4), BIT(4), 0, 5, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d6, "pll2_d6", "pll2", APB_SPARE8_REG,
> +                             BIT(5), BIT(5), 0, 6, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d7, "pll2_d7", "pll2", APB_SPARE8_REG,
> +                             BIT(6), BIT(6), 0, 7, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll2_d8, "pll2_d8", "pll2", APB_SPARE8_REG,
> +                             BIT(7), BIT(7), 0, 8, 1, 0);
> +
> +static CCU_GATE_FACTOR_DEFINE(pll3_d1, "pll3_d1", "pll3", APB_SPARE11_REG,
> +                             BIT(0), BIT(0), 0, 1, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d2, "pll3_d2", "pll3", APB_SPARE11_REG,
> +                             BIT(1), BIT(1), 0, 2, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d3, "pll3_d3", "pll3", APB_SPARE11_REG,
> +                             BIT(2), BIT(2), 0, 3, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d4, "pll3_d4", "pll3", APB_SPARE11_REG,
> +                             BIT(3), BIT(3), 0, 4, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d5, "pll3_d5", "pll3", APB_SPARE11_REG,
> +                             BIT(4), BIT(4), 0, 5, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d6, "pll3_d6", "pll3", APB_SPARE11_REG,
> +                             BIT(5), BIT(5), 0, 6, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d7, "pll3_d7", "pll3", APB_SPARE11_REG,
> +                             BIT(6), BIT(6), 0, 7, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll3_d8, "pll3_d8", "pll3", APB_SPARE11_REG,
> +                             BIT(7), BIT(7), 0, 8, 1, 0);
> +
> +static CCU_FACTOR_DEFINE(pll3_20, "pll3_20", "pll3_d8", 20, 1);
> +static CCU_FACTOR_DEFINE(pll3_40, "pll3_40", "pll3_d8", 10, 1);
> +static CCU_FACTOR_DEFINE(pll3_80, "pll3_80", "pll3_d8", 5, 1);
> +
> +/*     APBS clocks end         */
> +
> +/*     MPMU clocks start       */
> +static CCU_GATE_DEFINE(pll1_d8_307p2, "pll1_d8_307p2", "pll1_d8",
> +       MPMU_ACGR,
> +       BIT(13), BIT(13), 0, 0);
> +static CCU_FACTOR_DEFINE(pll1_d32_76p8, "pll1_d32_76p8", "pll1_d8_307p2",
> +                        4, 1);
> +static CCU_FACTOR_DEFINE(pll1_d40_61p44, "pll1_d40_61p44", "pll1_d8_307p2",
> +                        5, 1);
> +static CCU_FACTOR_DEFINE(pll1_d16_153p6, "pll1_d16_153p6", "pll1_d8",
> +                        2, 1);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d24_102p4, "pll1_d24_102p4", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(12), BIT(12), 0, 3, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d48_51p2, "pll1_d48_51p2", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(7), BIT(7), 0, 6, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d48_51p2_ap, "pll1_d48_51p2_ap", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(11), BIT(11), 0, 6, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_m3d128_57p6, "pll1_m3d128_57p6", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(8), BIT(8), 0, 16, 3, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d96_25p6, "pll1_d96_25p6", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(4), BIT(4), 0, 12, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d192_12p8, "pll1_d192_12p8", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(3), BIT(3), 0, 24, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d192_12p8_wdt, "pll1_d192_12p8_wdt",
> +                             "pll1_d8", MPMU_ACGR,
> +                             BIT(19), BIT(19), 0x0, 24, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d384_6p4, "pll1_d384_6p4", "pll1_d8",
> +                             MPMU_ACGR,
> +                             BIT(2), BIT(2), 0, 48, 1, 0);
> +static CCU_FACTOR_DEFINE(pll1_d768_3p2, "pll1_d768_3p2", "pll1_d384_6p4",
> +                        2, 1);
> +static CCU_FACTOR_DEFINE(pll1_d1536_1p6, "pll1_d1536_1p6", "pll1_d384_6p4",
> +                        4, 1);
> +static CCU_FACTOR_DEFINE(pll1_d3072_0p8, "pll1_d3072_0p8", "pll1_d384_6p4",
> +                        8, 1);
> +
> +static CCU_FACTOR_DEFINE(pll1_d7_351p08, "pll1_d7_351p08", "pll1_d7",
> +                        1, 1);
> +
> +static CCU_GATE_DEFINE(pll1_d6_409p6, "pll1_d6_409p6", "pll1_d6",
> +                      MPMU_ACGR,
> +                      BIT(0), BIT(0), 0, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d12_204p8, "pll1_d12_204p8", "pll1_d6",
> +                             MPMU_ACGR,
> +                             BIT(5), BIT(5), 0, 2, 1, 0);
> +
> +static CCU_GATE_DEFINE(pll1_d5_491p52, "pll1_d5_491p52", "pll1_d5",
> +                      MPMU_ACGR, BIT(21), BIT(21), 0, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d10_245p76, "pll1_d10_245p76", "pll1_d5",
> +                             MPMU_ACGR,
> +                             BIT(18), BIT(18), 0, 2, 1, 0);
> +
> +static CCU_GATE_DEFINE(pll1_d4_614p4, "pll1_d4_614p4", "pll1_d4",
> +                      MPMU_ACGR,
> +                      BIT(15), BIT(15), 0, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d52_47p26, "pll1_d52_47p26", "pll1_d4",
> +                             MPMU_ACGR,
> +                             BIT(10), BIT(10), 0, 13, 1, 0);
> +static CCU_GATE_FACTOR_DEFINE(pll1_d78_31p5, "pll1_d78_31p5", "pll1_d4",
> +                             MPMU_ACGR,
> +                             BIT(6), BIT(6), 0, 39, 2, 0);
> +
> +static CCU_GATE_DEFINE(pll1_d3_819p2, "pll1_d3_819p2", "pll1_d3",
> +                      MPMU_ACGR,
> +                      BIT(14), BIT(14), 0, 0);
> +
> +static CCU_GATE_DEFINE(pll1_d2_1228p8, "pll1_d2_1228p8", "pll1_d2",
> +                      MPMU_ACGR,
> +                      BIT(16), BIT(16), 0, 0);
> +
> +static struct ccu_ddn_info uart_ddn_mask_info = {
> +       .factor         = 2,
> +       .num_mask       = 0x1fff,
> +       .den_mask       = 0x1fff,
> +       .num_shift      = 16,
> +       .den_shift      = 0,
> +};
> +static struct ccu_ddn_tbl slow_uart1_tbl[] = {
> +       { .num = 125, .den = 24 },
> +};
> +static struct ccu_ddn_tbl slow_uart2_tbl[] = {
> +       { .num = 6144, .den = 960 },
> +};
> +static CCU_GATE_NO_PARENT_DEFINE(slow_uart, "slow_uart",
> +                                MPMU_ACGR,
> +                                BIT(1), BIT(1), 0, 0);
> +static CCU_DDN_DEFINE(slow_uart1_14p74, "slow_uart1_14p74", "pll1_d16_153p6",
> +                     &uart_ddn_mask_info, slow_uart1_tbl,
> +                     MPMU_SUCCR, 0);
> +static CCU_DDN_DEFINE(slow_uart2_48, "slow_uart2_48", "pll1_d4_614p4",
> +                     &uart_ddn_mask_info, slow_uart2_tbl,
> +                     MPMU_SUCCR_1, 0);
> +
> +static CCU_GATE_DEFINE(wdt_clk, "wdt_clk", "pll1_d96_25p6",
> +                      MPMU_WDTPCR,
> +                      0x3, 0x3, 0x0,
> +                      0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(ripc_clk, "ripc_clk",
> +                                MPMU_RIPCCR,
> +                                0x3, 0x3, 0x0,
> +                                0);
> +
> +static CCU_GATE_FACTOR_DEFINE(i2s_sysclk, "i2s_sysclk", "pll1_d16_153p6",
> +                             MPMU_ISCCR,
> +                             BIT(31), BIT(31), 0x0, 50, 1,
> +                             0);
> +static CCU_GATE_FACTOR_DEFINE(i2s_bclk, "i2s_bclk", "i2s_sysclk",
> +                             MPMU_ISCCR,
> +                             BIT(29), BIT(29), 0x0, 1, 1,
> +                             0);
> +
> +static const char * const apb_parent_names[] = {

Please don't use strings for parents. Either use struct clk_parent_data
or clk_hw pointers directly.

> +       "pll1_d96_25p6", "pll1_d48_51p2", "pll1_d96_25p6", "pll1_d24_102p4"
> +};
> +static CCU_MUX_DEFINE(apb_clk, "apb_clk", apb_parent_names,
> +                     MPMU_APBCSCR,
> +                     0, 2,
> +                     0);
> +/*     MPMU clocks end         */
> +
> +/*     APBC clocks start       */
> +static const char * const uart_clk_parents[] = {
> +       "pll1_m3d128_57p6", "slow_uart1_14p74", "slow_uart2_48",
> +};
> +static CCU_MUX_GATE_DEFINE(uart0_clk, "uart0_clk", uart_clk_parents,
> +                          APBC_UART1_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart2_clk, "uart2_clk", uart_clk_parents,
> +                          APBC_UART2_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart3_clk, "uart3_clk", uart_clk_parents,
> +                          APBC_UART3_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart4_clk, "uart4_clk", uart_clk_parents,
> +                          APBC_UART4_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart5_clk, "uart5_clk", uart_clk_parents,
> +                          APBC_UART5_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart6_clk, "uart6_clk", uart_clk_parents,
> +                          APBC_UART6_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart7_clk, "uart7_clk", uart_clk_parents,
> +                          APBC_UART7_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart8_clk, "uart8_clk", uart_clk_parents,
> +                          APBC_UART8_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(uart9_clk, "uart9_clk", uart_clk_parents,
> +                          APBC_UART9_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +
> +static CCU_GATE_DEFINE(gpio_clk, "gpio_clk", "vctcxo_24",
> +                      APBC_GPIO_CLK_RST,
> +                      0x3, 0x3, 0x0,
> +                      0);
> +
> +static const char * const pwm_parent_names[] = {
> +       "pll1_d192_12p8", "clk_32k"
> +};
> +static CCU_MUX_GATE_DEFINE(pwm0_clk, "pwm0_clk", pwm_parent_names,
> +                          APBC_PWM0_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm1_clk, "pwm1_clk", pwm_parent_names,
> +                          APBC_PWM1_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm2_clk, "pwm2_clk", pwm_parent_names,
> +                          APBC_PWM2_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm3_clk, "pwm3_clk", pwm_parent_names,
> +                          APBC_PWM3_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm4_clk, "pwm4_clk", pwm_parent_names,
> +                          APBC_PWM4_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm5_clk, "pwm5_clk", pwm_parent_names,
> +                          APBC_PWM5_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm6_clk, "pwm6_clk", pwm_parent_names,
> +                          APBC_PWM6_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm7_clk, "pwm7_clk", pwm_parent_names,
> +                          APBC_PWM7_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm8_clk, "pwm8_clk", pwm_parent_names,
> +                          APBC_PWM8_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm9_clk, "pwm9_clk", pwm_parent_names,
> +                          APBC_PWM9_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm10_clk, "pwm10_clk", pwm_parent_names,
> +                          APBC_PWM10_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm11_clk, "pwm11_clk", pwm_parent_names,
> +                          APBC_PWM11_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm12_clk, "pwm12_clk", pwm_parent_names,
> +                          APBC_PWM12_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm13_clk, "pwm13_clk", pwm_parent_names,
> +                          APBC_PWM13_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm14_clk, "pwm14_clk", pwm_parent_names,
> +                          APBC_PWM14_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm15_clk, "pwm15_clk", pwm_parent_names,
> +                          APBC_PWM15_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm16_clk, "pwm16_clk", pwm_parent_names,
> +                          APBC_PWM16_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm17_clk, "pwm17_clk", pwm_parent_names,
> +                          APBC_PWM17_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm18_clk, "pwm18_clk", pwm_parent_names,
> +                          APBC_PWM18_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(pwm19_clk, "pwm19_clk", pwm_parent_names,
> +                          APBC_PWM19_CLK_RST,
> +                          4, 3, 0x2, 0x2, 0x0,
> +                          0);
> +
> +static const char * const ssp_parent_names[] = {
> +       "pll1_d384_6p4", "pll1_d192_12p8", "pll1_d96_25p6", "pll1_d48_51p2",
> +       "pll1_d768_3p2", "pll1_d1536_1p6", "pll1_d3072_0p8"
> +};
> +static CCU_MUX_GATE_DEFINE(ssp3_clk, "ssp3_clk", ssp_parent_names,
> +                          APBC_SSP3_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +
> +static CCU_GATE_DEFINE(rtc_clk, "rtc_clk", "clk_32k",
> +                      APBC_RTC_CLK_RST,
> +                      0x83, 0x83, 0x0, 0);
> +
> +static const char * const twsi_parent_names[] = {
> +       "pll1_d78_31p5", "pll1_d48_51p2", "pll1_d40_61p44"
> +};
> +static CCU_MUX_GATE_DEFINE(twsi0_clk, "twsi0_clk", twsi_parent_names,
> +                          APBC_TWSI0_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi1_clk, "twsi1_clk", twsi_parent_names,
> +                          APBC_TWSI1_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi2_clk, "twsi2_clk", twsi_parent_names,
> +                          APBC_TWSI2_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi4_clk, "twsi4_clk", twsi_parent_names,
> +                          APBC_TWSI4_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi5_clk, "twsi5_clk", twsi_parent_names,
> +                          APBC_TWSI5_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi6_clk, "twsi6_clk", twsi_parent_names,
> +                          APBC_TWSI6_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi7_clk, "twsi7_clk", twsi_parent_names,
> +                          APBC_TWSI7_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(twsi8_clk, "twsi8_clk", twsi_parent_names,
> +                          APBC_TWSI8_CLK_RST,
> +                          4, 3, 0x7, 0x3, 0x4,
> +                          0);
> +
> +static const char * const timer_parent_names[] = {
> +       "pll1_d192_12p8", "clk_32k", "pll1_d384_6p4", "vctcxo_3", "vctcxo_1"
> +};
> +static CCU_MUX_GATE_DEFINE(timers1_clk, "timers1_clk", timer_parent_names,
> +                          APBC_TIMERS1_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(timers2_clk, "timers2_clk", timer_parent_names,
> +                          APBC_TIMERS2_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +
> +static CCU_GATE_DEFINE(aib_clk, "aib_clk", "vctcxo_24",
> +                      APBC_AIB_CLK_RST,
> +                      0x3, 0x3, 0x0, 0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(onewire_clk, "onewire_clk",
> +                                APBC_ONEWIRE_CLK_RST,
> +                                0x3, 0x3, 0x0,
> +                                0);
> +
> +static const char * const sspa_parent_names[] = {
> +       "pll1_d384_6p4", "pll1_d192_12p8", "pll1_d96_25p6", "pll1_d48_51p2",
> +       "pll1_d768_3p2", "pll1_d1536_1p6", "pll1_d3072_0p8", "i2s_bclk"
> +};
> +static CCU_MUX_GATE_DEFINE(sspa0_clk, "sspa0_clk", sspa_parent_names,
> +                          APBC_SSPA0_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_MUX_GATE_DEFINE(sspa1_clk, "sspa1_clk", sspa_parent_names,
> +                          APBC_SSPA1_CLK_RST,
> +                          4, 3, 0x3, 0x3, 0x0,
> +                          0);
> +static CCU_GATE_NO_PARENT_DEFINE(dro_clk, "dro_clk",
> +                                APBC_DRO_CLK_RST,
> +                                0x1, 0x1, 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(ir_clk, "ir_clk",
> +                                APBC_IR_CLK_RST,
> +                                0x1, 0x1, 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(tsen_clk, "tsen_clk",
> +                                APBC_TSEN_CLK_RST,
> +                                0x3, 0x3, 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(ipc_ap2aud_clk, "ipc_ap2aud_clk",
> +                                APBC_IPC_AP2AUD_CLK_RST,
> +                                0x3, 0x3, 0x0,
> +                                0);
> +
> +static const char * const can_parent_names[] = {
> +       "pll3_20", "pll3_40", "pll3_80"
> +};
> +static CCU_MUX_GATE_DEFINE(can0_clk, "can0_clk", can_parent_names,
> +                          APBC_CAN0_CLK_RST,
> +                          4, 3, BIT(1), BIT(1), 0x0,
> +                          0);
> +static CCU_GATE_NO_PARENT_DEFINE(can0_bus_clk, "can0_bus_clk",
> +                                APBC_CAN0_CLK_RST,
> +                                BIT(0), BIT(0), 0x0,
> +                                0);
> +/*     APBC clocks end         */
> +
> +/*     APMU clocks start       */
> +static const char * const cci550_clk_parents[] = {
> +       "pll1_d5_491p52", "pll1_d4_614p4", "pll1_d3_819p2", "pll2_d3"
> +};
> +static CCU_DIV_FC_MUX_DEFINE(cci550_clk, "cci550_clk", cci550_clk_parents,
> +                            APMU_CCI550_CLK_CTRL,
> +                            8, 3, BIT(12), 0, 2, CLK_IS_CRITICAL);
> +
> +static const char * const cpu_c0_hi_clk_parents[] = { "pll3_d2", "pll3_d1" };
> +static CCU_MUX_DEFINE(cpu_c0_hi_clk, "cpu_c0_hi_clk", cpu_c0_hi_clk_parents,
> +                     APMU_CPU_C0_CLK_CTRL,
> +                     13, 1, 0);
> +static const char * const cpu_c0_clk_parents[] = {
> +       "pll1_d4_614p4", "pll1_d3_819p2", "pll1_d6_409p6", "pll1_d5_491p52",
> +       "pll1_d2_1228p8", "pll3_d3", "pll2_d3", "cpu_c0_hi_clk"
> +};
> +static CCU_MUX_FC_DEFINE(cpu_c0_core_clk, "cpu_c0_core_clk", cpu_c0_clk_parents,
> +                        APMU_CPU_C0_CLK_CTRL,
> +                        BIT(12), 0, 3, CLK_IS_CRITICAL);
> +static CCU_DIV_DEFINE(cpu_c0_ace_clk, "cpu_c0_ace_clk", "cpu_c0_core_clk",
> +                     APMU_CPU_C0_CLK_CTRL,
> +                     6, 3, CLK_IS_CRITICAL);
> +static CCU_DIV_DEFINE(cpu_c0_tcm_clk, "cpu_c0_tcm_clk", "cpu_c0_core_clk",
> +                     APMU_CPU_C0_CLK_CTRL, 9, 3, CLK_IS_CRITICAL);
> +
> +static const char * const cpu_c1_hi_clk_parents[] = { "pll3_d2", "pll3_d1" };
> +static CCU_MUX_DEFINE(cpu_c1_hi_clk, "cpu_c1_hi_clk", cpu_c1_hi_clk_parents,
> +                     APMU_CPU_C1_CLK_CTRL,
> +                     13, 1, CLK_IS_CRITICAL);
> +static const char * const cpu_c1_clk_parents[] = {
> +       "pll1_d4_614p4", "pll1_d3_819p2", "pll1_d6_409p6", "pll1_d5_491p52",
> +       "pll1_d2_1228p8", "pll3_d3", "pll2_d3", "cpu_c1_hi_clk"
> +};
> +static CCU_MUX_FC_DEFINE(cpu_c1_core_clk, "cpu_c1_core_clk", cpu_c1_clk_parents,
> +                        APMU_CPU_C1_CLK_CTRL,
> +                        BIT(12), 0, 3, CLK_IS_CRITICAL);
> +static CCU_DIV_DEFINE(cpu_c1_ace_clk, "cpu_c1_ace_clk", "cpu_c1_core_clk",
> +                     APMU_CPU_C1_CLK_CTRL,
> +                     6, 3, CLK_IS_CRITICAL);
> +
> +static const char * const jpg_parent_names[] = {
> +       "pll1_d4_614p4", "pll1_d6_409p6", "pll1_d5_491p52", "pll1_d3_819p2",
> +       "pll1_d2_1228p8", "pll2_d4", "pll2_d3"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(jpg_clk, "jpg_clk", jpg_parent_names,
> +                                 APMU_JPG_CLK_RES_CTRL,
> +                                 5, 3, BIT(15),
> +                                 2, 3, BIT(1), BIT(1), 0x0,
> +                                 0);
> +static CCU_GATE_NO_PARENT_DEFINE(jpg_4kafbc_clk, "jpg_4kafbc_clk",
> +                                APMU_JPG_CLK_RES_CTRL,
> +                                BIT(16), BIT(16), 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(jpg_2kafbc_clk, "jpg_2kafbc_clk",
> +                                APMU_JPG_CLK_RES_CTRL,
> +                                BIT(17), BIT(17), 0x0,
> +                                0);
> +
> +static const char * const ccic2phy_parent_names[] = {
> +       "pll1_d24_102p4", "pll1_d48_51p2_ap"
> +};
> +static CCU_MUX_GATE_DEFINE(ccic2phy_clk, "ccic2phy_clk", ccic2phy_parent_names,
> +                          APMU_CSI_CCIC2_CLK_RES_CTRL,
> +                          7, 1, BIT(5), BIT(5), 0x0,
> +                          0);
> +
> +static const char * const ccic3phy_parent_names[] = {
> +       "pll1_d24_102p4", "pll1_d48_51p2_ap"
> +};
> +static CCU_MUX_GATE_DEFINE(ccic3phy_clk, "ccic3phy_clk", ccic3phy_parent_names,
> +                          APMU_CSI_CCIC2_CLK_RES_CTRL,
> +                          31, 1, BIT(30), BIT(30), 0x0,
> +                          0);
> +
> +static const char * const csi_parent_names[] = {
> +       "pll1_d5_491p52", "pll1_d6_409p6", "pll1_d4_614p4", "pll1_d3_819p2",
> +       "pll2_d2", "pll2_d3", "pll2_d4", "pll1_d2_1228p8"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(csi_clk, "csi_clk", csi_parent_names,
> +                                 APMU_CSI_CCIC2_CLK_RES_CTRL,
> +                                 20, 3, BIT(15),
> +                                 16, 3, BIT(4), BIT(4), 0x0,
> +                                 0);
> +
> +static const char * const camm_parent_names[] = {
> +       "pll1_d8_307p2", "pll2_d5", "pll1_d6_409p6", "vctcxo_24"
> +};
> +static CCU_DIV_MUX_GATE_DEFINE(camm0_clk, "camm0_clk", camm_parent_names,
> +                              APMU_CSI_CCIC2_CLK_RES_CTRL,
> +                              23, 4, 8, 2,
> +                              BIT(28), BIT(28), 0x0,
> +                              0);
> +static CCU_DIV_MUX_GATE_DEFINE(camm1_clk, "camm1_clk", camm_parent_names,
> +                              APMU_CSI_CCIC2_CLK_RES_CTRL,
> +                              23, 4, 8, 2, BIT(6), BIT(6), 0x0,
> +                              0);
> +static CCU_DIV_MUX_GATE_DEFINE(camm2_clk, "camm2_clk", camm_parent_names,
> +                              APMU_CSI_CCIC2_CLK_RES_CTRL,
> +                              23, 4, 8, 2, BIT(3), BIT(3), 0x0,
> +                              0);
> +
> +static const char * const isp_cpp_parent_names[] = {
> +       "pll1_d8_307p2", "pll1_d6_409p6"
> +};
> +static CCU_DIV_MUX_GATE_DEFINE(isp_cpp_clk, "isp_cpp_clk", isp_cpp_parent_names,
> +                              APMU_ISP_CLK_RES_CTRL,
> +                              24, 2, 26, 1, BIT(28), BIT(28), 0x0,
> +                              0);
> +static const char * const isp_bus_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d5_491p52", "pll1_d8_307p2", "pll1_d10_245p76"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(isp_bus_clk, "isp_bus_clk",
> +                                 isp_bus_parent_names,
> +                                 APMU_ISP_CLK_RES_CTRL,
> +                                 18, 3, BIT(23),
> +                                 21, 2, BIT(17), BIT(17), 0x0,
> +                                 0);
> +static const char * const isp_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d5_491p52", "pll1_d4_614p4", "pll1_d8_307p2"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(isp_clk, "isp_clk", isp_parent_names,
> +                                 APMU_ISP_CLK_RES_CTRL,
> +                                 4, 3, BIT(7),
> +                                 8, 2, BIT(1), BIT(1), 0x0,
> +                                 0);
> +
> +static const char * const dpumclk_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d5_491p52", "pll1_d4_614p4", "pll1_d8_307p2"
> +};
> +static CCU_DIV2_FC_MUX_GATE_DEFINE(dpu_mclk, "dpu_mclk", dpumclk_parent_names,
> +                                  APMU_LCD_CLK_RES_CTRL1,
> +                                  APMU_LCD_CLK_RES_CTRL2,
> +                                  1, 4, BIT(29),
> +                                  5, 3, BIT(0), BIT(0), 0x0,
> +                                  0);
> +
> +static const char * const dpuesc_parent_names[] = {
> +       "pll1_d48_51p2_ap", "pll1_d52_47p26", "pll1_d96_25p6", "pll1_d32_76p8"
> +};
> +static CCU_MUX_GATE_DEFINE(dpu_esc_clk, "dpu_esc_clk", dpuesc_parent_names,
> +                          APMU_LCD_CLK_RES_CTRL1,
> +                          0, 2, BIT(2), BIT(2), 0x0,
> +                          0);
> +
> +static const char * const dpubit_parent_names[] = {
> +       "pll1_d3_819p2", "pll2_d2", "pll2_d3", "pll1_d2_1228p8", "pll2_d4",
> +       "pll2_d5", "pll2_d8", "pll2_d8"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(dpu_bit_clk, "dpu_bit_clk",
> +                                 dpubit_parent_names,
> +                                 APMU_LCD_CLK_RES_CTRL1,
> +                                 17, 3, BIT(31),
> +                                 20, 3, BIT(16), BIT(16), 0x0,
> +                                 0);
> +
> +static const char * const dpupx_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d5_491p52", "pll1_d4_614p4", "pll1_d8_307p2", "pll2_d7", "pll2_d8"
> +};
> +static CCU_DIV2_FC_MUX_GATE_DEFINE(dpu_pxclk, "dpu_pxclk", dpupx_parent_names,
> +                                 APMU_LCD_CLK_RES_CTRL1,
> +                                 APMU_LCD_CLK_RES_CTRL2,
> +                                 17, 4, BIT(30),
> +                                 21, 3, BIT(16), BIT(16), 0x0,
> +                                 0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(dpu_hclk, "dpu_hclk",
> +                                APMU_LCD_CLK_RES_CTRL1,
> +                                BIT(5), BIT(5), 0x0,
> +                                0);
> +
> +static const char * const dpu_spi_parent_names[] = {
> +       "pll1_d8_307p2", "pll1_d6_409p6", "pll1_d10_245p76", "pll1_d11_223p4",
> +       "pll1_d13_189", "pll1_d23_106p8", "pll2_d3", "pll2_d5"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(dpu_spi_clk, "dpu_spi_clk",
> +                                 dpu_spi_parent_names,
> +                                 APMU_LCD_SPI_CLK_RES_CTRL,
> +                                 8, 3, BIT(7),
> +                                 12, 3, BIT(1), BIT(1), 0x0,
> +                                 0);
> +static CCU_GATE_NO_PARENT_DEFINE(dpu_spi_hbus_clk, "dpu_spi_hbus_clk",
> +                                APMU_LCD_SPI_CLK_RES_CTRL,
> +                                BIT(3), BIT(3), 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(dpu_spi_bus_clk, "dpu_spi_bus_clk",
> +                                APMU_LCD_SPI_CLK_RES_CTRL,
> +                                BIT(5), BIT(5), 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(dpu_spi_aclk, "dpu_spi_aclk",
> +                                APMU_LCD_SPI_CLK_RES_CTRL,
> +                                BIT(6), BIT(6), 0x0,
> +                                0);
> +
> +static const char * const v2d_parent_names[] = {
> +       "pll1_d5_491p52", "pll1_d6_409p6", "pll1_d8_307p2", "pll1_d4_614p4",
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(v2d_clk, "v2d_clk", v2d_parent_names,
> +                                 APMU_LCD_CLK_RES_CTRL1,
> +                                 9, 3, BIT(28),
> +                                 12, 2, BIT(8), BIT(8), 0x0,
> +                                 0);
> +
> +static const char * const ccic_4x_parent_names[] = {
> +       "pll1_d5_491p52", "pll1_d6_409p6", "pll1_d4_614p4", "pll1_d3_819p2",
> +       "pll2_d2", "pll2_d3", "pll2_d4", "pll1_d2_1228p8"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(ccic_4x_clk, "ccic_4x_clk",
> +                                 ccic_4x_parent_names,
> +                                 APMU_CCIC_CLK_RES_CTRL,
> +                                 18, 3, BIT(15),
> +                                 23, 2, BIT(4), BIT(4), 0x0,
> +                                 0);
> +
> +static const char * const ccic1phy_parent_names[] = {
> +       "pll1_d24_102p4", "pll1_d48_51p2_ap"
> +};
> +static CCU_MUX_GATE_DEFINE(ccic1phy_clk, "ccic1phy_clk", ccic1phy_parent_names,
> +                          APMU_CCIC_CLK_RES_CTRL,
> +                          7, 1, BIT(5), BIT(5), 0x0,
> +                          0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(sdh_axi_aclk, "sdh_axi_aclk",
> +                                APMU_SDH0_CLK_RES_CTRL,
> +                                BIT(3), BIT(3), 0x0,
> +                                0);
> +static const char * const sdh01_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d4_614p4", "pll2_d8", "pll2_d5",
> +       "pll1_d11_223p4", "pll1_d13_189", "pll1_d23_106p8"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(sdh0_clk, "sdh0_clk", sdh01_parent_names,
> +                                 APMU_SDH0_CLK_RES_CTRL,
> +                                 8, 3, BIT(11),
> +                                 5, 3, BIT(4), BIT(4), 0x0,
> +                                 0);
> +static CCU_DIV_FC_MUX_GATE_DEFINE(sdh1_clk, "sdh1_clk", sdh01_parent_names,
> +                                 APMU_SDH1_CLK_RES_CTRL,
> +                                 8, 3, BIT(11),
> +                                 5, 3, BIT(4), BIT(4), 0x0,
> +                                 0);
> +static const char * const sdh2_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d4_614p4", "pll2_d8", "pll1_d3_819p2",
> +       "pll1_d11_223p4", "pll1_d13_189", "pll1_d23_106p8"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(sdh2_clk, "sdh2_clk", sdh2_parent_names,
> +                                 APMU_SDH2_CLK_RES_CTRL,
> +                                 8, 3, BIT(11),
> +                                 5, 3, BIT(4), BIT(4), 0x0,
> +                                 0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(usb_axi_clk, "usb_axi_clk",
> +                                APMU_USB_CLK_RES_CTRL,
> +                                BIT(1), BIT(1), 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(usb_p1_aclk, "usb_p1_aclk",
> +                                APMU_USB_CLK_RES_CTRL,
> +                                BIT(5), BIT(5), 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(usb30_clk, "usb30_clk",
> +                                APMU_USB_CLK_RES_CTRL,
> +                                BIT(8), BIT(8), 0x0,
> +                                0);
> +
> +static const char * const qspi_parent_names[] = {
> +       "pll1_d6_409p6", "pll2_d8", "pll1_d8_307p2", "pll1_d10_245p76",
> +       "pll1_d11_223p4", "pll1_d23_106p8", "pll1_d5_491p52", "pll1_d13_189"
> +};
> +static CCU_DIV_MFC_MUX_GATE_DEFINE(qspi_clk, "qspi_clk", qspi_parent_names,
> +                                  APMU_QSPI_CLK_RES_CTRL,
> +                                  9, 3, BIT(12),
> +                                  6, 3, BIT(4), BIT(4), 0x0,
> +                                  0);
> +static CCU_GATE_NO_PARENT_DEFINE(qspi_bus_clk, "qspi_bus_clk",
> +                                APMU_QSPI_CLK_RES_CTRL,
> +                                BIT(3), BIT(3), 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(dma_clk, "dma_clk",
> +                                APMU_DMA_CLK_RES_CTRL,
> +                                BIT(3), BIT(3), 0x0,
> +                                0);
> +
> +static const char * const aes_parent_names[] = {
> +       "pll1_d12_204p8", "pll1_d24_102p4"
> +};
> +static CCU_MUX_GATE_DEFINE(aes_clk, "aes_clk", aes_parent_names,
> +                          APMU_AES_CLK_RES_CTRL,
> +                          6, 1, BIT(5), BIT(5), 0x0,
> +                          0);
> +
> +static const char * const vpu_parent_names[] = {
> +       "pll1_d4_614p4", "pll1_d5_491p52", "pll1_d3_819p2", "pll1_d6_409p6",
> +       "pll3_d6", "pll2_d3", "pll2_d4", "pll2_d5"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(vpu_clk, "vpu_clk", vpu_parent_names,
> +                                 APMU_VPU_CLK_RES_CTRL,
> +                                 13, 3, BIT(21),
> +                                 10, 3,
> +                                 BIT(3), BIT(3), 0x0,
> +                                 0);
> +
> +static const char * const gpu_parent_names[] = {
> +       "pll1_d4_614p4", "pll1_d5_491p52", "pll1_d3_819p2", "pll1_d6_409p6",
> +       "pll3_d6", "pll2_d3", "pll2_d4", "pll2_d5"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(gpu_clk, "gpu_clk", gpu_parent_names,
> +                                 APMU_GPU_CLK_RES_CTRL,
> +                                 12, 3, BIT(15),
> +                                 18, 3,
> +                                 BIT(4), BIT(4), 0x0,
> +                                 0);
> +
> +static const char * const emmc_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d4_614p4", "pll1_d52_47p26", "pll1_d3_819p2"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(emmc_clk, "emmc_clk", emmc_parent_names,
> +                                 APMU_PMUA_EM_CLK_RES_CTRL,
> +                                 8, 3, BIT(11),
> +                                 6, 2,
> +                                 0x18, 0x18, 0x0,
> +                                 0);
> +static CCU_DIV_GATE_DEFINE(emmc_x_clk, "emmc_x_clk", "pll1_d2_1228p8",
> +                          APMU_PMUA_EM_CLK_RES_CTRL,
> +                          12, 3, BIT(15), BIT(15), 0x0,
> +                          0);
> +
> +static const char * const audio_parent_names[] = {
> +       "pll1_aud_245p7", "pll1_d8_307p2", "pll1_d6_409p6"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(audio_clk, "audio_clk", audio_parent_names,
> +                                 APMU_AUDIO_CLK_RES_CTRL,
> +                                 4, 3, BIT(15),
> +                                 7, 3,
> +                                 BIT(12), BIT(12), 0x0,
> +                                 0);
> +
> +static const char * const hdmi_parent_names[] = {
> +       "pll1_d6_409p6", "pll1_d5_491p52", "pll1_d4_614p4", "pll1_d8_307p2"
> +};
> +static CCU_DIV_FC_MUX_GATE_DEFINE(hdmi_mclk, "hdmi_mclk", hdmi_parent_names,
> +                                 APMU_HDMI_CLK_RES_CTRL,
> +                                 1, 4, BIT(29),
> +                                 5, 3,
> +                                 BIT(0), BIT(0), 0x0,
> +                                 0);
> +
> +static const char * const pmua_aclk_parent_names[] = {
> +       "pll1_d10_245p76", "pll1_d8_307p2"
> +};
> +static CCU_DIV_FC_MUX_DEFINE(pmua_aclk, "pmua_aclk", pmua_aclk_parent_names,
> +                            APMU_ACLK_CLK_CTRL,
> +                            1, 2, BIT(4),
> +                            0, 1,
> +                            0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(pcie0_clk, "pcie0_clk",
> +                                APMU_PCIE_CLK_RES_CTRL_0,
> +                                0x7, 0x7, 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(pcie1_clk, "pcie1_clk",
> +                                APMU_PCIE_CLK_RES_CTRL_1,
> +                                0x7, 0x7, 0x0,
> +                                0);
> +static CCU_GATE_NO_PARENT_DEFINE(pcie2_clk, "pcie2_clk",
> +                                APMU_PCIE_CLK_RES_CTRL_2,
> +                                0x7, 0x7, 0x0,
> +                                0);
> +
> +static CCU_GATE_NO_PARENT_DEFINE(emac0_bus_clk, "emac0_bus_clk",
> +                                APMU_EMAC0_CLK_RES_CTRL,
> +                                BIT(0), BIT(0), 0x0,
> +                                0);
> +static CCU_GATE_DEFINE(emac0_ptp_clk, "emac0_ptp_clk", "pll2_d6",
> +                      APMU_EMAC0_CLK_RES_CTRL,
> +                      BIT(15), BIT(15), 0x0,
> +                      0);
> +static CCU_GATE_NO_PARENT_DEFINE(emac1_bus_clk, "emac1_bus_clk",
> +                                APMU_EMAC1_CLK_RES_CTRL,
> +                                BIT(0), BIT(0), 0x0,
> +                                0);
> +static CCU_GATE_DEFINE(emac1_ptp_clk, "emac1_ptp_clk", "pll2_d6",
> +                      APMU_EMAC1_CLK_RES_CTRL,
> +                      BIT(15), BIT(15), 0x0,
> +                      0);
> +/*     APMU clocks end         */
> +
> +static struct clk_hw_onecell_data k1_ccu_apbs_clks = {
> +       .hws = {
> +               [CLK_PLL1]              = &pll1.common.hw,
> +               [CLK_PLL2]              = &pll2.common.hw,
> +               [CLK_PLL3]              = &pll3.common.hw,
> +               [CLK_PLL1_D2]           = &pll1_d2.common.hw,
> +               [CLK_PLL1_D3]           = &pll1_d3.common.hw,
> +               [CLK_PLL1_D4]           = &pll1_d4.common.hw,
> +               [CLK_PLL1_D5]           = &pll1_d5.common.hw,
> +               [CLK_PLL1_D6]           = &pll1_d6.common.hw,
> +               [CLK_PLL1_D7]           = &pll1_d7.common.hw,
> +               [CLK_PLL1_D8]           = &pll1_d8.common.hw,
> +               [CLK_PLL1_D11]          = &pll1_d11_223p4.common.hw,
> +               [CLK_PLL1_D13]          = &pll1_d13_189.common.hw,
> +               [CLK_PLL1_D23]          = &pll1_d23_106p8.common.hw,
> +               [CLK_PLL1_D64]          = &pll1_d64_38p4.common.hw,
> +               [CLK_PLL1_D10_AUD]      = &pll1_aud_245p7.common.hw,
> +               [CLK_PLL1_D100_AUD]     = &pll1_aud_24p5.common.hw,
> +               [CLK_PLL2_D1]           = &pll2_d1.common.hw,
> +               [CLK_PLL2_D2]           = &pll2_d2.common.hw,
> +               [CLK_PLL2_D3]           = &pll2_d3.common.hw,
> +               [CLK_PLL2_D3]           = &pll2_d4.common.hw,
> +               [CLK_PLL2_D5]           = &pll2_d5.common.hw,
> +               [CLK_PLL2_D6]           = &pll2_d6.common.hw,
> +               [CLK_PLL2_D7]           = &pll2_d7.common.hw,
> +               [CLK_PLL2_D8]           = &pll2_d8.common.hw,
> +               [CLK_PLL3_D1]           = &pll3_d1.common.hw,
> +               [CLK_PLL3_D2]           = &pll3_d2.common.hw,
> +               [CLK_PLL3_D3]           = &pll3_d3.common.hw,
> +               [CLK_PLL3_D4]           = &pll3_d4.common.hw,
> +               [CLK_PLL3_D5]           = &pll3_d5.common.hw,
> +               [CLK_PLL3_D6]           = &pll3_d6.common.hw,
> +               [CLK_PLL3_D7]           = &pll3_d7.common.hw,
> +               [CLK_PLL3_D8]           = &pll3_d8.common.hw,
> +               [CLK_PLL3_80]           = &pll3_80.common.hw,
> +               [CLK_PLL3_40]           = &pll3_40.common.hw,
> +               [CLK_PLL3_20]           = &pll3_20.common.hw,
> +
> +       },
> +       .num = CLK_APBS_NUM,
> +};
> +
> +static struct clk_hw_onecell_data k1_ccu_mpmu_clks = {
> +       .hws = {
> +               [CLK_PLL1_307P2]        = &pll1_d8_307p2.common.hw,
> +               [CLK_PLL1_76P8]         = &pll1_d32_76p8.common.hw,
> +               [CLK_PLL1_61P44]        = &pll1_d40_61p44.common.hw,
> +               [CLK_PLL1_153P6]        = &pll1_d16_153p6.common.hw,
> +               [CLK_PLL1_102P4]        = &pll1_d24_102p4.common.hw,
> +               [CLK_PLL1_51P2]         = &pll1_d48_51p2.common.hw,
> +               [CLK_PLL1_51P2_AP]      = &pll1_d48_51p2_ap.common.hw,
> +               [CLK_PLL1_57P6]         = &pll1_m3d128_57p6.common.hw,
> +               [CLK_PLL1_25P6]         = &pll1_d96_25p6.common.hw,
> +               [CLK_PLL1_12P8]         = &pll1_d192_12p8.common.hw,
> +               [CLK_PLL1_12P8_WDT]     = &pll1_d192_12p8_wdt.common.hw,
> +               [CLK_PLL1_6P4]          = &pll1_d384_6p4.common.hw,
> +               [CLK_PLL1_3P2]          = &pll1_d768_3p2.common.hw,
> +               [CLK_PLL1_1P6]          = &pll1_d1536_1p6.common.hw,
> +               [CLK_PLL1_0P8]          = &pll1_d3072_0p8.common.hw,
> +               [CLK_PLL1_351]          = &pll1_d7_351p08.common.hw,
> +               [CLK_PLL1_409P6]        = &pll1_d6_409p6.common.hw,
> +               [CLK_PLL1_204P8]        = &pll1_d12_204p8.common.hw,
> +               [CLK_PLL1_491]          = &pll1_d5_491p52.common.hw,
> +               [CLK_PLL1_245P76]       = &pll1_d10_245p76.common.hw,
> +               [CLK_PLL1_614]          = &pll1_d4_614p4.common.hw,
> +               [CLK_PLL1_47P26]        = &pll1_d52_47p26.common.hw,
> +               [CLK_PLL1_31P5]         = &pll1_d78_31p5.common.hw,
> +               [CLK_PLL1_819]          = &pll1_d3_819p2.common.hw,
> +               [CLK_PLL1_1228]         = &pll1_d2_1228p8.common.hw,
> +               [CLK_SLOW_UART]         = &slow_uart.common.hw,
> +               [CLK_SLOW_UART1]        = &slow_uart1_14p74.common.hw,
> +               [CLK_SLOW_UART2]        = &slow_uart2_48.common.hw,
> +               [CLK_WDT]               = &wdt_clk.common.hw,
> +               [CLK_RIPC]              = &ripc_clk.common.hw,
> +               [CLK_I2S_SYSCLK]        = &i2s_sysclk.common.hw,
> +               [CLK_I2S_BCLK]          = &i2s_bclk.common.hw,
> +               [CLK_APB]               = &apb_clk.common.hw,
> +       },
> +       .num = CLK_MPMU_NUM,
> +};
> +
> +static struct clk_hw_onecell_data k1_ccu_apbc_clks = {
> +       .hws = {
> +               [CLK_UART0]             = &uart0_clk.common.hw,
> +               [CLK_UART2]             = &uart2_clk.common.hw,
> +               [CLK_UART3]             = &uart3_clk.common.hw,
> +               [CLK_UART4]             = &uart4_clk.common.hw,
> +               [CLK_UART5]             = &uart5_clk.common.hw,
> +               [CLK_UART6]             = &uart6_clk.common.hw,
> +               [CLK_UART7]             = &uart7_clk.common.hw,
> +               [CLK_UART8]             = &uart8_clk.common.hw,
> +               [CLK_UART9]             = &uart9_clk.common.hw,
> +               [CLK_GPIO]              = &gpio_clk.common.hw,
> +               [CLK_PWM0]              = &pwm0_clk.common.hw,
> +               [CLK_PWM1]              = &pwm1_clk.common.hw,
> +               [CLK_PWM2]              = &pwm2_clk.common.hw,
> +               [CLK_PWM3]              = &pwm3_clk.common.hw,
> +               [CLK_PWM4]              = &pwm4_clk.common.hw,
> +               [CLK_PWM5]              = &pwm5_clk.common.hw,
> +               [CLK_PWM6]              = &pwm6_clk.common.hw,
> +               [CLK_PWM7]              = &pwm7_clk.common.hw,
> +               [CLK_PWM8]              = &pwm8_clk.common.hw,
> +               [CLK_PWM9]              = &pwm9_clk.common.hw,
> +               [CLK_PWM10]             = &pwm10_clk.common.hw,
> +               [CLK_PWM11]             = &pwm11_clk.common.hw,
> +               [CLK_PWM12]             = &pwm12_clk.common.hw,
> +               [CLK_PWM13]             = &pwm13_clk.common.hw,
> +               [CLK_PWM14]             = &pwm14_clk.common.hw,
> +               [CLK_PWM15]             = &pwm15_clk.common.hw,
> +               [CLK_PWM16]             = &pwm16_clk.common.hw,
> +               [CLK_PWM17]             = &pwm17_clk.common.hw,
> +               [CLK_PWM18]             = &pwm18_clk.common.hw,
> +               [CLK_PWM19]             = &pwm19_clk.common.hw,
> +               [CLK_SSP3]              = &ssp3_clk.common.hw,
> +               [CLK_RTC]               = &rtc_clk.common.hw,
> +               [CLK_TWSI0]             = &twsi0_clk.common.hw,
> +               [CLK_TWSI1]             = &twsi1_clk.common.hw,
> +               [CLK_TWSI2]             = &twsi2_clk.common.hw,
> +               [CLK_TWSI4]             = &twsi4_clk.common.hw,
> +               [CLK_TWSI5]             = &twsi5_clk.common.hw,
> +               [CLK_TWSI6]             = &twsi6_clk.common.hw,
> +               [CLK_TWSI7]             = &twsi7_clk.common.hw,
> +               [CLK_TWSI8]             = &twsi8_clk.common.hw,
> +               [CLK_TIMERS1]           = &timers1_clk.common.hw,
> +               [CLK_TIMERS2]           = &timers2_clk.common.hw,
> +               [CLK_AIB]               = &aib_clk.common.hw,
> +               [CLK_ONEWIRE]           = &onewire_clk.common.hw,
> +               [CLK_SSPA0]             = &sspa0_clk.common.hw,
> +               [CLK_SSPA1]             = &sspa1_clk.common.hw,
> +               [CLK_DRO]               = &dro_clk.common.hw,
> +               [CLK_IR]                = &ir_clk.common.hw,
> +               [CLK_TSEN]              = &tsen_clk.common.hw,
> +               [CLK_IPC_AP2AUD]        = &ipc_ap2aud_clk.common.hw,
> +               [CLK_CAN0]              = &can0_clk.common.hw,
> +               [CLK_CAN0_BUS]          = &can0_bus_clk.common.hw,
> +       },
> +       .num = CLK_APBC_NUM,
> +};
> +
> +static struct clk_hw_onecell_data k1_ccu_apmu_clks = {
> +       .hws = {
> +               [CLK_CCI550]            = &cci550_clk.common.hw,
> +               [CLK_CPU_C0_HI]         = &cpu_c0_hi_clk.common.hw,
> +               [CLK_CPU_C0_CORE]       = &cpu_c0_core_clk.common.hw,
> +               [CLK_CPU_C0_ACE]        = &cpu_c0_ace_clk.common.hw,
> +               [CLK_CPU_C0_TCM]        = &cpu_c0_tcm_clk.common.hw,
> +               [CLK_CPU_C1_HI]         = &cpu_c1_hi_clk.common.hw,
> +               [CLK_CPU_C1_CORE]       = &cpu_c1_core_clk.common.hw,
> +               [CLK_CPU_C1_ACE]        = &cpu_c1_ace_clk.common.hw,
> +               [CLK_CCIC_4X]           = &ccic_4x_clk.common.hw,
> +               [CLK_CCIC1PHY]          = &ccic1phy_clk.common.hw,
> +               [CLK_SDH_AXI]           = &sdh_axi_aclk.common.hw,
> +               [CLK_SDH0]              = &sdh0_clk.common.hw,
> +               [CLK_SDH1]              = &sdh1_clk.common.hw,
> +               [CLK_SDH2]              = &sdh2_clk.common.hw,
> +               [CLK_USB_P1]            = &usb_p1_aclk.common.hw,
> +               [CLK_USB_AXI]           = &usb_axi_clk.common.hw,
> +               [CLK_USB30]             = &usb30_clk.common.hw,
> +               [CLK_QSPI]              = &qspi_clk.common.hw,
> +               [CLK_QSPI_BUS]          = &qspi_bus_clk.common.hw,
> +               [CLK_DMA]               = &dma_clk.common.hw,
> +               [CLK_AES]               = &aes_clk.common.hw,
> +               [CLK_VPU]               = &vpu_clk.common.hw,
> +               [CLK_GPU]               = &gpu_clk.common.hw,
> +               [CLK_EMMC]              = &emmc_clk.common.hw,
> +               [CLK_EMMC_X]            = &emmc_x_clk.common.hw,
> +               [CLK_AUDIO]             = &audio_clk.common.hw,
> +               [CLK_HDMI]              = &hdmi_mclk.common.hw,
> +               [CLK_PMUA_ACLK]         = &pmua_aclk.common.hw,
> +               [CLK_PCIE0]             = &pcie0_clk.common.hw,
> +               [CLK_PCIE1]             = &pcie1_clk.common.hw,
> +               [CLK_PCIE2]             = &pcie2_clk.common.hw,
> +               [CLK_EMAC0_BUS]         = &emac0_bus_clk.common.hw,
> +               [CLK_EMAC0_PTP]         = &emac0_ptp_clk.common.hw,
> +               [CLK_EMAC1_BUS]         = &emac1_bus_clk.common.hw,
> +               [CLK_EMAC1_PTP]         = &emac1_ptp_clk.common.hw,
> +               [CLK_JPG]               = &jpg_clk.common.hw,
> +               [CLK_JPF_4KAFBC]        = &jpg_4kafbc_clk.common.hw,
> +               [CLK_JPF_2KAFBC]        = &jpg_2kafbc_clk.common.hw,
> +               [CLK_CCIC2PHY]          = &ccic2phy_clk.common.hw,
> +               [CLK_CCIC3PHY]          = &ccic3phy_clk.common.hw,
> +               [CLK_CSI]               = &csi_clk.common.hw,
> +               [CLK_CAMM0]             = &camm0_clk.common.hw,
> +               [CLK_CAMM1]             = &camm1_clk.common.hw,
> +               [CLK_CAMM2]             = &camm2_clk.common.hw,
> +               [CLK_ISP_CPP]           = &isp_cpp_clk.common.hw,
> +               [CLK_ISP_BUS]           = &isp_bus_clk.common.hw,
> +               [CLK_ISP]               = &isp_clk.common.hw,
> +               [CLK_DPU_MCLK]          = &dpu_mclk.common.hw,
> +               [CLK_DPU_ESC]           = &dpu_esc_clk.common.hw,
> +               [CLK_DPU_BIT]           = &dpu_bit_clk.common.hw,
> +               [CLK_DPU_PXCLK]         = &dpu_pxclk.common.hw,
> +               [CLK_DPU_HCLK]          = &dpu_hclk.common.hw,
> +               [CLK_DPU_SPI]           = &dpu_spi_clk.common.hw,
> +               [CLK_DPU_SPI_HBUS]      = &dpu_spi_hbus_clk.common.hw,
> +               [CLK_DPU_SPIBUS]        = &dpu_spi_bus_clk.common.hw,
> +               [CLK_DPU_SPI_ACLK]      = &dpu_spi_aclk.common.hw,
> +               [CLK_V2D]               = &v2d_clk.common.hw,
> +       },
> +       .num = CLK_APMU_NUM
> +};
> +
> +struct spacemit_ccu_data {
> +       struct clk_hw_onecell_data *hw_clks;
> +       bool need_pll_lock;
> +};
> +
> +struct spacemit_ccu_priv {
> +       const struct spacemit_ccu_data *data;
> +       struct regmap *base;
> +       struct regmap *lock_base;
> +       spinlock_t lock;
> +};
> +
> +static int spacemit_ccu_register(struct device *dev,
> +                                struct spacemit_ccu_priv *priv)
> +{
> +       const struct spacemit_ccu_data *data = priv->data;
> +       int i, ret;
> +
> +       for (i = 0; i < data->hw_clks->num; i++) {
> +               struct clk_hw *hw = data->hw_clks->hws[i];
> +               struct ccu_common *common;
> +               const char *name;
> +
> +               if (!hw)
> +                       continue;
> +
> +               common = hw_to_ccu_common(hw);
> +               name = hw->init->name;
> +
> +               common->lock            = &priv->lock;
> +               common->base            = priv->base;
> +               common->lock_base       = priv->lock_base;
> +
> +               ret = devm_clk_hw_register(dev, hw);
> +               if (ret) {
> +                       dev_err(dev, "Cannot register clock %d - %s\n",
> +                               i, name);
> +                       return ret;
> +               }
> +       }
> +
> +       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> +                                          data->hw_clks);
> +}
> +
> +static int k1_ccu_probe(struct platform_device *pdev)
> +{
> +       const struct spacemit_ccu_data *data;
> +       struct regmap *base_map, *lock_map;
> +       struct device *dev = &pdev->dev;
> +       struct spacemit_ccu_priv *priv;
> +       struct device_node *parent;
> +       int ret;
> +
> +       data = of_device_get_match_data(dev);
> +       if (WARN_ON(!data))
> +               return -EINVAL;
> +
> +       parent   = of_get_parent(dev->of_node);
> +       base_map = syscon_node_to_regmap(parent);
> +       of_node_put(parent);
> +
> +       if (IS_ERR(base_map))
> +               return dev_err_probe(dev, PTR_ERR(base_map),
> +                                    "failed to get regmap\n");
> +
> +       if (data->need_pll_lock) {
> +               lock_map = syscon_regmap_lookup_by_phandle(dev->of_node,
> +                                                          "spacemit,mpmu");
> +               if (IS_ERR(lock_map))
> +                       return dev_err_probe(dev, PTR_ERR(lock_map),
> +                                            "failed to get lock regmap\n");
> +       }
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       priv->data      = data;
> +       priv->base      = base_map;
> +       priv->lock_base = lock_map;
> +       spin_lock_init(&priv->lock);
> +
> +       ret = spacemit_ccu_register(dev, priv);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "failed to register clocks");

Missing newline on printk

> +
> +       return 0;
> +}
> +
> +static const struct spacemit_ccu_data k1_ccu_apbs_data = {
> +       .need_pll_lock  = true,
> +       .hw_clks        = &k1_ccu_apbs_clks,
> +};
> +
> +static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
> +       .need_pll_lock  = false,
> +       .hw_clks        = &k1_ccu_mpmu_clks,
> +};
> +
> +static const struct spacemit_ccu_data k1_ccu_apbc_data = {
> +       .need_pll_lock  = false,
> +       .hw_clks        = &k1_ccu_apbc_clks,
> +};
> +
> +static const struct spacemit_ccu_data k1_ccu_apmu_data = {
> +       .need_pll_lock  = false,
> +       .hw_clks        = &k1_ccu_apmu_clks,
> +};
> +
> +static const struct of_device_id of_k1_ccu_match[] = {
> +       {
> +               .compatible     = "spacemit,k1-ccu-apbs",
> +               .data           = &k1_ccu_apbs_data,
> +       },
> +       {
> +               .compatible     = "spacemit,k1-ccu-mpmu",
> +               .data           = &k1_ccu_mpmu_data,
> +       },
> +       {
> +               .compatible     = "spacemit,k1-ccu-apbc",
> +               .data           = &k1_ccu_apbc_data,
> +       },
> +       {
> +               .compatible     = "spacemit,k1-ccu-apmu",
> +               .data           = &k1_ccu_apmu_data,
> +       },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, of_k1_ccu_match);
> +
> +static struct platform_driver k1_ccu_driver = {
> +       .driver = {
> +               .name           = "spacemit,k1-ccu",
> +               .of_match_table = of_k1_ccu_match,
> +       },
> +       .probe  = k1_ccu_probe,
> +};
> +module_platform_driver(k1_ccu_driver);
> +
> +MODULE_DESCRIPTION("Spacemit K1 CCU driver");
> +MODULE_AUTHOR("Haylen Chu <heylenay@...look.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/clk/spacemit/ccu_common.h b/drivers/clk/spacemit/ccu_common.h
> new file mode 100644
> index 000000000000..c4406099c3fc
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu_common.h
> @@ -0,0 +1,55 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenay@...look.com>
> + */
> +
> +#ifndef _CCU_COMMON_H_
> +#define _CCU_COMMON_H_
> +
> +#include <linux/regmap.h>
> +#include <linux/spinlock.h>
> +
> +enum ccu_div_type {
> +       CLK_DIV_TYPE_1REG_NOFC_V1 = 0,
> +       CLK_DIV_TYPE_1REG_FC_V2,
> +       CLK_DIV_TYPE_2REG_NOFC_V3,
> +       CLK_DIV_TYPE_2REG_FC_V4,
> +       CLK_DIV_TYPE_1REG_FC_DIV_V5,
> +       CLK_DIV_TYPE_1REG_FC_MUX_V6,
> +};
> +
> +struct ccu_common {
> +       struct regmap *base;
> +       struct regmap *lock_base;
> +       spinlock_t *lock;
> +
> +       enum ccu_div_type reg_type;
> +       u32 reg_ctrl;
> +       u32 reg_sel;
> +       u32 reg_xtc;
> +       u32 fc;
> +       bool is_pll;
> +
> +       unsigned long flags;
> +       const char *name;
> +       const char * const *parent_names;
> +       int num_parents;
> +
> +       struct clk_hw hw;
> +};
> +
> +static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct ccu_common, hw);
> +}
> +
> +#define ccu_read(reg, c, val)  regmap_read((c)->base, (c)->reg_##reg, val)
> +#define ccu_write(reg, c, val) regmap_write((c)->base, (c)->reg_##reg, val)
> +#define ccu_update(reg, c, mask, val) \
> +       regmap_update_bits((c)->base, (c)->reg_##reg, mask, val)
> +#define ccu_poll(reg, c, tmp, cond, sleep, timeout) \
> +       regmap_read_poll_timeout_atomic((c)->base, (c)->reg_##reg,      \
> +                                       tmp, cond, sleep, timeout)
> +
> +#endif /* _CCU_COMMON_H_ */
> diff --git a/drivers/clk/spacemit/ccu_ddn.c b/drivers/clk/spacemit/ccu_ddn.c
> new file mode 100644
> index 000000000000..2672da6b6179
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu_ddn.c
> @@ -0,0 +1,166 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Spacemit clock type ddn
> + *
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenay@...look.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_ddn.h"
> +
> +#define ddn_read_sel(common, val)      ccu_read(sel, common, val)
> +#define ddn_read_ctrl(common, val)     ccu_read(ctrl, common, val)
> +#define ddn_update_sel(common, m, v)   ccu_update(sel, common, m, v)
> +#define ddn_update_ctrl(common, m, v)  ccu_update(ctrl, common, m, v)
> +
> +/*
> + * It is M/N clock
> + *
> + * Fout from synthesizer can be given from two equations:
> + * numerator/denominator = Fin / (Fout * factor)
> + */
> +static void ccu_ddn_disable(struct clk_hw *hw)
> +{
> +       struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
> +       struct ccu_common *common = &ddn->common;
> +       unsigned long flags;
> +
> +       if (!ddn->gate)
> +               return;
> +
> +       spin_lock_irqsave(common->lock, flags);

The regmap can have a lock. Can you use that?

> +
> +       ddn_update_sel(common, ddn->gate, 0);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +}
> +
> +static int ccu_ddn_enable(struct clk_hw *hw)
> +{
> +       struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
> +       struct ccu_common *common = &ddn->common;
> +       unsigned long flags;
> +
> +       if (!ddn->gate)
> +               return 0;
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       ddn_update_sel(common, ddn->gate, ddn->gate);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       return 0;
> +}
> +
> +static int ccu_ddn_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
> +       struct ccu_common *common = &ddn->common;
> +       u32 tmp;
> +
> +       if (!ddn->gate)
> +               return 1;
> +
> +       ddn_read_sel(common, &tmp);
> +
> +       return tmp & ddn->gate;
> +}
> +
> +static long clk_ddn_round_rate(struct clk_hw *hw, unsigned long drate,
> +                              unsigned long *prate)
> +{
> +       struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
> +       struct ccu_ddn_config *params = &ddn->ddn;
> +       unsigned long rate = 0, prev_rate;
> +       unsigned long result;
> +       int i;
> +
> +       for (i = 0; i < params->tbl_size; i++) {
> +               prev_rate = rate;
> +               rate = (((*prate / 10000) * params->tbl[i].den) /
> +                       (params->tbl[i].num * params->info->factor)) * 10000;
> +               if (rate > drate)
> +                       break;
> +       }
> +
> +       if ((i == 0) || (i == params->tbl_size)) {
> +               result = rate;
> +       } else {
> +               if ((drate - prev_rate) > (rate - drate))
> +                       result = rate;
> +               else
> +                       result = prev_rate;
> +       }
> +
> +       return result;
> +}
> +
> +static unsigned long clk_ddn_recalc_rate(struct clk_hw *hw,
> +               unsigned long parent_rate)
> +{
> +       struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
> +       struct ccu_ddn_config *params = &ddn->ddn;
> +       unsigned int val, num, den;
> +       unsigned long rate;
> +
> +       ddn_read_ctrl(&ddn->common, &val);
> +
> +       num = (val >> params->info->num_shift) & params->info->num_mask;
> +       den = (val >> params->info->den_shift) & params->info->den_mask;
> +
> +       if (!den)
> +               return 0;
> +
> +       rate = ((parent_rate / 10000)  * den) / (num * params->info->factor);
> +       rate *= 10000;
> +
> +       return rate;
> +}
> +
> +/* Configures new clock rate*/
> +static int clk_ddn_set_rate(struct clk_hw *hw, unsigned long drate,
> +                           unsigned long prate)
> +{
> +       struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
> +       struct ccu_ddn_config *params = &ddn->ddn;
> +       struct ccu_ddn_info *info = params->info;
> +       unsigned long prev_rate, rate = 0;
> +       unsigned long flags;
> +       int i;
> +
> +       for (i = 0; i < params->tbl_size; i++) {
> +               prev_rate = rate;
> +               rate = ((prate / 10000) * params->tbl[i].den) /
> +                      (params->tbl[i].num * info->factor);
> +               rate *= 10000;
> +
> +               if (rate > drate)
> +                       break;
> +       }
> +
> +       if (i > 0)
> +               i--;
> +
> +       spin_lock_irqsave(ddn->common.lock, flags);
> +
> +       ddn_update_ctrl(&ddn->common,
> +                       info->num_mask | info->den_mask,
> +                       (params->tbl[i].num << info->num_shift) |
> +                       (params->tbl[i].den << info->den_shift));
> +
> +       spin_unlock_irqrestore(ddn->common.lock, flags);
> +
> +       return 0;
> +}
> +
> +const struct clk_ops spacemit_ccu_ddn_ops = {
> +       .disable        = ccu_ddn_disable,
> +       .enable         = ccu_ddn_enable,
> +       .is_enabled     = ccu_ddn_is_enabled,
> +       .recalc_rate    = clk_ddn_recalc_rate,
> +       .round_rate     = clk_ddn_round_rate,
> +       .set_rate       = clk_ddn_set_rate,
> +};
> diff --git a/drivers/clk/spacemit/ccu_ddn.h b/drivers/clk/spacemit/ccu_ddn.h
> new file mode 100644
> index 000000000000..ffbbe073199b
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu_ddn.h
> @@ -0,0 +1,82 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenayy@...look.com>
> + */
> +
> +#ifndef _CCU_DDN_H_
> +#define _CCU_DDN_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +
> +struct ccu_ddn_tbl {
> +       unsigned int num;
> +       unsigned int den;
> +};
> +
> +struct ccu_ddn_info {
> +       unsigned int factor;
> +       unsigned int num_mask;
> +       unsigned int den_mask;
> +       unsigned int num_shift;
> +       unsigned int den_shift;
> +};
> +
> +struct ccu_ddn_config {
> +       struct ccu_ddn_info *info;
> +       struct ccu_ddn_tbl *tbl;
> +       u32 tbl_size;
> +};
> +
> +struct ccu_ddn {
> +       struct ccu_ddn_config  ddn;
> +       struct ccu_common       common;
> +       u32 gate;
> +};
> +
> +#define CCU_DDN_CONFIG(_info, _table)                                  \
> +       {                                                               \
> +               .info           = (struct ccu_ddn_info *)_info,         \
> +               .tbl            = (struct ccu_ddn_tbl *)&_table,        \
> +               .tbl_size       = ARRAY_SIZE(_table),                   \
> +       }
> +
> +#define CCU_DDN_DEFINE(_struct, _name, _parent, _info, _table,         \
> +                      _reg_ctrl, _flags)                               \
> +       struct ccu_ddn _struct = {                                      \
> +               .ddn    = CCU_DDN_CONFIG(_info, _table),                \
> +               .common = {                                             \
> +                       .reg_ctrl = _reg_ctrl,                          \
> +                       .hw.init  = CLK_HW_INIT(_name, _parent,         \
> +                                              &spacemit_ccu_ddn_ops,   \
> +                                              _flags),                 \
> +               }                                                       \
> +       }
> +
> +#define CCU_DDN_GATE_DEFINE(_struct, _name, _parent, _info, _table,    \
> +                           _reg_ddn, _reg_gate, _gate_mask, _flags)    \
> +       struct ccu_ddn _struct = {                                      \
> +               .ddn    = CCU_DDN_CONFIG(_info, _table),                \
> +               .common = {                                             \
> +                       .reg_ctrl       = _reg_ddn,                     \
> +                       .reg_sel        = _reg_gate,                    \
> +                       .hw.init = CLK_HW_INIT(_name, _parent,          \
> +                                              &spacemit_ccu_ddn_ops,   \
> +                                              _flags),                 \
> +               }                                                       \
> +               .gate   = _gate_mask,                                   \
> +       }
> +
> +
> +static inline struct ccu_ddn *hw_to_ccu_ddn(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_ddn, common);
> +}
> +
> +extern const struct clk_ops spacemit_ccu_ddn_ops;
> +
> +#endif
> diff --git a/drivers/clk/spacemit/ccu_mix.c b/drivers/clk/spacemit/ccu_mix.c
> new file mode 100644
> index 000000000000..750882b6ed93
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu_mix.c
> @@ -0,0 +1,336 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Spacemit clock type mix(div/mux/gate/factor)
> + *
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenay@...look.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_mix.h"
> +
> +#define MIX_TIMEOUT    10000
> +
> +#define mix_read_sel(c, val)           ccu_read(sel, c, val)
> +#define mix_read_ctrl(c, val)          ccu_read(ctrl, c, val)
> +#define mix_update_sel(c, m, v)                ccu_update(sel, c, m, v)
> +#define mix_update_ctrl(c, m, v)       ccu_update(ctrl, c, m, v)
> +
> +#define mix_hwparam_in_sel(c) \
> +       ((c)->reg_type == CLK_DIV_TYPE_2REG_NOFC_V3 || \
> +        (c)->reg_type == CLK_DIV_TYPE_2REG_FC_V4)
> +
> +static void ccu_mix_disable(struct clk_hw *hw)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_gate_config *gate = mix->gate;
> +       unsigned long flags = 0;
> +
> +       if (!gate)
> +               return;
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_update_sel(common, gate->gate_mask, gate->val_disable);
> +       else
> +               mix_update_ctrl(common, gate->gate_mask, gate->val_disable);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +}
> +
> +static int ccu_mix_enable(struct clk_hw *hw)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_gate_config *gate = mix->gate;
> +       u32 val_enable, mask;
> +       unsigned long flags;
> +       u32 tmp;
> +
> +       if (!gate)
> +               return 0;
> +
> +       val_enable      = gate->val_enable;
> +       mask            = gate->gate_mask;
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_update_sel(common, mask, val_enable);
> +       else
> +               mix_update_ctrl(common, mask, val_enable);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       if (common->reg_type == CLK_DIV_TYPE_2REG_NOFC_V3 ||
> +           common->reg_type == CLK_DIV_TYPE_2REG_FC_V4)
> +               return ccu_poll(sel, common, tmp, (tmp & mask) == val_enable,
> +                               10, MIX_TIMEOUT);
> +       else
> +               return ccu_poll(ctrl, common, tmp, (tmp & mask) == val_enable,
> +                               10, MIX_TIMEOUT);
> +}
> +
> +static int ccu_mix_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_gate_config *gate = mix->gate;
> +       unsigned long flags = 0;
> +       u32 tmp;
> +
> +       if (!gate)
> +               return 1;
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_read_sel(common, &tmp);
> +       else
> +               mix_read_ctrl(common, &tmp);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       return (tmp & gate->gate_mask) == gate->val_enable;
> +}
> +
> +static unsigned long ccu_mix_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_div_config *div = mix->div;
> +       unsigned long val;
> +       u32 reg;
> +
> +       if (!div) {
> +               if (mix->factor)
> +                       return parent_rate * mix->factor->mul / mix->factor->div;
> +
> +               return parent_rate;
> +       }
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_read_sel(common, &reg);
> +       else
> +               mix_read_ctrl(common, &reg);
> +
> +       val = reg >> div->shift;
> +       val &= (1 << div->width) - 1;
> +
> +       val = divider_recalc_rate(hw, parent_rate, val, div->table,
> +                                 div->flags, div->width);
> +
> +       return val;
> +}
> +
> +
> +static int ccu_mix_trigger_fc(struct clk_hw *hw)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       int ret = 0, timeout = 50;
> +       unsigned int val = 0;
> +
> +       if (common->reg_type == CLK_DIV_TYPE_1REG_FC_V2 ||
> +           common->reg_type == CLK_DIV_TYPE_2REG_FC_V4 ||
> +           common->reg_type == CLK_DIV_TYPE_1REG_FC_DIV_V5 ||
> +           common->reg_type == CLK_DIV_TYPE_1REG_FC_MUX_V6) {
> +               timeout = 50;
> +               mix_update_ctrl(common, common->fc, common->fc);
> +
> +               ret = ccu_poll(ctrl, common, val, !(val & common->fc),
> +                              5, MIX_TIMEOUT);
> +       }
> +
> +       return ret;
> +}
> +
> +static int ccu_mix_determine_rate(struct clk_hw *hw,
> +                                 struct clk_rate_request *req)
> +{
> +       return 0;
> +}
> +
> +static long ccu_mix_round_rate(struct clk_hw *hw, unsigned long rate,
> +                               unsigned long *prate)
> +{
> +       return rate;
> +}
> +
> +static unsigned long
> +ccu_mix_calc_best_rate(struct clk_hw *hw, unsigned long rate, u32 *mux_val,
> +                      u32 *div_val)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_div_config *div = mix->div ? mix->div : NULL;
> +       struct clk_hw *parent;
> +       unsigned long parent_rate = 0, best_rate = 0;
> +       u32 i, j, div_max;
> +
> +       for (i = 0; i < common->num_parents; i++) {
> +               parent = clk_hw_get_parent_by_index(hw, i);
> +               if (!parent)
> +                       continue;
> +
> +               parent_rate = clk_hw_get_rate(parent);
> +
> +               if (div)
> +                       div_max = 1 << div->width;
> +               else
> +                       div_max = 1;
> +
> +               for (j = 1; j <= div_max; j++) {
> +                       if (abs(parent_rate/j - rate) < abs(best_rate - rate)) {
> +                               best_rate = DIV_ROUND_UP_ULL(parent_rate, j);
> +                               *mux_val = i;
> +                               *div_val = j - 1;
> +                       }
> +               }
> +       }
> +
> +       return best_rate;
> +}
> +
> +static int ccu_mix_set_rate(struct clk_hw *hw, unsigned long rate,
> +                          unsigned long parent_rate)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_div_config *div = mix->div;
> +       struct ccu_mux_config *mux = mix->mux;
> +       u32 cur_mux, cur_div, mux_val = 0, div_val = 0;
> +       unsigned long best_rate = 0;
> +       unsigned long flags;
> +       int ret = 0, tmp = 0;
> +
> +       if (!div && !mux)
> +               return 0;
> +
> +       best_rate = ccu_mix_calc_best_rate(hw, rate, &mux_val, &div_val);
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_read_sel(common, &tmp);
> +       else
> +               mix_read_ctrl(common, &tmp);
> +
> +       if (mux) {
> +               cur_mux = tmp >> mux->shift;
> +               cur_mux &= (1 << mux->width) - 1;
> +
> +               if (cur_mux != mux_val)
> +                       clk_hw_set_parent(hw,
> +                                         clk_hw_get_parent_by_index(hw,
> +                                                                    mux_val));
> +       }
> +
> +       if (div) {
> +               cur_div = tmp >> div->shift;
> +               cur_div &= (1 << div->width) - 1;
> +
> +               if (cur_div == div_val)
> +                       return 0;
> +       } else {
> +               return 0;
> +       }
> +
> +       tmp = GENMASK(div->width + div->shift - 1, div->shift);
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_update_sel(common, tmp, div_val << div->shift);
> +       else
> +               mix_update_ctrl(common, tmp, div_val << div->shift);
> +
> +       if (common->reg_type == CLK_DIV_TYPE_1REG_FC_V2 ||
> +           common->reg_type == CLK_DIV_TYPE_2REG_FC_V4 ||
> +           common->reg_type == CLK_DIV_TYPE_1REG_FC_DIV_V5)
> +               ret = ccu_mix_trigger_fc(hw);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       return ret;
> +}
> +
> +static u8 ccu_mix_get_parent(struct clk_hw *hw)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_mux_config *mux = mix->mux;
> +       u32 reg;
> +       u8 parent;
> +
> +       if (!mux)
> +               return 0;
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_read_sel(common, &reg);
> +       else
> +               mix_read_ctrl(common, &reg);
> +
> +       parent = reg >> mux->shift;
> +       parent &= (1 << mux->width) - 1;
> +
> +       if (mux->table) {
> +               int num_parents = clk_hw_get_num_parents(&common->hw);
> +               int i;
> +
> +               for (i = 0; i < num_parents; i++)
> +                       if (mux->table[i] == parent)
> +                               return i;
> +       }
> +
> +       return parent;
> +}
> +
> +static int ccu_mix_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct ccu_mix *mix = hw_to_ccu_mix(hw);
> +       struct ccu_common *common = &mix->common;
> +       struct ccu_mux_config *mux = mix->mux;
> +       unsigned long flags;
> +       int ret = 0;
> +       u32 mask;
> +
> +       if (!mux)
> +               return 0;
> +
> +       if (mux->table)
> +               index = mux->table[index];
> +
> +       mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       if (mix_hwparam_in_sel(common))
> +               mix_update_sel(common, mask, index << mux->shift);
> +       else
> +               mix_update_ctrl(common, mask, index << mux->shift);
> +
> +       if (common->reg_type == CLK_DIV_TYPE_1REG_FC_V2 ||
> +           common->reg_type == CLK_DIV_TYPE_2REG_FC_V4 ||
> +           common->reg_type == CLK_DIV_TYPE_1REG_FC_MUX_V6)
> +               ret = ccu_mix_trigger_fc(hw);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       return ret;
> +}
> +
> +const struct clk_ops spacemit_ccu_mix_ops = {
> +       .disable         = ccu_mix_disable,
> +       .enable          = ccu_mix_enable,
> +       .is_enabled      = ccu_mix_is_enabled,
> +       .get_parent      = ccu_mix_get_parent,
> +       .set_parent      = ccu_mix_set_parent,
> +       .determine_rate  = ccu_mix_determine_rate,
> +       .round_rate      = ccu_mix_round_rate,

Only implement determine_rate

> +       .recalc_rate     = ccu_mix_recalc_rate,
> +       .set_rate        = ccu_mix_set_rate,
> +};
> +
> diff --git a/drivers/clk/spacemit/ccu_mix.h b/drivers/clk/spacemit/ccu_mix.h
> new file mode 100644
> index 000000000000..753bc6177df7
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu_mix.h
> @@ -0,0 +1,348 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenay@...look.com>
> + */
> +
> +#ifndef _CCU_MIX_H_
> +#define _CCU_MIX_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +
> +struct ccu_gate_config {
> +       u32 gate_mask;
> +       u32 val_enable;
> +       u32 val_disable;
> +       u32 flags;
> +};
> +
> +struct ccu_factor_config {
> +       u32 div;
> +       u32 mul;
> +};
> +
> +struct ccu_mux_config {
> +       const u8 *table;
> +       u32 flags;
> +       u8 shift;
> +       u8 width;
> +};
> +
> +struct ccu_div_config {
> +       struct clk_div_table *table;
> +       u32 max;
> +       u32 offset;
> +       u32 flags;
> +       u8 shift;
> +       u8 width;
> +};
> +
> +struct ccu_mix {
> +       struct ccu_factor_config *factor;
> +       struct ccu_gate_config *gate;
> +       struct ccu_div_config *div;
> +       struct ccu_mux_config *mux;
> +       struct ccu_common common;
> +};
> +
> +#define CCU_GATE_INIT(_gate_mask, _val_enable, _val_disable, _flags)           \
> +       (&(struct ccu_gate_config) {                                            \
> +               .gate_mask   = _gate_mask,                                      \
> +               .val_enable  = _val_enable,                                     \
> +               .val_disable = _val_disable,                                    \
> +               .flags       = _flags,                                          \
> +       })
> +
> +#define CCU_FACTOR_INIT(_div, _mul)                                    \
> +       (&(struct ccu_factor_config) {                                  \
> +               .div = _div,                                            \
> +               .mul = _mul,                                            \
> +       })
> +
> +
> +#define CCU_MUX_INIT(_shift, _width, _table, _flags)                   \
> +       (&(struct ccu_mux_config) {                                     \
> +               .shift  = _shift,                                       \
> +               .width  = _width,                                       \
> +               .table  = _table,                                       \
> +               .flags  = _flags,                                       \
> +       })
> +
> +#define CCU_DIV_INIT(_shift, _width, _table, _flags)                   \
> +       (&(struct ccu_div_config) {                                     \
> +               .shift  = _shift,                                       \
> +               .width  = _width,                                       \
> +               .flags  = _flags,                                       \
> +               .table  = _table,                                       \
> +       })
> +
> +#define CCU_MIX_INITHW(_name, _parent, _flags) \
> +       CLK_HW_INIT(_name, _parent, &spacemit_ccu_mix_ops, _flags)
> +
> +#define CCU_MIX_ORPHAN_INITHW(_name, _flags) \
> +       CLK_HW_INIT_NO_PARENT(_name, &spacemit_ccu_mix_ops, _flags)
> +
> +#define CCU_MIX_INITHW_PARENTS(_name, _parents, _flags) \
> +       CLK_HW_INIT_PARENTS(_name, _parents, &spacemit_ccu_mix_ops, _flags)
> +
> +#define CCU_GATE_DEFINE(_struct, _name, _parent, _reg, _gate_mask,     \
> +                        _val_enable, _val_disable, _flags)             \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .num_parents    = 1,                                    \
> +               .hw.init        = CCU_MIX_INITHW(_name, _parent,        \
> +                                                _flags),               \
> +       }                                                               \
> +}
> +#define CCU_GATE_NO_PARENT_DEFINE(_struct, _name,  _reg, _gate_mask,   \
> +                                 _val_enable, _val_disable, _flags)    \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .num_parents    = 0,                                    \
> +               .hw.init        = CCU_MIX_ORPHAN_INITHW(_name, _flags)  \
> +       }                                                               \
> +}
> +
> +#define CCU_FACTOR_DEFINE(_struct, _name, _parent, _div, _mul)         \
> +struct ccu_mix _struct = {                                             \
> +       .factor = CCU_FACTOR_INIT(_div, _mul),                          \
> +       .common = {                                                     \
> +               .name           = _name,                                \
> +               .num_parents    = 1,                                    \
> +               .hw.init        = CCU_MIX_INITHW(_name, _parent, 0),    \
> +       }                                                               \
> +}
> +
> +#define CCU_MUX_DEFINE(_struct, _name, _parents, _reg, _shift, _width, \
> +                      _flags)                                          \
> +struct ccu_mix _struct = {                                             \
> +       .mux    = CCU_MUX_INIT(_shift, _width, NULL, 0),                \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       }                                                               \
> +}
> +
> +#define CCU_DIV_DEFINE(_struct, _name, _parent, _reg, _shift, _width,  \
> +                      _flags)                                          \
> +struct ccu_mix _struct = {                                             \
> +       .div    = CCU_DIV_INIT(_shift, _width, NULL, 0),                \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .num_parents    = 1,                                    \
> +               .hw.init = CCU_MIX_INITHW(_name, _parent, _flags)       \
> +       }                                                               \
> +}
> +
> +#define CCU_GATE_FACTOR_DEFINE(_struct, _name, _parent, _reg,          \
> +                              _gate_mask, _val_enable, _val_disable,   \
> +                              _div, _mul, _flags)                      \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .factor = CCU_FACTOR_INIT(_div, _mul),                          \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .num_parents    = 1,                                    \
> +               .hw.init = CCU_MIX_INITHW(_name, _parent, _flags)       \
> +       }                                                               \
> +}
> +
> +
> +#define CCU_MUX_GATE_DEFINE(_struct, _name, _parents, _reg, _shift,    \
> +                           _width, _gate_mask, _val_enable,            \
> +                           _val_disable, _flags)                       \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .mux    = CCU_MUX_INIT(_shift, _width, NULL, 0),                \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       }                                                               \
> +}
> +
> +#define CCU_DIV_GATE_DEFINE(_struct, _name, _parent, _reg, _shift,     \
> +                           _width, _gate_mask, _val_enable,            \
> +                           _val_disable, _flags)                       \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .div    = CCU_DIV_INIT(_shift, _width, NULL, 0),                \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg,                                 \
> +               .name           = _name,                                \
> +               .num_parents    = 1,                                    \
> +               .hw.init        = CCU_MIX_INITHW(_name, _parent,        \
> +                                                _flags),               \
> +       }                                                               \
> +}
> +
> +
> +#define CCU_DIV_MUX_GATE_DEFINE(_struct, _name, _parents,  _reg_ctrl,  \
> +                               _mshift, _mwidth, _muxshift, _muxwidth, \
> +                               _gate_mask, _val_enable, _val_disable,  \
> +                               _flags)                                 \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .div    = CCU_DIV_INIT(_mshift, _mwidth, NULL, 0),              \
> +       .mux    = CCU_MUX_INIT(_muxshift, _muxwidth, NULL, 0),          \
> +       .common = {                                                     \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       },                                                              \
> +}
> +
> +#define CCU_DIV2_FC_MUX_GATE_DEFINE(_struct, _name, _parents,          \
> +                                   _reg_ctrl, _reg_sel, _mshift,       \
> +                                   _mwidth, _fc, _muxshift, _muxwidth, \
> +                                   _gate_mask, _val_enable,            \
> +                                   _val_disable, _flags)               \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .div    = CCU_DIV_INIT(_mshift, _mwidth, NULL, 0),              \
> +       .mux    = CCU_MUX_INIT(_muxshift, _muxwidth, NULL, 0),          \
> +       .common = {                                                     \
> +           .reg_type = CLK_DIV_TYPE_2REG_FC_V4,                        \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .reg_sel        = _reg_sel,                             \
> +               .fc             = _fc,                                  \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       },                                                              \
> +}
> +
> +
> +#define CCU_DIV_FC_MUX_GATE_DEFINE(_struct, _name, _parents, _reg_ctrl,        \
> +                                  _mshift, _mwidth, _fc, _muxshift,    \
> +                                  _muxwidth, _gate_mask, _val_enable,  \
> +                                  _val_disable, _flags)                \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .div    = CCU_DIV_INIT(_mshift, _mwidth, NULL, 0),              \
> +       .mux    = CCU_MUX_INIT(_muxshift, _muxwidth, NULL, 0),          \
> +       .common = {                                                     \
> +               .reg_type       = CLK_DIV_TYPE_1REG_FC_V2,              \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .fc             = _fc,                                  \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       },                                                              \
> +}
> +
> +#define CCU_DIV_MFC_MUX_GATE_DEFINE(_struct, _name, _parents,          \
> +                                   _reg_ctrl, _mshift, _mwidth, _fc,   \
> +                                   _muxshift, _muxwidth, _gate_mask,   \
> +                                   _val_enable, _val_disable, _flags)  \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .div    = CCU_DIV_INIT(_mshift, _mwidth, NULL, 0),              \
> +       .mux    = CCU_MUX_INIT(_muxshift, _muxwidth, NULL, 0),          \
> +       .common = {                                                     \
> +               .reg_type = CLK_DIV_TYPE_1REG_FC_MUX_V6,                \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .fc             = _fc,                                  \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       },                                                              \
> +}
> +
> +#define CCU_DIV_FC_WITH_GATE_DEFINE(_struct, _name, _parent, _reg_ctrl,        \
> +                                   _mshift, _mwidth, _fc, _gate_mask,  \
> +                                   _val_enable, _val_disable, _flags)  \
> +struct ccu_mix _struct = {                                             \
> +       .gate   = CCU_GATE_INIT(_gate_mask, _val_enable,                \
> +                               _val_disable, 0),                       \
> +       .div    = CCU_DIV_INIT(_mshift, _mwidth, NULL, 0),              \
> +       .common = {                                                     \
> +               .reg_type = CLK_DIV_TYPE_1REG_FC_V2,                    \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .fc             = _fc,                                  \
> +               .name           = _name,                                \
> +               .num_parents    = 1,                                    \
> +               .hw.init        = CCU_MIXINITHW(_name, _parent,         \
> +                                               _flags),                \
> +       },                                                              \
> +}
> +
> +#define CCU_DIV_FC_MUX_DEFINE(_struct, _name, _parents, _reg_ctrl,     \
> +                             _mshift, _mwidth, _fc, _muxshift,         \
> +                             _muxwidth, _flags)                        \
> +struct ccu_mix _struct = {                                             \
> +       .div    = CCU_DIV_INIT(_mshift, _mwidth, NULL, 0),              \
> +       .mux    = CCU_MUX_INIT(_muxshift, _muxwidth, NULL, 0),          \
> +       .common = {                                                     \
> +               .reg_type       = CLK_DIV_TYPE_1REG_FC_V2,              \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .fc             = _fc,                                  \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags),              \
> +       },                                                              \
> +}
> +
> +#define CCU_MUX_FC_DEFINE(_struct, _name, _parents, _reg_ctrl, _fc,    \
> +                         _muxshift, _muxwidth, _flags)                 \
> +struct ccu_mix _struct = {                                             \
> +       .mux    = CCU_MUX_INIT(_muxshift, _muxwidth, NULL, 0),          \
> +       .common = {                                                     \
> +               .reg_type       = CLK_DIV_TYPE_1REG_FC_V2,              \
> +               .reg_ctrl       = _reg_ctrl,                            \
> +               .fc             = _fc,                                  \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .hw.init = CCU_MIX_INITHW_PARENTS(_name, _parents,      \
> +                                                 _flags)               \
> +       },                                                              \
> +}
> +
> +static inline struct ccu_mix *hw_to_ccu_mix(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_mix, common);
> +}
> +
> +extern const struct clk_ops spacemit_ccu_mix_ops;
> +
> +#endif /* _CCU_DIV_H_ */
> diff --git a/drivers/clk/spacemit/ccu_pll.c b/drivers/clk/spacemit/ccu_pll.c
> new file mode 100644
> index 000000000000..1f0ece6abcac
> --- /dev/null
> +++ b/drivers/clk/spacemit/ccu_pll.c
> @@ -0,0 +1,226 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Spacemit clock type pll
> + *
> + * Copyright (c) 2024 SpacemiT Technology Co. Ltd
> + * Copyright (c) 2024 Haylen Chu <heylenay@...look.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/regmap.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_pll.h"
> +
> +#define PLL_MIN_FREQ   600000000
> +#define PLL_MAX_FREQ   3400000000
> +#define PLL_DELAY_TIME 3000
> +
> +#define pll_read_swcr1(c, v)   ccu_read(ctrl, c, v)
> +#define pll_read_swcr2(c, v)   ccu_read(sel, c, v)
> +#define pll_read_swcr3(c, v)   ccu_read(xtc, c, v)
> +
> +#define pll_update_swcr1(c, m, v)      ccu_update(ctrl, c, m, v)
> +#define pll_update_swcr2(c, m, v)      ccu_update(sel, c, m, v)
> +#define pll_update_swcr3(c, m, v)      ccu_update(xtc, c, m, v)

Please stop wrapping regmap APIs. Just use them directly.

> +
> +#define PLL_SWCR1_REG5_OFF     0
> +#define PLL_SWCR1_REG5_MASK    GENMASK(7, 0)
> +#define PLL_SWCR1_REG6_OFF     8
> +#define PLL_SWCR1_REG6_MASK    GENMASK(15, 8)
> +#define PLL_SWCR1_REG7_OFF     16
> +#define PLL_SWCR1_REG7_MASK    GENMASK(23, 16)
> +#define PLL_SWCR1_REG8_OFF     24
> +#define PLL_SWCR1_REG8_MASK    GENMASK(31, 24)
> +
> +#define PLL_SWCR2_DIVn_EN(n)   BIT(n + 1)
> +#define PLL_SWCR2_ATEST_EN     BIT(12)
> +#define PLL_SWCR2_CKTEST_EN    BIT(13)
> +#define PLL_SWCR2_DTEST_EN     BIT(14)
> +
> +#define PLL_SWCR3_DIV_FRC_OFF  0
> +#define PLL_SWCR3_DIV_FRC_MASK GENMASK(23, 0)
> +#define PLL_SWCR3_DIV_INT_OFF  24
> +#define PLL_SWCR3_DIV_INT_MASK GENMASK(30, 24)
> +#define PLL_SWCR3_EN           BIT(31)
> +
> +static int ccu_pll_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_pll *p = hw_to_ccu_pll(hw);
> +       u32 tmp;
> +
> +       pll_read_swcr3(&p->common, &tmp);
> +
> +       return tmp & PLL_SWCR3_EN;
> +}
> +
> +/* frequency unit Mhz, return pll vco freq */
> +static unsigned long __get_vco_freq(struct clk_hw *hw)
> +{
> +       unsigned int reg5, reg6, reg7, reg8, size, i;
> +       unsigned int div_int, div_frc;
> +       struct ccu_pll_rate_tbl *freq_pll_regs_table;
> +       struct ccu_pll *p = hw_to_ccu_pll(hw);
> +       struct ccu_common *common = &p->common;
> +       u32 tmp;
> +
> +       pll_read_swcr1(common, &tmp);
> +       reg5 = (tmp & PLL_SWCR1_REG5_MASK) >> PLL_SWCR1_REG5_OFF;
> +       reg6 = (tmp & PLL_SWCR1_REG6_MASK) >> PLL_SWCR1_REG6_OFF;
> +       reg7 = (tmp & PLL_SWCR1_REG7_MASK) >> PLL_SWCR1_REG7_OFF;
> +       reg8 = (tmp & PLL_SWCR1_REG8_MASK) >> PLL_SWCR1_REG8_OFF;
> +
> +       pll_read_swcr3(common, &tmp);
> +       div_int = (tmp & PLL_SWCR3_DIV_INT_MASK) >> PLL_SWCR3_DIV_INT_OFF;
> +       div_frc = (tmp & PLL_SWCR3_DIV_FRC_MASK) >> PLL_SWCR3_DIV_FRC_OFF;
> +
> +       freq_pll_regs_table = p->pll.rate_tbl;
> +       size = p->pll.tbl_size;
> +
> +       for (i = 0; i < size; i++)
> +               if ((freq_pll_regs_table[i].reg5 == reg5) &&
> +                   (freq_pll_regs_table[i].reg6 == reg6) &&
> +                   (freq_pll_regs_table[i].reg7 == reg7) &&
> +                   (freq_pll_regs_table[i].reg8 == reg8) &&
> +                   (freq_pll_regs_table[i].div_int == div_int) &&
> +                   (freq_pll_regs_table[i].div_frac == div_frc))
> +                       return freq_pll_regs_table[i].rate;
> +
> +       WARN_ON_ONCE(1);
> +
> +       return 0;
> +}
> +
> +static int ccu_pll_enable(struct clk_hw *hw)
> +{
> +       struct ccu_pll *p = hw_to_ccu_pll(hw);
> +       struct ccu_common *common = &p->common;
> +       unsigned long flags;
> +       unsigned int tmp;
> +       int ret;
> +
> +       if (ccu_pll_is_enabled(hw))
> +               return 0;
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       pll_update_swcr3(common, PLL_SWCR3_EN, PLL_SWCR3_EN);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       /* check lock status */
> +       ret = regmap_read_poll_timeout_atomic(common->lock_base,
> +                                             p->pll.reg_lock,
> +                                             tmp,
> +                                             tmp & p->pll.lock_enable_bit,
> +                                             5, PLL_DELAY_TIME);
> +
> +       return ret;
> +}
> +
> +static void ccu_pll_disable(struct clk_hw *hw)
> +{
> +       struct ccu_pll *p = hw_to_ccu_pll(hw);
> +       struct ccu_common *common = &p->common;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(p->common.lock, flags);
> +
> +       pll_update_swcr3(common, PLL_SWCR3_EN, 0);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +}
> +
> +/*
> + * pll rate change requires sequence:
> + * clock off -> change rate setting -> clock on
> + * This function doesn't really change rate, but cache the config
> + */
> +static int ccu_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +                              unsigned long parent_rate)
> +{
> +       struct ccu_pll *p = hw_to_ccu_pll(hw);
> +       struct ccu_common *common = &p->common;
> +       struct ccu_pll_config *params = &p->pll;
> +       struct ccu_pll_rate_tbl *entry;
> +       unsigned long old_rate;
> +       unsigned long flags;
> +       bool found = false;
> +       u32 mask, val;
> +       int i;
> +
> +       if (ccu_pll_is_enabled(hw)) {
> +               pr_err("%s %s is enabled, ignore the setrate!\n",
> +                      __func__, __clk_get_name(hw->clk));
> +               return 0;
> +       }
> +
> +       old_rate = __get_vco_freq(hw);
> +
> +       for (i = 0; i < params->tbl_size; i++) {
> +               if (rate == params->rate_tbl[i].rate) {
> +                       found = true;
> +                       entry = &params->rate_tbl[i];
> +                       break;
> +               }
> +       }
> +       WARN_ON_ONCE(!found);
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       mask = PLL_SWCR1_REG5_MASK | PLL_SWCR1_REG6_MASK;
> +       mask |= PLL_SWCR1_REG7_MASK | PLL_SWCR1_REG8_MASK;
> +       val |= entry->reg5 << PLL_SWCR1_REG5_OFF;
> +       val |= entry->reg6 << PLL_SWCR1_REG6_OFF;
> +       val |= entry->reg7 << PLL_SWCR1_REG7_OFF;
> +       val |= entry->reg8 << PLL_SWCR1_REG8_OFF;
> +       pll_update_swcr1(common, mask, val);
> +
> +       mask = PLL_SWCR3_DIV_INT_MASK | PLL_SWCR3_DIV_FRC_MASK;
> +       val = entry->div_int << PLL_SWCR3_DIV_INT_OFF;
> +       val |= entry->div_frac << PLL_SWCR3_DIV_FRC_OFF;
> +       pll_update_swcr3(common, mask, val);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       return 0;
> +}
> +
> +static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,
> +                                        unsigned long parent_rate)
> +{
> +       return __get_vco_freq(hw);
> +}
> +
> +static long ccu_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +                              unsigned long *prate)
> +{
> +       struct ccu_pll *p = hw_to_ccu_pll(hw);
> +       struct ccu_pll_config *params = &p->pll;
> +       unsigned long max_rate = 0;
> +       unsigned int i;
> +
> +       if (rate > PLL_MAX_FREQ || rate < PLL_MIN_FREQ) {
> +               pr_err("%lu rate out of range!\n", rate);

We should simply clamp the rate here. It doesn't matter what 'rate' is
when this function is called. The callback is supposed to determine what
the clk rate will be if a consumer called clk_set_rate() with 'rate'.
Don't fail that if the rate is requested to be larger than max, just
tell clk_round_rate() that if you ask for something larger you'll get
PLL_MAX_FREQ.

> +               return -EINVAL;
> +       }
> +

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ