All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] add clock driver for Spreadtrum platforms
@ 2017-05-15  8:34 ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:34 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

In the last cycle, the patches support Whale2 sc9860 mobile chip have been
merged. This patchset adds clock driver which is used on almost all
Spreadtrum SoCs.

This series also adds Spreadtrum clock bindings and SC9860 clock devicetree
data.

This driver has been validated on Spreadtrum SC9860 mobile phone.

Any comments would be greatly appreciated.

Thanks,
Chunyan


Chunyan Zhang (1):
  Documentation: add sprd clock bindings

Xiaolong Zhang (2):
  arm64: dts: add SC9860 clock tree data
  clk: Add common clock driver for Spreadtrum SoCs

 .../clock/sprd/sprd,adjustable-pll-clock.txt       |   17 +
 .../bindings/clock/sprd/sprd,composite-clock.txt   |   28 +
 .../bindings/clock/sprd/sprd,divider-clock.txt     |   24 +
 .../bindings/clock/sprd/sprd,gates-clock.txt       |   73 +
 .../bindings/clock/sprd/sprd,muxed-clock.txt       |   23 +
 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi        | 1984 ++++++++++++++++++++
 arch/arm64/boot/dts/sprd/sc9860.dtsi               |    1 +
 arch/arm64/boot/dts/sprd/whale2.dtsi               |    7 -
 drivers/clk/Makefile                               |    1 +
 drivers/clk/sprd/Makefile                          |    3 +
 drivers/clk/sprd/clk-gates.c                       |  366 ++++
 drivers/clk/sprd/composite.c                       |  109 ++
 drivers/clk/sprd/divider.c                         |   79 +
 drivers/clk/sprd/mux.c                             |   77 +
 drivers/clk/sprd/pll.c                             |  359 ++++
 drivers/clk/sprd/pll.h                             |   73 +
 drivers/clk/sprd/pll_cfg.h                         |  390 ++++
 17 files changed, 3607 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/clk-gates.c
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/divider.c
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/pll_cfg.h

-- 
2.7.4

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

* [PATCH 0/3] add clock driver for Spreadtrum platforms
@ 2017-05-15  8:34 ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:34 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

In the last cycle, the patches support Whale2 sc9860 mobile chip have been
merged. This patchset adds clock driver which is used on almost all
Spreadtrum SoCs.

This series also adds Spreadtrum clock bindings and SC9860 clock devicetree
data.

This driver has been validated on Spreadtrum SC9860 mobile phone.

Any comments would be greatly appreciated.

Thanks,
Chunyan


Chunyan Zhang (1):
  Documentation: add sprd clock bindings

Xiaolong Zhang (2):
  arm64: dts: add SC9860 clock tree data
  clk: Add common clock driver for Spreadtrum SoCs

 .../clock/sprd/sprd,adjustable-pll-clock.txt       |   17 +
 .../bindings/clock/sprd/sprd,composite-clock.txt   |   28 +
 .../bindings/clock/sprd/sprd,divider-clock.txt     |   24 +
 .../bindings/clock/sprd/sprd,gates-clock.txt       |   73 +
 .../bindings/clock/sprd/sprd,muxed-clock.txt       |   23 +
 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi        | 1984 ++++++++++++++++++++
 arch/arm64/boot/dts/sprd/sc9860.dtsi               |    1 +
 arch/arm64/boot/dts/sprd/whale2.dtsi               |    7 -
 drivers/clk/Makefile                               |    1 +
 drivers/clk/sprd/Makefile                          |    3 +
 drivers/clk/sprd/clk-gates.c                       |  366 ++++
 drivers/clk/sprd/composite.c                       |  109 ++
 drivers/clk/sprd/divider.c                         |   79 +
 drivers/clk/sprd/mux.c                             |   77 +
 drivers/clk/sprd/pll.c                             |  359 ++++
 drivers/clk/sprd/pll.h                             |   73 +
 drivers/clk/sprd/pll_cfg.h                         |  390 ++++
 17 files changed, 3607 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/clk-gates.c
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/divider.c
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/pll_cfg.h

-- 
2.7.4

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

* [PATCH 0/3] add clock driver for Spreadtrum platforms
@ 2017-05-15  8:34 ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:34 UTC (permalink / raw)
  To: linux-arm-kernel

In the last cycle, the patches support Whale2 sc9860 mobile chip have been
merged. This patchset adds clock driver which is used on almost all
Spreadtrum SoCs.

This series also adds Spreadtrum clock bindings and SC9860 clock devicetree
data.

This driver has been validated on Spreadtrum SC9860 mobile phone.

Any comments would be greatly appreciated.

Thanks,
Chunyan


Chunyan Zhang (1):
  Documentation: add sprd clock bindings

Xiaolong Zhang (2):
  arm64: dts: add SC9860 clock tree data
  clk: Add common clock driver for Spreadtrum SoCs

 .../clock/sprd/sprd,adjustable-pll-clock.txt       |   17 +
 .../bindings/clock/sprd/sprd,composite-clock.txt   |   28 +
 .../bindings/clock/sprd/sprd,divider-clock.txt     |   24 +
 .../bindings/clock/sprd/sprd,gates-clock.txt       |   73 +
 .../bindings/clock/sprd/sprd,muxed-clock.txt       |   23 +
 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi        | 1984 ++++++++++++++++++++
 arch/arm64/boot/dts/sprd/sc9860.dtsi               |    1 +
 arch/arm64/boot/dts/sprd/whale2.dtsi               |    7 -
 drivers/clk/Makefile                               |    1 +
 drivers/clk/sprd/Makefile                          |    3 +
 drivers/clk/sprd/clk-gates.c                       |  366 ++++
 drivers/clk/sprd/composite.c                       |  109 ++
 drivers/clk/sprd/divider.c                         |   79 +
 drivers/clk/sprd/mux.c                             |   77 +
 drivers/clk/sprd/pll.c                             |  359 ++++
 drivers/clk/sprd/pll.h                             |   73 +
 drivers/clk/sprd/pll_cfg.h                         |  390 ++++
 17 files changed, 3607 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/clk-gates.c
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/divider.c
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/pll_cfg.h

-- 
2.7.4

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

* [PATCH 1/3] arm64: dts: add SC9860 clock tree data
  2017-05-15  8:34 ` Chunyan Zhang
  (?)
@ 2017-05-15  8:35   ` Chunyan Zhang
  -1 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

From: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>

This patch addresses SC9860 clock topology structure and provides clock
node to other devices (clock consumers) on chip.

This patch also removed replicated node of 26m fixed clock.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi | 1984 +++++++++++++++++++++++++++
 arch/arm64/boot/dts/sprd/sc9860.dtsi        |    1 +
 arch/arm64/boot/dts/sprd/whale2.dtsi        |    7 -
 3 files changed, 1985 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi

diff --git a/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi b/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
new file mode 100644
index 0000000..5756933
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
@@ -0,0 +1,1984 @@
+/*
+ * Spreadtrum SC9860 SoC DTS file
+ *
+ * Copyright (C) 2015, Spreadtrum Communications Inc.
+ *
+ * This file is licensed under a dual GPLv2 or X11 license.
+ */
+&soc {
+	aliases {
+		apb_pclk = &clk_ap_apb;
+	};
+
+	ext_26m: ext-26m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "ext_26m";
+	};
+
+	ext_32m_sine0: ext-32m-sine0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "ext_32m_sine0";
+	};
+
+	ext_32m_sine1: ext-32m-sine1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "ext_32m_sine1";
+	};
+
+	clk_pll_in: clk-pll-in {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "ext_26m";
+	};
+
+	clk_4m: clk-4m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_4m";
+	};
+
+	clk_2m: clk-2m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <13>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_2m";
+	};
+
+	clk_1m: clk-1m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <26>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_1m";
+	};
+
+	clk_250k: clk-250k {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <104>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_250k";
+	};
+
+	ext_rco_100m: ext-rco-100m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "ext_rco_100m";
+	};
+
+	ext_32k: ext-32k {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "ext_32k";
+	};
+
+	clk_rpll0_26m: clk-rpll0-26m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_rpll0_26m";
+	};
+
+	clk_rpll1_26m: clk-rpll1-26m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_rpll1_26m";
+	};
+
+	clk_rpll_gates: clk@402b016c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b016c 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_rpll0_gate", "clk_rpll1_gate";
+	};
+
+	clk_mpll_gates: clk@402b00b0 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b0 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
+	};
+
+	clk_dpll_gates: clk@402b00b4 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b4 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_dpll0_gate", "clk_dpll1_gate";
+	};
+
+	clk_gpll_gate: clk@402b032c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402b032d 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_gpll_gate";
+	};
+
+	clk_cppll_gate: clk@402b02b4 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b02b4 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_cppll_gate";
+	};
+
+	clk_ltepll0_gate: clk@402b00b8 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b8 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_ltepll0_gate";
+	};
+
+	clk_ltepll1_gate: clk@402b010c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b010c 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_ltepll1_gate";
+	};
+
+	clk_twpll_gate: clk@402b00bc {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00bc 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_twpll_gate";
+	};
+
+	clk_rpll0: clk@40400044 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400044 0 0x4>,
+		      <0 0x40400048 0 0x4>,
+		      <0 0x4040004c 0 0x4>;
+		clocks = <&clk_rpll_gates 2>;
+		clock-output-names = "clk_rpll0";
+	};
+
+	clk_rpll1: clk@40400050 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400050 0 0x4>,
+		      <0 0x40400054 0 0x4>,
+		      <0 0x40400058 0 0x4>;
+		clocks = <&clk_rpll_gates 18>;
+		clock-output-names = "clk_rpll1";
+	};
+
+	clk_mpll0: clk@40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
+
+	clk_mpll1: clk@4040002c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040002c 0 0x4>,
+		      <0 0x40400030 0 0x4>;
+		clocks = <&clk_mpll_gates 18>;
+		clock-output-names = "clk_mpll1";
+	};
+
+	clk_dpll0: clk@40400034 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400034 0 0x4>,
+		      <0 0x40400038 0 0x4>;
+		clocks = <&clk_dpll_gates 2>;
+		clock-output-names = "clk_dpll0";
+	};
+
+	clk_dpll1: clk@4040003c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040003c 0 0x4>,
+		      <0 0x40400040 0 0x4>;
+		clocks = <&clk_dpll_gates 18>;
+		clock-output-names = "clk_dpll1";
+	};
+
+	clk_gpll: clk@4040009c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040009c 0 0x4>,
+		      <0 0x404000a0 0 0x4>;
+		clocks = <&clk_gpll_gate>;
+		clock-output-names = "clk_gpll";
+	};
+
+	clk_cppll: clk@404000c4 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x404000c4 0 0x4>,
+		      <0 0x404000c8 0 0x4>;
+		clocks = <&clk_cppll_gate 2>;
+		clock-output-names = "clk_cppll";
+	};
+
+	clk_ltepll0: clk@40400064 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400064 0 0x4>,
+		      <0 0x40400068 0 0x4>;
+		clocks = <&clk_ltepll0_gate 2>;
+		clock-output-names = "clk_ltepll0";
+	};
+
+	clk_ltepll1: clk@4040006c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040006c 0 0x4>,
+		      <0 0x40400070 0 0x4>;
+		clocks = <&clk_ltepll1_gate 2>;
+		clock-output-names = "clk_ltepll1";
+	};
+
+	clk_twpll: clk@4040005c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040005c 0 0x4>,
+		      <0 0x40400060 0 0x4>;
+		clocks = <&clk_twpll_gate 2>;
+		clock-output-names = "clk_twpll";
+	};
+
+	clk_gpll_42m5: clk-gpll-42m5 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <20>;
+		clocks = <&clk_gpll>;
+		clock-output-names = "clk_gpll_42m5";
+	};
+
+	clk_twpll_768m: clk-tw-768m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_768m";
+	};
+
+	clk_twpll_384m: clk-tw-384m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <4>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_384m";
+	};
+
+	clk_twpll_192m: clk-tw-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <8>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_192m";
+	};
+
+	clk_twpll_96m: clk-tw-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_96m";
+	};
+
+	clk_twpll_48m: clk-tw-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_48m";
+	};
+
+	clk_twpll_24m: clk-tw-24m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <64>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_24m";
+	};
+
+	clk_twpll_12m: clk-tw-12m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <128>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_12m";
+	};
+
+	clk_twpll_512m: clk-tw-512m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <3>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_512m";
+	};
+
+	clk_twpll_256m: clk-tw-256m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_256m";
+	};
+
+	clk_twpll_128m: clk-tw-128m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_128m";
+	};
+
+	clk_twpll_64m: clk-tw-64m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_64m";
+	};
+
+	clk_twpll_307m2: clk-tw-307m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <5>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_307m2";
+	};
+
+	clk_twpll_153m6: clk-tw-153m6 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <10>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_153m6";
+	};
+
+	clk_twpll_76m8: clk-tw-76m8 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <20>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_76m8";
+	};
+
+	clk_twpll_51m2: clk-tw-51m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <30>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_51m2";
+	};
+
+	clk_twpll_38m4: clk-tw-38m4 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <40>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_38m4";
+	};
+
+	clk_twpll_19m2: clk-tw-19m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <80>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_19m2";
+	};
+
+	clk_l0_614m4: clk-l0-614m4 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_614m4";
+	};
+
+	clk_l0_38m: clk-l0-38m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_38m";
+	};
+
+	clk_l0_409m6: clk-l0-409m6 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <3>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_409m6";
+	};
+
+	clk_l1_38m: clk-l1-38m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_ltepll1>;
+		clock-output-names = "clk_l1_38m";
+	};
+
+	clk_rpll0_192m: clk-rpll0-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_192m";
+	};
+
+	clk_rpll0_96m: clk-rpll0-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_96m";
+	};
+
+	clk_rpll0_48m: clk-rpll0-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_48m";
+	};
+
+	clk_rpll1_468m: clk-rpll1-468m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_468m";
+	};
+
+	clk_rpll1_192m: clk-rpll1-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_192m";
+	};
+
+	clk_rpll1_96m: clk-rpll1-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_96m";
+	};
+
+	clk_rpll1_64m: clk-rpll1-64m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <18>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_64m";
+	};
+
+	clk_rpll1_48m: clk-rpll1-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_48m";
+	};
+
+	clk_dpll0_50m: clk-dpll0-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_dpll0>;
+		clock-output-names = "clk_dpll0_50m";
+	};
+
+	clk_dpll1_50m: clk-dpll1-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_dpll1>;
+		clock-output-names = "clk_dpll1_50m";
+	};
+
+	clk_cppll_50m: clk-cppll-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <18>;
+		clocks = <&clk_cppll>;
+		clock-output-names = "clk_cppll_50m";
+	};
+
+	clk_rco_25m: clk-rco-25m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <4>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_25m";
+	};
+
+	clk_rco_4m: clk-rco-4m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <25>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_4m";
+	};
+
+	clk_rco_2m: clk-rco-2m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <50>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_2m";
+	};
+
+	clk_3k2: clk-3k2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <10>;
+		clocks = <&ext_32k>;
+		clock-output-names = "clk_3k2";
+	};
+
+	clk_1k: clk-1k {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&ext_32k>;
+		clock-output-names = "clk_1k";
+	};
+
+	clk_aon_apb: clk@402d0230 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0230 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_rco_25m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_aon_apb";
+	};
+
+	clk_adi: clk@402d0234 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0234 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&clk_rco_25m>,
+			 <&clk_twpll_38m4>, <&clk_twpll_51m2>;
+		clock-output-names = "clk_adi";
+	};
+
+	clk_m0_39m: clk-m0-39m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_mpll0>;
+		clock-output-names = "clk_m0_39m";
+	};
+
+	clk_m1_63m: clk-m1-63m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_mpll1>;
+		clock-output-names = "clk_m1_63m";
+	};
+
+	clk_aux0: clk@402d0238 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0238 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux0";
+	};
+
+	clk_aux1: clk@402d023c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d023c 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux1";
+	};
+
+	clk_aux2: clk@402d0240 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0240 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux2";
+	};
+
+	clk_probe: clk@402d0244 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0244 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_probe";
+	};
+
+	clk_pwm0: clk@402d0248 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0248 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm0";
+	};
+
+	clk_pwm1: clk@402d024c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d024c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm1";
+	};
+
+	clk_pwm2: clk@402d0250 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0250 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm2";
+	};
+
+	clk_pwm3: clk@402d0254 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0254 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm3";
+	};
+
+	clk_efuse: clk@402d0258 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0258 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_efuse";
+	};
+
+	clk_cm3_uart0: clk@402d025c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d025c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>,<&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>;
+		clock-output-names = "clk_cm3_uart0";
+	};
+
+	clk_cm3_uart1: clk@402d0260 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0260 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>,<&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>;
+		clock-output-names = "clk_cm3_uart1";
+	};
+
+	clk_thm: clk@402d0270 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0270 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_250k>;
+		clock-output-names = "clk_thm";
+	};
+
+	clk_cm3_i2c0: clk@402d0274 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0274 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_cm3_i2c0";
+	};
+
+	clk_cm3_i2c1: clk@402d0278 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0278 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_cm3_i2c1";
+	};
+
+	clk_cm4_spi: clk@402d027c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d027c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&ext_rco_100m>,
+			 <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_cm4_spi";
+	};
+
+	clk_aon_i2c: clk@402d0280 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0280 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_aon_i2c";
+	};
+
+	clk_avs: clk@402d0284 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0284 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_avs";
+	};
+
+	clk_ca53_dap: clk@402d0288 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0288 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_26m>, <&clk_rco_4m>, <&ext_rco_100m>,
+			 <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ca53_dap";
+	};
+
+	clk_ca53_ts: clk@402d0290 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0290 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ca53_ts";
+	};
+
+	clk_26m_lvdsdis: clk@402d0294 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0294 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_26m_lvdsdis";
+	};
+
+	clk_lvdsrf_cali: clk@402d02b8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02b8 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_lvdsrf_cali";
+	};
+
+	clk_mdar_chk: clk@402d02bc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02bc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_mdar_chk";
+	};
+
+	clk_rco100m_ref: clk@402d02c0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c0 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_2m>;
+		clock-output-names = "clk_rco100m_ref";
+	};
+
+	clk_rco100m_fdk: clk@402d02c4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_2m>;
+		clock-output-names = "clk_rco100m_fdk";
+	};
+
+	clk_djtag_tck: clk@402d02c8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c8 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_4m>, <&ext_26m>;
+		clock-output-names = "clk_djtag_tck";
+	};
+
+	clk_sp_ahb: clk@402d02d0 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02d0 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_sp_ahb";
+	};
+
+	clk_det_32k: clk@402d02dc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02dc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_4m>;
+		clock-output-names = "clk_det_32k";
+	};
+
+	clk_pmu: clk@402d02e0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e0 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&clk_rco_4m>, <&clk_4m>;
+		clock-output-names = "clk_pmu";
+	};
+
+	clk_pmu_26m: clk@402d02e4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_pmu_26m";
+	};
+
+	clk_debounce: clk@402d02e8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e8 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_debounce";
+	};
+
+	clk_dphy_ref: clk@402d02f0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f0 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy_ref";
+	};
+
+	clk_otg2_ref: clk@402d02f4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_twpll_12m>, <&clk_twpll_24m>;
+		clock-output-names = "clk_otg2_ref";
+	};
+
+	clk_usb3_ref: clk@402d02f8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f8 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_24m>, <&clk_twpll_19m2>, <&clk_twpll_48m>;
+		clock-output-names = "clk_usb3_ref";
+	};
+
+	clk_usb3_suspend: clk@402d02fc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02fc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_1m>;
+		clock-output-names = "clk_usb3_suspend";
+	};
+
+	clk_cci: clk@402d0300 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0300 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&ext_26m>, <&clk_twpll_384m>, <&clk_l0_614m4>,
+			 <&clk_twpll_768m>;
+		clock-output-names = "clk_cci";
+	};
+
+	clk_gic: clk@402d0304 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0304 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&ext_26m>, <&clk_twpll_384m>, <&clk_l0_614m4>,
+			 <&clk_twpll_768m>;
+		clock-output-names = "clk_gic";
+	};
+
+	clk_ap_axi: clk@402d0324 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0324 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>;
+		clock-output-names = "clk_ap_axi";
+	};
+
+	clk_sdio_gates: clk@402e013c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e013c 0 0x3000>;
+		clock-indices = <2>, <3>,
+				<4>, <5>, <6>, <7>,
+				<8>, <9>;
+		clock-output-names = "sdio0_2x_en", "sdio0_1x_en",
+				     "sdio1_2x_en", "sdio1_1x_en",
+				     "sdio2_2x_en", "sdio2_1x_en",
+				     "emmc_1x_en", "emmc_2x_en";
+	};
+
+	clk_sdio0_2x: clk@402d0328 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0328 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio0_2x";
+	};
+
+	clk_sdio0_1x: clk@402d032c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d032c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio0_2x>;
+		clock-output-names = "clk_sdio0_1x";
+	};
+
+	clk_sdio1_2x: clk@402d0330 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0330 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio1_2x";
+	};
+
+	clk_sdio1_1x: clk@402d0334 {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0334 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio1_2x>;
+		clock-output-names = "clk_sdio1_1x";
+	};
+
+	clk_sdio2_2x: clk@402d0338 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0338 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio2_2x";
+	};
+
+	clk_sdio2_1x: clk@402d033c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d033c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio2_2x>;
+		clock-output-names = "clk_sdio2_1x";
+	};
+
+	clk_emmc_2x: clk@402d0340 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0340 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_emmc_2x";
+	};
+
+	clk_emmc_1x: clk@402d0344 {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0344 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_emmc_2x>;
+		clock-output-names = "clk_emmc_1x";
+	};
+
+	clk_ap_apb: clk@20000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_64m>, <&clk_twpll_96m>,
+			 <&clk_twpll_128m>;
+		clock-output-names = "clk_ap_apb";
+	};
+
+	clk_ap_usb3_ref: clk@2000002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000002c 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_twpll_24m>;
+		clock-output-names = "clk_ap_usb3_ref";
+	};
+
+	clk_uart0: clk@20000030 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart0";
+	};
+
+	clk_uart1: clk@20000034 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000034 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart1";
+	};
+
+	clk_uart2: clk@20000038 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000038 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart2";
+	};
+
+	clk_uart3: clk@2000003c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000003c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart3";
+	};
+
+	clk_uart4: clk@20000040 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000040 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart4";
+	};
+
+	clk_i2c0: clk@20000044 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000044 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c0";
+	};
+
+	clk_i2c1: clk@20000048 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000048 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c1";
+	};
+
+	clk_i2c2: clk@2000004c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000004c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c2";
+	};
+
+	clk_i2c3: clk@20000050 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000050 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c3";
+	};
+
+	clk_i2c4: clk@20000054 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000054 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c4";
+	};
+
+	clk_i2c5: clk@20000058 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000058 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c5";
+	};
+
+	clk_spi0: clk@2000005c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000005c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi0";
+	};
+
+	clk_spi1: clk@20000060 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000060 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi1";
+	};
+
+	clk_spi2: clk@20000064 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000064 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi2";
+	};
+
+	clk_spi3: clk@20000068 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000068 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi3";
+	};
+
+	clk_iis0: clk@2000006c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000006c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis0";
+	};
+
+	clk_iis1: clk@20000070 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000070 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis1";
+	};
+
+	clk_iis2: clk@20000074 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000074 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis2";
+	};
+
+	clk_iis3: clk@20000078 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000078 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis3";
+	};
+
+	clk_big_mcu: clk@40880024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40880024 0 0x4>;
+		sprd,mux-msk = <0xf>;
+		sprd,div-msk = <0x70>;
+		clocks = <&ext_26m>, <&clk_twpll_512m>, <&clk_twpll_768m>,
+			 <&clk_ltepll0>, <&clk_twpll>, <&clk_twpll>,
+			 <&clk_twpll>, <&clk_twpll>, <&clk_mpll1>;
+		clock-output-names = "clk_big_mcu";
+	};
+
+	clk_lit_mcu: clk@40880020 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40880020 0 0x4>;
+		sprd,mux-msk = <0xf>;
+		sprd,div-msk = <0x70>;
+		clocks = <&ext_26m>, <&clk_twpll_512m>, <&clk_twpll_768m>,
+			<&clk_ltepll0>, <&clk_twpll>, <&clk_twpll>,
+			<&clk_twpll>, <&clk_twpll>, <&clk_mpll0>;
+		clock-output-names = "clk_lit_mcu";
+	};
+
+	/* gpu domain */
+	clk_gpu: clk@60200020 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x60200020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_twpll_512m>, <&clk_twpll_768m>, <&clk_gpll>;
+		clock-output-names = "clk_gpu";
+	};
+
+	/* vsp domain */
+	clk_ahb_vsp: clk@61000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_vsp";
+	};
+
+	clk_vsp: clk@61000024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000024 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_vsp";
+	};
+
+	clk_vsp_enc: clk@61000028 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_vsp_enc";
+	};
+
+	clk_vpp: clk@6100002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6100002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_96m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_vpp";
+	};
+
+	clk_vsp_26m: clk@61000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000030 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_vsp_26m";
+	};
+
+	clk_ahb_disp: clk@63000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_disp";
+	};
+
+	clk_gsp0: clk@63000024 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000024 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_512m>, <&clk_l0_614m4>;
+		clock-output-names = "clk_gsp0";
+	};
+
+	clk_gsp1: clk@63000028 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_512m>, <&clk_l0_614m4>;
+		clock-output-names = "clk_gsp1";
+	};
+
+	clk_dispc0: clk@6300002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_192m>, <&clk_twpll_256m>,
+			 <&clk_twpll_384m>, <&clk_twpll_512m>;
+		clock-output-names = "clk_dispc0";
+	};
+
+	clk_dispc0_dbi: clk@63000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc0_dbi";
+	};
+
+	clk_dispc0_dpi: clk@63000034 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000034 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc0_dpi";
+	};
+
+	clk_dispc1: clk@63000038 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000038 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_192m>, <&clk_twpll_256m>,
+			 <&clk_twpll_384m>, <&clk_twpll_512m>;
+		clock-output-names = "clk_dispc1";
+	};
+
+	clk_dispc1_dbi: clk@6300003c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300003c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc1_dbi";
+	};
+
+	clk_dispc1_dpi: clk@63000040 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000040 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc1_dpi";
+	};
+
+	clk_dphy0: clk@6300004c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300004c 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy0";
+	};
+
+	clk_dphy1: clk@63000058 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000058 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy1";
+	};
+
+	clk_ahb_cam: clk@62000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_cam";
+	};
+
+	clk_sensor0: clk@62000024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000024 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor0";
+	};
+
+	clk_sensor1: clk@62000028 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor1";
+	};
+
+	clk_sensor2: clk@6200002c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor2";
+	};
+
+	clk_dcam0: clk@62000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_153m6>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>;
+		clock-output-names = "clk_dcam0";
+	};
+
+	clk_dcam1: clk@62000034 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000034 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_dcam1";
+	};
+
+	clk_dcam0_if: clk@62000038 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000038 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_dcam0_if";
+	};
+
+	clk_isp0: clk@6200003c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200003c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp0";
+	};
+
+	clk_isp1: clk@62000040 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000040 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp1";
+	};
+
+	clk_jpg0: clk@62000044 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000044 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_jpg0";
+	};
+
+	clk_jpg1: clk@62000048 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000048 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_jpg1";
+	};
+
+	clk_mipi_csi0_gate: clk@6200004c {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x6200004c 0 0x4>;
+		clock-indices = <16>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "mipi_csi0_eb";
+	};
+
+	clk_mipi_csi1_gate: clk@62000050 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62000050 0 0x4>;
+		clock-indices = <16>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "mipi_csi1_eb";
+	};
+
+	clk_cpp: clk@6200005c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200005c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_cpp";
+	};
+
+	clk_isp_mclk: clk@62000060 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000060 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp_mclk";
+	};
+
+	clk_isp_pclk: clk@62000064 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000064 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>;
+		clock-output-names = "clk_isp_pclk";
+	};
+
+	clk_isp_iclk: clk@62000068 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000068 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp_iclk";
+	};
+
+	clk_isp_lclk: clk@6200006c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200006c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp_lclk";
+	};
+
+	clk_isp2: clk@62000070 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000070 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp2";
+	};
+
+	clk_isp2dcam: clk@62000074 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000074 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_153m6>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>;
+		clock-output-names = "clk_isp2dcam";
+	};
+
+	clk_cam_26m: clk@62000078 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000078 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_cam_26m";
+	};
+
+	clk_ap_ahb_gates: clk@20210000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x20210000 0 0x3000>;
+		clock-indices = <2>, <3>, <4>, <5>,
+				<7>, <8>, <9>, <10>,
+				<12>, <13>, <22>,
+				<23>, <24>, <25>;
+		clocks = <&clk_ap_axi>;
+		clock-output-names = "usb3_eb", "usb3_suspend_eb",
+				     "usb3_ref_eb", "dma_eb",
+				     "sdio0_eb", "sdio1_eb",
+				     "sdio2_eb", "emmc_eb",
+				     "rom_eb", "busmon_eb",
+				     "cc63s_eb", "cc63p_eb",
+				     "ce0_eb", "ce1_eb";
+	};
+
+	clk_aon_apb_gates0: clk@402e0000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e0000 0 0x3000>;
+		clocks = <&clk_aon_apb>;
+		clock-output-names = "avs_ca53_lit_eb", "avs_ca53_big_eb",
+				     "ap_intc5_eb", "gpio_eb",
+				     "pwm0_eb", "pwm1_eb",
+				     "pwm2_eb", "pwm3_eb",
+				     "kpd_eb", "aon_syst_eb",
+				     "ap_syst_eb", "aon_tmr_eb",
+				     "ap_tmr0_eb", "efuse_eb",
+				     "eic_eb", "pub1_reg_eb",
+				     "adi_eb", "ap_intc0_eb",
+				     "ap_intc1_eb", "ap_intc2_eb",
+				     "ap_intc3_eb", "ap_intc4_eb",
+				     "splk_eb", "mspi_eb",
+				     "pub0_reg_eb", "pin_eb",
+				     "aon_ckg_eb", "gpu_eb",
+				     "apcpu_ts0_eb", "apcpu_ts1_eb",
+				     "dap_eb", "i2c_eb";
+	};
+
+	clk_aon_apb_gates1: clk@402e0004 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e0004 0 0x3000>;
+		clocks = <&clk_aon_apb>;
+		clock-output-names = "pmu_eb", "thm_eb",
+				     "aux0_eb", "aux1_eb",
+				     "aux2_eb", "probe_eb",
+				     "gpu0_avs_eb", "gpu1_avs_eb",
+				     "apcpu_wdg_eb", "ap_tmr1_eb",
+				     "ap_tmr2_eb", "disp_emc_eb",
+				     "zip_emc_eb", "gsp_emc_eb",
+				     "osc_aon_eb", "lvds_trx_eb",
+				     "lvds_tcxo_eb", "mdar_eb",
+				     "rtc4m0_cal_eb", "rct100m_cal_eb",
+				     "djtag_eb", "mbox_eb",
+				     "aon_dma_eb", "dbg_emc_eb",
+				     "lvds_pll_div_en", "def_eb",
+				     "aon_apb_gate1_rsv0", "orp_jtag_eb",
+				     "vsp_eb", "cam_eb",
+				     "disp_eb", "dbg_axi_if_eb";
+	};
+
+	clk_agcp_ahb_gates: clk@415e0000 {
+		compatible = "sprd,sc100-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x415e0000 0 0x300>;
+		clock-indices = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>,
+				<10>, <11>,
+				<12>, <13>, <14>, <15>,
+				<16>, <17>, <18>, <19>,
+				<20>;
+		clock-output-names = "agcp_iis0_eb", "agcp_iis1_eb",
+				     "agcp_iis2_eb", "agcp_iis3_eb",
+				     "agcp_uart_eb", "agcp_dmacp_eb",
+				     "agcp_dmaap_eb", "agcp_arc48k_eb",
+				     "agcp_src44p1k_eb", "agcp_mcdt_eb",
+				     "agcp_vbcifd_eb", "agcp_vbc_eb",
+				     "agcp_spinlock_eb", "agcp_icu_eb",
+				     "agcp_ap_ashb_eb", "agcp_cp_ashb_eb",
+				     "agcp_aud_eb", "agcp_audif_eb";
+	};
+
+	clk_ahb_vsp_gates: clk@61100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x61100000 0 0x3000>;
+		clocks = <&clk_ahb_vsp>;
+		clock-output-names = "vsp_dec_eb", "vsp_ckg_eb",
+				     "vsp_mmu_eb", "vsp_enc_eb",
+				     "vpp_eb", "vsp_26m_eb";
+	};
+
+	clk_vsp_axi_gates: clk@61100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x61100008 0 0x4>;
+		clock-indices = <0>, <1>, <2>,
+				<8>, <9>, <10>;
+		clocks = <&clk_ahb_vsp>;
+		clock-output-names = "vsp_axi_gate", "vsp_enc_gate",
+				     "vpp_axi_gate", "vsp_bm_gate",
+				     "vsp_enc_bm_gate", "vpp_bm_gate";
+	};
+
+	clk_ahb_cam_gates: clk@62100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100000 0 0x3000>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "dcam0_eb", "dcam1_eb",
+				     "isp0_eb", "csi0_eb",
+				     "csi1_eb", "jpg0_eb",
+				     "jpg1_eb", "cam_ckg_eb",
+				     "cam_mmu_eb", "isp1_eb",
+				     "cpp_eb", "mmu_pf_eb",
+				     "isp2_eb", "dcam2isp_if_eb",
+				     "isp2dcam_if_eb", "isp_lclk_eb",
+				     "isp_iclk_eb", "isp_mclk_eb",
+				     "isp_pclk_eb", "isp_isp2dcam_eb",
+				     "dcam0_if_eb", "clk26m_if_eb";
+	};
+
+	clk_cam_axi_gates: clk@62100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100008 0 0x4>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "cphy0_gate", "mipi_csi0_gate",
+				     "cphy1_gate", "mipi_csi1",
+				     "dcam0_axi_gate", "dcam1_axi_gate",
+				     "sensor0_gate", "sensor1_gate",
+				     "jpg0_axi_gate", "gpg1_axi_gate",
+				     "isp0_axi_gate", "isp1_axi_gate",
+				     "isp2_axi_gate", "cpp_axi_gate",
+				     "d0_if_axi_gate", "d2i_if_axi_gate",
+				     "i2d_if_axi_gate", "spare_axi_gate",
+				     "sensor2_gate";
+	};
+
+	clk_cam_module_gates: clk@62100028 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100028 0 0x3000>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "d0if_in_d_en", "d1if_in_d_en",
+				     "d0if_in_d2i_en", "d1if_in_d2i_en",
+				     "ia_in_d2i_en", "ib_in_d2i_en",
+				     "ic_in_d2i_en", "ia_in_i_en",
+				     "ib_in_i_en", "ic_in_i_en";
+	};
+
+	clk_ahb_disp_gates: clk@63100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x63100000 0 0x3000>;
+		clock-indices = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>, <7>,
+				<8>, <9>, <10>,
+				<13>, <14>, <15>,
+				<16>;
+		clocks = <&clk_ahb_disp>;
+		clock-output-names = "dispc0_eb", "dispc1_eb",
+				     "dispc_mmu_eb", "gsp0_eb",
+				     "gsp1_eb", "gsp0_mmu_eb",
+				     "gsp1_mmu_eb", "dsi0_eb",
+				     "dsi1_eb", "disp_ckg_eb",
+				     "disp_gpu_eb", "gpu_mtx_eb",
+				     "gsp_mtx_eb", "tmc_mtx_eb",
+				     "dispc_mtx_eb";
+	};
+
+	clk_disp_axi_gates: clk@63100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x63100008 0 0x4>;
+		clocks = <&clk_ahb_disp>;
+		clock-output-names = "dphy0_gate", "dphy1_gate",
+				     "gsp0_a_gate", "gsp1_a_gate",
+				     "gsp0_f_gate", "gsp1_f_gate",
+				     "d_mtx_f_gate", "d_mtx_a_gate",
+				     "d_noc_f_gate", "d_noc_a_gate",
+				     "gsp_mtx_f_gate", "gsp_mtx_a_gate",
+				     "gsp_noc_f_gate", "gsp_noc_a_gate",
+				     "dispm0idle_gate", "gspm0idle_gate";
+	};
+
+	clk_ap_apb_gates: clk@70b00000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x70b00000 0 0x3000>;
+		clocks = <&clk_ap_apb>;
+		clock-output-names = "sim0_eb", "iis0_eb",
+				     "iis1_eb", "iis2_eb",
+				     "iis3_eb", "spi0_eb",
+				     "spi1_eb", "spi2_eb",
+				     "i2c0_eb", "i2c1_eb",
+				     "i2c2_eb", "i2c3_eb",
+				     "i2c4_eb", "i2c5_eb",
+				     "uart0_eb", "uart1_eb",
+				     "uart2_eb", "uart3_eb",
+				     "uart4_eb", "ap_ckg_eb",
+				     "spi3_eb";
+	};
+};
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index 7b7d8ce..97794fe 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -8,6 +8,7 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "whale2.dtsi"
+#include "sc9860-clocks.dtsi"
 
 / {
 	cpus {
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi
index cd5a71f..8d1f8aa 100644
--- a/arch/arm64/boot/dts/sprd/whale2.dtsi
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -79,11 +79,4 @@
 		};
 
 	};
