linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/3] Add driver support for ESWIN eic700 SoC clock controller
@ 2025-08-15  9:35 dongxuyang
  2025-08-15  9:36 ` [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC dongxuyang
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: dongxuyang @ 2025-08-15  9:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, paul.walmsley, palmer, aou, alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela, Xuyang Dong

From: Xuyang Dong <dongxuyang@eswincomputing.com>

This series depends on the vendor prefix patch [1] and config option patch [2].

[1] https://lore.kernel.org/all/20250616112316.3833343-4-pinkesh.vaghela@einfochips.com/
[2] https://lore.kernel.org/all/20250616112316.3833343-3-pinkesh.vaghela@einfochips.com/

Updates:

  Changes in v4:
  - Updated YAML file
    - Changed name from cpu-default-frequency to cpu-default-freq-hz.
    - Dropped $ref of cpu-default-frequency.
    - Added cpu-default-frequency for required.
    - Removed cpu-default-frequency in updated file, because there was no
      need to add cpu-default-frequency.
    - Moved DIVIDER to DIV.
    - Arranged the IDs in order.
    - Dropped EIC7700_NR_CLKS.
    - Removed dt-bindings eswin,eic7700-clock.h. Because IDs was not used,
      and used clock device nodes.
    - According to the updated driver codes, the YAML has been updated.
  - Updated driver file
    - Remove undocumented parameters "cpu_no_boost_1_6ghz" and
      "cpu-default-frequency".
    - Modified the comment and used the correct Linux coding style.
    - Removed codes of voltage, because it was not the clock driver.
    - Updated the formula of clock frequency calculation. Removed the logic
      that only used register selection.
    - Used CLK_OF_DECLARE() to register clocks. Registered pll-clock,
      mux-clock, divider-clock, and gate-clock in clk-eic7700.c.
      The specific implementation of clock registration was in clk.c.
    - Added eic7700-clocks.dtsi.
    - Moved device information to DTS. Put all clocks' node in the
      eic7700-clocks.dtsi.

  - Link to v3: https://lore.kernel.org/all/20250624103212.287-1-dongxuyang@eswincomputing.com/

  Changes in v3:
  - Update example, drop child node and add '#clock-cells' to the parent
    node.
  - Change parent node from sys-crg to clock-controller for this yaml.
  - Drop "syscon", "simple-mfd" to clear warnings/errors by using "make
    dt_binding_check". And these are not necessary.
  - Add "cpu-default-frequency" definition in yaml for "undocumented ABI".
  - Drop Reviewed-by, this is misunderstanding. We have not received such
    an email.
  - Link to v2: https://lore.kernel.org/all/20250523090747.1830-1-dongxuyang@eswincomputing.com/

  Changes in v2:
  - Update example, drop child node.
  - Clear warnings/errors for using "make dt_binding_check".
  - Change to the correct format.
  - Drop some non-stanard code.
  - Use dev_err_probe() in probe functions.
  - Link to v1: https://lore.kernel.org/all/20250514002233.187-1-dongxuyang@eswincomputing.com/

Xuyang Dong (3):
  clock: eswin: Documentation for eic7700 SoC
  clock: eswin: Add eic7700 clock driver
  riscv: dts: eswin: Add clock driver support

 .../bindings/clock/eswin,eic7700-clock.yaml   |  381 +++
 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi | 2283 +++++++++++++++++
 drivers/clk/Kconfig                           |    1 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/eswin/Kconfig                     |   10 +
 drivers/clk/eswin/Makefile                    |    8 +
 drivers/clk/eswin/clk-eic7700.c               |   44 +
 drivers/clk/eswin/clk.c                       |  734 ++++++
 drivers/clk/eswin/clk.h                       |   69 +
 9 files changed, 3531 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
 create mode 100644 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
 create mode 100644 drivers/clk/eswin/Kconfig
 create mode 100644 drivers/clk/eswin/Makefile
 create mode 100644 drivers/clk/eswin/clk-eic7700.c
 create mode 100644 drivers/clk/eswin/clk.c
 create mode 100644 drivers/clk/eswin/clk.h

--
2.17.1


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

* [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC
  2025-08-15  9:35 [PATCH v4 0/3] Add driver support for ESWIN eic700 SoC clock controller dongxuyang
@ 2025-08-15  9:36 ` dongxuyang
  2025-08-17  6:01   ` Krzysztof Kozlowski
  2025-08-15  9:37 ` [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver dongxuyang
  2025-08-15  9:37 ` [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support dongxuyang
  2 siblings, 1 reply; 13+ messages in thread
From: dongxuyang @ 2025-08-15  9:36 UTC (permalink / raw)
  To: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, paul.walmsley, palmer, aou, alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela, Xuyang Dong

From: Xuyang Dong <dongxuyang@eswincomputing.com>

Add device tree binding documentation for the ESWIN eic7700
clock controller module.

Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
---
 .../bindings/clock/eswin,eic7700-clock.yaml   | 381 ++++++++++++++++++
 1 file changed, 381 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml

diff --git a/Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml b/Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
new file mode 100644
index 000000000000..45e70ebc08e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
@@ -0,0 +1,381 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/eswin,eic7700-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Eswin EIC7700 SoC clock controller
+
+maintainers:
+  - Yifeng Huang <huangyifeng@eswincomputing.com>
+  - Xuyang Dong <dongxuyang@eswincomputing.com>
+
+description:
+  The clock controller generates and supplies clock to all the modules
+  for eic7700 SoC.
+
+properties:
+  compatible:
+    const: eswin,eic7700-clock
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 0
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+  - '#address-cells'
+  - '#size-cells'
+
+patternProperties:
+  "^fixed-rate.*":
+    type: object
+    $ref: /schemas/clock/fixed-clock.yaml#
+
+  ".*pll@[a-f0-9]+$":
+    type: object
+
+    properties:
+      compatible:
+        const: eswin,pll-clock
+
+      reg:
+        items:
+          - description: PLL's config 0 register
+          - description: PLL's config 1 register
+          - description: PLL's config 2 register
+          - description: PLL's status register
+
+      '#clock-cells':
+        const: 0
+
+      clock-output-names:
+        maxItems: 1
+
+      enable-shift:
+        description: Bit shift of the enable register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      enable-width:
+        description: Width of the enable register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      refdiv-shift:
+        description: Bit shift of the reference divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      refdiv-width:
+        description: Width of the reference divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      fbdiv-shift:
+        description: Bit shift of the feedback divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      fbdiv-width:
+        description: Width of the feedback divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      frac-shift:
+        description: Bit shift of the fractional divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      frac-width:
+        description: Width of the fractional divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      postdiv1-shift:
+        description: Bit shift of the post divider 1 register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      postdiv1-width:
+        description: Width of the post divider 1 register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      postdiv2-shift:
+        description: Bit shift of the post divider 2 register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      postdiv2-width:
+        description: Width of the post divider 2 register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        maximum: 31
+
+      lock-shift:
+        description: Bit shift of the lock register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      lock-width:
+        description: Width of the lock register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+    required:
+      - compatible
+      - reg
+      - '#clock-cells'
+      - clock-output-names
+      - enable-shift
+      - enable-width
+      - refdiv-shift
+      - refdiv-width
+      - fbdiv-shift
+      - fbdiv-width
+      - frac-shift
+      - frac-width
+      - postdiv1-shift
+      - postdiv1-width
+      - postdiv2-shift
+      - postdiv2-width
+      - lock-shift
+      - lock-width
+
+    additionalProperties: false
+
+  ".*mux@[a-f0-9]+$":
+    type: object
+
+    properties:
+      compatible:
+        const: eswin,mux-clock
+
+      reg:
+        maxItems: 1
+
+      clocks:
+        minItems: 2
+        maxItems: 3
+
+      '#clock-cells':
+        const: 0
+
+      clock-output-names:
+        maxItems: 1
+
+      shift:
+        description: Bit shift of the select register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      width:
+        description: Width of the select register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+
+    required:
+      - compatible
+      - reg
+      - clocks
+      - '#clock-cells'
+      - clock-output-names
+      - shift
+      - width
+
+    additionalProperties: false
+
+  "^fixed-factor.*":
+    type: object
+    $ref: /schemas/clock/fixed-factor-clock.yaml#
+
+  ".*div@[a-f0-9]+$":
+    type: object
+
+    properties:
+      compatible:
+        const: eswin,divider-clock
+
+      reg:
+        maxItems: 1
+
+      clocks:
+        maxItems: 1
+
+      '#clock-cells':
+        const: 0
+
+      clock-output-names:
+        maxItems: 1
+
+      shift:
+        description: Bit shift of the divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      width:
+        description: Width of the divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+      div-flags:
+        description: Flags of the divider register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+    required:
+      - compatible
+      - reg
+      - clocks
+      - '#clock-cells'
+      - clock-output-names
+      - shift
+      - width
+      - div-flags
+
+    additionalProperties: false
+
+  ".*gate@[a-f0-9]+$":
+    type: object
+
+    properties:
+      compatible:
+        const: eswin,gate-clock
+
+      reg:
+        maxItems: 1
+
+      clocks:
+        maxItems: 1
+
+      '#clock-cells':
+        const: 0
+
+      clock-output-names:
+        maxItems: 1
+
+      bit-index:
+        description: Bit shift of the gate enable register.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 31
+
+    required:
+      - compatible
+      - reg
+      - clocks
+      - '#clock-cells'
+      - clock-output-names
+      - bit-index
+
+    additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-controller@51828000 {
+        compatible = "eswin,eic7700-clock";
+        reg = <0x51828000 0x80000>;
+        #clock-cells = <0>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        fixed_rate_clk_xtal_24m: fixed-rate-clk-xtal-24m {
+          compatible = "fixed-clock";
+          #clock-cells = <0>;
+          clock-frequency = <24000000>;
+          clock-output-names = "fixed_rate_clk_xtal_24m";
+        };
+
+        clk_pll_cpu: clk-cpu-pll@64 {
+          compatible = "eswin,pll-clock";
+          reg = <0x64>, <0x68>, <0x6c>, <0xa4>;
+          #clock-cells = <0>;
+          enable-shift = <0>;
+          enable-width = <1>;
+          refdiv-shift = <12>;
+          refdiv-width = <6>;
+          fbdiv-shift = <20>;
+          fbdiv-width = <12>;
+          frac-shift = <4>;
+          frac-width = <24>;
+          postdiv1-shift = <1>;
+          postdiv1-width = <3>;
+          postdiv2-shift = <16>;
+          postdiv2-width = <3>;
+          lock-shift = <5>;
+          lock-width = <1>;
+          clock-output-names = "clk_pll_cpu";
+        };
+
+        mux_cpu_root_3mux1: cpu-root-3mux1-mux@208 {
+          compatible = "eswin,mux-clock";
+          reg = <0x208>;
+          #clock-cells = <0>;
+          clocks = <&clk_pll_cpu>,
+                   <&fixed_factor_u84_core_lp_div2>,
+                   <&fixed_rate_clk_xtal_24m>;
+          shift = <0>;
+          width = <2>;
+          clock-output-names = "mux_cpu_root_3mux1";
+        };
+
+        fixed_factor_cpu_div2: fixed-factor-cpu-div2 {
+          compatible = "fixed-factor-clock";
+          #clock-cells = <0>;
+          clocks = <&mux_cpu_root_3mux1>;
+          clock-div = <2>;
+          clock-mult = <1>;
+          clock-output-names = "fixed_factor_cpu_div2";
+        };
+
+        divider_u84_rtc_toggle: u84-rtc-toggle-div@1ec {
+          compatible = "eswin,divider-clock";
+          reg = <0x1ec>;
+          #clock-cells = <0>;
+          clocks = <&fixed_rate_clk_xtal_24m>;
+          shift = <16>;
+          width = <5>;
+          div-flags = <0x5>;
+          clock-output-names = "divider_u84_rtc_toggle";
+        };
+
+        gate_vi_phy_cfg: vi-phy-cfg-gate@1ac {
+          compatible = "eswin,gate-clock";
+          reg = <0x1ac>;
+          #clock-cells = <0>;
+          clocks = <&fixed_rate_clk_xtal_24m>;
+          bit-index = <1>;
+          clock-output-names = "gate_vi_phy_cfg";
+        };
+    };
--
2.17.1


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

* [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver
  2025-08-15  9:35 [PATCH v4 0/3] Add driver support for ESWIN eic700 SoC clock controller dongxuyang
  2025-08-15  9:36 ` [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC dongxuyang
@ 2025-08-15  9:37 ` dongxuyang
  2025-08-17  6:07   ` Krzysztof Kozlowski
                     ` (2 more replies)
  2025-08-15  9:37 ` [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support dongxuyang
  2 siblings, 3 replies; 13+ messages in thread
From: dongxuyang @ 2025-08-15  9:37 UTC (permalink / raw)
  To: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, paul.walmsley, palmer, aou, alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela, Xuyang Dong

From: Xuyang Dong <dongxuyang@eswincomputing.com>

This driver depends on the CCF framework implementation.
  Based on this driver, other modules in the SoC can use the APIs
  provided by CCF to perform clock-related operations.
  The driver supports eic7700 series chips.

Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
---
 drivers/clk/Kconfig             |   1 +
 drivers/clk/Makefile            |   1 +
 drivers/clk/eswin/Kconfig       |  10 +
 drivers/clk/eswin/Makefile      |   8 +
 drivers/clk/eswin/clk-eic7700.c |  44 ++
 drivers/clk/eswin/clk.c         | 734 ++++++++++++++++++++++++++++++++
 drivers/clk/eswin/clk.h         |  69 +++
 7 files changed, 867 insertions(+)
 create mode 100644 drivers/clk/eswin/Kconfig
 create mode 100644 drivers/clk/eswin/Makefile
 create mode 100644 drivers/clk/eswin/clk-eic7700.c
 create mode 100644 drivers/clk/eswin/clk.c
 create mode 100644 drivers/clk/eswin/clk.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4d56475f94fc..184b76a406d7 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -505,6 +505,7 @@ source "drivers/clk/actions/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/baikal-t1/Kconfig"
 source "drivers/clk/bcm/Kconfig"
+source "drivers/clk/eswin/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 18ed29cfdc11..42c61e216511 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -120,6 +120,7 @@ obj-$(CONFIG_CLK_BAIKAL_T1)		+= baikal-t1/
 obj-y					+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
 obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
+obj-$(CONFIG_ARCH_ESWIN)		+= eswin/
 obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-y					+= imgtec/
 obj-y					+= imx/
diff --git a/drivers/clk/eswin/Kconfig b/drivers/clk/eswin/Kconfig
new file mode 100644
index 000000000000..f2284c2d790d
--- /dev/null
+++ b/drivers/clk/eswin/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config COMMON_CLK_EIC7700
+	bool "EIC7700 Clock Driver"
+	depends on ARCH_ESWIN
+	help
+	  Build the Eswin EIC7700 SoC clock driver based on the
+	  common clock framework. This driver provides support
+	  for the clock control on the Eswin EIC7700 SoC,
+	  which is essential for managing clock rates and power management.
diff --git a/drivers/clk/eswin/Makefile b/drivers/clk/eswin/Makefile
new file mode 100644
index 000000000000..a3139e34ee22
--- /dev/null
+++ b/drivers/clk/eswin/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Eswin Clock specific Makefile
+#
+
+obj-y	+= clk.o
+
+obj-$(CONFIG_COMMON_CLK_EIC7700)	+= clk-eic7700.o
diff --git a/drivers/clk/eswin/clk-eic7700.c b/drivers/clk/eswin/clk-eic7700.c
new file mode 100644
index 000000000000..278b256b4c52
--- /dev/null
+++ b/drivers/clk/eswin/clk-eic7700.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
+ * All rights reserved.
+ *
+ * ESWIN EIC7700 CLK Provider Driver
+ *
+ * Authors:
+ *	Yifeng Huang <huangyifeng@eswincomputing.com>
+ *	Xuyang Dong <dongxuyang@eswincomputing.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include "clk.h"
+
+static void __init eic7700_clk_pll_init(struct device_node *np)
+{
+	eswin_clk_pll_register(np);
+}
+
+static void __init eic7700_clk_mux_init(struct device_node *np)
+{
+	eswin_clk_mux_register(np);
+}
+
+static void __init eic7700_clk_div_init(struct device_node *np)
+{
+	eswin_clk_div_register(np);
+}
+
+static void __init eic7700_clk_gate_init(struct device_node *np)
+{
+	eswin_clk_gate_register(np);
+}
+
+CLK_OF_DECLARE(eic7700_clk_pll, "eswin,pll-clock", eic7700_clk_pll_init);
+CLK_OF_DECLARE(eic7700_clk_mux, "eswin,mux-clock", eic7700_clk_mux_init);
+CLK_OF_DECLARE(eic7700_clk_div, "eswin,divider-clock", eic7700_clk_div_init);
+CLK_OF_DECLARE(eic7700_clk_gate, "eswin,gate-clock", eic7700_clk_gate_init);
diff --git a/drivers/clk/eswin/clk.c b/drivers/clk/eswin/clk.c
new file mode 100644
index 000000000000..e227cc4664ca
--- /dev/null
+++ b/drivers/clk/eswin/clk.c
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
+ * All rights reserved.
+ *
+ * Authors:
+ *	Yifeng Huang <huangyifeng@eswincomputing.com>
+ *	Xuyang Dong <dongxuyang@eswincomputing.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/math.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/util_macros.h>
+#include "clk.h"
+
+enum pll_clk {
+	CLK_APLL_FOUT1 = 1,
+	CLK_PLL_CPU
+};
+
+static enum pll_clk str_to_pll_clk(const char *str)
+{
+	if (!strcmp(str, "clk_apll_fout1"))
+		return CLK_APLL_FOUT1;
+	else if (!strcmp(str, "clk_pll_cpu"))
+		return CLK_PLL_CPU;
+	else
+		return 0;
+}
+
+static void __iomem *parent_base;
+
+static void __init get_parent_base(struct device_node *parent_np)
+{
+	if (!parent_base) {
+		parent_base = of_iomap(parent_np, 0);
+		if (IS_ERR(parent_base)) {
+			pr_err("%s: Failed to map registers\n", __func__);
+			parent_base = NULL;
+		}
+	}
+}
+
+/**
+ * eswin_calc_pll - calculate PLL values
+ * @frac_val: fractional divider
+ * @fbdiv_val: feedback divider
+ * @rate: reference rate
+ *
+ *   Calculate PLL values for frac and fbdiv
+ */
+static void eswin_calc_pll(u32 *frac_val, u32 *fbdiv_val, u64 rate)
+{
+	u32 rem, tmp1, tmp2;
+
+	rate = rate * 4;
+	rem = do_div(rate, 1000);
+	if (rem)
+		tmp1 = rem;
+
+	rem = do_div(rate, 1000);
+	if (rem)
+		tmp2 = rem;
+
+	rem = do_div(rate, 24);
+	/* fbdiv = rate * 4 / 24000000 */
+	*fbdiv_val = rate;
+	/* frac = rate * 4 % 24000000 * (2 ^ 24) */
+	*frac_val = ((1000 * (1000 * rem + tmp2) + tmp1) << 21) / 3 / 1000000;
+}
+
+static inline struct eswin_clk_pll *to_pll_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct eswin_clk_pll, hw);
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct eswin_clk_pll *clk = to_pll_clk(hw);
+	const char *clk_name = clk_hw_get_name(&clk->hw);
+
+	if (!clk_name)
+		return -ENOMEM;
+
+	u32 frac_val = 0, fbdiv_val, refdiv_val = 1, postdiv1_val = 0;
+	u32 val;
+	int ret;
+	struct clk *clk_cpu_mux = NULL;
+	struct clk *clk_cpu_lp_pll = NULL;
+	struct clk *clk_cpu_pll = NULL;
+	int try_count = 0;
+	bool lock_flag = false;
+
+	eswin_calc_pll(&frac_val, &fbdiv_val, (u64)rate);
+
+	/* Must switch the CPU to other CLK before we change the CPU PLL. */
+	if (str_to_pll_clk(clk_name) == CLK_PLL_CPU) {
+		clk_cpu_mux = __clk_lookup("mux_cpu_root_3mux1");
+		if (!clk_cpu_mux) {
+			pr_err("%s %d, failed to get %s\n", __func__, __LINE__,
+			       "mux_cpu_root_3mux1");
+			return -EINVAL;
+		}
+		clk_cpu_lp_pll = __clk_lookup("fixed_factor_u84_core_lp_div2");
+		if (!clk_cpu_lp_pll) {
+			pr_err("%s %d, failed to get %s\n", __func__, __LINE__,
+			       "fixed_factor_u84_core_lp_div2");
+			return -EINVAL;
+		}
+		ret = clk_prepare_enable(clk_cpu_lp_pll);
+		if (ret) {
+			pr_err("%s %d, failed to enable %s, ret %d\n",
+			       __func__, __LINE__,
+			       "fixed_factor_u84_core_lp_div2", ret);
+			return ret;
+		}
+		clk_cpu_pll = __clk_lookup("clk_pll_cpu");
+		if (!clk_cpu_pll) {
+			pr_err("%s %d, failed to get %s\n", __func__, __LINE__,
+			       "clk_pll_cpu");
+			clk_disable_unprepare(clk_cpu_lp_pll);
+			return -EINVAL;
+		}
+
+		ret = clk_set_parent(clk_cpu_mux, clk_cpu_lp_pll);
+		if (ret) {
+			pr_err("%s %d, failed to switch %s to %s, ret %d\n",
+			       __func__, __LINE__, "mux_cpu_root_3mux1",
+			       "fixed_factor_u84_core_lp_div2", ret);
+			clk_disable_unprepare(clk_cpu_lp_pll);
+			return -EPERM;
+		}
+	}
+
+	/* first disable PLL */
+	val = readl_relaxed(clk->ctrl_reg0);
+	val &= ~(((1 << clk->pllen_width) - 1) << clk->pllen_shift);
+	val |= 0 << clk->pllen_shift;
+	writel_relaxed(val, clk->ctrl_reg0);
+
+	val = readl_relaxed(clk->ctrl_reg0);
+	val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift);
+	val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift);
+	val |= refdiv_val << clk->refdiv_shift;
+	val |= fbdiv_val << clk->fbdiv_shift;
+	writel_relaxed(val, clk->ctrl_reg0);
+
+	val = readl_relaxed(clk->ctrl_reg1);
+	val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift);
+	val |= frac_val << clk->frac_shift;
+	writel_relaxed(val, clk->ctrl_reg1);
+
+	val = readl_relaxed(clk->ctrl_reg2);
+	val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift);
+	val |= postdiv1_val << clk->postdiv1_shift;
+	writel_relaxed(val, clk->ctrl_reg2);
+
+	/* at last, enable PLL */
+	val = readl_relaxed(clk->ctrl_reg0);
+	val &= ~(((1 << clk->pllen_width) - 1) << clk->pllen_shift);
+	val |= 1 << clk->pllen_shift;
+	writel_relaxed(val, clk->ctrl_reg0);
+
+	/* usually the PLL would lock in 50us */
+	do {
+		usleep_range(refdiv_val * 80, refdiv_val * 80 * 2);
+		val = readl_relaxed(clk->status_reg);
+		if (val & 1 << clk->lock_shift) {
+			lock_flag = true;
+			break;
+		}
+	} while (try_count++ < 10);
+
+	if (!lock_flag) {
+		pr_err("%s %d, failed to lock the cpu pll", __func__, __LINE__);
+		return -EBUSY;
+	}
+
+	if (str_to_pll_clk(clk_name) == CLK_PLL_CPU) {
+		ret = clk_set_parent(clk_cpu_mux, clk_cpu_pll);
+		if (ret) {
+			pr_err("%s %d, failed to switch %s to %s, ret %d\n",
+			       __func__, __LINE__, "mux_cpu_root_3mux1",
+			       "clk_pll_cpu", ret);
+			return -EPERM;
+		}
+		clk_disable_unprepare(clk_cpu_lp_pll);
+	}
+	return ret;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct eswin_clk_pll *clk = to_pll_clk(hw);
+	const char *clk_name = clk_hw_get_name(&clk->hw);
+
+	if (!clk_name)
+		return -ENOMEM;
+
+	u64 frac_val, fbdiv_val, refdiv_val, tmp, rem;
+	u32 postdiv1_val;
+	u32 val;
+	u64 rate = 0;
+
+	val = readl_relaxed(clk->ctrl_reg0);
+	val = val >> clk->fbdiv_shift;
+	val &= ((1 << clk->fbdiv_width) - 1);
+	fbdiv_val = val;
+
+	val = readl_relaxed(clk->ctrl_reg0);
+	val = val >> clk->refdiv_shift;
+	val &= ((1 << clk->refdiv_width) - 1);
+	refdiv_val = val;
+
+	val = readl_relaxed(clk->ctrl_reg1);
+	val = val >> clk->frac_shift;
+	val &= ((1 << clk->frac_width) - 1);
+	frac_val = val;
+
+	val = readl_relaxed(clk->ctrl_reg2);
+	val = val >> clk->postdiv1_shift;
+	val &= ((1 << clk->postdiv1_width) - 1);
+	postdiv1_val = val;
+
+	/* rate = 24000000 * (fbdiv + frac / (2 ^ 24)) / 4 */
+	if (str_to_pll_clk(clk_name)) {
+		tmp = 1000 * frac_val;
+		rem = do_div(tmp, BIT(24));
+		if (rem)
+			rate = (u64)(6000 * (1000 * fbdiv_val + tmp) +
+				    ((6000 * rem) >> 24) + 1);
+		else
+			rate = (u64)(6000 * 1000 * fbdiv_val);
+	}
+
+	return rate;
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	struct eswin_clk_pll *clk = to_pll_clk(hw);
+	const char *clk_name = clk_hw_get_name(&clk->hw);
+
+	if (!clk_name)
+		return -ENOMEM;
+
+	int index;
+	u64 round_rate = 0;
+
+	/* Must be sorted in ascending order */
+	u64 apll_clk[] = { APLL_LOW_FREQ, APLL_HIGH_FREQ };
+	u64 cpu_pll_clk[] = { CLK_FREQ_100M,  CLK_FREQ_200M,  CLK_FREQ_400M,
+			      CLK_FREQ_500M,  CLK_FREQ_600M,  CLK_FREQ_700M,
+			      CLK_FREQ_800M,  CLK_FREQ_900M,  CLK_FREQ_1000M,
+			      CLK_FREQ_1200M, CLK_FREQ_1300M, CLK_FREQ_1400M,
+			      CLK_FREQ_1500M, CLK_FREQ_1600M, CLK_FREQ_1700M,
+			      CLK_FREQ_1800M };
+
+	switch (str_to_pll_clk(clk_name)) {
+	case CLK_APLL_FOUT1:
+		index = find_closest(rate, apll_clk, ARRAY_SIZE(apll_clk));
+		round_rate = apll_clk[index];
+		break;
+	case CLK_PLL_CPU:
+		index = find_closest(rate, cpu_pll_clk,
+				     ARRAY_SIZE(cpu_pll_clk));
+		round_rate = cpu_pll_clk[index];
+		break;
+	default:
+		pr_err("%s %d, unknown clk %s\n", __func__, __LINE__,
+		       clk_name);
+		break;
+	}
+	return round_rate;
+}
+
+static const struct clk_ops eswin_clk_pll_ops = {
+	.set_rate = clk_pll_set_rate,
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_round_rate,
+};
+
+void __init eswin_clk_gate_register(struct device_node *np)
+{
+	struct clk_hw *clk_hw;
+	struct device_node *parent_np;
+	const char *clk_name;
+	const char *parent_name;
+	u32 idx_bit;
+	u32 reg;
+	int ret;
+
+	parent_np = of_get_parent(np);
+	if (!parent_np) {
+		pr_err("%s: Failed to get parent node\n", __func__);
+		return;
+	}
+
+	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
+		get_parent_base(parent_np);
+	else
+		return;
+
+	if (IS_ERR(parent_base)) {
+		pr_err("%s: Failed to map registers\n", __func__);
+		goto put_node;
+	}
+
+	ret = of_property_read_string(np, "clock-output-names", &clk_name);
+	if (ret) {
+		pr_err("%s: Missing clock-output-names\n", __func__);
+		goto put_node;
+	}
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		goto put_node;
+
+	ret = of_property_read_u32(np, "bit-index", &idx_bit);
+	if (ret) {
+		pr_err("%s: Missing bit-index for gate %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret) {
+		pr_err("%s: Missing reg for gate %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	clk_hw = clk_hw_register_gate(NULL, clk_name, parent_name,
+				      CLK_SET_RATE_PARENT,
+				      parent_base + reg, idx_bit, 0, NULL);
+
+	if (IS_ERR(clk_hw)) {
+		pr_err("%s: Failed to register gate clock %s: %ld\n",
+		       __func__, clk_name, PTR_ERR(clk_hw));
+		goto put_node;
+	}
+	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk_hw);
+	if (ret) {
+		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
+		clk_hw_unregister_gate(clk_hw);
+	}
+
+put_node:
+	of_node_put(parent_np);
+}
+
+void __init eswin_clk_mux_register(struct device_node *np)
+{
+	struct clk *clk;
+	const char *clk_name = NULL;
+	const char **parent_names = NULL;
+	struct device_node *parent_np;
+	u32 shift, width;
+	u32 reg;
+	u8 num_parents;
+	u32 mask = 0;
+	int ret, i;
+
+	parent_np = of_get_parent(np);
+	if (!parent_np) {
+		pr_err("%s: Failed to get parent node\n", __func__);
+		return;
+	}
+
+	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
+		get_parent_base(parent_np);
+	else
+		return;
+
+	if (IS_ERR(parent_base)) {
+		pr_err("%s: Failed to map registers\n", __func__);
+		goto put_node;
+	}
+
+	ret = of_property_read_string(np, "clock-output-names", &clk_name);
+	if (ret) {
+		pr_err("%s: Missing clock-output-names\n", __func__);
+		goto put_node;
+	}
+
+	num_parents = of_clk_get_parent_count(np);
+	if (!num_parents) {
+		pr_err("%s: No parents for mux %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	parent_names = kcalloc(num_parents, sizeof(*parent_names),
+			       GFP_KERNEL);
+	if (!parent_names)
+		goto put_node;
+
+	for (i = 0; i < num_parents; i++) {
+		parent_names[i] = of_clk_get_parent_name(np, i);
+		if (!parent_names[i]) {
+			pr_err("%s: Failed to get parent name %d for %s\n",
+			       __func__, i, clk_name);
+			goto free_parents;
+		}
+	}
+
+	ret = of_property_read_u32(np, "shift", &shift);
+	if (ret) {
+		pr_err("%s: Missing shift for mux %s\n", __func__, clk_name);
+		goto free_parents;
+	}
+
+	ret = of_property_read_u32(np, "width", &width);
+	if (ret) {
+		pr_err("%s: Missing width for mux %s\n", __func__, clk_name);
+		goto free_parents;
+	}
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret) {
+		pr_err("%s: Missing reg for mux %s\n", __func__, clk_name);
+		goto free_parents;
+	}
+
+	mask = BIT(width) - 1;
+	clk = clk_register_mux_table(NULL, clk_name, parent_names, num_parents,
+				     CLK_SET_RATE_PARENT, parent_base + reg,
+				     shift, mask, 0, NULL, NULL);
+
+	if (IS_ERR(clk)) {
+		pr_err("%s: Failed to register mux clock %s: %ld\n", __func__,
+		       clk_name, PTR_ERR(clk));
+		goto free_parents;
+	}
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk);
+	if (ret) {
+		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
+		clk_unregister_mux(clk);
+	}
+
+free_parents:
+	kfree(parent_names);
+put_node:
+	of_node_put(parent_np);
+}
+
+void __init eswin_clk_div_register(struct device_node *np)
+{
+	struct clk_hw *clk_hw;
+	struct device_node *parent_np;
+	const char *clk_name;
+	const char *parent_name;
+	u32 shift, width, div_flags;
+	u32 reg;
+	int ret;
+
+	parent_np = of_get_parent(np);
+	if (!parent_np) {
+		pr_err("%s: Failed to get parent node\n", __func__);
+		return;
+	}
+
+	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
+		get_parent_base(parent_np);
+	else
+		return;
+
+	if (IS_ERR(parent_base)) {
+		pr_err("%s: Failed to map registers\n", __func__);
+		goto put_node;
+	}
+
+	ret = of_property_read_string(np, "clock-output-names", &clk_name);
+	if (ret) {
+		pr_err("%s: Missing clock-output-names\n", __func__);
+		goto put_node;
+	}
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name) {
+		pr_err("%s: No parent for div %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "shift", &shift);
+	if (ret) {
+		pr_err("%s: Missing shift for div %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "width", &width);
+	if (ret) {
+		pr_err("%s: Missing width for div %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "div-flags", &div_flags);
+	if (ret) {
+		pr_err("%s: Missing div-flags for div %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret) {
+		pr_err("%s: Missing reg for div %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	clk_hw = clk_hw_register_divider(NULL, clk_name, parent_name, 0,
+					 parent_base + reg, shift, width,
+					 div_flags, NULL);
+
+	if (IS_ERR(clk_hw)) {
+		pr_err("%s: Failed to register divider clock %s: %ld\n",
+		       __func__, clk_name, PTR_ERR(clk_hw));
+		goto put_node;
+	}
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk_hw);
+	if (ret) {
+		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
+		clk_hw_unregister_divider(clk_hw);
+	}
+
+put_node:
+	of_node_put(parent_np);
+}
+
+void __init eswin_clk_pll_register(struct device_node *np)
+{
+	struct eswin_clk_pll *p_clk = NULL;
+	struct clk *clk = NULL;
+	struct clk_init_data init = {};
+	struct device_node *parent_np;
+	const char *clk_name;
+	const char *parent_name;
+	int ret;
+	u32 reg[4];
+	u32 en_shift, en_width;
+	u32 refdiv_shift, refdiv_width;
+	u32 fbdiv_shift, fbdiv_width;
+	u32 frac_shift, frac_width;
+	u32 postdiv1_shift, postdiv1_width;
+	u32 postdiv2_shift, postdiv2_width;
+	u32 lock_shift, lock_width;
+
+	parent_np = of_get_parent(np);
+	if (!parent_np) {
+		pr_err("%s: Failed to get parent node\n", __func__);
+		return;
+	}
+
+	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
+		get_parent_base(parent_np);
+	else
+		return;
+
+	if (IS_ERR(parent_base)) {
+		pr_err("%s: Failed to map registers\n", __func__);
+		goto put_node;
+	}
+
+	ret = of_property_read_string(np, "clock-output-names", &clk_name);
+	if (ret) {
+		pr_err("%s: Missing clock-output-names\n", __func__);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "enable-shift", &en_shift);
+	if (ret) {
+		pr_err("%s: Missing enable-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "enable-width", &en_width);
+	if (ret) {
+		pr_err("%s: Missing enable-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "refdiv-shift", &refdiv_shift);
+	if (ret) {
+		pr_err("%s: Missing refdiv-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "refdiv-width", &refdiv_width);
+	if (ret) {
+		pr_err("%s: Missing refdiv-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "fbdiv-shift", &fbdiv_shift);
+	if (ret) {
+		pr_err("%s: Missing fbdiv-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "fbdiv-width", &fbdiv_width);
+	if (ret) {
+		pr_err("%s: Missing fbdiv-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "frac-shift", &frac_shift);
+	if (ret) {
+		pr_err("%s: Missing frac-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "frac-width", &frac_width);
+	if (ret) {
+		pr_err("%s: Missing frac-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "postdiv1-shift", &postdiv1_shift);
+	if (ret) {
+		pr_err("%s: Missing postdiv1-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "postdiv1-width", &postdiv1_width);
+	if (ret) {
+		pr_err("%s: Missing postdiv1-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "postdiv2-shift", &postdiv2_shift);
+	if (ret) {
+		pr_err("%s: Missing postdiv2-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "postdiv2-width", &postdiv2_width);
+	if (ret) {
+		pr_err("%s: Missing postdiv2-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "lock-shift", &lock_shift);
+	if (ret) {
+		pr_err("%s: Missing lock-shift for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32(np, "lock-width", &lock_width);
+	if (ret) {
+		pr_err("%s: Missing lock-width for pll %s\n", __func__,
+		       clk_name);
+		goto put_node;
+	}
+
+	ret = of_property_read_u32_array(np, "reg", reg, 4);
+	if (ret) {
+		pr_err("%s: Missing reg for pll %s\n", __func__, clk_name);
+		goto put_node;
+	}
+
+	p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
+	if (!p_clk)
+		goto put_node;
+
+	p_clk->ctrl_reg0 = parent_base + reg[0];
+	p_clk->pllen_shift = en_shift;
+	p_clk->pllen_width = en_width;
+	p_clk->refdiv_shift = refdiv_shift;
+	p_clk->refdiv_width = refdiv_width;
+	p_clk->fbdiv_shift = fbdiv_shift;
+	p_clk->fbdiv_width = fbdiv_width;
+
+	p_clk->ctrl_reg1 = parent_base + reg[1];
+	p_clk->frac_shift = frac_shift;
+	p_clk->frac_width = frac_width;
+
+	p_clk->ctrl_reg2 = parent_base + reg[2];
+	p_clk->postdiv1_shift = postdiv1_shift;
+	p_clk->postdiv1_width = postdiv1_width;
+	p_clk->postdiv2_shift = postdiv2_shift;
+	p_clk->postdiv2_width = postdiv2_width;
+
+	p_clk->status_reg = parent_base + reg[3];
+	p_clk->lock_shift = lock_shift;
+	p_clk->lock_width = lock_width;
+
+	init.name = clk_name;
+	init.flags = 0;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.ops = &eswin_clk_pll_ops;
+	p_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &p_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: Failed to register pll clock %s: %ld\n", __func__,
+		       clk_name, PTR_ERR(clk));
+		kfree(p_clk);
+		goto put_node;
+	}
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk);
+	if (ret) {
+		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
+		clk_unregister(clk);
+	}
+
+put_node:
+	of_node_put(parent_np);
+}
diff --git a/drivers/clk/eswin/clk.h b/drivers/clk/eswin/clk.h
new file mode 100644
index 000000000000..1302540f9e24
--- /dev/null
+++ b/drivers/clk/eswin/clk.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
+ * All rights reserved.
+ *
+ * Authors:
+ *	Yifeng Huang <huangyifeng@eswincomputing.com>
+ *	Xuyang Dong <dongxuyang@eswincomputing.com>
+ */
+
+#ifndef __ESWIN_CLK_H__
+#define __ESWIN_CLK_H__
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define CLK_FREQ_1800M 1800000000
+#define CLK_FREQ_1700M 1700000000
+#define CLK_FREQ_1600M 1600000000
+#define CLK_FREQ_1500M 1500000000
+#define CLK_FREQ_1400M 1400000000
+#define CLK_FREQ_1300M 1300000000
+#define CLK_FREQ_1200M 1200000000
+#define CLK_FREQ_1000M 1000000000
+#define CLK_FREQ_900M 900000000
+#define CLK_FREQ_800M 800000000
+#define CLK_FREQ_700M 700000000
+#define CLK_FREQ_600M 600000000
+#define CLK_FREQ_500M 500000000
+#define CLK_FREQ_400M 400000000
+#define CLK_FREQ_200M 200000000
+#define CLK_FREQ_100M 100000000
+#define CLK_FREQ_24M 24000000
+
+#define APLL_HIGH_FREQ 983040000
+#define APLL_LOW_FREQ 225792000
+
+struct eswin_clk_pll {
+	struct clk_hw hw;
+	void __iomem *ctrl_reg0;
+	u8 pllen_shift;
+	u8 pllen_width;
+	u8 refdiv_shift;
+	u8 refdiv_width;
+	u8 fbdiv_shift;
+	u8 fbdiv_width;
+
+	void __iomem *ctrl_reg1;
+	u8 frac_shift;
+	u8 frac_width;
+
+	void __iomem *ctrl_reg2;
+	u8 postdiv1_shift;
+	u8 postdiv1_width;
+	u8 postdiv2_shift;
+	u8 postdiv2_width;
+
+	void __iomem *status_reg;
+	u8 lock_shift;
+	u8 lock_width;
+};
+
+void __init eswin_clk_gate_register(struct device_node *np);
+void __init eswin_clk_mux_register(struct device_node *np);
+void __init eswin_clk_div_register(struct device_node *np);
+void __init eswin_clk_pll_register(struct device_node *np);
+
+#endif /* __ESWIN_CLK_H__ */
--
2.17.1


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

* [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support
  2025-08-15  9:35 [PATCH v4 0/3] Add driver support for ESWIN eic700 SoC clock controller dongxuyang
  2025-08-15  9:36 ` [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC dongxuyang
  2025-08-15  9:37 ` [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver dongxuyang
@ 2025-08-15  9:37 ` dongxuyang
  2025-08-17  6:07   ` Krzysztof Kozlowski
  2 siblings, 1 reply; 13+ messages in thread
From: dongxuyang @ 2025-08-15  9:37 UTC (permalink / raw)
  To: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, paul.walmsley, palmer, aou, alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela, Xuyang Dong

From: Xuyang Dong <dongxuyang@eswincomputing.com>

Add clock device tree support for eic7700 SoC.

Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
---
 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi | 2283 +++++++++++++++++
 1 file changed, 2283 insertions(+)
 create mode 100644 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi

diff --git a/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
new file mode 100644
index 000000000000..405d06f9190e
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
@@ -0,0 +1,2283 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2025, Beijing ESWIN Computing Technology Co., Ltd.
+ */
+
+/ {
+	clock-controller@51828000 {
+		compatible = "eswin,eic7700-clock";
+		reg = <0x000000 0x51828000 0x000000 0x80000>;
+		#clock-cells = <0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* fixed clock */
+		fixed_rate_clk_apll_fout2: fixed-rate-apll-fout2 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "fixed_rate_clk_apll_fout2";
+		};
+		fixed_rate_clk_apll_fout3: fixed-rate-apll-fout3 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "fixed_rate_clk_apll_fout3";
+		};
+		fixed_rate_clk_spll0_fout1: fixed-rate-spll0-fout1 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1600000000>;
+			clock-output-names = "fixed_rate_clk_spll0_fout1";
+		};
+		fixed_rate_clk_spll0_fout2: fixed-rate-spll0-fout2 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <800000000>;
+			clock-output-names = "fixed_rate_clk_spll0_fout2";
+		};
+		fixed_rate_clk_spll0_fout3: fixed-rate-spll0-fout3 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <400000000>;
+			clock-output-names = "fixed_rate_clk_spll0_fout3";
+		};
+		fixed_rate_clk_spll1_fout1: fixed-rate-spll1-fout1 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1500000000>;
+			clock-output-names = "fixed_rate_clk_spll1_fout1";
+		};
+		fixed_rate_clk_spll1_fout2: fixed-rate-spll1-fout2 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <300000000>;
+			clock-output-names = "fixed_rate_clk_spll1_fout2";
+		};
+		fixed_rate_clk_spll1_fout3: fixed-rate-spll1-fout3 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <250000000>;
+			clock-output-names = "fixed_rate_clk_spll1_fout3";
+		};
+		fixed_rate_clk_spll2_fout1: fixed-rate-spll2-fout1 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <2080000000>;
+			clock-output-names = "fixed_rate_clk_spll2_fout1";
+		};
+		fixed_rate_clk_spll2_fout2: fixed-rate-spll2-fout2 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1040000000>;
+			clock-output-names = "fixed_rate_clk_spll2_fout2";
+		};
+		fixed_rate_clk_spll2_fout3: fixed-rate-spll2-fout3 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <416000000>;
+			clock-output-names = "fixed_rate_clk_spll2_fout3";
+		};
+		fixed_rate_clk_vpll_fout1: fixed-rate-vpll-fout1 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1188000000>;
+			clock-output-names = "fixed_rate_clk_vpll_fout1";
+		};
+		fixed_rate_clk_vpll_fout2: fixed-rate-vpll-fout2 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <594000000>;
+			clock-output-names = "fixed_rate_clk_vpll_fout2";
+		};
+		fixed_rate_clk_vpll_fout3: fixed-rate-vpll-fout3 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <49500000>;
+			clock-output-names = "fixed_rate_clk_vpll_fout3";
+		};
+		fixed_rate_clk_xtal_24m: fixed-rate-xtal-24m {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <24000000>;
+			clock-output-names = "fixed_rate_clk_xtal_24m";
+		};
+		fixed_rate_clk_xtal_32k: fixed-rate-xtal-32K {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "fixed_rate_clk_xtal_32k";
+		};
+		fixed_rate_ext_mclk: fixed-rate-ext-mclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "fixed_rate_ext_mclk";
+		};
+		fixed_rate_lpddr_ref_bak: fixed-rate-lpddr {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+			clock-output-names = "fixed_rate_lpddr_ref_bak";
+		};
+		/* pll */
+		clk_apll_fout1: clk-apll-fout1-pll@50 {
+			compatible = "eswin,pll-clock";
+			reg = <0x50>, <0x54>, <0x58>, <0xa4>;
+			#clock-cells = <0>;
+			enable-shift = <0>;
+			enable-width = <1>;
+			refdiv-shift = <12>;
+			refdiv-width = <6>;
+			fbdiv-shift = <20>;
+			fbdiv-width = <12>;
+			frac-shift = <4>;
+			frac-width = <24>;
+			postdiv1-shift = <1>;
+			postdiv1-width = <3>;
+			postdiv2-shift = <16>;
+			postdiv2-width = <3>;
+			lock-shift = <4>;
+			lock-width = <1>;
+			clock-output-names = "clk_apll_fout1";
+		};
+		clk_pll_cpu: clk-cpu-pll@64 {
+			compatible = "eswin,pll-clock";
+			reg = <0x64>, <0x68>, <0x6c>, <0xa4>;
+			#clock-cells = <0>;
+			enable-shift = <0>;
+			enable-width = <1>;
+			refdiv-shift = <12>;
+			refdiv-width = <6>;
+			fbdiv-shift = <20>;
+			fbdiv-width = <12>;
+			frac-shift = <4>;
+			frac-width = <24>;
+			postdiv1-shift = <1>;
+			postdiv1-width = <3>;
+			postdiv2-shift = <16>;
+			postdiv2-width = <3>;
+			lock-shift = <5>;
+			lock-width = <1>;
+			clock-output-names = "clk_pll_cpu";
+		};
+		/* fixed factor clock */
+		fixed_factor_clk_1m_div24: fixed-factor-clk-1m-div24 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			clock-div = <24>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_clk_1m_div24";
+		};
+		fixed_factor_cpu_div2: fixed-factor-cpu-div2 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_cpu_div2";
+		};
+		fixed_factor_hsp_rmii_ref_div6: fixed-factor-hsp-rmii-ref-div6 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&fixed_rate_clk_spll1_fout2>;
+			clock-div = <6>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_hsp_rmii_ref_div6";
+		};
+		fixed_factor_lpcpu_bus_div2: fixed-factor-lpcpu-bus-div2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&mux_lpcpu_core_clk_2mux1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_lpcpu_bus_div2";
+		};
+		fixed_factor_mipi_txesc_div10: fixed-factor-mipi-txesc-div10 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			clock-div = <10>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_mipi_txesc_div10";
+		};
+		fixed_factor_pcie_aux_div4: fixed-factor-pcie-aux-div4 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_pcie_aux_div4";
+		};
+		fixed_factor_pcie_cr_div2: fixed-factor-pcie-cr-div2 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_pcie_cr_div2";
+		};
+		fixed_factor_pvt_div20: fixed-factor-pvt-div20 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			clock-div = <20>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_pvt_div20";
+		};
+		fixed_factor_scpu_bus_div2: fixed-factor-scpu-bus-div2 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clocks = <&mux_scpu_core_clk_2mux1>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_scpu_bus_div2";
+		};
+		fixed_factor_u84_core_lp_div2: fixed-factor-u84-core-lp-div2 {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&gate_clk_spll0_fout2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "fixed_factor_u84_core_lp_div2";
+		};
+		/* mux clock */
+		mux_bootspi_clk_2mux1: bootspi-clk-2mux1-mux@104 {
+			compatible = "eswin,mux-clock";
+			reg = <0x104>;
+			#clock-cells = <0>;
+			clocks = <&divider_bootspi_div>,
+				 <&fixed_rate_clk_xtal_24m>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_bootspi_clk_2mux1";
+		};
+		mux_scpu_core_clk_2mux1: scpu-core-clk-2mux1-mux@10c {
+			compatible = "eswin,mux-clock";
+			reg = <0x10c>;
+			#clock-cells = <0>;
+			clocks = <&divider_scpu_core_div>,
+				 <&fixed_rate_clk_xtal_24m>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_scpu_core_clk_2mux1";
+		};
+		mux_lpcpu_core_clk_2mux1: lpcpu-core-clk-2mux1-mux@114 {
+			compatible = "eswin,mux-clock";
+			reg = <0x114>;
+			#clock-cells = <0>;
+			clocks = <&divider_lpcpu_core_div>,
+				 <&fixed_rate_clk_xtal_24m>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_lpcpu_core_clk_2mux1";
+		};
+		mux_ddr_aclk_root_2mux1: ddr-aclk-root-2mux1-mux@124 {
+			compatible = "eswin,mux-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll2_fout1>,
+				 <&fixed_rate_clk_spll0_fout1>;
+			shift = <16>;
+			width = <1>;
+			clock-output-names = "mux_ddr_aclk_root_2mux1";
+		};
+		mux_dsp_aclk_root_2mux1: dsp-aclk-root-2mux1-mux@138 {
+			compatible = "eswin,mux-clock";
+			reg = <0x138>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll2_fout1>,
+				 <&fixed_rate_clk_spll0_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_dsp_aclk_root_2mux1";
+		};
+		mux_d2d_aclk_root_2mux1: d2d-aclk-root-2mux1-mux@140 {
+			compatible = "eswin,mux-clock";
+			reg = <0x140>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll2_fout1>,
+				 <&fixed_rate_clk_spll0_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_d2d_aclk_root_2mux1";
+		};
+		mux_sata_phy_2mux1: sata-phy-2mux1-mux@154 {
+			compatible = "eswin,mux-clock";
+			reg = <0x154>;
+			#clock-cells = <0>;
+			clocks = <&divider_sata_phy_ref_div>,
+				 <&fixed_rate_lpddr_ref_bak>;
+			shift = <9>;
+			width = <1>;
+			clock-output-names = "mux_sata_phy_2mux1";
+		};
+		mux_eth_core_2mux1: eth-core-2mux1-mux@158 {
+			compatible = "eswin,mux-clock";
+			reg = <0x158>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll1_fout3>,
+				 <&fixed_rate_lpddr_ref_bak>;
+			shift = <1>;
+			width = <1>;
+			clock-output-names = "mux_eth_core_2mux1";
+		};
+		mux_rmii_ref_2mux1: rmii-ref-2mux1-mux@158 {
+			compatible = "eswin,mux-clock";
+			reg = <0x158>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_hsp_rmii_ref_div6>,
+				 <&fixed_rate_lpddr_ref_bak>;
+			shift = <2>;
+			width = <1>;
+			clock-output-names = "mux_rmii_ref_2mux1";
+		};
+		mux_mshcore_root_3mux1_0: mshcore0-root-3mux1-mux@160 {
+			compatible = "eswin,mux-clock";
+			reg = <0x160>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout3>,
+				 <&fixed_rate_clk_spll2_fout3>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_mshcore_root_3mux1_0";
+		};
+		mux_mshcore_root_3mux1_1: mshcore1-root-3mux1-mux@164 {
+			compatible = "eswin,mux-clock";
+			reg = <0x164>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout3>,
+				 <&fixed_rate_clk_spll2_fout3>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_mshcore_root_3mux1_1";
+		};
+		mux_mshcore_root_3mux1_2: mshcore2-root-3mux1-mux@168 {
+			compatible = "eswin,mux-clock";
+			reg = <0x168>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout3>,
+				 <&fixed_rate_clk_spll2_fout3>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_mshcore_root_3mux1_2";
+		};
+		mux_npu_llclk_3mux1: npu-llclk-3mux1-mux@17c {
+			compatible = "eswin,mux-clock";
+			reg = <0x17c>;
+			#clock-cells = <0>;
+			clocks = <&divider_npu_llc_src0_div>,
+				 <&divider_npu_llc_src1_div>,
+				 <&fixed_rate_clk_vpll_fout1>;
+			shift = <0>;
+			width = <2>;
+			clock-output-names = "mux_npu_llclk_3mux1";
+		};
+		mux_npu_core_3mux1: npu-core-3mux1-mux@180 {
+			compatible = "eswin,mux-clock";
+			reg = <0x180>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll1_fout1>,
+				 <&fixed_rate_clk_vpll_fout1>,
+				 <&fixed_rate_clk_spll2_fout2>;
+			shift = <0>;
+			width = <2>;
+			clock-output-names = "mux_npu_core_3mux1";
+		};
+		mux_npu_e31_3mux1: npu-e31-3mux1-mux@180 {
+			compatible = "eswin,mux-clock";
+			reg = <0x180>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll1_fout1>,
+				 <&fixed_rate_clk_vpll_fout1>,
+				 <&fixed_rate_clk_spll2_fout2>;
+			shift = <8>;
+			width = <2>;
+			clock-output-names = "mux_npu_e31_3mux1";
+		};
+		mux_vi_dw_root_2mux1: vi-dw-root-2mux1-mux@184 {
+			compatible = "eswin,mux-clock";
+			reg = <0x184>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout1>,
+				 <&fixed_rate_clk_spll0_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vi_dw_root_2mux1";
+		};
+		mux_vi_aclk_root_2mux1: vi-aclk-root-2mux1-mux@188 {
+			compatible = "eswin,mux-clock";
+			reg = <0x188>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>,
+				 <&fixed_rate_clk_spll2_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vi_aclk_root_2mux1";
+		};
+		mux_vi_dig_isp_root_2mux1: vi-dig-isp-root-2mux1-mux@18c {
+			compatible = "eswin,mux-clock";
+			reg = <0x18c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout1>,
+				 <&fixed_rate_clk_spll0_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vi_dig_isp_root_2mux1";
+		};
+		mux_vi_dvp_root_2mux1: vi-dvp-root-2mux1-mux@190 {
+			compatible = "eswin,mux-clock";
+			reg = <0x190>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout1>,
+				 <&fixed_rate_clk_spll0_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vi_dvp_root_2mux1";
+		};
+		mux_vo_aclk_root_2mux1: vo-aclk-root-2mux1-mux@1b0 {
+			compatible = "eswin,mux-clock";
+			reg = <0x1b0>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>,
+				 <&fixed_rate_clk_spll2_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vo_aclk_root_2mux1";
+		};
+		mux_vo_pixel_root_2mux1: vo-pixel-root-2mux1-mux@1b8 {
+			compatible = "eswin,mux-clock";
+			reg = <0x1b8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout1>,
+				 <&fixed_rate_clk_spll2_fout2>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vo_pixel_root_2mux1";
+		};
+		mux_vo_mclk_2mux_ext_mclk: vo-mclk-2mux-ext-mclk-mux@1bc {
+			compatible = "eswin,mux-clock";
+			reg = <0x1bc>;
+			#clock-cells = <0>;
+			clocks = <&divider_vo_mclk_div>,
+				 <&fixed_rate_ext_mclk>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vo_mclk_2mux_ext_mclk";
+		};
+		mux_vcaclk_root_2mux1: vcaclk-root-2mux1-mux@1c4 {
+			compatible = "eswin,mux-clock";
+			reg = <0x1c4>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>,
+				 <&fixed_rate_clk_spll2_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vcaclk_root_2mux1";
+		};
+		mux_vcdec_root_2mux1: vcdec-root-2mux1-mux@1c8 {
+			compatible = "eswin,mux-clock";
+			reg = <0x1c8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>,
+				 <&fixed_rate_clk_spll2_fout1>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_vcdec_root_2mux1";
+		};
+		mux_aondma_axi2mux1: aondma-axi2mux1-mux@1e4 {
+			compatible = "eswin,mux-clock";
+			reg = <0x1e4>;
+			#clock-cells = <0>;
+			clocks = <&divider_aondma_axi_div>,
+				 <&fixed_rate_clk_xtal_24m>;
+			shift = <20>;
+			width = <1>;
+			clock-output-names = "mux_aondma_axi2mux1";
+		};
+		mux_cpu_aclk_2mux1: cpu-aclk-2mux1-mux@208 {
+			compatible = "eswin,mux-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_cpu_div2>,
+				 <&mux_cpu_root_3mux1>;
+			shift = <20>;
+			width = <1>;
+			clock-output-names = "mux_cpu_aclk_2mux1";
+		};
+		mux_cpu_root_3mux1: cpu-root-3mux1-mux@208 {
+			compatible = "eswin,mux-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&clk_pll_cpu>,
+				 <&fixed_factor_u84_core_lp_div2>,
+				 <&fixed_rate_clk_xtal_24m>;
+			shift = <0>;
+			width = <2>;
+			clock-output-names = "mux_cpu_root_3mux1";
+		};
+		mux_syscfg_clk_root_2mux1: syscfg-clk-root-2mux1-mux@20c {
+			compatible = "eswin,mux-clock";
+			reg = <0x20c>;
+			#clock-cells = <0>;
+			clocks = <&divider_sys_cfg_div>,
+				 <&fixed_rate_clk_xtal_24m>;
+			shift = <0>;
+			width = <1>;
+			clock-output-names = "mux_syscfg_clk_root_2mux1";
+		};
+		/* div clock */
+		divider_noc_nsp_div: noc-nsp-div@100 {
+			compatible = "eswin,divider-clock";
+			reg = <0x100>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll2_fout1>;
+			shift = <0>;
+			width = <3>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_noc_nsp_div";
+		};
+		divider_bootspi_div: bootspi-div@104 {
+			compatible = "eswin,divider-clock";
+			reg = <0x104>;
+			#clock-cells = <0>;
+			clocks = <&gate_clk_spll0_fout2>;
+			shift = <4>;
+			width = <6>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_bootspi_div";
+		};
+		divider_scpu_core_div: scpu-core-div@10c {
+			compatible = "eswin,divider-clock";
+			reg = <0x10c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_scpu_core_div";
+		};
+		divider_lpcpu_core_div: lpcpu-core-div@114 {
+			compatible = "eswin,divider-clock";
+			reg = <0x114>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_lpcpu_core_div";
+		};
+		divider_ddr_aclk_div: ddr-aclk-div@124 {
+			compatible = "eswin,divider-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&mux_ddr_aclk_root_2mux1>;
+			shift = <20>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_ddr_aclk_div";
+		};
+		divider_gpu_aclk_div: gpu-aclk-div@12c {
+			compatible = "eswin,divider-clock";
+			reg = <0x12c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_gpu_aclk_div";
+		};
+		divider_dsp_aclk_div: dsp-aclk-div@138 {
+			compatible = "eswin,divider-clock";
+			reg = <0x138>;
+			#clock-cells = <0>;
+			clocks = <&mux_dsp_aclk_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_dsp_aclk_div";
+		};
+		divider_dsp_0_aclk_div: dsp-0-aclk-div@13c {
+			compatible = "eswin,divider-clock";
+			reg = <0x13c>;
+			#clock-cells = <0>;
+			clocks = <&gate_dspt_aclk>;
+			shift = <19>;
+			width = <1>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_dsp_0_aclk_div";
+		};
+		divider_dsp_1_aclk_div: dsp-1-aclk-div@13c {
+			compatible = "eswin,divider-clock";
+			reg = <0x13c>;
+			#clock-cells = <0>;
+			clocks = <&gate_dspt_aclk>;
+			shift = <20>;
+			width = <1>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_dsp_1_aclk_div";
+		};
+		divider_dsp_2_aclk_div: dsp-2-aclk-div@13c {
+			compatible = "eswin,divider-clock";
+			reg = <0x13c>;
+			#clock-cells = <0>;
+			clocks = <&gate_dspt_aclk>;
+			shift = <21>;
+			width = <1>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_dsp_2_aclk_div";
+		};
+		divider_dsp_3_aclk_div: dsp-3-aclk-div@13c {
+			compatible = "eswin,divider-clock";
+			reg = <0x13c>;
+			#clock-cells = <0>;
+			clocks = <&gate_dspt_aclk>;
+			shift = <22>;
+			width = <1>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_dsp_3_aclk_div";
+		};
+		divider_d2d_aclk_div: d2d-aclk-div@140 {
+			compatible = "eswin,divider-clock";
+			reg = <0x140>;
+			#clock-cells = <0>;
+			clocks = <&mux_d2d_aclk_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_d2d_aclk_div";
+		};
+		divider_hsp_aclk_div: hsp-aclk-div@148 {
+			compatible = "eswin,divider-clock";
+			reg = <0x148>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_hsp_aclk_div";
+		};
+		divider_sata_phy_ref_div: sata-phy-ref-div@154 {
+			compatible = "eswin,divider-clock";
+			reg = <0x154>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll1_fout2>;
+			shift = <0>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_sata_phy_ref_div";
+		};
+		divider_eth_txclk_div_0: eth-0-txclk-div@158 {
+			compatible = "eswin,divider-clock";
+			reg = <0x158>;
+			#clock-cells = <0>;
+			clocks = <&mux_eth_core_2mux1>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_eth_txclk_div_0";
+		};
+		divider_eth_txclk_div_1: eth-1-txclk-div@15c {
+			compatible = "eswin,divider-clock";
+			reg = <0x15c>;
+			#clock-cells = <0>;
+			clocks = <&mux_eth_core_2mux1>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_eth_txclk_div_1";
+		};
+		divider_mshc_core_div_0: mshc-0-core-div@160 {
+			compatible = "eswin,divider-clock";
+			reg = <0x160>;
+			#clock-cells = <0>;
+			clocks = <&mux_mshcore_root_3mux1_0>;
+			shift = <4>;
+			width = <12>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_mshc_core_div_0";
+		};
+		divider_mshc_core_div_1: mshc-1-core-div@164 {
+			compatible = "eswin,divider-clock";
+			reg = <0x164>;
+			#clock-cells = <0>;
+			clocks = <&mux_mshcore_root_3mux1_1>;
+			shift = <4>;
+			width = <12>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_mshc_core_div_1";
+		};
+		divider_mshc_core_div_2: mshc-2-core-div@168 {
+			compatible = "eswin,divider-clock";
+			reg = <0x168>;
+			#clock-cells = <0>;
+			clocks = <&mux_mshcore_root_3mux1_2>;
+			shift = <4>;
+			width = <12>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_mshc_core_div_2";
+		};
+		divider_pcie_aclk_div: pcie-aclk-div@170 {
+			compatible = "eswin,divider-clock";
+			reg = <0x170>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll2_fout2>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_pcie_aclk_div";
+		};
+		divider_npu_aclk_div: npu-aclk-div@178 {
+			compatible = "eswin,divider-clock";
+			reg = <0x178>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_npu_aclk_div";
+		};
+		divider_npu_llc_src0_div: npu-llc-src0-div@17c {
+			compatible = "eswin,divider-clock";
+			reg = <0x17c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_npu_llc_src0_div";
+		};
+		divider_npu_llc_src1_div: npu-llc-src1-div@17c {
+			compatible = "eswin,divider-clock";
+			reg = <0x17c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll2_fout1>;
+			shift = <8>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_npu_llc_src1_div";
+		};
+		divider_npu_coreclk_div: npu-coreclk-div@180 {
+			compatible = "eswin,divider-clock";
+			reg = <0x180>;
+			#clock-cells = <0>;
+			clocks = <&mux_npu_core_3mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_npu_coreclk_div";
+		};
+		divider_npu_e31_div: npu-e31-div@180 {
+			compatible = "eswin,divider-clock";
+			reg = <0x180>;
+			#clock-cells = <0>;
+			clocks = <&mux_npu_e31_3mux1>;
+			shift = <12>;
+			width = <4>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_npu_e31_div";
+		};
+		divider_vi_dw_div: vi-dw-div@184 {
+			compatible = "eswin,divider-clock";
+			reg = <0x184>;
+			#clock-cells = <0>;
+			clocks = <&mux_vi_dw_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_dw_div";
+		};
+		divider_vi_aclk_div: vi-aclk-div@188 {
+			compatible = "eswin,divider-clock";
+			reg = <0x188>;
+			#clock-cells = <0>;
+			clocks = <&mux_vi_aclk_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_aclk_div";
+		};
+		divider_vi_dig_isp_div: vi-dig-isp-div@18c {
+			compatible = "eswin,divider-clock";
+			reg = <0x18c>;
+			#clock-cells = <0>;
+			clocks = <&mux_vi_dig_isp_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_dig_isp_div";
+		};
+		divider_vi_dvp_div: vi-dvp-div@190 {
+			compatible = "eswin,divider-clock";
+			reg = <0x190>;
+			#clock-cells = <0>;
+			clocks = <&mux_vi_dvp_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_dvp_div";
+		};
+		divider_vi_shutter_div_0: vi-shutter-0-div@194 {
+			compatible = "eswin,divider-clock";
+			reg = <0x194>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_shutter_div_0";
+		};
+		divider_vi_shutter_div_1: vi-shutter-1-div@198 {
+			compatible = "eswin,divider-clock";
+			reg = <0x198>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_shutter_div_1";
+		};
+		divider_vi_shutter_div_2: vi-shutter-2-div@19c {
+			compatible = "eswin,divider-clock";
+			reg = <0x19c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_shutter_div_2";
+		};
+		divider_vi_shutter_div_3: vi-shutter-3-div@1a0 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1a0>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_shutter_div_3";
+		};
+		divider_vi_shutter_div_4: vi-shutter-4-div@1a4 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1a4>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_shutter_div_4";
+		};
+		divider_vi_shutter_div_5: vi-shutter-5-div@1a8 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1a8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <4>;
+			width = <7>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vi_shutter_div_5";
+		};
+		divider_vo_aclk_div: vo-aclk-div@1b0 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1b0>;
+			#clock-cells = <0>;
+			clocks = <&mux_vo_aclk_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vo_aclk_div";
+		};
+		divider_iesmclk_div: iesmclk-div@1b4 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1b4>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout3>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_iesmclk_div";
+		};
+		divider_vo_pixel_div: vo-pixel-div@1b8 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1b8>;
+			#clock-cells = <0>;
+			clocks = <&mux_vo_pixel_root_2mux1>;
+			shift = <4>;
+			width = <6>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vo_pixel_div";
+		};
+		divider_vo_mclk_div: vo-mclk-div@1bc {
+			compatible = "eswin,divider-clock";
+			reg = <0x1bc>;
+			#clock-cells = <0>;
+			clocks = <&clk_apll_fout1>;
+			shift = <4>;
+			width = <8>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vo_mclk_div";
+		};
+		divider_vo_cec_div: vo-cec-div@1c0 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1c0>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout2>;
+			shift = <16>;
+			width = <16>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_vo_cec_div";
+		};
+		divider_vc_aclk_div: vc-aclk-div@1c4 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1c4>;
+			#clock-cells = <0>;
+			clocks = <&mux_vcaclk_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vc_aclk_div";
+		};
+		divider_g2d_div: g2d-div@1cc {
+			compatible = "eswin,divider-clock";
+			reg = <0x1cc>;
+			#clock-cells = <0>;
+			clocks = <&mux_dsp_aclk_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_g2d_div";
+		};
+		divider_aondma_axi_div: aondma-axi-div@1e4 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1d4>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_aondma_axi_div";
+		};
+		divider_je_div: je-div@1d4 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1d4>;
+			#clock-cells = <0>;
+			clocks = <&mux_vcdec_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_je_div";
+		};
+		divider_jd_div: jd-div@1d8 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1d8>;
+			#clock-cells = <0>;
+			clocks = <&mux_vcdec_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_jd_div";
+		};
+		divider_vd_div: vd-div@1dc {
+			compatible = "eswin,divider-clock";
+			reg = <0x1dc>;
+			#clock-cells = <0>;
+			clocks = <&mux_vcdec_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_vd_div";
+		};
+		divider_ve_div: ve-div@1e0 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1e0>;
+			#clock-cells = <0>;
+			clocks = <&mux_vcdec_root_2mux1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_ve_div";
+		};
+		divider_aon_rtc_div: aon-rtc-div@1ec{
+			compatible = "eswin,divider-clock";
+			reg = <0x1ec>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_clk_1m_div24>;
+			shift = <21>;
+			width = <11>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_aon_rtc_div";
+		};
+		divider_u84_rtc_toggle: u84-rtc-toggle-div@1ec {
+			compatible = "eswin,divider-clock";
+			reg = <0x1ec>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			shift = <16>;
+			width = <5>;
+			div-flags = <0x5>;
+			clock-output-names = "divider_u84_rtc_toggle";
+		};
+		divider_crypto_div: crypto-div@1f4 {
+			compatible = "eswin,divider-clock";
+			reg = <0x1f4>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout1>;
+			shift = <4>;
+			width = <4>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_crypto_div";
+		};
+		divider_sys_cfg_div: sys-cfg-div@20c {
+			compatible = "eswin,divider-clock";
+			reg = <0x20c>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout3>;
+			shift = <4>;
+			width = <3>;
+			div-flags = <0x1>;
+			clock-output-names = "divider_sys_cfg_div";
+		};
+		/* gate clock */
+		gate_clk_spll0_fout2: clk-spll0-fout2-gate@8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll0_fout2>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_spll0_fout2";
+		};
+		gate_noc_nsp_clk: noc-nsp-clk-gate@100 {
+			compatible = "eswin,gate-clock";
+			reg = <0x100>;
+			#clock-cells = <0>;
+			clocks = <&divider_noc_nsp_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_noc_nsp_clk";
+		};
+		gate_clk_bootspi: clk-bootspi-gate@104 {
+			compatible = "eswin,gate-clock";
+			reg = <0x104>;
+			#clock-cells = <0>;
+			clocks = <&mux_bootspi_clk_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_bootspi";
+		};
+		gate_clk_bootspi_cfg: clk-bootspi-cfg-gate@108 {
+			compatible = "eswin,gate-clock";
+			reg = <0x108>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_bootspi_cfg";
+		};
+		gate_clk_scpu_core: clk-scpu-core-gate@10c {
+			compatible = "eswin,gate-clock";
+			reg = <0x10c>;
+			#clock-cells = <0>;
+			clocks = <&mux_scpu_core_clk_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_scpu_core";
+		};
+		gate_clk_scpu_bus: clk-scpu-bus-gate@110 {
+			compatible = "eswin,gate-clock";
+			reg = <0x110>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_scpu_bus_div2>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_scpu_bus";
+		};
+		gate_clk_lpcpu_core: clk-lpcpu-core-gate@114 {
+			compatible = "eswin,gate-clock";
+			reg = <0x114>;
+			#clock-cells = <0>;
+			clocks = <&mux_lpcpu_core_clk_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_lpcpu_core";
+		};
+		gate_clk_lpcpu_bus: clk-lpcpu-bus-gate@118 {
+			compatible = "eswin,gate-clock";
+			reg = <0x118>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_lpcpu_bus_div2>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_lpcpu_bus";
+		};
+		gate_tcu_aclk: tcu-aclk-gate@11c {
+			compatible = "eswin,gate-clock";
+			reg = <0x11c>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_tcu_aclk";
+		};
+		gate_tcu_cfg_clk: tcu-cfg-clk-gate@120 {
+			compatible = "eswin,gate-clock";
+			reg = <0x120>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_tcu_cfg_clk";
+		};
+		gate_ddrt_cfg_clk: ddrt-cfg-clk-gate@124 {
+			compatible = "eswin,gate-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <9>;
+			clock-output-names = "gate_ddrt_cfg_clk";
+		};
+		gate_ddrt0_p0_aclk: ddrt0-p0-aclk-gate@124 {
+			compatible = "eswin,gate-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <4>;
+			clock-output-names = "gate_ddrt0_p0_aclk";
+		};
+		gate_ddrt0_p1_aclk: ddrt0-p1-aclk-gate@124 {
+			compatible = "eswin,gate-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <5>;
+			clock-output-names = "gate_ddrt0_p1_aclk";
+		};
+		gate_ddrt0_p2_aclk: ddrt0-p2-aclk-gate@124 {
+			compatible = "eswin,gate-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <6>;
+			clock-output-names = "gate_ddrt0_p2_aclk";
+		};
+		gate_ddrt0_p3_aclk: ddrt0-p3-aclk-gate@124 {
+			compatible = "eswin,gate-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <7>;
+			clock-output-names = "gate_ddrt0_p3_aclk";
+		};
+		gate_ddrt0_p4_aclk: ddrt0-p4-aclk-gate@124 {
+			compatible = "eswin,gate-clock";
+			reg = <0x124>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <8>;
+			clock-output-names = "gate_ddrt0_p4_aclk";
+		};
+		gate_ddrt1_p0_aclk: ddrt1-p0-aclk-gate@128 {
+			compatible = "eswin,gate-clock";
+			reg = <0x128>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <4>;
+			clock-output-names = "gate_ddrt1_p0_aclk";
+		};
+		gate_ddrt1_p1_aclk: ddrt1-p1-aclk-gate@128 {
+			compatible = "eswin,gate-clock";
+			reg = <0x128>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <5>;
+			clock-output-names = "gate_ddrt1_p1_aclk";
+		};
+		gate_ddrt1_p2_aclk: ddrt1-p2-aclk-gate@128 {
+			compatible = "eswin,gate-clock";
+			reg = <0x128>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <6>;
+			clock-output-names = "gate_ddrt1_p2_aclk";
+		};
+		gate_ddrt1_p3_aclk: ddrt1-p3-aclk-gate@128 {
+			compatible = "eswin,gate-clock";
+			reg = <0x128>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <7>;
+			clock-output-names = "gate_ddrt1_p3_aclk";
+		};
+		gate_ddrt1_p4_aclk: ddrt1-p4-aclk-gate@128 {
+			compatible = "eswin,gate-clock";
+			reg = <0x128>;
+			#clock-cells = <0>;
+			clocks = <&divider_ddr_aclk_div>;
+			bit-index = <8>;
+			clock-output-names = "gate_ddrt1_p4_aclk";
+		};
+		gate_gpu_aclk: gpu-aclk-gate@12c {
+			compatible = "eswin,gate-clock";
+			reg = <0x12c>;
+			#clock-cells = <0>;
+			clocks = <&divider_gpu_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_gpu_aclk";
+		};
+		gate_gpu_cfg_clk: gpu-cfg-clk-gate@130 {
+			compatible = "eswin,gate-clock";
+			reg = <0x130>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_gpu_cfg_clk";
+		};
+		gate_gpu_gray_clk: gpu-gray-clk-gate@134 {
+			compatible = "eswin,gate-clock";
+			reg = <0x134>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			bit-index = <31>;
+			clock-output-names = "gate_gpu_gray_clk";
+		};
+		gate_dspt_aclk: dspt-aclk-gate@138 {
+			compatible = "eswin,gate-clock";
+			reg = <0x138>;
+			#clock-cells = <0>;
+			clocks = <&divider_dsp_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_dspt_aclk";
+		};
+		gate_dspt_cfg_clk: dspt-cfg-clk-gate@13c {
+			compatible = "eswin,gate-clock";
+			reg = <0x13c>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_dspt_cfg_clk";
+		};
+		gate_d2d_aclk: d2d-aclk-gate@140 {
+			compatible = "eswin,gate-clock";
+			reg = <0x140>;
+			#clock-cells = <0>;
+			clocks = <&divider_d2d_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_d2d_aclk";
+		};
+		gate_d2d_cfg_clk: d2d-cfg-clk-gate@144 {
+			compatible = "eswin,gate-clock";
+			reg = <0x144>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_d2d_cfg_clk";
+		};
+		gate_clk_hsp_aclk: clk-hsp-aclk-gate@148 {
+			compatible = "eswin,gate-clock";
+			reg = <0x148>;
+			#clock-cells = <0>;
+			clocks = <&divider_hsp_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_hsp_aclk";
+		};
+		gate_hsp_dma0_clk: hsp-dma0-clk-gate@148 {
+			compatible = "eswin,gate-clock";
+			reg = <0x148>;
+			#clock-cells = <0>;
+			clocks = <&gate_clk_hsp_aclk>;
+			bit-index = <0>;
+			clock-output-names = "gate_hsp_dma0_clk";
+		};
+		gate_hsp_dma0_clk_test: hsp-dma0-clk-test-gate@148 {
+			compatible = "eswin,gate-clock";
+			reg = <0x148>;
+			#clock-cells = <0>;
+			clocks = <&gate_clk_hsp_aclk>;
+			bit-index = <1>;
+			clock-output-names = "gate_hsp_dma0_clk_test";
+		};
+		gate_clk_hsp_cfgclk: clk-hsp-cfgclk-gate@14c {
+			compatible = "eswin,gate-clock";
+			reg = <0x14c>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_hsp_cfgclk";
+		};
+		gate_hsp_sata_rbc_clk: hsp-sata-rbc-clk-gate@150 {
+			compatible = "eswin,gate-clock";
+			reg = <0x150>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_spll1_fout2>;
+			bit-index = <0>;
+			clock-output-names = "gate_hsp_sata_rbc_clk";
+		};
+		gate_hsp_sata_oob_clk: hsp-sata-oob-clk-gate@154 {
+			compatible = "eswin,gate-clock";
+			reg = <0x154>;
+			#clock-cells = <0>;
+			clocks = <&mux_sata_phy_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_hsp_sata_oob_clk";
+		};
+		gate_hsp_eth0_core_clk: hsp-eth0-core-clk-gate@158 {
+			compatible = "eswin,gate-clock";
+			reg = <0x158>;
+			#clock-cells = <0>;
+			clocks = <&divider_eth_txclk_div_0>;
+			bit-index = <0>;
+			clock-output-names = "gate_hsp_eth0_core_clk";
+		};
+		gate_hsp_rmii_ref_0: hsp-rmii-ref-0-gate@158 {
+			compatible = "eswin,gate-clock";
+			reg = <0x158>;
+			#clock-cells = <0>;
+			clocks = <&mux_rmii_ref_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_hsp_rmii_ref_0";
+		};
+		gate_hsp_eth1_core_clk: hsp-eth1-core-clk-gate@15c {
+			compatible = "eswin,gate-clock";
+			reg = <0x15c>;
+			#clock-cells = <0>;
+			clocks = <&divider_eth_txclk_div_1>;
+			bit-index = <0>;
+			clock-output-names = "gate_hsp_eth1_core_clk";
+		};
+		gate_hsp_rmii_ref_1: hsp-rmii-ref-1-gate@15c {
+			compatible = "eswin,gate-clock";
+			reg = <0x15c>;
+			#clock-cells = <0>;
+			clocks = <&mux_rmii_ref_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_hsp_rmii_ref_1";
+		};
+		gate_hsp_mshc0_core_clk: hsp-mshc0-core-clk-gate@160 {
+			compatible = "eswin,gate-clock";
+			reg = <0x160>;
+			#clock-cells = <0>;
+			clocks = <&divider_mshc_core_div_0>;
+			bit-index = <16>;
+			clock-output-names = "gate_hsp_mshc0_core_clk";
+		};
+		gate_hsp_mshc1_core_clk: hsp-mshc1-core-clk-gate@164 {
+			compatible = "eswin,gate-clock";
+			reg = <0x164>;
+			#clock-cells = <0>;
+			clocks = <&divider_mshc_core_div_1>;
+			bit-index = <16>;
+			clock-output-names = "gate_hsp_mshc1_core_clk";
+		};
+		gate_hsp_mshc2_core_clk: hsp-mshc2-core-clk-gate@168 {
+			compatible = "eswin,gate-clock";
+			reg = <0x168>;
+			#clock-cells = <0>;
+			clocks = <&divider_mshc_core_div_2>;
+			bit-index = <16>;
+			clock-output-names = "gate_hsp_mshc2_core_clk";
+		};
+		gate_pciet_aclk: pciet-aclk-gate@170 {
+			compatible = "eswin,gate-clock";
+			reg = <0x170>;
+			#clock-cells = <0>;
+			clocks = <&divider_pcie_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_pciet_aclk";
+		};
+		gate_pciet_aux_clk: pciet-aux-clk-gate@174 {
+			compatible = "eswin,gate-clock";
+			reg = <0x174>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_pcie_aux_div4>;
+			bit-index = <1>;
+			clock-output-names = "gate_pciet_aux_clk";
+		};
+		gate_pciet_cfg_clk: pciet-cfg-clk-gate@174 {
+			compatible = "eswin,gate-clock";
+			reg = <0x174>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_pciet_cfg_clk";
+		};
+		gate_pciet_cr_clk: pciet-cr-clk-gate@174 {
+			compatible = "eswin,gate-clock";
+			reg = <0x174>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_pcie_cr_div2>;
+			bit-index = <0>;
+			clock-output-names = "gate_pciet_cr_clk";
+		};
+		gate_npu_aclk: npu-aclk-gate@178 {
+			compatible = "eswin,gate-clock";
+			reg = <0x178>;
+			#clock-cells = <0>;
+			clocks = <&divider_npu_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_npu_aclk";
+		};
+		gate_npu_cfg_clk: npu-cfg-clk-gate@178 {
+			compatible = "eswin,gate-clock";
+			reg = <0x178>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <30>;
+			clock-output-names = "gate_npu_cfg_clk";
+		};
+		gate_npu_llc_aclk: npu-llc-aclk-gate@17c {
+			compatible = "eswin,gate-clock";
+			reg = <0x17c>;
+			#clock-cells = <0>;
+			clocks = <&mux_npu_llclk_3mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_npu_llc_aclk";
+		};
+		gate_npu_clk: npu-clk-gate@180 {
+			compatible = "eswin,gate-clock";
+			reg = <0x180>;
+			#clock-cells = <0>;
+			clocks = <&divider_npu_coreclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_npu_clk";
+		};
+		gate_npu_e31_clk: npu-e31-clk-gate@180 {
+			compatible = "eswin,gate-clock";
+			reg = <0x180>;
+			#clock-cells = <0>;
+			clocks = <&divider_npu_e31_div>;
+			bit-index = <30>;
+			clock-output-names = "gate_npu_e31_clk";
+		};
+		gate_vi_dig_dw_clk: vi-dig-dw-clk-gate@184 {
+			compatible = "eswin,gate-clock";
+			reg = <0x184>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_dw_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_dig_dw_clk";
+		};
+		gate_vi_aclk: vi-aclk-gate@188 {
+			compatible = "eswin,gate-clock";
+			reg = <0x188>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_aclk";
+		};
+		gate_vi_cfg_clk: vi-cfg-clk-gate@188 {
+			compatible = "eswin,gate-clock";
+			reg = <0x188>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <30>;
+			clock-output-names = "gate_vi_cfg_clk";
+		};
+		gate_vi_dig_isp_clk: vi-dig-isp-clk-gate@18c {
+			compatible = "eswin,gate-clock";
+			reg = <0x18c>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_dig_isp_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_dig_isp_clk";
+		};
+		gate_vi_dvp_clk: vi-dvp-clk-gate@190 {
+			compatible = "eswin,gate-clock";
+			reg = <0x190>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_dvp_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_dvp_clk";
+		};
+		gate_vi_shutter_0: vi-shutter-0-gate@194 {
+			compatible = "eswin,gate-clock";
+			reg = <0x194>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_shutter_div_0>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_shutter_0";
+		};
+		gate_vi_shutter_1: vi-shutter-1-gate@198 {
+			compatible = "eswin,gate-clock";
+			reg = <0x198>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_shutter_div_1>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_shutter_1";
+		};
+		gate_vi_shutter_2: vi-shutter-2-gate@19c {
+			compatible = "eswin,gate-clock";
+			reg = <0x19c>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_shutter_div_2>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_shutter_2";
+		};
+		gate_vi_shutter_3: vi-shutter-3-gate@1a0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1a0>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_shutter_div_3>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_shutter_3";
+		};
+		gate_vi_shutter_4: vi-shutter-4-gate@1a4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1a4>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_shutter_div_4>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_shutter_4";
+		};
+		gate_vi_shutter_5: vi-shutter-5-gate@1a8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1a8>;
+			#clock-cells = <0>;
+			clocks = <&divider_vi_shutter_div_5>;
+			bit-index = <31>;
+			clock-output-names = "gate_vi_shutter_5";
+		};
+		gate_vi_phy_cfg: vi-phy-cfg-gate@1ac {
+			compatible = "eswin,gate-clock";
+			reg = <0x1ac>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			bit-index = <1>;
+			clock-output-names = "gate_vi_phy_cfg";
+		};
+		gate_vi_phy_txclkesc: vi-phy-txclkesc-gate@1ac {
+			compatible = "eswin,gate-clock";
+			reg = <0x1ac>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_mipi_txesc_div10>;
+			bit-index = <0>;
+			clock-output-names = "gate_vi_phy_txclkesc";
+		};
+		gate_vo_aclk: vo-aclk-gate@1b0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1b0>;
+			#clock-cells = <0>;
+			clocks = <&divider_vo_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vo_aclk";
+		};
+		gate_vo_cfg_clk: vo-cfg-clk-gate@1b0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1b0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <30>;
+			clock-output-names = "gate_vo_cfg_clk";
+		};
+		gate_vo_hdmi_iesmclk: vo-hdmi-iesmclk-gate@1b4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1b4>;
+			#clock-cells = <0>;
+			clocks = <&divider_iesmclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vo_hdmi_iesmclk";
+		};
+		gate_vo_pixel_clk: vo-pixel-clk-gate@1b8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1b8>;
+			#clock-cells = <0>;
+			clocks = <&divider_vo_pixel_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vo_pixel_clk";
+		};
+		gate_vo_i2s_mclk: vo-i2s-mclk-gate@1bc {
+			compatible = "eswin,gate-clock";
+			reg = <0x1bc>;
+			#clock-cells = <0>;
+			clocks = <&mux_vo_mclk_2mux_ext_mclk>;
+			bit-index = <31>;
+			clock-output-names = "gate_vo_i2s_mclk";
+		};
+		gate_vo_cr_clk: vo-cr-clk-gate@1c0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1c0>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_mipi_txesc_div10>;
+			bit-index = <1>;
+			clock-output-names = "gate_vo_cr_clk";
+		};
+		gate_vc_aclk: vc-aclk-gate@1c4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1c4>;
+			#clock-cells = <0>;
+			clocks = <&divider_vc_aclk_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vc_aclk";
+		};
+		gate_g2d_aclk: g2d-aclk-gate@1cc {
+			compatible = "eswin,gate-clock";
+			reg = <0x1cc>;
+			#clock-cells = <0>;
+			clocks = <&divider_g2d_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_g2d_aclk";
+		};
+		gate_g2d_cfg_clk: g2d-cfg-clk-gate@1cc {
+			compatible = "eswin,gate-clock";
+			reg = <0x1cc>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <28>;
+			clock-output-names = "gate_g2d_cfg_clk";
+		};
+		gate_g2d_clk: g2d-clk-gate@1cc {
+			compatible = "eswin,gate-clock";
+			reg = <0x1cc>;
+			#clock-cells = <0>;
+			clocks = <&divider_g2d_div>;
+			bit-index = <30>;
+			clock-output-names = "gate_g2d_clk";
+		};
+		gate_vc_cfg_clk: vc-cfg-clk-gate@1d0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <0>;
+			clock-output-names = "gate_vc_cfg_clk";
+		};
+		gate_vc_jd_pclk: vc-jd-pclk-gate@1d0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <1>;
+			clock-output-names = "gate_vc_jd_pclk";
+		};
+		gate_vc_je_pclk: vc-je-pclk-gate@1d0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <2>;
+			clock-output-names = "gate_vc_je_pclk";
+		};
+		gate_vc_mon_pclk: vc-mon-pclk-gate@1d0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <3>;
+			clock-output-names = "gate_vc_mon_pclk";
+		};
+		gate_vc_vd_pclk: vc-vd-pclk-gate@1d0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <4>;
+			clock-output-names = "gate_vc_vd_pclk";
+		};
+		gate_vc_ve_pclk: vc-ve-pclk-gate@1d0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <5>;
+			clock-output-names = "gate_vc_ve_pclk";
+		};
+		gate_vc_je_clk: vc-je-clk-gate@1d4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d4>;
+			#clock-cells = <0>;
+			clocks = <&divider_je_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vc_je_clk";
+		};
+		gate_vc_jd_clk: vc-jd-clk-gate@1d8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1d8>;
+			#clock-cells = <0>;
+			clocks = <&divider_jd_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vc_jd_clk";
+		};
+		gate_vc_vd_clk: vc-vd-clk-gate@1dc {
+			compatible = "eswin,gate-clock";
+			reg = <0x1dc>;
+			#clock-cells = <0>;
+			clocks = <&divider_vd_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vc_vd_clk";
+		};
+		gate_vc_ve_clk: vc-ve-clk-gate@1e0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e0>;
+			#clock-cells = <0>;
+			clocks = <&divider_ve_div>;
+			bit-index = <31>;
+			clock-output-names = "gate_vc_ve_clk";
+		};
+		gate_aondma_aclk: aondma-aclk-gate@1e4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e4>;
+			#clock-cells = <0>;
+			clocks = <&mux_aondma_axi2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_aondma_aclk";
+		};
+		gate_aon_aclk: aon-aclk-gate@1e4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e4>;
+			#clock-cells = <0>;
+			clocks = <&mux_aondma_axi2mux1>;
+			bit-index = <29>;
+			clock-output-names = "gate_aon_aclk";
+		};
+		gate_clk_aondma_cfg: clk-aondma-cfg-gate@1e4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e4>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <30>;
+			clock-output-names = "gate_clk_aondma_cfg";
+		};
+		gate_timer3_clk8: timer3-clk8-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_vpll_fout3>;
+			bit-index = <8>;
+			clock-output-names = "gate_timer3_clk8";
+		};
+		gate_timer_pclk_0: timer-pclk-0-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <4>;
+			clock-output-names = "gate_timer_pclk_0";
+		};
+		gate_timer_pclk_1: timer-pclk-1-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <5>;
+			clock-output-names = "gate_timer_pclk_1";
+		};
+		gate_timer_pclk_2: timer-pclk-2-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <6>;
+			clock-output-names = "gate_timer_pclk_2";
+		};
+		gate_timer_pclk_3: timer-pclk-3-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <7>;
+			clock-output-names = "gate_timer_pclk_3";
+		};
+		gate_time_clk_0: time-clk-0-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			bit-index = <0>;
+			clock-output-names = "gate_time_clk_0";
+		};
+		gate_time_clk_1: time-clk-1-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			bit-index = <1>;
+			clock-output-names = "gate_time_clk_1";
+		};
+		gate_time_clk_2: time-clk-2-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			bit-index = <2>;
+			clock-output-names = "gate_time_clk_2";
+		};
+		gate_time_clk_3: time-clk-3-gate@1e8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1e8>;
+			#clock-cells = <0>;
+			clocks = <&fixed_rate_clk_xtal_24m>;
+			bit-index = <3>;
+			clock-output-names = "gate_time_clk_3";
+		};
+		gate_clk_rtc: clk-rtc-gate@1ec {
+			compatible = "eswin,gate-clock";
+			reg = <0x1ec>;
+			#clock-cells = <0>;
+			clocks = <&divider_aon_rtc_div>;
+			bit-index = <1>;
+			clock-output-names = "gate_clk_rtc";
+		};
+		gate_clk_rtc_cfg: clk-rtc-cfg-gate@1ec {
+			compatible = "eswin,gate-clock";
+			reg = <0x1ec>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <2>;
+			clock-output-names = "gate_clk_rtc_cfg";
+		};
+		gate_clk_pka_cfg: clk-pka-cfg-gate@1f0 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1f0>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_pka_cfg";
+		};
+		gate_clk_crypto: clk-crypto-gate@1f4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1f4>;
+			#clock-cells = <0>;
+			clocks = <&divider_crypto_div>;
+			bit-index = <30>;
+			clock-output-names = "gate_clk_crypto";
+		};
+		gate_clk_spacc_cfg: clk-spacc-cfg-gate@1f4 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1f4>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_spacc_cfg";
+		};
+		gate_clk_trng_cfg: clk-trng-cfg-gate@1f8 {
+			compatible = "eswin,gate-clock";
+			reg = <0x1f8>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_trng_cfg";
+		};
+		gate_clk_otp_cfg: clk-otp-cfg-gate@1fc {
+			compatible = "eswin,gate-clock";
+			reg = <0x1fc>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_clk_otp_cfg";
+		};
+		gate_i2c0_pclk: i2c0-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <7>;
+			clock-output-names = "gate_i2c0_pclk";
+		};
+		gate_i2c1_pclk: i2c1-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <8>;
+			clock-output-names = "gate_i2c1_pclk";
+		};
+		gate_i2c2_pclk: i2c2-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <9>;
+			clock-output-names = "gate_i2c2_pclk";
+		};
+		gate_i2c3_pclk: i2c3-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <10>;
+			clock-output-names = "gate_i2c3_pclk";
+		};
+		gate_i2c4_pclk: i2c4-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <11>;
+			clock-output-names = "gate_i2c4_pclk";
+		};
+		gate_i2c5_pclk: i2c5-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <12>;
+			clock-output-names = "gate_i2c5_pclk";
+		};
+		gate_i2c6_pclk: i2c6-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <13>;
+			clock-output-names = "gate_i2c6_pclk";
+		};
+		gate_i2c7_pclk: i2c7-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <14>;
+			clock-output-names = "gate_i2c7_pclk";
+		};
+		gate_i2c8_pclk: i2c8-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <15>;
+			clock-output-names = "gate_i2c8_pclk";
+		};
+		gate_i2c9_pclk: i2c9-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <16>;
+			clock-output-names = "gate_i2c9_pclk";
+		};
+		gate_lsp_fan_pclk: lsp-fan-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <0>;
+			clock-output-names = "gate_lsp_fan_pclk";
+		};
+		gate_lsp_pvt_pclk: lsp-pvt-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <1>;
+			clock-output-names = "gate_lsp_pvt_pclk";
+		};
+		gate_lsp_ssi0_pclk: lsp-ssi0-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <26>;
+			clock-output-names = "gate_lsp_ssi0_pclk";
+		};
+		gate_lsp_ssi1_pclk: lsp-ssi1-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <27>;
+			clock-output-names = "gate_lsp_ssi1_pclk";
+		};
+		gate_lsp_timer_pclk: lsp-timer-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <25>;
+			clock-output-names = "gate_lsp_timer_pclk";
+		};
+		gate_lspart0_pclk: lsp-uart0-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <17>;
+			clock-output-names = "gate_lsp_uart0_pclk";
+		};
+		gate_lsp_uart1_pclk: lsp-uart1-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <18>;
+			clock-output-names = "gate_lsp_uart1_pclk";
+		};
+		gate_lsp_uart2_pclk: lsp-uart2-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <19>;
+			clock-output-names = "gate_lsp_uart2_pclk";
+		};
+		gate_lsp_uart3_pclk: lsp-uart3-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <20>;
+			clock-output-names = "gate_lsp_uart3_pclk";
+		};
+		gate_lsp_uart4_pclk: lsp-uart4-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <21>;
+			clock-output-names = "gate_lsp_uart4_pclk";
+		};
+		gate_lsp_wdt0_pclk: lsp-wdt0-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <28>;
+			clock-output-names = "gate_lsp_wdt0_pclk";
+		};
+		gate_lsp_wdt1_pclk: lsp-wdt1-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <29>;
+			clock-output-names = "gate_lsp_wdt1_pclk";
+		};
+		gate_lsp_wdt2_pclk: lsp-wdt2-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <30>;
+			clock-output-names = "gate_lsp_wdt2_pclk";
+		};
+		gate_lsp_wdt3_pclk: lsp-wdt3-pclk-gate@200 {
+			compatible = "eswin,gate-clock";
+			reg = <0x200>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_lsp_wdt3_pclk";
+		};
+		gate_clk_mailbox_0: clk-mailbox-0-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <0>;
+			clock-output-names = "gate_clk_mailbox_0";
+		};
+		gate_clk_mailbox_1: clk-mailbox-1-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <1>;
+			clock-output-names = "gate_clk_mailbox_1";
+		};
+		gate_clk_mailbox_2: clk-mailbox-2-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <2>;
+			clock-output-names = "gate_clk_mailbox_2";
+		};
+		gate_clk_mailbox_3: clk-mailbox-3-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <3>;
+			clock-output-names = "gate_clk_mailbox_3";
+		};
+		gate_clk_mailbox_4: clk-mailbox-4-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <4>;
+			clock-output-names = "gate_clk_mailbox_4";
+		};
+		gate_clk_mailbox_5: clk-mailbox-5-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <5>;
+			clock-output-names = "gate_clk_mailbox_5";
+		};
+		gate_clk_mailbox_6: clk-mailbox-6-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <6>;
+			clock-output-names = "gate_clk_mailbox_6";
+		};
+		gate_clk_mailbox_7: clk-mailbox-7-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <7>;
+			clock-output-names = "gate_clk_mailbox_7";
+		};
+		gate_clk_mailbox_8: clk-mailbox-8-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <8>;
+			clock-output-names = "gate_clk_mailbox_8";
+		};
+		gate_clk_mailbox_9: clk-mailbox-9-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <9>;
+			clock-output-names = "gate_clk_mailbox_9";
+		};
+		gate_clk_mailbox_10: clk-mailbox-10-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <10>;
+			clock-output-names = "gate_clk_mailbox_10";
+		};
+		gate_clk_mailbox_11: clk-mailbox-11-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <11>;
+			clock-output-names = "gate_clk_mailbox_11";
+		};
+		gate_clk_mailbox_12: clk-mailbox-12-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <12>;
+			clock-output-names = "gate_clk_mailbox_12";
+		};
+		gate_clk_mailbox_13: clk-mailbox-13-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <13>;
+			clock-output-names = "gate_clk_mailbox_13";
+		};
+		gate_clk_mailbox_14: clk-mailbox-14-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <14>;
+			clock-output-names = "gate_clk_mailbox_14";
+		};
+		gate_clk_mailbox_15: clk-mailbox-15-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <15>;
+			clock-output-names = "gate_clk_mailbox_15";
+		};
+		gate_pvt0_clk: pvt0-clk-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_pvt_div20>;
+			bit-index = <16>;
+			clock-output-names = "gate_pvt0_clk";
+		};
+		gate_pvt1_clk: pvt1-clk-gate@204 {
+			compatible = "eswin,gate-clock";
+			reg = <0x204>;
+			#clock-cells = <0>;
+			clocks = <&fixed_factor_pvt_div20>;
+			bit-index = <17>;
+			clock-output-names = "gate_pvt1_clk";
+		};
+		gate_cpu_ext_src_core_0: cpu-ext-src-core-0-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <28>;
+			clock-output-names = "gate_cpu_ext_src_core_0";
+		};
+		gate_cpu_ext_src_core_1: cpu-ext-src-core-1-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <29>;
+			clock-output-names = "gate_cpu_ext_src_core_1";
+		};
+		gate_cpu_ext_src_core_2: cpu-ext-src-core-2-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <30>;
+			clock-output-names = "gate_cpu_ext_src_core_2";
+		};
+		gate_cpu_ext_src_core_3: cpu-ext-src-core-3-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_cpu_ext_src_core_3";
+		};
+		gate_clk_cpu_trace_clk_0: clk-cpu-trace-clk-0-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <24>;
+			clock-output-names = "gate_clk_cpu_trace_clk_0";
+		};
+		gate_clk_cpu_trace_clk_1: clk-cpu-trace-clk-1-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <25>;
+			clock-output-names = "gate_clk_cpu_trace_clk_1";
+		};
+		gate_clk_cpu_trace_clk_2: clk-cpu-trace-clk-2-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <26>;
+			clock-output-names = "gate_clk_cpu_trace_clk_2";
+		};
+		gate_clk_cpu_trace_clk_3: clk-cpu-trace-clk-3-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_root_3mux1>;
+			bit-index = <27>;
+			clock-output-names = "gate_clk_cpu_trace_clk_3";
+		};
+		gate_clk_cpu_trace_com_clk: clk-cpu-trace-com-clk-gate@208 {
+			compatible = "eswin,gate-clock";
+			reg = <0x208>;
+			#clock-cells = <0>;
+			clocks = <&mux_cpu_aclk_2mux1>;
+			bit-index = <23>;
+			clock-output-names = "gate_clk_cpu_trace_com_clk";
+		};
+		gate_aon_i2c0_pclk: aon-i2c0-pclk-gate@210 {
+			compatible = "eswin,gate-clock";
+			reg = <0x210>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_aon_i2c0_pclk";
+		};
+		gate_aon_i2c1_pclk: aon-i2c1-pclk-gate@214 {
+			compatible = "eswin,gate-clock";
+			reg = <0x214>;
+			#clock-cells = <0>;
+			clocks = <&mux_syscfg_clk_root_2mux1>;
+			bit-index = <31>;
+			clock-output-names = "gate_aon_i2c1_pclk";
+		};
+	};
+};
--
2.17.1


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

