[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250730-b4-k230-clk-v7-2-c57d3bb593d3@zohomail.com>
Date: Wed, 30 Jul 2025 02:43:52 +0800
From: Xukai Wang <kingxukai@...omail.com>
To: Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>, Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>, Xukai Wang <kingxukai@...omail.com>,
Paul Walmsley <paul.walmsley@...ive.com>,
Palmer Dabbelt <palmer@...belt.com>, Albert Ou <aou@...s.berkeley.edu>,
Conor Dooley <conor@...nel.org>
Cc: linux-clk@...r.kernel.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-riscv@...ts.infradead.org,
Samuel Holland <samuel.holland@...ive.com>,
Troy Mitchell <TroyMitchell988@...il.com>
Subject: [PATCH v7 2/3] clk: canaan: Add clock driver for Canaan K230
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@...il.com>
Signed-off-by: Troy Mitchell <TroyMitchell988@...il.com>
Signed-off-by: Xukai Wang <kingxukai@...omail.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@...omail.com>
+ * Author: Troy Mitchell <troymitchell988@...il.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
Powered by blists - more mailing lists