-
-	ext_26m: ext-26m {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <26000000>;
-		clock-output-names = "ext_26m";
-	};
 };
-- 
2.7.4

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

* [PATCH 1/3] arm64: dts: add SC9860 clock tree data
@ 2017-05-15  8:35   ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

From: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>

This patch addresses SC9860 clock topology structure and provides clock
node to other devices (clock consumers) on chip.

This patch also removed replicated node of 26m fixed clock.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi | 1984 +++++++++++++++++++++++++++
 arch/arm64/boot/dts/sprd/sc9860.dtsi        |    1 +
 arch/arm64/boot/dts/sprd/whale2.dtsi        |    7 -
 3 files changed, 1985 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi

diff --git a/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi b/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
new file mode 100644
index 0000000..5756933
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
@@ -0,0 +1,1984 @@
+/*
+ * Spreadtrum SC9860 SoC DTS file
+ *
+ * Copyright (C) 2015, Spreadtrum Communications Inc.
+ *
+ * This file is licensed under a dual GPLv2 or X11 license.
+ */
+&soc {
+	aliases {
+		apb_pclk = &clk_ap_apb;
+	};
+
+	ext_26m: ext-26m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "ext_26m";
+	};
+
+	ext_32m_sine0: ext-32m-sine0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "ext_32m_sine0";
+	};
+
+	ext_32m_sine1: ext-32m-sine1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "ext_32m_sine1";
+	};
+
+	clk_pll_in: clk-pll-in {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "ext_26m";
+	};
+
+	clk_4m: clk-4m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_4m";
+	};
+
+	clk_2m: clk-2m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <13>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_2m";
+	};
+
+	clk_1m: clk-1m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <26>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_1m";
+	};
+
+	clk_250k: clk-250k {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <104>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_250k";
+	};
+
+	ext_rco_100m: ext-rco-100m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "ext_rco_100m";
+	};
+
+	ext_32k: ext-32k {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "ext_32k";
+	};
+
+	clk_rpll0_26m: clk-rpll0-26m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_rpll0_26m";
+	};
+
+	clk_rpll1_26m: clk-rpll1-26m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_rpll1_26m";
+	};
+
+	clk_rpll_gates: clk@402b016c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b016c 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_rpll0_gate", "clk_rpll1_gate";
+	};
+
+	clk_mpll_gates: clk@402b00b0 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b0 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
+	};
+
+	clk_dpll_gates: clk@402b00b4 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b4 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_dpll0_gate", "clk_dpll1_gate";
+	};
+
+	clk_gpll_gate: clk@402b032c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402b032d 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_gpll_gate";
+	};
+
+	clk_cppll_gate: clk@402b02b4 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b02b4 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_cppll_gate";
+	};
+
+	clk_ltepll0_gate: clk@402b00b8 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b8 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_ltepll0_gate";
+	};
+
+	clk_ltepll1_gate: clk@402b010c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b010c 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_ltepll1_gate";
+	};
+
+	clk_twpll_gate: clk@402b00bc {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00bc 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_twpll_gate";
+	};
+
+	clk_rpll0: clk@40400044 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400044 0 0x4>,
+		      <0 0x40400048 0 0x4>,
+		      <0 0x4040004c 0 0x4>;
+		clocks = <&clk_rpll_gates 2>;
+		clock-output-names = "clk_rpll0";
+	};
+
+	clk_rpll1: clk@40400050 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400050 0 0x4>,
+		      <0 0x40400054 0 0x4>,
+		      <0 0x40400058 0 0x4>;
+		clocks = <&clk_rpll_gates 18>;
+		clock-output-names = "clk_rpll1";
+	};
+
+	clk_mpll0: clk@40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
+
+	clk_mpll1: clk@4040002c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040002c 0 0x4>,
+		      <0 0x40400030 0 0x4>;
+		clocks = <&clk_mpll_gates 18>;
+		clock-output-names = "clk_mpll1";
+	};
+
+	clk_dpll0: clk@40400034 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400034 0 0x4>,
+		      <0 0x40400038 0 0x4>;
+		clocks = <&clk_dpll_gates 2>;
+		clock-output-names = "clk_dpll0";
+	};
+
+	clk_dpll1: clk@4040003c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040003c 0 0x4>,
+		      <0 0x40400040 0 0x4>;
+		clocks = <&clk_dpll_gates 18>;
+		clock-output-names = "clk_dpll1";
+	};
+
+	clk_gpll: clk@4040009c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040009c 0 0x4>,
+		      <0 0x404000a0 0 0x4>;
+		clocks = <&clk_gpll_gate>;
+		clock-output-names = "clk_gpll";
+	};
+
+	clk_cppll: clk@404000c4 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x404000c4 0 0x4>,
+		      <0 0x404000c8 0 0x4>;
+		clocks = <&clk_cppll_gate 2>;
+		clock-output-names = "clk_cppll";
+	};
+
+	clk_ltepll0: clk@40400064 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400064 0 0x4>,
+		      <0 0x40400068 0 0x4>;
+		clocks = <&clk_ltepll0_gate 2>;
+		clock-output-names = "clk_ltepll0";
+	};
+
+	clk_ltepll1: clk@4040006c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040006c 0 0x4>,
+		      <0 0x40400070 0 0x4>;
+		clocks = <&clk_ltepll1_gate 2>;
+		clock-output-names = "clk_ltepll1";
+	};
+
+	clk_twpll: clk@4040005c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040005c 0 0x4>,
+		      <0 0x40400060 0 0x4>;
+		clocks = <&clk_twpll_gate 2>;
+		clock-output-names = "clk_twpll";
+	};
+
+	clk_gpll_42m5: clk-gpll-42m5 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <20>;
+		clocks = <&clk_gpll>;
+		clock-output-names = "clk_gpll_42m5";
+	};
+
+	clk_twpll_768m: clk-tw-768m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_768m";
+	};
+
+	clk_twpll_384m: clk-tw-384m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <4>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_384m";
+	};
+
+	clk_twpll_192m: clk-tw-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <8>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_192m";
+	};
+
+	clk_twpll_96m: clk-tw-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_96m";
+	};
+
+	clk_twpll_48m: clk-tw-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_48m";
+	};
+
+	clk_twpll_24m: clk-tw-24m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <64>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_24m";
+	};
+
+	clk_twpll_12m: clk-tw-12m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <128>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_12m";
+	};
+
+	clk_twpll_512m: clk-tw-512m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <3>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_512m";
+	};
+
+	clk_twpll_256m: clk-tw-256m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_256m";
+	};
+
+	clk_twpll_128m: clk-tw-128m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_128m";
+	};
+
+	clk_twpll_64m: clk-tw-64m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_64m";
+	};
+
+	clk_twpll_307m2: clk-tw-307m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <5>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_307m2";
+	};
+
+	clk_twpll_153m6: clk-tw-153m6 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <10>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_153m6";
+	};
+
+	clk_twpll_76m8: clk-tw-76m8 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <20>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_76m8";
+	};
+
+	clk_twpll_51m2: clk-tw-51m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <30>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_51m2";
+	};
+
+	clk_twpll_38m4: clk-tw-38m4 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <40>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_38m4";
+	};
+
+	clk_twpll_19m2: clk-tw-19m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <80>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_19m2";
+	};
+
+	clk_l0_614m4: clk-l0-614m4 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_614m4";
+	};
+
+	clk_l0_38m: clk-l0-38m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_38m";
+	};
+
+	clk_l0_409m6: clk-l0-409m6 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <3>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_409m6";
+	};
+
+	clk_l1_38m: clk-l1-38m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_ltepll1>;
+		clock-output-names = "clk_l1_38m";
+	};
+
+	clk_rpll0_192m: clk-rpll0-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_192m";
+	};
+
+	clk_rpll0_96m: clk-rpll0-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_96m";
+	};
+
+	clk_rpll0_48m: clk-rpll0-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_48m";
+	};
+
+	clk_rpll1_468m: clk-rpll1-468m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_468m";
+	};
+
+	clk_rpll1_192m: clk-rpll1-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_192m";
+	};
+
+	clk_rpll1_96m: clk-rpll1-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_96m";
+	};
+
+	clk_rpll1_64m: clk-rpll1-64m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <18>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_64m";
+	};
+
+	clk_rpll1_48m: clk-rpll1-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_48m";
+	};
+
+	clk_dpll0_50m: clk-dpll0-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_dpll0>;
+		clock-output-names = "clk_dpll0_50m";
+	};
+
+	clk_dpll1_50m: clk-dpll1-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_dpll1>;
+		clock-output-names = "clk_dpll1_50m";
+	};
+
+	clk_cppll_50m: clk-cppll-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <18>;
+		clocks = <&clk_cppll>;
+		clock-output-names = "clk_cppll_50m";
+	};
+
+	clk_rco_25m: clk-rco-25m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <4>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_25m";
+	};
+
+	clk_rco_4m: clk-rco-4m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <25>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_4m";
+	};
+
+	clk_rco_2m: clk-rco-2m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <50>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_2m";
+	};
+
+	clk_3k2: clk-3k2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <10>;
+		clocks = <&ext_32k>;
+		clock-output-names = "clk_3k2";
+	};
+
+	clk_1k: clk-1k {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&ext_32k>;
+		clock-output-names = "clk_1k";
+	};
+
+	clk_aon_apb: clk@402d0230 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0230 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_rco_25m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_aon_apb";
+	};
+
+	clk_adi: clk@402d0234 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0234 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&clk_rco_25m>,
+			 <&clk_twpll_38m4>, <&clk_twpll_51m2>;
+		clock-output-names = "clk_adi";
+	};
+
+	clk_m0_39m: clk-m0-39m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_mpll0>;
+		clock-output-names = "clk_m0_39m";
+	};
+
+	clk_m1_63m: clk-m1-63m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_mpll1>;
+		clock-output-names = "clk_m1_63m";
+	};
+
+	clk_aux0: clk@402d0238 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0238 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux0";
+	};
+
+	clk_aux1: clk@402d023c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d023c 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux1";
+	};
+
+	clk_aux2: clk@402d0240 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0240 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux2";
+	};
+
+	clk_probe: clk@402d0244 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0244 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_probe";
+	};
+
+	clk_pwm0: clk@402d0248 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0248 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm0";
+	};
+
+	clk_pwm1: clk@402d024c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d024c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm1";
+	};
+
+	clk_pwm2: clk@402d0250 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0250 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm2";
+	};
+
+	clk_pwm3: clk@402d0254 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0254 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm3";
+	};
+
+	clk_efuse: clk@402d0258 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0258 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_efuse";
+	};
+
+	clk_cm3_uart0: clk@402d025c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d025c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>,<&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>;
+		clock-output-names = "clk_cm3_uart0";
+	};
+
+	clk_cm3_uart1: clk@402d0260 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0260 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>,<&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>;
+		clock-output-names = "clk_cm3_uart1";
+	};
+
+	clk_thm: clk@402d0270 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0270 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_250k>;
+		clock-output-names = "clk_thm";
+	};
+
+	clk_cm3_i2c0: clk@402d0274 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0274 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_cm3_i2c0";
+	};
+
+	clk_cm3_i2c1: clk@402d0278 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0278 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_cm3_i2c1";
+	};
+
+	clk_cm4_spi: clk@402d027c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d027c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&ext_rco_100m>,
+			 <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_cm4_spi";
+	};
+
+	clk_aon_i2c: clk@402d0280 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0280 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_aon_i2c";
+	};
+
+	clk_avs: clk@402d0284 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0284 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_avs";
+	};
+
+	clk_ca53_dap: clk@402d0288 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0288 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_26m>, <&clk_rco_4m>, <&ext_rco_100m>,
+			 <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ca53_dap";
+	};
+
+	clk_ca53_ts: clk@402d0290 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0290 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ca53_ts";
+	};
+
+	clk_26m_lvdsdis: clk@402d0294 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0294 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_26m_lvdsdis";
+	};
+
+	clk_lvdsrf_cali: clk@402d02b8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02b8 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_lvdsrf_cali";
+	};
+
+	clk_mdar_chk: clk@402d02bc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02bc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_mdar_chk";
+	};
+
+	clk_rco100m_ref: clk@402d02c0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c0 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_2m>;
+		clock-output-names = "clk_rco100m_ref";
+	};
+
+	clk_rco100m_fdk: clk@402d02c4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_2m>;
+		clock-output-names = "clk_rco100m_fdk";
+	};
+
+	clk_djtag_tck: clk@402d02c8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c8 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_4m>, <&ext_26m>;
+		clock-output-names = "clk_djtag_tck";
+	};
+
+	clk_sp_ahb: clk@402d02d0 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02d0 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_sp_ahb";
+	};
+
+	clk_det_32k: clk@402d02dc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02dc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_4m>;
+		clock-output-names = "clk_det_32k";
+	};
+
+	clk_pmu: clk@402d02e0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e0 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&clk_rco_4m>, <&clk_4m>;
+		clock-output-names = "clk_pmu";
+	};
+
+	clk_pmu_26m: clk@402d02e4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_pmu_26m";
+	};
+
+	clk_debounce: clk@402d02e8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e8 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_debounce";
+	};
+
+	clk_dphy_ref: clk@402d02f0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f0 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy_ref";
+	};
+
+	clk_otg2_ref: clk@402d02f4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_twpll_12m>, <&clk_twpll_24m>;
+		clock-output-names = "clk_otg2_ref";
+	};
+
+	clk_usb3_ref: clk@402d02f8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f8 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_24m>, <&clk_twpll_19m2>, <&clk_twpll_48m>;
+		clock-output-names = "clk_usb3_ref";
+	};
+
+	clk_usb3_suspend: clk@402d02fc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02fc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_1m>;
+		clock-output-names = "clk_usb3_suspend";
+	};
+
+	clk_cci: clk@402d0300 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0300 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&ext_26m>, <&clk_twpll_384m>, <&clk_l0_614m4>,
+			 <&clk_twpll_768m>;
+		clock-output-names = "clk_cci";
+	};
+
+	clk_gic: clk@402d0304 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0304 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&ext_26m>, <&clk_twpll_384m>, <&clk_l0_614m4>,
+			 <&clk_twpll_768m>;
+		clock-output-names = "clk_gic";
+	};
+
+	clk_ap_axi: clk@402d0324 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0324 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>;
+		clock-output-names = "clk_ap_axi";
+	};
+
+	clk_sdio_gates: clk@402e013c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e013c 0 0x3000>;
+		clock-indices = <2>, <3>,
+				<4>, <5>, <6>, <7>,
+				<8>, <9>;
+		clock-output-names = "sdio0_2x_en", "sdio0_1x_en",
+				     "sdio1_2x_en", "sdio1_1x_en",
+				     "sdio2_2x_en", "sdio2_1x_en",
+				     "emmc_1x_en", "emmc_2x_en";
+	};
+
+	clk_sdio0_2x: clk@402d0328 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0328 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio0_2x";
+	};
+
+	clk_sdio0_1x: clk@402d032c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d032c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio0_2x>;
+		clock-output-names = "clk_sdio0_1x";
+	};
+
+	clk_sdio1_2x: clk@402d0330 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0330 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio1_2x";
+	};
+
+	clk_sdio1_1x: clk@402d0334 {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0334 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio1_2x>;
+		clock-output-names = "clk_sdio1_1x";
+	};
+
+	clk_sdio2_2x: clk@402d0338 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0338 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio2_2x";
+	};
+
+	clk_sdio2_1x: clk@402d033c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d033c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio2_2x>;
+		clock-output-names = "clk_sdio2_1x";
+	};
+
+	clk_emmc_2x: clk@402d0340 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0340 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_emmc_2x";
+	};
+
+	clk_emmc_1x: clk@402d0344 {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0344 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_emmc_2x>;
+		clock-output-names = "clk_emmc_1x";
+	};
+
+	clk_ap_apb: clk@20000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_64m>, <&clk_twpll_96m>,
+			 <&clk_twpll_128m>;
+		clock-output-names = "clk_ap_apb";
+	};
+
+	clk_ap_usb3_ref: clk@2000002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000002c 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_twpll_24m>;
+		clock-output-names = "clk_ap_usb3_ref";
+	};
+
+	clk_uart0: clk@20000030 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart0";
+	};
+
+	clk_uart1: clk@20000034 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000034 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart1";
+	};
+
+	clk_uart2: clk@20000038 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000038 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart2";
+	};
+
+	clk_uart3: clk@2000003c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000003c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart3";
+	};
+
+	clk_uart4: clk@20000040 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000040 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart4";
+	};
+
+	clk_i2c0: clk@20000044 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000044 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c0";
+	};
+
+	clk_i2c1: clk@20000048 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000048 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c1";
+	};
+
+	clk_i2c2: clk@2000004c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000004c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c2";
+	};
+
+	clk_i2c3: clk@20000050 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000050 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c3";
+	};
+
+	clk_i2c4: clk@20000054 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000054 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c4";
+	};
+
+	clk_i2c5: clk@20000058 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000058 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c5";
+	};
+
+	clk_spi0: clk@2000005c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000005c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi0";
+	};
+
+	clk_spi1: clk@20000060 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000060 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi1";
+	};
+
+	clk_spi2: clk@20000064 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000064 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi2";
+	};
+
+	clk_spi3: clk@20000068 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000068 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi3";
+	};
+
+	clk_iis0: clk@2000006c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000006c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis0";
+	};
+
+	clk_iis1: clk@20000070 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000070 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis1";
+	};
+
+	clk_iis2: clk@20000074 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000074 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis2";
+	};
+
+	clk_iis3: clk@20000078 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000078 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis3";
+	};
+
+	clk_big_mcu: clk@40880024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40880024 0 0x4>;
+		sprd,mux-msk = <0xf>;
+		sprd,div-msk = <0x70>;
+		clocks = <&ext_26m>, <&clk_twpll_512m>, <&clk_twpll_768m>,
+			 <&clk_ltepll0>, <&clk_twpll>, <&clk_twpll>,
+			 <&clk_twpll>, <&clk_twpll>, <&clk_mpll1>;
+		clock-output-names = "clk_big_mcu";
+	};
+
+	clk_lit_mcu: clk@40880020 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40880020 0 0x4>;
+		sprd,mux-msk = <0xf>;
+		sprd,div-msk = <0x70>;
+		clocks = <&ext_26m>, <&clk_twpll_512m>, <&clk_twpll_768m>,
+			<&clk_ltepll0>, <&clk_twpll>, <&clk_twpll>,
+			<&clk_twpll>, <&clk_twpll>, <&clk_mpll0>;
+		clock-output-names = "clk_lit_mcu";
+	};
+
+	/* gpu domain */
+	clk_gpu: clk@60200020 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x60200020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_twpll_512m>, <&clk_twpll_768m>, <&clk_gpll>;
+		clock-output-names = "clk_gpu";
+	};
+
+	/* vsp domain */
+	clk_ahb_vsp: clk@61000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_vsp";
+	};
+
+	clk_vsp: clk@61000024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000024 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_vsp";
+	};
+
+	clk_vsp_enc: clk@61000028 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_vsp_enc";
+	};
+
+	clk_vpp: clk@6100002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6100002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_96m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_vpp";
+	};
+
+	clk_vsp_26m: clk@61000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000030 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_vsp_26m";
+	};
+
+	clk_ahb_disp: clk@63000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_disp";
+	};
+
+	clk_gsp0: clk@63000024 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000024 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_512m>, <&clk_l0_614m4>;
+		clock-output-names = "clk_gsp0";
+	};
+
+	clk_gsp1: clk@63000028 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_512m>, <&clk_l0_614m4>;
+		clock-output-names = "clk_gsp1";
+	};
+
+	clk_dispc0: clk@6300002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_192m>, <&clk_twpll_256m>,
+			 <&clk_twpll_384m>, <&clk_twpll_512m>;
+		clock-output-names = "clk_dispc0";
+	};
+
+	clk_dispc0_dbi: clk@63000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc0_dbi";
+	};
+
+	clk_dispc0_dpi: clk@63000034 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000034 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc0_dpi";
+	};
+
+	clk_dispc1: clk@63000038 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000038 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_192m>, <&clk_twpll_256m>,
+			 <&clk_twpll_384m>, <&clk_twpll_512m>;
+		clock-output-names = "clk_dispc1";
+	};
+
+	clk_dispc1_dbi: clk@6300003c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300003c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc1_dbi";
+	};
+
+	clk_dispc1_dpi: clk@63000040 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000040 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc1_dpi";
+	};
+
+	clk_dphy0: clk@6300004c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300004c 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy0";
+	};
+
+	clk_dphy1: clk@63000058 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000058 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy1";
+	};
+
+	clk_ahb_cam: clk@62000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_cam";
+	};
+
+	clk_sensor0: clk@62000024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000024 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor0";
+	};
+
+	clk_sensor1: clk@62000028 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor1";
+	};
+
+	clk_sensor2: clk@6200002c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor2";
+	};
+
+	clk_dcam0: clk@62000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_153m6>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>;
+		clock-output-names = "clk_dcam0";
+	};
+
+	clk_dcam1: clk@62000034 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000034 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_dcam1";
+	};
+
+	clk_dcam0_if: clk@62000038 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000038 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_dcam0_if";
+	};
+
+	clk_isp0: clk@6200003c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200003c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp0";
+	};
+
+	clk_isp1: clk@62000040 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000040 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp1";
+	};
+
+	clk_jpg0: clk@62000044 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000044 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_jpg0";
+	};
+
+	clk_jpg1: clk@62000048 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000048 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_jpg1";
+	};
+
+	clk_mipi_csi0_gate: clk@6200004c {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x6200004c 0 0x4>;
+		clock-indices = <16>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "mipi_csi0_eb";
+	};
+
+	clk_mipi_csi1_gate: clk@62000050 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62000050 0 0x4>;
+		clock-indices = <16>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "mipi_csi1_eb";
+	};
+
+	clk_cpp: clk@6200005c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200005c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_cpp";
+	};
+
+	clk_isp_mclk: clk@62000060 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000060 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp_mclk";
+	};
+
+	clk_isp_pclk: clk@62000064 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000064 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>;
+		clock-output-names = "clk_isp_pclk";
+	};
+
+	clk_isp_iclk: clk@62000068 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000068 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp_iclk";
+	};
+
+	clk_isp_lclk: clk@6200006c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200006c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp_lclk";
+	};
+
+	clk_isp2: clk@62000070 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000070 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp2";
+	};
+
+	clk_isp2dcam: clk@62000074 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000074 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_153m6>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>;
+		clock-output-names = "clk_isp2dcam";
+	};
+
+	clk_cam_26m: clk@62000078 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000078 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_cam_26m";
+	};
+
+	clk_ap_ahb_gates: clk@20210000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x20210000 0 0x3000>;
+		clock-indices = <2>, <3>, <4>, <5>,
+				<7>, <8>, <9>, <10>,
+				<12>, <13>, <22>,
+				<23>, <24>, <25>;
+		clocks = <&clk_ap_axi>;
+		clock-output-names = "usb3_eb", "usb3_suspend_eb",
+				     "usb3_ref_eb", "dma_eb",
+				     "sdio0_eb", "sdio1_eb",
+				     "sdio2_eb", "emmc_eb",
+				     "rom_eb", "busmon_eb",
+				     "cc63s_eb", "cc63p_eb",
+				     "ce0_eb", "ce1_eb";
+	};
+
+	clk_aon_apb_gates0: clk@402e0000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e0000 0 0x3000>;
+		clocks = <&clk_aon_apb>;
+		clock-output-names = "avs_ca53_lit_eb", "avs_ca53_big_eb",
+				     "ap_intc5_eb", "gpio_eb",
+				     "pwm0_eb", "pwm1_eb",
+				     "pwm2_eb", "pwm3_eb",
+				     "kpd_eb", "aon_syst_eb",
+				     "ap_syst_eb", "aon_tmr_eb",
+				     "ap_tmr0_eb", "efuse_eb",
+				     "eic_eb", "pub1_reg_eb",
+				     "adi_eb", "ap_intc0_eb",
+				     "ap_intc1_eb", "ap_intc2_eb",
+				     "ap_intc3_eb", "ap_intc4_eb",
+				     "splk_eb", "mspi_eb",
+				     "pub0_reg_eb", "pin_eb",
+				     "aon_ckg_eb", "gpu_eb",
+				     "apcpu_ts0_eb", "apcpu_ts1_eb",
+				     "dap_eb", "i2c_eb";
+	};
+
+	clk_aon_apb_gates1: clk@402e0004 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e0004 0 0x3000>;
+		clocks = <&clk_aon_apb>;
+		clock-output-names = "pmu_eb", "thm_eb",
+				     "aux0_eb", "aux1_eb",
+				     "aux2_eb", "probe_eb",
+				     "gpu0_avs_eb", "gpu1_avs_eb",
+				     "apcpu_wdg_eb", "ap_tmr1_eb",
+				     "ap_tmr2_eb", "disp_emc_eb",
+				     "zip_emc_eb", "gsp_emc_eb",
+				     "osc_aon_eb", "lvds_trx_eb",
+				     "lvds_tcxo_eb", "mdar_eb",
+				     "rtc4m0_cal_eb", "rct100m_cal_eb",
+				     "djtag_eb", "mbox_eb",
+				     "aon_dma_eb", "dbg_emc_eb",
+				     "lvds_pll_div_en", "def_eb",
+				     "aon_apb_gate1_rsv0", "orp_jtag_eb",
+				     "vsp_eb", "cam_eb",
+				     "disp_eb", "dbg_axi_if_eb";
+	};
+
+	clk_agcp_ahb_gates: clk@415e0000 {
+		compatible = "sprd,sc100-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x415e0000 0 0x300>;
+		clock-indices = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>,
+				<10>, <11>,
+				<12>, <13>, <14>, <15>,
+				<16>, <17>, <18>, <19>,
+				<20>;
+		clock-output-names = "agcp_iis0_eb", "agcp_iis1_eb",
+				     "agcp_iis2_eb", "agcp_iis3_eb",
+				     "agcp_uart_eb", "agcp_dmacp_eb",
+				     "agcp_dmaap_eb", "agcp_arc48k_eb",
+				     "agcp_src44p1k_eb", "agcp_mcdt_eb",
+				     "agcp_vbcifd_eb", "agcp_vbc_eb",
+				     "agcp_spinlock_eb", "agcp_icu_eb",
+				     "agcp_ap_ashb_eb", "agcp_cp_ashb_eb",
+				     "agcp_aud_eb", "agcp_audif_eb";
+	};
+
+	clk_ahb_vsp_gates: clk@61100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x61100000 0 0x3000>;
+		clocks = <&clk_ahb_vsp>;
+		clock-output-names = "vsp_dec_eb", "vsp_ckg_eb",
+				     "vsp_mmu_eb", "vsp_enc_eb",
+				     "vpp_eb", "vsp_26m_eb";
+	};
+
+	clk_vsp_axi_gates: clk@61100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x61100008 0 0x4>;
+		clock-indices = <0>, <1>, <2>,
+				<8>, <9>, <10>;
+		clocks = <&clk_ahb_vsp>;
+		clock-output-names = "vsp_axi_gate", "vsp_enc_gate",
+				     "vpp_axi_gate", "vsp_bm_gate",
+				     "vsp_enc_bm_gate", "vpp_bm_gate";
+	};
+
+	clk_ahb_cam_gates: clk@62100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100000 0 0x3000>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "dcam0_eb", "dcam1_eb",
+				     "isp0_eb", "csi0_eb",
+				     "csi1_eb", "jpg0_eb",
+				     "jpg1_eb", "cam_ckg_eb",
+				     "cam_mmu_eb", "isp1_eb",
+				     "cpp_eb", "mmu_pf_eb",
+				     "isp2_eb", "dcam2isp_if_eb",
+				     "isp2dcam_if_eb", "isp_lclk_eb",
+				     "isp_iclk_eb", "isp_mclk_eb",
+				     "isp_pclk_eb", "isp_isp2dcam_eb",
+				     "dcam0_if_eb", "clk26m_if_eb";
+	};
+
+	clk_cam_axi_gates: clk@62100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100008 0 0x4>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "cphy0_gate", "mipi_csi0_gate",
+				     "cphy1_gate", "mipi_csi1",
+				     "dcam0_axi_gate", "dcam1_axi_gate",
+				     "sensor0_gate", "sensor1_gate",
+				     "jpg0_axi_gate", "gpg1_axi_gate",
+				     "isp0_axi_gate", "isp1_axi_gate",
+				     "isp2_axi_gate", "cpp_axi_gate",
+				     "d0_if_axi_gate", "d2i_if_axi_gate",
+				     "i2d_if_axi_gate", "spare_axi_gate",
+				     "sensor2_gate";
+	};
+
+	clk_cam_module_gates: clk@62100028 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100028 0 0x3000>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "d0if_in_d_en", "d1if_in_d_en",
+				     "d0if_in_d2i_en", "d1if_in_d2i_en",
+				     "ia_in_d2i_en", "ib_in_d2i_en",
+				     "ic_in_d2i_en", "ia_in_i_en",
+				     "ib_in_i_en", "ic_in_i_en";
+	};
+
+	clk_ahb_disp_gates: clk@63100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x63100000 0 0x3000>;
+		clock-indices = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>, <7>,
+				<8>, <9>, <10>,
+				<13>, <14>, <15>,
+				<16>;
+		clocks = <&clk_ahb_disp>;
+		clock-output-names = "dispc0_eb", "dispc1_eb",
+				     "dispc_mmu_eb", "gsp0_eb",
+				     "gsp1_eb", "gsp0_mmu_eb",
+				     "gsp1_mmu_eb", "dsi0_eb",
+				     "dsi1_eb", "disp_ckg_eb",
+				     "disp_gpu_eb", "gpu_mtx_eb",
+				     "gsp_mtx_eb", "tmc_mtx_eb",
+				     "dispc_mtx_eb";
+	};
+
+	clk_disp_axi_gates: clk@63100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x63100008 0 0x4>;
+		clocks = <&clk_ahb_disp>;
+		clock-output-names = "dphy0_gate", "dphy1_gate",
+				     "gsp0_a_gate", "gsp1_a_gate",
+				     "gsp0_f_gate", "gsp1_f_gate",
+				     "d_mtx_f_gate", "d_mtx_a_gate",
+				     "d_noc_f_gate", "d_noc_a_gate",
+				     "gsp_mtx_f_gate", "gsp_mtx_a_gate",
+				     "gsp_noc_f_gate", "gsp_noc_a_gate",
+				     "dispm0idle_gate", "gspm0idle_gate";
+	};
+
+	clk_ap_apb_gates: clk@70b00000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x70b00000 0 0x3000>;
+		clocks = <&clk_ap_apb>;
+		clock-output-names = "sim0_eb", "iis0_eb",
+				     "iis1_eb", "iis2_eb",
+				     "iis3_eb", "spi0_eb",
+				     "spi1_eb", "spi2_eb",
+				     "i2c0_eb", "i2c1_eb",
+				     "i2c2_eb", "i2c3_eb",
+				     "i2c4_eb", "i2c5_eb",
+				     "uart0_eb", "uart1_eb",
+				     "uart2_eb", "uart3_eb",
+				     "uart4_eb", "ap_ckg_eb",
+				     "spi3_eb";
+	};
+};
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index 7b7d8ce..97794fe 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -8,6 +8,7 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "whale2.dtsi"
+#include "sc9860-clocks.dtsi"
 
 / {
 	cpus {
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi
index cd5a71f..8d1f8aa 100644
--- a/arch/arm64/boot/dts/sprd/whale2.dtsi
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -79,11 +79,4 @@
 		};
 
 	};