* Re: [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC
  2025-08-15  9:36 ` [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC dongxuyang
@ 2025-08-17  6:01   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-17  6:01 UTC (permalink / raw)
  To: dongxuyang, mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk,
	devicetree, linux-kernel, paul.walmsley, palmer, aou, alex,
	linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

On 15/08/2025 11:36, dongxuyang@eswincomputing.com wrote:
> From: Xuyang Dong <dongxuyang@eswincomputing.com>
> 
> Add device tree binding documentation for the ESWIN eic7700
> clock controller module.
> 
> Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
> ---
>  .../bindings/clock/eswin,eic7700-clock.yaml   | 381 ++++++++++++++++++
>  1 file changed, 381 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
> 
> diff --git a/Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml b/Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
> new file mode 100644
> index 000000000000..45e70ebc08e6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
> @@ -0,0 +1,381 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/eswin,eic7700-clock.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Eswin EIC7700 SoC clock controller
> +
> +maintainers:
> +  - Yifeng Huang <huangyifeng@eswincomputing.com>
> +  - Xuyang Dong <dongxuyang@eswincomputing.com>
> +
> +description:
> +  The clock controller generates and supplies clock to all the modules
> +  for eic7700 SoC.
> +
> +properties:
> +  compatible:
> +    const: eswin,eic7700-clock
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#clock-cells':
> +    const: 0
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +required:

Incorrectly placed. required is after all properties.

> +  - compatible
> +  - reg
> +  - '#clock-cells'
> +  - '#address-cells'
> +  - '#size-cells'
> +
> +patternProperties:
> +  "^fixed-rate.*":
> +    type: object
> +    $ref: /schemas/clock/fixed-clock.yaml#

No, you do not get node per clock.

> +
> +  ".*pll@[a-f0-9]+$":
> +    type: object
> +
> +    properties:
> +      compatible:
> +        const: eswin,pll-clock


Nothing explains in the changelog why this appeared. Drop all these
nodes and fake or redundant compatibles.


> +
> +      reg:
> +        items:
> +          - description: PLL's config 0 register
> +          - description: PLL's config 1 register
> +          - description: PLL's config 2 register
> +          - description: PLL's status register
> +
> +      '#clock-cells':
> +        const: 0
> +
> +      clock-output-names:
> +        maxItems: 1
> +
> +      enable-shift:
> +        description: Bit shift of the enable register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      enable-width:
> +        description: Width of the enable register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      refdiv-shift:
> +        description: Bit shift of the reference divider register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      refdiv-width:
> +        description: Width of the reference divider register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      fbdiv-shift:
> +        description: Bit shift of the feedback divider register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      fbdiv-width:
> +        description: Width of the feedback divider register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      frac-shift:
> +        description: Bit shift of the fractional divider register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      frac-width:
> +        description: Width of the fractional divider register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      postdiv1-shift:
> +        description: Bit shift of the post divider 1 register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      postdiv1-width:
> +        description: Width of the post divider 1 register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      postdiv2-shift:
> +        description: Bit shift of the post divider 2 register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      postdiv2-width:
> +        description: Width of the post divider 2 register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        maximum: 31
> +
> +      lock-shift:
> +        description: Bit shift of the lock register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +      lock-width:
> +        description: Width of the lock register.
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 31
> +
> +    required:
> +      - compatible
> +      - reg
> +      - '#clock-cells'
> +      - clock-output-names
> +      - enable-shift
> +      - enable-width
> +      - refdiv-shift
> +      - refdiv-width
> +      - fbdiv-shift
> +      - fbdiv-width
> +      - frac-shift
> +      - frac-width
> +      - postdiv1-shift
> +      - postdiv1-width
> +      - postdiv2-shift
> +      - postdiv2-width
> +      - lock-shift
> +      - lock-width
> +
> +    additionalProperties: false
> +
> +  ".*mux@[a-f0-9]+$":
> +    type: object

NAK, but anyway explain in the changelog WHY you did this...


Best regards,
Krzysztof

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

* Re: [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver
  2025-08-15  9:37 ` [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver dongxuyang
@ 2025-08-17  6:07   ` Krzysztof Kozlowski
  2025-08-19  4:46   ` Troy Mitchell
  2025-08-21 18:32   ` Brian Masney
  2 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-17  6:07 UTC (permalink / raw)
  To: dongxuyang, mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk,
	devicetree, linux-kernel, paul.walmsley, palmer, aou, alex,
	linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

On 15/08/2025 11:37, dongxuyang@eswincomputing.com wrote:
> From: Xuyang Dong <dongxuyang@eswincomputing.com>
> 
> This driver depends on the CCF framework implementation.
>   Based on this driver, other modules in the SoC can use the APIs
>   provided by CCF to perform clock-related operations.

Useless description. Instead describe the hardware and architecture of
your driver. We all know what is the purpose of CCF and how it works.

>   The driver supports eic7700 series chips.

Messed indentation.

> 
> Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
> ---
>  drivers/clk/Kconfig             |   1 +
>  drivers/clk/Makefile            |   1 +
>  drivers/clk/eswin/Kconfig       |  10 +
>  drivers/clk/eswin/Makefile      |   8 +
>  drivers/clk/eswin/clk-eic7700.c |  44 ++
>  drivers/clk/eswin/clk.c         | 734 ++++++++++++++++++++++++++++++++
>  drivers/clk/eswin/clk.h         |  69 +++
>  7 files changed, 867 insertions(+)
>  create mode 100644 drivers/clk/eswin/Kconfig
>  create mode 100644 drivers/clk/eswin/Makefile
>  create mode 100644 drivers/clk/eswin/clk-eic7700.c
>  create mode 100644 drivers/clk/eswin/clk.c
>  create mode 100644 drivers/clk/eswin/clk.h
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4d56475f94fc..184b76a406d7 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -505,6 +505,7 @@ source "drivers/clk/actions/Kconfig"
>  source "drivers/clk/analogbits/Kconfig"
>  source "drivers/clk/baikal-t1/Kconfig"
>  source "drivers/clk/bcm/Kconfig"
> +source "drivers/clk/eswin/Kconfig"
>  source "drivers/clk/hisilicon/Kconfig"
>  source "drivers/clk/imgtec/Kconfig"
>  source "drivers/clk/imx/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 18ed29cfdc11..42c61e216511 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -120,6 +120,7 @@ obj-$(CONFIG_CLK_BAIKAL_T1)		+= baikal-t1/
>  obj-y					+= bcm/
>  obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
>  obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
> +obj-$(CONFIG_ARCH_ESWIN)		+= eswin/
>  obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
>  obj-y					+= imgtec/
>  obj-y					+= imx/
> diff --git a/drivers/clk/eswin/Kconfig b/drivers/clk/eswin/Kconfig
> new file mode 100644
> index 000000000000..f2284c2d790d
> --- /dev/null
> +++ b/drivers/clk/eswin/Kconfig
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config COMMON_CLK_EIC7700
> +	bool "EIC7700 Clock Driver"
> +	depends on ARCH_ESWIN
> +	help
> +	  Build the Eswin EIC7700 SoC clock driver based on the
> +	  common clock framework. This driver provides support
> +	  for the clock control on the Eswin EIC7700 SoC,
> +	  which is essential for managing clock rates and power management.
> diff --git a/drivers/clk/eswin/Makefile b/drivers/clk/eswin/Makefile
> new file mode 100644
> index 000000000000..a3139e34ee22
> --- /dev/null
> +++ b/drivers/clk/eswin/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Eswin Clock specific Makefile
> +#
> +
> +obj-y	+= clk.o
> +
> +obj-$(CONFIG_COMMON_CLK_EIC7700)	+= clk-eic7700.o
> diff --git a/drivers/clk/eswin/clk-eic7700.c b/drivers/clk/eswin/clk-eic7700.c
> new file mode 100644
> index 000000000000..278b256b4c52
> --- /dev/null
> +++ b/drivers/clk/eswin/clk-eic7700.c
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
> + * All rights reserved.
> + *
> + * ESWIN EIC7700 CLK Provider Driver
> + *
> + * Authors:
> + *	Yifeng Huang <huangyifeng@eswincomputing.com>
> + *	Xuyang Dong <dongxuyang@eswincomputing.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>

None of these three are used.

> +#include "clk.h"
> +
> +static void __init eic7700_clk_pll_init(struct device_node *np)
> +{
> +	eswin_clk_pll_register(np);
> +}
> +
> +static void __init eic7700_clk_mux_init(struct device_node *np)
> +{
> +	eswin_clk_mux_register(np);
> +}
> +
> +static void __init eic7700_clk_div_init(struct device_node *np)
> +{
> +	eswin_clk_div_register(np);
> +}
> +
> +static void __init eic7700_clk_gate_init(struct device_node *np)
> +{
> +	eswin_clk_gate_register(np);
> +}
> +
> +CLK_OF_DECLARE(eic7700_clk_pll, "eswin,pll-clock", eic7700_clk_pll_init);
> +CLK_OF_DECLARE(eic7700_clk_mux, "eswin,mux-clock", eic7700_clk_mux_init);
> +CLK_OF_DECLARE(eic7700_clk_div, "eswin,divider-clock", eic7700_clk_div_init);
> +CLK_OF_DECLARE(eic7700_clk_gate, "eswin,gate-clock", eic7700_clk_gate_init);

That's empty wrapper. You created just one more layer of indirection,
with no use at all, instead of calling these directly.

> diff --git a/drivers/clk/eswin/clk.c b/drivers/clk/eswin/clk.c
> new file mode 100644
> index 000000000000..e227cc4664ca
> --- /dev/null
> +++ b/drivers/clk/eswin/clk.c
> @@ -0,0 +1,734 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
> + * All rights reserved.
> + *
> + * Authors:
> + *	Yifeng Huang <huangyifeng@eswincomputing.com>
> + *	Xuyang Dong <dongxuyang@eswincomputing.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/math.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +#include <linux/util_macros.h>
> +#include "clk.h"
> +
> +enum pll_clk {
> +	CLK_APLL_FOUT1 = 1,
> +	CLK_PLL_CPU
> +};
> +
> +static enum pll_clk str_to_pll_clk(const char *str)
> +{
> +	if (!strcmp(str, "clk_apll_fout1"))
> +		return CLK_APLL_FOUT1;
> +	else if (!strcmp(str, "clk_pll_cpu"))
> +		return CLK_PLL_CPU;
> +	else
> +		return 0;
> +}
> +
> +static void __iomem *parent_base;

Don't write singletons.

> +
> +static void __init get_parent_base(struct device_node *parent_np)

This is just poor code. Drop.


> +{
> +	if (!parent_base) {
> +		parent_base = of_iomap(parent_np, 0);
> +		if (IS_ERR(parent_base)) {
> +			pr_err("%s: Failed to map registers\n", __func__);
> +			parent_base = NULL;
> +		}
> +	}
> +}
> +


...

> +
> +void __init eswin_clk_gate_register(struct device_node *np)
> +{
> +	struct clk_hw *clk_hw;
> +	struct device_node *parent_np;
> +	const char *clk_name;
> +	const char *parent_name;
> +	u32 idx_bit;
> +	u32 reg;
> +	int ret;
> +
> +	parent_np = of_get_parent(np);
> +	if (!parent_np) {
> +		pr_err("%s: Failed to get parent node\n", __func__);
> +		return;
> +	}
> +
> +	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
> +		get_parent_base(parent_np);
> +	else
> +		return;

What? Don't write drivers like that. All this is completely unnecessary
and confusing code. You don't get a singleton, you don't reference it
from some other init code. It's not needed even! Design this properly so
 other clocks will be instantiated from parent clock driver. Just like
every other clock controller is doing.

> +
> +	if (IS_ERR(parent_base)) {
> +		pr_err("%s: Failed to map registers\n", __func__);

Even more spaghetti code. If you need to check for the value, you check
right after obtaining it.

> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_string(np, "clock-output-names", &clk_name);
> +	if (ret) {
> +		pr_err("%s: Missing clock-output-names\n", __func__);
> +		goto put_node;
> +	}

...

> +
> +#define CLK_FREQ_1800M 1800000000
> +#define CLK_FREQ_1700M 1700000000
> +#define CLK_FREQ_1600M 1600000000
> +#define CLK_FREQ_1500M 1500000000
> +#define CLK_FREQ_1400M 1400000000
> +#define CLK_FREQ_1300M 1300000000
> +#define CLK_FREQ_1200M 1200000000
> +#define CLK_FREQ_1000M 1000000000
> +#define CLK_FREQ_900M 900000000
> +#define CLK_FREQ_800M 800000000
> +#define CLK_FREQ_700M 700000000
> +#define CLK_FREQ_600M 600000000
> +#define CLK_FREQ_500M 500000000
> +#define CLK_FREQ_400M 400000000
> +#define CLK_FREQ_200M 200000000
> +#define CLK_FREQ_100M 100000000
> +#define CLK_FREQ_24M 24000000

Useless defines, just like: #define true 1

> +
> +#define APLL_HIGH_FREQ 983040000
> +#define APLL_LOW_FREQ 225792000
> +
> +struct eswin_clk_pll {
> +	struct clk_hw hw;
> +	void __iomem *ctrl_reg0;
> +	u8 pllen_shift;
> +	u8 pllen_width;
> +	u8 refdiv_shift;
> +	u8 refdiv_width;
> +	u8 fbdiv_shift;
Best regards,
Krzysztof

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

* Re: [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support
  2025-08-15  9:37 ` [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support dongxuyang
@ 2025-08-17  6:07   ` Krzysztof Kozlowski
  2025-08-19  8:34     ` 董绪洋
  0 siblings, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-17  6:07 UTC (permalink / raw)
  To: dongxuyang, mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk,
	devicetree, linux-kernel, paul.walmsley, palmer, aou, alex,
	linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

On 15/08/2025 11:37, dongxuyang@eswincomputing.com wrote:
> From: Xuyang Dong <dongxuyang@eswincomputing.com>
> 
> Add clock device tree support for eic7700 SoC.
> 
> Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
> ---
>  arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi | 2283 +++++++++++++++++
>  1 file changed, 2283 insertions(+)
>  create mode 100644 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> 
> diff --git a/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> new file mode 100644
> index 000000000000..405d06f9190e
> --- /dev/null
> +++ b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> @@ -0,0 +1,2283 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Copyright (c) 2025, Beijing ESWIN Computing Technology Co., Ltd.
> + */
> +
> +/ {
> +	clock-controller@51828000 {
> +		compatible = "eswin,eic7700-clock";
> +		reg = <0x000000 0x51828000 0x000000 0x80000>;
> +		#clock-cells = <0>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		/* fixed clock */
> +		fixed_rate_clk_apll_fout2: fixed-rate-apll-fout2 {

Such pattern was years ago NAKed.

No, don't ever bring nodes per clock.


Best regards,
Krzysztof

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

* Re: [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver
  2025-08-15  9:37 ` [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver dongxuyang
  2025-08-17  6:07   ` Krzysztof Kozlowski
@ 2025-08-19  4:46   ` Troy Mitchell
  2025-08-21 18:32   ` Brian Masney
  2 siblings, 0 replies; 13+ messages in thread
From: Troy Mitchell @ 2025-08-19  4:46 UTC (permalink / raw)
  To: dongxuyang, mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk,
	devicetree, linux-kernel, paul.walmsley, palmer, aou, alex,
	linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela, Troy Mitchell

On Fri, Aug 15, 2025 at 05:37:20PM +0800, dongxuyang@eswincomputing.com wrote:
> From: Xuyang Dong <dongxuyang@eswincomputing.com>
> 
> This driver depends on the CCF framework implementation.
>   Based on this driver, other modules in the SoC can use the APIs
>   provided by CCF to perform clock-related operations.
>   The driver supports eic7700 series chips.
Please align and modify according to Krzysztof's suggestion.

> 
> Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
> ---
>  drivers/clk/Kconfig             |   1 +
>  drivers/clk/Makefile            |   1 +
>  drivers/clk/eswin/Kconfig       |  10 +
>  drivers/clk/eswin/Makefile      |   8 +
>  drivers/clk/eswin/clk-eic7700.c |  44 ++
>  drivers/clk/eswin/clk.c         | 734 ++++++++++++++++++++++++++++++++
>  drivers/clk/eswin/clk.h         |  69 +++
>  7 files changed, 867 insertions(+)
>  create mode 100644 drivers/clk/eswin/Kconfig
>  create mode 100644 drivers/clk/eswin/Makefile
>  create mode 100644 drivers/clk/eswin/clk-eic7700.c
>  create mode 100644 drivers/clk/eswin/clk.c
>  create mode 100644 drivers/clk/eswin/clk.h
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4d56475f94fc..184b76a406d7 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -505,6 +505,7 @@ source "drivers/clk/actions/Kconfig"
>  source "drivers/clk/analogbits/Kconfig"
>  source "drivers/clk/baikal-t1/Kconfig"
>  source "drivers/clk/bcm/Kconfig"
> +source "drivers/clk/eswin/Kconfig"
>  source "drivers/clk/hisilicon/Kconfig"
>  source "drivers/clk/imgtec/Kconfig"
>  source "drivers/clk/imx/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 18ed29cfdc11..42c61e216511 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -120,6 +120,7 @@ obj-$(CONFIG_CLK_BAIKAL_T1)		+= baikal-t1/
>  obj-y					+= bcm/
>  obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
>  obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
> +obj-$(CONFIG_ARCH_ESWIN)		+= eswin/
>  obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
>  obj-y					+= imgtec/
>  obj-y					+= imx/
> diff --git a/drivers/clk/eswin/Kconfig b/drivers/clk/eswin/Kconfig
> new file mode 100644
> index 000000000000..f2284c2d790d
> --- /dev/null
> +++ b/drivers/clk/eswin/Kconfig
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config COMMON_CLK_EIC7700
> +	bool "EIC7700 Clock Driver"
> +	depends on ARCH_ESWIN
also COMPILE_TEST here.

> +	help
> +	  Build the Eswin EIC7700 SoC clock driver based on the
> +	  common clock framework. This driver provides support
> +	  for the clock control on the Eswin EIC7700 SoC,
no need to mention CCF.

> +	  which is essential for managing clock rates and power management.
> diff --git a/drivers/clk/eswin/Makefile b/drivers/clk/eswin/Makefile
> new file mode 100644
> index 000000000000..a3139e34ee22
> --- /dev/null
> +++ b/drivers/clk/eswin/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Eswin Clock specific Makefile
> +#
> +
> +obj-y	+= clk.o
Should we always compile this?

                - Troy

> +
> +obj-$(CONFIG_COMMON_CLK_EIC7700)	+= clk-eic7700.o
> diff --git a/drivers/clk/eswin/clk-eic7700.c b/drivers/clk/eswin/clk-eic7700.c
> new file mode 100644
> index 000000000000..278b256b4c52
> --- /dev/null
> +++ b/drivers/clk/eswin/clk-eic7700.c
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
> + * All rights reserved.
> + *
> + * ESWIN EIC7700 CLK Provider Driver
> + *
> + * Authors:
> + *	Yifeng Huang <huangyifeng@eswincomputing.com>
> + *	Xuyang Dong <dongxuyang@eswincomputing.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include "clk.h"
> +
> +static void __init eic7700_clk_pll_init(struct device_node *np)
> +{
> +	eswin_clk_pll_register(np);
> +}
> +
> +static void __init eic7700_clk_mux_init(struct device_node *np)
> +{
> +	eswin_clk_mux_register(np);
> +}
> +
> +static void __init eic7700_clk_div_init(struct device_node *np)
> +{
> +	eswin_clk_div_register(np);
> +}
> +
> +static void __init eic7700_clk_gate_init(struct device_node *np)
> +{
> +	eswin_clk_gate_register(np);
> +}
> +
> +CLK_OF_DECLARE(eic7700_clk_pll, "eswin,pll-clock", eic7700_clk_pll_init);
> +CLK_OF_DECLARE(eic7700_clk_mux, "eswin,mux-clock", eic7700_clk_mux_init);
> +CLK_OF_DECLARE(eic7700_clk_div, "eswin,divider-clock", eic7700_clk_div_init);
> +CLK_OF_DECLARE(eic7700_clk_gate, "eswin,gate-clock", eic7700_clk_gate_init);
> diff --git a/drivers/clk/eswin/clk.c b/drivers/clk/eswin/clk.c
> new file mode 100644
> index 000000000000..e227cc4664ca
> --- /dev/null
> +++ b/drivers/clk/eswin/clk.c
> @@ -0,0 +1,734 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
> + * All rights reserved.
> + *
> + * Authors:
> + *	Yifeng Huang <huangyifeng@eswincomputing.com>
> + *	Xuyang Dong <dongxuyang@eswincomputing.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/math.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +#include <linux/util_macros.h>
> +#include "clk.h"
> +
> +enum pll_clk {
> +	CLK_APLL_FOUT1 = 1,
> +	CLK_PLL_CPU
> +};
> +
> +static enum pll_clk str_to_pll_clk(const char *str)
> +{
> +	if (!strcmp(str, "clk_apll_fout1"))
> +		return CLK_APLL_FOUT1;
> +	else if (!strcmp(str, "clk_pll_cpu"))
> +		return CLK_PLL_CPU;
> +	else
> +		return 0;
> +}
> +
> +static void __iomem *parent_base;
> +
> +static void __init get_parent_base(struct device_node *parent_np)
> +{
> +	if (!parent_base) {
> +		parent_base = of_iomap(parent_np, 0);
> +		if (IS_ERR(parent_base)) {
> +			pr_err("%s: Failed to map registers\n", __func__);
> +			parent_base = NULL;
> +		}
> +	}
> +}
> +
> +/**
> + * eswin_calc_pll - calculate PLL values
> + * @frac_val: fractional divider
> + * @fbdiv_val: feedback divider
> + * @rate: reference rate
> + *
> + *   Calculate PLL values for frac and fbdiv
> + */
> +static void eswin_calc_pll(u32 *frac_val, u32 *fbdiv_val, u64 rate)
> +{
> +	u32 rem, tmp1, tmp2;
> +
> +	rate = rate * 4;
> +	rem = do_div(rate, 1000);
> +	if (rem)
> +		tmp1 = rem;
> +
> +	rem = do_div(rate, 1000);
> +	if (rem)
> +		tmp2 = rem;
> +
> +	rem = do_div(rate, 24);
> +	/* fbdiv = rate * 4 / 24000000 */
> +	*fbdiv_val = rate;
> +	/* frac = rate * 4 % 24000000 * (2 ^ 24) */
> +	*frac_val = ((1000 * (1000 * rem + tmp2) + tmp1) << 21) / 3 / 1000000;
> +}
> +
> +static inline struct eswin_clk_pll *to_pll_clk(struct clk_hw *hw)
> +{
> +	return container_of(hw, struct eswin_clk_pll, hw);
> +}
> +
> +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +			    unsigned long parent_rate)
> +{
> +	struct eswin_clk_pll *clk = to_pll_clk(hw);
> +	const char *clk_name = clk_hw_get_name(&clk->hw);
> +
> +	if (!clk_name)
> +		return -ENOMEM;
> +
> +	u32 frac_val = 0, fbdiv_val, refdiv_val = 1, postdiv1_val = 0;
> +	u32 val;
> +	int ret;
> +	struct clk *clk_cpu_mux = NULL;
> +	struct clk *clk_cpu_lp_pll = NULL;
> +	struct clk *clk_cpu_pll = NULL;
> +	int try_count = 0;
> +	bool lock_flag = false;
> +
> +	eswin_calc_pll(&frac_val, &fbdiv_val, (u64)rate);
> +
> +	/* Must switch the CPU to other CLK before we change the CPU PLL. */
> +	if (str_to_pll_clk(clk_name) == CLK_PLL_CPU) {
> +		clk_cpu_mux = __clk_lookup("mux_cpu_root_3mux1");
> +		if (!clk_cpu_mux) {
> +			pr_err("%s %d, failed to get %s\n", __func__, __LINE__,
> +			       "mux_cpu_root_3mux1");
> +			return -EINVAL;
> +		}
> +		clk_cpu_lp_pll = __clk_lookup("fixed_factor_u84_core_lp_div2");
> +		if (!clk_cpu_lp_pll) {
> +			pr_err("%s %d, failed to get %s\n", __func__, __LINE__,
> +			       "fixed_factor_u84_core_lp_div2");
> +			return -EINVAL;
> +		}
> +		ret = clk_prepare_enable(clk_cpu_lp_pll);
> +		if (ret) {
> +			pr_err("%s %d, failed to enable %s, ret %d\n",
> +			       __func__, __LINE__,
> +			       "fixed_factor_u84_core_lp_div2", ret);
> +			return ret;
> +		}
> +		clk_cpu_pll = __clk_lookup("clk_pll_cpu");
> +		if (!clk_cpu_pll) {
> +			pr_err("%s %d, failed to get %s\n", __func__, __LINE__,
> +			       "clk_pll_cpu");
> +			clk_disable_unprepare(clk_cpu_lp_pll);
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_set_parent(clk_cpu_mux, clk_cpu_lp_pll);
> +		if (ret) {
> +			pr_err("%s %d, failed to switch %s to %s, ret %d\n",
> +			       __func__, __LINE__, "mux_cpu_root_3mux1",
> +			       "fixed_factor_u84_core_lp_div2", ret);
> +			clk_disable_unprepare(clk_cpu_lp_pll);
> +			return -EPERM;
> +		}
> +	}
> +
> +	/* first disable PLL */
> +	val = readl_relaxed(clk->ctrl_reg0);
> +	val &= ~(((1 << clk->pllen_width) - 1) << clk->pllen_shift);
> +	val |= 0 << clk->pllen_shift;
> +	writel_relaxed(val, clk->ctrl_reg0);
> +
> +	val = readl_relaxed(clk->ctrl_reg0);
> +	val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift);
> +	val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift);
> +	val |= refdiv_val << clk->refdiv_shift;
> +	val |= fbdiv_val << clk->fbdiv_shift;
> +	writel_relaxed(val, clk->ctrl_reg0);
> +
> +	val = readl_relaxed(clk->ctrl_reg1);
> +	val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift);
> +	val |= frac_val << clk->frac_shift;
> +	writel_relaxed(val, clk->ctrl_reg1);
> +
> +	val = readl_relaxed(clk->ctrl_reg2);
> +	val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift);
> +	val |= postdiv1_val << clk->postdiv1_shift;
> +	writel_relaxed(val, clk->ctrl_reg2);
> +
> +	/* at last, enable PLL */
> +	val = readl_relaxed(clk->ctrl_reg0);
> +	val &= ~(((1 << clk->pllen_width) - 1) << clk->pllen_shift);
> +	val |= 1 << clk->pllen_shift;
> +	writel_relaxed(val, clk->ctrl_reg0);
> +
> +	/* usually the PLL would lock in 50us */
> +	do {
> +		usleep_range(refdiv_val * 80, refdiv_val * 80 * 2);
> +		val = readl_relaxed(clk->status_reg);
> +		if (val & 1 << clk->lock_shift) {
> +			lock_flag = true;
> +			break;
> +		}
> +	} while (try_count++ < 10);
> +
> +	if (!lock_flag) {
> +		pr_err("%s %d, failed to lock the cpu pll", __func__, __LINE__);
> +		return -EBUSY;
> +	}
> +
> +	if (str_to_pll_clk(clk_name) == CLK_PLL_CPU) {
> +		ret = clk_set_parent(clk_cpu_mux, clk_cpu_pll);
> +		if (ret) {
> +			pr_err("%s %d, failed to switch %s to %s, ret %d\n",
> +			       __func__, __LINE__, "mux_cpu_root_3mux1",
> +			       "clk_pll_cpu", ret);
> +			return -EPERM;
> +		}
> +		clk_disable_unprepare(clk_cpu_lp_pll);
> +	}
> +	return ret;
> +}
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
> +					 unsigned long parent_rate)
> +{
> +	struct eswin_clk_pll *clk = to_pll_clk(hw);
> +	const char *clk_name = clk_hw_get_name(&clk->hw);
> +
> +	if (!clk_name)
> +		return -ENOMEM;
> +
> +	u64 frac_val, fbdiv_val, refdiv_val, tmp, rem;
> +	u32 postdiv1_val;
> +	u32 val;
> +	u64 rate = 0;
> +
> +	val = readl_relaxed(clk->ctrl_reg0);
> +	val = val >> clk->fbdiv_shift;
> +	val &= ((1 << clk->fbdiv_width) - 1);
> +	fbdiv_val = val;
> +
> +	val = readl_relaxed(clk->ctrl_reg0);
> +	val = val >> clk->refdiv_shift;
> +	val &= ((1 << clk->refdiv_width) - 1);
> +	refdiv_val = val;
> +
> +	val = readl_relaxed(clk->ctrl_reg1);
> +	val = val >> clk->frac_shift;
> +	val &= ((1 << clk->frac_width) - 1);
> +	frac_val = val;
> +
> +	val = readl_relaxed(clk->ctrl_reg2);
> +	val = val >> clk->postdiv1_shift;
> +	val &= ((1 << clk->postdiv1_width) - 1);
> +	postdiv1_val = val;
> +
> +	/* rate = 24000000 * (fbdiv + frac / (2 ^ 24)) / 4 */
> +	if (str_to_pll_clk(clk_name)) {
> +		tmp = 1000 * frac_val;
> +		rem = do_div(tmp, BIT(24));
> +		if (rem)
> +			rate = (u64)(6000 * (1000 * fbdiv_val + tmp) +
> +				    ((6000 * rem) >> 24) + 1);
> +		else
> +			rate = (u64)(6000 * 1000 * fbdiv_val);
> +	}
> +
> +	return rate;
> +}
> +
> +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +			       unsigned long *parent_rate)
> +{
> +	struct eswin_clk_pll *clk = to_pll_clk(hw);
> +	const char *clk_name = clk_hw_get_name(&clk->hw);
> +
> +	if (!clk_name)
> +		return -ENOMEM;
> +
> +	int index;
> +	u64 round_rate = 0;
> +
> +	/* Must be sorted in ascending order */
> +	u64 apll_clk[] = { APLL_LOW_FREQ, APLL_HIGH_FREQ };
> +	u64 cpu_pll_clk[] = { CLK_FREQ_100M,  CLK_FREQ_200M,  CLK_FREQ_400M,
> +			      CLK_FREQ_500M,  CLK_FREQ_600M,  CLK_FREQ_700M,
> +			      CLK_FREQ_800M,  CLK_FREQ_900M,  CLK_FREQ_1000M,
> +			      CLK_FREQ_1200M, CLK_FREQ_1300M, CLK_FREQ_1400M,
> +			      CLK_FREQ_1500M, CLK_FREQ_1600M, CLK_FREQ_1700M,
> +			      CLK_FREQ_1800M };
> +
> +	switch (str_to_pll_clk(clk_name)) {
> +	case CLK_APLL_FOUT1:
> +		index = find_closest(rate, apll_clk, ARRAY_SIZE(apll_clk));
> +		round_rate = apll_clk[index];
> +		break;
> +	case CLK_PLL_CPU:
> +		index = find_closest(rate, cpu_pll_clk,
> +				     ARRAY_SIZE(cpu_pll_clk));
> +		round_rate = cpu_pll_clk[index];
> +		break;
> +	default:
> +		pr_err("%s %d, unknown clk %s\n", __func__, __LINE__,
> +		       clk_name);
> +		break;
> +	}
> +	return round_rate;
> +}
> +
> +static const struct clk_ops eswin_clk_pll_ops = {
> +	.set_rate = clk_pll_set_rate,
> +	.recalc_rate = clk_pll_recalc_rate,
> +	.round_rate = clk_pll_round_rate,
> +};
> +
> +void __init eswin_clk_gate_register(struct device_node *np)
> +{
> +	struct clk_hw *clk_hw;
> +	struct device_node *parent_np;
> +	const char *clk_name;
> +	const char *parent_name;
> +	u32 idx_bit;
> +	u32 reg;
> +	int ret;
> +
> +	parent_np = of_get_parent(np);
> +	if (!parent_np) {
> +		pr_err("%s: Failed to get parent node\n", __func__);
> +		return;
> +	}
> +
> +	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
> +		get_parent_base(parent_np);
> +	else
> +		return;
> +
> +	if (IS_ERR(parent_base)) {
> +		pr_err("%s: Failed to map registers\n", __func__);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_string(np, "clock-output-names", &clk_name);
> +	if (ret) {
> +		pr_err("%s: Missing clock-output-names\n", __func__);
> +		goto put_node;
> +	}
> +
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	if (!parent_name)
> +		goto put_node;
> +
> +	ret = of_property_read_u32(np, "bit-index", &idx_bit);
> +	if (ret) {
> +		pr_err("%s: Missing bit-index for gate %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "reg", &reg);
> +	if (ret) {
> +		pr_err("%s: Missing reg for gate %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	clk_hw = clk_hw_register_gate(NULL, clk_name, parent_name,
> +				      CLK_SET_RATE_PARENT,
> +				      parent_base + reg, idx_bit, 0, NULL);
> +
> +	if (IS_ERR(clk_hw)) {
> +		pr_err("%s: Failed to register gate clock %s: %ld\n",
> +		       __func__, clk_name, PTR_ERR(clk_hw));
> +		goto put_node;
> +	}
> +	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk_hw);
> +	if (ret) {
> +		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
> +		clk_hw_unregister_gate(clk_hw);
> +	}
> +
> +put_node:
> +	of_node_put(parent_np);
> +}
> +
> +void __init eswin_clk_mux_register(struct device_node *np)
> +{
> +	struct clk *clk;
> +	const char *clk_name = NULL;
> +	const char **parent_names = NULL;
> +	struct device_node *parent_np;
> +	u32 shift, width;
> +	u32 reg;
> +	u8 num_parents;
> +	u32 mask = 0;
> +	int ret, i;
> +
> +	parent_np = of_get_parent(np);
> +	if (!parent_np) {
> +		pr_err("%s: Failed to get parent node\n", __func__);
> +		return;
> +	}
> +
> +	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
> +		get_parent_base(parent_np);
> +	else
> +		return;
> +
> +	if (IS_ERR(parent_base)) {
> +		pr_err("%s: Failed to map registers\n", __func__);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_string(np, "clock-output-names", &clk_name);
> +	if (ret) {
> +		pr_err("%s: Missing clock-output-names\n", __func__);
> +		goto put_node;
> +	}
> +
> +	num_parents = of_clk_get_parent_count(np);
> +	if (!num_parents) {
> +		pr_err("%s: No parents for mux %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	parent_names = kcalloc(num_parents, sizeof(*parent_names),
> +			       GFP_KERNEL);
> +	if (!parent_names)
> +		goto put_node;
> +
> +	for (i = 0; i < num_parents; i++) {
> +		parent_names[i] = of_clk_get_parent_name(np, i);
> +		if (!parent_names[i]) {
> +			pr_err("%s: Failed to get parent name %d for %s\n",
> +			       __func__, i, clk_name);
> +			goto free_parents;
> +		}
> +	}
> +
> +	ret = of_property_read_u32(np, "shift", &shift);
> +	if (ret) {
> +		pr_err("%s: Missing shift for mux %s\n", __func__, clk_name);
> +		goto free_parents;
> +	}
> +
> +	ret = of_property_read_u32(np, "width", &width);
> +	if (ret) {
> +		pr_err("%s: Missing width for mux %s\n", __func__, clk_name);
> +		goto free_parents;
> +	}
> +
> +	ret = of_property_read_u32(np, "reg", &reg);
> +	if (ret) {
> +		pr_err("%s: Missing reg for mux %s\n", __func__, clk_name);
> +		goto free_parents;
> +	}
> +
> +	mask = BIT(width) - 1;
> +	clk = clk_register_mux_table(NULL, clk_name, parent_names, num_parents,
> +				     CLK_SET_RATE_PARENT, parent_base + reg,
> +				     shift, mask, 0, NULL, NULL);
> +
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: Failed to register mux clock %s: %ld\n", __func__,
> +		       clk_name, PTR_ERR(clk));
> +		goto free_parents;
> +	}
> +
> +	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk);
> +	if (ret) {
> +		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
> +		clk_unregister_mux(clk);
> +	}
> +
> +free_parents:
> +	kfree(parent_names);
> +put_node:
> +	of_node_put(parent_np);
> +}
> +
> +void __init eswin_clk_div_register(struct device_node *np)
> +{
> +	struct clk_hw *clk_hw;
> +	struct device_node *parent_np;
> +	const char *clk_name;
> +	const char *parent_name;
> +	u32 shift, width, div_flags;
> +	u32 reg;
> +	int ret;
> +
> +	parent_np = of_get_parent(np);
> +	if (!parent_np) {
> +		pr_err("%s: Failed to get parent node\n", __func__);
> +		return;
> +	}
> +
> +	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
> +		get_parent_base(parent_np);
> +	else
> +		return;
> +
> +	if (IS_ERR(parent_base)) {
> +		pr_err("%s: Failed to map registers\n", __func__);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_string(np, "clock-output-names", &clk_name);
> +	if (ret) {
> +		pr_err("%s: Missing clock-output-names\n", __func__);
> +		goto put_node;
> +	}
> +
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	if (!parent_name) {
> +		pr_err("%s: No parent for div %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "shift", &shift);
> +	if (ret) {
> +		pr_err("%s: Missing shift for div %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "width", &width);
> +	if (ret) {
> +		pr_err("%s: Missing width for div %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "div-flags", &div_flags);
> +	if (ret) {
> +		pr_err("%s: Missing div-flags for div %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "reg", &reg);
> +	if (ret) {
> +		pr_err("%s: Missing reg for div %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	clk_hw = clk_hw_register_divider(NULL, clk_name, parent_name, 0,
> +					 parent_base + reg, shift, width,
> +					 div_flags, NULL);
> +
> +	if (IS_ERR(clk_hw)) {
> +		pr_err("%s: Failed to register divider clock %s: %ld\n",
> +		       __func__, clk_name, PTR_ERR(clk_hw));
> +		goto put_node;
> +	}
> +
> +	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk_hw);
> +	if (ret) {
> +		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
> +		clk_hw_unregister_divider(clk_hw);
> +	}
> +
> +put_node:
> +	of_node_put(parent_np);
> +}
> +
> +void __init eswin_clk_pll_register(struct device_node *np)
> +{
> +	struct eswin_clk_pll *p_clk = NULL;
> +	struct clk *clk = NULL;
> +	struct clk_init_data init = {};
> +	struct device_node *parent_np;
> +	const char *clk_name;
> +	const char *parent_name;
> +	int ret;
> +	u32 reg[4];
> +	u32 en_shift, en_width;
> +	u32 refdiv_shift, refdiv_width;
> +	u32 fbdiv_shift, fbdiv_width;
> +	u32 frac_shift, frac_width;
> +	u32 postdiv1_shift, postdiv1_width;
> +	u32 postdiv2_shift, postdiv2_width;
> +	u32 lock_shift, lock_width;
> +
> +	parent_np = of_get_parent(np);
> +	if (!parent_np) {
> +		pr_err("%s: Failed to get parent node\n", __func__);
> +		return;
> +	}
> +
> +	if (of_device_is_compatible(parent_np, "eswin,eic7700-clock"))
> +		get_parent_base(parent_np);
> +	else
> +		return;
> +
> +	if (IS_ERR(parent_base)) {
> +		pr_err("%s: Failed to map registers\n", __func__);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_string(np, "clock-output-names", &clk_name);
> +	if (ret) {
> +		pr_err("%s: Missing clock-output-names\n", __func__);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "enable-shift", &en_shift);
> +	if (ret) {
> +		pr_err("%s: Missing enable-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "enable-width", &en_width);
> +	if (ret) {
> +		pr_err("%s: Missing enable-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "refdiv-shift", &refdiv_shift);
> +	if (ret) {
> +		pr_err("%s: Missing refdiv-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "refdiv-width", &refdiv_width);
> +	if (ret) {
> +		pr_err("%s: Missing refdiv-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "fbdiv-shift", &fbdiv_shift);
> +	if (ret) {
> +		pr_err("%s: Missing fbdiv-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "fbdiv-width", &fbdiv_width);
> +	if (ret) {
> +		pr_err("%s: Missing fbdiv-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "frac-shift", &frac_shift);
> +	if (ret) {
> +		pr_err("%s: Missing frac-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "frac-width", &frac_width);
> +	if (ret) {
> +		pr_err("%s: Missing frac-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "postdiv1-shift", &postdiv1_shift);
> +	if (ret) {
> +		pr_err("%s: Missing postdiv1-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "postdiv1-width", &postdiv1_width);
> +	if (ret) {
> +		pr_err("%s: Missing postdiv1-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "postdiv2-shift", &postdiv2_shift);
> +	if (ret) {
> +		pr_err("%s: Missing postdiv2-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "postdiv2-width", &postdiv2_width);
> +	if (ret) {
> +		pr_err("%s: Missing postdiv2-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "lock-shift", &lock_shift);
> +	if (ret) {
> +		pr_err("%s: Missing lock-shift for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32(np, "lock-width", &lock_width);
> +	if (ret) {
> +		pr_err("%s: Missing lock-width for pll %s\n", __func__,
> +		       clk_name);
> +		goto put_node;
> +	}
> +
> +	ret = of_property_read_u32_array(np, "reg", reg, 4);
> +	if (ret) {
> +		pr_err("%s: Missing reg for pll %s\n", __func__, clk_name);
> +		goto put_node;
> +	}
> +
> +	p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
> +	if (!p_clk)
> +		goto put_node;
> +
> +	p_clk->ctrl_reg0 = parent_base + reg[0];
> +	p_clk->pllen_shift = en_shift;
> +	p_clk->pllen_width = en_width;
> +	p_clk->refdiv_shift = refdiv_shift;
> +	p_clk->refdiv_width = refdiv_width;
> +	p_clk->fbdiv_shift = fbdiv_shift;
> +	p_clk->fbdiv_width = fbdiv_width;
> +
> +	p_clk->ctrl_reg1 = parent_base + reg[1];
> +	p_clk->frac_shift = frac_shift;
> +	p_clk->frac_width = frac_width;
> +
> +	p_clk->ctrl_reg2 = parent_base + reg[2];
> +	p_clk->postdiv1_shift = postdiv1_shift;
> +	p_clk->postdiv1_width = postdiv1_width;
> +	p_clk->postdiv2_shift = postdiv2_shift;
> +	p_clk->postdiv2_width = postdiv2_width;
> +
> +	p_clk->status_reg = parent_base + reg[3];
> +	p_clk->lock_shift = lock_shift;
> +	p_clk->lock_width = lock_width;
> +
> +	init.name = clk_name;
> +	init.flags = 0;
> +	init.parent_names = parent_name ? &parent_name : NULL;
> +	init.num_parents = parent_name ? 1 : 0;
> +	init.ops = &eswin_clk_pll_ops;
> +	p_clk->hw.init = &init;
> +
> +	clk = clk_register(NULL, &p_clk->hw);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: Failed to register pll clock %s: %ld\n", __func__,
> +		       clk_name, PTR_ERR(clk));
> +		kfree(p_clk);
> +		goto put_node;
> +	}
> +
> +	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, clk);
> +	if (ret) {
> +		pr_err("%s: Failed to add clock provider: %d\n", __func__, ret);
> +		clk_unregister(clk);
> +	}
> +
> +put_node:
> +	of_node_put(parent_np);
> +}
> diff --git a/drivers/clk/eswin/clk.h b/drivers/clk/eswin/clk.h
> new file mode 100644
> index 000000000000..1302540f9e24
> --- /dev/null
> +++ b/drivers/clk/eswin/clk.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd..
> + * All rights reserved.
> + *
> + * Authors:
> + *	Yifeng Huang <huangyifeng@eswincomputing.com>
> + *	Xuyang Dong <dongxuyang@eswincomputing.com>
> + */
> +
> +#ifndef __ESWIN_CLK_H__
> +#define __ESWIN_CLK_H__
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +
> +#define CLK_FREQ_1800M 1800000000
> +#define CLK_FREQ_1700M 1700000000
> +#define CLK_FREQ_1600M 1600000000
> +#define CLK_FREQ_1500M 1500000000
> +#define CLK_FREQ_1400M 1400000000
> +#define CLK_FREQ_1300M 1300000000
> +#define CLK_FREQ_1200M 1200000000
> +#define CLK_FREQ_1000M 1000000000
> +#define CLK_FREQ_900M 900000000
> +#define CLK_FREQ_800M 800000000
> +#define CLK_FREQ_700M 700000000
> +#define CLK_FREQ_600M 600000000
> +#define CLK_FREQ_500M 500000000
> +#define CLK_FREQ_400M 400000000
> +#define CLK_FREQ_200M 200000000
> +#define CLK_FREQ_100M 100000000
> +#define CLK_FREQ_24M 24000000
> +
> +#define APLL_HIGH_FREQ 983040000
> +#define APLL_LOW_FREQ 225792000
> +
> +struct eswin_clk_pll {
> +	struct clk_hw hw;
> +	void __iomem *ctrl_reg0;
> +	u8 pllen_shift;
> +	u8 pllen_width;
> +	u8 refdiv_shift;
> +	u8 refdiv_width;
> +	u8 fbdiv_shift;
> +	u8 fbdiv_width;
> +
> +	void __iomem *ctrl_reg1;
> +	u8 frac_shift;
> +	u8 frac_width;
> +
> +	void __iomem *ctrl_reg2;
> +	u8 postdiv1_shift;
> +	u8 postdiv1_width;
> +	u8 postdiv2_shift;
> +	u8 postdiv2_width;
> +
> +	void __iomem *status_reg;
> +	u8 lock_shift;
> +	u8 lock_width;
> +};
> +
> +void __init eswin_clk_gate_register(struct device_node *np);
> +void __init eswin_clk_mux_register(struct device_node *np);
> +void __init eswin_clk_div_register(struct device_node *np);
> +void __init eswin_clk_pll_register(struct device_node *np);
> +
> +#endif /* __ESWIN_CLK_H__ */
> --
> 2.17.1
> 
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: Re: [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support
  2025-08-17  6:07   ` Krzysztof Kozlowski
@ 2025-08-19  8:34     ` 董绪洋
  2025-08-19  9:10       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 13+ messages in thread
From: 董绪洋 @ 2025-08-19  8:34 UTC (permalink / raw)
  To: Krzysztof Kozlowski, mturquette, sboyd, robh, krzk+dt, conor+dt,
	linux-clk, devicetree, linux-kernel, paul.walmsley, palmer, aou,
	alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

Hi Krzysztof,

Thank you very much for your constructive suggestions.

> > 
> > Add clock device tree support for eic7700 SoC.
> > 
> > Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
> > Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
> > ---
> >  arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi | 2283 +++++++++++++++++
> >  1 file changed, 2283 insertions(+)
> >  create mode 100644 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> > 
> > diff --git a/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> > new file mode 100644
> > index 000000000000..405d06f9190e
> > --- /dev/null
> > +++ b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> > @@ -0,0 +1,2283 @@
> > +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> > +/*
> > + * Copyright (c) 2025, Beijing ESWIN Computing Technology Co., Ltd.
> > + */
> > +
> > +/ {
> > +	clock-controller@51828000 {
> > +		compatible = "eswin,eic7700-clock";
> > +		reg = <0x000000 0x51828000 0x000000 0x80000>;
> > +		#clock-cells = <0>;
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		/* fixed clock */
> > +		fixed_rate_clk_apll_fout2: fixed-rate-apll-fout2 {
> 
> Such pattern was years ago NAKed.
> 
> No, don't ever bring nodes per clock.
> 
We have defined a large number of clock devices. 
The comment of v3 is "Driver is also way too big for simple clock driver and I 
am surprised to see so many redundancies.". Therefore, we modified the clock 
driver code and moved the description of clock device from the driver to the DTS.

But, this comment is that don't ever bring nodes per clock. We’ve run into some
trouble and aren’t sure which approach aligns better with community guidelines. 
Could you share your advice or suggestions on the best way forward?

I would be grateful for your reply.

Regards,
Xuyang Dong

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

* Re: [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support
  2025-08-19  8:34     ` 董绪洋
@ 2025-08-19  9:10       ` Krzysztof Kozlowski
  2025-08-21  8:45         ` 董绪洋
  0 siblings, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-19  9:10 UTC (permalink / raw)
  To: 董绪洋, mturquette, sboyd, robh, krzk+dt,
	conor+dt, linux-clk, devicetree, linux-kernel, paul.walmsley,
	palmer, aou, alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

On 19/08/2025 10:34, 董绪洋 wrote:
> Hi Krzysztof,
> 
> Thank you very much for your constructive suggestions.
> 
>>>
>>> Add clock device tree support for eic7700 SoC.
>>>
>>> Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
>>> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
>>> ---
>>>  arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi | 2283 +++++++++++++++++
>>>  1 file changed, 2283 insertions(+)
>>>  create mode 100644 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
>>>
>>> diff --git a/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
>>> new file mode 100644
>>> index 000000000000..405d06f9190e
>>> --- /dev/null
>>> +++ b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
>>> @@ -0,0 +1,2283 @@
>>> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
>>> +/*
>>> + * Copyright (c) 2025, Beijing ESWIN Computing Technology Co., Ltd.
>>> + */
>>> +
>>> +/ {
>>> +	clock-controller@51828000 {
>>> +		compatible = "eswin,eic7700-clock";
>>> +		reg = <0x000000 0x51828000 0x000000 0x80000>;
>>> +		#clock-cells = <0>;
>>> +		#address-cells = <1>;
>>> +		#size-cells = <0>;
>>> +
>>> +		/* fixed clock */
>>> +		fixed_rate_clk_apll_fout2: fixed-rate-apll-fout2 {
>>
>> Such pattern was years ago NAKed.
>>
>> No, don't ever bring nodes per clock.
>>
> We have defined a large number of clock devices. 
> The comment of v3 is "Driver is also way too big for simple clock driver and I 
> am surprised to see so many redundancies.". Therefore, we modified the clock 
> driver code and moved the description of clock device from the driver to the DTS.
> 
> But, this comment is that don't ever bring nodes per clock. We’ve run into some

And? What is unclear in that comment?

> trouble and aren’t sure which approach aligns better with community guidelines. 
> Could you share your advice or suggestions on the best way forward?

Look at any other recent clock drivers.

Best regards,
Krzysztof

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

* Re: Re: [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support
  2025-08-19  9:10       ` Krzysztof Kozlowski
@ 2025-08-21  8:45         ` 董绪洋
  2025-08-21  9:02           ` Krzysztof Kozlowski
  0 siblings, 1 reply; 13+ messages in thread
From: 董绪洋 @ 2025-08-21  8:45 UTC (permalink / raw)
  To: Krzysztof Kozlowski, mturquette, sboyd, robh, krzk+dt, conor+dt,
	linux-clk, devicetree, linux-kernel, paul.walmsley, palmer, aou,
	alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

Hi Krzysztof,

Thanks for your constructive suggestions.
 
> >>>
> >>> Add clock device tree support for eic7700 SoC.
> >>>
> >>> Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com>
> >>> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com>
> >>> ---
> >>>  arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi | 2283 +++++++++++++++++
> >>>  1 file changed, 2283 insertions(+)
> >>>  create mode 100644 arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> >>>
> >>> diff --git a/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> >>> new file mode 100644
> >>> index 000000000000..405d06f9190e
> >>> --- /dev/null
> >>> +++ b/arch/riscv/boot/dts/eswin/eic7700-clocks.dtsi
> >>> @@ -0,0 +1,2283 @@
> >>> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> >>> +/*
> >>> + * Copyright (c) 2025, Beijing ESWIN Computing Technology Co., Ltd.
> >>> + */
> >>> +
> >>> +/ {
> >>> +	clock-controller@51828000 {
> >>> +		compatible = "eswin,eic7700-clock";
> >>> +		reg = <0x000000 0x51828000 0x000000 0x80000>;
> >>> +		#clock-cells = <0>;
> >>> +		#address-cells = <1>;
> >>> +		#size-cells = <0>;
> >>> +
> >>> +		/* fixed clock */
> >>> +		fixed_rate_clk_apll_fout2: fixed-rate-apll-fout2 {
> >>
> >> Such pattern was years ago NAKed.
> >>
> >> No, don't ever bring nodes per clock.
> >>
> > We have defined a large number of clock devices. 
> > The comment of v3 is "Driver is also way too big for simple clock driver and I 
> > am surprised to see so many redundancies.". Therefore, we modified the clock 
> > driver code and moved the description of clock device from the driver to the DTS.
> > 
> > But, this comment is that don't ever bring nodes per clock. We’ve run into some
> 
> And? What is unclear in that comment?
> 
> > trouble and aren’t sure which approach aligns better with community guidelines. 
> > Could you share your advice or suggestions on the best way forward?
> 
> Look at any other recent clock drivers.

I found out that the recent clock drivers, such as sophgo/clk-sg2044.c 
and rockchip/clk-rk3562.c, the clock tree information of them was placed
in the C code. 
So, for EIC7700 SoC, should the clock tree information be placed in
clk-eic7700.c just as clk-sg2044.c? Is this understanding correct?

I would be grateful for your reply.

Regards,
Xuyang Dong

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

* Re: [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support
  2025-08-21  8:45         ` 董绪洋
@ 2025-08-21  9:02           ` Krzysztof Kozlowski
  0 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-21  9:02 UTC (permalink / raw)
  To: 董绪洋, mturquette, sboyd, robh, krzk+dt,
	conor+dt, linux-clk, devicetree, linux-kernel, paul.walmsley,
	palmer, aou, alex, linux-riscv
  Cc: ningyu, linmin, huangyifeng, pinkesh.vaghela

On 21/08/2025 10:45, 董绪洋 wrote:
>>>>> +		/* fixed clock */
>>>>> +		fixed_rate_clk_apll_fout2: fixed-rate-apll-fout2 {
>>>>
>>>> Such pattern was years ago NAKed.
>>>>
>>>> No, don't ever bring nodes per clock.
>>>>
>>> We have defined a large number of clock devices. 
>>> The comment of v3 is "Driver is also way too big for simple clock driver and I 
>>> am surprised to see so many redundancies.". Therefore, we modified the clock 
>>> driver code and moved the description of clock device from the driver to the DTS.
>>>
>>> But, this comment is that don't ever bring nodes per clock. We’ve run into some
>>
>> And? What is unclear in that comment?
>>
>>> trouble and aren’t sure which approach aligns better with community guidelines. 
>>> Could you share your advice or suggestions on the best way forward?
>>
>> Look at any other recent clock drivers.
> 
> I found out that the recent clock drivers, such as sophgo/clk-sg2044.c 
> and rockchip/clk-rk3562.c, the clock tree information of them was placed
> in the C code. 
> So, for EIC7700 SoC, should the clock tree information be placed in
> clk-eic7700.c just as clk-sg2044.c? Is this understanding correct?

Yes, entire clock hierarchy for one clock controller should be coded in
the Linux driver. How do you name it or how do you split your drivers to
code it efficiently, is different topic.


Best regards,
Krzysztof

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

* Re: [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver
  2025-08-15  9:37 ` [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver dongxuyang
  2025-08-17  6:07   ` Krzysztof Kozlowski
  2025-08-19  4:46   ` Troy Mitchell
@ 2025-08-21 18:32   ` Brian Masney
  2 siblings, 0 replies; 13+ messages in thread
From: Brian Masney @ 2025-08-21 18:32 UTC (permalink / raw)
  To: dongxuyang
  Cc: mturquette, sboyd, robh, krzk+dt, conor+dt, linux-clk, devicetree,
	linux-kernel, paul.walmsley, palmer, aou, alex, linux-riscv,
	ningyu, linmin, huangyifeng, pinkesh.vaghela

Hi,

On Fri, Aug 15, 2025 at 05:37:20PM +0800, dongxuyang@eswincomputing.com wrote:
> +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +			       unsigned long *parent_rate)
> +{
> +	struct eswin_clk_pll *clk = to_pll_clk(hw);
> +	const char *clk_name = clk_hw_get_name(&clk->hw);
> +
> +	if (!clk_name)
> +		return -ENOMEM;
> +
> +	int index;
> +	u64 round_rate = 0;
> +
> +	/* Must be sorted in ascending order */
> +	u64 apll_clk[] = { APLL_LOW_FREQ, APLL_HIGH_FREQ };
> +	u64 cpu_pll_clk[] = { CLK_FREQ_100M,  CLK_FREQ_200M,  CLK_FREQ_400M,
> +			      CLK_FREQ_500M,  CLK_FREQ_600M,  CLK_FREQ_700M,
> +			      CLK_FREQ_800M,  CLK_FREQ_900M,  CLK_FREQ_1000M,
> +			      CLK_FREQ_1200M, CLK_FREQ_1300M, CLK_FREQ_1400M,
> +			      CLK_FREQ_1500M, CLK_FREQ_1600M, CLK_FREQ_1700M,
> +			      CLK_FREQ_1800M };
> +
> +	switch (str_to_pll_clk(clk_name)) {
> +	case CLK_APLL_FOUT1:
> +		index = find_closest(rate, apll_clk, ARRAY_SIZE(apll_clk));
> +		round_rate = apll_clk[index];
> +		break;
> +	case CLK_PLL_CPU:
> +		index = find_closest(rate, cpu_pll_clk,
> +				     ARRAY_SIZE(cpu_pll_clk));
> +		round_rate = cpu_pll_clk[index];
> +		break;
> +	default:
> +		pr_err("%s %d, unknown clk %s\n", __func__, __LINE__,
> +		       clk_name);
> +		break;
> +	}
> +	return round_rate;
> +}
> +
> +static const struct clk_ops eswin_clk_pll_ops = {
> +	.set_rate = clk_pll_set_rate,
> +	.recalc_rate = clk_pll_recalc_rate,
> +	.round_rate = clk_pll_round_rate,
> +};

The round_rate clk op is deprecated. Please convert this over to use
determine_rate.

Brian


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

end of thread, other threads:[~2025-08-21 18:32 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-15  9:35 [PATCH v4 0/3] Add driver support for ESWIN eic700 SoC clock controller dongxuyang
2025-08-15  9:36 ` [PATCH v4 1/3] clock: eswin: Documentation for eic7700 SoC dongxuyang
2025-08-17  6:01   ` Krzysztof Kozlowski
2025-08-15  9:37 ` [PATCH v4 2/3] clock: eswin: Add eic7700 clock driver dongxuyang
2025-08-17  6:07   ` Krzysztof Kozlowski
2025-08-19  4:46   ` Troy Mitchell
2025-08-21 18:32   ` Brian Masney
2025-08-15  9:37 ` [PATCH v4 3/3] riscv: dts: eswin: Add clock driver support dongxuyang
2025-08-17  6:07   ` Krzysztof Kozlowski
2025-08-19  8:34     ` 董绪洋
2025-08-19  9:10       ` Krzysztof Kozlowski
2025-08-21  8:45         ` 董绪洋
2025-08-21  9:02           ` Krzysztof Kozlowski

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).