[PATCH v7 2/3] clk: canaan: Add clock driver for Canaan K230

Xukai Wang kingxukai at zohomail.com
Tue Jul 29 11:43:52 PDT 2025


This patch provides basic support for the K230 clock, which covers
all clocks in K230 SoC.

The clock tree of the K230 SoC consists of a 24MHZ external crystal
oscillator, PLLs and an external pulse input for timerX, and their
derived clocks.

Co-developed-by: Troy Mitchell <TroyMitchell988 at gmail.com>
Signed-off-by: Troy Mitchell <TroyMitchell988 at gmail.com>
Signed-off-by: Xukai Wang <kingxukai at zohomail.com>
---
 drivers/clk/Kconfig    |    6 +
 drivers/clk/Makefile   |    1 +
 drivers/clk/clk-k230.c | 2456 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 2463 insertions(+)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 299bc678ed1b9fcd9110bb8c5937a1bd1ea60e23..b597912607a6cc8eabff459a890a1e7353ef9c1d 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -464,6 +464,12 @@ config COMMON_CLK_K210
 	help
 	  Support for the Canaan Kendryte K210 RISC-V SoC clocks.
 
+config COMMON_CLK_K230
+	bool "Clock driver for the Canaan Kendryte K230 SoC"
+	depends on ARCH_CANAAN || COMPILE_TEST
+	help
+	  Support for the Canaan Kendryte K230 RISC-V SoC clocks.
+
 config COMMON_CLK_SP7021
 	tristate "Clock driver for Sunplus SP7021 SoC"
 	depends on SOC_SP7021 || COMPILE_TEST
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index fb8878a5d7d93da6bec487460cdf63f1f764a431..5df50b1e14c701ed38397bfb257db26e8dd278b8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_MACH_ASPEED_G6)		+= clk-ast2600.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
 obj-$(CONFIG_CLK_HSDK)			+= clk-hsdk-pll.o
 obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
+obj-$(CONFIG_COMMON_CLK_K230)		+= clk-k230.o
 obj-$(CONFIG_LMK04832)			+= clk-lmk04832.o
 obj-$(CONFIG_COMMON_CLK_LAN966X)	+= clk-lan966x.o
 obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