-
-	ext_26m: ext-26m {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <26000000>;
-		clock-output-names = "ext_26m";
-	};
 };
-- 
2.7.4

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

* [PATCH 1/3] arm64: dts: add SC9860 clock tree data
@ 2017-05-15  8:35   ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>

This patch addresses SC9860 clock topology structure and provides clock
node to other devices (clock consumers) on chip.

This patch also removed replicated node of 26m fixed clock.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi | 1984 +++++++++++++++++++++++++++
 arch/arm64/boot/dts/sprd/sc9860.dtsi        |    1 +
 arch/arm64/boot/dts/sprd/whale2.dtsi        |    7 -
 3 files changed, 1985 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi

diff --git a/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi b/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
new file mode 100644
index 0000000..5756933
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sc9860-clocks.dtsi
@@ -0,0 +1,1984 @@
+/*
+ * Spreadtrum SC9860 SoC DTS file
+ *
+ * Copyright (C) 2015, Spreadtrum Communications Inc.
+ *
+ * This file is licensed under a dual GPLv2 or X11 license.
+ */
+&soc {
+	aliases {
+		apb_pclk = &clk_ap_apb;
+	};
+
+	ext_26m: ext-26m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "ext_26m";
+	};
+
+	ext_32m_sine0: ext-32m-sine0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "ext_32m_sine0";
+	};
+
+	ext_32m_sine1: ext-32m-sine1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "ext_32m_sine1";
+	};
+
+	clk_pll_in: clk-pll-in {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "ext_26m";
+	};
+
+	clk_4m: clk-4m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_4m";
+	};
+
+	clk_2m: clk-2m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <13>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_2m";
+	};
+
+	clk_1m: clk-1m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <26>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_1m";
+	};
+
+	clk_250k: clk-250k {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <104>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_250k";
+	};
+
+	ext_rco_100m: ext-rco-100m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "ext_rco_100m";
+	};
+
+	ext_32k: ext-32k {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "ext_32k";
+	};
+
+	clk_rpll0_26m: clk-rpll0-26m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_rpll0_26m";
+	};
+
+	clk_rpll1_26m: clk-rpll1-26m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_rpll1_26m";
+	};
+
+	clk_rpll_gates: clk at 402b016c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b016c 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_rpll0_gate", "clk_rpll1_gate";
+	};
+
+	clk_mpll_gates: clk at 402b00b0 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b0 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
+	};
+
+	clk_dpll_gates: clk at 402b00b4 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b4 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_dpll0_gate", "clk_dpll1_gate";
+	};
+
+	clk_gpll_gate: clk at 402b032c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402b032d 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_gpll_gate";
+	};
+
+	clk_cppll_gate: clk at 402b02b4 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b02b4 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_cppll_gate";
+	};
+
+	clk_ltepll0_gate: clk at 402b00b8 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b8 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_ltepll0_gate";
+	};
+
+	clk_ltepll1_gate: clk at 402b010c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b010c 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_ltepll1_gate";
+	};
+
+	clk_twpll_gate: clk at 402b00bc {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00bc 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>;
+		clock-output-names = "clk_twpll_gate";
+	};
+
+	clk_rpll0: clk at 40400044 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400044 0 0x4>,
+		      <0 0x40400048 0 0x4>,
+		      <0 0x4040004c 0 0x4>;
+		clocks = <&clk_rpll_gates 2>;
+		clock-output-names = "clk_rpll0";
+	};
+
+	clk_rpll1: clk at 40400050 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400050 0 0x4>,
+		      <0 0x40400054 0 0x4>,
+		      <0 0x40400058 0 0x4>;
+		clocks = <&clk_rpll_gates 18>;
+		clock-output-names = "clk_rpll1";
+	};
+
+	clk_mpll0: clk at 40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
+
+	clk_mpll1: clk at 4040002c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040002c 0 0x4>,
+		      <0 0x40400030 0 0x4>;
+		clocks = <&clk_mpll_gates 18>;
+		clock-output-names = "clk_mpll1";
+	};
+
+	clk_dpll0: clk at 40400034 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400034 0 0x4>,
+		      <0 0x40400038 0 0x4>;
+		clocks = <&clk_dpll_gates 2>;
+		clock-output-names = "clk_dpll0";
+	};
+
+	clk_dpll1: clk at 4040003c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040003c 0 0x4>,
+		      <0 0x40400040 0 0x4>;
+		clocks = <&clk_dpll_gates 18>;
+		clock-output-names = "clk_dpll1";
+	};
+
+	clk_gpll: clk at 4040009c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040009c 0 0x4>,
+		      <0 0x404000a0 0 0x4>;
+		clocks = <&clk_gpll_gate>;
+		clock-output-names = "clk_gpll";
+	};
+
+	clk_cppll: clk at 404000c4 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x404000c4 0 0x4>,
+		      <0 0x404000c8 0 0x4>;
+		clocks = <&clk_cppll_gate 2>;
+		clock-output-names = "clk_cppll";
+	};
+
+	clk_ltepll0: clk at 40400064 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400064 0 0x4>,
+		      <0 0x40400068 0 0x4>;
+		clocks = <&clk_ltepll0_gate 2>;
+		clock-output-names = "clk_ltepll0";
+	};
+
+	clk_ltepll1: clk at 4040006c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040006c 0 0x4>,
+		      <0 0x40400070 0 0x4>;
+		clocks = <&clk_ltepll1_gate 2>;
+		clock-output-names = "clk_ltepll1";
+	};
+
+	clk_twpll: clk at 4040005c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040005c 0 0x4>,
+		      <0 0x40400060 0 0x4>;
+		clocks = <&clk_twpll_gate 2>;
+		clock-output-names = "clk_twpll";
+	};
+
+	clk_gpll_42m5: clk-gpll-42m5 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <20>;
+		clocks = <&clk_gpll>;
+		clock-output-names = "clk_gpll_42m5";
+	};
+
+	clk_twpll_768m: clk-tw-768m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_768m";
+	};
+
+	clk_twpll_384m: clk-tw-384m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <4>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_384m";
+	};
+
+	clk_twpll_192m: clk-tw-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <8>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_192m";
+	};
+
+	clk_twpll_96m: clk-tw-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_96m";
+	};
+
+	clk_twpll_48m: clk-tw-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_48m";
+	};
+
+	clk_twpll_24m: clk-tw-24m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <64>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_24m";
+	};
+
+	clk_twpll_12m: clk-tw-12m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <128>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_12m";
+	};
+
+	clk_twpll_512m: clk-tw-512m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <3>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_512m";
+	};
+
+	clk_twpll_256m: clk-tw-256m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_256m";
+	};
+
+	clk_twpll_128m: clk-tw-128m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_128m";
+	};
+
+	clk_twpll_64m: clk-tw-64m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_64m";
+	};
+
+	clk_twpll_307m2: clk-tw-307m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <5>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_307m2";
+	};
+
+	clk_twpll_153m6: clk-tw-153m6 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <10>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_153m6";
+	};
+
+	clk_twpll_76m8: clk-tw-76m8 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <20>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_76m8";
+	};
+
+	clk_twpll_51m2: clk-tw-51m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <30>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_51m2";
+	};
+
+	clk_twpll_38m4: clk-tw-38m4 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <40>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_38m4";
+	};
+
+	clk_twpll_19m2: clk-tw-19m2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <80>;
+		clocks = <&clk_twpll>;
+		clock-output-names = "clk_twpll_19m2";
+	};
+
+	clk_l0_614m4: clk-l0-614m4 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_614m4";
+	};
+
+	clk_l0_38m: clk-l0-38m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_38m";
+	};
+
+	clk_l0_409m6: clk-l0-409m6 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <3>;
+		clocks = <&clk_ltepll0>;
+		clock-output-names = "clk_l0_409m6";
+	};
+
+	clk_l1_38m: clk-l1-38m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_ltepll1>;
+		clock-output-names = "clk_l1_38m";
+	};
+
+	clk_rpll0_192m: clk-rpll0-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_192m";
+	};
+
+	clk_rpll0_96m: clk-rpll0-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_96m";
+	};
+
+	clk_rpll0_48m: clk-rpll0-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_rpll0>;
+		clock-output-names = "clk_rpll0_48m";
+	};
+
+	clk_rpll1_468m: clk-rpll1-468m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_468m";
+	};
+
+	clk_rpll1_192m: clk-rpll1-192m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <6>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_192m";
+	};
+
+	clk_rpll1_96m: clk-rpll1-96m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <12>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_96m";
+	};
+
+	clk_rpll1_64m: clk-rpll1-64m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <18>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_64m";
+	};
+
+	clk_rpll1_48m: clk-rpll1-48m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <24>;
+		clocks = <&clk_rpll1>;
+		clock-output-names = "clk_rpll1_48m";
+	};
+
+	clk_dpll0_50m: clk-dpll0-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_dpll0>;
+		clock-output-names = "clk_dpll0_50m";
+	};
+
+	clk_dpll1_50m: clk-dpll1-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <16>;
+		clocks = <&clk_dpll1>;
+		clock-output-names = "clk_dpll1_50m";
+	};
+
+	clk_cppll_50m: clk-cppll-50m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <18>;
+		clocks = <&clk_cppll>;
+		clock-output-names = "clk_cppll_50m";
+	};
+
+	clk_rco_25m: clk-rco-25m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <4>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_25m";
+	};
+
+	clk_rco_4m: clk-rco-4m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <25>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_4m";
+	};
+
+	clk_rco_2m: clk-rco-2m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <50>;
+		clocks = <&ext_rco_100m>;
+		clock-output-names = "clk_rco_2m";
+	};
+
+	clk_3k2: clk-3k2 {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <10>;
+		clocks = <&ext_32k>;
+		clock-output-names = "clk_3k2";
+	};
+
+	clk_1k: clk-1k {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&ext_32k>;
+		clock-output-names = "clk_1k";
+	};
+
+	clk_aon_apb: clk at 402d0230 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0230 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_rco_25m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_aon_apb";
+	};
+
+	clk_adi: clk at 402d0234 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0234 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&clk_rco_25m>,
+			 <&clk_twpll_38m4>, <&clk_twpll_51m2>;
+		clock-output-names = "clk_adi";
+	};
+
+	clk_m0_39m: clk-m0-39m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_mpll0>;
+		clock-output-names = "clk_m0_39m";
+	};
+
+	clk_m1_63m: clk-m1-63m {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <32>;
+		clocks = <&clk_mpll1>;
+		clock-output-names = "clk_m1_63m";
+	};
+
+	clk_aux0: clk at 402d0238 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0238 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux0";
+	};
+
+	clk_aux1: clk at 402d023c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d023c 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux1";
+	};
+
+	clk_aux2: clk at 402d0240 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0240 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_aux2";
+	};
+
+	clk_probe: clk at 402d0244 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0244 0 0x4>;
+		sprd,mux-msk = <0x1f>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&ext_32k>, <&clk_rpll0_26m>, <&clk_rpll1_26m>,
+			 <&ext_26m>, <&clk_cppll_50m>, <&clk_rco_25m>,
+			 <&clk_dpll0_50m>, <&clk_dpll1_50m>, <&clk_gpll_42m5>,
+			 <&clk_twpll_48m>, <&clk_m0_39m>, <&clk_m1_63m>,
+			 <&clk_l0_38m>, <&clk_l1_38m>;
+		clock-output-names = "clk_probe";
+	};
+
+	clk_pwm0: clk at 402d0248 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0248 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm0";
+	};
+
+	clk_pwm1: clk at 402d024c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d024c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm1";
+	};
+
+	clk_pwm2: clk at 402d0250 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0250 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm2";
+	};
+
+	clk_pwm3: clk at 402d0254 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0254 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&clk_twpll_48m>;
+		clock-output-names = "clk_pwm3";
+	};
+
+	clk_efuse: clk at 402d0258 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0258 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_efuse";
+	};
+
+	clk_cm3_uart0: clk at 402d025c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d025c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>,<&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>;
+		clock-output-names = "clk_cm3_uart0";
+	};
+
+	clk_cm3_uart1: clk at 402d0260 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0260 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>,<&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>;
+		clock-output-names = "clk_cm3_uart1";
+	};
+
+	clk_thm: clk at 402d0270 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0270 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_250k>;
+		clock-output-names = "clk_thm";
+	};
+
+	clk_cm3_i2c0: clk at 402d0274 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0274 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_cm3_i2c0";
+	};
+
+	clk_cm3_i2c1: clk at 402d0278 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0278 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_cm3_i2c1";
+	};
+
+	clk_cm4_spi: clk at 402d027c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d027c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&ext_rco_100m>,
+			 <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_cm4_spi";
+	};
+
+	clk_aon_i2c: clk at 402d0280 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0280 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_aon_i2c";
+	};
+
+	clk_avs: clk at 402d0284 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0284 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_avs";
+	};
+
+	clk_ca53_dap: clk at 402d0288 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0288 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&ext_26m>, <&clk_rco_4m>, <&ext_rco_100m>,
+			 <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ca53_dap";
+	};
+
+	clk_ca53_ts: clk at 402d0290 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0290 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&ext_26m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ca53_ts";
+	};
+
+	clk_26m_lvdsdis: clk at 402d0294 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0294 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_26m_lvdsdis";
+	};
+
+	clk_lvdsrf_cali: clk at 402d02b8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02b8 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_lvdsrf_cali";
+	};
+
+	clk_mdar_chk: clk at 402d02bc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02bc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_mdar_chk";
+	};
+
+	clk_rco100m_ref: clk at 402d02c0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c0 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_2m>;
+		clock-output-names = "clk_rco100m_ref";
+	};
+
+	clk_rco100m_fdk: clk at 402d02c4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_2m>;
+		clock-output-names = "clk_rco100m_fdk";
+	};
+
+	clk_djtag_tck: clk at 402d02c8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02c8 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_4m>, <&ext_26m>;
+		clock-output-names = "clk_djtag_tck";
+	};
+
+	clk_sp_ahb: clk at 402d02d0 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02d0 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&ext_rco_100m>,
+			 <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_sp_ahb";
+	};
+
+	clk_det_32k: clk at 402d02dc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02dc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_4m>;
+		clock-output-names = "clk_det_32k";
+	};
+
+	clk_pmu: clk at 402d02e0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e0 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&clk_rco_4m>, <&clk_4m>;
+		clock-output-names = "clk_pmu";
+	};
+
+	clk_pmu_26m: clk at 402d02e4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_pmu_26m";
+	};
+
+	clk_debounce: clk at 402d02e8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02e8 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_32k>, <&clk_rco_4m>,
+			 <&clk_rco_25m>, <&ext_26m>;
+		clock-output-names = "clk_debounce";
+	};
+
+	clk_dphy_ref: clk at 402d02f0 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f0 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy_ref";
+	};
+
+	clk_otg2_ref: clk at 402d02f4 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f4 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&clk_twpll_12m>, <&clk_twpll_24m>;
+		clock-output-names = "clk_otg2_ref";
+	};
+
+	clk_usb3_ref: clk at 402d02f8 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02f8 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_24m>, <&clk_twpll_19m2>, <&clk_twpll_48m>;
+		clock-output-names = "clk_usb3_ref";
+	};
+
+	clk_usb3_suspend: clk at 402d02fc {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d02fc 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_1m>;
+		clock-output-names = "clk_usb3_suspend";
+	};
+
+	clk_cci: clk at 402d0300 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0300 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&ext_26m>, <&clk_twpll_384m>, <&clk_l0_614m4>,
+			 <&clk_twpll_768m>;
+		clock-output-names = "clk_cci";
+	};
+
+	clk_gic: clk at 402d0304 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0304 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&ext_26m>, <&clk_twpll_384m>, <&clk_l0_614m4>,
+			 <&clk_twpll_768m>;
+		clock-output-names = "clk_gic";
+	};
+
+	clk_ap_axi: clk at 402d0324 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0324 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>;
+		clock-output-names = "clk_ap_axi";
+	};
+
+	clk_sdio_gates: clk at 402e013c {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e013c 0 0x3000>;
+		clock-indices = <2>, <3>,
+				<4>, <5>, <6>, <7>,
+				<8>, <9>;
+		clock-output-names = "sdio0_2x_en", "sdio0_1x_en",
+				     "sdio1_2x_en", "sdio1_1x_en",
+				     "sdio2_2x_en", "sdio2_1x_en",
+				     "emmc_1x_en", "emmc_2x_en";
+	};
+
+	clk_sdio0_2x: clk at 402d0328 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0328 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio0_2x";
+	};
+
+	clk_sdio0_1x: clk at 402d032c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d032c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio0_2x>;
+		clock-output-names = "clk_sdio0_1x";
+	};
+
+	clk_sdio1_2x: clk at 402d0330 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0330 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio1_2x";
+	};
+
+	clk_sdio1_1x: clk at 402d0334 {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0334 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio1_2x>;
+		clock-output-names = "clk_sdio1_1x";
+	};
+
+	clk_sdio2_2x: clk at 402d0338 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0338 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_sdio2_2x";
+	};
+
+	clk_sdio2_1x: clk at 402d033c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d033c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio2_2x>;
+		clock-output-names = "clk_sdio2_1x";
+	};
+
+	clk_emmc_2x: clk at 402d0340 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0340 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_1m>, <&ext_26m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>, <&clk_l0_409m6>;
+		clock-output-names = "clk_emmc_2x";
+	};
+
+	clk_emmc_1x: clk at 402d0344 {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0344 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_emmc_2x>;
+		clock-output-names = "clk_emmc_1x";
+	};
+
+	clk_ap_apb: clk at 20000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_64m>, <&clk_twpll_96m>,
+			 <&clk_twpll_128m>;
+		clock-output-names = "clk_ap_apb";
+	};
+
+	clk_ap_usb3_ref: clk at 2000002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000002c 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_32k>, <&clk_twpll_24m>;
+		clock-output-names = "clk_ap_usb3_ref";
+	};
+
+	clk_uart0: clk at 20000030 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart0";
+	};
+
+	clk_uart1: clk at 20000034 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000034 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart1";
+	};
+
+	clk_uart2: clk at 20000038 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000038 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart2";
+	};
+
+	clk_uart3: clk at 2000003c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000003c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart3";
+	};
+
+	clk_uart4: clk at 20000040 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000040 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_uart4";
+	};
+
+	clk_i2c0: clk at 20000044 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000044 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c0";
+	};
+
+	clk_i2c1: clk at 20000048 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000048 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c1";
+	};
+
+	clk_i2c2: clk at 2000004c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000004c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c2";
+	};
+
+	clk_i2c3: clk at 20000050 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000050 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c3";
+	};
+
+	clk_i2c4: clk at 20000054 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000054 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c4";
+	};
+
+	clk_i2c5: clk at 20000058 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000058 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_51m2>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_i2c5";
+	};
+
+	clk_spi0: clk at 2000005c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000005c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi0";
+	};
+
+	clk_spi1: clk at 20000060 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000060 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi1";
+	};
+
+	clk_spi2: clk at 20000064 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000064 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi2";
+	};
+
+	clk_spi3: clk at 20000068 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000068 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>;
+		clock-output-names = "clk_spi3";
+	};
+
+	clk_iis0: clk at 2000006c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x2000006c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis0";
+	};
+
+	clk_iis1: clk at 20000070 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000070 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis1";
+	};
+
+	clk_iis2: clk at 20000074 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000074 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis2";
+	};
+
+	clk_iis3: clk at 20000078 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x20000078 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x3f00>;
+		clocks = <&ext_26m>, <&clk_twpll_128m>, <&clk_twpll_153m6>;
+		clock-output-names = "clk_iis3";
+	};
+
+	clk_big_mcu: clk at 40880024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40880024 0 0x4>;
+		sprd,mux-msk = <0xf>;
+		sprd,div-msk = <0x70>;
+		clocks = <&ext_26m>, <&clk_twpll_512m>, <&clk_twpll_768m>,
+			 <&clk_ltepll0>, <&clk_twpll>, <&clk_twpll>,
+			 <&clk_twpll>, <&clk_twpll>, <&clk_mpll1>;
+		clock-output-names = "clk_big_mcu";
+	};
+
+	clk_lit_mcu: clk at 40880020 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40880020 0 0x4>;
+		sprd,mux-msk = <0xf>;
+		sprd,div-msk = <0x70>;
+		clocks = <&ext_26m>, <&clk_twpll_512m>, <&clk_twpll_768m>,
+			<&clk_ltepll0>, <&clk_twpll>, <&clk_twpll>,
+			<&clk_twpll>, <&clk_twpll>, <&clk_mpll0>;
+		clock-output-names = "clk_lit_mcu";
+	};
+
+	/* gpu domain */
+	clk_gpu: clk at 60200020 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x60200020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0xf00>;
+		clocks = <&clk_twpll_512m>, <&clk_twpll_768m>, <&clk_gpll>;
+		clock-output-names = "clk_gpu";
+	};
+
+	/* vsp domain */
+	clk_ahb_vsp: clk at 61000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_vsp";
+	};
+
+	clk_vsp: clk at 61000024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000024 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_vsp";
+	};
+
+	clk_vsp_enc: clk at 61000028 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_vsp_enc";
+	};
+
+	clk_vpp: clk at 6100002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6100002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_96m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_vpp";
+	};
+
+	clk_vsp_26m: clk at 61000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x61000030 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_vsp_26m";
+	};
+
+	clk_ahb_disp: clk at 63000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_disp";
+	};
+
+	clk_gsp0: clk at 63000024 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000024 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_512m>, <&clk_l0_614m4>;
+		clock-output-names = "clk_gsp0";
+	};
+
+	clk_gsp1: clk at 63000028 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_512m>, <&clk_l0_614m4>;
+		clock-output-names = "clk_gsp1";
+	};
+
+	clk_dispc0: clk at 6300002c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_192m>, <&clk_twpll_256m>,
+			 <&clk_twpll_384m>, <&clk_twpll_512m>;
+		clock-output-names = "clk_dispc0";
+	};
+
+	clk_dispc0_dbi: clk at 63000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc0_dbi";
+	};
+
+	clk_dispc0_dpi: clk at 63000034 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000034 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc0_dpi";
+	};
+
+	clk_dispc1: clk at 63000038 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000038 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_192m>, <&clk_twpll_256m>,
+			 <&clk_twpll_384m>, <&clk_twpll_512m>;
+		clock-output-names = "clk_dispc1";
+	};
+
+	clk_dispc1_dbi: clk at 6300003c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300003c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc1_dbi";
+	};
+
+	clk_dispc1_dpi: clk at 63000040 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000040 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x300>;
+		clocks = <&clk_twpll_128m>, <&clk_twpll_153m6>,
+			 <&clk_twpll_192m>, <&clk_twpll_256m>;
+		clock-output-names = "clk_dispc1_dpi";
+	};
+
+	clk_dphy0: clk at 6300004c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6300004c 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy0";
+	};
+
+	clk_dphy1: clk at 63000058 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x63000058 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_dphy1";
+	};
+
+	clk_ahb_cam: clk at 62000020 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000020 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_96m>, <&clk_twpll_128m>,
+			 <&clk_twpll_153m6>;
+		clock-output-names = "clk_ahb_cam";
+	};
+
+	clk_sensor0: clk at 62000024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000024 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor0";
+	};
+
+	clk_sensor1: clk at 62000028 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000028 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor1";
+	};
+
+	clk_sensor2: clk at 6200002c {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200002c 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>,
+			 <&clk_twpll_96m>;
+		clock-output-names = "clk_sensor2";
+	};
+
+	clk_dcam0: clk at 62000030 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000030 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_153m6>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>;
+		clock-output-names = "clk_dcam0";
+	};
+
+	clk_dcam1: clk at 62000034 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000034 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_dcam1";
+	};
+
+	clk_dcam0_if: clk at 62000038 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000038 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_dcam0_if";
+	};
+
+	clk_isp0: clk at 6200003c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200003c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp0";
+	};
+
+	clk_isp1: clk at 62000040 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000040 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp1";
+	};
+
+	clk_jpg0: clk at 62000044 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000044 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_jpg0";
+	};
+
+	clk_jpg1: clk at 62000048 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000048 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>;
+		clock-output-names = "clk_jpg1";
+	};
+
+	clk_mipi_csi0_gate: clk at 6200004c {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x6200004c 0 0x4>;
+		clock-indices = <16>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "mipi_csi0_eb";
+	};
+
+	clk_mipi_csi1_gate: clk at 62000050 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62000050 0 0x4>;
+		clock-indices = <16>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "mipi_csi1_eb";
+	};
+
+	clk_cpp: clk at 6200005c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200005c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_cpp";
+	};
+
+	clk_isp_mclk: clk at 62000060 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000060 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp_mclk";
+	};
+
+	clk_isp_pclk: clk at 62000064 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000064 0 0x4>;
+		sprd,mux-msk = <0x3>;
+		clocks = <&ext_26m>, <&clk_twpll_48m>, <&clk_twpll_76m8>;
+		clock-output-names = "clk_isp_pclk";
+	};
+
+	clk_isp_iclk: clk at 62000068 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000068 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_256m>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>,
+			 <&clk_twpll_512m>;
+		clock-output-names = "clk_isp_iclk";
+	};
+
+	clk_isp_lclk: clk at 6200006c {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x6200006c 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp_lclk";
+	};
+
+	clk_isp2: clk at 62000070 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000070 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_128m>,
+			 <&clk_twpll_256m>, <&clk_twpll_307m2>,
+			 <&clk_twpll_384m>;
+		clock-output-names = "clk_isp2";
+	};
+
+	clk_isp2dcam: clk at 62000074 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000074 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_twpll_76m8>, <&clk_twpll_153m6>,
+			 <&clk_twpll_307m2>, <&clk_twpll_384m>;
+		clock-output-names = "clk_isp2dcam";
+	};
+
+	clk_cam_26m: clk at 62000078 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x62000078 0 0x4>;
+		sprd,mux-msk = <0x1>;
+		clocks = <&ext_26m>;
+		clock-output-names = "clk_cam_26m";
+	};
+
+	clk_ap_ahb_gates: clk at 20210000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x20210000 0 0x3000>;
+		clock-indices = <2>, <3>, <4>, <5>,
+				<7>, <8>, <9>, <10>,
+				<12>, <13>, <22>,
+				<23>, <24>, <25>;
+		clocks = <&clk_ap_axi>;
+		clock-output-names = "usb3_eb", "usb3_suspend_eb",
+				     "usb3_ref_eb", "dma_eb",
+				     "sdio0_eb", "sdio1_eb",
+				     "sdio2_eb", "emmc_eb",
+				     "rom_eb", "busmon_eb",
+				     "cc63s_eb", "cc63p_eb",
+				     "ce0_eb", "ce1_eb";
+	};
+
+	clk_aon_apb_gates0: clk at 402e0000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e0000 0 0x3000>;
+		clocks = <&clk_aon_apb>;
+		clock-output-names = "avs_ca53_lit_eb", "avs_ca53_big_eb",
+				     "ap_intc5_eb", "gpio_eb",
+				     "pwm0_eb", "pwm1_eb",
+				     "pwm2_eb", "pwm3_eb",
+				     "kpd_eb", "aon_syst_eb",
+				     "ap_syst_eb", "aon_tmr_eb",
+				     "ap_tmr0_eb", "efuse_eb",
+				     "eic_eb", "pub1_reg_eb",
+				     "adi_eb", "ap_intc0_eb",
+				     "ap_intc1_eb", "ap_intc2_eb",
+				     "ap_intc3_eb", "ap_intc4_eb",
+				     "splk_eb", "mspi_eb",
+				     "pub0_reg_eb", "pin_eb",
+				     "aon_ckg_eb", "gpu_eb",
+				     "apcpu_ts0_eb", "apcpu_ts1_eb",
+				     "dap_eb", "i2c_eb";
+	};
+
+	clk_aon_apb_gates1: clk at 402e0004 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402e0004 0 0x3000>;
+		clocks = <&clk_aon_apb>;
+		clock-output-names = "pmu_eb", "thm_eb",
+				     "aux0_eb", "aux1_eb",
+				     "aux2_eb", "probe_eb",
+				     "gpu0_avs_eb", "gpu1_avs_eb",
+				     "apcpu_wdg_eb", "ap_tmr1_eb",
+				     "ap_tmr2_eb", "disp_emc_eb",
+				     "zip_emc_eb", "gsp_emc_eb",
+				     "osc_aon_eb", "lvds_trx_eb",
+				     "lvds_tcxo_eb", "mdar_eb",
+				     "rtc4m0_cal_eb", "rct100m_cal_eb",
+				     "djtag_eb", "mbox_eb",
+				     "aon_dma_eb", "dbg_emc_eb",
+				     "lvds_pll_div_en", "def_eb",
+				     "aon_apb_gate1_rsv0", "orp_jtag_eb",
+				     "vsp_eb", "cam_eb",
+				     "disp_eb", "dbg_axi_if_eb";
+	};
+
+	clk_agcp_ahb_gates: clk at 415e0000 {
+		compatible = "sprd,sc100-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x415e0000 0 0x300>;
+		clock-indices = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>,
+				<10>, <11>,
+				<12>, <13>, <14>, <15>,
+				<16>, <17>, <18>, <19>,
+				<20>;
+		clock-output-names = "agcp_iis0_eb", "agcp_iis1_eb",
+				     "agcp_iis2_eb", "agcp_iis3_eb",
+				     "agcp_uart_eb", "agcp_dmacp_eb",
+				     "agcp_dmaap_eb", "agcp_arc48k_eb",
+				     "agcp_src44p1k_eb", "agcp_mcdt_eb",
+				     "agcp_vbcifd_eb", "agcp_vbc_eb",
+				     "agcp_spinlock_eb", "agcp_icu_eb",
+				     "agcp_ap_ashb_eb", "agcp_cp_ashb_eb",
+				     "agcp_aud_eb", "agcp_audif_eb";
+	};
+
+	clk_ahb_vsp_gates: clk at 61100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x61100000 0 0x3000>;
+		clocks = <&clk_ahb_vsp>;
+		clock-output-names = "vsp_dec_eb", "vsp_ckg_eb",
+				     "vsp_mmu_eb", "vsp_enc_eb",
+				     "vpp_eb", "vsp_26m_eb";
+	};
+
+	clk_vsp_axi_gates: clk at 61100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x61100008 0 0x4>;
+		clock-indices = <0>, <1>, <2>,
+				<8>, <9>, <10>;
+		clocks = <&clk_ahb_vsp>;
+		clock-output-names = "vsp_axi_gate", "vsp_enc_gate",
+				     "vpp_axi_gate", "vsp_bm_gate",
+				     "vsp_enc_bm_gate", "vpp_bm_gate";
+	};
+
+	clk_ahb_cam_gates: clk at 62100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100000 0 0x3000>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "dcam0_eb", "dcam1_eb",
+				     "isp0_eb", "csi0_eb",
+				     "csi1_eb", "jpg0_eb",
+				     "jpg1_eb", "cam_ckg_eb",
+				     "cam_mmu_eb", "isp1_eb",
+				     "cpp_eb", "mmu_pf_eb",
+				     "isp2_eb", "dcam2isp_if_eb",
+				     "isp2dcam_if_eb", "isp_lclk_eb",
+				     "isp_iclk_eb", "isp_mclk_eb",
+				     "isp_pclk_eb", "isp_isp2dcam_eb",
+				     "dcam0_if_eb", "clk26m_if_eb";
+	};
+
+	clk_cam_axi_gates: clk at 62100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100008 0 0x4>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "cphy0_gate", "mipi_csi0_gate",
+				     "cphy1_gate", "mipi_csi1",
+				     "dcam0_axi_gate", "dcam1_axi_gate",
+				     "sensor0_gate", "sensor1_gate",
+				     "jpg0_axi_gate", "gpg1_axi_gate",
+				     "isp0_axi_gate", "isp1_axi_gate",
+				     "isp2_axi_gate", "cpp_axi_gate",
+				     "d0_if_axi_gate", "d2i_if_axi_gate",
+				     "i2d_if_axi_gate", "spare_axi_gate",
+				     "sensor2_gate";
+	};
+
+	clk_cam_module_gates: clk at 62100028 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x62100028 0 0x3000>;
+		clocks = <&clk_ahb_cam>;
+		clock-output-names = "d0if_in_d_en", "d1if_in_d_en",
+				     "d0if_in_d2i_en", "d1if_in_d2i_en",
+				     "ia_in_d2i_en", "ib_in_d2i_en",
+				     "ic_in_d2i_en", "ia_in_i_en",
+				     "ib_in_i_en", "ic_in_i_en";
+	};
+
+	clk_ahb_disp_gates: clk at 63100000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x63100000 0 0x3000>;
+		clock-indices = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>, <7>,
+				<8>, <9>, <10>,
+				<13>, <14>, <15>,
+				<16>;
+		clocks = <&clk_ahb_disp>;
+		clock-output-names = "dispc0_eb", "dispc1_eb",
+				     "dispc_mmu_eb", "gsp0_eb",
+				     "gsp1_eb", "gsp0_mmu_eb",
+				     "gsp1_mmu_eb", "dsi0_eb",
+				     "dsi1_eb", "disp_ckg_eb",
+				     "disp_gpu_eb", "gpu_mtx_eb",
+				     "gsp_mtx_eb", "tmc_mtx_eb",
+				     "dispc_mtx_eb";
+	};
+
+	clk_disp_axi_gates: clk at 63100008 {
+		compatible = "sprd,gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x63100008 0 0x4>;
+		clocks = <&clk_ahb_disp>;
+		clock-output-names = "dphy0_gate", "dphy1_gate",
+				     "gsp0_a_gate", "gsp1_a_gate",
+				     "gsp0_f_gate", "gsp1_f_gate",
+				     "d_mtx_f_gate", "d_mtx_a_gate",
+				     "d_noc_f_gate", "d_noc_a_gate",
+				     "gsp_mtx_f_gate", "gsp_mtx_a_gate",
+				     "gsp_noc_f_gate", "gsp_noc_a_gate",
+				     "dispm0idle_gate", "gspm0idle_gate";
+	};
+
+	clk_ap_apb_gates: clk at 70b00000 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x70b00000 0 0x3000>;
+		clocks = <&clk_ap_apb>;
+		clock-output-names = "sim0_eb", "iis0_eb",
+				     "iis1_eb", "iis2_eb",
+				     "iis3_eb", "spi0_eb",
+				     "spi1_eb", "spi2_eb",
+				     "i2c0_eb", "i2c1_eb",
+				     "i2c2_eb", "i2c3_eb",
+				     "i2c4_eb", "i2c5_eb",
+				     "uart0_eb", "uart1_eb",
+				     "uart2_eb", "uart3_eb",
+				     "uart4_eb", "ap_ckg_eb",
+				     "spi3_eb";
+	};
+};
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index 7b7d8ce..97794fe 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -8,6 +8,7 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "whale2.dtsi"
+#include "sc9860-clocks.dtsi"
 
 / {
 	cpus {
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi
index cd5a71f..8d1f8aa 100644
--- a/arch/arm64/boot/dts/sprd/whale2.dtsi
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -79,11 +79,4 @@
 		};
 
 	};
