linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Add T-HEAD th1520 soc clock support
@ 2023-05-15  5:43 Yangtao Li
  2023-05-15  5:43 ` [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock Yangtao Li
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Yangtao Li @ 2023-05-15  5:43 UTC (permalink / raw)
  To: mturquette, sboyd
  Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, linux-riscv, Yangtao Li

It is planned to support th1520 soc from T-HEAD in Linux, which is the clock part.

BTW, we are already in the shell console, and some modules are already available.
This patchset depends on some of the patches in the link below:
https://www.spinics.net/lists/kernel/msg4780793.html

Yangtao Li (3):
  dt-bindings: clock: Add thead th1520 clock
  clk: thead: add support for the T-HEAD TH1520 CCU
  MAINTAINERS: update entry for T-HEAD RISC-V SoC

 .../bindings/clock/thead,th1520-ccu.yaml      |  60 ++
 MAINTAINERS                                   |   6 +-
 drivers/clk/Kconfig                           |   6 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-th1520.c                      | 999 ++++++++++++++++++
 include/dt-bindings/clock/th1520-clock.h      |  92 ++
 6 files changed, 1163 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
 create mode 100644 drivers/clk/clk-th1520.c
 create mode 100644 include/dt-bindings/clock/th1520-clock.h

-- 
2.39.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock
  2023-05-15  5:43 [PATCH 0/3] Add T-HEAD th1520 soc clock support Yangtao Li
@ 2023-05-15  5:43 ` Yangtao Li
  2023-05-15  6:22   ` Krzysztof Kozlowski
  2023-05-15  6:26   ` Krzysztof Kozlowski
  2023-05-15  5:44 ` [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU Yangtao Li
  2023-05-15  5:44 ` [PATCH 3/3] MAINTAINERS: update entry for T-HEAD RISC-V SoC Yangtao Li
  2 siblings, 2 replies; 11+ messages in thread
From: Yangtao Li @ 2023-05-15  5:43 UTC (permalink / raw)
  To: mturquette, sboyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jisheng Zhang, Wei Fu, Yangtao Li
  Cc: linux-clk, devicetree, linux-kernel, linux-riscv, Icenowy Zheng

Add devicetree binding document and related header file
for the T-HEAD TH1520 clock.

Cc: Icenowy Zheng <uwu@icenowy.me>
Cc: Wei Fu <wefu@redhat.com>
Cc: Jisheng Zhang <jszhang@kernel.org>
Signed-off-by: Yangtao Li <frank.li@vivo.com>
---
 .../bindings/clock/thead,th1520-ccu.yaml      | 60 +++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml

diff --git a/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml b/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
new file mode 100644
index 000000000000..c3e2d8c7efa6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/thead,th1520-ccu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: T-HEAD Clock Control Unit
+
+maintainers:
+  - Jisheng Zhang <jszhang@kernel.org>
+  - Wei Fu <wefu@redhat.com>
+  - Yangtao Li <frank.li@vivo.com>
+
+
+properties:
+  "#clock-cells":
+    const: 1
+
+  "#reset-cells":
+    const: 1
+
+  compatible:
+    enum:
+      - thead,th1520-ccu
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    const: 2
+    items:
+      - description: High Frequency Oscillator (usually at 24MHz)
+      - description: Low Frequency Oscillator (usually at 32kHz)
+
+  clock-names:
+    const: 2
+    items:
+      - const: hosc
+      - const: losc
+
+required:
+  - "#clock-cells"
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    clk: clock-controller@ffef010000 {
+      compatible = "thead,th1520-ccu";
+      reg = <0xff 0xef010000 0x0 0x1000>;
+      clocks = <&osc32k>, <&osc24m>;
+      clock-names = "losc", "hosc";
+      #clock-cells = <1>;
+    };
+
+...
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU
  2023-05-15  5:43 [PATCH 0/3] Add T-HEAD th1520 soc clock support Yangtao Li
  2023-05-15  5:43 ` [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock Yangtao Li
@ 2023-05-15  5:44 ` Yangtao Li
  2023-05-15  6:27   ` Krzysztof Kozlowski
                     ` (2 more replies)
  2023-05-15  5:44 ` [PATCH 3/3] MAINTAINERS: update entry for T-HEAD RISC-V SoC Yangtao Li
  2 siblings, 3 replies; 11+ messages in thread
From: Yangtao Li @ 2023-05-15  5:44 UTC (permalink / raw)
  To: mturquette, sboyd, Jisheng Zhang, Wei Fu, Yangtao Li,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-clk, devicetree, linux-kernel, linux-riscv, Icenowy Zheng

Add support for th1520 in the clock framework.

Cc: Icenowy Zheng <uwu@icenowy.me>
Cc: Wei Fu <wefu@redhat.com>
Cc: Jisheng Zhang <jszhang@kernel.org>
Signed-off-by: Yangtao Li <frank.li@vivo.com>
---
 drivers/clk/Kconfig                      |   6 +
 drivers/clk/Makefile                     |   1 +
 drivers/clk/clk-th1520.c                 | 999 +++++++++++++++++++++++
 include/dt-bindings/clock/th1520-clock.h |  92 +++
 4 files changed, 1098 insertions(+)
 create mode 100644 drivers/clk/clk-th1520.c
 create mode 100644 include/dt-bindings/clock/th1520-clock.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 016814e15536..aa69a4d17916 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -464,6 +464,12 @@ config COMMON_CLK_SP7021
 	  Not all features of the PLL are currently supported
 	  by the driver.
 
+config COMMON_CLK_THEAD
+	tristate "Clock driver for TH1520 SoC"
+	depends on ARCH_THEAD || COMPILE_TEST
+	help
+	  Support for the T-HEAD TH1520 RISC-V SoC clocks.
+
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/baikal-t1/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 0aebef17edc6..95c89bfb129f 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_RS9_PCIE)	+= clk-renesas-pcie.o
 obj-$(CONFIG_COMMON_CLK_SI521XX)	+= clk-si521xx.o
+obj-$(CONFIG_COMMON_CLK_THEAD)		+= clk-th1520.o
 obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
 obj-$(CONFIG_COMMON_CLK_VC7)		+= clk-versaclock7.o
 obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
diff --git a/drivers/clk/clk-th1520.c b/drivers/clk/clk-th1520.c
new file mode 100644
index 000000000000..5dfa9e5207e2
--- /dev/null
+++ b/drivers/clk/clk-th1520.c
@@ -0,0 +1,999 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.
+ * Authors: Yangtao Li <frank.li@vivo.com>
+ */
+
+#include <dt-bindings/clock/th1520-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+struct ccu_internal {
+	u8	shift;
+	u8	width;
+};
+
+struct ccu_div_internal {
+	u8	shift;
+	u8	width;
+	u32	flags;
+};
+
+struct ccu_common {
+	struct regmap	*map;
+	u16		reg;
+	struct clk_hw	hw;
+};
+
+struct ccu_mux {
+	struct ccu_internal	mux;
+	struct ccu_common	common;
+};
+
+struct ccu_gate {
+	u32			enable;
+	struct ccu_common	common;
+};
+
+struct ccu_div {
+	u32			enable;
+	struct ccu_div_internal	div;
+	struct ccu_internal	mux;
+	struct ccu_common	common;
+};
+
+/*
+ * struct ccu_mdiv - Definition of an M-D-I-V clock
+ *
+ * Clocks based on the formula (parent * M) / (D * I * V)
+ */
+struct ccu_mdiv {
+	struct ccu_internal	m;
+	struct ccu_internal	d;
+	struct ccu_internal	i;
+	struct ccu_internal	v;
+	struct ccu_common	common;
+};
+
+#define TH_CCU_ARG(_shift, _width)					\
+	{								\
+		.shift	= _shift,					\
+		.width	= _width,					\
+	}
+
+#define TH_CCU_DIV_FLAGS(_shift, _width, _flags)			\
+	{								\
+		.shift	= _shift,					\
+		.width	= _width,					\
+		.flags	= _flags,					\
+	}
+
+#define CCU_GATE(_struct, _name, _parent, _reg, _gate, _flags)		\
+	struct ccu_gate _struct = {					\
+		.enable	= _gate,					\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= CLK_HW_INIT(_name,		\
+						      _parent,		\
+						      &ccu_gate_ops,	\
+						      _flags),		\
+		}							\
+	}
+
+static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
+{
+	return container_of(hw, struct ccu_common, hw);
+}
+
+static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_mux, common);
+}
+
+static inline struct ccu_mdiv *hw_to_ccu_mdiv(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_mdiv, common);
+}
+
+static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_div, common);
+}
+
+static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_gate, common);
+}
+
+static u8 ccu_get_parent_helper(struct ccu_common *common,
+				struct ccu_internal *mux)
+{
+	unsigned int val;
+	u8 parent;
+
+	regmap_read(common->map, common->reg, &val);
+	parent = val >> mux->shift;
+	parent &= GENMASK(mux->width - 1, 0);
+
+	return parent;
+}
+
+static int ccu_set_parent_helper(struct ccu_common *common,
+				struct ccu_internal *mux,
+				u8 index)
+{
+	return regmap_update_bits(common->map, common->reg,
+			GENMASK(mux->width - 1, 0) << mux->shift,
+			index << mux->shift);
+}
+
+static u8 ccu_mux_get_parent(struct clk_hw *hw)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_get_parent_helper(&cm->common, &cm->mux);
+}
+
+static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_set_parent_helper(&cm->common, &cm->mux, index);
+}
+
+static const struct clk_ops ccu_mux_ops = {
+	.get_parent	= ccu_mux_get_parent,
+	.set_parent	= ccu_mux_set_parent,
+	.determine_rate	= __clk_mux_determine_rate,
+};
+
+void ccu_disable_helper(struct ccu_common *common, u32 gate)
+{
+	if (!gate)
+		return;
+
+	regmap_update_bits(common->map, common->reg,
+			   gate, ~gate);
+}
+
+int ccu_enable_helper(struct ccu_common *common, u32 gate)
+{
+	if (!gate)
+		return 0;
+
+	return regmap_update_bits(common->map, common->reg,
+				  gate, gate);
+}
+
+static int ccu_is_enabled_helper(struct ccu_common *common, u32 gate)
+{
+	unsigned int val;
+
+	if (!gate)
+		return true;
+
+	regmap_read(common->map, common->reg, &val);
+	return val & gate;
+}
+
+static int ccu_gate_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+	return ccu_is_enabled_helper(&cg->common, cg->enable);
+}
+
+static void ccu_gate_disable(struct clk_hw *hw)
+{
+	struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+	ccu_disable_helper(&cg->common, cg->enable);
+}
+
+static int ccu_gate_enable(struct clk_hw *hw)
+{
+	struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+	return ccu_enable_helper(&cg->common, cg->enable);
+}
+
+static const struct clk_ops ccu_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.is_enabled	= ccu_gate_is_enabled,
+};
+
+static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_div *cd = hw_to_ccu_div(hw);
+	unsigned int val;
+
+	regmap_read(cd->common.map, cd->common.reg, &val);
+	val = val >> cd->div.shift;
+	val &= GENMASK(cd->div.width - 1, 0);
+
+	val = divider_recalc_rate(hw, parent_rate, val, NULL,
+				  cd->div.flags, cd->div.width);
+
+	return val;
+}
+
+static u8 ccu_div_get_parent(struct clk_hw *hw)
+{
+	struct ccu_div *cd = hw_to_ccu_div(hw);
+
+	return ccu_get_parent_helper(&cd->common, &cd->mux);
+}
+
+static int ccu_div_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct ccu_div *cd = hw_to_ccu_div(hw);
+
+	return ccu_set_parent_helper(&cd->common, &cd->mux, index);
+}
+
+static void ccu_div_disable(struct clk_hw *hw)
+{
+	struct ccu_div *cd = hw_to_ccu_div(hw);
+
+	ccu_disable_helper(&cd->common, cd->enable);
+}
+
+static int ccu_div_enable(struct clk_hw *hw)
+{
+	struct ccu_div *cd = hw_to_ccu_div(hw);
+
+	return ccu_enable_helper(&cd->common, cd->enable);
+}
+
+static int ccu_div_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_div *cd = hw_to_ccu_div(hw);
+
+	return ccu_is_enabled_helper(&cd->common, cd->enable);
+}
+
+static const struct clk_ops ccu_div_ops = {
+	.disable	= ccu_div_disable,
+	.enable		= ccu_div_enable,
+	.is_enabled	= ccu_div_is_enabled,
+	.get_parent	= ccu_div_get_parent,
+	.set_parent	= ccu_div_set_parent,
+	.recalc_rate	= ccu_div_recalc_rate,
+};
+
+
+static unsigned long ccu_mdiv_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_mdiv *mdiv = hw_to_ccu_mdiv(hw);
+	unsigned long div, rate = parent_rate;
+	unsigned int m, d, i, v, val;
+
+	regmap_read(mdiv->common.map, mdiv->common.reg, &val);
+
+	m = val >> mdiv->m.shift;
+	m &= GENMASK(mdiv->m.width - 1, 0);
+
+	d = val >> mdiv->d.shift;
+	d &= GENMASK(mdiv->d.width - 1, 0);
+
+	i = val >> mdiv->i.shift;
+	i &= GENMASK(mdiv->i.width - 1, 0);
+
+	v = val >> mdiv->v.shift;
+	v &= GENMASK(mdiv->v.width - 1, 0);
+
+	rate = parent_rate * m;
+	div = d * i * v;
+	do_div(rate, div);
+
+	return rate;
+}
+
+static const struct clk_ops clk_mdiv_ops = {
+	.recalc_rate	= ccu_mdiv_recalc_rate,
+};
+
+static struct ccu_mdiv pll_cpu0_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x000,
+		.hw.init	= CLK_HW_INIT("pll-cpu0", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static struct ccu_mdiv pll_cpu1_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x010,
+		.hw.init	= CLK_HW_INIT("pll-cpu1", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static struct ccu_mdiv pll_gmac_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x020,
+		.hw.init	= CLK_HW_INIT("pll-gmac", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static struct ccu_mdiv pll_video_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x030,
+		.hw.init	= CLK_HW_INIT("pll-video", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static struct ccu_mdiv pll_dpu0_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x040,
+		.hw.init	= CLK_HW_INIT("pll-dpu0", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static struct ccu_mdiv pll_dpu1_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x050,
+		.hw.init	= CLK_HW_INIT("pll-dpu1", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static struct ccu_mdiv pll_tee_clk = {
+	.m		= TH_CCU_ARG(8, 12),
+	.d		= TH_CCU_ARG(24, 3),
+	.i		= TH_CCU_ARG(20, 3),
+	.v		= TH_CCU_ARG(0, 6),
+	.common		= {
+		.reg		= 0x060,
+		.hw.init	= CLK_HW_INIT("pll-tee", "osc24m",
+					      &clk_mdiv_ops,
+					      0),
+	},
+};
+
+static const char * const c910_i0_parents[] = { "pll-cpu0", "osc24m" };
+struct ccu_mux c910_i0_clk = {
+	.mux	= TH_CCU_ARG(1, 1),
+	.common	= {
+		.reg		= 00100,
+		.hw.init	= CLK_HW_INIT_PARENTS("c910-i0",
+					      c910_i0_parents,
+					      &ccu_mux_ops,
+					      0),
+	}
+};
+
+static const char * const c910_parents[] = { "c910-i0", "pll-cpu1" };
+struct ccu_mux c910_clk = {
+	.mux	= TH_CCU_ARG(0, 1),
+	.common	= {
+		.reg		= 0x100,
+		.hw.init	= CLK_HW_INIT_PARENTS("c910",
+					      c910_parents,
+					      &ccu_mux_ops,
+					      0),
+	}
+};
+
+static CCU_GATE(brom_clk, "brom", "ahb2",
+		0x100, BIT(4), 0);
+
+static CCU_GATE(bmu_clk, "bmu", "axi4",
+		0x100, BIT(5), 0);
+
+static const char * const ahb2_parents[] = { "pll-gmac", "osc24m" };
+static struct ccu_div ahb2_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(5, 1),
+	.common		= {
+		.reg		= 0x120,
+		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
+						      ahb2_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static struct ccu_div apb3_clk = {
+	.div		= TH_CCU_ARG(0, 3),
+	.common		= {
+		.reg		= 0x130,
+		.hw.init	= CLK_HW_INIT("apb3", "ahb2",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div axi4_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x134,
+		.hw.init	= CLK_HW_INIT("axi4", "pll-gmac",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static CCU_GATE(aon2cpu_clk, "aon2cpu", "axi4",
+		0x134, BIT(8), 0);
+
+static CCU_GATE(x2x_clk, "x2x", "axi4",
+		0x134, BIT(7), 0);
+
+static const char * const axi_parents[] = { "pll-video", "osc24m" };
+static struct ccu_div axi_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(5, 1),
+	.common		= {
+		.reg		= 0x138,
+		.hw.init	= CLK_HW_INIT_PARENTS("axi",
+						      axi_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static CCU_GATE(cpu2aon_clk, "cpu2aon", "axi",
+		0x138, BIT(8), 0);
+
+static const char * const peri_ahb_parents[] = { "pll-gmac", "osc24m" };
+static struct ccu_div peri_ahb_clk = {
+	.enable		= BIT(6),
+	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(5, 1),
+	.common		= {
+		.reg		= 0x140,
+		.hw.init	= CLK_HW_INIT_PARENTS("peri-ahb",
+						      peri_ahb_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static CCU_GATE(cpu2peri_clk, "cpu2peri", "axi4",
+		0x140, BIT(9), 0);
+
+static struct ccu_div peri_apb_clk = {
+	.div		= TH_CCU_ARG(0, 3),
+	.common		= {
+		.reg		= 0x150,
+		.hw.init	= CLK_HW_INIT("peri-apb", "peri-ahb",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div peri2apb_clk = {
+	.div		= TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x150,
+		.hw.init	= CLK_HW_INIT("peri2apb",
+					      "pll-gmac",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static CCU_GATE(peri_apb1_clk, "peri-apb1", "peri-ahb",
+		0x150, BIT(9), 0);
+
+static CCU_GATE(peri_apb2_clk, "peri-apb2", "peri-ahb",
+		0x150, BIT(10), 0);
+
+static CCU_GATE(peri_apb3_clk, "peri-apb3", "peri-ahb",
+		0x150, BIT(11), 0);
+
+static CCU_GATE(peri_apb4_clk, "peri-apb4", "peri-ahb",
+		0x150, BIT(12), 0);
+
+static CLK_FIXED_FACTOR_FW_NAME(osc12m_clk, "osc12m", "hosc", 2, 1, 0);
+
+static const char * const out_parents[] = { "osc24m", "osc12m" };
+
+static struct ccu_div out1_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(4, 1),
+	.common		= {
+		.reg		= 0x1b4,
+		.hw.init	= CLK_HW_INIT_PARENTS("out1",
+						      out_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static struct ccu_div out2_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(4, 1),
+	.common		= {
+		.reg		= 0x1b8,
+		.hw.init	= CLK_HW_INIT_PARENTS("out2",
+						      out_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static struct ccu_div out3_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(4, 1),
+	.common		= {
+		.reg		= 0x1bc,
+		.hw.init	= CLK_HW_INIT_PARENTS("out3",
+						      out_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static struct ccu_div out4_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(4, 1),
+	.common		= {
+		.reg		= 0x1c0,
+		.hw.init	= CLK_HW_INIT_PARENTS("out4",
+						      out_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static const char * const apb_parents[] = { "pll-gmac", "osc24m" };
+static struct ccu_div apb_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(7, 1),
+	.common		= {
+		.reg		= 0x1c4,
+		.hw.init	= CLK_HW_INIT_PARENTS("apb",
+						      apb_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static const char * const npu_parents[] = { "pll-gmac", "pll-video" };
+static struct ccu_div npu_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.mux		= TH_CCU_ARG(6, 1),
+	.common		= {
+		.reg		= 0x1c8,
+		.hw.init	= CLK_HW_INIT_PARENTS("npu",
+						      npu_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static struct ccu_div vi_clk = {
+	.div		= TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1d0,
+		.hw.init	= CLK_HW_INIT("vi",
+					      "pll-video",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div vi_ahb_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1d0,
+		.hw.init	= CLK_HW_INIT("vi-ahb",
+					      "pll-video",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div vo_axi_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1dc,
+		.hw.init	= CLK_HW_INIT("vo-axi",
+					      "pll-video",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div vp_apb_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1e0,
+		.hw.init	= CLK_HW_INIT("vp-apb",
+					      "pll-gmac",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div vp_axi_clk = {
+	.enable		= BIT(15),
+	.div		= TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1e0,
+		.hw.init	= CLK_HW_INIT("vp-axi",
+					      "pll-video",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static CCU_GATE(cpu2vp_clk, "cpu2vp", "axi",
+		0x1e0, BIT(13), 0);
+
+static struct ccu_div venc_clk = {
+	.enable		= BIT(5),
+	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1e4,
+		.hw.init	= CLK_HW_INIT("venc",
+					      "pll-gmac",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div dpu0_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1e8,
+		.hw.init	= CLK_HW_INIT("dpu0",
+					      "pll-dpu0",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static struct ccu_div dpu1_clk = {
+	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
+	.common		= {
+		.reg		= 0x1ec,
+		.hw.init	= CLK_HW_INIT("dpu1",
+					      "pll-dpu1",
+					      &ccu_div_ops,
+					      0),
+	},
+};
+
+static CCU_GATE(mmc_clk, "mmc", "pll-video", 0x204, BIT(30), 0);
+static CCU_GATE(gmac1_clk, "gmac1", "pll-gmac", 0x204, BIT(26), 0);
+static CCU_GATE(padctrl1_clk, "padctrl1", "peri-apb", 0x204, BIT(24), 0);
+static CCU_GATE(dsmart_clk, "dsmart", "peri-apb", 0x204, BIT(23), 0);
+static CCU_GATE(padctrl0_clk, "padctrl0", "peri-apb", 0x204, BIT(22), 0);
+static CCU_GATE(gmac_axi_clk, "gmac-axi", "axi4", 0x204, BIT(21), 0);
+static CCU_GATE(gmac0_clk, "gmac0", "pll-gmac", 0x204, BIT(19), 0);
+static CCU_GATE(pwm_clk, "pwm", "peri-apb", 0x204, BIT(18), 0);
+static CCU_GATE(qspi0_clk, "qspi0", "pll-video", 0x204, BIT(17), 0);
+static CCU_GATE(qspi1_clk, "qspi1", "pll-video", 0x204, BIT(16), 0);
+static CCU_GATE(spi_clk, "spi", "pll-video", 0x204, BIT(15), 0);
+static CCU_GATE(uart0_clk, "uart0", "peri-apb", 0x204, BIT(14), 0);
+static CCU_GATE(uart1_clk, "uart1", "peri-apb", 0x204, BIT(13), 0);
+static CCU_GATE(uart2_clk, "uart2", "peri-apb", 0x204, BIT(12), 0);
+static CCU_GATE(uart3_clk, "uart3", "peri-apb", 0x204, BIT(11), 0);
+static CCU_GATE(uart4_clk, "uart4", "peri-apb", 0x204, BIT(10), 0);
+static CCU_GATE(uart5_clk, "uart5", "peri-apb", 0x204, BIT(9), 0);
+static CCU_GATE(i2c0_clk, "i2c0", "peri-apb", 0x204, BIT(5), 0);
+static CCU_GATE(i2c1_clk, "i2c1", "peri-apb", 0x204, BIT(4), 0);
+static CCU_GATE(i2c2_clk, "i2c2", "peri-apb", 0x204, BIT(3), 0);
+static CCU_GATE(i2c3_clk, "i2c3", "peri-apb", 0x204, BIT(2), 0);
+static CCU_GATE(i2c4_clk, "i2c4", "peri-apb", 0x204, BIT(1), 0);
+static CCU_GATE(i2c5_clk, "i2c5", "peri-apb", 0x204, BIT(0), 0);
+
+static CCU_GATE(spinlock_clk, "spinlock", "ahb2", 0x208, BIT(10), 0);
+static CCU_GATE(dma_clk, "dma", "axi4", 0x208, BIT(8), 0);
+static CCU_GATE(mbox0_clk, "mbox0", "apb3", 0x208, BIT(7), 0);
+static CCU_GATE(mbox1_clk, "mbox1", "apb3", 0x208, BIT(6), 0);
+static CCU_GATE(mbox2_clk, "mbox2", "apb3", 0x208, BIT(5), 0);
+static CCU_GATE(mbox3_clk, "mbox3", "apb3", 0x208, BIT(4), 0);
+static CCU_GATE(wdt0_clk, "wdt0", "apb3", 0x208, BIT(3), 0);
+static CCU_GATE(wdt1_clk, "wdt1", "apb3", 0x208, BIT(2), 0);
+static CCU_GATE(timer0_clk, "timer0", "apb3", 0x208, BIT(1), 0);
+static CCU_GATE(timer1_clk, "timer1", "apb3", 0x208, BIT(0), 0);
+
+static CCU_GATE(sram0_clk, "sram0", "axi", 0x20c, BIT(4), 0);
+static CCU_GATE(sram1_clk, "sram1", "axi", 0x20c, BIT(3), 0);
+static CCU_GATE(sram2_clk, "sram2", "axi", 0x20c, BIT(2), 0);
+static CCU_GATE(sram3_clk, "sram3", "axi", 0x20c, BIT(1), 0);
+
+static CLK_FIXED_FACTOR_HW(pll_gmac_100m_clk, "pll-gmac-100m",
+			   &pll_gmac_clk.common.hw,
+			   10, 1, 0);
+
+static const char * const uart_parents[] = { "pll-gmac-100m", "osc24m" };
+struct ccu_mux uart_clk = {
+	.mux	= TH_CCU_ARG(0, 1),
+	.common	= {
+		.reg		= 0x210,
+		.hw.init	= CLK_HW_INIT_PARENTS("uart",
+					      uart_parents,
+					      &ccu_mux_ops,
+					      0),
+	}
+};
+
+static struct ccu_common *th1520_clks[] = {
+	&pll_cpu0_clk.common,
+	&pll_cpu1_clk.common,
+	&pll_gmac_clk.common,
+	&pll_video_clk.common,
+	&pll_dpu0_clk.common,
+	&pll_dpu1_clk.common,
+	&pll_tee_clk.common,
+	&c910_i0_clk.common,
+	&c910_clk.common,
+	&brom_clk.common,
+	&bmu_clk.common,
+	&ahb2_clk.common,
+	&apb3_clk.common,
+	&axi4_clk.common,
+	&aon2cpu_clk.common,
+	&x2x_clk.common,
+	&axi_clk.common,
+	&cpu2aon_clk.common,
+	&peri_ahb_clk.common,
+	&cpu2peri_clk.common,
+	&peri_apb_clk.common,
+	&peri2apb_clk.common,
+	&peri_apb1_clk.common,
+	&peri_apb2_clk.common,
+	&peri_apb3_clk.common,
+	&peri_apb4_clk.common,
+	&out1_clk.common,
+	&out2_clk.common,
+	&out3_clk.common,
+	&out4_clk.common,
+	&apb_clk.common,
+	&npu_clk.common,
+	&vi_clk.common,
+	&vi_ahb_clk.common,
+	&vo_axi_clk.common,
+	&vp_apb_clk.common,
+	&vp_axi_clk.common,
+	&cpu2vp_clk.common,
+	&venc_clk.common,
+	&dpu0_clk.common,
+	&dpu1_clk.common,
+	&mmc_clk.common,
+	&gmac1_clk.common,
+	&padctrl1_clk.common,
+	&dsmart_clk.common,
+	&padctrl0_clk.common,
+	&gmac_axi_clk.common,
+	&gmac0_clk.common,
+	&pwm_clk.common,
+	&qspi0_clk.common,
+	&qspi1_clk.common,
+	&spi_clk.common,
+	&uart0_clk.common,
+	&uart1_clk.common,
+	&uart2_clk.common,
+	&uart3_clk.common,
+	&uart4_clk.common,
+	&uart5_clk.common,
+	&i2c0_clk.common,
+	&i2c1_clk.common,
+	&i2c2_clk.common,
+	&i2c3_clk.common,
+	&i2c4_clk.common,
+	&i2c5_clk.common,
+	&spinlock_clk.common,
+	&dma_clk.common,
+	&mbox0_clk.common,
+	&mbox1_clk.common,
+	&mbox2_clk.common,
+	&mbox3_clk.common,
+	&wdt0_clk.common,
+	&wdt1_clk.common,
+	&timer0_clk.common,
+	&timer1_clk.common,
+	&sram0_clk.common,
+	&sram1_clk.common,
+	&sram2_clk.common,
+	&sram3_clk.common,
+	&uart_clk.common,
+};
+
+#define NR_CLKS	(CLK_UART + 1)
+
+static struct clk_hw_onecell_data th1520_hw_clks = {
+	.hws	= {
+		[CLK_OSC12M]		= &osc12m_clk.hw,
+		[CLK_PLL_CPU0]		= &pll_cpu0_clk.common.hw,
+		[CLK_PLL_CPU1]		= &pll_cpu1_clk.common.hw,
+		[CLK_PLL_GMAC]		= &pll_gmac_clk.common.hw,
+		[CLK_PLL_VIDEO]		= &pll_video_clk.common.hw,
+		[CLK_PLL_DPU0]		= &pll_dpu0_clk.common.hw,
+		[CLK_PLL_DPU1]		= &pll_dpu1_clk.common.hw,
+		[CLK_PLL_TEE]		= &pll_tee_clk.common.hw,
+		[CLK_C910_I0]		= &c910_i0_clk.common.hw,
+		[CLK_C910]		= &c910_clk.common.hw,
+		[CLK_BROM]		= &brom_clk.common.hw,
+		[CLK_BMU]		= &bmu_clk.common.hw,
+		[CLK_AHB2]		= &ahb2_clk.common.hw,
+		[CLK_APB3]		= &apb3_clk.common.hw,
+		[CLK_AXI4]		= &axi4_clk.common.hw,
+		[CLK_AON2CPU]		= &aon2cpu_clk.common.hw,
+		[CLK_X2X]		= &x2x_clk.common.hw,
+		[CLK_AXI]		= &axi_clk.common.hw,
+		[CLK_CPU2AON]		= &cpu2aon_clk.common.hw,
+		[CLK_PERI_AHB]		= &peri_ahb_clk.common.hw,
+		[CLK_CPU2PERI]		= &cpu2peri_clk.common.hw,
+		[CLK_PERI_APB]		= &peri_apb_clk.common.hw,
+		[CLK_PERI2APB]		= &peri2apb_clk.common.hw,
+		[CLK_PERI_APB1]		= &peri_apb1_clk.common.hw,
+		[CLK_PERI_APB2]		= &peri_apb2_clk.common.hw,
+		[CLK_PERI_APB3]		= &peri_apb3_clk.common.hw,
+		[CLK_PERI_APB4]		= &peri_apb4_clk.common.hw,
+		[CLK_OUT1]		= &out1_clk.common.hw,
+		[CLK_OUT2]		= &out2_clk.common.hw,
+		[CLK_OUT3]		= &out3_clk.common.hw,
+		[CLK_OUT4]		= &out4_clk.common.hw,
+		[CLK_APB]		= &apb_clk.common.hw,
+		[CLK_NPU]		= &npu_clk.common.hw,
+		[CLK_VI]		= &vi_clk.common.hw,
+		[CLK_VI_AHB]		= &vi_ahb_clk.common.hw,
+		[CLK_VO_AXI]		= &vo_axi_clk.common.hw,
+		[CLK_VP_APB]		= &vp_apb_clk.common.hw,
+		[CLK_VP_AXI]		= &vp_axi_clk.common.hw,
+		[CLK_CPU2VP]		= &cpu2vp_clk.common.hw,
+		[CLK_VENC]		= &venc_clk.common.hw,
+		[CLK_DPU0]		= &dpu0_clk.common.hw,
+		[CLK_DPU1]		= &dpu1_clk.common.hw,
+		[CLK_MMC]		= &mmc_clk.common.hw,
+		[CLK_GMAC]		= &gmac1_clk.common.hw,
+		[CLK_PADCTRL1]		= &padctrl1_clk.common.hw,
+		[CLK_DSMART]		= &dsmart_clk.common.hw,
+		[CLK_PADCTRL0]		= &padctrl0_clk.common.hw,
+		[CLK_GMAC_AXI]		= &gmac_axi_clk.common.hw,
+		[CLK_GMAC0]		= &gmac0_clk.common.hw,
+		[CLK_PWM]		= &pwm_clk.common.hw,
+		[CLK_QSPI0]		= &qspi0_clk.common.hw,
+		[CLK_QSPI1]		= &qspi1_clk.common.hw,
+		[CLK_SPI]		= &spi_clk.common.hw,
+		[CLK_UART0]		= &uart0_clk.common.hw,
+		[CLK_UART1]		= &uart1_clk.common.hw,
+		[CLK_UART2]		= &uart2_clk.common.hw,
+		[CLK_UART3]		= &uart3_clk.common.hw,
+		[CLK_UART4]		= &uart4_clk.common.hw,
+		[CLK_UART5]		= &uart5_clk.common.hw,
+		[CLK_I2C0]		= &i2c0_clk.common.hw,
+		[CLK_I2C1]		= &i2c1_clk.common.hw,
+		[CLK_I2C2]		= &i2c2_clk.common.hw,
+		[CLK_I2C3]		= &i2c3_clk.common.hw,
+		[CLK_I2C4]		= &i2c4_clk.common.hw,
+		[CLK_I2C5]		= &i2c5_clk.common.hw,
+		[CLK_SPINLOCK]		= &spinlock_clk.common.hw,
+		[CLK_DMA]		= &dma_clk.common.hw,
+		[CLK_MBOX0]		= &mbox0_clk.common.hw,
+		[CLK_MBOX1]		= &mbox1_clk.common.hw,
+		[CLK_MBOX2]		= &mbox2_clk.common.hw,
+		[CLK_MBOX3]		= &mbox3_clk.common.hw,
+		[CLK_WDT0]		= &wdt0_clk.common.hw,
+		[CLK_WDT1]		= &wdt1_clk.common.hw,
+		[CLK_TIMER0]		= &timer0_clk.common.hw,
+		[CLK_TIMER1]		= &timer1_clk.common.hw,
+		[CLK_SRAM0]		= &sram0_clk.common.hw,
+		[CLK_SRAM1]		= &sram1_clk.common.hw,
+		[CLK_SRAM2]		= &sram2_clk.common.hw,
+		[CLK_SRAM3]		= &sram3_clk.common.hw,
+		[CLK_PLL_GMAC_100M]	= &pll_gmac_100m_clk.hw,
+		[CLK_UART]		= &uart_clk.common.hw,
+	},
+	.num = NR_CLKS,
+};
+
+static const struct regmap_config config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+};
+
+static int th1520_clock_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *map;
+	void __iomem *regs;
+	int ret, i;
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	map = devm_regmap_init_mmio(dev, regs, &config);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	for (i = 0; i < ARRAY_SIZE(th1520_clks); i++)
+		th1520_clks[i]->map = map;
+
+	for (i = 0; i < th1520_hw_clks.num; i++) {
+		ret = devm_clk_hw_register(dev, th1520_hw_clks.hws[i]);
+		if (ret)
+			return ret;
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+					&th1520_hw_clks);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id clk_match_table[] = {
+	{
+		.compatible = "thead,th1520-ccu",
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, clk_match_table);
+
+static struct platform_driver th1520_clk_driver = {
+	.probe		= th1520_clock_probe,
+	.driver		= {
+		.name	= "th1520-clk",
+		.of_match_table = clk_match_table,
+	},
+};
+module_platform_driver(th1520_clk_driver);
+
+MODULE_DESCRIPTION("T-HEAD th1520 Clock driver");
+MODULE_AUTHOR("Yangtao Li <frank.li@vivo.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/clock/th1520-clock.h b/include/dt-bindings/clock/th1520-clock.h
new file mode 100644
index 000000000000..e5a1e1c127fc
--- /dev/null
+++ b/include/dt-bindings/clock/th1520-clock.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.
+ * Authors: Yangtao Li <frank.li@vivo.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_TH1520_H_
+#define _DT_BINDINGS_CLK_TH1520_H_
+
+#define CLK_PLL_CPU0		0
+#define CLK_PLL_CPU1		1
+#define CLK_PLL_GMAC		2
+#define CLK_PLL_VIDEO		3
+#define CLK_PLL_DPU0		4
+#define CLK_PLL_DPU1		5
+#define CLK_PLL_TEE		6
+#define CLK_C910_I0		7
+#define CLK_C910		8
+#define CLK_BROM		9
+#define CLK_BMU			10
+#define CLK_AHB2		11
+#define CLK_APB3		12
+#define CLK_AXI4		13
+#define CLK_AON2CPU		14
+#define CLK_X2X			15
+#define CLK_AXI			16
+#define CLK_CPU2AON		17
+#define CLK_PERI_AHB		18
+#define CLK_CPU2PERI		19
+#define CLK_PERI_APB		20
+#define CLK_PERI2APB		21
+#define CLK_PERI_APB1		22
+#define CLK_PERI_APB2		23
+#define CLK_PERI_APB3		24
+#define CLK_PERI_APB4		25
+#define CLK_OSC12M		26
+#define CLK_OUT1		27
+#define CLK_OUT2		28
+#define CLK_OUT3		29
+#define CLK_OUT4		30
+#define CLK_APB			31
+#define CLK_NPU			32
+#define CLK_VI			33
+#define CLK_VI_AHB		34
+#define CLK_VO_AXI		35
+#define CLK_VP_APB		36
+#define CLK_VP_AXI		37
+#define CLK_CPU2VP		38
+#define CLK_VENC		39
+#define CLK_DPU0		40
+#define CLK_DPU1		41
+#define CLK_MMC			42
+#define CLK_GMAC		43
+#define CLK_PADCTRL1		44
+#define CLK_DSMART		45
+#define CLK_PADCTRL0		46
+#define CLK_GMAC_AXI		47
+#define CLK_GMAC0		48
+#define CLK_PWM			49
+#define CLK_QSPI0		50
+#define CLK_QSPI1		51
+#define CLK_SPI			52
+#define CLK_UART0		53
+#define CLK_UART1		54
+#define CLK_UART2		55
+#define CLK_UART3		56
+#define CLK_UART4		57
+#define CLK_UART5		58
+#define CLK_I2C0		59
+#define CLK_I2C1		60
+#define CLK_I2C2		61
+#define CLK_I2C3		62
+#define CLK_I2C4		63
+#define CLK_I2C5		64
+#define CLK_SPINLOCK		65
+#define CLK_DMA			66
+#define CLK_MBOX0		67
+#define CLK_MBOX1		68
+#define CLK_MBOX2		69
+#define CLK_MBOX3		70
+#define CLK_WDT0		71
+#define CLK_WDT1		72
+#define CLK_TIMER0		73
+#define CLK_TIMER1		74
+#define CLK_SRAM0		75
+#define CLK_SRAM1		76
+#define CLK_SRAM2		77
+#define CLK_SRAM3		78
+#define CLK_PLL_GMAC_100M	79
+#define CLK_UART		80
+
+#endif
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/3] MAINTAINERS: update entry for T-HEAD RISC-V SoC
  2023-05-15  5:43 [PATCH 0/3] Add T-HEAD th1520 soc clock support Yangtao Li
  2023-05-15  5:43 ` [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock Yangtao Li
  2023-05-15  5:44 ` [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU Yangtao Li
@ 2023-05-15  5:44 ` Yangtao Li
  2023-05-15 17:15   ` Conor Dooley
  2 siblings, 1 reply; 11+ messages in thread
From: Yangtao Li @ 2023-05-15  5:44 UTC (permalink / raw)
  To: mturquette, sboyd
  Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, linux-riscv, Yangtao Li, Icenowy Zheng, Wei Fu,
	Jisheng Zhang

Wei and me would like to help support and maintain too.

Cc: Icenowy Zheng <uwu@icenowy.me>
Cc: Wei Fu <wefu@redhat.com>
Cc: Jisheng Zhang <jszhang@kernel.org>
Signed-off-by: Yangtao Li <frank.li@vivo.com>
---
 MAINTAINERS | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index e1e51accec4f..dc35c654f78e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18155,11 +18155,15 @@ T:	git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
 F:	Documentation/devicetree/bindings/riscv/
 F:	arch/riscv/boot/dts/
 
-RISC-V THEAD SoC SUPPORT
+RISC-V T-HEAD SOC SUPPORT
 M:	Jisheng Zhang <jszhang@kernel.org>
+M:	Wei Fu <wefu@redhat.com>
+M:	Yangtao Li <frank.li@vivo.com>
 L:	linux-riscv@lists.infradead.org
 S:	Maintained
 F:	arch/riscv/boot/dts/thead/
+F:	drivers/clk/clk-th1520.c
+F:	include/dt-bindings/clock/th1520-clock.h
 
 RNBD BLOCK DRIVERS
 M:	Md. Haris Iqbal <haris.iqbal@ionos.com>
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock
  2023-05-15  5:43 ` [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock Yangtao Li
@ 2023-05-15  6:22   ` Krzysztof Kozlowski
  2023-05-15  6:26   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 11+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-15  6:22 UTC (permalink / raw)
  To: Yangtao Li
  Cc: linux-riscv, Icenowy Zheng, linux-kernel, Rob Herring,
	mturquette, Krzysztof Kozlowski, sboyd, Wei Fu, Conor Dooley,
	Jisheng Zhang, linux-clk, devicetree

On Mon, 15 May 2023 13:43:59 +0800, Yangtao Li wrote:
> Add devicetree binding document and related header file
> for the T-HEAD TH1520 clock.
> 
> Cc: Icenowy Zheng <uwu@icenowy.me>
> Cc: Wei Fu <wefu@redhat.com>
> Cc: Jisheng Zhang <jszhang@kernel.org>
> Signed-off-by: Yangtao Li <frank.li@vivo.com>
> ---
>  .../bindings/clock/thead,th1520-ccu.yaml      | 60 +++++++++++++++++++
>  1 file changed, 60 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml: properties:clock-names: 'const' should not be valid under {'enum': ['const', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'minimum', 'maximum', 'multipleOf', 'pattern']}
	hint: Scalar and array keywords cannot be mixed
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml: properties:clocks: 'const' should not be valid under {'enum': ['const', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'minimum', 'maximum', 'multipleOf', 'pattern']}
	hint: Scalar and array keywords cannot be mixed
	from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml: properties:clock-names:const: 2 is not of type 'string'
	from schema $id: http://devicetree.org/meta-schemas/string-array.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
	/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml: properties:clocks: 'anyOf' conditional failed, one must be fixed:
		'maxItems' is a required property
			hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
		'const' is not one of ['maxItems', 'description', 'deprecated']
			hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
		'items' is not one of ['maxItems', 'description', 'deprecated']
			hint: Only "maxItems" is required for a single entry if there are no constraints defined for the values.
		Additional properties are not allowed ('const' was unexpected)
			hint: Arrays must be described with a combination of minItems/maxItems/items
		'items' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'multipleOf', 'default', '$ref', 'oneOf']
		hint: cell array properties must define how many entries and what the entries are when there is more than one entry.
		from schema $id: http://devicetree.org/meta-schemas/clocks.yaml#
	'const' is not one of ['type', 'description', 'dependencies', 'dependentRequired', 'dependentSchemas', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'not', 'allOf', 'anyOf', 'oneOf', '$ref']
	'items' is not one of ['type', 'description', 'dependencies', 'dependentRequired', 'dependentSchemas', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'not', 'allOf', 'anyOf', 'oneOf', '$ref']
	'type' is a required property
		hint: DT nodes ("object" type in schemas) can only use a subset of json-schema keywords
	from schema $id: http://devicetree.org/meta-schemas/clocks.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.example.dtb: clock-controller@ffef010000: reg: [[255, 4009820160], [0, 4096]] is too long
	From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.example.dtb: clock-controller@ffef010000: clocks:0:0: 2 was expected
	From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.example.dtb: clock-controller@ffef010000: clock-names:0: 'losc' is not of type 'array'
	From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.example.dtb: clock-controller@ffef010000: clock-names: ['losc', 'hosc'] is too long
	From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml

See https://patchwork.ozlabs.org/patch/1781099

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock
  2023-05-15  5:43 ` [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock Yangtao Li
  2023-05-15  6:22   ` Krzysztof Kozlowski
@ 2023-05-15  6:26   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 11+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-15  6:26 UTC (permalink / raw)
  To: Yangtao Li, mturquette, sboyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jisheng Zhang, Wei Fu
  Cc: linux-clk, devicetree, linux-kernel, linux-riscv, Icenowy Zheng

On 15/05/2023 07:43, Yangtao Li wrote:
> Add devicetree binding document and related header file
> for the T-HEAD TH1520 clock.
> 
> Cc: Icenowy Zheng <uwu@icenowy.me>
> Cc: Wei Fu <wefu@redhat.com>
> Cc: Jisheng Zhang <jszhang@kernel.org>
> Signed-off-by: Yangtao Li <frank.li@vivo.com>
> ---
>  .../bindings/clock/thead,th1520-ccu.yaml      | 60 +++++++++++++++++++
>  1 file changed, 60 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
> 
> diff --git a/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml b/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
> new file mode 100644
> index 000000000000..c3e2d8c7efa6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/thead,th1520-ccu.yaml
> @@ -0,0 +1,60 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license.

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/thead,th1520-ccu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: T-HEAD Clock Control Unit
> +
> +maintainers:
> +  - Jisheng Zhang <jszhang@kernel.org>
> +  - Wei Fu <wefu@redhat.com>
> +  - Yangtao Li <frank.li@vivo.com>
> +
> +

Stray blank line.

> +properties:
> +  "#clock-cells":
> +    const: 1
> +
> +  "#reset-cells":
> +    const: 1
> +
> +  compatible:

Compatible is always first property.

> +    enum:
> +      - thead,th1520-ccu
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    const: 2
> +    items:
> +      - description: High Frequency Oscillator (usually at 24MHz)
> +      - description: Low Frequency Oscillator (usually at 32kHz)

Does not look like you tested the bindings. Please run `make
dt_binding_check` (see
Documentation/devicetree/bindings/writing-schema.rst for instructions).

I'll stop review.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU
  2023-05-15  5:44 ` [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU Yangtao Li
@ 2023-05-15  6:27   ` Krzysztof Kozlowski
  2023-06-13  1:35   ` Stephen Boyd
  2023-08-27 10:37   ` Jisheng Zhang
  2 siblings, 0 replies; 11+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-15  6:27 UTC (permalink / raw)
  To: Yangtao Li, mturquette, sboyd, Jisheng Zhang, Wei Fu,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-clk, devicetree, linux-kernel, linux-riscv, Icenowy Zheng

On 15/05/2023 07:44, Yangtao Li wrote:
> Add support for th1520 in the clock framework.
> 
> Cc: Icenowy Zheng <uwu@icenowy.me>
> Cc: Wei Fu <wefu@redhat.com>
> Cc: Jisheng Zhang <jszhang@kernel.org>
> Signed-off-by: Yangtao Li <frank.li@vivo.com>
> ---
>  drivers/clk/Kconfig                      |   6 +
>  drivers/clk/Makefile                     |   1 +
>  drivers/clk/clk-th1520.c                 | 999 +++++++++++++++++++++++
>  include/dt-bindings/clock/th1520-clock.h |  92 +++
>  4 files changed, 1098 insertions(+)

Please run scripts/checkpatch.pl and fix reported warnings.

Bindings are always separate patches.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] MAINTAINERS: update entry for T-HEAD RISC-V SoC
  2023-05-15  5:44 ` [PATCH 3/3] MAINTAINERS: update entry for T-HEAD RISC-V SoC Yangtao Li
@ 2023-05-15 17:15   ` Conor Dooley
  0 siblings, 0 replies; 11+ messages in thread
From: Conor Dooley @ 2023-05-15 17:15 UTC (permalink / raw)
  To: Yangtao Li
  Cc: mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	linux-clk, devicetree, linux-kernel, linux-riscv, Icenowy Zheng,
	Wei Fu, Jisheng Zhang

[-- Attachment #1: Type: text/plain, Size: 1321 bytes --]

On Mon, May 15, 2023 at 01:44:01PM +0800, Yangtao Li wrote:
> Wei and me would like to help support and maintain too.
> 
> Cc: Icenowy Zheng <uwu@icenowy.me>
> Cc: Wei Fu <wefu@redhat.com>
> Cc: Jisheng Zhang <jszhang@kernel.org>
> Signed-off-by: Yangtao Li <frank.li@vivo.com>
> ---
>  MAINTAINERS | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e1e51accec4f..dc35c654f78e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -18155,11 +18155,15 @@ T:	git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
>  F:	Documentation/devicetree/bindings/riscv/
>  F:	arch/riscv/boot/dts/
>  
> -RISC-V THEAD SoC SUPPORT
> +RISC-V T-HEAD SOC SUPPORT
>  M:	Jisheng Zhang <jszhang@kernel.org>
> +M:	Wei Fu <wefu@redhat.com>
> +M:	Yangtao Li <frank.li@vivo.com>
>  L:	linux-riscv@lists.infradead.org
>  S:	Maintained
>  F:	arch/riscv/boot/dts/thead/
> +F:	drivers/clk/clk-th1520.c

Please tell me you actually communicated with Jisheng this time about
maintainership of stuff, since you're signing them up to maintain the
dt-bindings and the clock driver!

Thanks,
Conor.

> +F:	include/dt-bindings/clock/th1520-clock.h
>  
>  RNBD BLOCK DRIVERS
>  M:	Md. Haris Iqbal <haris.iqbal@ionos.com>
> -- 
> 2.39.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU
  2023-05-15  5:44 ` [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU Yangtao Li
  2023-05-15  6:27   ` Krzysztof Kozlowski
@ 2023-06-13  1:35   ` Stephen Boyd
  2023-08-27 10:37   ` Jisheng Zhang
  2 siblings, 0 replies; 11+ messages in thread
From: Stephen Boyd @ 2023-06-13  1:35 UTC (permalink / raw)
  To: Conor Dooley, Jisheng Zhang, Krzysztof Kozlowski, Rob Herring,
	Wei Fu, Yangtao Li, mturquette
  Cc: linux-clk, devicetree, linux-kernel, linux-riscv, Icenowy Zheng

Quoting Yangtao Li (2023-05-14 22:44:00)
> diff --git a/drivers/clk/clk-th1520.c b/drivers/clk/clk-th1520.c
> new file mode 100644
> index 000000000000..5dfa9e5207e2
> --- /dev/null
> +++ b/drivers/clk/clk-th1520.c
> @@ -0,0 +1,999 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.
> + * Authors: Yangtao Li <frank.li@vivo.com>
> + */
> +
[....]
> +
> +
> +static CLK_FIXED_FACTOR_HW(pll_gmac_100m_clk, "pll-gmac-100m",
> +                          &pll_gmac_clk.common.hw,
> +                          10, 1, 0);
> +
> +static const char * const uart_parents[] = { "pll-gmac-100m", "osc24m" };
> +struct ccu_mux uart_clk = {
> +       .mux    = TH_CCU_ARG(0, 1),
> +       .common = {
> +               .reg            = 0x210,
> +               .hw.init        = CLK_HW_INIT_PARENTS("uart",

Don't use strings for clk tree topology. Instead use clk_parent_data or
clk_hw pointers directly.

> +                                             uart_parents,
> +                                             &ccu_mux_ops,
> +                                             0),
> +       }
> +};
> +};
> +
> +static const struct regmap_config config = {

Namespace this, th1520_clk_regmap_config[]

> +       .reg_bits = 32,
> +       .val_bits = 32,
> +       .reg_stride = 4,
> +       .fast_io = true,
> +};
> +
> +static int th1520_clock_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct regmap *map;
> +       void __iomem *regs;
> +       int ret, i;
> +
> +       regs = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(regs))
> +               return PTR_ERR(regs);
> +
> +       map = devm_regmap_init_mmio(dev, regs, &config);
> +       if (IS_ERR(map))
> +               return PTR_ERR(map);
> +
> +       for (i = 0; i < ARRAY_SIZE(th1520_clks); i++)
> +               th1520_clks[i]->map = map;
> +
> +       for (i = 0; i < th1520_hw_clks.num; i++) {
> +               ret = devm_clk_hw_register(dev, th1520_hw_clks.hws[i]);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> +                                       &th1520_hw_clks);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id clk_match_table[] = {

Namespace this, th1520_clk_match_table[]

> +       {
> +               .compatible = "thead,th1520-ccu",
> +       },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, clk_match_table);
> +

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU
  2023-05-15  5:44 ` [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU Yangtao Li
  2023-05-15  6:27   ` Krzysztof Kozlowski
  2023-06-13  1:35   ` Stephen Boyd
@ 2023-08-27 10:37   ` Jisheng Zhang
  2023-09-03 22:37     ` Drew Fustini
  2 siblings, 1 reply; 11+ messages in thread
From: Jisheng Zhang @ 2023-08-27 10:37 UTC (permalink / raw)
  To: Yangtao Li
  Cc: mturquette, sboyd, Wei Fu, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-clk, devicetree, linux-kernel, linux-riscv,
	Icenowy Zheng

On Mon, May 15, 2023 at 01:44:00PM +0800, Yangtao Li wrote:
> Add support for th1520 in the clock framework.

Hi Yangtao,

I didn't see any new version of this series in this development window,
and we have already talked about it several times on wechat, so do
you still plan to renew this series? If not, I will update it and may
rewrite the code once next development window is open.

Thanks in advance

> 
> Cc: Icenowy Zheng <uwu@icenowy.me>
> Cc: Wei Fu <wefu@redhat.com>
> Cc: Jisheng Zhang <jszhang@kernel.org>
> Signed-off-by: Yangtao Li <frank.li@vivo.com>
> ---
>  drivers/clk/Kconfig                      |   6 +
>  drivers/clk/Makefile                     |   1 +
>  drivers/clk/clk-th1520.c                 | 999 +++++++++++++++++++++++
>  include/dt-bindings/clock/th1520-clock.h |  92 +++
>  4 files changed, 1098 insertions(+)
>  create mode 100644 drivers/clk/clk-th1520.c
>  create mode 100644 include/dt-bindings/clock/th1520-clock.h
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 016814e15536..aa69a4d17916 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -464,6 +464,12 @@ config COMMON_CLK_SP7021
>  	  Not all features of the PLL are currently supported
>  	  by the driver.
>  
> +config COMMON_CLK_THEAD
> +	tristate "Clock driver for TH1520 SoC"
> +	depends on ARCH_THEAD || COMPILE_TEST
> +	help
> +	  Support for the T-HEAD TH1520 RISC-V SoC clocks.
> +
>  source "drivers/clk/actions/Kconfig"
>  source "drivers/clk/analogbits/Kconfig"
>  source "drivers/clk/baikal-t1/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 0aebef17edc6..95c89bfb129f 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -76,6 +76,7 @@ obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
>  obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
>  obj-$(CONFIG_COMMON_CLK_RS9_PCIE)	+= clk-renesas-pcie.o
>  obj-$(CONFIG_COMMON_CLK_SI521XX)	+= clk-si521xx.o
> +obj-$(CONFIG_COMMON_CLK_THEAD)		+= clk-th1520.o
>  obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
>  obj-$(CONFIG_COMMON_CLK_VC7)		+= clk-versaclock7.o
>  obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
> diff --git a/drivers/clk/clk-th1520.c b/drivers/clk/clk-th1520.c
> new file mode 100644
> index 000000000000..5dfa9e5207e2
> --- /dev/null
> +++ b/drivers/clk/clk-th1520.c
> @@ -0,0 +1,999 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.
> + * Authors: Yangtao Li <frank.li@vivo.com>
> + */
> +
> +#include <dt-bindings/clock/th1520-clock.h>
> +#include <linux/clk-provider.h>
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +struct ccu_internal {
> +	u8	shift;
> +	u8	width;
> +};
> +
> +struct ccu_div_internal {
> +	u8	shift;
> +	u8	width;
> +	u32	flags;
> +};
> +
> +struct ccu_common {
> +	struct regmap	*map;
> +	u16		reg;
> +	struct clk_hw	hw;
> +};
> +
> +struct ccu_mux {
> +	struct ccu_internal	mux;
> +	struct ccu_common	common;
> +};
> +
> +struct ccu_gate {
> +	u32			enable;
> +	struct ccu_common	common;
> +};
> +
> +struct ccu_div {
> +	u32			enable;
> +	struct ccu_div_internal	div;
> +	struct ccu_internal	mux;
> +	struct ccu_common	common;
> +};
> +
> +/*
> + * struct ccu_mdiv - Definition of an M-D-I-V clock
> + *
> + * Clocks based on the formula (parent * M) / (D * I * V)
> + */
> +struct ccu_mdiv {
> +	struct ccu_internal	m;
> +	struct ccu_internal	d;
> +	struct ccu_internal	i;
> +	struct ccu_internal	v;
> +	struct ccu_common	common;
> +};
> +
> +#define TH_CCU_ARG(_shift, _width)					\
> +	{								\
> +		.shift	= _shift,					\
> +		.width	= _width,					\
> +	}
> +
> +#define TH_CCU_DIV_FLAGS(_shift, _width, _flags)			\
> +	{								\
> +		.shift	= _shift,					\
> +		.width	= _width,					\
> +		.flags	= _flags,					\
> +	}
> +
> +#define CCU_GATE(_struct, _name, _parent, _reg, _gate, _flags)		\
> +	struct ccu_gate _struct = {					\
> +		.enable	= _gate,					\
> +		.common	= {						\
> +			.reg		= _reg,				\
> +			.hw.init	= CLK_HW_INIT(_name,		\
> +						      _parent,		\
> +						      &ccu_gate_ops,	\
> +						      _flags),		\
> +		}							\
> +	}
> +
> +static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
> +{
> +	return container_of(hw, struct ccu_common, hw);
> +}
> +
> +static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
> +{
> +	struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +	return container_of(common, struct ccu_mux, common);
> +}
> +
> +static inline struct ccu_mdiv *hw_to_ccu_mdiv(struct clk_hw *hw)
> +{
> +	struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +	return container_of(common, struct ccu_mdiv, common);
> +}
> +
> +static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
> +{
> +	struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +	return container_of(common, struct ccu_div, common);
> +}
> +
> +static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
> +{
> +	struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +	return container_of(common, struct ccu_gate, common);
> +}
> +
> +static u8 ccu_get_parent_helper(struct ccu_common *common,
> +				struct ccu_internal *mux)
> +{
> +	unsigned int val;
> +	u8 parent;
> +
> +	regmap_read(common->map, common->reg, &val);
> +	parent = val >> mux->shift;
> +	parent &= GENMASK(mux->width - 1, 0);
> +
> +	return parent;
> +}
> +
> +static int ccu_set_parent_helper(struct ccu_common *common,
> +				struct ccu_internal *mux,
> +				u8 index)
> +{
> +	return regmap_update_bits(common->map, common->reg,
> +			GENMASK(mux->width - 1, 0) << mux->shift,
> +			index << mux->shift);
> +}
> +
> +static u8 ccu_mux_get_parent(struct clk_hw *hw)
> +{
> +	struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +	return ccu_get_parent_helper(&cm->common, &cm->mux);
> +}
> +
> +static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +	return ccu_set_parent_helper(&cm->common, &cm->mux, index);
> +}
> +
> +static const struct clk_ops ccu_mux_ops = {
> +	.get_parent	= ccu_mux_get_parent,
> +	.set_parent	= ccu_mux_set_parent,
> +	.determine_rate	= __clk_mux_determine_rate,
> +};
> +
> +void ccu_disable_helper(struct ccu_common *common, u32 gate)
> +{
> +	if (!gate)
> +		return;
> +
> +	regmap_update_bits(common->map, common->reg,
> +			   gate, ~gate);
> +}
> +
> +int ccu_enable_helper(struct ccu_common *common, u32 gate)
> +{
> +	if (!gate)
> +		return 0;
> +
> +	return regmap_update_bits(common->map, common->reg,
> +				  gate, gate);
> +}
> +
> +static int ccu_is_enabled_helper(struct ccu_common *common, u32 gate)
> +{
> +	unsigned int val;
> +
> +	if (!gate)
> +		return true;
> +
> +	regmap_read(common->map, common->reg, &val);
> +	return val & gate;
> +}
> +
> +static int ccu_gate_is_enabled(struct clk_hw *hw)
> +{
> +	struct ccu_gate *cg = hw_to_ccu_gate(hw);
> +
> +	return ccu_is_enabled_helper(&cg->common, cg->enable);
> +}
> +
> +static void ccu_gate_disable(struct clk_hw *hw)
> +{
> +	struct ccu_gate *cg = hw_to_ccu_gate(hw);
> +
> +	ccu_disable_helper(&cg->common, cg->enable);
> +}
> +
> +static int ccu_gate_enable(struct clk_hw *hw)
> +{
> +	struct ccu_gate *cg = hw_to_ccu_gate(hw);
> +
> +	return ccu_enable_helper(&cg->common, cg->enable);
> +}
> +
> +static const struct clk_ops ccu_gate_ops = {
> +	.disable	= ccu_gate_disable,
> +	.enable		= ccu_gate_enable,
> +	.is_enabled	= ccu_gate_is_enabled,
> +};
> +
> +static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
> +					unsigned long parent_rate)
> +{
> +	struct ccu_div *cd = hw_to_ccu_div(hw);
> +	unsigned int val;
> +
> +	regmap_read(cd->common.map, cd->common.reg, &val);
> +	val = val >> cd->div.shift;
> +	val &= GENMASK(cd->div.width - 1, 0);
> +
> +	val = divider_recalc_rate(hw, parent_rate, val, NULL,
> +				  cd->div.flags, cd->div.width);
> +
> +	return val;
> +}
> +
> +static u8 ccu_div_get_parent(struct clk_hw *hw)
> +{
> +	struct ccu_div *cd = hw_to_ccu_div(hw);
> +
> +	return ccu_get_parent_helper(&cd->common, &cd->mux);
> +}
> +
> +static int ccu_div_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct ccu_div *cd = hw_to_ccu_div(hw);
> +
> +	return ccu_set_parent_helper(&cd->common, &cd->mux, index);
> +}
> +
> +static void ccu_div_disable(struct clk_hw *hw)
> +{
> +	struct ccu_div *cd = hw_to_ccu_div(hw);
> +
> +	ccu_disable_helper(&cd->common, cd->enable);
> +}
> +
> +static int ccu_div_enable(struct clk_hw *hw)
> +{
> +	struct ccu_div *cd = hw_to_ccu_div(hw);
> +
> +	return ccu_enable_helper(&cd->common, cd->enable);
> +}
> +
> +static int ccu_div_is_enabled(struct clk_hw *hw)
> +{
> +	struct ccu_div *cd = hw_to_ccu_div(hw);
> +
> +	return ccu_is_enabled_helper(&cd->common, cd->enable);
> +}
> +
> +static const struct clk_ops ccu_div_ops = {
> +	.disable	= ccu_div_disable,
> +	.enable		= ccu_div_enable,
> +	.is_enabled	= ccu_div_is_enabled,
> +	.get_parent	= ccu_div_get_parent,
> +	.set_parent	= ccu_div_set_parent,
> +	.recalc_rate	= ccu_div_recalc_rate,
> +};
> +
> +
> +static unsigned long ccu_mdiv_recalc_rate(struct clk_hw *hw,
> +					unsigned long parent_rate)
> +{
> +	struct ccu_mdiv *mdiv = hw_to_ccu_mdiv(hw);
> +	unsigned long div, rate = parent_rate;
> +	unsigned int m, d, i, v, val;
> +
> +	regmap_read(mdiv->common.map, mdiv->common.reg, &val);
> +
> +	m = val >> mdiv->m.shift;
> +	m &= GENMASK(mdiv->m.width - 1, 0);
> +
> +	d = val >> mdiv->d.shift;
> +	d &= GENMASK(mdiv->d.width - 1, 0);
> +
> +	i = val >> mdiv->i.shift;
> +	i &= GENMASK(mdiv->i.width - 1, 0);
> +
> +	v = val >> mdiv->v.shift;
> +	v &= GENMASK(mdiv->v.width - 1, 0);
> +
> +	rate = parent_rate * m;
> +	div = d * i * v;
> +	do_div(rate, div);
> +
> +	return rate;
> +}
> +
> +static const struct clk_ops clk_mdiv_ops = {
> +	.recalc_rate	= ccu_mdiv_recalc_rate,
> +};
> +
> +static struct ccu_mdiv pll_cpu0_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x000,
> +		.hw.init	= CLK_HW_INIT("pll-cpu0", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_mdiv pll_cpu1_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x010,
> +		.hw.init	= CLK_HW_INIT("pll-cpu1", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_mdiv pll_gmac_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x020,
> +		.hw.init	= CLK_HW_INIT("pll-gmac", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_mdiv pll_video_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x030,
> +		.hw.init	= CLK_HW_INIT("pll-video", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_mdiv pll_dpu0_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x040,
> +		.hw.init	= CLK_HW_INIT("pll-dpu0", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_mdiv pll_dpu1_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x050,
> +		.hw.init	= CLK_HW_INIT("pll-dpu1", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_mdiv pll_tee_clk = {
> +	.m		= TH_CCU_ARG(8, 12),
> +	.d		= TH_CCU_ARG(24, 3),
> +	.i		= TH_CCU_ARG(20, 3),
> +	.v		= TH_CCU_ARG(0, 6),
> +	.common		= {
> +		.reg		= 0x060,
> +		.hw.init	= CLK_HW_INIT("pll-tee", "osc24m",
> +					      &clk_mdiv_ops,
> +					      0),
> +	},
> +};
> +
> +static const char * const c910_i0_parents[] = { "pll-cpu0", "osc24m" };
> +struct ccu_mux c910_i0_clk = {
> +	.mux	= TH_CCU_ARG(1, 1),
> +	.common	= {
> +		.reg		= 00100,
> +		.hw.init	= CLK_HW_INIT_PARENTS("c910-i0",
> +					      c910_i0_parents,
> +					      &ccu_mux_ops,
> +					      0),
> +	}
> +};
> +
> +static const char * const c910_parents[] = { "c910-i0", "pll-cpu1" };
> +struct ccu_mux c910_clk = {
> +	.mux	= TH_CCU_ARG(0, 1),
> +	.common	= {
> +		.reg		= 0x100,
> +		.hw.init	= CLK_HW_INIT_PARENTS("c910",
> +					      c910_parents,
> +					      &ccu_mux_ops,
> +					      0),
> +	}
> +};
> +
> +static CCU_GATE(brom_clk, "brom", "ahb2",
> +		0x100, BIT(4), 0);
> +
> +static CCU_GATE(bmu_clk, "bmu", "axi4",
> +		0x100, BIT(5), 0);
> +
> +static const char * const ahb2_parents[] = { "pll-gmac", "osc24m" };
> +static struct ccu_div ahb2_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(5, 1),
> +	.common		= {
> +		.reg		= 0x120,
> +		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
> +						      ahb2_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static struct ccu_div apb3_clk = {
> +	.div		= TH_CCU_ARG(0, 3),
> +	.common		= {
> +		.reg		= 0x130,
> +		.hw.init	= CLK_HW_INIT("apb3", "ahb2",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div axi4_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x134,
> +		.hw.init	= CLK_HW_INIT("axi4", "pll-gmac",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static CCU_GATE(aon2cpu_clk, "aon2cpu", "axi4",
> +		0x134, BIT(8), 0);
> +
> +static CCU_GATE(x2x_clk, "x2x", "axi4",
> +		0x134, BIT(7), 0);
> +
> +static const char * const axi_parents[] = { "pll-video", "osc24m" };
> +static struct ccu_div axi_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(5, 1),
> +	.common		= {
> +		.reg		= 0x138,
> +		.hw.init	= CLK_HW_INIT_PARENTS("axi",
> +						      axi_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static CCU_GATE(cpu2aon_clk, "cpu2aon", "axi",
> +		0x138, BIT(8), 0);
> +
> +static const char * const peri_ahb_parents[] = { "pll-gmac", "osc24m" };
> +static struct ccu_div peri_ahb_clk = {
> +	.enable		= BIT(6),
> +	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(5, 1),
> +	.common		= {
> +		.reg		= 0x140,
> +		.hw.init	= CLK_HW_INIT_PARENTS("peri-ahb",
> +						      peri_ahb_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static CCU_GATE(cpu2peri_clk, "cpu2peri", "axi4",
> +		0x140, BIT(9), 0);
> +
> +static struct ccu_div peri_apb_clk = {
> +	.div		= TH_CCU_ARG(0, 3),
> +	.common		= {
> +		.reg		= 0x150,
> +		.hw.init	= CLK_HW_INIT("peri-apb", "peri-ahb",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div peri2apb_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x150,
> +		.hw.init	= CLK_HW_INIT("peri2apb",
> +					      "pll-gmac",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static CCU_GATE(peri_apb1_clk, "peri-apb1", "peri-ahb",
> +		0x150, BIT(9), 0);
> +
> +static CCU_GATE(peri_apb2_clk, "peri-apb2", "peri-ahb",
> +		0x150, BIT(10), 0);
> +
> +static CCU_GATE(peri_apb3_clk, "peri-apb3", "peri-ahb",
> +		0x150, BIT(11), 0);
> +
> +static CCU_GATE(peri_apb4_clk, "peri-apb4", "peri-ahb",
> +		0x150, BIT(12), 0);
> +
> +static CLK_FIXED_FACTOR_FW_NAME(osc12m_clk, "osc12m", "hosc", 2, 1, 0);
> +
> +static const char * const out_parents[] = { "osc24m", "osc12m" };
> +
> +static struct ccu_div out1_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(4, 1),
> +	.common		= {
> +		.reg		= 0x1b4,
> +		.hw.init	= CLK_HW_INIT_PARENTS("out1",
> +						      out_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static struct ccu_div out2_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(4, 1),
> +	.common		= {
> +		.reg		= 0x1b8,
> +		.hw.init	= CLK_HW_INIT_PARENTS("out2",
> +						      out_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static struct ccu_div out3_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(4, 1),
> +	.common		= {
> +		.reg		= 0x1bc,
> +		.hw.init	= CLK_HW_INIT_PARENTS("out3",
> +						      out_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static struct ccu_div out4_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(4, 1),
> +	.common		= {
> +		.reg		= 0x1c0,
> +		.hw.init	= CLK_HW_INIT_PARENTS("out4",
> +						      out_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static const char * const apb_parents[] = { "pll-gmac", "osc24m" };
> +static struct ccu_div apb_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(7, 1),
> +	.common		= {
> +		.reg		= 0x1c4,
> +		.hw.init	= CLK_HW_INIT_PARENTS("apb",
> +						      apb_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static const char * const npu_parents[] = { "pll-gmac", "pll-video" };
> +static struct ccu_div npu_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.mux		= TH_CCU_ARG(6, 1),
> +	.common		= {
> +		.reg		= 0x1c8,
> +		.hw.init	= CLK_HW_INIT_PARENTS("npu",
> +						      npu_parents,
> +						      &ccu_div_ops,
> +						      0),
> +	},
> +};
> +
> +static struct ccu_div vi_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1d0,
> +		.hw.init	= CLK_HW_INIT("vi",
> +					      "pll-video",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div vi_ahb_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1d0,
> +		.hw.init	= CLK_HW_INIT("vi-ahb",
> +					      "pll-video",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div vo_axi_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1dc,
> +		.hw.init	= CLK_HW_INIT("vo-axi",
> +					      "pll-video",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div vp_apb_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1e0,
> +		.hw.init	= CLK_HW_INIT("vp-apb",
> +					      "pll-gmac",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div vp_axi_clk = {
> +	.enable		= BIT(15),
> +	.div		= TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1e0,
> +		.hw.init	= CLK_HW_INIT("vp-axi",
> +					      "pll-video",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static CCU_GATE(cpu2vp_clk, "cpu2vp", "axi",
> +		0x1e0, BIT(13), 0);
> +
> +static struct ccu_div venc_clk = {
> +	.enable		= BIT(5),
> +	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1e4,
> +		.hw.init	= CLK_HW_INIT("venc",
> +					      "pll-gmac",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div dpu0_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1e8,
> +		.hw.init	= CLK_HW_INIT("dpu0",
> +					      "pll-dpu0",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static struct ccu_div dpu1_clk = {
> +	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
> +	.common		= {
> +		.reg		= 0x1ec,
> +		.hw.init	= CLK_HW_INIT("dpu1",
> +					      "pll-dpu1",
> +					      &ccu_div_ops,
> +					      0),
> +	},
> +};
> +
> +static CCU_GATE(mmc_clk, "mmc", "pll-video", 0x204, BIT(30), 0);
> +static CCU_GATE(gmac1_clk, "gmac1", "pll-gmac", 0x204, BIT(26), 0);
> +static CCU_GATE(padctrl1_clk, "padctrl1", "peri-apb", 0x204, BIT(24), 0);
> +static CCU_GATE(dsmart_clk, "dsmart", "peri-apb", 0x204, BIT(23), 0);
> +static CCU_GATE(padctrl0_clk, "padctrl0", "peri-apb", 0x204, BIT(22), 0);
> +static CCU_GATE(gmac_axi_clk, "gmac-axi", "axi4", 0x204, BIT(21), 0);
> +static CCU_GATE(gmac0_clk, "gmac0", "pll-gmac", 0x204, BIT(19), 0);
> +static CCU_GATE(pwm_clk, "pwm", "peri-apb", 0x204, BIT(18), 0);
> +static CCU_GATE(qspi0_clk, "qspi0", "pll-video", 0x204, BIT(17), 0);
> +static CCU_GATE(qspi1_clk, "qspi1", "pll-video", 0x204, BIT(16), 0);
> +static CCU_GATE(spi_clk, "spi", "pll-video", 0x204, BIT(15), 0);
> +static CCU_GATE(uart0_clk, "uart0", "peri-apb", 0x204, BIT(14), 0);
> +static CCU_GATE(uart1_clk, "uart1", "peri-apb", 0x204, BIT(13), 0);
> +static CCU_GATE(uart2_clk, "uart2", "peri-apb", 0x204, BIT(12), 0);
> +static CCU_GATE(uart3_clk, "uart3", "peri-apb", 0x204, BIT(11), 0);
> +static CCU_GATE(uart4_clk, "uart4", "peri-apb", 0x204, BIT(10), 0);
> +static CCU_GATE(uart5_clk, "uart5", "peri-apb", 0x204, BIT(9), 0);
> +static CCU_GATE(i2c0_clk, "i2c0", "peri-apb", 0x204, BIT(5), 0);
> +static CCU_GATE(i2c1_clk, "i2c1", "peri-apb", 0x204, BIT(4), 0);
> +static CCU_GATE(i2c2_clk, "i2c2", "peri-apb", 0x204, BIT(3), 0);
> +static CCU_GATE(i2c3_clk, "i2c3", "peri-apb", 0x204, BIT(2), 0);
> +static CCU_GATE(i2c4_clk, "i2c4", "peri-apb", 0x204, BIT(1), 0);
> +static CCU_GATE(i2c5_clk, "i2c5", "peri-apb", 0x204, BIT(0), 0);
> +
> +static CCU_GATE(spinlock_clk, "spinlock", "ahb2", 0x208, BIT(10), 0);
> +static CCU_GATE(dma_clk, "dma", "axi4", 0x208, BIT(8), 0);
> +static CCU_GATE(mbox0_clk, "mbox0", "apb3", 0x208, BIT(7), 0);
> +static CCU_GATE(mbox1_clk, "mbox1", "apb3", 0x208, BIT(6), 0);
> +static CCU_GATE(mbox2_clk, "mbox2", "apb3", 0x208, BIT(5), 0);
> +static CCU_GATE(mbox3_clk, "mbox3", "apb3", 0x208, BIT(4), 0);
> +static CCU_GATE(wdt0_clk, "wdt0", "apb3", 0x208, BIT(3), 0);
> +static CCU_GATE(wdt1_clk, "wdt1", "apb3", 0x208, BIT(2), 0);
> +static CCU_GATE(timer0_clk, "timer0", "apb3", 0x208, BIT(1), 0);
> +static CCU_GATE(timer1_clk, "timer1", "apb3", 0x208, BIT(0), 0);
> +
> +static CCU_GATE(sram0_clk, "sram0", "axi", 0x20c, BIT(4), 0);
> +static CCU_GATE(sram1_clk, "sram1", "axi", 0x20c, BIT(3), 0);
> +static CCU_GATE(sram2_clk, "sram2", "axi", 0x20c, BIT(2), 0);
> +static CCU_GATE(sram3_clk, "sram3", "axi", 0x20c, BIT(1), 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_gmac_100m_clk, "pll-gmac-100m",
> +			   &pll_gmac_clk.common.hw,
> +			   10, 1, 0);
> +
> +static const char * const uart_parents[] = { "pll-gmac-100m", "osc24m" };
> +struct ccu_mux uart_clk = {
> +	.mux	= TH_CCU_ARG(0, 1),
> +	.common	= {
> +		.reg		= 0x210,
> +		.hw.init	= CLK_HW_INIT_PARENTS("uart",
> +					      uart_parents,
> +					      &ccu_mux_ops,
> +					      0),
> +	}
> +};
> +
> +static struct ccu_common *th1520_clks[] = {
> +	&pll_cpu0_clk.common,
> +	&pll_cpu1_clk.common,
> +	&pll_gmac_clk.common,
> +	&pll_video_clk.common,
> +	&pll_dpu0_clk.common,
> +	&pll_dpu1_clk.common,
> +	&pll_tee_clk.common,
> +	&c910_i0_clk.common,
> +	&c910_clk.common,
> +	&brom_clk.common,
> +	&bmu_clk.common,
> +	&ahb2_clk.common,
> +	&apb3_clk.common,
> +	&axi4_clk.common,
> +	&aon2cpu_clk.common,
> +	&x2x_clk.common,
> +	&axi_clk.common,
> +	&cpu2aon_clk.common,
> +	&peri_ahb_clk.common,
> +	&cpu2peri_clk.common,
> +	&peri_apb_clk.common,
> +	&peri2apb_clk.common,
> +	&peri_apb1_clk.common,
> +	&peri_apb2_clk.common,
> +	&peri_apb3_clk.common,
> +	&peri_apb4_clk.common,
> +	&out1_clk.common,
> +	&out2_clk.common,
> +	&out3_clk.common,
> +	&out4_clk.common,
> +	&apb_clk.common,
> +	&npu_clk.common,
> +	&vi_clk.common,
> +	&vi_ahb_clk.common,
> +	&vo_axi_clk.common,
> +	&vp_apb_clk.common,
> +	&vp_axi_clk.common,
> +	&cpu2vp_clk.common,
> +	&venc_clk.common,
> +	&dpu0_clk.common,
> +	&dpu1_clk.common,
> +	&mmc_clk.common,
> +	&gmac1_clk.common,
> +	&padctrl1_clk.common,
> +	&dsmart_clk.common,
> +	&padctrl0_clk.common,
> +	&gmac_axi_clk.common,
> +	&gmac0_clk.common,
> +	&pwm_clk.common,
> +	&qspi0_clk.common,
> +	&qspi1_clk.common,
> +	&spi_clk.common,
> +	&uart0_clk.common,
> +	&uart1_clk.common,
> +	&uart2_clk.common,
> +	&uart3_clk.common,
> +	&uart4_clk.common,
> +	&uart5_clk.common,
> +	&i2c0_clk.common,
> +	&i2c1_clk.common,
> +	&i2c2_clk.common,
> +	&i2c3_clk.common,
> +	&i2c4_clk.common,
> +	&i2c5_clk.common,
> +	&spinlock_clk.common,
> +	&dma_clk.common,
> +	&mbox0_clk.common,
> +	&mbox1_clk.common,
> +	&mbox2_clk.common,
> +	&mbox3_clk.common,
> +	&wdt0_clk.common,
> +	&wdt1_clk.common,
> +	&timer0_clk.common,
> +	&timer1_clk.common,
> +	&sram0_clk.common,
> +	&sram1_clk.common,
> +	&sram2_clk.common,
> +	&sram3_clk.common,
> +	&uart_clk.common,
> +};
> +
> +#define NR_CLKS	(CLK_UART + 1)
> +
> +static struct clk_hw_onecell_data th1520_hw_clks = {
> +	.hws	= {
> +		[CLK_OSC12M]		= &osc12m_clk.hw,
> +		[CLK_PLL_CPU0]		= &pll_cpu0_clk.common.hw,
> +		[CLK_PLL_CPU1]		= &pll_cpu1_clk.common.hw,
> +		[CLK_PLL_GMAC]		= &pll_gmac_clk.common.hw,
> +		[CLK_PLL_VIDEO]		= &pll_video_clk.common.hw,
> +		[CLK_PLL_DPU0]		= &pll_dpu0_clk.common.hw,
> +		[CLK_PLL_DPU1]		= &pll_dpu1_clk.common.hw,
> +		[CLK_PLL_TEE]		= &pll_tee_clk.common.hw,
> +		[CLK_C910_I0]		= &c910_i0_clk.common.hw,
> +		[CLK_C910]		= &c910_clk.common.hw,
> +		[CLK_BROM]		= &brom_clk.common.hw,
> +		[CLK_BMU]		= &bmu_clk.common.hw,
> +		[CLK_AHB2]		= &ahb2_clk.common.hw,
> +		[CLK_APB3]		= &apb3_clk.common.hw,
> +		[CLK_AXI4]		= &axi4_clk.common.hw,
> +		[CLK_AON2CPU]		= &aon2cpu_clk.common.hw,
> +		[CLK_X2X]		= &x2x_clk.common.hw,
> +		[CLK_AXI]		= &axi_clk.common.hw,
> +		[CLK_CPU2AON]		= &cpu2aon_clk.common.hw,
> +		[CLK_PERI_AHB]		= &peri_ahb_clk.common.hw,
> +		[CLK_CPU2PERI]		= &cpu2peri_clk.common.hw,
> +		[CLK_PERI_APB]		= &peri_apb_clk.common.hw,
> +		[CLK_PERI2APB]		= &peri2apb_clk.common.hw,
> +		[CLK_PERI_APB1]		= &peri_apb1_clk.common.hw,
> +		[CLK_PERI_APB2]		= &peri_apb2_clk.common.hw,
> +		[CLK_PERI_APB3]		= &peri_apb3_clk.common.hw,
> +		[CLK_PERI_APB4]		= &peri_apb4_clk.common.hw,
> +		[CLK_OUT1]		= &out1_clk.common.hw,
> +		[CLK_OUT2]		= &out2_clk.common.hw,
> +		[CLK_OUT3]		= &out3_clk.common.hw,
> +		[CLK_OUT4]		= &out4_clk.common.hw,
> +		[CLK_APB]		= &apb_clk.common.hw,
> +		[CLK_NPU]		= &npu_clk.common.hw,
> +		[CLK_VI]		= &vi_clk.common.hw,
> +		[CLK_VI_AHB]		= &vi_ahb_clk.common.hw,
> +		[CLK_VO_AXI]		= &vo_axi_clk.common.hw,
> +		[CLK_VP_APB]		= &vp_apb_clk.common.hw,
> +		[CLK_VP_AXI]		= &vp_axi_clk.common.hw,
> +		[CLK_CPU2VP]		= &cpu2vp_clk.common.hw,
> +		[CLK_VENC]		= &venc_clk.common.hw,
> +		[CLK_DPU0]		= &dpu0_clk.common.hw,
> +		[CLK_DPU1]		= &dpu1_clk.common.hw,
> +		[CLK_MMC]		= &mmc_clk.common.hw,
> +		[CLK_GMAC]		= &gmac1_clk.common.hw,
> +		[CLK_PADCTRL1]		= &padctrl1_clk.common.hw,
> +		[CLK_DSMART]		= &dsmart_clk.common.hw,
> +		[CLK_PADCTRL0]		= &padctrl0_clk.common.hw,
> +		[CLK_GMAC_AXI]		= &gmac_axi_clk.common.hw,
> +		[CLK_GMAC0]		= &gmac0_clk.common.hw,
> +		[CLK_PWM]		= &pwm_clk.common.hw,
> +		[CLK_QSPI0]		= &qspi0_clk.common.hw,
> +		[CLK_QSPI1]		= &qspi1_clk.common.hw,
> +		[CLK_SPI]		= &spi_clk.common.hw,
> +		[CLK_UART0]		= &uart0_clk.common.hw,
> +		[CLK_UART1]		= &uart1_clk.common.hw,
> +		[CLK_UART2]		= &uart2_clk.common.hw,
> +		[CLK_UART3]		= &uart3_clk.common.hw,
> +		[CLK_UART4]		= &uart4_clk.common.hw,
> +		[CLK_UART5]		= &uart5_clk.common.hw,
> +		[CLK_I2C0]		= &i2c0_clk.common.hw,
> +		[CLK_I2C1]		= &i2c1_clk.common.hw,
> +		[CLK_I2C2]		= &i2c2_clk.common.hw,
> +		[CLK_I2C3]		= &i2c3_clk.common.hw,
> +		[CLK_I2C4]		= &i2c4_clk.common.hw,
> +		[CLK_I2C5]		= &i2c5_clk.common.hw,
> +		[CLK_SPINLOCK]		= &spinlock_clk.common.hw,
> +		[CLK_DMA]		= &dma_clk.common.hw,
> +		[CLK_MBOX0]		= &mbox0_clk.common.hw,
> +		[CLK_MBOX1]		= &mbox1_clk.common.hw,
> +		[CLK_MBOX2]		= &mbox2_clk.common.hw,
> +		[CLK_MBOX3]		= &mbox3_clk.common.hw,
> +		[CLK_WDT0]		= &wdt0_clk.common.hw,
> +		[CLK_WDT1]		= &wdt1_clk.common.hw,
> +		[CLK_TIMER0]		= &timer0_clk.common.hw,
> +		[CLK_TIMER1]		= &timer1_clk.common.hw,
> +		[CLK_SRAM0]		= &sram0_clk.common.hw,
> +		[CLK_SRAM1]		= &sram1_clk.common.hw,
> +		[CLK_SRAM2]		= &sram2_clk.common.hw,
> +		[CLK_SRAM3]		= &sram3_clk.common.hw,
> +		[CLK_PLL_GMAC_100M]	= &pll_gmac_100m_clk.hw,
> +		[CLK_UART]		= &uart_clk.common.hw,
> +	},
> +	.num = NR_CLKS,
> +};
> +
> +static const struct regmap_config config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.fast_io = true,
> +};
> +
> +static int th1520_clock_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct regmap *map;
> +	void __iomem *regs;
> +	int ret, i;
> +
> +	regs = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	map = devm_regmap_init_mmio(dev, regs, &config);
> +	if (IS_ERR(map))
> +		return PTR_ERR(map);
> +
> +	for (i = 0; i < ARRAY_SIZE(th1520_clks); i++)
> +		th1520_clks[i]->map = map;
> +
> +	for (i = 0; i < th1520_hw_clks.num; i++) {
> +		ret = devm_clk_hw_register(dev, th1520_hw_clks.hws[i]);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> +					&th1520_hw_clks);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id clk_match_table[] = {
> +	{
> +		.compatible = "thead,th1520-ccu",
> +	},
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, clk_match_table);
> +
> +static struct platform_driver th1520_clk_driver = {
> +	.probe		= th1520_clock_probe,
> +	.driver		= {
> +		.name	= "th1520-clk",
> +		.of_match_table = clk_match_table,
> +	},
> +};
> +module_platform_driver(th1520_clk_driver);
> +
> +MODULE_DESCRIPTION("T-HEAD th1520 Clock driver");
> +MODULE_AUTHOR("Yangtao Li <frank.li@vivo.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/include/dt-bindings/clock/th1520-clock.h b/include/dt-bindings/clock/th1520-clock.h
> new file mode 100644
> index 000000000000..e5a1e1c127fc
> --- /dev/null
> +++ b/include/dt-bindings/clock/th1520-clock.h
> @@ -0,0 +1,92 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.
> + * Authors: Yangtao Li <frank.li@vivo.com>
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_TH1520_H_
> +#define _DT_BINDINGS_CLK_TH1520_H_
> +
> +#define CLK_PLL_CPU0		0
> +#define CLK_PLL_CPU1		1
> +#define CLK_PLL_GMAC		2
> +#define CLK_PLL_VIDEO		3
> +#define CLK_PLL_DPU0		4
> +#define CLK_PLL_DPU1		5
> +#define CLK_PLL_TEE		6
> +#define CLK_C910_I0		7
> +#define CLK_C910		8
> +#define CLK_BROM		9
> +#define CLK_BMU			10
> +#define CLK_AHB2		11
> +#define CLK_APB3		12
> +#define CLK_AXI4		13
> +#define CLK_AON2CPU		14
> +#define CLK_X2X			15
> +#define CLK_AXI			16
> +#define CLK_CPU2AON		17
> +#define CLK_PERI_AHB		18
> +#define CLK_CPU2PERI		19
> +#define CLK_PERI_APB		20
> +#define CLK_PERI2APB		21
> +#define CLK_PERI_APB1		22
> +#define CLK_PERI_APB2		23
> +#define CLK_PERI_APB3		24
> +#define CLK_PERI_APB4		25
> +#define CLK_OSC12M		26
> +#define CLK_OUT1		27
> +#define CLK_OUT2		28
> +#define CLK_OUT3		29
> +#define CLK_OUT4		30
> +#define CLK_APB			31
> +#define CLK_NPU			32
> +#define CLK_VI			33
> +#define CLK_VI_AHB		34
> +#define CLK_VO_AXI		35
> +#define CLK_VP_APB		36
> +#define CLK_VP_AXI		37
> +#define CLK_CPU2VP		38
> +#define CLK_VENC		39
> +#define CLK_DPU0		40
> +#define CLK_DPU1		41
> +#define CLK_MMC			42
> +#define CLK_GMAC		43
> +#define CLK_PADCTRL1		44
> +#define CLK_DSMART		45
> +#define CLK_PADCTRL0		46
> +#define CLK_GMAC_AXI		47
> +#define CLK_GMAC0		48
> +#define CLK_PWM			49
> +#define CLK_QSPI0		50
> +#define CLK_QSPI1		51
> +#define CLK_SPI			52
> +#define CLK_UART0		53
> +#define CLK_UART1		54
> +#define CLK_UART2		55
> +#define CLK_UART3		56
> +#define CLK_UART4		57
> +#define CLK_UART5		58
> +#define CLK_I2C0		59
> +#define CLK_I2C1		60
> +#define CLK_I2C2		61
> +#define CLK_I2C3		62
> +#define CLK_I2C4		63
> +#define CLK_I2C5		64
> +#define CLK_SPINLOCK		65
> +#define CLK_DMA			66
> +#define CLK_MBOX0		67
> +#define CLK_MBOX1		68
> +#define CLK_MBOX2		69
> +#define CLK_MBOX3		70
> +#define CLK_WDT0		71
> +#define CLK_WDT1		72
> +#define CLK_TIMER0		73
> +#define CLK_TIMER1		74
> +#define CLK_SRAM0		75
> +#define CLK_SRAM1		76
> +#define CLK_SRAM2		77
> +#define CLK_SRAM3		78
> +#define CLK_PLL_GMAC_100M	79
> +#define CLK_UART		80
> +
> +#endif
> -- 
> 2.39.0
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU
  2023-08-27 10:37   ` Jisheng Zhang
@ 2023-09-03 22:37     ` Drew Fustini
  0 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-09-03 22:37 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: Yangtao Li, devicetree, Conor Dooley, sboyd, mturquette,
	linux-kernel, Rob Herring, Krzysztof Kozlowski, linux-riscv,
	linux-clk, Wei Fu

On Sun, Aug 27, 2023 at 06:37:21PM +0800, Jisheng Zhang wrote:
> On Mon, May 15, 2023 at 01:44:00PM +0800, Yangtao Li wrote:
> > Add support for th1520 in the clock framework.
> 
> Hi Yangtao,
> 
> I didn't see any new version of this series in this development window,
> and we have already talked about it several times on wechat, so do
> you still plan to renew this series? If not, I will update it and may
> rewrite the code once next development window is open.
> 
> Thanks in advance

I tried this clock driver on the BeagleV Ahead board and I got the
following during boot [1]:

  __clk_core_init: ahb2 must implement .set_parent & .determine_rate
  th1520-clk: probe of ffef010000.clock-controller failed with error -22

I am guessing this has to do with how ahb2_clk is defined?

 432 static struct ccu_div ahb2_clk = {
 433         .div            = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),
 434         .mux            = TH_CCU_ARG(5, 1),
 435         .common         = {
 436                 .reg            = 0x120,                      
 437                 .hw.init        = CLK_HW_INIT_PARENTS("ahb2",
 438                                                       ahb2_parents,
 439                                                       &ccu_div_ops,
 440                                                       0),
 441         },
 442 };

It passes ccu_div_ops in CLK_HW_INIT_PARENTS(). ccu_div_ops does
implement .set_parent but it doesn't implement .determine_rate. Maybe
that is the problem?

Yangtao or Jisheng: would you be able to share the device tree you're
using?

I added this based on the example in the device tree binding:
=============================================================
diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi
index 18761a06c866..8153bf73e8c0 100644
--- a/arch/riscv/boot/dts/thead/th1520.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520.dtsi
@@ -313,6 +313,14 @@ dmac0: dma-controller@ffefc00000 {
                        status = "disabled";
                };
 
+               clk: clock-controller@ffef010000 {
+                       compatible = "thead,th1520-ccu";
+                       reg = <0xff 0xef010000 0x0 0x1000>;
+                       clocks = <&osc_32k>, <&osc>;
+                       clock-names = "losc", "hosc";
+                       #clock-cells = <1>;
+               };
+
                mmc0: mmc@ffe7080000 {
                        compatible = "thead,th1520-dwcmshc";
                        reg = <0xff 0xe7080000 0x0 0x10000

=============================================================

Thank you,
Drew

[1] https://gist.github.com/pdp7/b585a6dad5134fc8773e53ad48600fef

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2023-09-03 22:37 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-15  5:43 [PATCH 0/3] Add T-HEAD th1520 soc clock support Yangtao Li
2023-05-15  5:43 ` [PATCH 1/3] dt-bindings: clock: Add thead th1520 clock Yangtao Li
2023-05-15  6:22   ` Krzysztof Kozlowski
2023-05-15  6:26   ` Krzysztof Kozlowski
2023-05-15  5:44 ` [PATCH 2/3] clk: thead: add support for the T-HEAD TH1520 CCU Yangtao Li
2023-05-15  6:27   ` Krzysztof Kozlowski
2023-06-13  1:35   ` Stephen Boyd
2023-08-27 10:37   ` Jisheng Zhang
2023-09-03 22:37     ` Drew Fustini
2023-05-15  5:44 ` [PATCH 3/3] MAINTAINERS: update entry for T-HEAD RISC-V SoC Yangtao Li
2023-05-15 17:15   ` Conor Dooley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).