diff --git a/drivers/clk/clk-k230.c b/drivers/clk/clk-k230.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ba74c008b30ae3400acbd8c08550e8315dfe205
--- /dev/null
+++ b/drivers/clk/clk-k230.c
@@ -0,0 +1,2456 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Kendryte Canaan K230 Clock Drivers
+ *
+ * Author: Xukai Wang <kingxukai at zohomail.com>
+ * Author: Troy Mitchell <troymitchell988 at gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/iopoll.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/canaan,k230-clk.h>
+
+/* PLL control register bits. */
+#define K230_PLL_BYPASS_ENABLE			BIT(19)
+#define K230_PLL_GATE_ENABLE			BIT(2)
+#define K230_PLL_GATE_WRITE_ENABLE		BIT(18)
+#define K230_PLL_OD_SHIFT			24
+#define K230_PLL_OD_MASK			0xF
+#define K230_PLL_R_SHIFT			16
+#define K230_PLL_R_MASK				0x3F
+#define K230_PLL_F_SHIFT			0
+#define K230_PLL_F_MASK				0x1FFF
+#define K230_PLL_DIV_REG_OFFSET			0x00
+#define K230_PLL_BYPASS_REG_OFFSET		0x04
+#define K230_PLL_GATE_REG_OFFSET		0x08
+#define K230_PLL_LOCK_REG_OFFSET		0x0C
+
+/* PLL lock register */
+#define K230_PLL_LOCK_STATUS_MASK		BIT(0)
+#define K230_PLL_LOCK_TIME_DELAY		400
+#define K230_PLL_LOCK_TIMEOUT			0
+
+/* K230 CLK registers offset */
+#define K230_CLK_AUDIO_CLKDIV_OFFSET		0x34
+#define K230_CLK_PDM_CLKDIV_OFFSET		0x40
+#define K230_CLK_CODEC_ADC_MCLKDIV_OFFSET	0x38
+#define K230_CLK_CODEC_DAC_MCLKDIV_OFFSET	0x3c
+
+#define K230_PLLX_DIV_ADDR(base, idx)						\
+	(K230_PLL_DIV_REG_OFFSET + (base) + (idx) * 0x10)
+
+#define K230_PLLX_BYPASS_ADDR(base, idx)					\
+	(K230_PLL_BYPASS_REG_OFFSET + (base) + (idx) * 0x10)
+
+#define K230_PLLX_GATE_ADDR(base, idx)						\
+	(K230_PLL_GATE_REG_OFFSET + (base) + (idx) * 0x10)
+
+#define K230_PLLX_LOCK_ADDR(base, idx)						\
+	(K230_PLL_LOCK_REG_OFFSET + (base) + (idx) * 0x10)
+
+#define K230_CLK_RATE_FORMAT_PNAME(_var, _id,					\
+				   _mul_min, _mul_max, _mul_shift, _mul_mask,	\
+				   _div_min, _div_max, _div_shift, _div_mask,	\
+				   _reg, _bit, _method, _reg2,			\
+				   _read_only, _flags,				\
+				   _pname)					\
+	static struct k230_clk_rate _var = {					\
+		.div_reg_off = _reg,						\
+		.mul_reg_off = _reg2,						\
+		.id = _id,							\
+		.clk = {							\
+			.write_enable_bit = _bit,				\
+			.mul_min = _mul_min,					\
+			.mul_max = _mul_max,					\
+			.mul_shift = _mul_shift,				\
+			.mul_mask = _mul_mask,					\
+			.div_min = _div_min,					\
+			.div_max = _div_max,					\
+			.div_shift = _div_shift,				\
+			.div_mask = _div_mask,					\
+			.read_only = _read_only,				\
+			.hw.init = CLK_HW_INIT_FW_NAME(#_var,			\
+				   _pname, &k230_clk_ops_##_method,		\
+				   _flags),					\
+		},								\
+	}
+
+#define K230_CLK_RATE_FORMAT(_var, _id,						\
+			     _mul_min, _mul_max, _mul_shift, _mul_mask,		\
+			     _div_min, _div_max, _div_shift, _div_mask,		\
+			     _reg, _bit, _method, _reg2,			\
+			     _read_only, _flags,				\
+			     _phw)						\
+	static struct k230_clk_rate _var = {					\
+		.div_reg_off = _reg,						\
+		.mul_reg_off = _reg2,						\
+		.id = _id,							\
+		.clk = {							\
+			.write_enable_bit = _bit,				\
+			.mul_min = _mul_min,					\
+			.mul_max = _mul_max,					\
+			.mul_shift = _mul_shift,				\
+			.mul_mask = _mul_mask,					\
+			.div_min = _div_min,					\
+			.div_max = _div_max,					\
+			.div_shift = _div_shift,				\
+			.div_mask = _div_mask,					\
+			.read_only = _read_only,				\
+			.hw.init = CLK_HW_INIT_HW(#_var,			\
+				   _phw, &k230_clk_ops_##_method,		\
+				   _flags),					\
+		},								\
+	}
+
+#define K230_CLK_GATE_FORMAT_PNAME(_var, _id,					\
+				   _reg, _bit, _flags, _gate_flags,		\
+				   _pname)					\
+	static struct k230_clk_gate _var = {					\
+		.reg_off = _reg,						\
+		.id = _id,							\
+		.clk = {							\
+			.bit_idx = _bit,					\
+			.flags = _gate_flags,					\
+			.hw.init = CLK_HW_INIT_FW_NAME(#_var,			\
+				   _pname, &clk_gate_ops, _flags),		\
+		},								\
+	}
+
+#define K230_CLK_GATE_FORMAT(_var, _id,						\
+			     _reg, _bit, _flags, _gate_flags,			\
+			     _phw)						\
+	static struct k230_clk_gate _var = {					\
+		.reg_off = _reg,						\
+		.id = _id,							\
+		.clk = {							\
+			.bit_idx = _bit,					\
+			.flags = _gate_flags,					\
+			.hw.init = CLK_HW_INIT_HW(#_var,			\
+				   _phw, &clk_gate_ops, _flags),		\
+		},								\
+	}
+
+#define K230_CLK_MUX_FORMAT(_var, _id,						\
+			    _reg, _shift, _mask, _flags, _mux_flags, _pdata)	\
+	static struct k230_clk_mux _var = {					\
+		.reg_off = _reg,						\
+		.id = _id,							\
+		.clk = {							\
+			.flags = _mux_flags,					\
+			.shift = _shift,					\
+			.mask = _mask,						\
+			.hw.init = CLK_HW_INIT_PARENTS_DATA(#_var,		\
+				   _pdata, &clk_mux_ops, _flags),		\
+		},								\
+	}
+
+#define K230_CLK_FIXED_FACTOR_FORMAT(_var,					\
+				     _mul, _div, _flags,			\
+				     _phw)					\
+	static struct clk_fixed_factor _var = {					\
+		.mult = _mul,							\
+		.div = _div,							\
+		.hw.init = CLK_HW_INIT_HW(#_var,				\
+			   _phw, &clk_fixed_factor_ops, _flags),		\
+	}
+
+#define K230_CLK_PLL_FORMAT(_var, _id, _flags, _pname)				\
+	static struct k230_pll _var = {						\
+		.hw.init = CLK_HW_INIT_FW_NAME(#_var,				\
+			   _pname, &k230_pll_ops, _flags),			\
+		.id = _id,							\
+	}
+
+struct k230_pll {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	/* ensures mutual exclusion for concurrent register access. */
+	spinlock_t	*lock;
+	int id;
+};
+
+#define hw_to_k230_pll(_hw) container_of(_hw, struct k230_pll, hw)
+
+struct k230_clk_rate_self {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	bool		read_only;
+	u32		write_enable_bit;
+	u32		mul_min;
+	u32		mul_max;
+	u32		mul_shift;
+	u32		mul_mask;
+	u32		div_min;
+	u32		div_max;
+	u32		div_shift;
+	u32		div_mask;
+	/* ensures mutual exclusion for concurrent register access. */
+	spinlock_t	*lock;
+};
+
+#define hw_to_k230_clk_rate_self(_hw)	container_of(_hw,			\
+					struct k230_clk_rate_self, hw)
+
+struct k230_clk_rate {
+	u32				mul_reg_off;
+	u32				div_reg_off;
+	struct k230_clk_rate_self	clk;
+	int				id;
+};
+
+static inline struct k230_clk_rate *hw_to_k230_clk_rate(struct clk_hw *hw)
+{
+	return container_of(hw_to_k230_clk_rate_self(hw), struct k230_clk_rate,
+			    clk);
+}
+
+struct k230_clk_gate {
+	u32			reg_off;
+	struct clk_gate		clk;
+	int			id;
+};
+
+struct k230_clk_mux {
+	u32			reg_off;
+	struct clk_mux		clk;
+	int			id;
+};
+
+static int k230_pll_prepare(struct clk_hw *hw);
+static int k230_pll_enable(struct clk_hw *hw);
+static void k230_pll_disable(struct clk_hw *hw);
+static int k230_pll_is_enabled(struct clk_hw *hw);
+static unsigned long k230_pll_get_rate(struct clk_hw *hw, unsigned long parent_rate);
+
+static const struct clk_ops k230_pll_ops = {
+	.prepare	= k230_pll_prepare,
+	.enable	        = k230_pll_enable,
+	.disable	= k230_pll_disable,
+	.is_enabled	= k230_pll_is_enabled,
+	.recalc_rate	= k230_pll_get_rate,
+};
+
+K230_CLK_PLL_FORMAT(pll0, 0, CLK_IS_CRITICAL, 0);
+K230_CLK_PLL_FORMAT(pll1, 1, CLK_IS_CRITICAL, 0);
+K230_CLK_PLL_FORMAT(pll2, 2, CLK_IS_CRITICAL, 0);
+K230_CLK_PLL_FORMAT(pll3, 3, CLK_IS_CRITICAL, 0);
+
+struct k230_pll *k230_plls[] = {
+	&pll0,
+	&pll1,
+	&pll2,
+	&pll3,
+};
+
+K230_CLK_FIXED_FACTOR_FORMAT(pll0_div2, 1, 2, 0, &pll0.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll0_div3, 1, 3, 0, &pll0.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll0_div4, 1, 4, 0, &pll0.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll0_div16, 1, 16, 0, &pll0.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll1_div2, 1, 2, 0, &pll1.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll1_div3, 1, 3, 0, &pll1.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll1_div4, 1, 4, 0, &pll1.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll2_div2, 1, 2, 0, &pll2.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll2_div3, 1, 3, 0, &pll2.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll2_div4, 1, 4, 0, &pll2.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll3_div2, 1, 2, 0, &pll3.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll3_div3, 1, 3, 0, &pll3.hw);
+K230_CLK_FIXED_FACTOR_FORMAT(pll3_div4, 1, 4, 0, &pll3.hw);
+
+struct clk_fixed_factor *k230_pll_divs[] = {
+	&pll0_div2,
+	&pll0_div3,
+	&pll0_div4,
+	&pll0_div16,
+	&pll1_div2,
+	&pll1_div3,
+	&pll1_div4,
+	&pll2_div2,
+	&pll2_div3,
+	&pll2_div4,
+	&pll3_div2,
+	&pll3_div3,
+	&pll3_div4,
+};
+
+static int k230_clk_set_rate_mul(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate);
+static long k230_clk_round_rate_mul(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate);
+static unsigned long k230_clk_get_rate_mul(struct clk_hw *hw,
+					   unsigned long parent_rate);
+static int k230_clk_set_rate_div(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate);
+static long k230_clk_round_rate_div(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate);
+static unsigned long k230_clk_get_rate_div(struct clk_hw *hw,
+					   unsigned long parent_rate);
+static int k230_clk_set_rate_mul_div(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate);
+static long k230_clk_round_rate_mul_div(struct clk_hw *hw, unsigned long rate,
+					unsigned long *parent_rate);
+static unsigned long k230_clk_get_rate_mul_div(struct clk_hw *hw,
+					       unsigned long parent_rate);
+
+/* clk_ops for clocks whose rate is determined by a configurable multiplier */
+static const struct clk_ops k230_clk_ops_mul = {
+	.set_rate	= k230_clk_set_rate_mul,
+	.round_rate	= k230_clk_round_rate_mul,
+	.recalc_rate	= k230_clk_get_rate_mul,
+};
+
+/* clk_ops for clocks whose rate is determined by a configurable divider */
+static const struct clk_ops k230_clk_ops_div = {
+	.set_rate	= k230_clk_set_rate_div,
+	.round_rate	= k230_clk_round_rate_div,
+	.recalc_rate	= k230_clk_get_rate_div,
+};
+
+/* clk_ops for clocks whose rate is determined by both a multiplier and a divider */
+static const struct clk_ops k230_clk_ops_mul_div = {
+	.set_rate	= k230_clk_set_rate_mul_div,
+	.round_rate	= k230_clk_round_rate_mul_div,
+	.recalc_rate	= k230_clk_get_rate_mul_div,
+};
+
+K230_CLK_GATE_FORMAT(cpu0_src_gate,
+		     K230_CPU0_SRC_GATE,
+		     0, 0, 0, 0,
+		     &pll0_div2.hw);
+
+K230_CLK_RATE_FORMAT(cpu0_src_rate,
+		     K230_CPU0_SRC_RATE,
+		     1, 16, 1, 0xF,
+		     16, 16, 0, 0x0,
+		     0x0, 31, mul, 0x0,
+		     false, 0,
+		     &cpu0_src_gate.clk.hw);
+
+K230_CLK_RATE_FORMAT(cpu0_axi_rate,
+		     K230_CPU0_AXI_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 6, 0x7,
+		     0x0, 31, div, 0x0,
+		     0, 0,
+		     &cpu0_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(cpu0_plic_gate,
+		     K230_CPU0_PLIC_GATE,
+		     0x0, 9, 0, 0,
+		     &cpu0_src_rate.clk.hw);
+
+K230_CLK_RATE_FORMAT(cpu0_plic_rate,
+		     K230_CPU0_PLIC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 10, 0x7,
+		     0x0, 31, div, 0x0,
+		     false, 0,
+		     &cpu0_plic_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(cpu0_noc_ddrcp4_gate,
+		     K230_CPU0_NOC_DDRCP4_GATE,
+		     0x60, 7, 0, 0,
+		     &cpu0_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(cpu0_apb_gate,
+		     K230_CPU0_APB_GATE,
+		     0x0, 13, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(cpu0_apb_rate,
+		     K230_CPU0_APB_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 15, 0x7,
+		     0x0, 31, div, 0x0,
+		     false, 0,
+		     &cpu0_apb_gate.clk.hw);
+
+static const struct clk_parent_data k230_cpu1_src_mux_pdata[] = {
+	{ .hw = &pll0_div2.hw, },
+	{ .hw = &pll3.hw, },
+	{ .hw = &pll0.hw, },
+};
+
+K230_CLK_MUX_FORMAT(cpu1_src_mux,
+		    K230_CPU1_SRC_MUX,
+		    0x4, 1, 0x3,
+		    0, 0,
+		    k230_cpu1_src_mux_pdata);
+
+K230_CLK_GATE_FORMAT(cpu1_src_gate,
+		     K230_CPU1_SRC_GATE,
+		     0x4, 0, CLK_IGNORE_UNUSED, 0,
+		     &cpu1_src_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(cpu1_src_rate,
+		     K230_CPU1_SRC_GATE,
+		     1, 1, 0, 0,
+		     1, 8, 3, 0x7,
+		     0x4, 31, div, 0x0,
+		     false, 0,
+		     &cpu1_src_gate.clk.hw);
+
+K230_CLK_RATE_FORMAT(cpu1_axi_rate,
+		     K230_CPU1_AXI_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 12, 0x7,
+		     0x4, 31, div, 0x0,
+		     false, 0,
+		     &cpu1_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(cpu1_plic_gate,
+		     K230_CPU1_PLIC_GATE,
+		     0x4, 15, CLK_IGNORE_UNUSED, 0,
+		     &cpu1_src_rate.clk.hw);
+
+K230_CLK_RATE_FORMAT(cpu1_plic_rate,
+		     K230_CPU1_PLIC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 16, 0x7,
+		     0x4, 31, div, 0x0,
+		     false, 0,
+		     &cpu1_plic_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(cpu1_apb_gate,
+		     K230_CPU1_APB_GATE,
+		     0x4, 19, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(cpu1_apb_rate,
+		     K230_CPU1_APB_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 15, 0x7,
+		     0x0, 31, div, 0x0,
+		     false, 0,
+		     &cpu1_apb_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT_PNAME(pmu_apb_gate,
+			   K230_PMU_APB_GATE,
+			   0x10, 0, 0, 0,
+			   "osc24m");
+
+K230_CLK_RATE_FORMAT(hs_hclk_high_src_rate,
+		     K230_HS_HCLK_HIGH_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 0, 0x7,
+		     0x1C, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_GATE_FORMAT(hs_hclk_high_gate,
+		     K230_HS_HCLK_HIGH_GATE,
+		     0x18, 1, 0, 0,
+		     &hs_hclk_high_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_hclk_src_gate,
+		     K230_HS_HCLK_SRC_GATE,
+		     0x18, 1, 0, 0,
+		     &hs_hclk_high_src_rate.clk.hw);
+
+K230_CLK_RATE_FORMAT(hs_hclk_src_rate,
+		     K230_HS_HCLK_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 3, 0x7,
+		     0x1C, 31, div, 0x0,
+		     false, 0,
+		     &hs_hclk_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd0_ahb_gate,
+		     K230_HS_SD0_AHB_GATE,
+		     0x18, 2, 0, 0,
+		     &hs_hclk_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd1_ahb_gate,
+		     K230_HS_SD1_AHB_GATE,
+		     0x18, 3, 0, 0,
+		     &hs_hclk_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi1_ahb_gate,
+		     K230_HS_SSI1_AHB_GATE,
+		     0x18, 7, 0, 0,
+		     &hs_hclk_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi2_ahb_gate,
+		     K230_HS_SSI2_AHB_GATE,
+		     0x18, 8, 0, 0,
+		     &hs_hclk_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_usb0_ahb_gate,
+		     K230_HS_USB0_AHB_GATE,
+		     0x18, 4, 0, 0,
+		     &hs_hclk_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_usb1_ahb_gate,
+		     K230_HS_USB1_AHB_GATE,
+		     0x18, 5, 0, 0,
+		     &hs_hclk_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi0_axi_gate,
+		     K230_HS_SSI0_AXI_GATE,
+		     0x18, 27, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(hs_ssi0_axi_rate,
+		     K230_HS_SSI0_AXI_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 9, 0x7,
+		     0x20, 31, div, 0x0,
+		     false, 0,
+		     &hs_ssi0_axi_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi1_gate,
+		     K230_HS_SSI1_GATE,
+		     0x18, 25, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(hs_ssi1_rate,
+		     K230_HS_SSI1_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 3, 0x7,
+		     0x20, 31, div, 0x0,
+		     false, 0,
+		     &hs_ssi1_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi2_gate,
+		     K230_HS_SSI2_GATE,
+		     0x18, 26, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(hs_ssi2_rate,
+		     K230_HS_SSI2_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 6, 0x7,
+		     0x20, 31, div, 0x0,
+		     false, 0,
+		     &hs_ssi2_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_qspi_axi_src_gate,
+		     K230_HS_QSPI_AXI_SRC_GATE,
+		     0x18, 28, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(hs_qspi_axi_src_rate,
+		     K230_HS_QSPI_AXI_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 12, 0x7,
+		     0x20, 31, div, 0x0,
+		     false, 0,
+		     &hs_qspi_axi_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi1_axi_gate,
+		     K230_HS_SSI1_AXI_GATE,
+		     0x18, 29, 0, 0,
+		     &hs_qspi_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_ssi2_axi_gate,
+		     K230_HS_SSI2_AXI_GATE,
+		     0x18, 30, 0, 0,
+		     &hs_qspi_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd_card_src_gate,
+		     K230_HS_SD_CARD_SRC_GATE,
+		     0x18, 11, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(hs_sd_card_src_rate,
+		     K230_HS_SD_CARD_SRC_RATE,
+		     1, 1, 0, 0,
+		     2, 8, 12, 0x7,
+		     0x1C, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd0_card_gate,
+		     K230_HS_SD0_CARD_GATE,
+		     0x18, 15, 0, 0,
+		     &hs_sd_card_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd1_card_gate,
+		     K230_HS_SD1_CARD_GATE,
+		     0x18, 19, 0, 0,
+		     &hs_sd_card_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd_axi_src_gate,
+		     K230_HS_SD_AXI_SRC_GATE,
+		     0x18, 9, 0, 0,
+		     &pll2_div4.hw);
+
+K230_CLK_RATE_FORMAT(hs_sd_axi_src_rate,
+		     K230_HS_SD_AXI_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 6, 0x7,
+		     0x1C, 31, div, 0x0,
+		     false, 0,
+		     &hs_sd_axi_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd0_axi_gate,
+		     K230_HS_SD0_AXI_GATE,
+		     0x18, 13, 0, 0,
+		     &hs_sd_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd1_axi_gate,
+		     K230_HS_SD1_AXI_GATE,
+		     0x18, 17, 0, 0,
+		     &hs_sd_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd0_base_gate,
+		     K230_HS_SD0_BASE_GATE,
+		     0x18, 14, 0, 0,
+		     &hs_sd_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd1_base_gate,
+		     K230_HS_SD1_BASE_GATE,
+		     0x18, 18, 0, 0,
+		     &hs_sd_axi_src_rate.clk.hw);
+
+static const struct clk_parent_data k230_hs_ospi_src_mux_pdata[] = {
+	{ .hw = &pll0_div2.hw, },
+	{ .hw = &pll2_div4.hw, },
+};
+
+K230_CLK_MUX_FORMAT(hs_ospi_src_mux,
+		    K230_HS_OSPI_SRC_MUX,
+		    0x20, 18, 0x1,
+		    0, 0,
+		    k230_hs_ospi_src_mux_pdata);
+
+K230_CLK_GATE_FORMAT(hs_ospi_src_gate,
+		     K230_HS_OSPI_SRC_GATE,
+		     0x18, 24, CLK_IGNORE_UNUSED, 0,
+		     &hs_ospi_src_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(hs_usb_ref_50m_rate,
+		     K230_HS_USB_REF_50M_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 15, 0x7,
+		     0x20, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT_PNAME(hs_sd_timer_src_gate,
+			   K230_HS_SD_TIMER_SRC_GATE,
+			   0x18, 12, 0, 0,
+			   "osc24m");
+
+K230_CLK_RATE_FORMAT(hs_sd_timer_src_rate,
+		     K230_HS_SD_TIMER_SRC_RATE,
+		     1, 1, 0, 0,
+		     24, 32, 15, 0x1F,
+		     0x1C, 31, div, 0x0,
+		     false, 0,
+		     &hs_sd_timer_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd0_timer_gate,
+		     K230_HS_SD0_TIMER_GATE,
+		     0x18, 16, 0, 0,
+		     &hs_sd_timer_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_sd1_timer_gate,
+		     K230_HS_SD1_TIMER_GATE,
+		     0x18, 20, 0, 0,
+		     &hs_sd_timer_src_rate.clk.hw);
+
+static const struct clk_parent_data k230_hs_usb_ref_mux_pdata[] = {
+	{ .fw_name = "osc24m", },
+	{ .hw = &hs_usb_ref_50m_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(hs_usb_ref_mux,
+		    K230_HS_USB_REF_MUX,
+		    0x18, 23, 0x1,
+		    0, 0,
+		    k230_hs_usb_ref_mux_pdata);
+
+K230_CLK_GATE_FORMAT(hs_usb0_ref_gate,
+		     K230_HS_USB0_REF_GATE,
+		     0x18, 21, CLK_IGNORE_UNUSED, 0,
+		     &hs_usb_ref_mux.clk.hw);
+
+K230_CLK_GATE_FORMAT(hs_usb1_ref_gate,
+		     K230_HS_USB1_REF_GATE,
+		     0x18, 22, CLK_IGNORE_UNUSED, 0,
+		     &hs_usb_ref_mux.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_apb_src_gate,
+		     K230_LS_APB_SRC_GATE,
+		     0x24, 0, CLK_IS_CRITICAL, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_apb_src_rate,
+		     K230_LS_APB_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 0, 0x7,
+		     0x30, 31, div, 0x0,
+		     false, 0,
+		     &ls_apb_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart0_apb_gate,
+		     K230_LS_UART0_APB_GATE,
+		     0x24, 1, CLK_IS_CRITICAL, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart1_apb_gate,
+		     K230_LS_UART1_APB_GATE,
+		     0x24, 2, CLK_IS_CRITICAL, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart2_apb_gate,
+		     K230_LS_UART2_APB_GATE,
+		     0x24, 3, CLK_IS_CRITICAL, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart3_apb_gate,
+		     K230_LS_UART3_APB_GATE,
+		     0x24, 4, CLK_IS_CRITICAL, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart4_apb_gate,
+		     K230_LS_UART4_APB_GATE,
+		     0x24, 5, CLK_IS_CRITICAL, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c0_apb_gate,
+		     K230_LS_I2C0_APB_GATE,
+		     0x24, 6, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c1_apb_gate,
+		     K230_LS_I2C1_APB_GATE,
+		     0x24, 7, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c2_apb_gate,
+		     K230_LS_I2C2_APB_GATE,
+		     0x24, 8, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c3_apb_gate,
+		     K230_LS_I2C3_APB_GATE,
+		     0x24, 9, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c4_apb_gate,
+		     K230_LS_I2C4_APB_GATE,
+		     0x24, 10, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_gpio_apb_gate,
+		     K230_LS_GPIO_APB_GATE,
+		     0x24, 11, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_pwm_apb_gate,
+		     K230_LS_PWM_APB_GATE,
+		     0x24, 12, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink0_apb_gate,
+		     K230_LS_JAMLINK0_APB_GATE,
+		     0x28, 4, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink1_apb_gate,
+		     K230_LS_JAMLINK1_APB_GATE,
+		     0x28, 5, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink2_apb_gate,
+		     K230_LS_JAMLINK2_APB_GATE,
+		     0x28, 6, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink3_apb_gate,
+		     K230_LS_JAMLINK3_APB_GATE,
+		     0x28, 7, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_audio_apb_gate,
+		     K230_LS_AUDIO_APB_GATE,
+		     0x24, 13, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_adc_apb_gate,
+		     K230_LS_ADC_APB_GATE,
+		     0x24, 15, 0, 0,
+		     &ls_apb_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_codec_apb_gate,
+		     K230_LS_CODEC_APB_GATE,
+		     0x24, 14, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c0_gate,
+		     K230_LS_I2C0_GATE,
+		     0x24, 21, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_i2c0_rate,
+		     K230_LS_I2C0_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 15, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_i2c0_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c1_gate,
+		     K230_LS_I2C1_GATE,
+		     0x24, 22, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_i2c1_rate,
+		     K230_LS_I2C1_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 18, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_i2c1_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c2_gate,
+		     K230_LS_I2C2_GATE,
+		     0x24, 23, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_i2c2_rate,
+		     K230_LS_I2C2_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 21, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_i2c2_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c3_gate,
+		     K230_LS_I2C3_GATE,
+		     0x24, 24, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_i2c3_rate,
+		     K230_LS_I2C3_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 24, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_i2c3_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_i2c4_gate,
+		     K230_LS_I2C4_GATE,
+		     0x24, 25, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_i2c4_rate,
+		     K230_LS_I2C4_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 27, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_i2c4_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_codec_adc_gate,
+		     K230_LS_CODEC_ADC_GATE,
+		     0x24, 29, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_codec_adc_rate,
+		     K230_LS_CODEC_ADC_RATE,
+		     0x10, 0x1B9, 14, 0x1FFF,
+		     0xC35, 0x3D09, 0, 0x3FFF,
+		     0x38, 31, mul_div, 0x38,
+		     false, 0,
+		     &ls_codec_adc_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_codec_dac_gate,
+		     K230_LS_CODEC_DAC_GATE,
+		     0x24, 30, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_codec_dac_rate,
+		     K230_LS_CODEC_DAC_RATE,
+		     0x10, 0x1B9, 14, 0x1FFF,
+		     0xC35, 0x3D09, 0, 0x3FFF,
+		     0x3C, 31, mul_div, 0x3C,
+		     false, 0,
+		     &ls_codec_dac_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_audio_dev_gate,
+		     K230_LS_AUDIO_DEV_GATE,
+		     0x24, 28, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_audio_dev_rate,
+		     K230_LS_AUDIO_DEV_RATE,
+		     0x4, 0x1B9, 16, 0x7FFF,
+		     0xC35, 0xF424, 0, 0xFFFF,
+		     0x34, 31, mul_div, 0x34,
+		     false, 0,
+		     &ls_audio_dev_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_pdm_gate,
+		     K230_LS_PDM_GATE,
+		     0x24, 31, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_pdm_rate,
+		     K230_LS_PDM_RATE,
+		     0x2, 0x1B9, 0, 0xFFFF,
+		     0xC35, 0x1E848, 0, 0x1FFFF,
+		     0x40, 0, mul_div, 0x44,
+		     false, 0,
+		     &ls_pdm_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_adc_gate,
+		     K230_LS_ADC_GATE,
+		     0x24, 26, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ls_adc_rate,
+		     K230_LS_ADC_RATE,
+		     1, 1, 0, 0,
+		     1, 1024, 3, 0x3FF,
+		     0x30, 31, div, 0x0,
+		     false, 0,
+		     &ls_adc_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart0_gate,
+		     K230_LS_UART0_GATE,
+		     0x24, 16, CLK_IS_CRITICAL, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(ls_uart0_rate,
+		     K230_LS_UART0_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 0, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_uart0_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart1_gate,
+		     K230_LS_UART1_GATE,
+		     0x24, 17, CLK_IS_CRITICAL, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(ls_uart1_rate,
+		     K230_LS_UART1_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 3, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_uart1_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart2_gate,
+		     K230_LS_UART2_GATE,
+		     0x24, 18, CLK_IS_CRITICAL, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(ls_uart2_rate,
+		     K230_LS_UART2_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 6, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_uart2_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart3_gate,
+		     K230_LS_UART3_GATE,
+		     0x24, 19, CLK_IS_CRITICAL, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(ls_uart3_rate,
+		     K230_LS_UART3_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 9, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_uart3_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_uart4_gate,
+		     K230_LS_UART4_GATE,
+		     0x24, 20, CLK_IS_CRITICAL, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(ls_uart4_rate,
+		     K230_LS_UART4_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 12, 0x7,
+		     0x2C, 31, div, 0x0,
+		     false, 0,
+		     &ls_uart4_gate.clk.hw);
+
+K230_CLK_RATE_FORMAT(ls_jamlinkco_src_rate,
+		     K230_LS_JAMLINKCO_SRC_RATE,
+		     1, 1, 0, 0,
+		     2, 512, 23, 0xFF,
+		     0x30, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink0co_gate,
+		     K230_LS_JAMLINK0CO_GATE,
+		     0x28, 0, 0, 0,
+		     &ls_jamlinkco_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink1co_gate,
+		     K230_LS_JAMLINK1CO_GATE,
+		     0x28, 1, 0, 0,
+		     &ls_jamlinkco_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink2co_gate,
+		     K230_LS_JAMLINK2CO_GATE,
+		     0x28, 2, 0, 0,
+		     &ls_jamlinkco_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ls_jamlink3co_gate,
+		     K230_LS_JAMLINK3CO_GATE,
+		     0x28, 3, 0, 0,
+		     &ls_jamlinkco_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT_PNAME(ls_gpio_debounce_gate,
+			   K230_LS_GPIO_DEBOUNCE_GATE,
+			   0x24, 27, 0, 0,
+			   "osc24m");
+
+K230_CLK_RATE_FORMAT(ls_gpio_debounce_rate,
+		     K230_LS_GPIO_DEBOUNCE_RATE,
+		     1, 1, 0, 0,
+		     1, 1024, 13, 0x3FF,
+		     0x30, 31, div, 0x0,
+		     false, 0,
+		     &ls_gpio_debounce_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_wdt0_apb_gate,
+		     K230_SYSCTL_WDT0_APB_GATE,
+		     0x50, 1, 0, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_wdt1_apb_gate,
+		     K230_SYSCTL_WDT1_APB_GATE,
+		     0x50, 2, 0, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_timer_apb_gate,
+		     K230_SYSCTL_TIMER_APB_GATE,
+		     0x50, 3, 0, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_iomux_apb_gate,
+		     K230_SYSCTL_IOMUX_APB_GATE,
+		     0x50, 20, 0, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_mailbox_apb_gate,
+		     K230_SYSCTL_MAILBOX_APB_GATE,
+		     0x50, 4, 0, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_hdi_gate,
+		     K230_SYSCTL_HDI_GATE,
+		     0x50, 21, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(sysctl_hdi_rate,
+		     K230_SYSCTL_HDI_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 28, 0x7,
+		     0x58, 31, div, 0x0,
+		     false, 0,
+		     &sysctl_hdi_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(sysctl_time_stamp_gate,
+		     K230_SYSCTL_TIME_STAMP_GATE,
+		     0x50, 19, CLK_IS_CRITICAL, 0,
+		     &pll1_div4.hw);
+
+K230_CLK_RATE_FORMAT(sysctl_time_stamp_rate,
+		     K230_SYSCTL_TIME_STAMP_RATE,
+		     1, 1, 0, 0,
+		     1, 32, 15, 0x1F,
+		     0x58, 31, div, 0x0,
+		     false, 0,
+		     &sysctl_time_stamp_gate.clk.hw);
+
+K230_CLK_RATE_FORMAT_PNAME(sysctl_temp_sensor_rate,
+			   K230_SYSCTL_TEMP_SENSOR_RATE,
+			   1, 1, 0, 0,
+			   1, 256, 20, 0xFF,
+			   0x58, 31, div, 0x0,
+			   false, 0,
+			   "osc24m");
+
+K230_CLK_GATE_FORMAT_PNAME(sysctl_wdt0_gate,
+			   K230_SYSCTL_WDT0_GATE,
+			   0x50, 5, 0, 0,
+			   "osc24m");
+
+K230_CLK_RATE_FORMAT(sysctl_wdt0_rate,
+		     K230_SYSCTL_WDT0_RATE,
+		     1, 1, 0, 0,
+		     1, 64, 3, 0x3F,
+		     0x58, 31, div, 0x0,
+		     false, 0,
+		     &sysctl_wdt0_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT_PNAME(sysctl_wdt1_gate,
+			   K230_SYSCTL_WDT1_GATE,
+			   0x50, 6, 0, 0,
+			   "osc24m");
+
+K230_CLK_RATE_FORMAT(sysctl_wdt1_rate,
+		     K230_SYSCTL_WDT1_RATE,
+		     1, 1, 0, 0,
+		     1, 64, 9, 0x3F,
+		     0x58, 31, div, 0x0,
+		     false, 0,
+		     &sysctl_wdt1_gate.clk.hw);
+
+K230_CLK_RATE_FORMAT(timer0_src_rate,
+		     K230_TIMER0_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 0, 0x7,
+		     0x54, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(timer1_src_rate,
+		     K230_TIMER1_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 3, 0x7,
+		     0x54, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(timer2_src_rate,
+		     K230_TIMER2_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 6, 0x7,
+		     0x54, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(timer3_src_rate,
+		     K230_TIMER3_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 9, 0x7,
+		     0x54, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(timer4_src_rate,
+		     K230_TIMER4_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 12, 0x7,
+		     0x54, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+K230_CLK_RATE_FORMAT(timer5_src_rate,
+		     K230_TIMER5_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 15, 0x7,
+		     0x54, 31, div, 0x0,
+		     false, 0,
+		     &pll0_div16.hw);
+
+static const struct clk_parent_data k230_timer0_mux_pdata[] = {
+	{ .fw_name = "timer-pulse-in", },
+	{ .hw = &timer0_src_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(timer0_mux,
+		    K230_TIMER0_MUX,
+		    0x50, 7, 0x1,
+		    0, 0,
+		    k230_timer0_mux_pdata);
+
+K230_CLK_GATE_FORMAT(timer0_gate,
+		     K230_TIMER0_GATE,
+		     0x50, 13, CLK_IGNORE_UNUSED, 0,
+		     &timer0_mux.clk.hw);
+
+static const struct clk_parent_data k230_timer1_mux_pdata[] = {
+	{ .fw_name = "timer-pulse-in", },
+	{ .hw = &timer1_src_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(timer1_mux,
+		    K230_TIMER1_MUX,
+		    0x50, 8, 0x1,
+		    0, 0,
+		    k230_timer1_mux_pdata);
+
+K230_CLK_GATE_FORMAT(timer1_gate,
+		     K230_TIMER1_GATE,
+		     0x50, 14, CLK_IGNORE_UNUSED, 0,
+		     &timer1_mux.clk.hw);
+
+static const struct clk_parent_data k230_timer2_mux_pdata[] = {
+	{ .fw_name = "timer-pulse-in", },
+	{ .hw = &timer2_src_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(timer2_mux,
+		    K230_TIMER2_MUX,
+		    0x50, 9, 0x1,
+		    0, 0,
+		    k230_timer2_mux_pdata);
+
+K230_CLK_GATE_FORMAT(timer2_gate,
+		     K230_TIMER2_GATE,
+		     0x50, 15, CLK_IGNORE_UNUSED, 0,
+		     &timer2_mux.clk.hw);
+
+static const struct clk_parent_data k230_timer3_mux_pdata[] = {
+	{ .fw_name = "timer-pulse-in", },
+	{ .hw = &timer3_src_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(timer3_mux,
+		    K230_TIMER3_MUX,
+		    0x50, 10, 0x1,
+		    0, 0,
+		    k230_timer3_mux_pdata);
+
+K230_CLK_GATE_FORMAT(timer3_gate,
+		     K230_TIMER3_GATE,
+		     0x50, 16, CLK_IGNORE_UNUSED, 0,
+		     &timer3_mux.clk.hw);
+
+static const struct clk_parent_data k230_timer4_mux_pdata[] = {
+	{ .fw_name = "timer-pulse-in", },
+	{ .hw = &timer4_src_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(timer4_mux,
+		    K230_TIMER4_MUX,
+		    0x50, 11, 0x1,
+		    0, 0,
+		    k230_timer4_mux_pdata);
+
+K230_CLK_GATE_FORMAT(timer4_gate,
+		     K230_TIMER4_GATE,
+		     0x50, 17, CLK_IGNORE_UNUSED, 0,
+		     &timer4_mux.clk.hw);
+
+static const struct clk_parent_data k230_timer5_mux_pdata[] = {
+	{ .fw_name = "timer-pulse-in", },
+	{ .hw = &timer5_src_rate.clk.hw, },
+};
+
+K230_CLK_MUX_FORMAT(timer5_mux,
+		    K230_TIMER5_MUX,
+		    0x50, 12, 0x1,
+		    0, 0,
+		    k230_timer5_mux_pdata);
+
+K230_CLK_GATE_FORMAT(timer5_gate,
+		     K230_TIMER5_GATE,
+		     0x50, 18, CLK_IGNORE_UNUSED, 0,
+		     &timer5_mux.clk.hw);
+
+K230_CLK_GATE_FORMAT(shrm_apb_gate,
+		     K230_SHRM_APB_GATE,
+		     0x5C, 0, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(shrm_apb_rate,
+		     K230_SHRM_APB_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 18, 0x7,
+		     0x5C, 31, div, 0x0,
+		     false, 0,
+		     &shrm_apb_gate.clk.hw);
+
+static const struct clk_parent_data k230_shrm_sram_mux_pdata[] = {
+	{ .hw = &pll3_div2.hw, },
+	{ .hw = &pll0_div2.hw, },
+};
+
+K230_CLK_MUX_FORMAT(shrm_sram_mux,
+		    K230_SHRM_SRAM_MUX,
+		    0x50, 14, 0x1,
+		    0, 0,
+		    k230_shrm_sram_mux_pdata);
+
+K230_CLK_GATE_FORMAT(shrm_sram_gate,
+		     K230_SHRM_SRAM_GATE,
+		     0x5c, 10, CLK_IGNORE_UNUSED, 0,
+		     &shrm_sram_mux.clk.hw);
+
+K230_CLK_FIXED_FACTOR_FORMAT(shrm_sram_div2,
+			     1, 2, 0,
+			     &shrm_sram_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(shrm_axi_slave_gate,
+		     K230_SHRM_AXI_SLAVE_GATE,
+		     0x5C, 11, CLK_IGNORE_UNUSED, 0,
+		     &shrm_sram_div2.hw);
+
+K230_CLK_GATE_FORMAT(shrm_axi_gate,
+		     K230_SHRM_AXI_GATE,
+		     0x5C, 12, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_GATE_FORMAT(shrm_nonai2d_axi_gate,
+		     K230_SHRM_NONAI2D_AXI_GATE,
+		     0x5C, 9, 0, 0,
+		     &shrm_axi_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(shrm_decompress_axi_gate,
+		     K230_SHRM_DECOMPRESS_AXI_GATE,
+		     0x5C, 7, CLK_IGNORE_UNUSED, 0,
+		     &shrm_sram_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(shrm_sdma_axi_gate,
+		     K230_SHRM_SDMA_AXI_GATE,
+		     0x5C, 5, 0, 0,
+		     &shrm_axi_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(shrm_pdma_axi_gate,
+		     K230_SHRM_PDMA_AXI_GATE,
+		     0x5C, 3, 0, 0,
+		     &shrm_axi_gate.clk.hw);
+
+static const struct clk_parent_data k230_ddrc_src_mux_pdata[] = {
+	{ .hw = &pll0_div2.hw, },
+	{ .hw = &pll0_div3.hw, },
+	{ .hw = &pll2_div4.hw, },
+};
+
+K230_CLK_MUX_FORMAT(ddrc_src_mux,
+		    K230_DDRC_SRC_MUX,
+		    0x60, 0, 0x3,
+		    0, 0,
+		    k230_ddrc_src_mux_pdata);
+
+K230_CLK_GATE_FORMAT(ddrc_src_gate,
+		     K230_DDRC_SRC_GATE,
+		     0x60, 2, CLK_IGNORE_UNUSED, 0,
+		     &ddrc_src_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(ddrc_src_rate,
+		     K230_DDRC_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 10, 0xF,
+		     0x60, 31, div, 0x0,
+		     false, 0,
+		     &ddrc_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ddrc_bypass_gate,
+		     K230_DDRC_BYPASS_GATE,
+		     0x60, 8, 0, 0,
+		     &pll2_div4.hw);
+
+K230_CLK_GATE_FORMAT(ddrc_apb_gate,
+		     K230_DDRC_APB_GATE,
+		     0x60, 9, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(ddrc_apb_rate,
+		     K230_DDRC_APB_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 14, 0xF,
+		     0x60, 31, div, 0x0,
+		     false, 0,
+		     &ddrc_apb_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(display_ahb_gate,
+		     K230_DISPLAY_AHB_GATE,
+		     0x74, 0, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(display_ahb_rate,
+		     K230_DISPLAY_AHB_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 0, 0x7,
+		     0x78, 31, div, 0x0,
+		     false, 0,
+		     &display_ahb_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(display_axi_gate,
+		     K230_DISPLAY_AXI_GATE,
+		     0x74, 1, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(display_clkext_rate,
+		     K230_DISPLAY_CLKEXT_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 16, 0xF,
+		     0x78, 31, div, 0x0,
+		     false, 0,
+		     &display_axi_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(display_gpu_gate,
+		     K230_DISPLAY_GPU_GATE,
+		     0x74, 6, 0, 0,
+		     &pll0_div3.hw);
+
+K230_CLK_RATE_FORMAT(display_gpu_rate,
+		     K230_DISPLAY_GPU_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 20, 0xF,
+		     0x78, 31, div, 0x0,
+		     false, 0,
+		     &display_gpu_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(display_dpip_gate,
+		     K230_DISPLAY_DPIP_GATE,
+		     0x74, 2, 0, 0,
+		     &pll1_div4.hw);
+
+K230_CLK_RATE_FORMAT(display_dpip_rate,
+		     K230_DISPLAY_DPIP_RATE,
+		     1, 1, 0, 0,
+		     1, 256, 3, 0xFF,
+		     0x78, 31, div, 0x0,
+		     false, 0,
+		     &display_dpip_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(display_cfg_gate,
+		     K230_DISPLAY_CFG_GATE,
+		     0x74, 4, 0, 0,
+		     &pll1_div4.hw);
+
+K230_CLK_RATE_FORMAT(display_cfg_rate,
+		     K230_DISPLAY_CFG_RATE,
+		     1, 1, 0, 0,
+		     1, 32, 11, 0x1F,
+		     0x78, 31, div, 0x0,
+		     false, 0,
+		     &display_cfg_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT_PNAME(display_ref_gate,
+			   K230_DISPLAY_REF_GATE,
+			   0x74, 3, 0, 0,
+			   "osc24m");
+
+K230_CLK_GATE_FORMAT(vpu_src_gate,
+		     K230_VPU_SRC_GATE,
+		     0xC, 0, 0, 0,
+		     &pll0_div2.hw);
+
+K230_CLK_RATE_FORMAT(vpu_src_rate,
+		     K230_VPU_SRC_RATE,
+		     1, 16, 1, 0xF,
+		     16, 16, 0, 0,
+		     0x0, 31, mul, 0xC,
+		     false, 0,
+		     &vpu_src_gate.clk.hw);
+
+K230_CLK_RATE_FORMAT(vpu_axi_src_rate,
+		     K230_VPU_AXI_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 6, 0xF,
+		     0xC, 31, div, 0x0,
+		     false, 0,
+		     &vpu_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(vpu_axi_gate,
+		     K230_VPU_AXI_GATE,
+		     0xC, 5, 0, 0,
+		     &vpu_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(vpu_ddrcp2_gate,
+		     K230_VPU_DDRCP2_GATE,
+		     0x60, 5, 0, 0,
+		     &vpu_axi_src_rate.clk.hw);
+
+K230_CLK_GATE_FORMAT(vpu_cfg_gate,
+		     K230_VPU_CFG_GATE,
+		     0xC, 10, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(vpu_cfg_rate,
+		     K230_VPU_CFG_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 11, 0xF,
+		     0xC, 31, div, 0x0,
+		     false, 0,
+		     &vpu_cfg_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(sec_apb_gate,
+		     K230_SEC_APB_GATE,
+		     0x80, 0, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(sec_apb_rate,
+		     K230_SEC_APB_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 1, 0x7,
+		     0x80, 31, div, 0x0,
+		     false, 0,
+		     &sec_apb_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(sec_fix_gate,
+		     K230_SEC_FIX_GATE,
+		     0x80, 5, 0, 0,
+		     &pll1_div4.hw);
+
+K230_CLK_RATE_FORMAT(sec_fix_rate,
+		     K230_SEC_FIX_RATE,
+		     1, 1, 0, 0,
+		     1, 32, 6, 0x1F,
+		     0x80, 31, div, 0x0,
+		     false, 0,
+		     &sec_fix_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(sec_axi_gate,
+		     K230_SEC_AXI_GATE,
+		     0x80, 4, 0, 0,
+		     &pll1_div4.hw);
+
+K230_CLK_RATE_FORMAT(sec_axi_rate,
+		     K230_SEC_AXI_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 11, 0x3,
+		     0x80, 31, div, 0,
+		     false, 0,
+		     &sec_axi_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(usb_480m_gate,
+		     K230_USB_480M_GATE,
+		     0x100, 0, 0, 0,
+		     &pll1.hw);
+
+K230_CLK_RATE_FORMAT(usb_480m_rate,
+		     K230_USB_480M_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 1, 0x7,
+		     0x100, 31, div, 0,
+		     false, 0,
+		     &usb_480m_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(usb_100m_gate,
+		     K230_USB_100M_GATE,
+		     0x100, 0, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(usb_100m_rate,
+		     K230_USB_100M_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 4, 0x7,
+		     0x100, 31, div, 0,
+		     false, 0,
+		     &usb_100m_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(dphy_dft_gate,
+		     K230_DPHY_DFT_GATE,
+		     0x100, 0, 0, 0,
+		     &pll0.hw);
+
+K230_CLK_RATE_FORMAT(dphy_dft_rate,
+		     K230_DPHY_DFT_RATE,
+		     1, 1, 0, 0,
+		     1, 16, 1, 0xF,
+		     0x104, 31, div, 0,
+		     false, 0,
+		     &dphy_dft_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(spi2axi_gate,
+		     K230_SPI2AXI_GATE,
+		     0x108, 0, 0, 0,
+		     &pll0_div4.hw);
+
+K230_CLK_RATE_FORMAT(spi2axi_rate,
+		     K230_SPI2AXI_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 1, 0x7,
+		     0x108, 31, div, 0x0,
+		     false, 0,
+		     &spi2axi_gate.clk.hw);
+
+static const struct clk_parent_data k230_ai_src_mux_pdata[] = {
+	{ .hw = &pll0_div2.hw, },
+	{ .hw = &pll3_div2.hw, },
+};
+
+K230_CLK_MUX_FORMAT(ai_src_mux,
+		    K230_AI_SRC_MUX,
+		    0x8, 2, 0x1,
+		    0, 0,
+		    k230_ai_src_mux_pdata);
+
+K230_CLK_GATE_FORMAT(ai_src_gate,
+		     K230_AI_SRC_GATE,
+		     0x8, 0, CLK_IGNORE_UNUSED, 0,
+		     &ai_src_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(ai_src_rate,
+		     K230_AI_SRC_RATE,
+		     1, 1, 0, 0,
+		     1, 8, 3, 0x7,
+		     0x8, 31, div, 0x0,
+		     false, 0,
+		     &ai_src_gate.clk.hw);
+
+K230_CLK_GATE_FORMAT(ai_axi_gate,
+		     K230_AI_AXI_GATE,
+		     0x8, 10, 0, 0,
+		     &ai_src_rate.clk.hw);
+
+static const struct clk_parent_data k230_camera0_mux_pdata[] = {
+	{ .hw = &pll1_div3.hw, },
+	{ .hw = &pll1_div4.hw, },
+	{ .hw = &pll0_div4.hw, },
+};
+
+K230_CLK_MUX_FORMAT(camera0_mux,
+		    K230_CAMERA0_MUX,
+		    0x6C, 3, 0x3,
+		    0, 0,
+		    k230_camera0_mux_pdata);
+
+K230_CLK_GATE_FORMAT(camera0_gate,
+		     K230_CAMERA0_GATE,
+		     0x6C, 0, CLK_IGNORE_UNUSED, 0,
+		     &camera0_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(camera0_rate,
+		     K230_CAMERA0_RATE,
+		     1, 1, 0, 0,
+		     1, 32, 5, 0x1f,
+		     0x6C, 31, div, 0x0,
+		     false, 0,
+		     &camera0_gate.clk.hw);
+
+static const struct clk_parent_data k230_camera1_mux_pdata[] = {
+	{ .hw = &pll1_div3.hw, },
+	{ .hw = &pll1_div4.hw, },
+	{ .hw = &pll0_div4.hw, },
+};
+
+K230_CLK_MUX_FORMAT(camera1_mux,
+		    K230_CAMERA1_MUX,
+		    0x6C, 10, 0x3,
+		    0, 0,
+		    k230_camera1_mux_pdata);
+
+K230_CLK_GATE_FORMAT(camera1_gate,
+		     K230_CAMERA1_GATE,
+		     0x6C, 1, CLK_IGNORE_UNUSED, 0,
+		     &camera1_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(camera1_rate,
+		     K230_CAMERA1_RATE,
+		     1, 1, 0, 0,
+		     1, 32, 12, 0x1f,
+		     0x6C, 31, div, 0x0,
+		     false, 0,
+		     &camera1_gate.clk.hw);
+
+static const struct clk_parent_data k230_camera2_mux_pdata[] = {
+	{ .hw = &pll1_div3.hw, },
+	{ .hw = &pll1_div4.hw, },
+	{ .hw = &pll0_div4.hw, },
+};
+
+K230_CLK_MUX_FORMAT(camera2_mux,
+		    K230_CAMERA2_MUX,
+		    0x6C, 17, 0x3,
+		    0, 0,
+		    k230_camera2_mux_pdata);
+
+K230_CLK_GATE_FORMAT(camera2_gate,
+		     K230_CAMERA2_GATE,
+		     0x6C, 2, CLK_IGNORE_UNUSED, 0,
+		     &camera2_mux.clk.hw);
+
+K230_CLK_RATE_FORMAT(camera2_rate,
+		     K230_CAMERA2_RATE,
+		     1, 1, 0, 0,
+		     1, 32, 19, 0x1f,
+		     0x6C, 31, div, 0x0,
+		     false, 0,
+		     &camera2_gate.clk.hw);
+
+static struct k230_clk_mux *k230_clk_muxs[] = {
+	&hs_ospi_src_mux,
+	&hs_usb_ref_mux,
+	&cpu1_src_mux,
+	&timer0_mux,
+	&timer1_mux,
+	&timer2_mux,
+	&timer3_mux,
+	&timer4_mux,
+	&timer5_mux,
+	&shrm_sram_mux,
+	&ddrc_src_mux,
+	&ai_src_mux,
+	&camera0_mux,
+	&camera1_mux,
+	&camera2_mux,
+};
+
+#define K230_CLK_MUX_NUM ARRAY_SIZE(k230_clk_muxs)
+
+static struct k230_clk_gate *k230_clk_gates[] = {
+	&cpu0_src_gate,
+	&cpu0_plic_gate,
+	&cpu0_noc_ddrcp4_gate,
+	&cpu0_apb_gate,
+	&cpu1_src_gate,
+	&cpu1_plic_gate,
+	&cpu1_apb_gate,
+	&pmu_apb_gate,
+	&hs_hclk_high_gate,
+	&hs_hclk_src_gate,
+	&hs_sd0_ahb_gate,
+	&hs_sd1_ahb_gate,
+	&hs_ssi1_ahb_gate,
+	&hs_ssi2_ahb_gate,
+	&hs_usb0_ahb_gate,
+	&hs_usb1_ahb_gate,
+	&hs_ssi0_axi_gate,
+	&hs_ssi1_gate,
+	&hs_ssi2_gate,
+	&hs_qspi_axi_src_gate,
+	&hs_ssi1_axi_gate,
+	&hs_ssi2_axi_gate,
+	&hs_sd_card_src_gate,
+	&hs_sd0_card_gate,
+	&hs_sd1_card_gate,
+	&hs_sd_axi_src_gate,
+	&hs_sd0_axi_gate,
+	&hs_sd1_axi_gate,
+	&hs_sd0_base_gate,
+	&hs_sd1_base_gate,
+	&hs_ospi_src_gate,
+	&hs_sd_timer_src_gate,
+	&hs_sd0_timer_gate,
+	&hs_sd1_timer_gate,
+	&hs_usb0_ref_gate,
+	&hs_usb1_ref_gate,
+	&ls_apb_src_gate,
+	&ls_uart0_apb_gate,
+	&ls_uart1_apb_gate,
+	&ls_uart2_apb_gate,
+	&ls_uart3_apb_gate,
+	&ls_uart4_apb_gate,
+	&ls_i2c0_apb_gate,
+	&ls_i2c1_apb_gate,
+	&ls_i2c2_apb_gate,
+	&ls_i2c3_apb_gate,
+	&ls_i2c4_apb_gate,
+	&ls_gpio_apb_gate,
+	&ls_pwm_apb_gate,
+	&ls_jamlink0_apb_gate,
+	&ls_jamlink1_apb_gate,
+	&ls_jamlink2_apb_gate,
+	&ls_jamlink3_apb_gate,
+	&ls_audio_apb_gate,
+	&ls_adc_apb_gate,
+	&ls_codec_apb_gate,
+	&ls_i2c0_gate,
+	&ls_i2c1_gate,
+	&ls_i2c2_gate,
+	&ls_i2c3_gate,
+	&ls_i2c4_gate,
+	&ls_codec_adc_gate,
+	&ls_codec_dac_gate,
+	&ls_audio_dev_gate,
+	&ls_pdm_gate,
+	&ls_adc_gate,
+	&ls_uart0_gate,
+	&ls_uart1_gate,
+	&ls_uart2_gate,
+	&ls_uart3_gate,
+	&ls_uart4_gate,
+	&ls_jamlink0co_gate,
+	&ls_jamlink1co_gate,
+	&ls_jamlink2co_gate,
+	&ls_jamlink3co_gate,
+	&ls_gpio_debounce_gate,
+	&sysctl_wdt0_apb_gate,
+	&sysctl_wdt1_apb_gate,
+	&sysctl_timer_apb_gate,
+	&sysctl_iomux_apb_gate,
+	&sysctl_mailbox_apb_gate,
+	&sysctl_hdi_gate,
+	&sysctl_time_stamp_gate,
+	&sysctl_wdt0_gate,
+	&sysctl_wdt1_gate,
+	&timer0_gate,
+	&timer1_gate,
+	&timer2_gate,
+	&timer3_gate,
+	&timer4_gate,
+	&timer5_gate,
+	&shrm_apb_gate,
+	&shrm_sram_gate,
+	&shrm_axi_gate,
+	&shrm_axi_slave_gate,
+	&shrm_nonai2d_axi_gate,
+	&shrm_decompress_axi_gate,
+	&shrm_sdma_axi_gate,
+	&shrm_pdma_axi_gate,
+	&ddrc_src_gate,
+	&ddrc_bypass_gate,
+	&ddrc_apb_gate,
+	&display_ahb_gate,
+	&display_axi_gate,
+	&display_gpu_gate,
+	&display_dpip_gate,
+	&display_cfg_gate,
+	&display_ref_gate,
+	&vpu_src_gate,
+	&vpu_axi_gate,
+	&vpu_ddrcp2_gate,
+	&vpu_cfg_gate,
+	&sec_apb_gate,
+	&sec_fix_gate,
+	&sec_axi_gate,
+	&usb_480m_gate,
+	&usb_100m_gate,
+	&dphy_dft_gate,
+	&spi2axi_gate,
+	&ai_src_gate,
+	&ai_axi_gate,
+	&camera0_gate,
+	&camera1_gate,
+	&camera2_gate,
+};
+
+#define K230_CLK_GATE_NUM ARRAY_SIZE(k230_clk_gates)
+
+static struct k230_clk_rate *k230_clk_rates[] = {
+	&cpu0_src_rate,
+	&cpu0_axi_rate,
+	&cpu0_plic_rate,
+	&cpu0_apb_rate,
+	&cpu1_src_rate,
+	&cpu1_axi_rate,
+	&cpu1_plic_rate,
+	&cpu1_apb_rate,
+	&hs_hclk_high_src_rate,
+	&hs_hclk_src_rate,
+	&hs_ssi0_axi_rate,
+	&hs_ssi1_rate,
+	&hs_ssi2_rate,
+	&hs_qspi_axi_src_rate,
+	&hs_sd_card_src_rate,
+	&hs_sd_axi_src_rate,
+	&hs_usb_ref_50m_rate,
+	&hs_sd_timer_src_rate,
+	&ls_apb_src_rate,
+	&ls_gpio_debounce_rate,
+	&ls_i2c0_rate,
+	&ls_i2c1_rate,
+	&ls_i2c2_rate,
+	&ls_i2c3_rate,
+	&ls_i2c4_rate,
+	&ls_codec_adc_rate,
+	&ls_codec_dac_rate,
+	&ls_audio_dev_rate,
+	&ls_pdm_rate,
+	&ls_adc_rate,
+	&ls_uart0_rate,
+	&ls_uart1_rate,
+	&ls_uart2_rate,
+	&ls_uart3_rate,
+	&ls_uart4_rate,
+	&ls_jamlinkco_src_rate,
+	&sysctl_hdi_rate,
+	&sysctl_time_stamp_rate,
+	&sysctl_temp_sensor_rate,
+	&sysctl_wdt0_rate,
+	&sysctl_wdt1_rate,
+	&timer0_src_rate,
+	&timer1_src_rate,
+	&timer2_src_rate,
+	&timer3_src_rate,
+	&timer4_src_rate,
+	&timer5_src_rate,
+	&shrm_apb_rate,
+	&ddrc_src_rate,
+	&ddrc_apb_rate,
+	&display_ahb_rate,
+	&display_clkext_rate,
+	&display_gpu_rate,
+	&display_dpip_rate,
+	&display_cfg_rate,
+	&vpu_src_rate,
+	&vpu_axi_src_rate,
+	&vpu_cfg_rate,
+	&sec_apb_rate,
+	&sec_fix_rate,
+	&sec_axi_rate,
+	&usb_480m_rate,
+	&usb_100m_rate,
+	&dphy_dft_rate,
+	&spi2axi_rate,
+	&ai_src_rate,
+	&camera0_rate,
+	&camera1_rate,
+	&camera2_rate,
+};
+
+#define K230_CLK_RATE_NUM ARRAY_SIZE(k230_clk_rates)
+
+#define K230_CLK_NUM (K230_CLK_MUX_NUM + K230_CLK_GATE_NUM + K230_CLK_RATE_NUM + 1)
+
+static int k230_pll_prepare(struct clk_hw *hw)
+{
+	struct k230_pll *pll = hw_to_k230_pll(hw);
+	u32 reg;
+
+	/* wait for PLL lock until it reaches lock status */
+	return readl_poll_timeout(K230_PLLX_LOCK_ADDR(pll->reg, pll->id), reg,
+				  reg & K230_PLL_LOCK_STATUS_MASK,
+				  K230_PLL_LOCK_TIME_DELAY, K230_PLL_LOCK_TIMEOUT);
+}
+
+static inline bool k230_pll_hw_is_enabled(struct k230_pll *pll)
+{
+	return readl(K230_PLLX_GATE_ADDR(pll->reg, pll->id)) & K230_PLL_GATE_ENABLE;
+}
+
+static void k230_pll_enable_hw(struct k230_pll *pll)
+{
+	u32 reg;
+
+	if (k230_pll_hw_is_enabled(pll))
+		return;
+
+	reg = readl(K230_PLLX_GATE_ADDR(pll->reg, pll->id));
+	reg |= K230_PLL_GATE_ENABLE | K230_PLL_GATE_WRITE_ENABLE;
+	writel(reg, K230_PLLX_GATE_ADDR(pll->reg, pll->id));
+}
+
+static int k230_pll_enable(struct clk_hw *hw)
+{
+	struct k230_pll *pll = hw_to_k230_pll(hw);
+
+	guard(spinlock)(pll->lock);
+
+	k230_pll_enable_hw(pll);
+
+	return 0;
+}
+
+static void k230_pll_disable(struct clk_hw *hw)
+{
+	struct k230_pll *pll = hw_to_k230_pll(hw);
+	u32 reg;
+
+	guard(spinlock)(pll->lock);
+
+	reg = readl(K230_PLLX_GATE_ADDR(pll->reg, pll->id));
+	reg &= ~(K230_PLL_GATE_ENABLE);
+	reg |= (K230_PLL_GATE_WRITE_ENABLE);
+	writel(reg, K230_PLLX_GATE_ADDR(pll->reg, pll->id));
+}
+
+static int k230_pll_is_enabled(struct clk_hw *hw)
+{
+	return k230_pll_hw_is_enabled(hw_to_k230_pll(hw));
+}
+
+static unsigned long k230_pll_get_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct k230_pll *pll = hw_to_k230_pll(hw);
+	u32 reg;
+	u32 r, f, od;
+
+	guard(spinlock)(pll->lock);
+
+	reg = readl(K230_PLLX_BYPASS_ADDR(pll->reg, pll->id));
+	if (reg & K230_PLL_BYPASS_ENABLE)
+		return parent_rate;
+
+	reg = readl(K230_PLLX_LOCK_ADDR(pll->reg, pll->id));
+	if (!(reg & (K230_PLL_LOCK_STATUS_MASK)))
+		return 0;
+
+	reg = readl(K230_PLLX_DIV_ADDR(pll->reg, pll->id));
+	r = ((reg >> K230_PLL_R_SHIFT) & K230_PLL_R_MASK) + 1;
+	f = ((reg >> K230_PLL_F_SHIFT) & K230_PLL_F_MASK) + 1;
+	od = ((reg >> K230_PLL_OD_SHIFT) & K230_PLL_OD_MASK) + 1;
+
+	return mul_u64_u32_div(parent_rate, f, r * od);
+}
+
+static int k230_register_plls(struct platform_device *pdev, spinlock_t *lock,
+			      void __iomem *reg)
+{
+	int i, ret;
+	struct k230_pll *pll;
+
+	for (i = 0; i < ARRAY_SIZE(k230_plls); i++) {
+		const char *name;
+
+		pll = k230_plls[i];
+
+		name = pll->hw.init->name;
+		pll->lock = lock;
+		pll->reg = reg;
+
+		ret = devm_clk_hw_register(&pdev->dev, &pll->hw);
+		if (ret)
+			return ret;
+
+		ret = devm_clk_hw_register_clkdev(&pdev->dev, &pll->hw, name, NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int k230_register_pll_divs(struct platform_device *pdev)
+{
+	struct clk_fixed_factor *pll_div;
+	int ret;
+
+	for (int i = 0; i < ARRAY_SIZE(k230_pll_divs); i++) {
+		const char *name;
+
+		pll_div = k230_pll_divs[i];
+
+		name = pll_div->hw.init->name;
+
+		ret = devm_clk_hw_register(&pdev->dev, &pll_div->hw);
+		if (ret)
+			return ret;
+
+		ret = devm_clk_hw_register_clkdev(&pdev->dev, &pll_div->hw,
+						  name, NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static unsigned long k230_clk_get_rate_mul(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
+	struct k230_clk_rate_self *rate_self = &clk->clk;
+	u32 mul, div;
+
+	guard(spinlock)(rate_self->lock);
+
+	div = rate_self->div_max;
+	mul = (readl(rate_self->reg + clk->mul_reg_off) >> rate_self->mul_shift)
+	      & rate_self->mul_mask;
+
+	return mul_u64_u32_div(parent_rate, mul + 1, div);
+}
+
+static unsigned long k230_clk_get_rate_div(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
+	struct k230_clk_rate_self *rate_self = &clk->clk;
+	u32 mul, div;
+
+	guard(spinlock)(rate_self->lock);
+
+	mul = rate_self->mul_max;
+	div = (readl(rate_self->reg + clk->div_reg_off) >> rate_self->div_shift)
+	      & rate_self->div_mask;
+
+	return mul_u64_u32_div(parent_rate, mul, div + 1);
+}
+
+static unsigned long k230_clk_get_rate_mul_div(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
+	struct k230_clk_rate_self *rate_self = &clk->clk;
+	u32 mul, div;
+
+	guard(spinlock)(rate_self->lock);
+
+	div = (readl(rate_self->reg + clk->div_reg_off) >> rate_self->div_shift)
+	      & rate_self->div_mask;
+	mul = (readl(rate_self->reg + clk->mul_reg_off) >> rate_self->mul_shift)
+	      & rate_self->mul_mask;
+
+	return mul_u64_u32_div(parent_rate, mul, div);
+}
+
+static int k230_clk_find_approximate_mul(u32 mul_min, u32 mul_max,
+					 u32 div_min, u32 div_max,
+					 unsigned long rate, unsigned long parent_rate,
+					 u32 *div, u32 *mul)
+{
+	long abs_min;
+	long abs_current;
+	long perfect_divide;
+
+	if (!rate || !parent_rate || !mul_min)
+		return -EINVAL;
+
+	perfect_divide = (long)((parent_rate * 1000) / rate);
+	abs_min = abs(perfect_divide -
+		     (long)(((long)div_max * 1000) / (long)mul_min));
+	*mul = mul_min;
+
+	for (u32 i = mul_min + 1; i <= mul_max; i++) {
+		abs_current = abs(perfect_divide -
+				(long)(((long)div_max * 1000) / (long)i));
+
+		if (abs_min > abs_current) {
+			abs_min = abs_current;
+			*mul = i;
+		}
+	}
+
+	*div = div_max;
+
+	return 0;
+}
+
+static int k230_clk_find_approximate_div(u32 mul_min, u32 mul_max,
+					 u32 div_min, u32 div_max,
+					 unsigned long rate, unsigned long parent_rate,
+					 u32 *div, u32 *mul)
+{
+	long abs_min;
+	long abs_current;
+	long perfect_divide;
+
+	if (!rate || !parent_rate || !mul_max)
+		return -EINVAL;
+
+	perfect_divide = (long)((parent_rate * 1000) / rate);
+	abs_min = abs(perfect_divide -
+		     (long)(((long)div_min * 1000) / (long)mul_max));
+	*div = div_min;
+
+	for (u32 i = div_min + 1; i <= div_max; i++) {
+		abs_current = abs(perfect_divide -
+				 (long)(((long)i * 1000) / (long)mul_max));
+
+		if (abs_min > abs_current) {
+			abs_min = abs_current;
+			*div = i;
+		}
+	}
+
+	*mul = mul_max;
+
+	return 0;
+}
+
+static int k230_clk_find_approximate_mul_div(u32 mul_min, u32 mul_max,
+					     u32 div_min, u32 div_max,
+					     unsigned long rate,
+					     unsigned long parent_rate,
+					     u32 *div, u32 *mul)
+{
+	long abs_min;
+	long abs_current;
+	long perfect_divide;
+
+	if (!rate || !parent_rate || !mul_min)
+		return -EINVAL;
+
+	perfect_divide = (long)((parent_rate * 1000) / rate);
+	abs_min = abs(perfect_divide -
+		     (long)(((long)div_max * 1000) / (long)mul_min));
+
+	*div = div_max;
+	*mul = mul_min;
+
+	for (u32 i = div_max - 1; i >= div_min; i--) {
+		for (u32 j = mul_min + 1; j <= mul_max; j++) {
+			abs_current = abs(perfect_divide -
+					 (long)(((long)i * 1000) / (long)j));
+
+			if (abs_min > abs_current) {
+				abs_min = abs_current;
+				*div = i;
+				*mul = j;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static long k230_clk_round_rate_mul(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate)
+{
+	struct k230_clk_rate_self *rate_self = hw_to_k230_clk_rate_self(hw);
+	u32 div, mul;
+
+	if (k230_clk_find_approximate_mul(rate_self->mul_min, rate_self->mul_max,
+					  rate_self->div_min, rate_self->div_max,
+					  rate, *parent_rate, &div, &mul))
+		return 0;
+
+	return mul_u64_u32_div(*parent_rate, mul, div);
+}
+
+static long k230_clk_round_rate_div(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate)
+{
+	struct k230_clk_rate_self *rate_self = hw_to_k230_clk_rate_self(hw);
+	u32 div, mul;
+
+	if (k230_clk_find_approximate_div(rate_self->mul_min, rate_self->mul_max,
+					  rate_self->div_min, rate_self->div_max,
+					  rate, *parent_rate, &div, &mul))
+		return 0;
+
+	return mul_u64_u32_div(*parent_rate, mul, div);
+}
+
+static long k230_clk_round_rate_mul_div(struct clk_hw *hw, unsigned long rate,
+					unsigned long *parent_rate)
+{
+	struct k230_clk_rate_self *rate_self = hw_to_k230_clk_rate_self(hw);
+	u32 div, mul;
+
+	if (k230_clk_find_approximate_mul_div(rate_self->mul_min, rate_self->mul_max,
+					      rate_self->div_min, rate_self->div_max,
+					      rate, *parent_rate, &div, &mul))
+		return 0;
+
+	return mul_u64_u32_div(*parent_rate, mul, div);
+}
+
+static int k230_clk_set_rate_mul(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
+	struct k230_clk_rate_self *rate_self = &clk->clk;
+	u32 div, mul, mul_reg;
+
+	if (rate > parent_rate)
+		return -EINVAL;
+
+	if (rate_self->read_only)
+		return 0;
+
+	if (k230_clk_find_approximate_mul(rate_self->mul_min, rate_self->mul_max,
+					  rate_self->div_min, rate_self->div_max,
+					  rate, parent_rate, &div, &mul))
+		return -EINVAL;
+
+	guard(spinlock)(rate_self->lock);
+
+	mul_reg = readl(rate_self->reg + clk->mul_reg_off);
+	mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
+	mul_reg |= BIT(rate_self->write_enable_bit);
+	writel(mul_reg, rate_self->reg + clk->mul_reg_off);
+
+	return 0;
+}
+
+static int k230_clk_set_rate_div(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
+	struct k230_clk_rate_self *rate_self = &clk->clk;
+	u32 div, mul, div_reg;
+
+	if (rate > parent_rate)
+		return -EINVAL;
+
+	if (rate_self->read_only)
+		return 0;
+
+	if (k230_clk_find_approximate_div(rate_self->mul_min, rate_self->mul_max,
+					  rate_self->div_min, rate_self->div_max,
+					  rate, parent_rate, &div, &mul))
+		return -EINVAL;
+
+	guard(spinlock)(rate_self->lock);
+
+	div_reg = readl(rate_self->reg + clk->div_reg_off);
+	div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
+	div_reg |= BIT(rate_self->write_enable_bit);
+	writel(div_reg, rate_self->reg + clk->div_reg_off);
+
+	return 0;
+}
+
+static int k230_clk_set_rate_mul_div(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
+	struct k230_clk_rate_self *rate_self = &clk->clk;
+	u32 div, mul, div_reg, mul_reg;
+
+	if (rate > parent_rate)
+		return -EINVAL;
+
+	if (rate_self->read_only)
+		return 0;
+
+	if (k230_clk_find_approximate_mul_div(rate_self->mul_min, rate_self->mul_max,
+					      rate_self->div_min, rate_self->div_max,
+					      rate, parent_rate, &div, &mul))
+		return -EINVAL;
+
+	guard(spinlock)(rate_self->lock);
+
+	div_reg = readl(rate_self->reg + clk->div_reg_off);
+	div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
+	div_reg |= BIT(rate_self->write_enable_bit);
+	writel(div_reg, rate_self->reg + clk->div_reg_off);
+
+	mul_reg = readl(rate_self->reg + clk->mul_reg_off);
+	mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
+	mul_reg |= BIT(rate_self->write_enable_bit);
+	writel(mul_reg, rate_self->reg + clk->mul_reg_off);
+
+	return 0;
+}
+
+static int k230_register_clk(int id, struct clk_hw *hw, struct device *dev,
+			     struct clk_hw_onecell_data *hw_data)
+{
+	int ret;
+
+	ret = devm_clk_hw_register(dev, hw);
+	if (ret)
+		return ret;
+
+	hw_data->hws[id] = hw;
+
+	return 0;
+}
+
+static int k230_register_clks(struct platform_device *pdev,
+			      struct clk_hw_onecell_data *hw_data,
+			      spinlock_t *lock, void __iomem *reg)
+{
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct clk_fixed_factor *fixed_factor = &shrm_sram_div2;
+	struct k230_clk_mux *mux;
+	struct k230_clk_gate *gate;
+	struct k230_clk_rate *rate;
+
+	for (i = 0; i < K230_CLK_MUX_NUM; i++) {
+		mux = k230_clk_muxs[i];
+		mux->clk.lock = lock;
+		mux->clk.reg = reg + mux->reg_off;
+
+		ret = k230_register_clk(mux->id, &mux->clk.hw, dev, hw_data);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < K230_CLK_GATE_NUM; i++) {
+		gate = k230_clk_gates[i];
+		gate->clk.lock = lock;
+		gate->clk.reg = reg + gate->reg_off;
+
+		ret = k230_register_clk(gate->id, &gate->clk.hw, dev, hw_data);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < K230_CLK_RATE_NUM; i++) {
+		rate = k230_clk_rates[i];
+		rate->clk.lock = lock;
+		rate->clk.reg = reg;
+
+		ret = k230_register_clk(rate->id, &rate->clk.hw, dev, hw_data);
+		if (ret)
+			return ret;
+	}
+
+	ret = k230_register_clk(K230_SHRM_SRAM_DIV2, &fixed_factor->hw, dev, hw_data);
+	if (ret)
+		return ret;
+
+	return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, hw_data);
+}
+
+static int k230_clk_init_plls(struct platform_device *pdev)
+{
+	int ret;
+	void __iomem *reg;
+	/* used for all the plls */
+	spinlock_t *lock;
+
+	lock = devm_kzalloc(&pdev->dev, sizeof(*lock), GFP_KERNEL);
+	if (!lock)
+		return -ENOMEM;
+
+	spin_lock_init(lock);
+
+	reg = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	ret = k230_register_plls(pdev, lock, reg);
+	if (ret)
+		return ret;
+
+	ret = k230_register_pll_divs(pdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int k230_clk_init_clks(struct platform_device *pdev,
+			      struct clk_hw_onecell_data *hw_data)
+{
+	int ret;
+	void __iomem *reg;
+	/* used for all the clocks */
+	spinlock_t *lock;
+
+	lock = devm_kzalloc(&pdev->dev, sizeof(*lock), GFP_KERNEL);
+	if (!lock)
+		return -ENOMEM;
+
+	spin_lock_init(lock);
+
+	hw_data->num = K230_CLK_NUM;
+
+	reg = devm_platform_ioremap_resource(pdev, 1);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	ret = k230_register_clks(pdev, hw_data, lock, reg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int k230_clk_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct clk_hw_onecell_data *hw_data;
+
+	hw_data = devm_kzalloc(&pdev->dev, struct_size(hw_data, hws, K230_CLK_NUM),
+			       GFP_KERNEL);
+	if (!hw_data)
+		return -ENOMEM;
+
+	ret = k230_clk_init_plls(pdev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "init plls failed\n");
+
+	ret = k230_clk_init_clks(pdev, hw_data);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "init clks failed\n");
+
+	return 0;
+}
+
+static const struct of_device_id k230_clk_ids[] = {
+	{ .compatible = "canaan,k230-clk" },
+	{ /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, k230_clk_ids);
+
+static struct platform_driver k230_clk_driver = {
+	.driver = {
+		.name = "k230_clock_controller",
+		.of_match_table = k230_clk_ids,
+	},
+	.probe = k230_clk_probe,
+};
+builtin_platform_driver(k230_clk_driver);

-- 
2.34.1




More information about the linux-riscv mailing list