-
-	ext_26m: ext-26m {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <26000000>;
-		clock-output-names = "ext_26m";
-	};
 };
-- 
2.7.4

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

* [PATCH 2/3] Documentation: add sprd clock bindings
  2017-05-15  8:34 ` Chunyan Zhang
  (?)
@ 2017-05-15  8:35   ` Chunyan Zhang
  -1 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

This patch adds a new directory under the 'clock' for Spreadtrum platform,
also bindings which document compatible strings and properties used for
devicetree node of clocks on Spreadtrum SoCs.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
 .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
 .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
 .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
 .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
 5 files changed, 165 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
new file mode 100644
index 0000000..476e315
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
@@ -0,0 +1,17 @@
+Spreadtrum adjustable pll clock driver
+
+Required properties:
+
+- compatible : must be one of:
+	"sprd,sc9836-adjustable-pll-clock"
+	"sprd,sc9860-adjustable-pll-clock"
+
+Example:
+	clk_mpll0: clk@40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
new file mode 100644
index 0000000..a476eb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
@@ -0,0 +1,28 @@
+Spreadtrum composite clock driver.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible:	should be "sprd,composite-clock"
+
+- sprd,mux-msk:	arbitrary bitmask for selecting clock input
+
+- sprd,div-msk:	arbitrary bitmask for programming the divider,
+		denominator of divider is the value consisted
+		of these bits plus 1
+
+Example:
+
+	clk_sensor: clk@60e00024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x60e00024 0 0x4>;
+		clocks = <&ext_26m>, <&clk_twpll_48m_def>,
+			 <&clk_twpll_76m8_def>, <&clk_twpll_96m_def>;
+		clock-output-names = "clk_sensor";
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
new file mode 100644
index 0000000..0bfc0ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
@@ -0,0 +1,24 @@
+Spreadtrum divider clock driver which only supports simple indexed divider
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : should be "sprd,divider-clock"
+
+- sprd,div-msk:	arbitrary bitmask for programming the divider,
+		denominator of divider is the value consisted
+		of these bits plus 1.
+
+Example:
+
+	clk_sdio0_1x: clk@402d032c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d032c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio0_2x>;
+		clock-output-names = "clk_sdio0_1x";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
new file mode 100644
index 0000000..f23ecb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
@@ -0,0 +1,73 @@
+Spreadtrum gate clock driver
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Spreadtrum's SoCs often use one register to control more than one gate clocks.
+Clock consumers can use index to get the correct gate clock.
+
+In Spreadtrum platform, some of gate clocks have three registers, respectively
+used for controlling, setting and clearing gate clock, the addresses of
+these three registers generally are <start>, <start + offset>, and
+<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
+size of gate clocks is either 0x3000 or 0x300. While for some historical issue
+there also are some clocks which don't have independent set/clear registers.
+Please see bellow for more specific information.
+
+Required properties:
+
+- compatible:	should be one of the following:
+		"sprd,sc1000-gates-clock"
+		- offset of the registers for setting gate is 0x1000
+
+		"sprd,sc100-gates-clock"
+		- offset of the registers for setting gate is 0x100
+
+		"sprd,gates-clock"
+		- for clocks without independent set/clear registers
+
+- reg:	the first cell represents the address of this clock gate controller
+	register, the second cell implies how is the offset of set/clear
+	registers of this clock gate, like addressed in the head of this
+	file
+
+optional properties:
+
+- clock-indices:	If the identifying number for the clocks in the node
+			is not linear from zero, this property is necessary
+
+Example:
+
+	clk_mpll_gates: clk@402b00b0 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b0 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
+	};
+
+Below are two examples of how consumers use the gate clock.
+The 'clk_mpll0' uses index 2 of 'clk_mpll_gates' and 'clk_mpll1'
+uses index 18.
+
+Examples:
+
+	clk_mpll0: clk@40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
+
+	clk_mpll1: clk@4040002c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040002c 0 0x4>,
+		      <0 0x40400030 0 0x4>;
+		clocks = <&clk_mpll_gates 18>;
+		clock-output-names = "clk_mpll1";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
new file mode 100644
index 0000000..b752977
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
@@ -0,0 +1,23 @@
+Spreadtrum multiplexed clock driver
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : should be "sprd,muxed-clock"
+
+- sprd,mux-msk:	arbitrary bitmask for selecting clock input
+
+Example:
+
+	clk_adi: clk@402d0234 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0234 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&clk_rco_25m>,
+			 <&clk_twpll_38m4>, <&clk_twpll_51m2>;
+		clock-output-names = "clk_adi";
+	};
-- 
2.7.4

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

* [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-15  8:35   ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

This patch adds a new directory under the 'clock' for Spreadtrum platform,
also bindings which document compatible strings and properties used for
devicetree node of clocks on Spreadtrum SoCs.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
 .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
 .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
 .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
 .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
 5 files changed, 165 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
new file mode 100644
index 0000000..476e315
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
@@ -0,0 +1,17 @@
+Spreadtrum adjustable pll clock driver
+
+Required properties:
+
+- compatible : must be one of:
+	"sprd,sc9836-adjustable-pll-clock"
+	"sprd,sc9860-adjustable-pll-clock"
+
+Example:
+	clk_mpll0: clk@40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
new file mode 100644
index 0000000..a476eb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
@@ -0,0 +1,28 @@
+Spreadtrum composite clock driver.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible:	should be "sprd,composite-clock"
+
+- sprd,mux-msk:	arbitrary bitmask for selecting clock input
+
+- sprd,div-msk:	arbitrary bitmask for programming the divider,
+		denominator of divider is the value consisted
+		of these bits plus 1
+
+Example:
+
+	clk_sensor: clk@60e00024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x60e00024 0 0x4>;
+		clocks = <&ext_26m>, <&clk_twpll_48m_def>,
+			 <&clk_twpll_76m8_def>, <&clk_twpll_96m_def>;
+		clock-output-names = "clk_sensor";
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
new file mode 100644
index 0000000..0bfc0ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
@@ -0,0 +1,24 @@
+Spreadtrum divider clock driver which only supports simple indexed divider
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : should be "sprd,divider-clock"
+
+- sprd,div-msk:	arbitrary bitmask for programming the divider,
+		denominator of divider is the value consisted
+		of these bits plus 1.
+
+Example:
+
+	clk_sdio0_1x: clk@402d032c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d032c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio0_2x>;
+		clock-output-names = "clk_sdio0_1x";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
new file mode 100644
index 0000000..f23ecb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
@@ -0,0 +1,73 @@
+Spreadtrum gate clock driver
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Spreadtrum's SoCs often use one register to control more than one gate clocks.
+Clock consumers can use index to get the correct gate clock.
+
+In Spreadtrum platform, some of gate clocks have three registers, respectively
+used for controlling, setting and clearing gate clock, the addresses of
+these three registers generally are <start>, <start + offset>, and
+<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
+size of gate clocks is either 0x3000 or 0x300. While for some historical issue
+there also are some clocks which don't have independent set/clear registers.
+Please see bellow for more specific information.
+
+Required properties:
+
+- compatible:	should be one of the following:
+		"sprd,sc1000-gates-clock"
+		- offset of the registers for setting gate is 0x1000
+
+		"sprd,sc100-gates-clock"
+		- offset of the registers for setting gate is 0x100
+
+		"sprd,gates-clock"
+		- for clocks without independent set/clear registers
+
+- reg:	the first cell represents the address of this clock gate controller
+	register, the second cell implies how is the offset of set/clear
+	registers of this clock gate, like addressed in the head of this
+	file
+
+optional properties:
+
+- clock-indices:	If the identifying number for the clocks in the node
+			is not linear from zero, this property is necessary
+
+Example:
+
+	clk_mpll_gates: clk@402b00b0 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b0 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
+	};
+
+Below are two examples of how consumers use the gate clock.
+The 'clk_mpll0' uses index 2 of 'clk_mpll_gates' and 'clk_mpll1'
+uses index 18.
+
+Examples:
+
+	clk_mpll0: clk@40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
+
+	clk_mpll1: clk@4040002c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040002c 0 0x4>,
+		      <0 0x40400030 0 0x4>;
+		clocks = <&clk_mpll_gates 18>;
+		clock-output-names = "clk_mpll1";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
new file mode 100644
index 0000000..b752977
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
@@ -0,0 +1,23 @@
+Spreadtrum multiplexed clock driver
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : should be "sprd,muxed-clock"
+
+- sprd,mux-msk:	arbitrary bitmask for selecting clock input
+
+Example:
+
+	clk_adi: clk@402d0234 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0234 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&clk_rco_25m>,
+			 <&clk_twpll_38m4>, <&clk_twpll_51m2>;
+		clock-output-names = "clk_adi";
+	};
-- 
2.7.4

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

* [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-15  8:35   ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds a new directory under the 'clock' for Spreadtrum platform,
also bindings which document compatible strings and properties used for
devicetree node of clocks on Spreadtrum SoCs.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
 .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
 .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
 .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
 .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
 5 files changed, 165 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
 create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
new file mode 100644
index 0000000..476e315
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
@@ -0,0 +1,17 @@
+Spreadtrum adjustable pll clock driver
+
+Required properties:
+
+- compatible : must be one of:
+	"sprd,sc9836-adjustable-pll-clock"
+	"sprd,sc9860-adjustable-pll-clock"
+
+Example:
+	clk_mpll0: clk at 40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
new file mode 100644
index 0000000..a476eb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
@@ -0,0 +1,28 @@
+Spreadtrum composite clock driver.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible:	should be "sprd,composite-clock"
+
+- sprd,mux-msk:	arbitrary bitmask for selecting clock input
+
+- sprd,div-msk:	arbitrary bitmask for programming the divider,
+		denominator of divider is the value consisted
+		of these bits plus 1
+
+Example:
+
+	clk_sensor: clk at 60e00024 {
+		compatible = "sprd,composite-clock";
+		#clock-cells = <0>;
+		reg = <0 0x60e00024 0 0x4>;
+		clocks = <&ext_26m>, <&clk_twpll_48m_def>,
+			 <&clk_twpll_76m8_def>, <&clk_twpll_96m_def>;
+		clock-output-names = "clk_sensor";
+		sprd,mux-msk = <0x3>;
+		sprd,div-msk = <0x700>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
new file mode 100644
index 0000000..0bfc0ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
@@ -0,0 +1,24 @@
+Spreadtrum divider clock driver which only supports simple indexed divider
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : should be "sprd,divider-clock"
+
+- sprd,div-msk:	arbitrary bitmask for programming the divider,
+		denominator of divider is the value consisted
+		of these bits plus 1.
+
+Example:
+
+	clk_sdio0_1x: clk at 402d032c {
+		compatible = "sprd,divider-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d032c 0 0x4>;
+		sprd,div-msk = <0x100>;
+		clocks = <&clk_sdio0_2x>;
+		clock-output-names = "clk_sdio0_1x";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
new file mode 100644
index 0000000..f23ecb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
@@ -0,0 +1,73 @@
+Spreadtrum gate clock driver
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Spreadtrum's SoCs often use one register to control more than one gate clocks.
+Clock consumers can use index to get the correct gate clock.
+
+In Spreadtrum platform, some of gate clocks have three registers, respectively
+used for controlling, setting and clearing gate clock, the addresses of
+these three registers generally are <start>, <start + offset>, and
+<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
+size of gate clocks is either 0x3000 or 0x300. While for some historical issue
+there also are some clocks which don't have independent set/clear registers.
+Please see bellow for more specific information.
+
+Required properties:
+
+- compatible:	should be one of the following:
+		"sprd,sc1000-gates-clock"
+		- offset of the registers for setting gate is 0x1000
+
+		"sprd,sc100-gates-clock"
+		- offset of the registers for setting gate is 0x100
+
+		"sprd,gates-clock"
+		- for clocks without independent set/clear registers
+
+- reg:	the first cell represents the address of this clock gate controller
+	register, the second cell implies how is the offset of set/clear
+	registers of this clock gate, like addressed in the head of this
+	file
+
+optional properties:
+
+- clock-indices:	If the identifying number for the clocks in the node
+			is not linear from zero, this property is necessary
+
+Example:
+
+	clk_mpll_gates: clk at 402b00b0 {
+		compatible = "sprd,sc1000-gates-clock";
+		#clock-cells = <1>;
+		reg = <0 0x402b00b0 0 0x3000>;
+		clocks = <&ext_26m>;
+		clock-indices = <2>, <18>;
+		clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
+	};
+
+Below are two examples of how consumers use the gate clock.
+The 'clk_mpll0' uses index 2 of 'clk_mpll_gates' and 'clk_mpll1'
+uses index 18.
+
+Examples:
+
+	clk_mpll0: clk at 40400024 {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x40400024 0 0x4>,
+		      <0 0x40400028 0 0x4>;
+		clocks = <&clk_mpll_gates 2>;
+		clock-output-names = "clk_mpll0";
+	};
+
+	clk_mpll1: clk at 4040002c {
+		compatible = "sprd,sc9860-adjustable-pll-clock";
+		#clock-cells = <0>;
+		reg = <0 0x4040002c 0 0x4>,
+		      <0 0x40400030 0 0x4>;
+		clocks = <&clk_mpll_gates 18>;
+		clock-output-names = "clk_mpll1";
+	};
diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
new file mode 100644
index 0000000..b752977
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
@@ -0,0 +1,23 @@
+Spreadtrum multiplexed clock driver
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : should be "sprd,muxed-clock"
+
+- sprd,mux-msk:	arbitrary bitmask for selecting clock input
+
+Example:
+
+	clk_adi: clk at 402d0234 {
+		compatible = "sprd,muxed-clock";
+		#clock-cells = <0>;
+		reg = <0 0x402d0234 0 0x4>;
+		sprd,mux-msk = <0x7>;
+		clocks = <&clk_rco_4m>, <&ext_26m>, <&clk_rco_25m>,
+			 <&clk_twpll_38m4>, <&clk_twpll_51m2>;
+		clock-output-names = "clk_adi";
+	};
-- 
2.7.4

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

* [PATCH 3/3] clk: Add common clock driver for Spreadtrum SoCs
  2017-05-15  8:34 ` Chunyan Zhang
  (?)
@ 2017-05-15  8:35   ` Chunyan Zhang
  -1 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

From: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>

This patch adds an initial common clock driver comprising clock gate,
divider, multiplexer, composite, pll, these drivers are used on almost
all Spreadtrum platforms so far.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/Makefile         |   1 +
 drivers/clk/sprd/Makefile    |   3 +
 drivers/clk/sprd/clk-gates.c | 366 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/composite.c | 109 ++++++++++++
 drivers/clk/sprd/divider.c   |  79 +++++++++
 drivers/clk/sprd/mux.c       |  77 +++++++++
 drivers/clk/sprd/pll.c       | 359 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/pll.h       |  73 ++++++++
 drivers/clk/sprd/pll_cfg.h   | 390 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1457 insertions(+)
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/clk-gates.c
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/divider.c
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/pll_cfg.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c19983a..1d62721 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 0000000..a783c27
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+ifneq ($(CONFIG_OF),)
+obj-y					+= divider.o mux.o composite.o pll.o clk-gates.o
+endif
diff --git a/drivers/clk/sprd/clk-gates.c b/drivers/clk/sprd/clk-gates.c
new file mode 100644
index 0000000..8d4ccb9
--- /dev/null
+++ b/drivers/clk/sprd/clk-gates.c
@@ -0,0 +1,366 @@
+/*
+ * Spreadtrum clock set/clear gate driver
+ *
+ * Copyright (C) 2015~2017 spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+
+DEFINE_SPINLOCK(gate_lock);
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+#define CLK_GATE_HWSPINLOCK		BIT(7)
+#define GLB_CLK_HWSPINLOCK_TIMEOUT	5000
+
+static struct hwspinlock		*glb_clk_hw_lock;
+
+static void sprd_clk_lock(struct clk_gate *gate,
+			unsigned long flags)
+{
+	if (gate->lock)
+		spin_lock_irqsave(gate->lock, flags);
+	else
+		__acquire(gate->lock);
+}
+
+static void sprd_clk_unlock(struct clk_gate *gate,
+			unsigned long flags)
+{
+	if (gate->lock)
+		spin_unlock_irqrestore(gate->lock, flags);
+	else
+		__release(gate->lock);
+}
+
+static void sprd_clk_hw_lock(struct clk_gate *gate,
+				unsigned long *flags)
+{
+	int ret = 0;
+
+	if (glb_clk_hw_lock && (gate->flags & CLK_GATE_HWSPINLOCK)) {
+		ret = hwspin_lock_timeout_irqsave(glb_clk_hw_lock,
+					  GLB_CLK_HWSPINLOCK_TIMEOUT,
+					  flags);
+		if (ret)
+			pr_err("glb_clk:%s lock the hwlock failed.\n",
+			       __clk_get_name(gate->hw.clk));
+		return;
+	}
+
+	sprd_clk_lock(gate, *flags);
+}
+
+static void sprd_clk_hw_unlock(struct clk_gate *gate,
+				unsigned long *flags)
+{
+	if (glb_clk_hw_lock && (gate->flags & CLK_GATE_HWSPINLOCK)) {
+		hwspin_unlock_irqrestore(glb_clk_hw_lock, flags);
+		return;
+	}
+
+	sprd_clk_unlock(gate, *flags);
+}
+
+static void sprd_clk_gate_endisable(struct clk_hw *hw, int enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned long flags = 0;
+	u32 reg;
+
+	set ^= enable;
+
+	sprd_clk_hw_lock(gate, &flags);
+
+	reg = clk_readl(gate->reg);
+
+	if (set)
+		reg |= BIT(gate->bit_idx);
+	else
+		reg &= ~BIT(gate->bit_idx);
+
+	clk_writel(reg, gate->reg);
+
+	sprd_clk_hw_unlock(gate, &flags);
+}
+
+static int sprd_clk_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_gate_endisable(hw, 1);
+
+	return 0;
+}
+
+static void sprd_clk_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_gate_endisable(hw, 0);
+}
+
+static int sprd_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	u32 reg;
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	reg = clk_readl(gate->reg);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		reg ^= BIT(gate->bit_idx);
+
+	reg &= BIT(gate->bit_idx);
+
+	return reg ? 1 : 0;
+}
+
+const struct clk_ops sprd_clk_gate_ops = {
+	.enable = sprd_clk_gate_enable,
+	.disable = sprd_clk_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+static void sprd_clk_sc_gate_endisable(struct clk_hw *hw, int enable,
+				       unsigned int offset)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned long flags = 0;
+	void __iomem *reg;
+
+	set ^= enable;
+
+	sprd_clk_lock(gate, flags);
+
+	/*
+	 * Each gate clock has three registers:
+	 * gate->reg			- base register
+	 * gate->reg + offset		- set register
+	 * gate->reg + 2 * offset	- clear register
+	 */
+	reg = set ? gate->reg + offset : gate->reg + 2 * offset;
+	clk_writel(BIT(gate->bit_idx), reg);
+
+	sprd_clk_unlock(gate, flags);
+
+}
+
+static int sprd_clk_sc100_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 1, 0x100);
+
+	return 0;
+}
+
+static void sprd_clk_sc100_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 0, 0x100);
+}
+
+static int sprd_clk_sc1000_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 1, 0x1000);
+
+	return 0;
+}
+
+static void sprd_clk_sc1000_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 0, 0x1000);
+}
+
+const struct clk_ops sprd_clk_sc100_gate_ops = {
+	.enable = sprd_clk_sc100_gate_enable,
+	.disable = sprd_clk_sc100_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+const struct clk_ops sprd_clk_sc1000_gate_ops = {
+	.enable = sprd_clk_sc1000_gate_enable,
+	.disable = sprd_clk_sc1000_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+static struct clk *sprd_clk_register_gate(struct device *dev,
+		const char *name, const char *parent_name,
+		unsigned long flags, void __iomem *reg,
+		u8 bit_idx, u8 clk_gate_flags,
+		spinlock_t *lock, const struct clk_ops *ops)
+{
+	struct clk_gate *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+	gate->lock = lock;
+	gate->hw.init = &init;
+
+	clk = clk_register(dev, &gate->hw);
+
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
+
+static void __init sprd_clk_gates_setup(struct device_node *node,
+					   const struct clk_ops *ops)
+{
+	const char *clk_name = NULL;
+	void __iomem *reg;
+	const char *parent_name;
+	unsigned long flags = CLK_IGNORE_UNUSED;
+	u8 gate_flags = 0;
+	u32 index;
+	int number, i = 0;
+	struct resource res;
+	struct clk_onecell_data *clk_data;
+	struct property *prop;
+	const __be32 *p;
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_err("%s: no DT registers found for %s\n",
+		       __func__, node->full_name);
+		return;
+	}
+
+	/*
+	 * bit[1:0] represents the gate flags, but bit[1] is not used
+	 * for the time being.
+	 */
+	if (res.start & 0x3) {
+		res.start &= ~0x3;
+		gate_flags |= CLK_GATE_SET_TO_DISABLE;
+	}
+	reg = ioremap(res.start, resource_size(&res));
+	if (!reg) {
+		pr_err("%s: gates clock[%s] ioremap failed!\n",
+		       __func__, node->full_name);
+		return;
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+	if (!clk_data)
+		goto iounmap_reg;
+
+	number = of_property_count_u32_elems(node, "clock-indices");
+	if (number > 0) {
+		of_property_read_u32_index(node, "clock-indices",
+					   number - 1, &number);
+		number += 1;
+	} else {
+		number = of_property_count_strings(node, "clock-output-names");
+	}
+
+	clk_data->clks = kcalloc(number, sizeof(struct clk *),
+				 GFP_KERNEL);
+	if (!clk_data->clks)
+		goto kfree_clk_data;
+
+	/*
+	 * If the identifying number for the clocks in the node is not
+	 * linear from zero, then we use clock-indices mapping
+	 * identifiers into the clock-output-names array in DT.
+	 */
+	if (of_property_count_u32_elems(node, "clock-indices") > 0) {
+		of_property_for_each_u32(node, "clock-indices",
+					 prop, p, index) {
+			of_property_read_string_index(node,
+						      "clock-output-names",
+						      i++, &clk_name);
+
+			clk_data->clks[index] = sprd_clk_register_gate(NULL,
+						clk_name, parent_name, flags,
+						reg, index, gate_flags,
+						&gate_lock, ops);
+			WARN_ON(IS_ERR(clk_data->clks[index]));
+
+			clk_register_clkdev(clk_data->clks[index], clk_name,
+					    NULL);
+		}
+	} else {
+		of_property_for_each_string(node, "clock-output-names",
+					    prop, clk_name) {
+			clk_data->clks[i] = sprd_clk_register_gate(NULL,
+						clk_name, parent_name, flags,
+						reg, i,	gate_flags,
+						&gate_lock, ops);
+			WARN_ON(IS_ERR(clk_data->clks[i]));
+
+			clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
+			i++;
+		}
+	}
+
+	clk_data->clk_num = number;
+	if (number == 1)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk_data);
+	else
+		of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	return;
+
+kfree_clk_data:
+	kfree(clk_data);
+
+iounmap_reg:
+	iounmap(reg);
+}
+
+static void __init sprd_sc100_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_sc100_gate_ops);
+}
+
+static void __init sprd_sc1000_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_sc1000_gate_ops);
+}
+
+static void __init sprd_trad_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_gate_ops);
+}
+
+CLK_OF_DECLARE(gates_clock, "sprd,gates-clock",
+		sprd_trad_clk_gates_setup);
+CLK_OF_DECLARE(sc100_gates_clock, "sprd,sc100-gates-clock",
+	       sprd_sc100_clk_gates_setup);
+CLK_OF_DECLARE(sc1000_gates_clock, "sprd,sc1000-gates-clock",
+	       sprd_sc1000_clk_gates_setup);
+
+#ifdef CONFIG_SPRD_HWSPINLOCK
+static int __init sprd_clk_hwspinlock_init(void)
+{
+	/*
+	 * glb_clk belongs to the global registers, so it can use the
+	 * same hwspinlock
+	 */
+	glb_clk_hw_lock = hwspin_lock_get_used(1);
+	if (!glb_clk_hw_lock) {
+		pr_err("%s: Can't get the hardware spinlock.\n", __func__);
+		return -ENXIO;
+	}
+
+	return 0;
+}
+subsys_initcall_sync(sprd_clk_hwspinlock_init);
+#endif
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
new file mode 100644
index 0000000..118565a
--- /dev/null
+++ b/drivers/clk/sprd/composite.c
@@ -0,0 +1,109 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_composite_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	const struct clk_ops *mux_ops = NULL;
+	struct clk_divider *div = NULL;
+	const struct clk_ops *div_ops = NULL;
+	const char *clk_name = node->name;
+	const char **parent_names;
+	unsigned long flags = 0;
+	u32 msk;
+	int num_parents = 0;
+	int i = 0;
+	int index = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (!num_parents) {
+		pr_err("%s: Failed to get %s's parent number!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	while (i < num_parents &&
+			(parent_names[i] =
+			 of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+	if (!mux)
+		goto kfree_parent_names;
+
+	if (!of_property_read_u32(node, "sprd,mux-msk", &msk)) {
+		mux->reg = of_iomap(node, index++);
+		if (!mux->reg)
+			goto kfree_mux;
+
+		mux->shift = __ffs(msk);
+		mux->mask = msk >> (mux->shift);
+		mux_ops = &clk_mux_ops;
+	}
+
+	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+	if (!div)
+		goto iounmap_mux_reg;
+
+	if (!of_property_read_u32(node, "sprd,div-msk", &msk)) {
+		div->reg = of_iomap(node, index);
+		if (!div->reg)
+			div->reg = mux->reg;
+		if (!div->reg)
+			goto iounmap_mux_reg;
+
+		div->shift = __ffs(msk);
+		div->width = fls(msk) - div->shift;
+		div_ops = &clk_divider_ops;
+	}
+
+	flags |= CLK_IGNORE_UNUSED;
+	clk = clk_register_composite(NULL, clk_name, parent_names, num_parents,
+				     &mux->hw, mux_ops, &div->hw, div_ops, NULL,
+				     NULL, flags);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+	if (div->reg)
+		if (!mux || (div->reg != mux->reg))
+			iounmap(div->reg);
+
+	kfree(div);
+
+iounmap_mux_reg:
+	if (mux->reg)
+		iounmap(mux->reg);
+
+kfree_mux:
+	kfree(mux);
+
+kfree_parent_names:
+	pr_err("Failed to register composite clk %s!\n", clk_name);
+	kfree(parent_names);
+}
+
+CLK_OF_DECLARE(composite_clock, "sprd,composite-clock",
+	       sprd_composite_clk_setup);
diff --git a/drivers/clk/sprd/divider.c b/drivers/clk/sprd/divider.c
new file mode 100644
index 0000000..785d6c4
--- /dev/null
+++ b/drivers/clk/sprd/divider.c
@@ -0,0 +1,79 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_divider_clk_setup(struct device_node *node)
+{
+	struct clk *clk, *pclk;
+	struct clk_divider *clk_div;
+	struct clk_composite *clk_composite;
+	const char *clk_name = node->name;
+	const char *parent;
+	void __iomem *reg;
+	u32 msk = 0;
+	u8 shift = 0;
+	u8 width = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	parent = of_clk_get_parent_name(node, 0);
+
+	if (of_property_read_bool(node, "reg")) {
+		reg = of_iomap(node, 0);
+	} else {
+		pclk = __clk_lookup(parent);
+		if (!pclk) {
+			pr_err("%s: clock[%s] has no reg and parent!\n",
+			       __func__, clk_name);
+			return;
+		}
+
+		clk_composite = container_of(__clk_get_hw(pclk),
+					     struct clk_composite, hw);
+
+		clk_div = container_of(clk_composite->rate_hw,
+				       struct clk_divider, hw);
+
+		reg = clk_div->reg;
+	}
+
+	if (!reg) {
+		pr_err("%s: clock[%s] remap register failed!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	if (of_property_read_u32(node, "sprd,div-msk", &msk)) {
+		pr_err("%s: Failed to get %s's div-msk\n", __func__, clk_name);
+		goto iounmap_reg;
+	}
+
+	shift = __ffs(msk);
+	width = fls(msk) - shift;
+	clk = clk_register_divider(NULL, clk_name, parent,
+				   0, reg, shift, width, 0, NULL);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+iounmap_reg:
+	iounmap(reg);
+	pr_err("%s: Failed to register divider clock[%s]!\n",
+	       __func__, clk_name);
+}
+
+CLK_OF_DECLARE(divider_clock, "sprd,divider-clock", sprd_divider_clk_setup);
diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c
new file mode 100644
index 0000000..5969282
--- /dev/null
+++ b/drivers/clk/sprd/mux.c
@@ -0,0 +1,77 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_mux_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char **parent_names;
+	int   num_parents = 0;
+	void __iomem *reg;
+	u32  msk = 0;
+	u8   shift = 0;
+	u8   width = 0;
+	int i = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	if (of_property_read_u32(node, "sprd,mux-msk", &msk)) {
+		pr_err("%s: No mux-msk property found for %s!\n",
+		       __func__, clk_name);
+		return;
+	}
+	shift = __ffs(msk);
+	width = fls(msk) - shift;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (!num_parents) {
+		pr_err("%s: no parent found for %s!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	while (i < num_parents &&
+		(parent_names[i] =
+		 of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s: mux-clock[%s] of_iomap failed!\n", __func__,
+			clk_name);
+		goto kfree_parent_names;
+	}
+
+	clk = clk_register_mux(NULL, clk_name, parent_names, num_parents,
+			       CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+			       reg, shift, width, 0, NULL);
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+	iounmap(reg);
+
+kfree_parent_names:
+	kfree(parent_names);
+}
+
+CLK_OF_DECLARE(muxed_clock, "sprd,muxed-clock", sprd_mux_clk_setup);
diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c
new file mode 100644
index 0000000..de32bce
--- /dev/null
+++ b/drivers/clk/sprd/pll.c
@@ -0,0 +1,359 @@
+/*
+ * Spreatrum pll clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/delay.h>
+#include "pll_cfg.h"
+
+struct sprd_pll_config *g_sprd_pll_config;
+
+static void pll_write(void __iomem *reg, u32 val, u32 msk)
+{
+	writel_relaxed((readl_relaxed(reg) & ~msk) | val, reg);
+}
+
+static unsigned long pll_get_refin_rate(struct sprd_pll_hw *pll,
+					struct sprd_pll_config *ppll_config)
+{
+	u32 i = 3;
+	u8 index;
+	u32 value;
+	const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+	value = ppll_config->refin_msk.value;
+	index = ppll_config->refin_msk.index;
+	if (value) {
+		i = (readl_relaxed(pll->reg[index]) & value) >> __ffs(value);
+		i = i > 3 ? 3 : i;
+	}
+
+	return refin[i];
+}
+
+static u8 pll_get_ibias(unsigned long rate, struct pll_ibias_table *table)
+{
+	if (!table)
+		return 0;
+
+	for (; table->rate < SPRD_PLL_MAX_RATE; table++)
+		if (rate <= table->rate)
+			break;
+
+	return table->ibias;
+}
+
+static void *pll_get_config(struct clk_hw *hw,
+			    struct sprd_pll_config *pll_config)
+{
+	struct sprd_pll_config *p;
+
+	for (p = pll_config; p->name != NULL; p++)
+		if (!strcmp(p->name, __clk_get_name(hw->clk)))
+			break;
+
+	return p->name ? p : NULL;
+}
+
+static int pll_clk_prepare(struct clk_hw *hw)
+{
+	struct sprd_pll_config *pcfg;
+
+	pcfg = pll_get_config(hw, g_sprd_pll_config);
+	if (!pcfg)
+		return -EPERM;
+
+	udelay(pcfg->udelay);
+
+	return 0;
+}
+
+static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long *prate)
+{
+	return rate;
+}
+
+static inline int pll_check(struct sprd_pll_hw *pll,
+			    struct sprd_pll_config *ppll_config)
+{
+	if ((ppll_config->lock_done.index >= pll->reg_num)	||
+	    (ppll_config->div_s.index >= pll->reg_num)		||
+	    (ppll_config->mod_en.index >= pll->reg_num)		||
+	    (ppll_config->sdm_en.index >= pll->reg_num)		||
+	    (ppll_config->refin_msk.index >= pll->reg_num)	||
+	    (ppll_config->ibias_msk.index >= pll->reg_num)	||
+	    (ppll_config->pll_n_msk.index >= pll->reg_num)	||
+	    (ppll_config->nint_msk.index >= pll->reg_num)	||
+	    (ppll_config->kint_msk.index >= pll->reg_num)	||
+	    (ppll_config->prediv_msk.index >= pll->reg_num)) {
+		pr_err("%s: pll[%s] exceed max:%d\n", __func__,
+		       __clk_get_name(pll->hw.clk), pll->reg_num);
+
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* get field */
+#define gf(array, pll_struct) \
+	(array[pll_struct.index] & pll_struct.value)
+
+/* get field value */
+#define gfv(array, pll_struct) \
+	(gf(array, pll_struct) >> __ffs(pll_struct.value))
+
+static unsigned long pll_recalc_rate(struct sprd_pll_hw *pll,
+				     struct sprd_pll_config *ppll_config,
+				     unsigned long parent_rate)
+{
+	unsigned long rate, refin, k1, k2;
+	unsigned long kint = 0, nint, cfg[SPRD_PLL_MAX_REGNUM], n;
+	int i;
+	u32 value;
+
+	if (!ppll_config) {
+		pr_err("%s:%d Cannot get pll %s\n", __func__,
+			__LINE__, __clk_get_name(pll->hw.clk));
+		return parent_rate;
+	}
+
+	if (pll_check(pll, ppll_config))
+		return parent_rate;
+
+	for (i = 0; i < pll->reg_num; i++)
+		cfg[i] = readl_relaxed(pll->reg[i]);
+
+	refin = pll_get_refin_rate(pll, ppll_config);
+
+	if (gf(cfg, ppll_config->prediv_msk))
+		refin = refin * 2;
+
+	if (ppll_config->postdiv_msk.value &&
+	    (((ppll_config->postdiv_msk.fvco_threshold->flag == 1) &&
+	      gf(cfg, ppll_config->postdiv_msk)) ||
+	     ((ppll_config->postdiv_msk.fvco_threshold->flag == 0) &&
+	      !gf(cfg, ppll_config->postdiv_msk))))
+		refin = refin / 2;
+
+	if (!gf(cfg, ppll_config->div_s)) {
+		n = gfv(cfg, ppll_config->pll_n_msk);
+		rate = refin * n * 10000000;
+	} else {
+		nint = gfv(cfg, ppll_config->nint_msk);
+		if (gf(cfg, ppll_config->sdm_en))
+			kint = gfv(cfg, ppll_config->kint_msk);
+
+		value = ppll_config->kint_msk.value;
+#ifdef CONFIG_64BIT
+		k1 = 1000;
+		k2 = 1000;
+		i = 0;
+#else
+		k1 = 100;
+		k2 = 10000;
+		i = fls(value >> __ffs(value));
+		i = i < 20 ? 0 : i - 20;
+#endif
+		rate = DIV_ROUND_CLOSEST(refin * (kint >> i) * k1,
+					 ((value >> (__ffs(value) + i)) + 1)) *
+					 k2 + refin * nint * 1000000;
+	}
+
+	return rate;
+}
+
+static int pll_adjustable_set_rate(struct sprd_pll_hw *pll,
+				   struct sprd_pll_config *ppll_config,
+				   unsigned long rate,
+				   unsigned long parent_rate)
+{
+	u8 ibias, index;
+	u32 value;
+	unsigned long kint, nint;
+	unsigned long refin, val, fvco = rate;
+	struct reg_cfg cfg[SPRD_PLL_MAX_REGNUM] = {{},};
+	struct fvco_threshold *ft;
+	int i = 0;
+
+	if (ppll_config == NULL) {
+		pr_err("%s:%d Cannot get pll clk[%s]\n", __func__,
+			__LINE__, __clk_get_name(pll->hw.clk));
+		return -EINVAL;
+	}
+
+	if (pll_check(pll, ppll_config))
+		return -EINVAL;
+
+	/* calc the pll refin */
+	refin = pll_get_refin_rate(pll, ppll_config);
+
+	value = ppll_config->prediv_msk.value;
+	index = ppll_config->prediv_msk.index;
+	if (value) {
+		val = readl_relaxed(pll->reg[index]);
+		if (val & value)
+			refin = refin * 2;
+	}
+
+	value = ppll_config->postdiv_msk.value;
+	index = ppll_config->postdiv_msk.index;
+	ft = ppll_config->postdiv_msk.fvco_threshold;
+	cfg[index].msk = value;
+	if (value && ((ft->flag == 1 && fvco <= ft->rate) ||
+		      (ft->flag == 0 && fvco > ft->rate)))
+		cfg[index].val |= value;
+
+	if (fvco <= ft->rate)
+		fvco = fvco * 2;
+
+	value = ppll_config->div_s.value;
+	index = ppll_config->div_s.index;
+	cfg[index].val |= value;
+	cfg[index].msk |= value;
+
+	value = ppll_config->sdm_en.value;
+	index = ppll_config->sdm_en.index;
+	cfg[index].val |= value;
+	cfg[index].msk |= value;
+
+	nint  = fvco/(refin * 1000000);
+
+	value = ppll_config->nint_msk.value;
+	index = ppll_config->nint_msk.index;
+	cfg[index].val |= (nint << __ffs(value)) & value;
+	cfg[index].msk |= value;
+
+	value = ppll_config->kint_msk.value;
+	index = ppll_config->kint_msk.index;
+#ifndef CONFIG_64BIT
+	i = fls(value >> __ffs(value));
+	i = i < 20 ? 0 : i - 20;
+#endif
+	kint = DIV_ROUND_CLOSEST(((fvco - refin * nint * 1000000)/10000) *
+	((value >> (__ffs(value) + i)) + 1), refin * 100) << i;
+	cfg[index].val |= (kint << __ffs(value)) & value;
+	cfg[index].msk |= value;
+
+	ibias = pll_get_ibias(fvco, ppll_config->itable);
+	value = ppll_config->ibias_msk.value;
+	index = ppll_config->ibias_msk.index;
+	cfg[index].val |= ibias << __ffs(value) & value;
+	cfg[index].msk |= value;
+
+	for (i = 0; i < pll->reg_num; i++)
+		if (cfg[i].msk)
+			pll_write(pll->reg[i], cfg[i].val, cfg[i].msk);
+
+	udelay(ppll_config->udelay);
+
+	return 0;
+}
+
+static void pll_clk_setup(struct device_node *node,
+			  const struct clk_ops *clk_ops)
+{
+	struct clk *clk = NULL;
+	const char *parent_names;
+	struct sprd_pll_hw *pll;
+	int reg_num, index;
+	struct clk_init_data init = {
+		.ops = clk_ops,
+		.flags = CLK_IGNORE_UNUSED,
+		.num_parents = 1,
+	};
+
+	parent_names = of_clk_get_parent_name(node, 0);
+	if (!parent_names) {
+		pr_err("%s: Failed to get parent_names in node[%s]\n",
+			__func__, node->name);
+		return;
+	}
+	init.parent_names = &parent_names;
+
+	if (of_property_read_string(node, "clock-output-names", &init.name))
+		return;
+
+	pll = kzalloc(sizeof(struct sprd_pll_hw), GFP_KERNEL);
+	if (!pll)
+		return;
+
+	reg_num = of_property_count_u32_elems(node, "reg");
+	reg_num = reg_num / (of_n_addr_cells(node) + of_n_size_cells(node));
+	if (reg_num > SPRD_PLL_MAX_REGNUM) {
+		pr_err("%s: reg_num:%d exceed max number\n",
+		       __func__, reg_num);
+		goto kfree_pll;
+	}
+	pll->reg_num = reg_num;
+
+	for (index = 0; index < reg_num; index++) {
+		pll->reg[index] = of_iomap(node, index);
+		if (!pll->reg[index])
+			goto kfree_pll;
+	}
+
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (!IS_ERR(clk)) {
+		clk_register_clkdev(clk, init.name, 0);
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return;
+	}
+
+kfree_pll:
+	kfree(pll);
+}
+
+static unsigned long sprd_adjustable_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long parent_rate)
+{
+	struct sprd_pll_config *ppll_config;
+	struct sprd_pll_hw *pll = to_sprd_pll_hw(hw);
+
+	ppll_config = pll_get_config(hw, g_sprd_pll_config);
+
+	return pll_recalc_rate(pll, ppll_config, parent_rate);
+}
+
+static int sprd_adjustable_pll_set_rate(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct sprd_pll_config *ppll_config;
+	struct sprd_pll_hw *pll = to_sprd_pll_hw(hw);
+
+	ppll_config = pll_get_config(hw, g_sprd_pll_config);
+
+	return pll_adjustable_set_rate(pll, ppll_config, rate,
+					    parent_rate);
+}
+
+const struct clk_ops sprd_adjustable_pll_ops = {
+	.prepare = pll_clk_prepare,
+	.round_rate = pll_round_rate,
+	.set_rate = sprd_adjustable_pll_set_rate,
+	.recalc_rate = sprd_adjustable_pll_recalc_rate,
+};
+
+static void __init sc9836_adjustable_pll_setup(struct device_node *node)
+{
+	g_sprd_pll_config = sc9836_pll_config;
+	pll_clk_setup(node, &sprd_adjustable_pll_ops);
+}
+
+static void __init sc9860_adjustable_pll_setup(struct device_node *node)
+{
+	g_sprd_pll_config = sc9860_pll_config;
+	pll_clk_setup(node, &sprd_adjustable_pll_ops);
+}
+
+CLK_OF_DECLARE(sc9836_adjustable_pll_clock, "sprd,sc9836-adjustable-pll-clock",
+	       sc9836_adjustable_pll_setup);
+CLK_OF_DECLARE(sc9860_adjustable_pll_clock, "sprd,sc9860-adjustable-pll-clock",
+	       sc9860_adjustable_pll_setup);
diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h
new file mode 100644
index 0000000..4b79092
--- /dev/null
+++ b/drivers/clk/sprd/pll.h
@@ -0,0 +1,73 @@
+/*
+ * Spreatrum clock pll driver head file
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SPRD_PLL_H__
+#define __SPRD_PLL_H__
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SPRD_PLL_MAX_RATE	ULONG_MAX
+#define SPRD_PLL_MAX_REGNUM	(3)
+#define SPRD_DELAY_200		(200)
+#define SPRD_DELAY_1000		(1000)
+
+struct reg_cfg {
+	u32 val;
+	u32 msk;
+};
+
+struct pll_common {
+	u32 value;
+	u8  index;
+};
+
+struct fvco_threshold {
+	unsigned long rate;
+	int flag;
+};
+
+struct pll_div_mask {
+	u32 value;
+	u8  index;
+	struct fvco_threshold *fvco_threshold;
+};
+
+struct pll_ibias_table {
+	unsigned long rate;
+	u8 ibias;
+};
+
+struct sprd_pll_config {
+	char	*name;
+	u32		udelay;
+	struct pll_common	lock_done;
+	struct pll_common	div_s;
+	struct pll_common	mod_en;
+	struct pll_common	sdm_en;
+	struct pll_common	refin_msk;
+	struct pll_common	ibias_msk;
+	struct pll_common	pll_n_msk;
+	struct pll_common	nint_msk;
+	struct pll_common	kint_msk;
+	struct pll_div_mask	prediv_msk;
+	struct pll_div_mask	postdiv_msk;
+	struct pll_ibias_table	*itable;
+};
+
+struct sprd_pll_hw {
+	struct clk_hw	hw;
+	void __iomem	*reg[SPRD_PLL_MAX_REGNUM];
+	int		reg_num;
+};
+
+#define to_sprd_pll_hw(_hw) container_of(_hw, struct sprd_pll_hw, hw)
+
+#endif
diff --git a/drivers/clk/sprd/pll_cfg.h b/drivers/clk/sprd/pll_cfg.h
new file mode 100644
index 0000000..64e79f3
--- /dev/null
+++ b/drivers/clk/sprd/pll_cfg.h
@@ -0,0 +1,390 @@
+/*
+ * Spreatrum clock pll configurations
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SPRD_PLL_CFG_H__
+#define __SPRD_PLL_CFG_H__
+
+#include "pll.h"
+
+static struct sprd_pll_config sc9836_pll_config[] = {
+	{
+		.name = "sc9836_pll",
+		.udelay = SPRD_DELAY_1000,
+		.lock_done.value = 1 << 27,
+		.lock_done.index = 0,
+		.div_s.value = 1 << 26,
+		.div_s.index = 0,
+		.mod_en.value = 1 << 25,
+		.mod_en.index = 0,
+		.sdm_en.value = 1 << 24,
+		.sdm_en.index = 0,
+		.refin_msk.value = 3 << 18,
+		.refin_msk.index = 0,
+		.ibias_msk.value = 3 << 16,
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7ff,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = 0x3f << 24,
+		.nint_msk.index = 1,
+		.kint_msk.value = 0xfffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0,
+		.prediv_msk.index = 0,
+		.postdiv_msk.value = 0x0,
+		.itable = NULL,
+	},
+
+	/* add configures above this */
+	{
+		.name = NULL,
+	}
+};
+
+/* GPLL/LPLL/DPLL/RPLL/CPLL */
+static struct pll_ibias_table sc9860_adjustable_pll1_table[] = {
+	{
+		.rate = 780000000,
+		.ibias = 0x0,
+	},
+	{
+		.rate = 988000000,
+		.ibias = 0x1,
+	},
+	{
+		.rate = 1196000000,
+		.ibias = 0x2,
+	},
+
+	/* add items above this */
+	{
+		.rate = SPRD_PLL_MAX_RATE,
+		.ibias = 0x2,
+	},
+};
+
+/* TWPLL/MPLL0/MPLL1 */
+static struct pll_ibias_table sc9860_adjustable_pll2_table[] = {
+	{
+		.rate = 1638000000,
+		.ibias = 0x0,
+	},
+	{
+		.rate = 2080000000,
+		.ibias = 0x1,
+	},
+	{
+		.rate = 2600000000UL,
+		.ibias = 0x2,
+	},
+
+	/* add items above this */
+	{
+		.rate = SPRD_PLL_MAX_RATE,
+		.ibias = 0x2,
+	},
+};
+
+static struct fvco_threshold sc9860_mpll0_threshold = {
+	.rate = 1300000000,
+	.flag = 1,
+};
+
+static struct fvco_threshold sc9860_gpll_threshold = {
+	.rate = 600000000,
+	.flag = 1,
+};
+
+static struct sprd_pll_config sc9860_pll_config[] = {
+	{
+		.name  = "clk_mpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 20),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 19),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 18),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 11),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = (1 << 24),
+		.postdiv_msk.index = 1,
+		.postdiv_msk.fvco_threshold = &sc9860_mpll0_threshold,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_mpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 20),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 19),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 18),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 11),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = (1 << 24),
+		.prediv_msk.index = 1,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_gpll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 18),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.fvco_threshold = &sc9860_gpll_threshold,
+		.postdiv_msk.value = (1 << 17),
+		.postdiv_msk.index = 0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_dpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 16),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_dpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 16),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_twpll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 21),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 20),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 19),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 18),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 13),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_ltepll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 31),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 27),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 26),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 25),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 20),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_ltepll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 31),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 27),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 26),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 25),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 20),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_cppll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 17),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+	/* rpll register bit is different from other plls. */
+		.name  = "clk_rpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 0),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 3),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 16),
+		.mod_en.index = 2,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 2,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 14),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f << 16),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 4),
+		.nint_msk.index = 0,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_rpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 0),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 3),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 16),
+		.mod_en.index = 2,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 2,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 14),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f << 16),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 4),
+		.nint_msk.index = 0,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+
+	/* add configures above this */
+	{
+		.name = NULL,
+	}
+};
+#endif
-- 
2.7.4

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

* [PATCH 3/3] clk: Add common clock driver for Spreadtrum SoCs
@ 2017-05-15  8:35   ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: mturquette, sboyd, robh+dt, mark.rutland, catalin.marinas, will.deacon
  Cc: xiaolong.zhang, orson.zhai, geng.ren, arnd, linux-clk,
	linux-kernel, devicetree, linux-arm-kernel, zhang.lyra,
	chunyan.zhang

From: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>

This patch adds an initial common clock driver comprising clock gate,
divider, multiplexer, composite, pll, these drivers are used on almost
all Spreadtrum platforms so far.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/Makefile         |   1 +
 drivers/clk/sprd/Makefile    |   3 +
 drivers/clk/sprd/clk-gates.c | 366 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/composite.c | 109 ++++++++++++
 drivers/clk/sprd/divider.c   |  79 +++++++++
 drivers/clk/sprd/mux.c       |  77 +++++++++
 drivers/clk/sprd/pll.c       | 359 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/pll.h       |  73 ++++++++
 drivers/clk/sprd/pll_cfg.h   | 390 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1457 insertions(+)
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/clk-gates.c
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/divider.c
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/pll_cfg.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c19983a..1d62721 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 0000000..a783c27
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+ifneq ($(CONFIG_OF),)
+obj-y					+= divider.o mux.o composite.o pll.o clk-gates.o
+endif
diff --git a/drivers/clk/sprd/clk-gates.c b/drivers/clk/sprd/clk-gates.c
new file mode 100644
index 0000000..8d4ccb9
--- /dev/null
+++ b/drivers/clk/sprd/clk-gates.c
@@ -0,0 +1,366 @@
+/*
+ * Spreadtrum clock set/clear gate driver
+ *
+ * Copyright (C) 2015~2017 spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+
+DEFINE_SPINLOCK(gate_lock);
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+#define CLK_GATE_HWSPINLOCK		BIT(7)
+#define GLB_CLK_HWSPINLOCK_TIMEOUT	5000
+
+static struct hwspinlock		*glb_clk_hw_lock;
+
+static void sprd_clk_lock(struct clk_gate *gate,
+			unsigned long flags)
+{
+	if (gate->lock)
+		spin_lock_irqsave(gate->lock, flags);
+	else
+		__acquire(gate->lock);
+}
+
+static void sprd_clk_unlock(struct clk_gate *gate,
+			unsigned long flags)
+{
+	if (gate->lock)
+		spin_unlock_irqrestore(gate->lock, flags);
+	else
+		__release(gate->lock);
+}
+
+static void sprd_clk_hw_lock(struct clk_gate *gate,
+				unsigned long *flags)
+{
+	int ret = 0;
+
+	if (glb_clk_hw_lock && (gate->flags & CLK_GATE_HWSPINLOCK)) {
+		ret = hwspin_lock_timeout_irqsave(glb_clk_hw_lock,
+					  GLB_CLK_HWSPINLOCK_TIMEOUT,
+					  flags);
+		if (ret)
+			pr_err("glb_clk:%s lock the hwlock failed.\n",
+			       __clk_get_name(gate->hw.clk));
+		return;
+	}
+
+	sprd_clk_lock(gate, *flags);
+}
+
+static void sprd_clk_hw_unlock(struct clk_gate *gate,
+				unsigned long *flags)
+{
+	if (glb_clk_hw_lock && (gate->flags & CLK_GATE_HWSPINLOCK)) {
+		hwspin_unlock_irqrestore(glb_clk_hw_lock, flags);
+		return;
+	}
+
+	sprd_clk_unlock(gate, *flags);
+}
+
+static void sprd_clk_gate_endisable(struct clk_hw *hw, int enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned long flags = 0;
+	u32 reg;
+
+	set ^= enable;
+
+	sprd_clk_hw_lock(gate, &flags);
+
+	reg = clk_readl(gate->reg);
+
+	if (set)
+		reg |= BIT(gate->bit_idx);
+	else
+		reg &= ~BIT(gate->bit_idx);
+
+	clk_writel(reg, gate->reg);
+
+	sprd_clk_hw_unlock(gate, &flags);
+}
+
+static int sprd_clk_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_gate_endisable(hw, 1);
+
+	return 0;
+}
+
+static void sprd_clk_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_gate_endisable(hw, 0);
+}
+
+static int sprd_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	u32 reg;
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	reg = clk_readl(gate->reg);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		reg ^= BIT(gate->bit_idx);
+
+	reg &= BIT(gate->bit_idx);
+
+	return reg ? 1 : 0;
+}
+
+const struct clk_ops sprd_clk_gate_ops = {
+	.enable = sprd_clk_gate_enable,
+	.disable = sprd_clk_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+static void sprd_clk_sc_gate_endisable(struct clk_hw *hw, int enable,
+				       unsigned int offset)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned long flags = 0;
+	void __iomem *reg;
+
+	set ^= enable;
+
+	sprd_clk_lock(gate, flags);
+
+	/*
+	 * Each gate clock has three registers:
+	 * gate->reg			- base register
+	 * gate->reg + offset		- set register
+	 * gate->reg + 2 * offset	- clear register
+	 */
+	reg = set ? gate->reg + offset : gate->reg + 2 * offset;
+	clk_writel(BIT(gate->bit_idx), reg);
+
+	sprd_clk_unlock(gate, flags);
+
+}
+
+static int sprd_clk_sc100_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 1, 0x100);
+
+	return 0;
+}
+
+static void sprd_clk_sc100_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 0, 0x100);
+}
+
+static int sprd_clk_sc1000_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 1, 0x1000);
+
+	return 0;
+}
+
+static void sprd_clk_sc1000_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 0, 0x1000);
+}
+
+const struct clk_ops sprd_clk_sc100_gate_ops = {
+	.enable = sprd_clk_sc100_gate_enable,
+	.disable = sprd_clk_sc100_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+const struct clk_ops sprd_clk_sc1000_gate_ops = {
+	.enable = sprd_clk_sc1000_gate_enable,
+	.disable = sprd_clk_sc1000_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+static struct clk *sprd_clk_register_gate(struct device *dev,
+		const char *name, const char *parent_name,
+		unsigned long flags, void __iomem *reg,
+		u8 bit_idx, u8 clk_gate_flags,
+		spinlock_t *lock, const struct clk_ops *ops)
+{
+	struct clk_gate *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+	gate->lock = lock;
+	gate->hw.init = &init;
+
+	clk = clk_register(dev, &gate->hw);
+
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
+
+static void __init sprd_clk_gates_setup(struct device_node *node,
+					   const struct clk_ops *ops)
+{
+	const char *clk_name = NULL;
+	void __iomem *reg;
+	const char *parent_name;
+	unsigned long flags = CLK_IGNORE_UNUSED;
+	u8 gate_flags = 0;
+	u32 index;
+	int number, i = 0;
+	struct resource res;
+	struct clk_onecell_data *clk_data;
+	struct property *prop;
+	const __be32 *p;
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_err("%s: no DT registers found for %s\n",
+		       __func__, node->full_name);
+		return;
+	}
+
+	/*
+	 * bit[1:0] represents the gate flags, but bit[1] is not used
+	 * for the time being.
+	 */
+	if (res.start & 0x3) {
+		res.start &= ~0x3;
+		gate_flags |= CLK_GATE_SET_TO_DISABLE;
+	}
+	reg = ioremap(res.start, resource_size(&res));
+	if (!reg) {
+		pr_err("%s: gates clock[%s] ioremap failed!\n",
+		       __func__, node->full_name);
+		return;
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+	if (!clk_data)
+		goto iounmap_reg;
+
+	number = of_property_count_u32_elems(node, "clock-indices");
+	if (number > 0) {
+		of_property_read_u32_index(node, "clock-indices",
+					   number - 1, &number);
+		number += 1;
+	} else {
+		number = of_property_count_strings(node, "clock-output-names");
+	}
+
+	clk_data->clks = kcalloc(number, sizeof(struct clk *),
+				 GFP_KERNEL);
+	if (!clk_data->clks)
+		goto kfree_clk_data;
+
+	/*
+	 * If the identifying number for the clocks in the node is not
+	 * linear from zero, then we use clock-indices mapping
+	 * identifiers into the clock-output-names array in DT.
+	 */
+	if (of_property_count_u32_elems(node, "clock-indices") > 0) {
+		of_property_for_each_u32(node, "clock-indices",
+					 prop, p, index) {
+			of_property_read_string_index(node,
+						      "clock-output-names",
+						      i++, &clk_name);
+
+			clk_data->clks[index] = sprd_clk_register_gate(NULL,
+						clk_name, parent_name, flags,
+						reg, index, gate_flags,
+						&gate_lock, ops);
+			WARN_ON(IS_ERR(clk_data->clks[index]));
+
+			clk_register_clkdev(clk_data->clks[index], clk_name,
+					    NULL);
+		}
+	} else {
+		of_property_for_each_string(node, "clock-output-names",
+					    prop, clk_name) {
+			clk_data->clks[i] = sprd_clk_register_gate(NULL,
+						clk_name, parent_name, flags,
+						reg, i,	gate_flags,
+						&gate_lock, ops);
+			WARN_ON(IS_ERR(clk_data->clks[i]));
+
+			clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
+			i++;
+		}
+	}
+
+	clk_data->clk_num = number;
+	if (number == 1)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk_data);
+	else
+		of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	return;
+
+kfree_clk_data:
+	kfree(clk_data);
+
+iounmap_reg:
+	iounmap(reg);
+}
+
+static void __init sprd_sc100_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_sc100_gate_ops);
+}
+
+static void __init sprd_sc1000_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_sc1000_gate_ops);
+}
+
+static void __init sprd_trad_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_gate_ops);
+}
+
+CLK_OF_DECLARE(gates_clock, "sprd,gates-clock",
+		sprd_trad_clk_gates_setup);
+CLK_OF_DECLARE(sc100_gates_clock, "sprd,sc100-gates-clock",
+	       sprd_sc100_clk_gates_setup);
+CLK_OF_DECLARE(sc1000_gates_clock, "sprd,sc1000-gates-clock",
+	       sprd_sc1000_clk_gates_setup);
+
+#ifdef CONFIG_SPRD_HWSPINLOCK
+static int __init sprd_clk_hwspinlock_init(void)
+{
+	/*
+	 * glb_clk belongs to the global registers, so it can use the
+	 * same hwspinlock
+	 */
+	glb_clk_hw_lock = hwspin_lock_get_used(1);
+	if (!glb_clk_hw_lock) {
+		pr_err("%s: Can't get the hardware spinlock.\n", __func__);
+		return -ENXIO;
+	}
+
+	return 0;
+}
+subsys_initcall_sync(sprd_clk_hwspinlock_init);
+#endif
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
new file mode 100644
index 0000000..118565a
--- /dev/null
+++ b/drivers/clk/sprd/composite.c
@@ -0,0 +1,109 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_composite_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	const struct clk_ops *mux_ops = NULL;
+	struct clk_divider *div = NULL;
+	const struct clk_ops *div_ops = NULL;
+	const char *clk_name = node->name;
+	const char **parent_names;
+	unsigned long flags = 0;
+	u32 msk;
+	int num_parents = 0;
+	int i = 0;
+	int index = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (!num_parents) {
+		pr_err("%s: Failed to get %s's parent number!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	while (i < num_parents &&
+			(parent_names[i] =
+			 of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+	if (!mux)
+		goto kfree_parent_names;
+
+	if (!of_property_read_u32(node, "sprd,mux-msk", &msk)) {
+		mux->reg = of_iomap(node, index++);
+		if (!mux->reg)
+			goto kfree_mux;
+
+		mux->shift = __ffs(msk);
+		mux->mask = msk >> (mux->shift);
+		mux_ops = &clk_mux_ops;
+	}
+
+	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+	if (!div)
+		goto iounmap_mux_reg;
+
+	if (!of_property_read_u32(node, "sprd,div-msk", &msk)) {
+		div->reg = of_iomap(node, index);
+		if (!div->reg)
+			div->reg = mux->reg;
+		if (!div->reg)
+			goto iounmap_mux_reg;
+
+		div->shift = __ffs(msk);
+		div->width = fls(msk) - div->shift;
+		div_ops = &clk_divider_ops;
+	}
+
+	flags |= CLK_IGNORE_UNUSED;
+	clk = clk_register_composite(NULL, clk_name, parent_names, num_parents,
+				     &mux->hw, mux_ops, &div->hw, div_ops, NULL,
+				     NULL, flags);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+	if (div->reg)
+		if (!mux || (div->reg != mux->reg))
+			iounmap(div->reg);
+
+	kfree(div);
+
+iounmap_mux_reg:
+	if (mux->reg)
+		iounmap(mux->reg);
+
+kfree_mux:
+	kfree(mux);
+
+kfree_parent_names:
+	pr_err("Failed to register composite clk %s!\n", clk_name);
+	kfree(parent_names);
+}
+
+CLK_OF_DECLARE(composite_clock, "sprd,composite-clock",
+	       sprd_composite_clk_setup);
diff --git a/drivers/clk/sprd/divider.c b/drivers/clk/sprd/divider.c
new file mode 100644
index 0000000..785d6c4
--- /dev/null
+++ b/drivers/clk/sprd/divider.c
@@ -0,0 +1,79 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_divider_clk_setup(struct device_node *node)
+{
+	struct clk *clk, *pclk;
+	struct clk_divider *clk_div;
+	struct clk_composite *clk_composite;
+	const char *clk_name = node->name;
+	const char *parent;
+	void __iomem *reg;
+	u32 msk = 0;
+	u8 shift = 0;
+	u8 width = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	parent = of_clk_get_parent_name(node, 0);
+
+	if (of_property_read_bool(node, "reg")) {
+		reg = of_iomap(node, 0);
+	} else {
+		pclk = __clk_lookup(parent);
+		if (!pclk) {
+			pr_err("%s: clock[%s] has no reg and parent!\n",
+			       __func__, clk_name);
+			return;
+		}
+
+		clk_composite = container_of(__clk_get_hw(pclk),
+					     struct clk_composite, hw);
+
+		clk_div = container_of(clk_composite->rate_hw,
+				       struct clk_divider, hw);
+
+		reg = clk_div->reg;
+	}
+
+	if (!reg) {
+		pr_err("%s: clock[%s] remap register failed!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	if (of_property_read_u32(node, "sprd,div-msk", &msk)) {
+		pr_err("%s: Failed to get %s's div-msk\n", __func__, clk_name);
+		goto iounmap_reg;
+	}
+
+	shift = __ffs(msk);
+	width = fls(msk) - shift;
+	clk = clk_register_divider(NULL, clk_name, parent,
+				   0, reg, shift, width, 0, NULL);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+iounmap_reg:
+	iounmap(reg);
+	pr_err("%s: Failed to register divider clock[%s]!\n",
+	       __func__, clk_name);
+}
+
+CLK_OF_DECLARE(divider_clock, "sprd,divider-clock", sprd_divider_clk_setup);
diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c
new file mode 100644
index 0000000..5969282
--- /dev/null
+++ b/drivers/clk/sprd/mux.c
@@ -0,0 +1,77 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_mux_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char **parent_names;
+	int   num_parents = 0;
+	void __iomem *reg;
+	u32  msk = 0;
+	u8   shift = 0;
+	u8   width = 0;
+	int i = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	if (of_property_read_u32(node, "sprd,mux-msk", &msk)) {
+		pr_err("%s: No mux-msk property found for %s!\n",
+		       __func__, clk_name);
+		return;
+	}
+	shift = __ffs(msk);
+	width = fls(msk) - shift;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (!num_parents) {
+		pr_err("%s: no parent found for %s!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	while (i < num_parents &&
+		(parent_names[i] =
+		 of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s: mux-clock[%s] of_iomap failed!\n", __func__,
+			clk_name);
+		goto kfree_parent_names;
+	}
+
+	clk = clk_register_mux(NULL, clk_name, parent_names, num_parents,
+			       CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+			       reg, shift, width, 0, NULL);
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+	iounmap(reg);
+
+kfree_parent_names:
+	kfree(parent_names);
+}
+
+CLK_OF_DECLARE(muxed_clock, "sprd,muxed-clock", sprd_mux_clk_setup);
diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c
new file mode 100644
index 0000000..de32bce
--- /dev/null
+++ b/drivers/clk/sprd/pll.c
@@ -0,0 +1,359 @@
+/*
+ * Spreatrum pll clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/delay.h>
+#include "pll_cfg.h"
+
+struct sprd_pll_config *g_sprd_pll_config;
+
+static void pll_write(void __iomem *reg, u32 val, u32 msk)
+{
+	writel_relaxed((readl_relaxed(reg) & ~msk) | val, reg);
+}
+
+static unsigned long pll_get_refin_rate(struct sprd_pll_hw *pll,
+					struct sprd_pll_config *ppll_config)
+{
+	u32 i = 3;
+	u8 index;
+	u32 value;
+	const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+	value = ppll_config->refin_msk.value;
+	index = ppll_config->refin_msk.index;
+	if (value) {
+		i = (readl_relaxed(pll->reg[index]) & value) >> __ffs(value);
+		i = i > 3 ? 3 : i;
+	}
+
+	return refin[i];
+}
+
+static u8 pll_get_ibias(unsigned long rate, struct pll_ibias_table *table)
+{
+	if (!table)
+		return 0;
+
+	for (; table->rate < SPRD_PLL_MAX_RATE; table++)
+		if (rate <= table->rate)
+			break;
+
+	return table->ibias;
+}
+
+static void *pll_get_config(struct clk_hw *hw,
+			    struct sprd_pll_config *pll_config)
+{
+	struct sprd_pll_config *p;
+
+	for (p = pll_config; p->name != NULL; p++)
+		if (!strcmp(p->name, __clk_get_name(hw->clk)))
+			break;
+
+	return p->name ? p : NULL;
+}
+
+static int pll_clk_prepare(struct clk_hw *hw)
+{
+	struct sprd_pll_config *pcfg;
+
+	pcfg = pll_get_config(hw, g_sprd_pll_config);
+	if (!pcfg)
+		return -EPERM;
+
+	udelay(pcfg->udelay);
+
+	return 0;
+}
+
+static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long *prate)
+{
+	return rate;
+}
+
+static inline int pll_check(struct sprd_pll_hw *pll,
+			    struct sprd_pll_config *ppll_config)
+{
+	if ((ppll_config->lock_done.index >= pll->reg_num)	||
+	    (ppll_config->div_s.index >= pll->reg_num)		||
+	    (ppll_config->mod_en.index >= pll->reg_num)		||
+	    (ppll_config->sdm_en.index >= pll->reg_num)		||
+	    (ppll_config->refin_msk.index >= pll->reg_num)	||
+	    (ppll_config->ibias_msk.index >= pll->reg_num)	||
+	    (ppll_config->pll_n_msk.index >= pll->reg_num)	||
+	    (ppll_config->nint_msk.index >= pll->reg_num)	||
+	    (ppll_config->kint_msk.index >= pll->reg_num)	||
+	    (ppll_config->prediv_msk.index >= pll->reg_num)) {
+		pr_err("%s: pll[%s] exceed max:%d\n", __func__,
+		       __clk_get_name(pll->hw.clk), pll->reg_num);
+
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* get field */
+#define gf(array, pll_struct) \
+	(array[pll_struct.index] & pll_struct.value)
+
+/* get field value */
+#define gfv(array, pll_struct) \
+	(gf(array, pll_struct) >> __ffs(pll_struct.value))
+
+static unsigned long pll_recalc_rate(struct sprd_pll_hw *pll,
+				     struct sprd_pll_config *ppll_config,
+				     unsigned long parent_rate)
+{
+	unsigned long rate, refin, k1, k2;
+	unsigned long kint = 0, nint, cfg[SPRD_PLL_MAX_REGNUM], n;
+	int i;
+	u32 value;
+
+	if (!ppll_config) {
+		pr_err("%s:%d Cannot get pll %s\n", __func__,
+			__LINE__, __clk_get_name(pll->hw.clk));
+		return parent_rate;
+	}
+
+	if (pll_check(pll, ppll_config))
+		return parent_rate;
+
+	for (i = 0; i < pll->reg_num; i++)
+		cfg[i] = readl_relaxed(pll->reg[i]);
+
+	refin = pll_get_refin_rate(pll, ppll_config);
+
+	if (gf(cfg, ppll_config->prediv_msk))
+		refin = refin * 2;
+
+	if (ppll_config->postdiv_msk.value &&
+	    (((ppll_config->postdiv_msk.fvco_threshold->flag == 1) &&
+	      gf(cfg, ppll_config->postdiv_msk)) ||
+	     ((ppll_config->postdiv_msk.fvco_threshold->flag == 0) &&
+	      !gf(cfg, ppll_config->postdiv_msk))))
+		refin = refin / 2;
+
+	if (!gf(cfg, ppll_config->div_s)) {
+		n = gfv(cfg, ppll_config->pll_n_msk);
+		rate = refin * n * 10000000;
+	} else {
+		nint = gfv(cfg, ppll_config->nint_msk);
+		if (gf(cfg, ppll_config->sdm_en))
+			kint = gfv(cfg, ppll_config->kint_msk);
+
+		value = ppll_config->kint_msk.value;
+#ifdef CONFIG_64BIT
+		k1 = 1000;
+		k2 = 1000;
+		i = 0;
+#else
+		k1 = 100;
+		k2 = 10000;
+		i = fls(value >> __ffs(value));
+		i = i < 20 ? 0 : i - 20;
+#endif
+		rate = DIV_ROUND_CLOSEST(refin * (kint >> i) * k1,
+					 ((value >> (__ffs(value) + i)) + 1)) *
+					 k2 + refin * nint * 1000000;
+	}
+
+	return rate;
+}
+
+static int pll_adjustable_set_rate(struct sprd_pll_hw *pll,
+				   struct sprd_pll_config *ppll_config,
+				   unsigned long rate,
+				   unsigned long parent_rate)
+{
+	u8 ibias, index;
+	u32 value;
+	unsigned long kint, nint;
+	unsigned long refin, val, fvco = rate;
+	struct reg_cfg cfg[SPRD_PLL_MAX_REGNUM] = {{},};
+	struct fvco_threshold *ft;
+	int i = 0;
+
+	if (ppll_config == NULL) {
+		pr_err("%s:%d Cannot get pll clk[%s]\n", __func__,
+			__LINE__, __clk_get_name(pll->hw.clk));
+		return -EINVAL;
+	}
+
+	if (pll_check(pll, ppll_config))
+		return -EINVAL;
+
+	/* calc the pll refin */
+	refin = pll_get_refin_rate(pll, ppll_config);
+
+	value = ppll_config->prediv_msk.value;
+	index = ppll_config->prediv_msk.index;
+	if (value) {
+		val = readl_relaxed(pll->reg[index]);
+		if (val & value)
+			refin = refin * 2;
+	}
+
+	value = ppll_config->postdiv_msk.value;
+	index = ppll_config->postdiv_msk.index;
+	ft = ppll_config->postdiv_msk.fvco_threshold;
+	cfg[index].msk = value;
+	if (value && ((ft->flag == 1 && fvco <= ft->rate) ||
+		      (ft->flag == 0 && fvco > ft->rate)))
+		cfg[index].val |= value;
+
+	if (fvco <= ft->rate)
+		fvco = fvco * 2;
+
+	value = ppll_config->div_s.value;
+	index = ppll_config->div_s.index;
+	cfg[index].val |= value;
+	cfg[index].msk |= value;
+
+	value = ppll_config->sdm_en.value;
+	index = ppll_config->sdm_en.index;
+	cfg[index].val |= value;
+	cfg[index].msk |= value;
+
+	nint  = fvco/(refin * 1000000);
+
+	value = ppll_config->nint_msk.value;
+	index = ppll_config->nint_msk.index;
+	cfg[index].val |= (nint << __ffs(value)) & value;
+	cfg[index].msk |= value;
+
+	value = ppll_config->kint_msk.value;
+	index = ppll_config->kint_msk.index;
+#ifndef CONFIG_64BIT
+	i = fls(value >> __ffs(value));
+	i = i < 20 ? 0 : i - 20;
+#endif
+	kint = DIV_ROUND_CLOSEST(((fvco - refin * nint * 1000000)/10000) *
+	((value >> (__ffs(value) + i)) + 1), refin * 100) << i;
+	cfg[index].val |= (kint << __ffs(value)) & value;
+	cfg[index].msk |= value;
+
+	ibias = pll_get_ibias(fvco, ppll_config->itable);
+	value = ppll_config->ibias_msk.value;
+	index = ppll_config->ibias_msk.index;
+	cfg[index].val |= ibias << __ffs(value) & value;
+	cfg[index].msk |= value;
+
+	for (i = 0; i < pll->reg_num; i++)
+		if (cfg[i].msk)
+			pll_write(pll->reg[i], cfg[i].val, cfg[i].msk);
+
+	udelay(ppll_config->udelay);
+
+	return 0;
+}
+
+static void pll_clk_setup(struct device_node *node,
+			  const struct clk_ops *clk_ops)
+{
+	struct clk *clk = NULL;
+	const char *parent_names;
+	struct sprd_pll_hw *pll;
+	int reg_num, index;
+	struct clk_init_data init = {
+		.ops = clk_ops,
+		.flags = CLK_IGNORE_UNUSED,
+		.num_parents = 1,
+	};
+
+	parent_names = of_clk_get_parent_name(node, 0);
+	if (!parent_names) {
+		pr_err("%s: Failed to get parent_names in node[%s]\n",
+			__func__, node->name);
+		return;
+	}
+	init.parent_names = &parent_names;
+
+	if (of_property_read_string(node, "clock-output-names", &init.name))
+		return;
+
+	pll = kzalloc(sizeof(struct sprd_pll_hw), GFP_KERNEL);
+	if (!pll)
+		return;
+
+	reg_num = of_property_count_u32_elems(node, "reg");
+	reg_num = reg_num / (of_n_addr_cells(node) + of_n_size_cells(node));
+	if (reg_num > SPRD_PLL_MAX_REGNUM) {
+		pr_err("%s: reg_num:%d exceed max number\n",
+		       __func__, reg_num);
+		goto kfree_pll;
+	}
+	pll->reg_num = reg_num;
+
+	for (index = 0; index < reg_num; index++) {
+		pll->reg[index] = of_iomap(node, index);
+		if (!pll->reg[index])
+			goto kfree_pll;
+	}
+
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (!IS_ERR(clk)) {
+		clk_register_clkdev(clk, init.name, 0);
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return;
+	}
+
+kfree_pll:
+	kfree(pll);
+}
+
+static unsigned long sprd_adjustable_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long parent_rate)
+{
+	struct sprd_pll_config *ppll_config;
+	struct sprd_pll_hw *pll = to_sprd_pll_hw(hw);
+
+	ppll_config = pll_get_config(hw, g_sprd_pll_config);
+
+	return pll_recalc_rate(pll, ppll_config, parent_rate);
+}
+
+static int sprd_adjustable_pll_set_rate(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct sprd_pll_config *ppll_config;
+	struct sprd_pll_hw *pll = to_sprd_pll_hw(hw);
+
+	ppll_config = pll_get_config(hw, g_sprd_pll_config);
+
+	return pll_adjustable_set_rate(pll, ppll_config, rate,
+					    parent_rate);
+}
+
+const struct clk_ops sprd_adjustable_pll_ops = {
+	.prepare = pll_clk_prepare,
+	.round_rate = pll_round_rate,
+	.set_rate = sprd_adjustable_pll_set_rate,
+	.recalc_rate = sprd_adjustable_pll_recalc_rate,
+};
+
+static void __init sc9836_adjustable_pll_setup(struct device_node *node)
+{
+	g_sprd_pll_config = sc9836_pll_config;
+	pll_clk_setup(node, &sprd_adjustable_pll_ops);
+}
+
+static void __init sc9860_adjustable_pll_setup(struct device_node *node)
+{
+	g_sprd_pll_config = sc9860_pll_config;
+	pll_clk_setup(node, &sprd_adjustable_pll_ops);
+}
+
+CLK_OF_DECLARE(sc9836_adjustable_pll_clock, "sprd,sc9836-adjustable-pll-clock",
+	       sc9836_adjustable_pll_setup);
+CLK_OF_DECLARE(sc9860_adjustable_pll_clock, "sprd,sc9860-adjustable-pll-clock",
+	       sc9860_adjustable_pll_setup);
diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h
new file mode 100644
index 0000000..4b79092
--- /dev/null
+++ b/drivers/clk/sprd/pll.h
@@ -0,0 +1,73 @@
+/*
+ * Spreatrum clock pll driver head file
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SPRD_PLL_H__
+#define __SPRD_PLL_H__
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SPRD_PLL_MAX_RATE	ULONG_MAX
+#define SPRD_PLL_MAX_REGNUM	(3)
+#define SPRD_DELAY_200		(200)
+#define SPRD_DELAY_1000		(1000)
+
+struct reg_cfg {
+	u32 val;
+	u32 msk;
+};
+
+struct pll_common {
+	u32 value;
+	u8  index;
+};
+
+struct fvco_threshold {
+	unsigned long rate;
+	int flag;
+};
+
+struct pll_div_mask {
+	u32 value;
+	u8  index;
+	struct fvco_threshold *fvco_threshold;
+};
+
+struct pll_ibias_table {
+	unsigned long rate;
+	u8 ibias;
+};
+
+struct sprd_pll_config {
+	char	*name;
+	u32		udelay;
+	struct pll_common	lock_done;
+	struct pll_common	div_s;
+	struct pll_common	mod_en;
+	struct pll_common	sdm_en;
+	struct pll_common	refin_msk;
+	struct pll_common	ibias_msk;
+	struct pll_common	pll_n_msk;
+	struct pll_common	nint_msk;
+	struct pll_common	kint_msk;
+	struct pll_div_mask	prediv_msk;
+	struct pll_div_mask	postdiv_msk;
+	struct pll_ibias_table	*itable;
+};
+
+struct sprd_pll_hw {
+	struct clk_hw	hw;
+	void __iomem	*reg[SPRD_PLL_MAX_REGNUM];
+	int		reg_num;
+};
+
+#define to_sprd_pll_hw(_hw) container_of(_hw, struct sprd_pll_hw, hw)
+
+#endif
diff --git a/drivers/clk/sprd/pll_cfg.h b/drivers/clk/sprd/pll_cfg.h
new file mode 100644
index 0000000..64e79f3
--- /dev/null
+++ b/drivers/clk/sprd/pll_cfg.h
@@ -0,0 +1,390 @@
+/*
+ * Spreatrum clock pll configurations
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SPRD_PLL_CFG_H__
+#define __SPRD_PLL_CFG_H__
+
+#include "pll.h"
+
+static struct sprd_pll_config sc9836_pll_config[] = {
+	{
+		.name = "sc9836_pll",
+		.udelay = SPRD_DELAY_1000,
+		.lock_done.value = 1 << 27,
+		.lock_done.index = 0,
+		.div_s.value = 1 << 26,
+		.div_s.index = 0,
+		.mod_en.value = 1 << 25,
+		.mod_en.index = 0,
+		.sdm_en.value = 1 << 24,
+		.sdm_en.index = 0,
+		.refin_msk.value = 3 << 18,
+		.refin_msk.index = 0,
+		.ibias_msk.value = 3 << 16,
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7ff,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = 0x3f << 24,
+		.nint_msk.index = 1,
+		.kint_msk.value = 0xfffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0,
+		.prediv_msk.index = 0,
+		.postdiv_msk.value = 0x0,
+		.itable = NULL,
+	},
+
+	/* add configures above this */
+	{
+		.name = NULL,
+	}
+};
+
+/* GPLL/LPLL/DPLL/RPLL/CPLL */
+static struct pll_ibias_table sc9860_adjustable_pll1_table[] = {
+	{
+		.rate = 780000000,
+		.ibias = 0x0,
+	},
+	{
+		.rate = 988000000,
+		.ibias = 0x1,
+	},
+	{
+		.rate = 1196000000,
+		.ibias = 0x2,
+	},
+
+	/* add items above this */
+	{
+		.rate = SPRD_PLL_MAX_RATE,
+		.ibias = 0x2,
+	},
+};
+
+/* TWPLL/MPLL0/MPLL1 */
+static struct pll_ibias_table sc9860_adjustable_pll2_table[] = {
+	{
+		.rate = 1638000000,
+		.ibias = 0x0,
+	},
+	{
+		.rate = 2080000000,
+		.ibias = 0x1,
+	},
+	{
+		.rate = 2600000000UL,
+		.ibias = 0x2,
+	},
+
+	/* add items above this */
+	{
+		.rate = SPRD_PLL_MAX_RATE,
+		.ibias = 0x2,
+	},
+};
+
+static struct fvco_threshold sc9860_mpll0_threshold = {
+	.rate = 1300000000,
+	.flag = 1,
+};
+
+static struct fvco_threshold sc9860_gpll_threshold = {
+	.rate = 600000000,
+	.flag = 1,
+};
+
+static struct sprd_pll_config sc9860_pll_config[] = {
+	{
+		.name  = "clk_mpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 20),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 19),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 18),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 11),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = (1 << 24),
+		.postdiv_msk.index = 1,
+		.postdiv_msk.fvco_threshold = &sc9860_mpll0_threshold,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_mpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 20),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 19),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 18),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 11),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = (1 << 24),
+		.prediv_msk.index = 1,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_gpll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 18),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.fvco_threshold = &sc9860_gpll_threshold,
+		.postdiv_msk.value = (1 << 17),
+		.postdiv_msk.index = 0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_dpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 16),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_dpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 16),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_twpll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 21),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 20),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 19),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 18),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 13),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_ltepll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 31),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 27),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 26),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 25),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 20),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_ltepll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 31),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 27),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 26),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 25),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 20),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_cppll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 17),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+	/* rpll register bit is different from other plls. */
+		.name  = "clk_rpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 0),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 3),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 16),
+		.mod_en.index = 2,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 2,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 14),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f << 16),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 4),
+		.nint_msk.index = 0,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_rpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 0),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 3),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 16),
+		.mod_en.index = 2,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 2,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 14),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f << 16),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 4),
+		.nint_msk.index = 0,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+
+	/* add configures above this */
+	{
+		.name = NULL,
+	}
+};
+#endif
-- 
2.7.4

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

* [PATCH 3/3] clk: Add common clock driver for Spreadtrum SoCs
@ 2017-05-15  8:35   ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-15  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>

This patch adds an initial common clock driver comprising clock gate,
divider, multiplexer, composite, pll, these drivers are used on almost
all Spreadtrum platforms so far.

Signed-off-by: Xiaolong Zhang <xiaolong.zhang@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/Makefile         |   1 +
 drivers/clk/sprd/Makefile    |   3 +
 drivers/clk/sprd/clk-gates.c | 366 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/composite.c | 109 ++++++++++++
 drivers/clk/sprd/divider.c   |  79 +++++++++
 drivers/clk/sprd/mux.c       |  77 +++++++++
 drivers/clk/sprd/pll.c       | 359 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/pll.h       |  73 ++++++++
 drivers/clk/sprd/pll_cfg.h   | 390 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1457 insertions(+)
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/clk-gates.c
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/divider.c
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/pll_cfg.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c19983a..1d62721 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 0000000..a783c27
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+ifneq ($(CONFIG_OF),)
+obj-y					+= divider.o mux.o composite.o pll.o clk-gates.o
+endif
diff --git a/drivers/clk/sprd/clk-gates.c b/drivers/clk/sprd/clk-gates.c
new file mode 100644
index 0000000..8d4ccb9
--- /dev/null
+++ b/drivers/clk/sprd/clk-gates.c
@@ -0,0 +1,366 @@
+/*
+ * Spreadtrum clock set/clear gate driver
+ *
+ * Copyright (C) 2015~2017 spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+
+DEFINE_SPINLOCK(gate_lock);
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+#define CLK_GATE_HWSPINLOCK		BIT(7)
+#define GLB_CLK_HWSPINLOCK_TIMEOUT	5000
+
+static struct hwspinlock		*glb_clk_hw_lock;
+
+static void sprd_clk_lock(struct clk_gate *gate,
+			unsigned long flags)
+{
+	if (gate->lock)
+		spin_lock_irqsave(gate->lock, flags);
+	else
+		__acquire(gate->lock);
+}
+
+static void sprd_clk_unlock(struct clk_gate *gate,
+			unsigned long flags)
+{
+	if (gate->lock)
+		spin_unlock_irqrestore(gate->lock, flags);
+	else
+		__release(gate->lock);
+}
+
+static void sprd_clk_hw_lock(struct clk_gate *gate,
+				unsigned long *flags)
+{
+	int ret = 0;
+
+	if (glb_clk_hw_lock && (gate->flags & CLK_GATE_HWSPINLOCK)) {
+		ret = hwspin_lock_timeout_irqsave(glb_clk_hw_lock,
+					  GLB_CLK_HWSPINLOCK_TIMEOUT,
+					  flags);
+		if (ret)
+			pr_err("glb_clk:%s lock the hwlock failed.\n",
+			       __clk_get_name(gate->hw.clk));
+		return;
+	}
+
+	sprd_clk_lock(gate, *flags);
+}
+
+static void sprd_clk_hw_unlock(struct clk_gate *gate,
+				unsigned long *flags)
+{
+	if (glb_clk_hw_lock && (gate->flags & CLK_GATE_HWSPINLOCK)) {
+		hwspin_unlock_irqrestore(glb_clk_hw_lock, flags);
+		return;
+	}
+
+	sprd_clk_unlock(gate, *flags);
+}
+
+static void sprd_clk_gate_endisable(struct clk_hw *hw, int enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned long flags = 0;
+	u32 reg;
+
+	set ^= enable;
+
+	sprd_clk_hw_lock(gate, &flags);
+
+	reg = clk_readl(gate->reg);
+
+	if (set)
+		reg |= BIT(gate->bit_idx);
+	else
+		reg &= ~BIT(gate->bit_idx);
+
+	clk_writel(reg, gate->reg);
+
+	sprd_clk_hw_unlock(gate, &flags);
+}
+
+static int sprd_clk_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_gate_endisable(hw, 1);
+
+	return 0;
+}
+
+static void sprd_clk_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_gate_endisable(hw, 0);
+}
+
+static int sprd_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	u32 reg;
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	reg = clk_readl(gate->reg);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		reg ^= BIT(gate->bit_idx);
+
+	reg &= BIT(gate->bit_idx);
+
+	return reg ? 1 : 0;
+}
+
+const struct clk_ops sprd_clk_gate_ops = {
+	.enable = sprd_clk_gate_enable,
+	.disable = sprd_clk_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+static void sprd_clk_sc_gate_endisable(struct clk_hw *hw, int enable,
+				       unsigned int offset)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned long flags = 0;
+	void __iomem *reg;
+
+	set ^= enable;
+
+	sprd_clk_lock(gate, flags);
+
+	/*
+	 * Each gate clock has three registers:
+	 * gate->reg			- base register
+	 * gate->reg + offset		- set register
+	 * gate->reg + 2 * offset	- clear register
+	 */
+	reg = set ? gate->reg + offset : gate->reg + 2 * offset;
+	clk_writel(BIT(gate->bit_idx), reg);
+
+	sprd_clk_unlock(gate, flags);
+
+}
+
+static int sprd_clk_sc100_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 1, 0x100);
+
+	return 0;
+}
+
+static void sprd_clk_sc100_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 0, 0x100);
+}
+
+static int sprd_clk_sc1000_gate_enable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 1, 0x1000);
+
+	return 0;
+}
+
+static void sprd_clk_sc1000_gate_disable(struct clk_hw *hw)
+{
+	sprd_clk_sc_gate_endisable(hw, 0, 0x1000);
+}
+
+const struct clk_ops sprd_clk_sc100_gate_ops = {
+	.enable = sprd_clk_sc100_gate_enable,
+	.disable = sprd_clk_sc100_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+const struct clk_ops sprd_clk_sc1000_gate_ops = {
+	.enable = sprd_clk_sc1000_gate_enable,
+	.disable = sprd_clk_sc1000_gate_disable,
+	.is_enabled = sprd_clk_gate_is_enabled,
+};
+
+static struct clk *sprd_clk_register_gate(struct device *dev,
+		const char *name, const char *parent_name,
+		unsigned long flags, void __iomem *reg,
+		u8 bit_idx, u8 clk_gate_flags,
+		spinlock_t *lock, const struct clk_ops *ops)
+{
+	struct clk_gate *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+	gate->lock = lock;
+	gate->hw.init = &init;
+
+	clk = clk_register(dev, &gate->hw);
+
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
+
+static void __init sprd_clk_gates_setup(struct device_node *node,
+					   const struct clk_ops *ops)
+{
+	const char *clk_name = NULL;
+	void __iomem *reg;
+	const char *parent_name;
+	unsigned long flags = CLK_IGNORE_UNUSED;
+	u8 gate_flags = 0;
+	u32 index;
+	int number, i = 0;
+	struct resource res;
+	struct clk_onecell_data *clk_data;
+	struct property *prop;
+	const __be32 *p;
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_err("%s: no DT registers found for %s\n",
+		       __func__, node->full_name);
+		return;
+	}
+
+	/*
+	 * bit[1:0] represents the gate flags, but bit[1] is not used
+	 * for the time being.
+	 */
+	if (res.start & 0x3) {
+		res.start &= ~0x3;
+		gate_flags |= CLK_GATE_SET_TO_DISABLE;
+	}
+	reg = ioremap(res.start, resource_size(&res));
+	if (!reg) {
+		pr_err("%s: gates clock[%s] ioremap failed!\n",
+		       __func__, node->full_name);
+		return;
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+	if (!clk_data)
+		goto iounmap_reg;
+
+	number = of_property_count_u32_elems(node, "clock-indices");
+	if (number > 0) {
+		of_property_read_u32_index(node, "clock-indices",
+					   number - 1, &number);
+		number += 1;
+	} else {
+		number = of_property_count_strings(node, "clock-output-names");
+	}
+
+	clk_data->clks = kcalloc(number, sizeof(struct clk *),
+				 GFP_KERNEL);
+	if (!clk_data->clks)
+		goto kfree_clk_data;
+
+	/*
+	 * If the identifying number for the clocks in the node is not
+	 * linear from zero, then we use clock-indices mapping
+	 * identifiers into the clock-output-names array in DT.
+	 */
+	if (of_property_count_u32_elems(node, "clock-indices") > 0) {
+		of_property_for_each_u32(node, "clock-indices",
+					 prop, p, index) {
+			of_property_read_string_index(node,
+						      "clock-output-names",
+						      i++, &clk_name);
+
+			clk_data->clks[index] = sprd_clk_register_gate(NULL,
+						clk_name, parent_name, flags,
+						reg, index, gate_flags,
+						&gate_lock, ops);
+			WARN_ON(IS_ERR(clk_data->clks[index]));
+
+			clk_register_clkdev(clk_data->clks[index], clk_name,
+					    NULL);
+		}
+	} else {
+		of_property_for_each_string(node, "clock-output-names",
+					    prop, clk_name) {
+			clk_data->clks[i] = sprd_clk_register_gate(NULL,
+						clk_name, parent_name, flags,
+						reg, i,	gate_flags,
+						&gate_lock, ops);
+			WARN_ON(IS_ERR(clk_data->clks[i]));
+
+			clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
+			i++;
+		}
+	}
+
+	clk_data->clk_num = number;
+	if (number == 1)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk_data);
+	else
+		of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	return;
+
+kfree_clk_data:
+	kfree(clk_data);
+
+iounmap_reg:
+	iounmap(reg);
+}
+
+static void __init sprd_sc100_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_sc100_gate_ops);
+}
+
+static void __init sprd_sc1000_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_sc1000_gate_ops);
+}
+
+static void __init sprd_trad_clk_gates_setup(struct device_node *node)
+{
+	sprd_clk_gates_setup(node, &sprd_clk_gate_ops);
+}
+
+CLK_OF_DECLARE(gates_clock, "sprd,gates-clock",
+		sprd_trad_clk_gates_setup);
+CLK_OF_DECLARE(sc100_gates_clock, "sprd,sc100-gates-clock",
+	       sprd_sc100_clk_gates_setup);
+CLK_OF_DECLARE(sc1000_gates_clock, "sprd,sc1000-gates-clock",
+	       sprd_sc1000_clk_gates_setup);
+
+#ifdef CONFIG_SPRD_HWSPINLOCK
+static int __init sprd_clk_hwspinlock_init(void)
+{
+	/*
+	 * glb_clk belongs to the global registers, so it can use the
+	 * same hwspinlock
+	 */
+	glb_clk_hw_lock = hwspin_lock_get_used(1);
+	if (!glb_clk_hw_lock) {
+		pr_err("%s: Can't get the hardware spinlock.\n", __func__);
+		return -ENXIO;
+	}
+
+	return 0;
+}
+subsys_initcall_sync(sprd_clk_hwspinlock_init);
+#endif
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
new file mode 100644
index 0000000..118565a
--- /dev/null
+++ b/drivers/clk/sprd/composite.c
@@ -0,0 +1,109 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_composite_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	const struct clk_ops *mux_ops = NULL;
+	struct clk_divider *div = NULL;
+	const struct clk_ops *div_ops = NULL;
+	const char *clk_name = node->name;
+	const char **parent_names;
+	unsigned long flags = 0;
+	u32 msk;
+	int num_parents = 0;
+	int i = 0;
+	int index = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (!num_parents) {
+		pr_err("%s: Failed to get %s's parent number!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	while (i < num_parents &&
+			(parent_names[i] =
+			 of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+	if (!mux)
+		goto kfree_parent_names;
+
+	if (!of_property_read_u32(node, "sprd,mux-msk", &msk)) {
+		mux->reg = of_iomap(node, index++);
+		if (!mux->reg)
+			goto kfree_mux;
+
+		mux->shift = __ffs(msk);
+		mux->mask = msk >> (mux->shift);
+		mux_ops = &clk_mux_ops;
+	}
+
+	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+	if (!div)
+		goto iounmap_mux_reg;
+
+	if (!of_property_read_u32(node, "sprd,div-msk", &msk)) {
+		div->reg = of_iomap(node, index);
+		if (!div->reg)
+			div->reg = mux->reg;
+		if (!div->reg)
+			goto iounmap_mux_reg;
+
+		div->shift = __ffs(msk);
+		div->width = fls(msk) - div->shift;
+		div_ops = &clk_divider_ops;
+	}
+
+	flags |= CLK_IGNORE_UNUSED;
+	clk = clk_register_composite(NULL, clk_name, parent_names, num_parents,
+				     &mux->hw, mux_ops, &div->hw, div_ops, NULL,
+				     NULL, flags);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+	if (div->reg)
+		if (!mux || (div->reg != mux->reg))
+			iounmap(div->reg);
+
+	kfree(div);
+
+iounmap_mux_reg:
+	if (mux->reg)
+		iounmap(mux->reg);
+
+kfree_mux:
+	kfree(mux);
+
+kfree_parent_names:
+	pr_err("Failed to register composite clk %s!\n", clk_name);
+	kfree(parent_names);
+}
+
+CLK_OF_DECLARE(composite_clock, "sprd,composite-clock",
+	       sprd_composite_clk_setup);
diff --git a/drivers/clk/sprd/divider.c b/drivers/clk/sprd/divider.c
new file mode 100644
index 0000000..785d6c4
--- /dev/null
+++ b/drivers/clk/sprd/divider.c
@@ -0,0 +1,79 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_divider_clk_setup(struct device_node *node)
+{
+	struct clk *clk, *pclk;
+	struct clk_divider *clk_div;
+	struct clk_composite *clk_composite;
+	const char *clk_name = node->name;
+	const char *parent;
+	void __iomem *reg;
+	u32 msk = 0;
+	u8 shift = 0;
+	u8 width = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	parent = of_clk_get_parent_name(node, 0);
+
+	if (of_property_read_bool(node, "reg")) {
+		reg = of_iomap(node, 0);
+	} else {
+		pclk = __clk_lookup(parent);
+		if (!pclk) {
+			pr_err("%s: clock[%s] has no reg and parent!\n",
+			       __func__, clk_name);
+			return;
+		}
+
+		clk_composite = container_of(__clk_get_hw(pclk),
+					     struct clk_composite, hw);
+
+		clk_div = container_of(clk_composite->rate_hw,
+				       struct clk_divider, hw);
+
+		reg = clk_div->reg;
+	}
+
+	if (!reg) {
+		pr_err("%s: clock[%s] remap register failed!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	if (of_property_read_u32(node, "sprd,div-msk", &msk)) {
+		pr_err("%s: Failed to get %s's div-msk\n", __func__, clk_name);
+		goto iounmap_reg;
+	}
+
+	shift = __ffs(msk);
+	width = fls(msk) - shift;
+	clk = clk_register_divider(NULL, clk_name, parent,
+				   0, reg, shift, width, 0, NULL);
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+iounmap_reg:
+	iounmap(reg);
+	pr_err("%s: Failed to register divider clock[%s]!\n",
+	       __func__, clk_name);
+}
+
+CLK_OF_DECLARE(divider_clock, "sprd,divider-clock", sprd_divider_clk_setup);
diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c
new file mode 100644
index 0000000..5969282
--- /dev/null
+++ b/drivers/clk/sprd/mux.c
@@ -0,0 +1,77 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __init sprd_mux_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char **parent_names;
+	int   num_parents = 0;
+	void __iomem *reg;
+	u32  msk = 0;
+	u8   shift = 0;
+	u8   width = 0;
+	int i = 0;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	if (of_property_read_u32(node, "sprd,mux-msk", &msk)) {
+		pr_err("%s: No mux-msk property found for %s!\n",
+		       __func__, clk_name);
+		return;
+	}
+	shift = __ffs(msk);
+	width = fls(msk) - shift;
+
+	num_parents = of_clk_get_parent_count(node);
+	if (!num_parents) {
+		pr_err("%s: no parent found for %s!\n",
+		       __func__, clk_name);
+		return;
+	}
+
+	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	while (i < num_parents &&
+		(parent_names[i] =
+		 of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s: mux-clock[%s] of_iomap failed!\n", __func__,
+			clk_name);
+		goto kfree_parent_names;
+	}
+
+	clk = clk_register_mux(NULL, clk_name, parent_names, num_parents,
+			       CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+			       reg, shift, width, 0, NULL);
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+		return;
+	}
+
+	iounmap(reg);
+
+kfree_parent_names:
+	kfree(parent_names);
+}
+
+CLK_OF_DECLARE(muxed_clock, "sprd,muxed-clock", sprd_mux_clk_setup);
diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c
new file mode 100644
index 0000000..de32bce
--- /dev/null
+++ b/drivers/clk/sprd/pll.c
@@ -0,0 +1,359 @@
+/*
+ * Spreatrum pll clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/delay.h>
+#include "pll_cfg.h"
+
+struct sprd_pll_config *g_sprd_pll_config;
+
+static void pll_write(void __iomem *reg, u32 val, u32 msk)
+{
+	writel_relaxed((readl_relaxed(reg) & ~msk) | val, reg);
+}
+
+static unsigned long pll_get_refin_rate(struct sprd_pll_hw *pll,
+					struct sprd_pll_config *ppll_config)
+{
+	u32 i = 3;
+	u8 index;
+	u32 value;
+	const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+	value = ppll_config->refin_msk.value;
+	index = ppll_config->refin_msk.index;
+	if (value) {
+		i = (readl_relaxed(pll->reg[index]) & value) >> __ffs(value);
+		i = i > 3 ? 3 : i;
+	}
+
+	return refin[i];
+}
+
+static u8 pll_get_ibias(unsigned long rate, struct pll_ibias_table *table)
+{
+	if (!table)
+		return 0;
+
+	for (; table->rate < SPRD_PLL_MAX_RATE; table++)
+		if (rate <= table->rate)
+			break;
+
+	return table->ibias;
+}
+
+static void *pll_get_config(struct clk_hw *hw,
+			    struct sprd_pll_config *pll_config)
+{
+	struct sprd_pll_config *p;
+
+	for (p = pll_config; p->name != NULL; p++)
+		if (!strcmp(p->name, __clk_get_name(hw->clk)))
+			break;
+
+	return p->name ? p : NULL;
+}
+
+static int pll_clk_prepare(struct clk_hw *hw)
+{
+	struct sprd_pll_config *pcfg;
+
+	pcfg = pll_get_config(hw, g_sprd_pll_config);
+	if (!pcfg)
+		return -EPERM;
+
+	udelay(pcfg->udelay);
+
+	return 0;
+}
+
+static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long *prate)
+{
+	return rate;
+}
+
+static inline int pll_check(struct sprd_pll_hw *pll,
+			    struct sprd_pll_config *ppll_config)
+{
+	if ((ppll_config->lock_done.index >= pll->reg_num)	||
+	    (ppll_config->div_s.index >= pll->reg_num)		||
+	    (ppll_config->mod_en.index >= pll->reg_num)		||
+	    (ppll_config->sdm_en.index >= pll->reg_num)		||
+	    (ppll_config->refin_msk.index >= pll->reg_num)	||
+	    (ppll_config->ibias_msk.index >= pll->reg_num)	||
+	    (ppll_config->pll_n_msk.index >= pll->reg_num)	||
+	    (ppll_config->nint_msk.index >= pll->reg_num)	||
+	    (ppll_config->kint_msk.index >= pll->reg_num)	||
+	    (ppll_config->prediv_msk.index >= pll->reg_num)) {
+		pr_err("%s: pll[%s] exceed max:%d\n", __func__,
+		       __clk_get_name(pll->hw.clk), pll->reg_num);
+
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* get field */
+#define gf(array, pll_struct) \
+	(array[pll_struct.index] & pll_struct.value)
+
+/* get field value */
+#define gfv(array, pll_struct) \
+	(gf(array, pll_struct) >> __ffs(pll_struct.value))
+
+static unsigned long pll_recalc_rate(struct sprd_pll_hw *pll,
+				     struct sprd_pll_config *ppll_config,
+				     unsigned long parent_rate)
+{
+	unsigned long rate, refin, k1, k2;
+	unsigned long kint = 0, nint, cfg[SPRD_PLL_MAX_REGNUM], n;
+	int i;
+	u32 value;
+
+	if (!ppll_config) {
+		pr_err("%s:%d Cannot get pll %s\n", __func__,
+			__LINE__, __clk_get_name(pll->hw.clk));
+		return parent_rate;
+	}
+
+	if (pll_check(pll, ppll_config))
+		return parent_rate;
+
+	for (i = 0; i < pll->reg_num; i++)
+		cfg[i] = readl_relaxed(pll->reg[i]);
+
+	refin = pll_get_refin_rate(pll, ppll_config);
+
+	if (gf(cfg, ppll_config->prediv_msk))
+		refin = refin * 2;
+
+	if (ppll_config->postdiv_msk.value &&
+	    (((ppll_config->postdiv_msk.fvco_threshold->flag == 1) &&
+	      gf(cfg, ppll_config->postdiv_msk)) ||
+	     ((ppll_config->postdiv_msk.fvco_threshold->flag == 0) &&
+	      !gf(cfg, ppll_config->postdiv_msk))))
+		refin = refin / 2;
+
+	if (!gf(cfg, ppll_config->div_s)) {
+		n = gfv(cfg, ppll_config->pll_n_msk);
+		rate = refin * n * 10000000;
+	} else {
+		nint = gfv(cfg, ppll_config->nint_msk);
+		if (gf(cfg, ppll_config->sdm_en))
+			kint = gfv(cfg, ppll_config->kint_msk);
+
+		value = ppll_config->kint_msk.value;
+#ifdef CONFIG_64BIT
+		k1 = 1000;
+		k2 = 1000;
+		i = 0;
+#else
+		k1 = 100;
+		k2 = 10000;
+		i = fls(value >> __ffs(value));
+		i = i < 20 ? 0 : i - 20;
+#endif
+		rate = DIV_ROUND_CLOSEST(refin * (kint >> i) * k1,
+					 ((value >> (__ffs(value) + i)) + 1)) *
+					 k2 + refin * nint * 1000000;
+	}
+
+	return rate;
+}
+
+static int pll_adjustable_set_rate(struct sprd_pll_hw *pll,
+				   struct sprd_pll_config *ppll_config,
+				   unsigned long rate,
+				   unsigned long parent_rate)
+{
+	u8 ibias, index;
+	u32 value;
+	unsigned long kint, nint;
+	unsigned long refin, val, fvco = rate;
+	struct reg_cfg cfg[SPRD_PLL_MAX_REGNUM] = {{},};
+	struct fvco_threshold *ft;
+	int i = 0;
+
+	if (ppll_config == NULL) {
+		pr_err("%s:%d Cannot get pll clk[%s]\n", __func__,
+			__LINE__, __clk_get_name(pll->hw.clk));
+		return -EINVAL;
+	}
+
+	if (pll_check(pll, ppll_config))
+		return -EINVAL;
+
+	/* calc the pll refin */
+	refin = pll_get_refin_rate(pll, ppll_config);
+
+	value = ppll_config->prediv_msk.value;
+	index = ppll_config->prediv_msk.index;
+	if (value) {
+		val = readl_relaxed(pll->reg[index]);
+		if (val & value)
+			refin = refin * 2;
+	}
+
+	value = ppll_config->postdiv_msk.value;
+	index = ppll_config->postdiv_msk.index;
+	ft = ppll_config->postdiv_msk.fvco_threshold;
+	cfg[index].msk = value;
+	if (value && ((ft->flag == 1 && fvco <= ft->rate) ||
+		      (ft->flag == 0 && fvco > ft->rate)))
+		cfg[index].val |= value;
+
+	if (fvco <= ft->rate)
+		fvco = fvco * 2;
+
+	value = ppll_config->div_s.value;
+	index = ppll_config->div_s.index;
+	cfg[index].val |= value;
+	cfg[index].msk |= value;
+
+	value = ppll_config->sdm_en.value;
+	index = ppll_config->sdm_en.index;
+	cfg[index].val |= value;
+	cfg[index].msk |= value;
+
+	nint  = fvco/(refin * 1000000);
+
+	value = ppll_config->nint_msk.value;
+	index = ppll_config->nint_msk.index;
+	cfg[index].val |= (nint << __ffs(value)) & value;
+	cfg[index].msk |= value;
+
+	value = ppll_config->kint_msk.value;
+	index = ppll_config->kint_msk.index;
+#ifndef CONFIG_64BIT
+	i = fls(value >> __ffs(value));
+	i = i < 20 ? 0 : i - 20;
+#endif
+	kint = DIV_ROUND_CLOSEST(((fvco - refin * nint * 1000000)/10000) *
+	((value >> (__ffs(value) + i)) + 1), refin * 100) << i;
+	cfg[index].val |= (kint << __ffs(value)) & value;
+	cfg[index].msk |= value;
+
+	ibias = pll_get_ibias(fvco, ppll_config->itable);
+	value = ppll_config->ibias_msk.value;
+	index = ppll_config->ibias_msk.index;
+	cfg[index].val |= ibias << __ffs(value) & value;
+	cfg[index].msk |= value;
+
+	for (i = 0; i < pll->reg_num; i++)
+		if (cfg[i].msk)
+			pll_write(pll->reg[i], cfg[i].val, cfg[i].msk);
+
+	udelay(ppll_config->udelay);
+
+	return 0;
+}
+
+static void pll_clk_setup(struct device_node *node,
+			  const struct clk_ops *clk_ops)
+{
+	struct clk *clk = NULL;
+	const char *parent_names;
+	struct sprd_pll_hw *pll;
+	int reg_num, index;
+	struct clk_init_data init = {
+		.ops = clk_ops,
+		.flags = CLK_IGNORE_UNUSED,
+		.num_parents = 1,
+	};
+
+	parent_names = of_clk_get_parent_name(node, 0);
+	if (!parent_names) {
+		pr_err("%s: Failed to get parent_names in node[%s]\n",
+			__func__, node->name);
+		return;
+	}
+	init.parent_names = &parent_names;
+
+	if (of_property_read_string(node, "clock-output-names", &init.name))
+		return;
+
+	pll = kzalloc(sizeof(struct sprd_pll_hw), GFP_KERNEL);
+	if (!pll)
+		return;
+
+	reg_num = of_property_count_u32_elems(node, "reg");
+	reg_num = reg_num / (of_n_addr_cells(node) + of_n_size_cells(node));
+	if (reg_num > SPRD_PLL_MAX_REGNUM) {
+		pr_err("%s: reg_num:%d exceed max number\n",
+		       __func__, reg_num);
+		goto kfree_pll;
+	}
+	pll->reg_num = reg_num;
+
+	for (index = 0; index < reg_num; index++) {
+		pll->reg[index] = of_iomap(node, index);
+		if (!pll->reg[index])
+			goto kfree_pll;
+	}
+
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (!IS_ERR(clk)) {
+		clk_register_clkdev(clk, init.name, 0);
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return;
+	}
+
+kfree_pll:
+	kfree(pll);
+}
+
+static unsigned long sprd_adjustable_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long parent_rate)
+{
+	struct sprd_pll_config *ppll_config;
+	struct sprd_pll_hw *pll = to_sprd_pll_hw(hw);
+
+	ppll_config = pll_get_config(hw, g_sprd_pll_config);
+
+	return pll_recalc_rate(pll, ppll_config, parent_rate);
+}
+
+static int sprd_adjustable_pll_set_rate(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct sprd_pll_config *ppll_config;
+	struct sprd_pll_hw *pll = to_sprd_pll_hw(hw);
+
+	ppll_config = pll_get_config(hw, g_sprd_pll_config);
+
+	return pll_adjustable_set_rate(pll, ppll_config, rate,
+					    parent_rate);
+}
+
+const struct clk_ops sprd_adjustable_pll_ops = {
+	.prepare = pll_clk_prepare,
+	.round_rate = pll_round_rate,
+	.set_rate = sprd_adjustable_pll_set_rate,
+	.recalc_rate = sprd_adjustable_pll_recalc_rate,
+};
+
+static void __init sc9836_adjustable_pll_setup(struct device_node *node)
+{
+	g_sprd_pll_config = sc9836_pll_config;
+	pll_clk_setup(node, &sprd_adjustable_pll_ops);
+}
+
+static void __init sc9860_adjustable_pll_setup(struct device_node *node)
+{
+	g_sprd_pll_config = sc9860_pll_config;
+	pll_clk_setup(node, &sprd_adjustable_pll_ops);
+}
+
+CLK_OF_DECLARE(sc9836_adjustable_pll_clock, "sprd,sc9836-adjustable-pll-clock",
+	       sc9836_adjustable_pll_setup);
+CLK_OF_DECLARE(sc9860_adjustable_pll_clock, "sprd,sc9860-adjustable-pll-clock",
+	       sc9860_adjustable_pll_setup);
diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h
new file mode 100644
index 0000000..4b79092
--- /dev/null
+++ b/drivers/clk/sprd/pll.h
@@ -0,0 +1,73 @@
+/*
+ * Spreatrum clock pll driver head file
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SPRD_PLL_H__
+#define __SPRD_PLL_H__
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SPRD_PLL_MAX_RATE	ULONG_MAX
+#define SPRD_PLL_MAX_REGNUM	(3)
+#define SPRD_DELAY_200		(200)
+#define SPRD_DELAY_1000		(1000)
+
+struct reg_cfg {
+	u32 val;
+	u32 msk;
+};
+
+struct pll_common {
+	u32 value;
+	u8  index;
+};
+
+struct fvco_threshold {
+	unsigned long rate;
+	int flag;
+};
+
+struct pll_div_mask {
+	u32 value;
+	u8  index;
+	struct fvco_threshold *fvco_threshold;
+};
+
+struct pll_ibias_table {
+	unsigned long rate;
+	u8 ibias;
+};
+
+struct sprd_pll_config {
+	char	*name;
+	u32		udelay;
+	struct pll_common	lock_done;
+	struct pll_common	div_s;
+	struct pll_common	mod_en;
+	struct pll_common	sdm_en;
+	struct pll_common	refin_msk;
+	struct pll_common	ibias_msk;
+	struct pll_common	pll_n_msk;
+	struct pll_common	nint_msk;
+	struct pll_common	kint_msk;
+	struct pll_div_mask	prediv_msk;
+	struct pll_div_mask	postdiv_msk;
+	struct pll_ibias_table	*itable;
+};
+
+struct sprd_pll_hw {
+	struct clk_hw	hw;
+	void __iomem	*reg[SPRD_PLL_MAX_REGNUM];
+	int		reg_num;
+};
+
+#define to_sprd_pll_hw(_hw) container_of(_hw, struct sprd_pll_hw, hw)
+
+#endif
diff --git a/drivers/clk/sprd/pll_cfg.h b/drivers/clk/sprd/pll_cfg.h
new file mode 100644
index 0000000..64e79f3
--- /dev/null
+++ b/drivers/clk/sprd/pll_cfg.h
@@ -0,0 +1,390 @@
+/*
+ * Spreatrum clock pll configurations
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SPRD_PLL_CFG_H__
+#define __SPRD_PLL_CFG_H__
+
+#include "pll.h"
+
+static struct sprd_pll_config sc9836_pll_config[] = {
+	{
+		.name = "sc9836_pll",
+		.udelay = SPRD_DELAY_1000,
+		.lock_done.value = 1 << 27,
+		.lock_done.index = 0,
+		.div_s.value = 1 << 26,
+		.div_s.index = 0,
+		.mod_en.value = 1 << 25,
+		.mod_en.index = 0,
+		.sdm_en.value = 1 << 24,
+		.sdm_en.index = 0,
+		.refin_msk.value = 3 << 18,
+		.refin_msk.index = 0,
+		.ibias_msk.value = 3 << 16,
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7ff,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = 0x3f << 24,
+		.nint_msk.index = 1,
+		.kint_msk.value = 0xfffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0,
+		.prediv_msk.index = 0,
+		.postdiv_msk.value = 0x0,
+		.itable = NULL,
+	},
+
+	/* add configures above this */
+	{
+		.name = NULL,
+	}
+};
+
+/* GPLL/LPLL/DPLL/RPLL/CPLL */
+static struct pll_ibias_table sc9860_adjustable_pll1_table[] = {
+	{
+		.rate = 780000000,
+		.ibias = 0x0,
+	},
+	{
+		.rate = 988000000,
+		.ibias = 0x1,
+	},
+	{
+		.rate = 1196000000,
+		.ibias = 0x2,
+	},
+
+	/* add items above this */
+	{
+		.rate = SPRD_PLL_MAX_RATE,
+		.ibias = 0x2,
+	},
+};
+
+/* TWPLL/MPLL0/MPLL1 */
+static struct pll_ibias_table sc9860_adjustable_pll2_table[] = {
+	{
+		.rate = 1638000000,
+		.ibias = 0x0,
+	},
+	{
+		.rate = 2080000000,
+		.ibias = 0x1,
+	},
+	{
+		.rate = 2600000000UL,
+		.ibias = 0x2,
+	},
+
+	/* add items above this */
+	{
+		.rate = SPRD_PLL_MAX_RATE,
+		.ibias = 0x2,
+	},
+};
+
+static struct fvco_threshold sc9860_mpll0_threshold = {
+	.rate = 1300000000,
+	.flag = 1,
+};
+
+static struct fvco_threshold sc9860_gpll_threshold = {
+	.rate = 600000000,
+	.flag = 1,
+};
+
+static struct sprd_pll_config sc9860_pll_config[] = {
+	{
+		.name  = "clk_mpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 20),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 19),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 18),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 11),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = (1 << 24),
+		.postdiv_msk.index = 1,
+		.postdiv_msk.fvco_threshold = &sc9860_mpll0_threshold,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_mpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 20),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 19),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 18),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 11),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = (1 << 24),
+		.prediv_msk.index = 1,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_gpll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 18),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.fvco_threshold = &sc9860_gpll_threshold,
+		.postdiv_msk.value = (1 << 17),
+		.postdiv_msk.index = 0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_dpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 16),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_dpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 16),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_twpll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 21),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 20),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 19),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 18),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 13),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll2_table,
+	},
+	{
+		.name  = "clk_ltepll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 31),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 27),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 26),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 25),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 20),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_ltepll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 31),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 27),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 26),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 25),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 20),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_cppll",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 17),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 15),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 14),
+		.mod_en.index = 0,
+		.sdm_en.value = (1 << 13),
+		.sdm_en.index = 0,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 8),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = 0x7f,
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 25),
+		.nint_msk.index = 1,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+	/* rpll register bit is different from other plls. */
+		.name  = "clk_rpll0",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 0),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 3),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 16),
+		.mod_en.index = 2,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 2,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 14),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f << 16),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 4),
+		.nint_msk.index = 0,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+	{
+		.name  = "clk_rpll1",
+		.udelay = SPRD_DELAY_200,
+		.lock_done.value = (1 << 0),
+		.lock_done.index = 0,
+		.div_s.value = (1 << 3),
+		.div_s.index = 0,
+		.mod_en.value = (1 << 16),
+		.mod_en.index = 2,
+		.sdm_en.value = (1 << 17),
+		.sdm_en.index = 2,
+		.refin_msk.value = 0,
+		.refin_msk.index = 0,
+		.ibias_msk.value = (3 << 14),
+		.ibias_msk.index = 0,
+		.pll_n_msk.value = (0x7f << 16),
+		.pll_n_msk.index = 0,
+		.nint_msk.value = (0x7f << 4),
+		.nint_msk.index = 0,
+		.kint_msk.value = 0x7fffff,
+		.kint_msk.index = 1,
+		.prediv_msk.value = 0x0,
+		.postdiv_msk.value = 0x0,
+		.itable = sc9860_adjustable_pll1_table,
+	},
+
+	/* add configures above this */
+	{
+		.name = NULL,
+	}
+};
+#endif
-- 
2.7.4

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-17 19:43     ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2017-05-17 19:43 UTC (permalink / raw)
  To: Chunyan Zhang
  Cc: Michael Turquette, Stephen Boyd, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon, xiaolong.zhang,
	Orson Zhai (翟京),
	geng.ren, linux-clk, Linux Kernel Mailing List, devicetree,
	Linux ARM, Lyra Zhang

On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
<chunyan.zhang@spreadtrum.com> wrote:
> This patch adds a new directory under the 'clock' for Spreadtrum platform,
> also bindings which document compatible strings and properties used for
> devicetree node of clocks on Spreadtrum SoCs.
>
> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
> ---
>  .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
>  .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
>  .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
>  .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
>  .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
>  5 files changed, 165 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> new file mode 100644
> index 0000000..476e315
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> @@ -0,0 +1,17 @@
> +Spreadtrum adjustable pll clock driver
> +
> +Required properties:
> +
> +- compatible : must be one of:
> +       "sprd,sc9836-adjustable-pll-clock"
> +       "sprd,sc9860-adjustable-pll-clock"
> +
> +Example:
> +       clk_mpll0: clk@40400024 {
> +               compatible = "sprd,sc9860-adjustable-pll-clock";
> +               #clock-cells = <0>;
> +               reg = <0 0x40400024 0 0x4>,
> +                     <0 0x40400028 0 0x4>;
> +               clocks = <&clk_mpll_gates 2>;
> +               clock-output-names = "clk_mpll0";
> +       };

The properties listed in the example must all be either
defined as "required" or "optional" properties and have a
description.

The reg property here is a bit odd, as it lists two consecutive
4-byte areas, and both are suspiciously close to a round
address (0x40400000), so I would guess that they are
in fact part of a clock controller with several registers.

If so, please define a node for the entire clock controller,
the DT description should reflect the design of the hardware
rather than the design of your device driver.

> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
> new file mode 100644
> index 0000000..a476eb6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
> @@ -0,0 +1,28 @@
> +Spreadtrum composite clock driver.
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +
> +- compatible:  should be "sprd,composite-clock"
> +
> +- sprd,mux-msk:        arbitrary bitmask for selecting clock input

"arbitrary" is not a good word to use in a specification document ;-)

Are there no constraints whatsoever on the allowed values? How
many bits are there?

> +- sprd,div-msk:        arbitrary bitmask for programming the divider,
> +               denominator of divider is the value consisted
> +               of these bits plus 1

This sounds like it should just be the denominator, you can add
or subtract one in the driver.

> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
> new file mode 100644
> index 0000000..f23ecb6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
> @@ -0,0 +1,73 @@
> +Spreadtrum gate clock driver
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Spreadtrum's SoCs often use one register to control more than one gate clocks.
> +Clock consumers can use index to get the correct gate clock.
> +
> +In Spreadtrum platform, some of gate clocks have three registers, respectively
> +used for controlling, setting and clearing gate clock, the addresses of
> +these three registers generally are <start>, <start + offset>, and
> +<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
> +size of gate clocks is either 0x3000 or 0x300. While for some historical issue
> +there also are some clocks which don't have independent set/clear registers.
> +Please see bellow for more specific information.
> +
> +Required properties:
> +
> +- compatible:  should be one of the following:
> +               "sprd,sc1000-gates-clock"
> +               - offset of the registers for setting gate is 0x1000
> +
> +               "sprd,sc100-gates-clock"
> +               - offset of the registers for setting gate is 0x100
> +
> +               "sprd,gates-clock"
> +               - for clocks without independent set/clear registers

I think the compatible value should refer to at least some more
specific product that uses these: I would guess that there are
some chips that spreadtrum has made that have clock gates
which are not compatible with this.

Can all three appear in the same chip, or would you always
have only one of them?

> +- reg: the first cell represents the address of this clock gate controller
> +       register, the second cell implies how is the offset of set/clear
> +       registers of this clock gate, like addressed in the head of this
> +       file
> +
> +optional properties:
> +
> +- clock-indices:       If the identifying number for the clocks in the node
> +                       is not linear from zero, this property is necessary
> +
> +Example:
> +
> +       clk_mpll_gates: clk@402b00b0 {
> +               compatible = "sprd,sc1000-gates-clock";
> +               #clock-cells = <1>;
> +               reg = <0 0x402b00b0 0 0x3000>;
> +               clocks = <&ext_26m>;
> +               clock-indices = <2>, <18>;
> +               clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
> +       };
>

For clock-output-names, please drop the "clk_" prefix from each
identifier, and maybe use '-' instead of '_' as the separator.

       Arnd

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-17 19:43     ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2017-05-17 19:43 UTC (permalink / raw)
  To: Chunyan Zhang
  Cc: Michael Turquette, Stephen Boyd, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon,
	xiaolong.zhang-lxIno14LUO0EEoCn2XhGlw,
	Orson Zhai (翟京),
	geng.ren-lxIno14LUO0EEoCn2XhGlw,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, Linux Kernel Mailing List,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Linux ARM, Lyra Zhang

On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
<chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org> wrote:
> This patch adds a new directory under the 'clock' for Spreadtrum platform,
> also bindings which document compatible strings and properties used for
> devicetree node of clocks on Spreadtrum SoCs.
>
> Signed-off-by: Chunyan Zhang <chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
> ---
>  .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
>  .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
>  .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
>  .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
>  .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
>  5 files changed, 165 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> new file mode 100644
> index 0000000..476e315
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> @@ -0,0 +1,17 @@
> +Spreadtrum adjustable pll clock driver
> +
> +Required properties:
> +
> +- compatible : must be one of:
> +       "sprd,sc9836-adjustable-pll-clock"
> +       "sprd,sc9860-adjustable-pll-clock"
> +
> +Example:
> +       clk_mpll0: clk@40400024 {
> +               compatible = "sprd,sc9860-adjustable-pll-clock";
> +               #clock-cells = <0>;
> +               reg = <0 0x40400024 0 0x4>,
> +                     <0 0x40400028 0 0x4>;
> +               clocks = <&clk_mpll_gates 2>;
> +               clock-output-names = "clk_mpll0";
> +       };

The properties listed in the example must all be either
defined as "required" or "optional" properties and have a
description.

The reg property here is a bit odd, as it lists two consecutive
4-byte areas, and both are suspiciously close to a round
address (0x40400000), so I would guess that they are
in fact part of a clock controller with several registers.

If so, please define a node for the entire clock controller,
the DT description should reflect the design of the hardware
rather than the design of your device driver.

> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
> new file mode 100644
> index 0000000..a476eb6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
> @@ -0,0 +1,28 @@
> +Spreadtrum composite clock driver.
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +
> +- compatible:  should be "sprd,composite-clock"
> +
> +- sprd,mux-msk:        arbitrary bitmask for selecting clock input

"arbitrary" is not a good word to use in a specification document ;-)

Are there no constraints whatsoever on the allowed values? How
many bits are there?

> +- sprd,div-msk:        arbitrary bitmask for programming the divider,
> +               denominator of divider is the value consisted
> +               of these bits plus 1

This sounds like it should just be the denominator, you can add
or subtract one in the driver.

> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
> new file mode 100644
> index 0000000..f23ecb6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
> @@ -0,0 +1,73 @@
> +Spreadtrum gate clock driver
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Spreadtrum's SoCs often use one register to control more than one gate clocks.
> +Clock consumers can use index to get the correct gate clock.
> +
> +In Spreadtrum platform, some of gate clocks have three registers, respectively
> +used for controlling, setting and clearing gate clock, the addresses of
> +these three registers generally are <start>, <start + offset>, and
> +<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
> +size of gate clocks is either 0x3000 or 0x300. While for some historical issue
> +there also are some clocks which don't have independent set/clear registers.
> +Please see bellow for more specific information.
> +
> +Required properties:
> +
> +- compatible:  should be one of the following:
> +               "sprd,sc1000-gates-clock"
> +               - offset of the registers for setting gate is 0x1000
> +
> +               "sprd,sc100-gates-clock"
> +               - offset of the registers for setting gate is 0x100
> +
> +               "sprd,gates-clock"
> +               - for clocks without independent set/clear registers

I think the compatible value should refer to at least some more
specific product that uses these: I would guess that there are
some chips that spreadtrum has made that have clock gates
which are not compatible with this.

Can all three appear in the same chip, or would you always
have only one of them?

> +- reg: the first cell represents the address of this clock gate controller
> +       register, the second cell implies how is the offset of set/clear
> +       registers of this clock gate, like addressed in the head of this
> +       file
> +
> +optional properties:
> +
> +- clock-indices:       If the identifying number for the clocks in the node
> +                       is not linear from zero, this property is necessary
> +
> +Example:
> +
> +       clk_mpll_gates: clk@402b00b0 {
> +               compatible = "sprd,sc1000-gates-clock";
> +               #clock-cells = <1>;
> +               reg = <0 0x402b00b0 0 0x3000>;
> +               clocks = <&ext_26m>;
> +               clock-indices = <2>, <18>;
> +               clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
> +       };
>

For clock-output-names, please drop the "clk_" prefix from each
identifier, and maybe use '-' instead of '_' as the separator.

       Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-17 19:43     ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2017-05-17 19:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
<chunyan.zhang@spreadtrum.com> wrote:
> This patch adds a new directory under the 'clock' for Spreadtrum platform,
> also bindings which document compatible strings and properties used for
> devicetree node of clocks on Spreadtrum SoCs.
>
> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
> ---
>  .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
>  .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
>  .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
>  .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
>  .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
>  5 files changed, 165 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> new file mode 100644
> index 0000000..476e315
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> @@ -0,0 +1,17 @@
> +Spreadtrum adjustable pll clock driver
> +
> +Required properties:
> +
> +- compatible : must be one of:
> +       "sprd,sc9836-adjustable-pll-clock"
> +       "sprd,sc9860-adjustable-pll-clock"
> +
> +Example:
> +       clk_mpll0: clk at 40400024 {
> +               compatible = "sprd,sc9860-adjustable-pll-clock";
> +               #clock-cells = <0>;
> +               reg = <0 0x40400024 0 0x4>,
> +                     <0 0x40400028 0 0x4>;
> +               clocks = <&clk_mpll_gates 2>;
> +               clock-output-names = "clk_mpll0";
> +       };

The properties listed in the example must all be either
defined as "required" or "optional" properties and have a
description.

The reg property here is a bit odd, as it lists two consecutive
4-byte areas, and both are suspiciously close to a round
address (0x40400000), so I would guess that they are
in fact part of a clock controller with several registers.

If so, please define a node for the entire clock controller,
the DT description should reflect the design of the hardware
rather than the design of your device driver.

> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
> new file mode 100644
> index 0000000..a476eb6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
> @@ -0,0 +1,28 @@
> +Spreadtrum composite clock driver.
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +
> +- compatible:  should be "sprd,composite-clock"
> +
> +- sprd,mux-msk:        arbitrary bitmask for selecting clock input

"arbitrary" is not a good word to use in a specification document ;-)

Are there no constraints whatsoever on the allowed values? How
many bits are there?

> +- sprd,div-msk:        arbitrary bitmask for programming the divider,
> +               denominator of divider is the value consisted
> +               of these bits plus 1

This sounds like it should just be the denominator, you can add
or subtract one in the driver.

> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
> new file mode 100644
> index 0000000..f23ecb6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
> @@ -0,0 +1,73 @@
> +Spreadtrum gate clock driver
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Spreadtrum's SoCs often use one register to control more than one gate clocks.
> +Clock consumers can use index to get the correct gate clock.
> +
> +In Spreadtrum platform, some of gate clocks have three registers, respectively
> +used for controlling, setting and clearing gate clock, the addresses of
> +these three registers generally are <start>, <start + offset>, and
> +<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
> +size of gate clocks is either 0x3000 or 0x300. While for some historical issue
> +there also are some clocks which don't have independent set/clear registers.
> +Please see bellow for more specific information.
> +
> +Required properties:
> +
> +- compatible:  should be one of the following:
> +               "sprd,sc1000-gates-clock"
> +               - offset of the registers for setting gate is 0x1000
> +
> +               "sprd,sc100-gates-clock"
> +               - offset of the registers for setting gate is 0x100
> +
> +               "sprd,gates-clock"
> +               - for clocks without independent set/clear registers

I think the compatible value should refer to at least some more
specific product that uses these: I would guess that there are
some chips that spreadtrum has made that have clock gates
which are not compatible with this.

Can all three appear in the same chip, or would you always
have only one of them?

> +- reg: the first cell represents the address of this clock gate controller
> +       register, the second cell implies how is the offset of set/clear
> +       registers of this clock gate, like addressed in the head of this
> +       file
> +
> +optional properties:
> +
> +- clock-indices:       If the identifying number for the clocks in the node
> +                       is not linear from zero, this property is necessary
> +
> +Example:
> +
> +       clk_mpll_gates: clk at 402b00b0 {
> +               compatible = "sprd,sc1000-gates-clock";
> +               #clock-cells = <1>;
> +               reg = <0 0x402b00b0 0 0x3000>;
> +               clocks = <&ext_26m>;
> +               clock-indices = <2>, <18>;
> +               clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
> +       };
>

For clock-output-names, please drop the "clk_" prefix from each
identifier, and maybe use '-' instead of '_' as the separator.

       Arnd

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
  2017-05-17 19:43     ` Arnd Bergmann
  (?)
@ 2017-05-18  8:47       ` Chunyan Zhang
  -1 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-18  8:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Chunyan Zhang, Michael Turquette, Stephen Boyd, Rob Herring,
	Mark Rutland, Catalin Marinas, Will Deacon, xiaolong.zhang,
	Orson Zhai (翟京),
	geng.ren, linux-clk, Linux Kernel Mailing List, devicetree,
	Linux ARM

Hi Arnd,

Many thanks for your time.

On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
> On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
> <chunyan.zhang@spreadtrum.com> wrote:
>> This patch adds a new directory under the 'clock' for Spreadtrum platform,
>> also bindings which document compatible strings and properties used for
>> devicetree node of clocks on Spreadtrum SoCs.
>>
>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
>> ---
>>  .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
>>  .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
>>  .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
>>  .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
>>  .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
>>  5 files changed, 165 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> new file mode 100644
>> index 0000000..476e315
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> @@ -0,0 +1,17 @@
>> +Spreadtrum adjustable pll clock driver
>> +
>> +Required properties:
>> +
>> +- compatible : must be one of:
>> +       "sprd,sc9836-adjustable-pll-clock"
>> +       "sprd,sc9860-adjustable-pll-clock"
>> +
>> +Example:
>> +       clk_mpll0: clk@40400024 {
>> +               compatible = "sprd,sc9860-adjustable-pll-clock";
>> +               #clock-cells = <0>;
>> +               reg = <0 0x40400024 0 0x4>,
>> +                     <0 0x40400028 0 0x4>;
>> +               clocks = <&clk_mpll_gates 2>;
>> +               clock-output-names = "clk_mpll0";
>> +       };
>
> The properties listed in the example must all be either
> defined as "required" or "optional" properties and have a
> description.

Since these common properties are documented in the common clock binding [1]

[1] Documentation/devicetree/bindings/clock/clock-bindings.txt

I will add explanation in this file like I do in other bindings
introduced in this patch, and will address 'reg' which probably is not
similar to the common usage.

>
> The reg property here is a bit odd, as it lists two consecutive
> 4-byte areas, and both are suspiciously close to a round
> address (0x40400000), so I would guess that they are
> in fact part of a clock controller with several registers.

They are PLL clock configuration registers.

Different PLL has different configurations which listed in pll_cfg.h,
and probably has different number of registers for storing
configurations, and on some Spreadtrum's SoCs PLL clock configuration
registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
(at least so far) are using the same driver.

>
> If so, please define a node for the entire clock controller,
> the DT description should reflect the design of the hardware
> rather than the design of your device driver.

I also realized our implementation might not be easy to be understood,
but I haven't thought out a better solution considering the hardware
limitation I explained above.

>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>> new file mode 100644
>> index 0000000..a476eb6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>> @@ -0,0 +1,28 @@
>> +Spreadtrum composite clock driver.
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +
>> +- compatible:  should be "sprd,composite-clock"
>> +
>> +- sprd,mux-msk:        arbitrary bitmask for selecting clock input
>
> "arbitrary" is not a good word to use in a specification document ;-)
>
> Are there no constraints whatsoever on the allowed values? How
> many bits are there?

This actually represents which bits in the register of this clock
should be used for selecting clock inputs, so it depends on how many
clock inputs this composite-clock includes.  Also different
composite-clock has different combination of clock inputs.

>
>> +- sprd,div-msk:        arbitrary bitmask for programming the divider,
>> +               denominator of divider is the value consisted
>> +               of these bits plus 1
>
> This sounds like it should just be the denominator, you can add
> or subtract one in the driver.

I will rephrase this description.  This represents which bits in the
register of this clock should be used for setting the value of
denominator (more exactly to say that the value plus 1 as
denominator).

>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>> new file mode 100644
>> index 0000000..f23ecb6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>> @@ -0,0 +1,73 @@
>> +Spreadtrum gate clock driver
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Spreadtrum's SoCs often use one register to control more than one gate clocks.
>> +Clock consumers can use index to get the correct gate clock.
>> +
>> +In Spreadtrum platform, some of gate clocks have three registers, respectively
>> +used for controlling, setting and clearing gate clock, the addresses of
>> +these three registers generally are <start>, <start + offset>, and
>> +<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
>> +size of gate clocks is either 0x3000 or 0x300. While for some historical issue
>> +there also are some clocks which don't have independent set/clear registers.
>> +Please see bellow for more specific information.
>> +
>> +Required properties:
>> +
>> +- compatible:  should be one of the following:
>> +               "sprd,sc1000-gates-clock"
>> +               - offset of the registers for setting gate is 0x1000
>> +
>> +               "sprd,sc100-gates-clock"
>> +               - offset of the registers for setting gate is 0x100
>> +
>> +               "sprd,gates-clock"
>> +               - for clocks without independent set/clear registers
>
> I think the compatible value should refer to at least some more
> specific product that uses these: I would guess that there are
> some chips that spreadtrum has made that have clock gates
> which are not compatible with this.

All chips that Spreadtrum has made so far have the similar h/w design
on clock gates, only the meaning of each bit in their registers is a
little different.

The 'sc1000-gates-clock' has dedicated registers respectively used for
setting and clearing gate clocks.

Like documented in this binding, 1000 means the address of registers
for setting is the address of gate clock control register plus 1000,
and clearing registers plus 1000 * 2, the similar with
'sc100-gates-clock'.

>
> Can all three appear in the same chip, or would you always
> have only one of them?

All these three kinds of gates indeed are being used on SC9860.

>
>> +- reg: the first cell represents the address of this clock gate controller
>> +       register, the second cell implies how is the offset of set/clear
>> +       registers of this clock gate, like addressed in the head of this
>> +       file
>> +
>> +optional properties:
>> +
>> +- clock-indices:       If the identifying number for the clocks in the node
>> +                       is not linear from zero, this property is necessary
>> +
>> +Example:
>> +
>> +       clk_mpll_gates: clk@402b00b0 {
>> +               compatible = "sprd,sc1000-gates-clock";
>> +               #clock-cells = <1>;
>> +               reg = <0 0x402b00b0 0 0x3000>;
>> +               clocks = <&ext_26m>;
>> +               clock-indices = <2>, <18>;
>> +               clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
>> +       };
>>
>
> For clock-output-names, please drop the "clk_" prefix from each
> identifier, and maybe use '-' instead of '_' as the separator.

Ok, will address this.

Thanks for the review,
Chunyan

>
>        Arnd

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-18  8:47       ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-18  8:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mark Rutland, devicetree, Orson Zhai (翟京),
	Catalin Marinas, Michael Turquette, Stephen Boyd,
	Linux Kernel Mailing List, Will Deacon, geng.ren, Rob Herring,
	Chunyan Zhang, linux-clk, Linux ARM, xiaolong.zhang

Hi Arnd,

Many thanks for your time.

On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
> On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
> <chunyan.zhang@spreadtrum.com> wrote:
>> This patch adds a new directory under the 'clock' for Spreadtrum platform,
>> also bindings which document compatible strings and properties used for
>> devicetree node of clocks on Spreadtrum SoCs.
>>
>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
>> ---
>>  .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
>>  .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
>>  .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
>>  .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
>>  .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
>>  5 files changed, 165 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> new file mode 100644
>> index 0000000..476e315
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> @@ -0,0 +1,17 @@
>> +Spreadtrum adjustable pll clock driver
>> +
>> +Required properties:
>> +
>> +- compatible : must be one of:
>> +       "sprd,sc9836-adjustable-pll-clock"
>> +       "sprd,sc9860-adjustable-pll-clock"
>> +
>> +Example:
>> +       clk_mpll0: clk@40400024 {
>> +               compatible = "sprd,sc9860-adjustable-pll-clock";
>> +               #clock-cells = <0>;
>> +               reg = <0 0x40400024 0 0x4>,
>> +                     <0 0x40400028 0 0x4>;
>> +               clocks = <&clk_mpll_gates 2>;
>> +               clock-output-names = "clk_mpll0";
>> +       };
>
> The properties listed in the example must all be either
> defined as "required" or "optional" properties and have a
> description.

Since these common properties are documented in the common clock binding [1]

[1] Documentation/devicetree/bindings/clock/clock-bindings.txt

I will add explanation in this file like I do in other bindings
introduced in this patch, and will address 'reg' which probably is not
similar to the common usage.

>
> The reg property here is a bit odd, as it lists two consecutive
> 4-byte areas, and both are suspiciously close to a round
> address (0x40400000), so I would guess that they are
> in fact part of a clock controller with several registers.

They are PLL clock configuration registers.

Different PLL has different configurations which listed in pll_cfg.h,
and probably has different number of registers for storing
configurations, and on some Spreadtrum's SoCs PLL clock configuration
registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
(at least so far) are using the same driver.

>
> If so, please define a node for the entire clock controller,
> the DT description should reflect the design of the hardware
> rather than the design of your device driver.

I also realized our implementation might not be easy to be understood,
but I haven't thought out a better solution considering the hardware
limitation I explained above.

>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>> new file mode 100644
>> index 0000000..a476eb6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>> @@ -0,0 +1,28 @@
>> +Spreadtrum composite clock driver.
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +
>> +- compatible:  should be "sprd,composite-clock"
>> +
>> +- sprd,mux-msk:        arbitrary bitmask for selecting clock input
>
> "arbitrary" is not a good word to use in a specification document ;-)
>
> Are there no constraints whatsoever on the allowed values? How
> many bits are there?

This actually represents which bits in the register of this clock
should be used for selecting clock inputs, so it depends on how many
clock inputs this composite-clock includes.  Also different
composite-clock has different combination of clock inputs.

>
>> +- sprd,div-msk:        arbitrary bitmask for programming the divider,
>> +               denominator of divider is the value consisted
>> +               of these bits plus 1
>
> This sounds like it should just be the denominator, you can add
> or subtract one in the driver.

I will rephrase this description.  This represents which bits in the
register of this clock should be used for setting the value of
denominator (more exactly to say that the value plus 1 as
denominator).

>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>> new file mode 100644
>> index 0000000..f23ecb6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>> @@ -0,0 +1,73 @@
>> +Spreadtrum gate clock driver
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Spreadtrum's SoCs often use one register to control more than one gate clocks.
>> +Clock consumers can use index to get the correct gate clock.
>> +
>> +In Spreadtrum platform, some of gate clocks have three registers, respectively
>> +used for controlling, setting and clearing gate clock, the addresses of
>> +these three registers generally are <start>, <start + offset>, and
>> +<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
>> +size of gate clocks is either 0x3000 or 0x300. While for some historical issue
>> +there also are some clocks which don't have independent set/clear registers.
>> +Please see bellow for more specific information.
>> +
>> +Required properties:
>> +
>> +- compatible:  should be one of the following:
>> +               "sprd,sc1000-gates-clock"
>> +               - offset of the registers for setting gate is 0x1000
>> +
>> +               "sprd,sc100-gates-clock"
>> +               - offset of the registers for setting gate is 0x100
>> +
>> +               "sprd,gates-clock"
>> +               - for clocks without independent set/clear registers
>
> I think the compatible value should refer to at least some more
> specific product that uses these: I would guess that there are
> some chips that spreadtrum has made that have clock gates
> which are not compatible with this.

All chips that Spreadtrum has made so far have the similar h/w design
on clock gates, only the meaning of each bit in their registers is a
little different.

The 'sc1000-gates-clock' has dedicated registers respectively used for
setting and clearing gate clocks.

Like documented in this binding, 1000 means the address of registers
for setting is the address of gate clock control register plus 1000,
and clearing registers plus 1000 * 2, the similar with
'sc100-gates-clock'.

>
> Can all three appear in the same chip, or would you always
> have only one of them?

All these three kinds of gates indeed are being used on SC9860.

>
>> +- reg: the first cell represents the address of this clock gate controller
>> +       register, the second cell implies how is the offset of set/clear
>> +       registers of this clock gate, like addressed in the head of this
>> +       file
>> +
>> +optional properties:
>> +
>> +- clock-indices:       If the identifying number for the clocks in the node
>> +                       is not linear from zero, this property is necessary
>> +
>> +Example:
>> +
>> +       clk_mpll_gates: clk@402b00b0 {
>> +               compatible = "sprd,sc1000-gates-clock";
>> +               #clock-cells = <1>;
>> +               reg = <0 0x402b00b0 0 0x3000>;
>> +               clocks = <&ext_26m>;
>> +               clock-indices = <2>, <18>;
>> +               clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
>> +       };
>>
>
> For clock-output-names, please drop the "clk_" prefix from each
> identifier, and maybe use '-' instead of '_' as the separator.

Ok, will address this.

Thanks for the review,
Chunyan

>
>        Arnd

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

* [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-18  8:47       ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-18  8:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd,

Many thanks for your time.

On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
> On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
> <chunyan.zhang@spreadtrum.com> wrote:
>> This patch adds a new directory under the 'clock' for Spreadtrum platform,
>> also bindings which document compatible strings and properties used for
>> devicetree node of clocks on Spreadtrum SoCs.
>>
>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
>> ---
>>  .../clock/sprd/sprd,adjustable-pll-clock.txt       | 17 +++++
>>  .../bindings/clock/sprd/sprd,composite-clock.txt   | 28 +++++++++
>>  .../bindings/clock/sprd/sprd,divider-clock.txt     | 24 +++++++
>>  .../bindings/clock/sprd/sprd,gates-clock.txt       | 73 ++++++++++++++++++++++
>>  .../bindings/clock/sprd/sprd,muxed-clock.txt       | 23 +++++++
>>  5 files changed, 165 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,divider-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>>  create mode 100644 Documentation/devicetree/bindings/clock/sprd/sprd,muxed-clock.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> new file mode 100644
>> index 0000000..476e315
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> @@ -0,0 +1,17 @@
>> +Spreadtrum adjustable pll clock driver
>> +
>> +Required properties:
>> +
>> +- compatible : must be one of:
>> +       "sprd,sc9836-adjustable-pll-clock"
>> +       "sprd,sc9860-adjustable-pll-clock"
>> +
>> +Example:
>> +       clk_mpll0: clk at 40400024 {
>> +               compatible = "sprd,sc9860-adjustable-pll-clock";
>> +               #clock-cells = <0>;
>> +               reg = <0 0x40400024 0 0x4>,
>> +                     <0 0x40400028 0 0x4>;
>> +               clocks = <&clk_mpll_gates 2>;
>> +               clock-output-names = "clk_mpll0";
>> +       };
>
> The properties listed in the example must all be either
> defined as "required" or "optional" properties and have a
> description.

Since these common properties are documented in the common clock binding [1]

[1] Documentation/devicetree/bindings/clock/clock-bindings.txt

I will add explanation in this file like I do in other bindings
introduced in this patch, and will address 'reg' which probably is not
similar to the common usage.

>
> The reg property here is a bit odd, as it lists two consecutive
> 4-byte areas, and both are suspiciously close to a round
> address (0x40400000), so I would guess that they are
> in fact part of a clock controller with several registers.

They are PLL clock configuration registers.

Different PLL has different configurations which listed in pll_cfg.h,
and probably has different number of registers for storing
configurations, and on some Spreadtrum's SoCs PLL clock configuration
registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
(at least so far) are using the same driver.

>
> If so, please define a node for the entire clock controller,
> the DT description should reflect the design of the hardware
> rather than the design of your device driver.

I also realized our implementation might not be easy to be understood,
but I haven't thought out a better solution considering the hardware
limitation I explained above.

>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>> new file mode 100644
>> index 0000000..a476eb6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,composite-clock.txt
>> @@ -0,0 +1,28 @@
>> +Spreadtrum composite clock driver.
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +
>> +- compatible:  should be "sprd,composite-clock"
>> +
>> +- sprd,mux-msk:        arbitrary bitmask for selecting clock input
>
> "arbitrary" is not a good word to use in a specification document ;-)
>
> Are there no constraints whatsoever on the allowed values? How
> many bits are there?

This actually represents which bits in the register of this clock
should be used for selecting clock inputs, so it depends on how many
clock inputs this composite-clock includes.  Also different
composite-clock has different combination of clock inputs.

>
>> +- sprd,div-msk:        arbitrary bitmask for programming the divider,
>> +               denominator of divider is the value consisted
>> +               of these bits plus 1
>
> This sounds like it should just be the denominator, you can add
> or subtract one in the driver.

I will rephrase this description.  This represents which bits in the
register of this clock should be used for setting the value of
denominator (more exactly to say that the value plus 1 as
denominator).

>
>> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>> new file mode 100644
>> index 0000000..f23ecb6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,gates-clock.txt
>> @@ -0,0 +1,73 @@
>> +Spreadtrum gate clock driver
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Spreadtrum's SoCs often use one register to control more than one gate clocks.
>> +Clock consumers can use index to get the correct gate clock.
>> +
>> +In Spreadtrum platform, some of gate clocks have three registers, respectively
>> +used for controlling, setting and clearing gate clock, the addresses of
>> +these three registers generally are <start>, <start + offset>, and
>> +<start + offset * 2>, and offset would be 0x1000 or 0x100, so the register
>> +size of gate clocks is either 0x3000 or 0x300. While for some historical issue
>> +there also are some clocks which don't have independent set/clear registers.
>> +Please see bellow for more specific information.
>> +
>> +Required properties:
>> +
>> +- compatible:  should be one of the following:
>> +               "sprd,sc1000-gates-clock"
>> +               - offset of the registers for setting gate is 0x1000
>> +
>> +               "sprd,sc100-gates-clock"
>> +               - offset of the registers for setting gate is 0x100
>> +
>> +               "sprd,gates-clock"
>> +               - for clocks without independent set/clear registers
>
> I think the compatible value should refer to at least some more
> specific product that uses these: I would guess that there are
> some chips that spreadtrum has made that have clock gates
> which are not compatible with this.

All chips that Spreadtrum has made so far have the similar h/w design
on clock gates, only the meaning of each bit in their registers is a
little different.

The 'sc1000-gates-clock' has dedicated registers respectively used for
setting and clearing gate clocks.

Like documented in this binding, 1000 means the address of registers
for setting is the address of gate clock control register plus 1000,
and clearing registers plus 1000 * 2, the similar with
'sc100-gates-clock'.

>
> Can all three appear in the same chip, or would you always
> have only one of them?

All these three kinds of gates indeed are being used on SC9860.

>
>> +- reg: the first cell represents the address of this clock gate controller
>> +       register, the second cell implies how is the offset of set/clear
>> +       registers of this clock gate, like addressed in the head of this
>> +       file
>> +
>> +optional properties:
>> +
>> +- clock-indices:       If the identifying number for the clocks in the node
>> +                       is not linear from zero, this property is necessary
>> +
>> +Example:
>> +
>> +       clk_mpll_gates: clk at 402b00b0 {
>> +               compatible = "sprd,sc1000-gates-clock";
>> +               #clock-cells = <1>;
>> +               reg = <0 0x402b00b0 0 0x3000>;
>> +               clocks = <&ext_26m>;
>> +               clock-indices = <2>, <18>;
>> +               clock-output-names = "clk_mpll0_gate", "clk_mpll1_gate";
>> +       };
>>
>
> For clock-output-names, please drop the "clk_" prefix from each
> identifier, and maybe use '-' instead of '_' as the separator.

Ok, will address this.

Thanks for the review,
Chunyan

>
>        Arnd

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
  2017-05-18  8:47       ` Chunyan Zhang
@ 2017-05-19  2:12         ` Stephen Boyd
  -1 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2017-05-19  2:12 UTC (permalink / raw)
  To: Chunyan Zhang
  Cc: Arnd Bergmann, Chunyan Zhang, Michael Turquette, Rob Herring,
	Mark Rutland, Catalin Marinas, Will Deacon, xiaolong.zhang,
	Orson Zhai (翟京),
	geng.ren, linux-clk, Linux Kernel Mailing List, devicetree,
	Linux ARM

On 05/18, Chunyan Zhang wrote:
> On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
> > <chunyan.zhang@spreadtrum.com> wrote:
> >> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> >> new file mode 100644
> >> index 0000000..476e315
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> >> @@ -0,0 +1,17 @@
> >> +Spreadtrum adjustable pll clock driver
> >> +
> >> +Required properties:
> >> +
> >> +- compatible : must be one of:
> >> +       "sprd,sc9836-adjustable-pll-clock"
> >> +       "sprd,sc9860-adjustable-pll-clock"
> >> +
> >> +Example:
> >> +       clk_mpll0: clk@40400024 {
> >> +               compatible = "sprd,sc9860-adjustable-pll-clock";
> >> +               #clock-cells = <0>;
> >> +               reg = <0 0x40400024 0 0x4>,
> >> +                     <0 0x40400028 0 0x4>;
> >> +               clocks = <&clk_mpll_gates 2>;
> >> +               clock-output-names = "clk_mpll0";
> >> +       };
> >
> > The properties listed in the example must all be either
> > defined as "required" or "optional" properties and have a
> > description.
> 
> Since these common properties are documented in the common clock binding [1]
> 
> [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> 
> I will add explanation in this file like I do in other bindings
> introduced in this patch, and will address 'reg' which probably is not
> similar to the common usage.
> 
> >
> > The reg property here is a bit odd, as it lists two consecutive
> > 4-byte areas, and both are suspiciously close to a round
> > address (0x40400000), so I would guess that they are
> > in fact part of a clock controller with several registers.
> 
> They are PLL clock configuration registers.
> 
> Different PLL has different configurations which listed in pll_cfg.h,
> and probably has different number of registers for storing
> configurations, and on some Spreadtrum's SoCs PLL clock configuration
> registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
> (at least so far) are using the same driver.
> 
> >
> > If so, please define a node for the entire clock controller,
> > the DT description should reflect the design of the hardware
> > rather than the design of your device driver.
> 
> I also realized our implementation might not be easy to be understood,
> but I haven't thought out a better solution considering the hardware
> limitation I explained above.

This binding is going down the wrong path. Please look at how
drivers such as sunxi-ng have done the binding in comparison to
original sunxi design. We don't put this level of detail into DT,
instead we put the details into the driver code and have clock
controller nodes in DT. A quick glance shows that this binding is
making a node per-clk, which is not going to be accepted.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-19  2:12         ` Stephen Boyd
  0 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2017-05-19  2:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/18, Chunyan Zhang wrote:
> On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
> > <chunyan.zhang@spreadtrum.com> wrote:
> >> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> >> new file mode 100644
> >> index 0000000..476e315
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
> >> @@ -0,0 +1,17 @@
> >> +Spreadtrum adjustable pll clock driver
> >> +
> >> +Required properties:
> >> +
> >> +- compatible : must be one of:
> >> +       "sprd,sc9836-adjustable-pll-clock"
> >> +       "sprd,sc9860-adjustable-pll-clock"
> >> +
> >> +Example:
> >> +       clk_mpll0: clk at 40400024 {
> >> +               compatible = "sprd,sc9860-adjustable-pll-clock";
> >> +               #clock-cells = <0>;
> >> +               reg = <0 0x40400024 0 0x4>,
> >> +                     <0 0x40400028 0 0x4>;
> >> +               clocks = <&clk_mpll_gates 2>;
> >> +               clock-output-names = "clk_mpll0";
> >> +       };
> >
> > The properties listed in the example must all be either
> > defined as "required" or "optional" properties and have a
> > description.
> 
> Since these common properties are documented in the common clock binding [1]
> 
> [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> 
> I will add explanation in this file like I do in other bindings
> introduced in this patch, and will address 'reg' which probably is not
> similar to the common usage.
> 
> >
> > The reg property here is a bit odd, as it lists two consecutive
> > 4-byte areas, and both are suspiciously close to a round
> > address (0x40400000), so I would guess that they are
> > in fact part of a clock controller with several registers.
> 
> They are PLL clock configuration registers.
> 
> Different PLL has different configurations which listed in pll_cfg.h,
> and probably has different number of registers for storing
> configurations, and on some Spreadtrum's SoCs PLL clock configuration
> registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
> (at least so far) are using the same driver.
> 
> >
> > If so, please define a node for the entire clock controller,
> > the DT description should reflect the design of the hardware
> > rather than the design of your device driver.
> 
> I also realized our implementation might not be easy to be understood,
> but I haven't thought out a better solution considering the hardware
> limitation I explained above.

This binding is going down the wrong path. Please look at how
drivers such as sunxi-ng have done the binding in comparison to
original sunxi design. We don't put this level of detail into DT,
instead we put the details into the driver code and have clock
controller nodes in DT. A quick glance shows that this binding is
making a node per-clk, which is not going to be accepted.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-24  2:48           ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-24  2:48 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Arnd Bergmann, Chunyan Zhang, Michael Turquette, Rob Herring,
	Mark Rutland, Catalin Marinas, Will Deacon, xiaolong.zhang,
	Orson Zhai (翟京),
	geng.ren, linux-clk, Linux Kernel Mailing List, devicetree,
	Linux ARM

Hi Stephen,

On 19 May 2017 at 10:12, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 05/18, Chunyan Zhang wrote:
>> On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
>> > On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
>> > <chunyan.zhang@spreadtrum.com> wrote:
>> >> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> >> new file mode 100644
>> >> index 0000000..476e315
>> >> --- /dev/null
>> >> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> >> @@ -0,0 +1,17 @@
>> >> +Spreadtrum adjustable pll clock driver
>> >> +
>> >> +Required properties:
>> >> +
>> >> +- compatible : must be one of:
>> >> +       "sprd,sc9836-adjustable-pll-clock"
>> >> +       "sprd,sc9860-adjustable-pll-clock"
>> >> +
>> >> +Example:
>> >> +       clk_mpll0: clk@40400024 {
>> >> +               compatible = "sprd,sc9860-adjustable-pll-clock";
>> >> +               #clock-cells = <0>;
>> >> +               reg = <0 0x40400024 0 0x4>,
>> >> +                     <0 0x40400028 0 0x4>;
>> >> +               clocks = <&clk_mpll_gates 2>;
>> >> +               clock-output-names = "clk_mpll0";
>> >> +       };
>> >
>> > The properties listed in the example must all be either
>> > defined as "required" or "optional" properties and have a
>> > description.
>>
>> Since these common properties are documented in the common clock binding [1]
>>
>> [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>>
>> I will add explanation in this file like I do in other bindings
>> introduced in this patch, and will address 'reg' which probably is not
>> similar to the common usage.
>>
>> >
>> > The reg property here is a bit odd, as it lists two consecutive
>> > 4-byte areas, and both are suspiciously close to a round
>> > address (0x40400000), so I would guess that they are
>> > in fact part of a clock controller with several registers.
>>
>> They are PLL clock configuration registers.
>>
>> Different PLL has different configurations which listed in pll_cfg.h,
>> and probably has different number of registers for storing
>> configurations, and on some Spreadtrum's SoCs PLL clock configuration
>> registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
>> (at least so far) are using the same driver.
>>
>> >
>> > If so, please define a node for the entire clock controller,
>> > the DT description should reflect the design of the hardware
>> > rather than the design of your device driver.
>>
>> I also realized our implementation might not be easy to be understood,
>> but I haven't thought out a better solution considering the hardware
>> limitation I explained above.
>
> This binding is going down the wrong path. Please look at how
> drivers such as sunxi-ng have done the binding in comparison to
> original sunxi design. We don't put this level of detail into DT,
> instead we put the details into the driver code and have clock
> controller nodes in DT. A quick glance shows that this binding is
> making a node per-clk, which is not going to be accepted.

I have had a look at sunxi-ng design, I will try to rewrite the driver
included in this patch-set, also DT and bindings.

Thanks for your comments,
Chunyan

>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project

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

* Re: [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-24  2:48           ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-24  2:48 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Arnd Bergmann, Chunyan Zhang, Michael Turquette, Rob Herring,
	Mark Rutland, Catalin Marinas, Will Deacon,
	xiaolong.zhang-lxIno14LUO0EEoCn2XhGlw,
	Orson Zhai (翟京),
	geng.ren-lxIno14LUO0EEoCn2XhGlw,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, Linux Kernel Mailing List,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Linux ARM

Hi Stephen,

On 19 May 2017 at 10:12, Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> On 05/18, Chunyan Zhang wrote:
>> On 18 May 2017 at 03:43, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
>> > On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
>> > <chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org> wrote:
>> >> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> >> new file mode 100644
>> >> index 0000000..476e315
>> >> --- /dev/null
>> >> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> >> @@ -0,0 +1,17 @@
>> >> +Spreadtrum adjustable pll clock driver
>> >> +
>> >> +Required properties:
>> >> +
>> >> +- compatible : must be one of:
>> >> +       "sprd,sc9836-adjustable-pll-clock"
>> >> +       "sprd,sc9860-adjustable-pll-clock"
>> >> +
>> >> +Example:
>> >> +       clk_mpll0: clk@40400024 {
>> >> +               compatible = "sprd,sc9860-adjustable-pll-clock";
>> >> +               #clock-cells = <0>;
>> >> +               reg = <0 0x40400024 0 0x4>,
>> >> +                     <0 0x40400028 0 0x4>;
>> >> +               clocks = <&clk_mpll_gates 2>;
>> >> +               clock-output-names = "clk_mpll0";
>> >> +       };
>> >
>> > The properties listed in the example must all be either
>> > defined as "required" or "optional" properties and have a
>> > description.
>>
>> Since these common properties are documented in the common clock binding [1]
>>
>> [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>>
>> I will add explanation in this file like I do in other bindings
>> introduced in this patch, and will address 'reg' which probably is not
>> similar to the common usage.
>>
>> >
>> > The reg property here is a bit odd, as it lists two consecutive
>> > 4-byte areas, and both are suspiciously close to a round
>> > address (0x40400000), so I would guess that they are
>> > in fact part of a clock controller with several registers.
>>
>> They are PLL clock configuration registers.
>>
>> Different PLL has different configurations which listed in pll_cfg.h,
>> and probably has different number of registers for storing
>> configurations, and on some Spreadtrum's SoCs PLL clock configuration
>> registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
>> (at least so far) are using the same driver.
>>
>> >
>> > If so, please define a node for the entire clock controller,
>> > the DT description should reflect the design of the hardware
>> > rather than the design of your device driver.
>>
>> I also realized our implementation might not be easy to be understood,
>> but I haven't thought out a better solution considering the hardware
>> limitation I explained above.
>
> This binding is going down the wrong path. Please look at how
> drivers such as sunxi-ng have done the binding in comparison to
> original sunxi design. We don't put this level of detail into DT,
> instead we put the details into the driver code and have clock
> controller nodes in DT. A quick glance shows that this binding is
> making a node per-clk, which is not going to be accepted.

I have had a look at sunxi-ng design, I will try to rewrite the driver
included in this patch-set, also DT and bindings.

Thanks for your comments,
Chunyan

>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/3] Documentation: add sprd clock bindings
@ 2017-05-24  2:48           ` Chunyan Zhang
  0 siblings, 0 replies; 23+ messages in thread
From: Chunyan Zhang @ 2017-05-24  2:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Stephen,

On 19 May 2017 at 10:12, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 05/18, Chunyan Zhang wrote:
>> On 18 May 2017 at 03:43, Arnd Bergmann <arnd@arndb.de> wrote:
>> > On Mon, May 15, 2017 at 10:35 AM, Chunyan Zhang
>> > <chunyan.zhang@spreadtrum.com> wrote:
>> >> diff --git a/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> >> new file mode 100644
>> >> index 0000000..476e315
>> >> --- /dev/null
>> >> +++ b/Documentation/devicetree/bindings/clock/sprd/sprd,adjustable-pll-clock.txt
>> >> @@ -0,0 +1,17 @@
>> >> +Spreadtrum adjustable pll clock driver
>> >> +
>> >> +Required properties:
>> >> +
>> >> +- compatible : must be one of:
>> >> +       "sprd,sc9836-adjustable-pll-clock"
>> >> +       "sprd,sc9860-adjustable-pll-clock"
>> >> +
>> >> +Example:
>> >> +       clk_mpll0: clk at 40400024 {
>> >> +               compatible = "sprd,sc9860-adjustable-pll-clock";
>> >> +               #clock-cells = <0>;
>> >> +               reg = <0 0x40400024 0 0x4>,
>> >> +                     <0 0x40400028 0 0x4>;
>> >> +               clocks = <&clk_mpll_gates 2>;
>> >> +               clock-output-names = "clk_mpll0";
>> >> +       };
>> >
>> > The properties listed in the example must all be either
>> > defined as "required" or "optional" properties and have a
>> > description.
>>
>> Since these common properties are documented in the common clock binding [1]
>>
>> [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>>
>> I will add explanation in this file like I do in other bindings
>> introduced in this patch, and will address 'reg' which probably is not
>> similar to the common usage.
>>
>> >
>> > The reg property here is a bit odd, as it lists two consecutive
>> > 4-byte areas, and both are suspiciously close to a round
>> > address (0x40400000), so I would guess that they are
>> > in fact part of a clock controller with several registers.
>>
>> They are PLL clock configuration registers.
>>
>> Different PLL has different configurations which listed in pll_cfg.h,
>> and probably has different number of registers for storing
>> configurations, and on some Spreadtrum's SoCs PLL clock configuration
>> registers aren't consecutive, but all PLLs on all Spreadtrum's SoCs
>> (at least so far) are using the same driver.
>>
>> >
>> > If so, please define a node for the entire clock controller,
>> > the DT description should reflect the design of the hardware
>> > rather than the design of your device driver.
>>
>> I also realized our implementation might not be easy to be understood,
>> but I haven't thought out a better solution considering the hardware
>> limitation I explained above.
>
> This binding is going down the wrong path. Please look at how
> drivers such as sunxi-ng have done the binding in comparison to
> original sunxi design. We don't put this level of detail into DT,
> instead we put the details into the driver code and have clock
> controller nodes in DT. A quick glance shows that this binding is
> making a node per-clk, which is not going to be accepted.

I have had a look at sunxi-ng design, I will try to rewrite the driver
included in this patch-set, also DT and bindings.

Thanks for your comments,
Chunyan

>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project

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

end of thread, other threads:[~2017-05-24  2:48 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-15  8:34 [PATCH 0/3] add clock driver for Spreadtrum platforms Chunyan Zhang
2017-05-15  8:34 ` Chunyan Zhang
2017-05-15  8:34 ` Chunyan Zhang
2017-05-15  8:35 ` [PATCH 1/3] arm64: dts: add SC9860 clock tree data Chunyan Zhang
2017-05-15  8:35   ` Chunyan Zhang
2017-05-15  8:35   ` Chunyan Zhang
2017-05-15  8:35 ` [PATCH 2/3] Documentation: add sprd clock bindings Chunyan Zhang
2017-05-15  8:35   ` Chunyan Zhang
2017-05-15  8:35   ` Chunyan Zhang
2017-05-17 19:43   ` Arnd Bergmann
2017-05-17 19:43     ` Arnd Bergmann
2017-05-17 19:43     ` Arnd Bergmann
2017-05-18  8:47     ` Chunyan Zhang
2017-05-18  8:47       ` Chunyan Zhang
2017-05-18  8:47       ` Chunyan Zhang
2017-05-19  2:12       ` Stephen Boyd
2017-05-19  2:12         ` Stephen Boyd
2017-05-24  2:48         ` Chunyan Zhang
2017-05-24  2:48           ` Chunyan Zhang
2017-05-24  2:48           ` Chunyan Zhang
2017-05-15  8:35 ` [PATCH 3/3] clk: Add common clock driver for Spreadtrum SoCs Chunyan Zhang
2017-05-15  8:35   ` Chunyan Zhang
2017-05-15  8:35   ` Chunyan Zhang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.