All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05  9:24 ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

Hello,

Hi6220 is one mobile solution of Hisilicon, this patchset contains
initial support for Hi6220 SoC and HiKey development board, which
is based on ARM Cortex A53 architecture. Initial support is minimal
and includes just the arch configuration, clock driver, device tree
configuration. 

Many peripheral drivers will be submitted later.

Any comments will be appreciated!

Thanks,  

Bintian Wang (3):
  arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
  clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  arm64: dts: Add dts files for Hisilicon Hi6220 SoC

 .../bindings/arm/hisilicon/hisilicon.txt           |   33 +++
 .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
 arch/arm64/Kconfig                                 |    6 +
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++
 arch/arm64/configs/defconfig                       |    1 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    4 +-
 drivers/clk/hisilicon/Kconfig                      |    5 +
 drivers/clk/hisilicon/Makefile                     |    1 +
 drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |   29 ++
 drivers/clk/hisilicon/clk.h                        |   17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
 include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
 17 files changed, 1095 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
 create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

-- 
1.7.9.5


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

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05  9:24 ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

Hello,

Hi6220 is one mobile solution of Hisilicon, this patchset contains
initial support for Hi6220 SoC and HiKey development board, which
is based on ARM Cortex A53 architecture. Initial support is minimal
and includes just the arch configuration, clock driver, device tree
configuration. 

Many peripheral drivers will be submitted later.

Any comments will be appreciated!

Thanks,  

Bintian Wang (3):
  arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
  clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  arm64: dts: Add dts files for Hisilicon Hi6220 SoC

 .../bindings/arm/hisilicon/hisilicon.txt           |   33 +++
 .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
 arch/arm64/Kconfig                                 |    6 +
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++
 arch/arm64/configs/defconfig                       |    1 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    4 +-
 drivers/clk/hisilicon/Kconfig                      |    5 +
 drivers/clk/hisilicon/Makefile                     |    1 +
 drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |   29 ++
 drivers/clk/hisilicon/clk.h                        |   17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
 include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
 17 files changed, 1095 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
 create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

-- 
1.7.9.5

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

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05  9:24 ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

Hi6220 is one mobile solution of Hisilicon, this patchset contains
initial support for Hi6220 SoC and HiKey development board, which
is based on ARM Cortex A53 architecture. Initial support is minimal
and includes just the arch configuration, clock driver, device tree
configuration. 

Many peripheral drivers will be submitted later.

Any comments will be appreciated!

Thanks,  

Bintian Wang (3):
  arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
  clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  arm64: dts: Add dts files for Hisilicon Hi6220 SoC

 .../bindings/arm/hisilicon/hisilicon.txt           |   33 +++
 .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
 arch/arm64/Kconfig                                 |    6 +
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++
 arch/arm64/configs/defconfig                       |    1 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    4 +-
 drivers/clk/hisilicon/Kconfig                      |    5 +
 drivers/clk/hisilicon/Makefile                     |    1 +
 drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |   29 ++
 drivers/clk/hisilicon/clk.h                        |   17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
 include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
 17 files changed, 1095 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
 create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

-- 
1.7.9.5

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

* [PATCH 1/3] arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
  2015-02-05  9:24 ` Bintian Wang
  (?)
@ 2015-02-05  9:24   ` Bintian Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

This patch introduces ARCH_HISI to enable Hisilicon SoC family in
Kconfig and defconfig.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Wei Xu <xuwei5@hisilicon.com>
---
 arch/arm64/Kconfig           |    5 +++++
 arch/arm64/configs/defconfig |    1 +
 2 files changed, 6 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b1f9a20..78cd41c8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -173,6 +173,11 @@ config ARCH_XGENE
 	help
 	  This enables support for AppliedMicro X-Gene SOC Family
 
+config ARCH_HISI
+	bool "Hisilicon SoC Family"
+	help
+	  This enables support for Hisilicon ARMv8 Family of SoCs.
+
 endmenu
 
 menu "Bus support"
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5376d90..a829774 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_THUNDER=y
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
+CONFIG_ARCH_HISI=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_XGENE=y
-- 
1.7.9.5


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

* [PATCH 1/3] arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

This patch introduces ARCH_HISI to enable Hisilicon SoC family in
Kconfig and defconfig.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Wei Xu <xuwei5@hisilicon.com>
---
 arch/arm64/Kconfig           |    5 +++++
 arch/arm64/configs/defconfig |    1 +
 2 files changed, 6 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b1f9a20..78cd41c8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -173,6 +173,11 @@ config ARCH_XGENE
 	help
 	  This enables support for AppliedMicro X-Gene SOC Family
 
+config ARCH_HISI
+	bool "Hisilicon SoC Family"
+	help
+	  This enables support for Hisilicon ARMv8 Family of SoCs.
+
 endmenu
 
 menu "Bus support"
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5376d90..a829774 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_THUNDER=y
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
+CONFIG_ARCH_HISI=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_XGENE=y
-- 
1.7.9.5

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

* [PATCH 1/3] arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel

This patch introduces ARCH_HISI to enable Hisilicon SoC family in
Kconfig and defconfig.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Wei Xu <xuwei5@hisilicon.com>
---
 arch/arm64/Kconfig           |    5 +++++
 arch/arm64/configs/defconfig |    1 +
 2 files changed, 6 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b1f9a20..78cd41c8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -173,6 +173,11 @@ config ARCH_XGENE
 	help
 	  This enables support for AppliedMicro X-Gene SOC Family
 
+config ARCH_HISI
+	bool "Hisilicon SoC Family"
+	help
+	  This enables support for Hisilicon ARMv8 Family of SoCs.
+
 endmenu
 
 menu "Bus support"
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5376d90..a829774 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_THUNDER=y
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
+CONFIG_ARCH_HISI=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_XGENE=y
-- 
1.7.9.5

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

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  2015-02-05  9:24 ` Bintian Wang
  (?)
@ 2015-02-05  9:24   ` Bintian Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

Add clock drivers for hi6220 SoC, this driver controls the SoC
registers to supply different clocks to different IPs in the SoC.

We add one divider clock for hi6220 because the divider in hi6220
also has a mask bit but it doesnot obey the rule defined by flag
"CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
left shift fixed bits (e.g. 16 bits), so we add this divider clock
to handle it.

This patch also enables this clock driver for ARCH_HISI and document
devicetree bindings.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
 .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
 arch/arm64/Kconfig                                 |    1 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    4 +-
 drivers/clk/hisilicon/Kconfig                      |    5 +
 drivers/clk/hisilicon/Makefile                     |    1 +
 drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |   29 ++
 drivers/clk/hisilicon/clk.h                        |   17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
 include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
 11 files changed, 815 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
new file mode 100644
index 0000000..a3ddda1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
@@ -0,0 +1,30 @@
+* Hisilicon Hi6220 Clock Controller
+
+The hi6220 clock controller generates and supplies clock to various
+controllers within the hi6220 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following:
+  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
+     power always on(AO) domain, it is the sub node of SoC power AO
+     controller in dts file.
+  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
+     system control domain, it is the sub node of SoC system controller
+     in dts file.
+  - "hisilicon,hi6220-clock-media" - controller for those clocks under
+     SoC media control domain, it is the sub node of SoC media controller
+     in dts file.
+  - "hisilicon,hi6220-clock-power" - controller for those clocks under
+     SoC power control domain, it is the sub node of SoC power controller
+     in dts file.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 78cd41c8..6efc3e3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -175,6 +175,7 @@ config ARCH_XGENE
 
 config ARCH_HISI
 	bool "Hisilicon SoC Family"
+	select COMMON_CLK_HI6220
 	help
 	  This enables support for Hisilicon ARMv8 Family of SoCs.
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3f44f29..b52c95c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -136,6 +136,8 @@ config COMMON_CLK_PXA
 
 source "drivers/clk/qcom/Kconfig"
 
+source "drivers/clk/hisilicon/Kconfig"
+
 endmenu
 
 source "drivers/clk/bcm/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..c58703b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
 obj-$(CONFIG_ARCH_BCM_MOBILE)		+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
-obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
+obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 0000000..e3ead46
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_CLK_HI6220
+	tristate "Hi6220 Clock Driver"
+	depends on OF && ARCH_HISI
+	help
+	  Build the Hisilicon Hi6220 clock driver based on the common clock framework.
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f..bbf0539 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -7,3 +7,4 @@ obj-y	+= clk.o clkgate-separated.o
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI6220)	+= clkdivider-hi6220.o clk-hi6220.o
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
new file mode 100644
index 0000000..01d0c46
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon Hi6220 clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+#include "clk.h"
+
+
+/* clocks in AO (always on) controller */
+static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
+	{ HI6220_REF32K,	"ref32k",	NULL, CLK_IS_ROOT, 32764,     },
+	{ HI6220_CLK_TCXO,	"clk_tcxo",	NULL, CLK_IS_ROOT, 19200000,  },
+	{ HI6220_MMC1_PAD,	"mmc1_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC2_PAD,	"mmc2_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC0_PAD,	"mmc0_pad",	NULL, CLK_IS_ROOT, 200000000, },
+	{ HI6220_PLL_BBP,	"bbppll0",	NULL, CLK_IS_ROOT, 245760000, },
+	{ HI6220_PLL_GPU,	"gpupll",	NULL, CLK_IS_ROOT, 1000000000,},
+	{ HI6220_PLL1_DDR,	"ddrpll1",	NULL, CLK_IS_ROOT, 1066000000,},
+	{ HI6220_PLL_SYS,	"syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_SYS_MEDIA,	"media_syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_DDR_SRC,	"ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_MEDIA,	"media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
+	{ HI6220_PLL_DDR,	"ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
+};
+
+static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
+	{ HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
+	{ HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
+	{ HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
+	{ HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
+	{ HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
+	{ HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
+};
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
+	{ HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
+	{ HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
+	{ HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
+	{ HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
+	{ HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
+	{ HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
+	{ HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
+	{ HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
+	{ HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
+	{ HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
+	{ HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
+	{ HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
+	{ HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
+};
+
+static void __init hi6220_clk_ao_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
+				ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
+
+	hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
+				ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
+				ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
+
+
+/* clocks in sysctrl */
+static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
+static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
+static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
+static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
+static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
+static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
+static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
+static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
+static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
+static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
+	{ HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
+	{ HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
+	{ HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
+	{ HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
+	{ HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
+	{ HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
+	{ HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
+	{ HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
+	{ HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
+	{ HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
+	{ HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
+	{ HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
+	{ HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
+	{ HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
+	{ HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
+	{ HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
+	{ HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
+	{ HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
+	{ HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
+	{ HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
+	{ HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
+	{ HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
+	{ HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
+	{ HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
+	{ HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
+	{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
+	{ HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
+	{ HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
+	{ HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
+	{ HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
+	{ HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
+	{ HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
+	{ HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
+	{ HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
+	{ HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
+};
+
+static void __init hi6220_clk_sys_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
+			ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_sys,
+			ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_sys,
+			ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
+
+
+/* clocks in media controller */
+static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
+static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
+static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
+	{ HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
+	{ HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
+	{ HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
+	{ HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
+	{ HI6220_ADE_CORE,	 "ade_core",	     "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
+	{ HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
+	{ HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
+	{ HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
+	{ HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
+	{ HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
+	{ HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
+	{ HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
+	{ HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
+	{ HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
+	{ HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
+	{ HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
+	{ HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
+	{ HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
+	{ HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
+	{ HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
+	{ HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
+	{ HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
+	{ HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
+};
+
+static void __init hi6220_clk_media_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
+				ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_media,
+				ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_media,
+				ARRAY_SIZE(hi6220_div_clks_media), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
+
+
+/* clocks in pmctrl */
+static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
+	{ HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
+	{ HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
+	{ HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
+	{ HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
+	{ HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
+	{ HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
+	{ HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
+};
+
+static void __init hi6220_clk_power_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate(hi6220_gate_clks_power,
+				ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_power,
+				ARRAY_SIZE(hi6220_div_clks_power), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84..5d2305c 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
+					  int nums, struct hisi_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = hi6220_register_clkdiv(NULL, clks[i].name,
+						clks[i].parent_name,
+						clks[i].flags,
+						base + clks[i].offset,
+						clks[i].shift,
+						clks[i].width,
+						clks[i].mask_bit,
+						&hisi_clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+
+		if (clks[i].alias)
+			clk_register_clkdev(clk, clks[i].alias, NULL);
+
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ff..462a570 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -79,6 +79,18 @@ struct hisi_divider_clock {
 	const char		*alias;
 };
 
+struct hi6220_divider_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			shift;
+	u8			width;
+	u32			mask_bit;
+	const char		*alias;
+};
+
 struct hisi_gate_clock {
 	unsigned int		id;
 	const char		*name;
@@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
 				u8, spinlock_t *);
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
@@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
+					int, struct hisi_clock_data *);
 #endif	/* __HISI_CLK_H */
diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
new file mode 100644
index 0000000..9e3825b
--- /dev/null
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -0,0 +1,273 @@
+/*
+ * Hisilicon hi6220 SoC divider clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#define div_mask(width)	((1 << (width)) - 1)
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+/**
+ * struct hi6220_clk_divider - divider clock for hi6220
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @mask:	mask for setting divider rate
+ * @table:	the div table that the divider supports
+ * @lock:	register lock
+ */
+struct hi6220_clk_divider {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u32		mask;
+	const struct clk_div_table *table;
+	spinlock_t	*lock;
+};
+
+#define to_hi6220_clk_divider(_hw)	\
+	container_of(_hw, struct hi6220_clk_divider, hw)
+
+static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
+{
+	unsigned int maxdiv = 0;
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div > maxdiv)
+			maxdiv = clkt->div;
+	return maxdiv;
+}
+
+static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
+					unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+
+	return 0;
+}
+
+static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
+					unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	unsigned int div, val;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	val = readl_relaxed(dclk->reg) >> dclk->shift;
+	val &= div_mask(dclk->width);
+
+	div = hi6220_get_table_div(dclk->table, val);
+	if (!div) {
+		pr_warn("%s: Invalid divisor for clock %s\n", __func__,
+			   __clk_get_name(hw->clk));
+		return parent_rate;
+	}
+
+	return parent_rate / div;
+}
+
+static bool hi6220_is_valid_div(const struct clk_div_table *table,
+				unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *best_parent_rate)
+{
+	unsigned int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+	struct clk *clk_parent = __clk_get_parent(hw->clk);
+
+	maxdiv = hi6220_get_table_maxdiv(dclk->table);
+
+	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+		parent_rate = *best_parent_rate;
+		bestdiv = DIV_ROUND_UP(parent_rate, rate);
+		bestdiv = (bestdiv == 0) ? 1 : bestdiv;
+		bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
+		return bestdiv;
+	}
+
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		if (!hi6220_is_valid_div(dclk->table, i))
+			continue;
+		parent_rate = __clk_round_rate(clk_parent,
+					MULT_ROUND_UP(rate, i));
+		now = parent_rate / i;
+		if (now <= rate && now > best) {
+			bestdiv = i;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = hi6220_get_table_maxdiv(dclk->table);
+		*best_parent_rate = __clk_round_rate(clk_parent, 1);
+	}
+
+	return bestdiv;
+}
+
+static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *prate)
+{
+	int div;
+
+	if (!rate)
+		rate = 1;
+
+	div = hi6220_clkdiv_bestdiv(hw, rate, prate);
+
+	return *prate / div;
+}
+
+static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	unsigned int div, value;
+	unsigned long flags = 0;
+	u32 data;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	div = parent_rate / rate;
+
+	if (!hi6220_is_valid_div(dclk->table, div))
+		return -EINVAL;
+
+	value = hi6220_get_table_val(dclk->table, div);
+
+	if (value > div_mask(dclk->width))
+		value = div_mask(dclk->width);
+
+	if (dclk->lock)
+		spin_lock_irqsave(dclk->lock, flags);
+
+	data = readl_relaxed(dclk->reg);
+	data &= ~(div_mask(dclk->width) << dclk->shift);
+	data |= value << dclk->shift;
+	data |= dclk->mask;
+
+	writel_relaxed(data, dclk->reg);
+
+	if (dclk->lock)
+		spin_unlock_irqrestore(dclk->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops hi6220_clkdiv_ops = {
+	.recalc_rate = hi6220_clkdiv_recalc_rate,
+	.round_rate = hi6220_clkdiv_round_rate,
+	.set_rate = hi6220_clkdiv_set_rate,
+};
+
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
+{
+	struct hi6220_clk_divider *div;
+	struct clk *clk;
+	struct clk_init_data init;
+	struct clk_div_table *table;
+	u32 max_div, min_div;
+	int i;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
+	if (!div) {
+		pr_err("%s: could not allocate divider clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Init the divider table */
+	max_div = div_mask(width) + 1;
+	min_div = 1;
+
+	table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
+	if (!table) {
+		kfree(div);
+		pr_err("%s: failed to alloc divider table!\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < max_div; i++) {
+		table[i].div = min_div + i;
+		table[i].val = table[i].div - 1;
+	}
+
+	init.name = name;
+	init.ops = &hi6220_clkdiv_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	/* struct hi6220_clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->mask = mask_bit ? BIT(mask_bit) : 0;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	clk = clk_register(dev, &div->hw);
+
+	if (IS_ERR(clk)) {
+		kfree(table);
+		kfree(div);
+	}
+
+	return clk;
+}
diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
new file mode 100644
index 0000000..05033e7
--- /dev/null
+++ b/include/dt-bindings/clock/hi6220-clock.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_HI6220_H
+#define __DT_BINDINGS_CLOCK_HI6220_H
+
+/* clk in AO (always on) controller */
+#define HI6220_NONE_CLOCK	0
+
+/* fixed rate clocks */
+#define HI6220_REF32K		1
+#define HI6220_CLK_TCXO		2
+#define HI6220_MMC1_PAD		3
+#define HI6220_MMC2_PAD		4
+#define HI6220_MMC0_PAD		5
+#define HI6220_PLL_BBP		6
+#define HI6220_PLL_GPU		7
+#define HI6220_PLL1_DDR		8
+#define HI6220_PLL_SYS		9
+#define HI6220_PLL_SYS_MEDIA	10
+#define HI6220_DDR_SRC		11
+#define HI6220_PLL_MEDIA	12
+#define HI6220_PLL_DDR		13
+
+/* fixed factor clocks */
+#define HI6220_300M		16
+#define HI6220_150M		17
+#define HI6220_PICOPHY_SRC	18
+#define HI6220_MMC0_SRC_SEL	19
+#define HI6220_MMC1_SRC_SEL	20
+#define HI6220_MMC2_SRC_SEL	21
+#define HI6220_VPU_CODEC	22
+#define HI6220_MMC0_SMP		23
+#define HI6220_MMC1_SMP		24
+#define HI6220_MMC2_SMP		25
+
+/* gate clocks */
+#define HI6220_WDT0_PCLK	28
+#define HI6220_WDT1_PCLK	29
+#define HI6220_WDT2_PCLK	30
+#define HI6220_TIMER0_PCLK	31
+#define HI6220_TIMER1_PCLK	32
+#define HI6220_TIMER2_PCLK	33
+#define HI6220_TIMER3_PCLK	34
+#define HI6220_TIMER4_PCLK	35
+#define HI6220_TIMER5_PCLK	36
+#define HI6220_TIMER6_PCLK	37
+#define HI6220_TIMER7_PCLK	38
+#define HI6220_TIMER8_PCLK	39
+#define HI6220_UART0_PCLK	40
+
+#define HI6220_AO_NR_CLKS	48
+
+/* clk in systrl */
+/* gate clock */
+#define HI6220_MMC0_CLK		1
+#define HI6220_MMC0_CIUCLK	2
+#define HI6220_MMC1_CLK		3
+#define HI6220_MMC1_CIUCLK	4
+#define HI6220_MMC2_CLK		5
+#define HI6220_MMC2_CIUCLK	6
+#define HI6220_USBOTG_HCLK	7
+#define HI6220_CLK_PICOPHY	8
+#define HI6220_HIFI		9
+#define HI6220_DACODEC_PCLK	10
+#define HI6220_EDMAC_ACLK	11
+#define HI6220_CS_ATB		12
+#define HI6220_I2C0_CLK		13
+#define HI6220_I2C1_CLK		14
+#define HI6220_I2C2_CLK		15
+#define HI6220_I2C3_CLK		16
+#define HI6220_UART1_PCLK	17
+#define HI6220_UART2_PCLK	18
+#define HI6220_UART3_PCLK	19
+#define HI6220_UART4_PCLK	20
+#define HI6220_SPI_CLK		21
+#define HI6220_MMU_CLK		22
+#define HI6220_HIFI_SEL		23
+#define HI6220_MMC0_SYSPLL	24
+#define HI6220_MMC1_SYSPLL	25
+#define HI6220_MMC2_SYSPLL	26
+#define HI6220_MMC0_SEL		27
+#define HI6220_MMC1_SEL		28
+#define HI6220_BBPPLL_SEL	29
+#define HI6220_MEDIA_PLL_SRC	30
+#define HI6220_MMC2_SEL		31
+#define HI6220_CS_ATB_SYSPLL	32
+
+/* mux clocks */
+#define HI6220_MMC0_SRC		35
+#define HI6220_MMC0_SMP_IN	36
+#define HI6220_MMC1_SRC		37
+#define HI6220_MMC1_SMP_IN	38
+#define HI6220_MMC2_SRC		39
+#define HI6220_MMC2_SMP_IN	40
+#define HI6220_HIFI_SRC		41
+#define HI6220_UART1_SRC	42
+#define HI6220_UART2_SRC	43
+#define HI6220_UART3_SRC	44
+#define HI6220_UART4_SRC	45
+#define HI6220_MMC0_MUX0	46
+#define HI6220_MMC1_MUX0	47
+#define HI6220_MMC2_MUX0	48
+#define HI6220_MMC0_MUX1	49
+#define HI6220_MMC1_MUX1	50
+#define HI6220_MMC2_MUX1	51
+
+/* divider clocks */
+#define HI6220_CLK_BUS		54
+#define HI6220_MMC0_DIV		55
+#define HI6220_MMC1_DIV		56
+#define HI6220_MMC2_DIV		57
+#define HI6220_HIFI_DIV		58
+#define HI6220_BBPPLL0_DIV	59
+#define HI6220_CS_DAPB		60
+#define HI6220_CS_ATB_DIV	61
+
+#define HI6220_SYS_NR_CLKS	64
+
+/* clk in media controller */
+/* gate clocks */
+#define HI6220_DSI_PCLK		1
+#define HI6220_G3D_PCLK		2
+#define HI6220_ACLK_CODEC_VPU	3
+#define HI6220_ISP_SCLK		4
+#define HI6220_ADE_CORE		5
+#define HI6220_MED_MMU		6
+#define HI6220_CFG_CSI4PHY	7
+#define HI6220_CFG_CSI2PHY	8
+#define HI6220_ISP_SCLK_GATE	9
+#define HI6220_ISP_SCLK_GATE1	10
+#define HI6220_ADE_CORE_GATE	11
+#define HI6220_CODEC_VPU_GATE	12
+#define HI6220_MED_SYSPLL	13
+
+/* mux clocks */
+#define HI6220_1440_1200	20
+#define HI6220_1000_1200	21
+#define HI6220_1000_1440	22
+
+/* divider clocks */
+#define HI6220_CODEC_JPEG	30
+#define HI6220_ISP_SCLK_SRC	31
+#define HI6220_ISP_SCLK1	32
+#define HI6220_ADE_CORE_SRC	33
+#define HI6220_ADE_PIX_SRC	34
+#define HI6220_G3D_CLK		35
+#define HI6220_CODEC_VPU_SRC	36
+
+#define HI6220_MEDIA_NR_CLKS	40
+
+/* clk in power controller */
+/* gate clocks */
+#define HI6220_PLL_GPU_GATE	1
+#define HI6220_PLL1_DDR_GATE	2
+#define HI6220_PLL_DDR_GATE	3
+#define HI6220_PLL_MEDIA_GATE	4
+#define HI6220_PLL0_BBP_GATE	5
+
+/* divider clocks */
+#define HI6220_DDRC_SRC		10
+#define HI6220_DDRC_AXI1	11
+
+#define HI6220_POWER_NR_CLKS	16
+#endif
-- 
1.7.9.5


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

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

Add clock drivers for hi6220 SoC, this driver controls the SoC
registers to supply different clocks to different IPs in the SoC.

We add one divider clock for hi6220 because the divider in hi6220
also has a mask bit but it doesnot obey the rule defined by flag
"CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
left shift fixed bits (e.g. 16 bits), so we add this divider clock
to handle it.

This patch also enables this clock driver for ARCH_HISI and document
devicetree bindings.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
 .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
 arch/arm64/Kconfig                                 |    1 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    4 +-
 drivers/clk/hisilicon/Kconfig                      |    5 +
 drivers/clk/hisilicon/Makefile                     |    1 +
 drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |   29 ++
 drivers/clk/hisilicon/clk.h                        |   17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
 include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
 11 files changed, 815 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
new file mode 100644
index 0000000..a3ddda1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
@@ -0,0 +1,30 @@
+* Hisilicon Hi6220 Clock Controller
+
+The hi6220 clock controller generates and supplies clock to various
+controllers within the hi6220 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following:
+  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
+     power always on(AO) domain, it is the sub node of SoC power AO
+     controller in dts file.
+  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
+     system control domain, it is the sub node of SoC system controller
+     in dts file.
+  - "hisilicon,hi6220-clock-media" - controller for those clocks under
+     SoC media control domain, it is the sub node of SoC media controller
+     in dts file.
+  - "hisilicon,hi6220-clock-power" - controller for those clocks under
+     SoC power control domain, it is the sub node of SoC power controller
+     in dts file.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 78cd41c8..6efc3e3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -175,6 +175,7 @@ config ARCH_XGENE
 
 config ARCH_HISI
 	bool "Hisilicon SoC Family"
+	select COMMON_CLK_HI6220
 	help
 	  This enables support for Hisilicon ARMv8 Family of SoCs.
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3f44f29..b52c95c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -136,6 +136,8 @@ config COMMON_CLK_PXA
 
 source "drivers/clk/qcom/Kconfig"
 
+source "drivers/clk/hisilicon/Kconfig"
+
 endmenu
 
 source "drivers/clk/bcm/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..c58703b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
 obj-$(CONFIG_ARCH_BCM_MOBILE)		+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
-obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
+obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 0000000..e3ead46
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_CLK_HI6220
+	tristate "Hi6220 Clock Driver"
+	depends on OF && ARCH_HISI
+	help
+	  Build the Hisilicon Hi6220 clock driver based on the common clock framework.
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f..bbf0539 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -7,3 +7,4 @@ obj-y	+= clk.o clkgate-separated.o
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI6220)	+= clkdivider-hi6220.o clk-hi6220.o
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
new file mode 100644
index 0000000..01d0c46
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon Hi6220 clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+#include "clk.h"
+
+
+/* clocks in AO (always on) controller */
+static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
+	{ HI6220_REF32K,	"ref32k",	NULL, CLK_IS_ROOT, 32764,     },
+	{ HI6220_CLK_TCXO,	"clk_tcxo",	NULL, CLK_IS_ROOT, 19200000,  },
+	{ HI6220_MMC1_PAD,	"mmc1_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC2_PAD,	"mmc2_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC0_PAD,	"mmc0_pad",	NULL, CLK_IS_ROOT, 200000000, },
+	{ HI6220_PLL_BBP,	"bbppll0",	NULL, CLK_IS_ROOT, 245760000, },
+	{ HI6220_PLL_GPU,	"gpupll",	NULL, CLK_IS_ROOT, 1000000000,},
+	{ HI6220_PLL1_DDR,	"ddrpll1",	NULL, CLK_IS_ROOT, 1066000000,},
+	{ HI6220_PLL_SYS,	"syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_SYS_MEDIA,	"media_syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_DDR_SRC,	"ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_MEDIA,	"media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
+	{ HI6220_PLL_DDR,	"ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
+};
+
+static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
+	{ HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
+	{ HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
+	{ HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
+	{ HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
+	{ HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
+	{ HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
+};
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
+	{ HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
+	{ HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
+	{ HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
+	{ HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
+	{ HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
+	{ HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
+	{ HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
+	{ HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
+	{ HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
+	{ HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
+	{ HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
+	{ HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
+	{ HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
+};
+
+static void __init hi6220_clk_ao_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
+				ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
+
+	hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
+				ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
+				ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
+
+
+/* clocks in sysctrl */
+static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
+static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
+static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
+static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
+static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
+static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
+static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
+static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
+static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
+static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
+	{ HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
+	{ HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
+	{ HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
+	{ HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
+	{ HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
+	{ HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
+	{ HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
+	{ HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
+	{ HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
+	{ HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
+	{ HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
+	{ HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
+	{ HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
+	{ HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
+	{ HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
+	{ HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
+	{ HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
+	{ HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
+	{ HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
+	{ HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
+	{ HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
+	{ HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
+	{ HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
+	{ HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
+	{ HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
+	{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
+	{ HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
+	{ HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
+	{ HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
+	{ HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
+	{ HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
+	{ HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
+	{ HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
+	{ HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
+	{ HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
+};
+
+static void __init hi6220_clk_sys_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
+			ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_sys,
+			ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_sys,
+			ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
+
+
+/* clocks in media controller */
+static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
+static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
+static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
+	{ HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
+	{ HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
+	{ HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
+	{ HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
+	{ HI6220_ADE_CORE,	 "ade_core",	     "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
+	{ HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
+	{ HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
+	{ HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
+	{ HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
+	{ HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
+	{ HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
+	{ HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
+	{ HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
+	{ HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
+	{ HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
+	{ HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
+	{ HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
+	{ HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
+	{ HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
+	{ HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
+	{ HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
+	{ HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
+	{ HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
+};
+
+static void __init hi6220_clk_media_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
+				ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_media,
+				ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_media,
+				ARRAY_SIZE(hi6220_div_clks_media), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
+
+
+/* clocks in pmctrl */
+static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
+	{ HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
+	{ HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
+	{ HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
+	{ HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
+	{ HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
+	{ HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
+	{ HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
+};
+
+static void __init hi6220_clk_power_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate(hi6220_gate_clks_power,
+				ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_power,
+				ARRAY_SIZE(hi6220_div_clks_power), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84..5d2305c 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
+					  int nums, struct hisi_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = hi6220_register_clkdiv(NULL, clks[i].name,
+						clks[i].parent_name,
+						clks[i].flags,
+						base + clks[i].offset,
+						clks[i].shift,
+						clks[i].width,
+						clks[i].mask_bit,
+						&hisi_clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+
+		if (clks[i].alias)
+			clk_register_clkdev(clk, clks[i].alias, NULL);
+
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ff..462a570 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -79,6 +79,18 @@ struct hisi_divider_clock {
 	const char		*alias;
 };
 
+struct hi6220_divider_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			shift;
+	u8			width;
+	u32			mask_bit;
+	const char		*alias;
+};
+
 struct hisi_gate_clock {
 	unsigned int		id;
 	const char		*name;
@@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
 				u8, spinlock_t *);
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
@@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
+					int, struct hisi_clock_data *);
 #endif	/* __HISI_CLK_H */
diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
new file mode 100644
index 0000000..9e3825b
--- /dev/null
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -0,0 +1,273 @@
+/*
+ * Hisilicon hi6220 SoC divider clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#define div_mask(width)	((1 << (width)) - 1)
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+/**
+ * struct hi6220_clk_divider - divider clock for hi6220
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @mask:	mask for setting divider rate
+ * @table:	the div table that the divider supports
+ * @lock:	register lock
+ */
+struct hi6220_clk_divider {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u32		mask;
+	const struct clk_div_table *table;
+	spinlock_t	*lock;
+};
+
+#define to_hi6220_clk_divider(_hw)	\
+	container_of(_hw, struct hi6220_clk_divider, hw)
+
+static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
+{
+	unsigned int maxdiv = 0;
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div > maxdiv)
+			maxdiv = clkt->div;
+	return maxdiv;
+}
+
+static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
+					unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+
+	return 0;
+}
+
+static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
+					unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	unsigned int div, val;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	val = readl_relaxed(dclk->reg) >> dclk->shift;
+	val &= div_mask(dclk->width);
+
+	div = hi6220_get_table_div(dclk->table, val);
+	if (!div) {
+		pr_warn("%s: Invalid divisor for clock %s\n", __func__,
+			   __clk_get_name(hw->clk));
+		return parent_rate;
+	}
+
+	return parent_rate / div;
+}
+
+static bool hi6220_is_valid_div(const struct clk_div_table *table,
+				unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *best_parent_rate)
+{
+	unsigned int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+	struct clk *clk_parent = __clk_get_parent(hw->clk);
+
+	maxdiv = hi6220_get_table_maxdiv(dclk->table);
+
+	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+		parent_rate = *best_parent_rate;
+		bestdiv = DIV_ROUND_UP(parent_rate, rate);
+		bestdiv = (bestdiv == 0) ? 1 : bestdiv;
+		bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
+		return bestdiv;
+	}
+
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		if (!hi6220_is_valid_div(dclk->table, i))
+			continue;
+		parent_rate = __clk_round_rate(clk_parent,
+					MULT_ROUND_UP(rate, i));
+		now = parent_rate / i;
+		if (now <= rate && now > best) {
+			bestdiv = i;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = hi6220_get_table_maxdiv(dclk->table);
+		*best_parent_rate = __clk_round_rate(clk_parent, 1);
+	}
+
+	return bestdiv;
+}
+
+static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *prate)
+{
+	int div;
+
+	if (!rate)
+		rate = 1;
+
+	div = hi6220_clkdiv_bestdiv(hw, rate, prate);
+
+	return *prate / div;
+}
+
+static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	unsigned int div, value;
+	unsigned long flags = 0;
+	u32 data;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	div = parent_rate / rate;
+
+	if (!hi6220_is_valid_div(dclk->table, div))
+		return -EINVAL;
+
+	value = hi6220_get_table_val(dclk->table, div);
+
+	if (value > div_mask(dclk->width))
+		value = div_mask(dclk->width);
+
+	if (dclk->lock)
+		spin_lock_irqsave(dclk->lock, flags);
+
+	data = readl_relaxed(dclk->reg);
+	data &= ~(div_mask(dclk->width) << dclk->shift);
+	data |= value << dclk->shift;
+	data |= dclk->mask;
+
+	writel_relaxed(data, dclk->reg);
+
+	if (dclk->lock)
+		spin_unlock_irqrestore(dclk->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops hi6220_clkdiv_ops = {
+	.recalc_rate = hi6220_clkdiv_recalc_rate,
+	.round_rate = hi6220_clkdiv_round_rate,
+	.set_rate = hi6220_clkdiv_set_rate,
+};
+
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
+{
+	struct hi6220_clk_divider *div;
+	struct clk *clk;
+	struct clk_init_data init;
+	struct clk_div_table *table;
+	u32 max_div, min_div;
+	int i;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
+	if (!div) {
+		pr_err("%s: could not allocate divider clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Init the divider table */
+	max_div = div_mask(width) + 1;
+	min_div = 1;
+
+	table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
+	if (!table) {
+		kfree(div);
+		pr_err("%s: failed to alloc divider table!\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < max_div; i++) {
+		table[i].div = min_div + i;
+		table[i].val = table[i].div - 1;
+	}
+
+	init.name = name;
+	init.ops = &hi6220_clkdiv_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	/* struct hi6220_clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->mask = mask_bit ? BIT(mask_bit) : 0;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	clk = clk_register(dev, &div->hw);
+
+	if (IS_ERR(clk)) {
+		kfree(table);
+		kfree(div);
+	}
+
+	return clk;
+}
diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
new file mode 100644
index 0000000..05033e7
--- /dev/null
+++ b/include/dt-bindings/clock/hi6220-clock.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_HI6220_H
+#define __DT_BINDINGS_CLOCK_HI6220_H
+
+/* clk in AO (always on) controller */
+#define HI6220_NONE_CLOCK	0
+
+/* fixed rate clocks */
+#define HI6220_REF32K		1
+#define HI6220_CLK_TCXO		2
+#define HI6220_MMC1_PAD		3
+#define HI6220_MMC2_PAD		4
+#define HI6220_MMC0_PAD		5
+#define HI6220_PLL_BBP		6
+#define HI6220_PLL_GPU		7
+#define HI6220_PLL1_DDR		8
+#define HI6220_PLL_SYS		9
+#define HI6220_PLL_SYS_MEDIA	10
+#define HI6220_DDR_SRC		11
+#define HI6220_PLL_MEDIA	12
+#define HI6220_PLL_DDR		13
+
+/* fixed factor clocks */
+#define HI6220_300M		16
+#define HI6220_150M		17
+#define HI6220_PICOPHY_SRC	18
+#define HI6220_MMC0_SRC_SEL	19
+#define HI6220_MMC1_SRC_SEL	20
+#define HI6220_MMC2_SRC_SEL	21
+#define HI6220_VPU_CODEC	22
+#define HI6220_MMC0_SMP		23
+#define HI6220_MMC1_SMP		24
+#define HI6220_MMC2_SMP		25
+
+/* gate clocks */
+#define HI6220_WDT0_PCLK	28
+#define HI6220_WDT1_PCLK	29
+#define HI6220_WDT2_PCLK	30
+#define HI6220_TIMER0_PCLK	31
+#define HI6220_TIMER1_PCLK	32
+#define HI6220_TIMER2_PCLK	33
+#define HI6220_TIMER3_PCLK	34
+#define HI6220_TIMER4_PCLK	35
+#define HI6220_TIMER5_PCLK	36
+#define HI6220_TIMER6_PCLK	37
+#define HI6220_TIMER7_PCLK	38
+#define HI6220_TIMER8_PCLK	39
+#define HI6220_UART0_PCLK	40
+
+#define HI6220_AO_NR_CLKS	48
+
+/* clk in systrl */
+/* gate clock */
+#define HI6220_MMC0_CLK		1
+#define HI6220_MMC0_CIUCLK	2
+#define HI6220_MMC1_CLK		3
+#define HI6220_MMC1_CIUCLK	4
+#define HI6220_MMC2_CLK		5
+#define HI6220_MMC2_CIUCLK	6
+#define HI6220_USBOTG_HCLK	7
+#define HI6220_CLK_PICOPHY	8
+#define HI6220_HIFI		9
+#define HI6220_DACODEC_PCLK	10
+#define HI6220_EDMAC_ACLK	11
+#define HI6220_CS_ATB		12
+#define HI6220_I2C0_CLK		13
+#define HI6220_I2C1_CLK		14
+#define HI6220_I2C2_CLK		15
+#define HI6220_I2C3_CLK		16
+#define HI6220_UART1_PCLK	17
+#define HI6220_UART2_PCLK	18
+#define HI6220_UART3_PCLK	19
+#define HI6220_UART4_PCLK	20
+#define HI6220_SPI_CLK		21
+#define HI6220_MMU_CLK		22
+#define HI6220_HIFI_SEL		23
+#define HI6220_MMC0_SYSPLL	24
+#define HI6220_MMC1_SYSPLL	25
+#define HI6220_MMC2_SYSPLL	26
+#define HI6220_MMC0_SEL		27
+#define HI6220_MMC1_SEL		28
+#define HI6220_BBPPLL_SEL	29
+#define HI6220_MEDIA_PLL_SRC	30
+#define HI6220_MMC2_SEL		31
+#define HI6220_CS_ATB_SYSPLL	32
+
+/* mux clocks */
+#define HI6220_MMC0_SRC		35
+#define HI6220_MMC0_SMP_IN	36
+#define HI6220_MMC1_SRC		37
+#define HI6220_MMC1_SMP_IN	38
+#define HI6220_MMC2_SRC		39
+#define HI6220_MMC2_SMP_IN	40
+#define HI6220_HIFI_SRC		41
+#define HI6220_UART1_SRC	42
+#define HI6220_UART2_SRC	43
+#define HI6220_UART3_SRC	44
+#define HI6220_UART4_SRC	45
+#define HI6220_MMC0_MUX0	46
+#define HI6220_MMC1_MUX0	47
+#define HI6220_MMC2_MUX0	48
+#define HI6220_MMC0_MUX1	49
+#define HI6220_MMC1_MUX1	50
+#define HI6220_MMC2_MUX1	51
+
+/* divider clocks */
+#define HI6220_CLK_BUS		54
+#define HI6220_MMC0_DIV		55
+#define HI6220_MMC1_DIV		56
+#define HI6220_MMC2_DIV		57
+#define HI6220_HIFI_DIV		58
+#define HI6220_BBPPLL0_DIV	59
+#define HI6220_CS_DAPB		60
+#define HI6220_CS_ATB_DIV	61
+
+#define HI6220_SYS_NR_CLKS	64
+
+/* clk in media controller */
+/* gate clocks */
+#define HI6220_DSI_PCLK		1
+#define HI6220_G3D_PCLK		2
+#define HI6220_ACLK_CODEC_VPU	3
+#define HI6220_ISP_SCLK		4
+#define HI6220_ADE_CORE		5
+#define HI6220_MED_MMU		6
+#define HI6220_CFG_CSI4PHY	7
+#define HI6220_CFG_CSI2PHY	8
+#define HI6220_ISP_SCLK_GATE	9
+#define HI6220_ISP_SCLK_GATE1	10
+#define HI6220_ADE_CORE_GATE	11
+#define HI6220_CODEC_VPU_GATE	12
+#define HI6220_MED_SYSPLL	13
+
+/* mux clocks */
+#define HI6220_1440_1200	20
+#define HI6220_1000_1200	21
+#define HI6220_1000_1440	22
+
+/* divider clocks */
+#define HI6220_CODEC_JPEG	30
+#define HI6220_ISP_SCLK_SRC	31
+#define HI6220_ISP_SCLK1	32
+#define HI6220_ADE_CORE_SRC	33
+#define HI6220_ADE_PIX_SRC	34
+#define HI6220_G3D_CLK		35
+#define HI6220_CODEC_VPU_SRC	36
+
+#define HI6220_MEDIA_NR_CLKS	40
+
+/* clk in power controller */
+/* gate clocks */
+#define HI6220_PLL_GPU_GATE	1
+#define HI6220_PLL1_DDR_GATE	2
+#define HI6220_PLL_DDR_GATE	3
+#define HI6220_PLL_MEDIA_GATE	4
+#define HI6220_PLL0_BBP_GATE	5
+
+/* divider clocks */
+#define HI6220_DDRC_SRC		10
+#define HI6220_DDRC_AXI1	11
+
+#define HI6220_POWER_NR_CLKS	16
+#endif
-- 
1.7.9.5

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

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add clock drivers for hi6220 SoC, this driver controls the SoC
registers to supply different clocks to different IPs in the SoC.

We add one divider clock for hi6220 because the divider in hi6220
also has a mask bit but it doesnot obey the rule defined by flag
"CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
left shift fixed bits (e.g. 16 bits), so we add this divider clock
to handle it.

This patch also enables this clock driver for ARCH_HISI and document
devicetree bindings.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
 .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
 arch/arm64/Kconfig                                 |    1 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    4 +-
 drivers/clk/hisilicon/Kconfig                      |    5 +
 drivers/clk/hisilicon/Makefile                     |    1 +
 drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
 drivers/clk/hisilicon/clk.c                        |   29 ++
 drivers/clk/hisilicon/clk.h                        |   17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
 include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
 11 files changed, 815 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
new file mode 100644
index 0000000..a3ddda1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
@@ -0,0 +1,30 @@
+* Hisilicon Hi6220 Clock Controller
+
+The hi6220 clock controller generates and supplies clock to various
+controllers within the hi6220 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following:
+  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
+     power always on(AO) domain, it is the sub node of SoC power AO
+     controller in dts file.
+  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
+     system control domain, it is the sub node of SoC system controller
+     in dts file.
+  - "hisilicon,hi6220-clock-media" - controller for those clocks under
+     SoC media control domain, it is the sub node of SoC media controller
+     in dts file.
+  - "hisilicon,hi6220-clock-power" - controller for those clocks under
+     SoC power control domain, it is the sub node of SoC power controller
+     in dts file.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 78cd41c8..6efc3e3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -175,6 +175,7 @@ config ARCH_XGENE
 
 config ARCH_HISI
 	bool "Hisilicon SoC Family"
+	select COMMON_CLK_HI6220
 	help
 	  This enables support for Hisilicon ARMv8 Family of SoCs.
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3f44f29..b52c95c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -136,6 +136,8 @@ config COMMON_CLK_PXA
 
 source "drivers/clk/qcom/Kconfig"
 
+source "drivers/clk/hisilicon/Kconfig"
+
 endmenu
 
 source "drivers/clk/bcm/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..c58703b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
 obj-$(CONFIG_ARCH_BCM_MOBILE)		+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
-obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
+obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 0000000..e3ead46
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_CLK_HI6220
+	tristate "Hi6220 Clock Driver"
+	depends on OF && ARCH_HISI
+	help
+	  Build the Hisilicon Hi6220 clock driver based on the common clock framework.
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f..bbf0539 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -7,3 +7,4 @@ obj-y	+= clk.o clkgate-separated.o
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI6220)	+= clkdivider-hi6220.o clk-hi6220.o
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
new file mode 100644
index 0000000..01d0c46
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon Hi6220 clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+#include "clk.h"
+
+
+/* clocks in AO (always on) controller */
+static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
+	{ HI6220_REF32K,	"ref32k",	NULL, CLK_IS_ROOT, 32764,     },
+	{ HI6220_CLK_TCXO,	"clk_tcxo",	NULL, CLK_IS_ROOT, 19200000,  },
+	{ HI6220_MMC1_PAD,	"mmc1_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC2_PAD,	"mmc2_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC0_PAD,	"mmc0_pad",	NULL, CLK_IS_ROOT, 200000000, },
+	{ HI6220_PLL_BBP,	"bbppll0",	NULL, CLK_IS_ROOT, 245760000, },
+	{ HI6220_PLL_GPU,	"gpupll",	NULL, CLK_IS_ROOT, 1000000000,},
+	{ HI6220_PLL1_DDR,	"ddrpll1",	NULL, CLK_IS_ROOT, 1066000000,},
+	{ HI6220_PLL_SYS,	"syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_SYS_MEDIA,	"media_syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_DDR_SRC,	"ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_MEDIA,	"media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
+	{ HI6220_PLL_DDR,	"ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
+};
+
+static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
+	{ HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
+	{ HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
+	{ HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
+	{ HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
+	{ HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
+	{ HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
+};
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
+	{ HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
+	{ HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
+	{ HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
+	{ HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
+	{ HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
+	{ HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
+	{ HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
+	{ HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
+	{ HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
+	{ HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
+	{ HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
+	{ HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
+	{ HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
+};
+
+static void __init hi6220_clk_ao_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
+				ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
+
+	hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
+				ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
+				ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
+
+
+/* clocks in sysctrl */
+static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
+static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
+static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
+static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
+static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
+static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
+static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
+static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
+static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
+static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
+static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
+static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
+	{ HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
+	{ HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
+	{ HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
+	{ HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
+	{ HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
+	{ HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
+	{ HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
+	{ HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
+	{ HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
+	{ HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
+	{ HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
+	{ HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
+	{ HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
+	{ HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
+	{ HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
+	{ HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
+	{ HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
+	{ HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
+	{ HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
+	{ HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
+	{ HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
+	{ HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
+	{ HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
+	{ HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
+	{ HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
+	{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
+	{ HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
+	{ HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
+	{ HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
+	{ HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
+	{ HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
+	{ HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
+	{ HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
+	{ HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
+	{ HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
+};
+
+static void __init hi6220_clk_sys_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
+			ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_sys,
+			ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_sys,
+			ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
+
+
+/* clocks in media controller */
+static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
+static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
+static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
+	{ HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
+	{ HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
+	{ HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
+	{ HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
+	{ HI6220_ADE_CORE,	 "ade_core",	     "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
+	{ HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
+	{ HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
+	{ HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
+	{ HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
+	{ HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
+	{ HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
+	{ HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
+	{ HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
+	{ HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
+	{ HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
+	{ HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
+	{ HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
+	{ HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
+	{ HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
+	{ HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
+	{ HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
+	{ HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
+	{ HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
+};
+
+static void __init hi6220_clk_media_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
+				ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_media,
+				ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_media,
+				ARRAY_SIZE(hi6220_div_clks_media), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
+
+
+/* clocks in pmctrl */
+static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
+	{ HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
+	{ HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
+	{ HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
+	{ HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
+	{ HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
+	{ HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
+	{ HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
+};
+
+static void __init hi6220_clk_power_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate(hi6220_gate_clks_power,
+				ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_power,
+				ARRAY_SIZE(hi6220_div_clks_power), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84..5d2305c 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
+					  int nums, struct hisi_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = hi6220_register_clkdiv(NULL, clks[i].name,
+						clks[i].parent_name,
+						clks[i].flags,
+						base + clks[i].offset,
+						clks[i].shift,
+						clks[i].width,
+						clks[i].mask_bit,
+						&hisi_clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+
+		if (clks[i].alias)
+			clk_register_clkdev(clk, clks[i].alias, NULL);
+
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ff..462a570 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -79,6 +79,18 @@ struct hisi_divider_clock {
 	const char		*alias;
 };
 
+struct hi6220_divider_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			shift;
+	u8			width;
+	u32			mask_bit;
+	const char		*alias;
+};
+
 struct hisi_gate_clock {
 	unsigned int		id;
 	const char		*name;
@@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
 				u8, spinlock_t *);
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
 
 struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
 void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
@@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
 void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 					int, struct hisi_clock_data *);
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
+					int, struct hisi_clock_data *);
 #endif	/* __HISI_CLK_H */
diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
new file mode 100644
index 0000000..9e3825b
--- /dev/null
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -0,0 +1,273 @@
+/*
+ * Hisilicon hi6220 SoC divider clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#define div_mask(width)	((1 << (width)) - 1)
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+/**
+ * struct hi6220_clk_divider - divider clock for hi6220
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @mask:	mask for setting divider rate
+ * @table:	the div table that the divider supports
+ * @lock:	register lock
+ */
+struct hi6220_clk_divider {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u32		mask;
+	const struct clk_div_table *table;
+	spinlock_t	*lock;
+};
+
+#define to_hi6220_clk_divider(_hw)	\
+	container_of(_hw, struct hi6220_clk_divider, hw)
+
+static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
+{
+	unsigned int maxdiv = 0;
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div > maxdiv)
+			maxdiv = clkt->div;
+	return maxdiv;
+}
+
+static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
+					unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+
+	return 0;
+}
+
+static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
+					unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	unsigned int div, val;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	val = readl_relaxed(dclk->reg) >> dclk->shift;
+	val &= div_mask(dclk->width);
+
+	div = hi6220_get_table_div(dclk->table, val);
+	if (!div) {
+		pr_warn("%s: Invalid divisor for clock %s\n", __func__,
+			   __clk_get_name(hw->clk));
+		return parent_rate;
+	}
+
+	return parent_rate / div;
+}
+
+static bool hi6220_is_valid_div(const struct clk_div_table *table,
+				unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *best_parent_rate)
+{
+	unsigned int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+	struct clk *clk_parent = __clk_get_parent(hw->clk);
+
+	maxdiv = hi6220_get_table_maxdiv(dclk->table);
+
+	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+		parent_rate = *best_parent_rate;
+		bestdiv = DIV_ROUND_UP(parent_rate, rate);
+		bestdiv = (bestdiv == 0) ? 1 : bestdiv;
+		bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
+		return bestdiv;
+	}
+
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		if (!hi6220_is_valid_div(dclk->table, i))
+			continue;
+		parent_rate = __clk_round_rate(clk_parent,
+					MULT_ROUND_UP(rate, i));
+		now = parent_rate / i;
+		if (now <= rate && now > best) {
+			bestdiv = i;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = hi6220_get_table_maxdiv(dclk->table);
+		*best_parent_rate = __clk_round_rate(clk_parent, 1);
+	}
+
+	return bestdiv;
+}
+
+static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *prate)
+{
+	int div;
+
+	if (!rate)
+		rate = 1;
+
+	div = hi6220_clkdiv_bestdiv(hw, rate, prate);
+
+	return *prate / div;
+}
+
+static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	unsigned int div, value;
+	unsigned long flags = 0;
+	u32 data;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	div = parent_rate / rate;
+
+	if (!hi6220_is_valid_div(dclk->table, div))
+		return -EINVAL;
+
+	value = hi6220_get_table_val(dclk->table, div);
+
+	if (value > div_mask(dclk->width))
+		value = div_mask(dclk->width);
+
+	if (dclk->lock)
+		spin_lock_irqsave(dclk->lock, flags);
+
+	data = readl_relaxed(dclk->reg);
+	data &= ~(div_mask(dclk->width) << dclk->shift);
+	data |= value << dclk->shift;
+	data |= dclk->mask;
+
+	writel_relaxed(data, dclk->reg);
+
+	if (dclk->lock)
+		spin_unlock_irqrestore(dclk->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops hi6220_clkdiv_ops = {
+	.recalc_rate = hi6220_clkdiv_recalc_rate,
+	.round_rate = hi6220_clkdiv_round_rate,
+	.set_rate = hi6220_clkdiv_set_rate,
+};
+
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
+{
+	struct hi6220_clk_divider *div;
+	struct clk *clk;
+	struct clk_init_data init;
+	struct clk_div_table *table;
+	u32 max_div, min_div;
+	int i;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
+	if (!div) {
+		pr_err("%s: could not allocate divider clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Init the divider table */
+	max_div = div_mask(width) + 1;
+	min_div = 1;
+
+	table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
+	if (!table) {
+		kfree(div);
+		pr_err("%s: failed to alloc divider table!\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < max_div; i++) {
+		table[i].div = min_div + i;
+		table[i].val = table[i].div - 1;
+	}
+
+	init.name = name;
+	init.ops = &hi6220_clkdiv_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	/* struct hi6220_clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->mask = mask_bit ? BIT(mask_bit) : 0;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	clk = clk_register(dev, &div->hw);
+
+	if (IS_ERR(clk)) {
+		kfree(table);
+		kfree(div);
+	}
+
+	return clk;
+}
diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
new file mode 100644
index 0000000..05033e7
--- /dev/null
+++ b/include/dt-bindings/clock/hi6220-clock.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_HI6220_H
+#define __DT_BINDINGS_CLOCK_HI6220_H
+
+/* clk in AO (always on) controller */
+#define HI6220_NONE_CLOCK	0
+
+/* fixed rate clocks */
+#define HI6220_REF32K		1
+#define HI6220_CLK_TCXO		2
+#define HI6220_MMC1_PAD		3
+#define HI6220_MMC2_PAD		4
+#define HI6220_MMC0_PAD		5
+#define HI6220_PLL_BBP		6
+#define HI6220_PLL_GPU		7
+#define HI6220_PLL1_DDR		8
+#define HI6220_PLL_SYS		9
+#define HI6220_PLL_SYS_MEDIA	10
+#define HI6220_DDR_SRC		11
+#define HI6220_PLL_MEDIA	12
+#define HI6220_PLL_DDR		13
+
+/* fixed factor clocks */
+#define HI6220_300M		16
+#define HI6220_150M		17
+#define HI6220_PICOPHY_SRC	18
+#define HI6220_MMC0_SRC_SEL	19
+#define HI6220_MMC1_SRC_SEL	20
+#define HI6220_MMC2_SRC_SEL	21
+#define HI6220_VPU_CODEC	22
+#define HI6220_MMC0_SMP		23
+#define HI6220_MMC1_SMP		24
+#define HI6220_MMC2_SMP		25
+
+/* gate clocks */
+#define HI6220_WDT0_PCLK	28
+#define HI6220_WDT1_PCLK	29
+#define HI6220_WDT2_PCLK	30
+#define HI6220_TIMER0_PCLK	31
+#define HI6220_TIMER1_PCLK	32
+#define HI6220_TIMER2_PCLK	33
+#define HI6220_TIMER3_PCLK	34
+#define HI6220_TIMER4_PCLK	35
+#define HI6220_TIMER5_PCLK	36
+#define HI6220_TIMER6_PCLK	37
+#define HI6220_TIMER7_PCLK	38
+#define HI6220_TIMER8_PCLK	39
+#define HI6220_UART0_PCLK	40
+
+#define HI6220_AO_NR_CLKS	48
+
+/* clk in systrl */
+/* gate clock */
+#define HI6220_MMC0_CLK		1
+#define HI6220_MMC0_CIUCLK	2
+#define HI6220_MMC1_CLK		3
+#define HI6220_MMC1_CIUCLK	4
+#define HI6220_MMC2_CLK		5
+#define HI6220_MMC2_CIUCLK	6
+#define HI6220_USBOTG_HCLK	7
+#define HI6220_CLK_PICOPHY	8
+#define HI6220_HIFI		9
+#define HI6220_DACODEC_PCLK	10
+#define HI6220_EDMAC_ACLK	11
+#define HI6220_CS_ATB		12
+#define HI6220_I2C0_CLK		13
+#define HI6220_I2C1_CLK		14
+#define HI6220_I2C2_CLK		15
+#define HI6220_I2C3_CLK		16
+#define HI6220_UART1_PCLK	17
+#define HI6220_UART2_PCLK	18
+#define HI6220_UART3_PCLK	19
+#define HI6220_UART4_PCLK	20
+#define HI6220_SPI_CLK		21
+#define HI6220_MMU_CLK		22
+#define HI6220_HIFI_SEL		23
+#define HI6220_MMC0_SYSPLL	24
+#define HI6220_MMC1_SYSPLL	25
+#define HI6220_MMC2_SYSPLL	26
+#define HI6220_MMC0_SEL		27
+#define HI6220_MMC1_SEL		28
+#define HI6220_BBPPLL_SEL	29
+#define HI6220_MEDIA_PLL_SRC	30
+#define HI6220_MMC2_SEL		31
+#define HI6220_CS_ATB_SYSPLL	32
+
+/* mux clocks */
+#define HI6220_MMC0_SRC		35
+#define HI6220_MMC0_SMP_IN	36
+#define HI6220_MMC1_SRC		37
+#define HI6220_MMC1_SMP_IN	38
+#define HI6220_MMC2_SRC		39
+#define HI6220_MMC2_SMP_IN	40
+#define HI6220_HIFI_SRC		41
+#define HI6220_UART1_SRC	42
+#define HI6220_UART2_SRC	43
+#define HI6220_UART3_SRC	44
+#define HI6220_UART4_SRC	45
+#define HI6220_MMC0_MUX0	46
+#define HI6220_MMC1_MUX0	47
+#define HI6220_MMC2_MUX0	48
+#define HI6220_MMC0_MUX1	49
+#define HI6220_MMC1_MUX1	50
+#define HI6220_MMC2_MUX1	51
+
+/* divider clocks */
+#define HI6220_CLK_BUS		54
+#define HI6220_MMC0_DIV		55
+#define HI6220_MMC1_DIV		56
+#define HI6220_MMC2_DIV		57
+#define HI6220_HIFI_DIV		58
+#define HI6220_BBPPLL0_DIV	59
+#define HI6220_CS_DAPB		60
+#define HI6220_CS_ATB_DIV	61
+
+#define HI6220_SYS_NR_CLKS	64
+
+/* clk in media controller */
+/* gate clocks */
+#define HI6220_DSI_PCLK		1
+#define HI6220_G3D_PCLK		2
+#define HI6220_ACLK_CODEC_VPU	3
+#define HI6220_ISP_SCLK		4
+#define HI6220_ADE_CORE		5
+#define HI6220_MED_MMU		6
+#define HI6220_CFG_CSI4PHY	7
+#define HI6220_CFG_CSI2PHY	8
+#define HI6220_ISP_SCLK_GATE	9
+#define HI6220_ISP_SCLK_GATE1	10
+#define HI6220_ADE_CORE_GATE	11
+#define HI6220_CODEC_VPU_GATE	12
+#define HI6220_MED_SYSPLL	13
+
+/* mux clocks */
+#define HI6220_1440_1200	20
+#define HI6220_1000_1200	21
+#define HI6220_1000_1440	22
+
+/* divider clocks */
+#define HI6220_CODEC_JPEG	30
+#define HI6220_ISP_SCLK_SRC	31
+#define HI6220_ISP_SCLK1	32
+#define HI6220_ADE_CORE_SRC	33
+#define HI6220_ADE_PIX_SRC	34
+#define HI6220_G3D_CLK		35
+#define HI6220_CODEC_VPU_SRC	36
+
+#define HI6220_MEDIA_NR_CLKS	40
+
+/* clk in power controller */
+/* gate clocks */
+#define HI6220_PLL_GPU_GATE	1
+#define HI6220_PLL1_DDR_GATE	2
+#define HI6220_PLL_DDR_GATE	3
+#define HI6220_PLL_MEDIA_GATE	4
+#define HI6220_PLL0_BBP_GATE	5
+
+/* divider clocks */
+#define HI6220_DDRC_SRC		10
+#define HI6220_DDRC_AXI1	11
+
+#define HI6220_POWER_NR_CLKS	16
+#endif
-- 
1.7.9.5

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, catalin.marinas, will.deacon,
	devicetree, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu
  Cc: xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, bintian.wang, z.liuxinliang, heyunlei,
	kong.kongxinwei, btw, w.f, liguozhu

Add initial dtsi file to support Hisilicon Hi6220 SoC with
support of Octal core CPUs in two clusters and each cluster
has quard Cortex-A53.

We now use the "spin-table" method for SMP, and it will be
changed to PSCI later.

Also add dts file to support HiKey development board which
based on Hi6220 SoC and document the devicetree bindings.

These dts files will be changed later and more nodes will be
added to describe other devices.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
---
 .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
 5 files changed, 274 insertions(+)
 create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index f717c7b..5eb6b41 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -9,6 +9,9 @@ HiP04 D01 Board
 Required root node properties:
 	- compatible = "hisilicon,hip04-d01";
 
+HiKey Board
+Required root node properties:
+	- compatible = "hisilicon,hi6220-hikey";
 
 Hisilicon system controller
 
@@ -62,6 +65,36 @@ Example:
 	};
 
 -----------------------------------------------------------------------
+Hisilicon Power Always ON domain controller
+
+Required properties:
+- compatible : "hisilicon,aoctrl"
+- reg : Register address and size
+
+Some clock registers are defined in power always on system controller,
+especially in Hi6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
+Hisilicon Media domain controller
+
+Required properties:
+- compatible : "hisilicon,mediactrl"
+- reg : Register address and size
+
+Some clock registers of media module are defined in media system
+controller, especially in Hi6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
+Hisilicon Power Management domain controller
+
+Required properties:
+- compatible : "hisilicon,pmctrl"
+- reg : Register address and size
+
+Some clock registers and PMU registers are defined in power management
+controller, especially in Hin6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
 Fabric:
 
 Required Properties:
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index c62b0f4..bffd6b7 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -2,5 +2,6 @@ dts-dirs += amd
 dts-dirs += apm
 dts-dirs += arm
 dts-dirs += cavium
+dts-dirs += hisilicon
 
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
new file mode 100644
index 0000000..fa81a6e
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/Makefile
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
new file mode 100644
index 0000000..a94da84
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
@@ -0,0 +1,31 @@
+/*
+ * dts file for Hisilicon HiKey Development Board
+ *
+ * Copyright (C) 2015, Hisilicon Ltd.
+ *
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x0740f000 0x1000;
+
+#include "hi6220.dtsi"
+
+/ {
+	model = "HiKey Development Board";
+	compatible = "hisilicon,hi6220-hikey";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&gic>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen { };
+
+	memory@7400000 {
+		device_type = "memory";
+		reg = <0x0 0x07400000 0x0 0x38c00000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
new file mode 100644
index 0000000..53ba9cf
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -0,0 +1,204 @@
+/*
+ * dts file for Hisilicon Hi6220 SoC
+ *
+ * Copyright (C) 2015, Hisilicon Ltd.
+ */
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+/ {
+	cpu-map {
+		cluster0 {
+			core0 {
+				cpu = <&cpu0>;
+			};
+			core1 {
+				cpu = <&cpu1>;
+			};
+			core2 {
+				cpu = <&cpu2>;
+			};
+			core3 {
+				cpu = <&cpu3>;
+			};
+		};
+		cluster1 {
+			core0 {
+				cpu = <&cpu4>;
+			};
+			core1 {
+				cpu = <&cpu5>;
+			};
+			core2 {
+				cpu = <&cpu6>;
+			};
+			core3 {
+				cpu = <&cpu7>;
+			};
+		};
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@000 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu1: cpu@001 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu2: cpu@002 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x2>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu3: cpu@003 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x3>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu4: cpu@100 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x100>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu5: cpu@101 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x101>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu6: cpu@102 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x102>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu7: cpu@103 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x103>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+	};
+
+	gic: interrupt-controller@f6800000 {
+		compatible = "arm,gic-400", "arm,cortex-a15-gic";
+		reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
+		      <0x0 0xf6802000 0x0 0x2000>, /* GICC */
+		      <0x0 0xf6804000 0x0 0x2000>, /* GICH */
+		      <0x0 0xf6806000 0x0 0x2000>; /* GICV */
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+	};
+
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <1 13 0xff08>,
+			     <1 14 0xff08>,
+			     <1 11 0xff08>,
+			     <1 10 0xff08>;
+		clock-frequency = <1200000>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		interrupt-parent = <&gic>;
+		ranges;
+
+		ao_ctrl: ao_ctrl {
+			compatible = "hisilicon,aoctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7800000 0x0 0x2000>;
+			ranges = <0 0x0 0xf7800000 0x2000>;
+
+			clock_ao: clock0@0 {
+				compatible = "hisilicon,hi6220-clock-ao";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		sys_ctrl: sys_ctrl {
+			compatible = "hisilicon,sysctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7030000 0x0 0x2000>;
+			ranges = <0 0x0 0xf7030000 0x2000>;
+
+			clock_sys: clock1@0 {
+				compatible = "hisilicon,hi6220-clock-sys";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		media_ctrl: media_ctrl {
+			compatible = "hisilicon,mediactrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf4410000 0x0 0x1000>;
+			ranges = <0 0x0 0xf4410000 0x1000>;
+
+			clock_media: clock2@0 {
+				compatible = "hisilicon,hi6220-clock-media";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		pm_ctrl: pm_ctrl {
+			compatible = "hisilicon,pmctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7032000 0x0 0x1000>;
+			ranges = <0 0x0 0xf7032000 0x1000>;
+
+			clock_power: clock3@0 {
+				compatible = "hisilicon,hi6220-clock-power";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		uart0: uart@f8015000 {	/* console */
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xf8015000 0x0 0x1000>;
+			interrupts = <0 36 4>;
+			clocks = <&clock_ao HI6220_UART0_PCLK>, <&clock_ao HI6220_UART0_PCLK>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+	};
+};
-- 
1.7.9.5


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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, khilman-QSEj5FYQhm4dnm+yROfE0A,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	rob.herring-QSEj5FYQhm4dnm+yROfE0A,
	zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A,
	haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, jh80.chung-Sze3O3UU22JBDgjK7y7TUQ,
	olof-nZhT3qVonbNeoWH0uzbU5w, yanhaifeng-Re5JQEeQqe8AvxtiuMwx3w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	xuejiancheng-hv44wF8Li93QT0dZR+AlfA,
	sledge.yanwei-hv44wF8Li93QT0dZR+AlfA,
	tomeu.vizoso-ZGY8ohtN/8qB+jHODAdFcQ,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, guodong.xu-QSEj5FYQhm4dnm+yROfE0A
  Cc: xuyiping-C8/M+/jPZTeaMJb+Lgu22Q,
	wangbinghui-C8/M+/jPZTeaMJb+Lgu22Q,
	zhenwei.wang-C8/M+/jPZTeaMJb+Lgu22Q,
	victor.lixin-C8/M+/jPZTeaMJb+Lgu22Q,
	puck.chen-C8/M+/jPZTeaMJb+Lgu22Q,
	dan.zhao-C8/M+/jPZTeaMJb+Lgu22Q, huxinwei-hv44wF8Li93QT0dZR+AlfA,
	bintian.wang-hv44wF8Li93QT0dZR+AlfA,
	z.liuxinliang-hv44wF8Li93QT0dZR+AlfA,
	heyunlei-hv44wF8Li93QT0dZR+AlfA,
	kong.kongxinwei-C8/M+/jPZTeaMJb+Lgu22Q,
	btw-aAikPa0K0u50tdys+9eLAQ, w.f-hv44wF8Li93QT0dZR+AlfA,
	liguozhu-C8/M+/jPZTeaMJb+Lgu22Q

Add initial dtsi file to support Hisilicon Hi6220 SoC with
support of Octal core CPUs in two clusters and each cluster
has quard Cortex-A53.

We now use the "spin-table" method for SMP, and it will be
changed to PSCI later.

Also add dts file to support HiKey development board which
based on Hi6220 SoC and document the devicetree bindings.

These dts files will be changed later and more nodes will be
added to describe other devices.

Signed-off-by: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Reviewed-by: Haojian Zhuang <haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Reviewed-by: Yiping Xu <xuyiping-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
---
 .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
 5 files changed, 274 insertions(+)
 create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index f717c7b..5eb6b41 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -9,6 +9,9 @@ HiP04 D01 Board
 Required root node properties:
 	- compatible = "hisilicon,hip04-d01";
 
+HiKey Board
+Required root node properties:
+	- compatible = "hisilicon,hi6220-hikey";
 
 Hisilicon system controller
 
@@ -62,6 +65,36 @@ Example:
 	};
 
 -----------------------------------------------------------------------
+Hisilicon Power Always ON domain controller
+
+Required properties:
+- compatible : "hisilicon,aoctrl"
+- reg : Register address and size
+
+Some clock registers are defined in power always on system controller,
+especially in Hi6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
+Hisilicon Media domain controller
+
+Required properties:
+- compatible : "hisilicon,mediactrl"
+- reg : Register address and size
+
+Some clock registers of media module are defined in media system
+controller, especially in Hi6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
+Hisilicon Power Management domain controller
+
+Required properties:
+- compatible : "hisilicon,pmctrl"
+- reg : Register address and size
+
+Some clock registers and PMU registers are defined in power management
+controller, especially in Hin6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
 Fabric:
 
 Required Properties:
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index c62b0f4..bffd6b7 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -2,5 +2,6 @@ dts-dirs += amd
 dts-dirs += apm
 dts-dirs += arm
 dts-dirs += cavium
+dts-dirs += hisilicon
 
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
new file mode 100644
index 0000000..fa81a6e
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/Makefile
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
new file mode 100644
index 0000000..a94da84
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
@@ -0,0 +1,31 @@
+/*
+ * dts file for Hisilicon HiKey Development Board
+ *
+ * Copyright (C) 2015, Hisilicon Ltd.
+ *
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x0740f000 0x1000;
+
+#include "hi6220.dtsi"
+
+/ {
+	model = "HiKey Development Board";
+	compatible = "hisilicon,hi6220-hikey";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&gic>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen { };
+
+	memory@7400000 {
+		device_type = "memory";
+		reg = <0x0 0x07400000 0x0 0x38c00000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
new file mode 100644
index 0000000..53ba9cf
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -0,0 +1,204 @@
+/*
+ * dts file for Hisilicon Hi6220 SoC
+ *
+ * Copyright (C) 2015, Hisilicon Ltd.
+ */
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+/ {
+	cpu-map {
+		cluster0 {
+			core0 {
+				cpu = <&cpu0>;
+			};
+			core1 {
+				cpu = <&cpu1>;
+			};
+			core2 {
+				cpu = <&cpu2>;
+			};
+			core3 {
+				cpu = <&cpu3>;
+			};
+		};
+		cluster1 {
+			core0 {
+				cpu = <&cpu4>;
+			};
+			core1 {
+				cpu = <&cpu5>;
+			};
+			core2 {
+				cpu = <&cpu6>;
+			};
+			core3 {
+				cpu = <&cpu7>;
+			};
+		};
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@000 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu1: cpu@001 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu2: cpu@002 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x2>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu3: cpu@003 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x3>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu4: cpu@100 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x100>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu5: cpu@101 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x101>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu6: cpu@102 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x102>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu7: cpu@103 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x103>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+	};
+
+	gic: interrupt-controller@f6800000 {
+		compatible = "arm,gic-400", "arm,cortex-a15-gic";
+		reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
+		      <0x0 0xf6802000 0x0 0x2000>, /* GICC */
+		      <0x0 0xf6804000 0x0 0x2000>, /* GICH */
+		      <0x0 0xf6806000 0x0 0x2000>; /* GICV */
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+	};
+
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <1 13 0xff08>,
+			     <1 14 0xff08>,
+			     <1 11 0xff08>,
+			     <1 10 0xff08>;
+		clock-frequency = <1200000>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		interrupt-parent = <&gic>;
+		ranges;
+
+		ao_ctrl: ao_ctrl {
+			compatible = "hisilicon,aoctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7800000 0x0 0x2000>;
+			ranges = <0 0x0 0xf7800000 0x2000>;
+
+			clock_ao: clock0@0 {
+				compatible = "hisilicon,hi6220-clock-ao";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		sys_ctrl: sys_ctrl {
+			compatible = "hisilicon,sysctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7030000 0x0 0x2000>;
+			ranges = <0 0x0 0xf7030000 0x2000>;
+
+			clock_sys: clock1@0 {
+				compatible = "hisilicon,hi6220-clock-sys";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		media_ctrl: media_ctrl {
+			compatible = "hisilicon,mediactrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf4410000 0x0 0x1000>;
+			ranges = <0 0x0 0xf4410000 0x1000>;
+
+			clock_media: clock2@0 {
+				compatible = "hisilicon,hi6220-clock-media";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		pm_ctrl: pm_ctrl {
+			compatible = "hisilicon,pmctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7032000 0x0 0x1000>;
+			ranges = <0 0x0 0xf7032000 0x1000>;
+
+			clock_power: clock3@0 {
+				compatible = "hisilicon,hi6220-clock-power";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		uart0: uart@f8015000 {	/* console */
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xf8015000 0x0 0x1000>;
+			interrupts = <0 36 4>;
+			clocks = <&clock_ao HI6220_UART0_PCLK>, <&clock_ao HI6220_UART0_PCLK>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+	};
+};
-- 
1.7.9.5

--
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 related	[flat|nested] 85+ messages in thread

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-05  9:24   ` Bintian Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Bintian Wang @ 2015-02-05  9:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add initial dtsi file to support Hisilicon Hi6220 SoC with
support of Octal core CPUs in two clusters and each cluster
has quard Cortex-A53.

We now use the "spin-table" method for SMP, and it will be
changed to PSCI later.

Also add dts file to support HiKey development board which
based on Hi6220 SoC and document the devicetree bindings.

These dts files will be changed later and more nodes will be
added to describe other devices.

Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
---
 .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
 5 files changed, 274 insertions(+)
 create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index f717c7b..5eb6b41 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -9,6 +9,9 @@ HiP04 D01 Board
 Required root node properties:
 	- compatible = "hisilicon,hip04-d01";
 
+HiKey Board
+Required root node properties:
+	- compatible = "hisilicon,hi6220-hikey";
 
 Hisilicon system controller
 
@@ -62,6 +65,36 @@ Example:
 	};
 
 -----------------------------------------------------------------------
+Hisilicon Power Always ON domain controller
+
+Required properties:
+- compatible : "hisilicon,aoctrl"
+- reg : Register address and size
+
+Some clock registers are defined in power always on system controller,
+especially in Hi6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
+Hisilicon Media domain controller
+
+Required properties:
+- compatible : "hisilicon,mediactrl"
+- reg : Register address and size
+
+Some clock registers of media module are defined in media system
+controller, especially in Hi6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
+Hisilicon Power Management domain controller
+
+Required properties:
+- compatible : "hisilicon,pmctrl"
+- reg : Register address and size
+
+Some clock registers and PMU registers are defined in power management
+controller, especially in Hin6220 SoC which is used for mobile platform.
+
+-----------------------------------------------------------------------
 Fabric:
 
 Required Properties:
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index c62b0f4..bffd6b7 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -2,5 +2,6 @@ dts-dirs += amd
 dts-dirs += apm
 dts-dirs += arm
 dts-dirs += cavium
+dts-dirs += hisilicon
 
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
new file mode 100644
index 0000000..fa81a6e
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/Makefile
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
new file mode 100644
index 0000000..a94da84
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
@@ -0,0 +1,31 @@
+/*
+ * dts file for Hisilicon HiKey Development Board
+ *
+ * Copyright (C) 2015, Hisilicon Ltd.
+ *
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x0740f000 0x1000;
+
+#include "hi6220.dtsi"
+
+/ {
+	model = "HiKey Development Board";
+	compatible = "hisilicon,hi6220-hikey";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&gic>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen { };
+
+	memory at 7400000 {
+		device_type = "memory";
+		reg = <0x0 0x07400000 0x0 0x38c00000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
new file mode 100644
index 0000000..53ba9cf
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -0,0 +1,204 @@
+/*
+ * dts file for Hisilicon Hi6220 SoC
+ *
+ * Copyright (C) 2015, Hisilicon Ltd.
+ */
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+/ {
+	cpu-map {
+		cluster0 {
+			core0 {
+				cpu = <&cpu0>;
+			};
+			core1 {
+				cpu = <&cpu1>;
+			};
+			core2 {
+				cpu = <&cpu2>;
+			};
+			core3 {
+				cpu = <&cpu3>;
+			};
+		};
+		cluster1 {
+			core0 {
+				cpu = <&cpu4>;
+			};
+			core1 {
+				cpu = <&cpu5>;
+			};
+			core2 {
+				cpu = <&cpu6>;
+			};
+			core3 {
+				cpu = <&cpu7>;
+			};
+		};
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 000 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu1: cpu at 001 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu2: cpu at 002 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x2>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu3: cpu at 003 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x3>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu4: cpu at 100 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x100>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu5: cpu at 101 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x101>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu6: cpu at 102 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x102>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+		cpu7: cpu at 103 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x103>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x740fff8>;
+			clock-latency = <0>;
+		};
+	};
+
+	gic: interrupt-controller at f6800000 {
+		compatible = "arm,gic-400", "arm,cortex-a15-gic";
+		reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
+		      <0x0 0xf6802000 0x0 0x2000>, /* GICC */
+		      <0x0 0xf6804000 0x0 0x2000>, /* GICH */
+		      <0x0 0xf6806000 0x0 0x2000>; /* GICV */
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+	};
+
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <1 13 0xff08>,
+			     <1 14 0xff08>,
+			     <1 11 0xff08>,
+			     <1 10 0xff08>;
+		clock-frequency = <1200000>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		interrupt-parent = <&gic>;
+		ranges;
+
+		ao_ctrl: ao_ctrl {
+			compatible = "hisilicon,aoctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7800000 0x0 0x2000>;
+			ranges = <0 0x0 0xf7800000 0x2000>;
+
+			clock_ao: clock0 at 0 {
+				compatible = "hisilicon,hi6220-clock-ao";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		sys_ctrl: sys_ctrl {
+			compatible = "hisilicon,sysctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7030000 0x0 0x2000>;
+			ranges = <0 0x0 0xf7030000 0x2000>;
+
+			clock_sys: clock1 at 0 {
+				compatible = "hisilicon,hi6220-clock-sys";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		media_ctrl: media_ctrl {
+			compatible = "hisilicon,mediactrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf4410000 0x0 0x1000>;
+			ranges = <0 0x0 0xf4410000 0x1000>;
+
+			clock_media: clock2 at 0 {
+				compatible = "hisilicon,hi6220-clock-media";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		pm_ctrl: pm_ctrl {
+			compatible = "hisilicon,pmctrl", "syscon";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0xf7032000 0x0 0x1000>;
+			ranges = <0 0x0 0xf7032000 0x1000>;
+
+			clock_power: clock3 at 0 {
+				compatible = "hisilicon,hi6220-clock-power";
+				reg = <0 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		uart0: uart at f8015000 {	/* console */
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xf8015000 0x0 0x1000>;
+			interrupts = <0 36 4>;
+			clocks = <&clock_ao HI6220_UART0_PCLK>, <&clock_ao HI6220_UART0_PCLK>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+	};
+};
-- 
1.7.9.5

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 18:46   ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-05 18:46 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel, catalin.marinas, Will Deacon,
	devicetree, robh+dt, pawel.moll, Mark Rutland, ijc+devicetree,
	galak, Kevin Hilman, Mike Turquette, Rob Herring, Zhangfei Gao,
	Haojian Zhuang, Xu Wei, jh80.chung, Olof Johansson, yanhaifeng,
	Stephen Boyd, xuejiancheng, sledge.yanwei, tomeu.vizoso,
	Russell King - ARM Linux, Guodong Xu, dan.zhao, huxinwei,
	xuyiping, victor.lixin, btw, puck.chen, wangbinghui,
	zhenwei.wang, liguozhu, kong.kongxinwei, heyunlei, w.f,
	z.liuxinliang

Hi Bintian,

On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
> Hello,
>
> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> initial support for Hi6220 SoC and HiKey development board, which
> is based on ARM Cortex A53 architecture. Initial support is minimal
> and includes just the arch configuration, clock driver, device tree
> configuration.
>
> Many peripheral drivers will be submitted later.
>
> Any comments will be appreciated!
>
> Thanks,
>
> Bintian Wang (3):
>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC

Thanks for posting these! I've applied this series on top of
next-20150204, however there was some fuzz that needed to be cleaned
up on 3/3 [1]. I've confirmed the platform is booting to a basic user
space without issue.

Tested-by: Tyler Baker <tyler.baker@linaro.org>

>
>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 +++
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    6 +
>  arch/arm64/boot/dts/Makefile                       |    1 +
>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++
>  arch/arm64/configs/defconfig                       |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  17 files changed, 1095 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Cheers,

Tyler

[1] https://git.linaro.org/people/tyler.baker/linux.git/commitdiff/e9ab7b08e844009c66ba5ecf946d4b3e23551f73?hp=fcfe654f30cf75c847f69b2965c6b9e4d01c5b08

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 18:46   ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-05 18:46 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	catalin.marinas-5wv7dgnIgG8, Will Deacon,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	Mark Rutland, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, Kevin Hilman, Mike Turquette,
	Rob Herring, Zhangfei Gao, Haojian Zhuang, Xu Wei,
	jh80.chung-Sze3O3UU22JBDgjK7y7TUQ, Olof Johansson,
	yanhaifeng-Re5JQEeQqe8AvxtiuMwx3w, Stephen Boyd,
	xuejiancheng-hv44wF8Li93QT0dZR+AlfA,
	sledge.yanwei-hv44wF8Li93QT0dZR+AlfA,
	tomeu.vizoso-ZGY8ohtN/8qB+jHODAdFcQ, Russell King - ARM Linux,
	Guodong Xu, dan.zhao-C8/M+/jPZTeaMJb+Lgu22Q,
	huxinwei-hv44wF8Li93QT0dZR+AlfA, xuyiping

Hi Bintian,

On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
> Hello,
>
> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> initial support for Hi6220 SoC and HiKey development board, which
> is based on ARM Cortex A53 architecture. Initial support is minimal
> and includes just the arch configuration, clock driver, device tree
> configuration.
>
> Many peripheral drivers will be submitted later.
>
> Any comments will be appreciated!
>
> Thanks,
>
> Bintian Wang (3):
>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC

Thanks for posting these! I've applied this series on top of
next-20150204, however there was some fuzz that needed to be cleaned
up on 3/3 [1]. I've confirmed the platform is booting to a basic user
space without issue.

Tested-by: Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

>
>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 +++
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    6 +
>  arch/arm64/boot/dts/Makefile                       |    1 +
>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++
>  arch/arm64/configs/defconfig                       |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  17 files changed, 1095 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Cheers,

Tyler

[1] https://git.linaro.org/people/tyler.baker/linux.git/commitdiff/e9ab7b08e844009c66ba5ecf946d4b3e23551f73?hp=fcfe654f30cf75c847f69b2965c6b9e4d01c5b08
--
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] 85+ messages in thread

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 18:46   ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-05 18:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Bintian,

On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
> Hello,
>
> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> initial support for Hi6220 SoC and HiKey development board, which
> is based on ARM Cortex A53 architecture. Initial support is minimal
> and includes just the arch configuration, clock driver, device tree
> configuration.
>
> Many peripheral drivers will be submitted later.
>
> Any comments will be appreciated!
>
> Thanks,
>
> Bintian Wang (3):
>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC

Thanks for posting these! I've applied this series on top of
next-20150204, however there was some fuzz that needed to be cleaned
up on 3/3 [1]. I've confirmed the platform is booting to a basic user
space without issue.

Tested-by: Tyler Baker <tyler.baker@linaro.org>

>
>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 +++
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    6 +
>  arch/arm64/boot/dts/Makefile                       |    1 +
>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++
>  arch/arm64/configs/defconfig                       |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  17 files changed, 1095 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Cheers,

Tyler

[1] https://git.linaro.org/people/tyler.baker/linux.git/commitdiff/e9ab7b08e844009c66ba5ecf946d4b3e23551f73?hp=fcfe654f30cf75c847f69b2965c6b9e4d01c5b08

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 19:02     ` Olof Johansson
  0 siblings, 0 replies; 85+ messages in thread
From: Olof Johansson @ 2015-02-05 19:02 UTC (permalink / raw)
  To: Tyler Baker
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Kevin Hilman, Mike Turquette,
	Rob Herring, Zhangfei Gao, Haojian Zhuang, Xu Wei, Jaehoon Chung,
	Haifeng Yan, Stephen Boyd, xuejiancheng, sledge.yanwei,
	Tomeu Vizoso, Russell King - ARM Linux, Guodong Xu, dan.zhao,
	huxinwei, xuyiping, victor.lixin, btw, puck.chen, wangbinghui,
	zhenwei.wang, Liguozhu (Kenneth),
	kong.kongxinwei, heyunlei, w.f, z.liuxinliang

On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org> wrote:
> Hi Bintian,
>
> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>> Hello,
>>
>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>> initial support for Hi6220 SoC and HiKey development board, which
>> is based on ARM Cortex A53 architecture. Initial support is minimal
>> and includes just the arch configuration, clock driver, device tree
>> configuration.
>>
>> Many peripheral drivers will be submitted later.
>>
>> Any comments will be appreciated!
>>
>> Thanks,
>>
>> Bintian Wang (3):
>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>
> Thanks for posting these! I've applied this series on top of
> next-20150204, however there was some fuzz that needed to be cleaned
> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> space without issue.

>From ramdisk only, right? Given the timing of the posting of this
patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
there will be some more peripheral support as well -- at least some
sort of storage device.


-Olof

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 19:02     ` Olof Johansson
  0 siblings, 0 replies; 85+ messages in thread
From: Olof Johansson @ 2015-02-05 19:02 UTC (permalink / raw)
  To: Tyler Baker
  Cc: Bintian Wang, linux-arm-kernel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd,
	xuejiancheng-hv44wF8Li93QT0dZR+AlfA,
	sledge.yanwei-hv44wF8Li93QT0dZR+AlfA

On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Hi Bintian,
>
> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
>> Hello,
>>
>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>> initial support for Hi6220 SoC and HiKey development board, which
>> is based on ARM Cortex A53 architecture. Initial support is minimal
>> and includes just the arch configuration, clock driver, device tree
>> configuration.
>>
>> Many peripheral drivers will be submitted later.
>>
>> Any comments will be appreciated!
>>
>> Thanks,
>>
>> Bintian Wang (3):
>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>
> Thanks for posting these! I've applied this series on top of
> next-20150204, however there was some fuzz that needed to be cleaned
> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> space without issue.

>From ramdisk only, right? Given the timing of the posting of this
patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
there will be some more peripheral support as well -- at least some
sort of storage device.


-Olof
--
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] 85+ messages in thread

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 19:02     ` Olof Johansson
  0 siblings, 0 replies; 85+ messages in thread
From: Olof Johansson @ 2015-02-05 19:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org> wrote:
> Hi Bintian,
>
> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>> Hello,
>>
>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>> initial support for Hi6220 SoC and HiKey development board, which
>> is based on ARM Cortex A53 architecture. Initial support is minimal
>> and includes just the arch configuration, clock driver, device tree
>> configuration.
>>
>> Many peripheral drivers will be submitted later.
>>
>> Any comments will be appreciated!
>>
>> Thanks,
>>
>> Bintian Wang (3):
>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>
> Thanks for posting these! I've applied this series on top of
> next-20150204, however there was some fuzz that needed to be cleaned
> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> space without issue.

>From ramdisk only, right? Given the timing of the posting of this
patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
there will be some more peripheral support as well -- at least some
sort of storage device.


-Olof

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  2015-02-05  9:24   ` Bintian Wang
  (?)
@ 2015-02-05 19:25     ` Mark Rutland
  -1 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-05 19:25 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel, Catalin Marinas, Will Deacon,
	devicetree, robh+dt, Pawel Moll, ijc+devicetree, galak, khilman,
	mturquette, rob.herring, zhangfei.gao, haojian.zhuang, xuwei5,
	jh80.chung, olof, yanhaifeng, sboyd, xuejiancheng, sledge.yanwei,
	tomeu.vizoso, linux, guodong.xu, xuyiping, wangbinghui,
	zhenwei.wang, victor.lixin, puck.chen, dan.zhao, huxinwei,
	z.liuxinliang, heyunlei, kong.kongxinwei, btw, w.f, liguozhu

On Thu, Feb 05, 2015 at 09:24:36AM +0000, Bintian Wang wrote:
> Add clock drivers for hi6220 SoC, this driver controls the SoC
> registers to supply different clocks to different IPs in the SoC.
> 
> We add one divider clock for hi6220 because the divider in hi6220
> also has a mask bit but it doesnot obey the rule defined by flag
> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
> left shift fixed bits (e.g. 16 bits), so we add this divider clock
> to handle it.
> 
> This patch also enables this clock driver for ARCH_HISI and document
> devicetree bindings.
> 
> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  11 files changed, 815 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> new file mode 100644
> index 0000000..a3ddda1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> @@ -0,0 +1,30 @@
> +* Hisilicon Hi6220 Clock Controller
> +
> +The hi6220 clock controller generates and supplies clock to various
> +controllers within the hi6220 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be one of the following:
> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
> +     power always on(AO) domain, it is the sub node of SoC power AO
> +     controller in dts file.
> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
> +     system control domain, it is the sub node of SoC system controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
> +     SoC media control domain, it is the sub node of SoC media controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
> +     SoC power control domain, it is the sub node of SoC power controller
> +     in dts file.

These all refer to things which aren't documented (yet).

Please sort out your patches so that any documentation you depend on
comes earlier.

Please also separate documentation from code. Note that dt includes are
_bindings_ and should be added with the relevant documentation.

Thanks,
Mark.

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-05 19:25     ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-05 19:25 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel, Catalin Marinas, Will Deacon,
	devicetree, robh+dt, Pawel Moll, ijc+devicetree, galak, khilman,
	mturquette, rob.herring, zhangfei.gao, haojian.zhuang, xuwei5,
	jh80.chung, olof

On Thu, Feb 05, 2015 at 09:24:36AM +0000, Bintian Wang wrote:
> Add clock drivers for hi6220 SoC, this driver controls the SoC
> registers to supply different clocks to different IPs in the SoC.
> 
> We add one divider clock for hi6220 because the divider in hi6220
> also has a mask bit but it doesnot obey the rule defined by flag
> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
> left shift fixed bits (e.g. 16 bits), so we add this divider clock
> to handle it.
> 
> This patch also enables this clock driver for ARCH_HISI and document
> devicetree bindings.
> 
> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  11 files changed, 815 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> new file mode 100644
> index 0000000..a3ddda1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> @@ -0,0 +1,30 @@
> +* Hisilicon Hi6220 Clock Controller
> +
> +The hi6220 clock controller generates and supplies clock to various
> +controllers within the hi6220 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be one of the following:
> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
> +     power always on(AO) domain, it is the sub node of SoC power AO
> +     controller in dts file.
> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
> +     system control domain, it is the sub node of SoC system controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
> +     SoC media control domain, it is the sub node of SoC media controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
> +     SoC power control domain, it is the sub node of SoC power controller
> +     in dts file.

These all refer to things which aren't documented (yet).

Please sort out your patches so that any documentation you depend on
comes earlier.

Please also separate documentation from code. Note that dt includes are
_bindings_ and should be added with the relevant documentation.

Thanks,
Mark.

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

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-05 19:25     ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-05 19:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 05, 2015 at 09:24:36AM +0000, Bintian Wang wrote:
> Add clock drivers for hi6220 SoC, this driver controls the SoC
> registers to supply different clocks to different IPs in the SoC.
> 
> We add one divider clock for hi6220 because the divider in hi6220
> also has a mask bit but it doesnot obey the rule defined by flag
> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
> left shift fixed bits (e.g. 16 bits), so we add this divider clock
> to handle it.
> 
> This patch also enables this clock driver for ARCH_HISI and document
> devicetree bindings.
> 
> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  11 files changed, 815 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> new file mode 100644
> index 0000000..a3ddda1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> @@ -0,0 +1,30 @@
> +* Hisilicon Hi6220 Clock Controller
> +
> +The hi6220 clock controller generates and supplies clock to various
> +controllers within the hi6220 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be one of the following:
> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
> +     power always on(AO) domain, it is the sub node of SoC power AO
> +     controller in dts file.
> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
> +     system control domain, it is the sub node of SoC system controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
> +     SoC media control domain, it is the sub node of SoC media controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
> +     SoC power control domain, it is the sub node of SoC power controller
> +     in dts file.

These all refer to things which aren't documented (yet).

Please sort out your patches so that any documentation you depend on
comes earlier.

Please also separate documentation from code. Note that dt includes are
_bindings_ and should be added with the relevant documentation.

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-05  9:24   ` Bintian Wang
  (?)
@ 2015-02-05 19:30     ` Mark Rutland
  -1 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-05 19:30 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel, Catalin Marinas, Will Deacon,
	devicetree, robh+dt, Pawel Moll, ijc+devicetree, galak, khilman,
	mturquette, rob.herring, zhangfei.gao, haojian.zhuang, xuwei5,
	jh80.chung, olof, yanhaifeng, sboyd, xuejiancheng, sledge.yanwei,
	tomeu.vizoso, linux, guodong.xu, xuyiping, wangbinghui,
	zhenwei.wang, victor.lixin, puck.chen, dan.zhao, huxinwei,
	z.liuxinliang, heyunlei, kong.kongxinwei, btw, w.f, liguozhu

On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> support of Octal core CPUs in two clusters and each cluster
> has quard Cortex-A53.
> 
> We now use the "spin-table" method for SMP, and it will be
> changed to PSCI later.

If that's the case, please don't place the enable-method and related
properties in this file. Get your bootloader to add the appropriate
properties for its boot protocol.

When is PSCI likely to appear?

Are we certain of the split between components the PSCI implementation
must touch and those the kernel must touch?

> Also add dts file to support HiKey development board which
> based on Hi6220 SoC and document the devicetree bindings.
> 
> These dts files will be changed later and more nodes will be
> added to describe other devices.

How is this going to be changed other than the addition of nodes?

Will this DTB continue to work in future? Or do you intend to make
changes that will break support?

> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
> ---
>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
>  arch/arm64/boot/dts/Makefile                       |    1 +
>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
>  5 files changed, 274 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index f717c7b..5eb6b41 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -9,6 +9,9 @@ HiP04 D01 Board
>  Required root node properties:
>  	- compatible = "hisilicon,hip04-d01";
>  
> +HiKey Board
> +Required root node properties:
> +	- compatible = "hisilicon,hi6220-hikey";
>  
>  Hisilicon system controller
>  
> @@ -62,6 +65,36 @@ Example:
>  	};
>  
>  -----------------------------------------------------------------------
> +Hisilicon Power Always ON domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,aoctrl"
> +- reg : Register address and size
> +
> +Some clock registers are defined in power always on system controller,
> +especially in Hi6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------
> +Hisilicon Media domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,mediactrl"
> +- reg : Register address and size
> +
> +Some clock registers of media module are defined in media system
> +controller, especially in Hi6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------
> +Hisilicon Power Management domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,pmctrl"
> +- reg : Register address and size
> +
> +Some clock registers and PMU registers are defined in power management
> +controller, especially in Hin6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------

Looking at the dts below, none of these binding docs are sufficient.

Define _all_ the properties and what they mean.

Please also split documentation into earlier patches.

>  Fabric:
>  
>  Required Properties:
> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
> index c62b0f4..bffd6b7 100644
> --- a/arch/arm64/boot/dts/Makefile
> +++ b/arch/arm64/boot/dts/Makefile
> @@ -2,5 +2,6 @@ dts-dirs += amd
>  dts-dirs += apm
>  dts-dirs += arm
>  dts-dirs += cavium
> +dts-dirs += hisilicon
>  
>  subdir-y	:= $(dts-dirs)
> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
> new file mode 100644
> index 0000000..fa81a6e
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
> @@ -0,0 +1,5 @@
> +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
> +
> +always		:= $(dtb-y)
> +subdir-y	:= $(dts-dirs)
> +clean-files	:= *.dtb
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> new file mode 100644
> index 0000000..a94da84
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> @@ -0,0 +1,31 @@
> +/*
> + * dts file for Hisilicon HiKey Development Board
> + *
> + * Copyright (C) 2015, Hisilicon Ltd.
> + *
> + */
> +
> +/dts-v1/;
> +
> +/memreserve/ 0x0740f000 0x1000;

If you're going to use /memreserve/, please add a comment regarding what
it is intended to protect, and why that's in memory given to the kernel
to begin with.

> +
> +#include "hi6220.dtsi"
> +
> +/ {
> +	model = "HiKey Development Board";
> +	compatible = "hisilicon,hi6220-hikey";
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +	interrupt-parent = <&gic>;
> +
> +	aliases {
> +		serial0 = &uart0;
> +	};
> +
> +	chosen { };

You should use stdout-path here, ideally with the full UART
configuration.

> +
> +	memory@7400000 {
> +		device_type = "memory";
> +		reg = <0x0 0x07400000 0x0 0x38c00000>;
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> new file mode 100644
> index 0000000..53ba9cf
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> @@ -0,0 +1,204 @@
> +/*
> + * dts file for Hisilicon Hi6220 SoC
> + *
> + * Copyright (C) 2015, Hisilicon Ltd.
> + */
> +
> +#include <dt-bindings/clock/hi6220-clock.h>
> +
> +/ {
> +	cpu-map {

Per the binding, this must live under /cpus. 

Move this within the /cpus node.

> +		cluster0 {
> +			core0 {
> +				cpu = <&cpu0>;
> +			};
> +			core1 {
> +				cpu = <&cpu1>;
> +			};
> +			core2 {
> +				cpu = <&cpu2>;
> +			};
> +			core3 {
> +				cpu = <&cpu3>;
> +			};
> +		};
> +		cluster1 {
> +			core0 {
> +				cpu = <&cpu4>;
> +			};
> +			core1 {
> +				cpu = <&cpu5>;
> +			};
> +			core2 {
> +				cpu = <&cpu6>;
> +			};
> +			core3 {
> +				cpu = <&cpu7>;
> +			};
> +		};
> +	};
> +
> +	cpus {
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@000 {
> +			compatible = "arm,cortex-a53", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x0>;
> +			enable-method = "spin-table";
> +			cpu-release-addr = <0x0 0x740fff8>;

If you _must_ use spin-table, please give each CPU a unique release
address. Using a shared address was a mistake, and we should learn from
it.

Which CPU does the system boot on?

> +			clock-latency = <0>;

Why is this here?

There is no reason for this to be on any CPU node.

> +		};

[...]

> +	gic: interrupt-controller@f6800000 {
> +		compatible = "arm,gic-400", "arm,cortex-a15-gic";

Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
am I missing?

> +		reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */

This doesn't match the unit-address.

> +		      <0x0 0xf6802000 0x0 0x2000>, /* GICC */
> +		      <0x0 0xf6804000 0x0 0x2000>, /* GICH */
> +		      <0x0 0xf6806000 0x0 0x2000>; /* GICV */

I guess no-one's bothered to consider 64k pages?

Given GICH and GICV, I hope that this platform is booted at EL2?

> +		#interrupt-cells = <3>;
> +		#address-cells = <0>;
> +		interrupt-controller;
> +	};
> +
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupt-parent = <&gic>;
> +		interrupts = <1 13 0xff08>,
> +			     <1 14 0xff08>,
> +			     <1 11 0xff08>,
> +			     <1 10 0xff08>;
> +		clock-frequency = <1200000>;
> +	};

NAK. Fix your firmware to configure CNTFRQ, on all CPUs.

That frequency also looks a bit low; timekeeping isn't going to be very
precise.

> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		interrupt-parent = <&gic>;
> +		ranges;
> +
> +		ao_ctrl: ao_ctrl {
> +			compatible = "hisilicon,aoctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7800000 0x0 0x2000>;
> +			ranges = <0 0x0 0xf7800000 0x2000>;
> +
> +			clock_ao: clock0@0 {
> +				compatible = "hisilicon,hi6220-clock-ao";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		sys_ctrl: sys_ctrl {
> +			compatible = "hisilicon,sysctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7030000 0x0 0x2000>;
> +			ranges = <0 0x0 0xf7030000 0x2000>;
> +
> +			clock_sys: clock1@0 {
> +				compatible = "hisilicon,hi6220-clock-sys";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		media_ctrl: media_ctrl {
> +			compatible = "hisilicon,mediactrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf4410000 0x0 0x1000>;
> +			ranges = <0 0x0 0xf4410000 0x1000>;
> +
> +			clock_media: clock2@0 {
> +				compatible = "hisilicon,hi6220-clock-media";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		pm_ctrl: pm_ctrl {
> +			compatible = "hisilicon,pmctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7032000 0x0 0x1000>;
> +			ranges = <0 0x0 0xf7032000 0x1000>;
> +
> +			clock_power: clock3@0 {
> +				compatible = "hisilicon,hi6220-clock-power";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};

I really doesn't see the point in having a sub-device that covers the
entirely of the register space of the containing node, and that being
the case I am extremely concerned that the containers are marked as
syscon compatible.

Why are these marked as being syscon devices? Per the dts _all_ their
registers are clearly owned by their child nodes, and shouldn't be poked
by anything else.

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-05 19:30     ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-05 19:30 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel, Catalin Marinas, Will Deacon,
	devicetree, robh+dt, Pawel Moll, ijc+devicetree, galak, khilman,
	mturquette, rob.herring, zhangfei.gao, haojian.zhuang, xuwei5,
	jh80.chung, olof

On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> support of Octal core CPUs in two clusters and each cluster
> has quard Cortex-A53.
> 
> We now use the "spin-table" method for SMP, and it will be
> changed to PSCI later.

If that's the case, please don't place the enable-method and related
properties in this file. Get your bootloader to add the appropriate
properties for its boot protocol.

When is PSCI likely to appear?

Are we certain of the split between components the PSCI implementation
must touch and those the kernel must touch?

> Also add dts file to support HiKey development board which
> based on Hi6220 SoC and document the devicetree bindings.
> 
> These dts files will be changed later and more nodes will be
> added to describe other devices.

How is this going to be changed other than the addition of nodes?

Will this DTB continue to work in future? Or do you intend to make
changes that will break support?

> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
> ---
>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
>  arch/arm64/boot/dts/Makefile                       |    1 +
>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
>  5 files changed, 274 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index f717c7b..5eb6b41 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -9,6 +9,9 @@ HiP04 D01 Board
>  Required root node properties:
>  	- compatible = "hisilicon,hip04-d01";
>  
> +HiKey Board
> +Required root node properties:
> +	- compatible = "hisilicon,hi6220-hikey";
>  
>  Hisilicon system controller
>  
> @@ -62,6 +65,36 @@ Example:
>  	};
>  
>  -----------------------------------------------------------------------
> +Hisilicon Power Always ON domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,aoctrl"
> +- reg : Register address and size
> +
> +Some clock registers are defined in power always on system controller,
> +especially in Hi6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------
> +Hisilicon Media domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,mediactrl"
> +- reg : Register address and size
> +
> +Some clock registers of media module are defined in media system
> +controller, especially in Hi6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------
> +Hisilicon Power Management domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,pmctrl"
> +- reg : Register address and size
> +
> +Some clock registers and PMU registers are defined in power management
> +controller, especially in Hin6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------

Looking at the dts below, none of these binding docs are sufficient.

Define _all_ the properties and what they mean.

Please also split documentation into earlier patches.

>  Fabric:
>  
>  Required Properties:
> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
> index c62b0f4..bffd6b7 100644
> --- a/arch/arm64/boot/dts/Makefile
> +++ b/arch/arm64/boot/dts/Makefile
> @@ -2,5 +2,6 @@ dts-dirs += amd
>  dts-dirs += apm
>  dts-dirs += arm
>  dts-dirs += cavium
> +dts-dirs += hisilicon
>  
>  subdir-y	:= $(dts-dirs)
> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
> new file mode 100644
> index 0000000..fa81a6e
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
> @@ -0,0 +1,5 @@
> +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
> +
> +always		:= $(dtb-y)
> +subdir-y	:= $(dts-dirs)
> +clean-files	:= *.dtb
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> new file mode 100644
> index 0000000..a94da84
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> @@ -0,0 +1,31 @@
> +/*
> + * dts file for Hisilicon HiKey Development Board
> + *
> + * Copyright (C) 2015, Hisilicon Ltd.
> + *
> + */
> +
> +/dts-v1/;
> +
> +/memreserve/ 0x0740f000 0x1000;

If you're going to use /memreserve/, please add a comment regarding what
it is intended to protect, and why that's in memory given to the kernel
to begin with.

> +
> +#include "hi6220.dtsi"
> +
> +/ {
> +	model = "HiKey Development Board";
> +	compatible = "hisilicon,hi6220-hikey";
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +	interrupt-parent = <&gic>;
> +
> +	aliases {
> +		serial0 = &uart0;
> +	};
> +
> +	chosen { };

You should use stdout-path here, ideally with the full UART
configuration.

> +
> +	memory@7400000 {
> +		device_type = "memory";
> +		reg = <0x0 0x07400000 0x0 0x38c00000>;
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> new file mode 100644
> index 0000000..53ba9cf
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> @@ -0,0 +1,204 @@
> +/*
> + * dts file for Hisilicon Hi6220 SoC
> + *
> + * Copyright (C) 2015, Hisilicon Ltd.
> + */
> +
> +#include <dt-bindings/clock/hi6220-clock.h>
> +
> +/ {
> +	cpu-map {

Per the binding, this must live under /cpus. 

Move this within the /cpus node.

> +		cluster0 {
> +			core0 {
> +				cpu = <&cpu0>;
> +			};
> +			core1 {
> +				cpu = <&cpu1>;
> +			};
> +			core2 {
> +				cpu = <&cpu2>;
> +			};
> +			core3 {
> +				cpu = <&cpu3>;
> +			};
> +		};
> +		cluster1 {
> +			core0 {
> +				cpu = <&cpu4>;
> +			};
> +			core1 {
> +				cpu = <&cpu5>;
> +			};
> +			core2 {
> +				cpu = <&cpu6>;
> +			};
> +			core3 {
> +				cpu = <&cpu7>;
> +			};
> +		};
> +	};
> +
> +	cpus {
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@000 {
> +			compatible = "arm,cortex-a53", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x0>;
> +			enable-method = "spin-table";
> +			cpu-release-addr = <0x0 0x740fff8>;

If you _must_ use spin-table, please give each CPU a unique release
address. Using a shared address was a mistake, and we should learn from
it.

Which CPU does the system boot on?

> +			clock-latency = <0>;

Why is this here?

There is no reason for this to be on any CPU node.

> +		};

[...]

> +	gic: interrupt-controller@f6800000 {
> +		compatible = "arm,gic-400", "arm,cortex-a15-gic";

Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
am I missing?

> +		reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */

This doesn't match the unit-address.

> +		      <0x0 0xf6802000 0x0 0x2000>, /* GICC */
> +		      <0x0 0xf6804000 0x0 0x2000>, /* GICH */
> +		      <0x0 0xf6806000 0x0 0x2000>; /* GICV */

I guess no-one's bothered to consider 64k pages?

Given GICH and GICV, I hope that this platform is booted at EL2?

> +		#interrupt-cells = <3>;
> +		#address-cells = <0>;
> +		interrupt-controller;
> +	};
> +
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupt-parent = <&gic>;
> +		interrupts = <1 13 0xff08>,
> +			     <1 14 0xff08>,
> +			     <1 11 0xff08>,
> +			     <1 10 0xff08>;
> +		clock-frequency = <1200000>;
> +	};

NAK. Fix your firmware to configure CNTFRQ, on all CPUs.

That frequency also looks a bit low; timekeeping isn't going to be very
precise.

> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		interrupt-parent = <&gic>;
> +		ranges;
> +
> +		ao_ctrl: ao_ctrl {
> +			compatible = "hisilicon,aoctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7800000 0x0 0x2000>;
> +			ranges = <0 0x0 0xf7800000 0x2000>;
> +
> +			clock_ao: clock0@0 {
> +				compatible = "hisilicon,hi6220-clock-ao";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		sys_ctrl: sys_ctrl {
> +			compatible = "hisilicon,sysctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7030000 0x0 0x2000>;
> +			ranges = <0 0x0 0xf7030000 0x2000>;
> +
> +			clock_sys: clock1@0 {
> +				compatible = "hisilicon,hi6220-clock-sys";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		media_ctrl: media_ctrl {
> +			compatible = "hisilicon,mediactrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf4410000 0x0 0x1000>;
> +			ranges = <0 0x0 0xf4410000 0x1000>;
> +
> +			clock_media: clock2@0 {
> +				compatible = "hisilicon,hi6220-clock-media";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		pm_ctrl: pm_ctrl {
> +			compatible = "hisilicon,pmctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7032000 0x0 0x1000>;
> +			ranges = <0 0x0 0xf7032000 0x1000>;
> +
> +			clock_power: clock3@0 {
> +				compatible = "hisilicon,hi6220-clock-power";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};

I really doesn't see the point in having a sub-device that covers the
entirely of the register space of the containing node, and that being
the case I am extremely concerned that the containers are marked as
syscon compatible.

Why are these marked as being syscon devices? Per the dts _all_ their
registers are clearly owned by their child nodes, and shouldn't be poked
by anything else.

Thanks,
Mark.

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-05 19:30     ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-05 19:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> support of Octal core CPUs in two clusters and each cluster
> has quard Cortex-A53.
> 
> We now use the "spin-table" method for SMP, and it will be
> changed to PSCI later.

If that's the case, please don't place the enable-method and related
properties in this file. Get your bootloader to add the appropriate
properties for its boot protocol.

When is PSCI likely to appear?

Are we certain of the split between components the PSCI implementation
must touch and those the kernel must touch?

> Also add dts file to support HiKey development board which
> based on Hi6220 SoC and document the devicetree bindings.
> 
> These dts files will be changed later and more nodes will be
> added to describe other devices.

How is this going to be changed other than the addition of nodes?

Will this DTB continue to work in future? Or do you intend to make
changes that will break support?

> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
> ---
>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
>  arch/arm64/boot/dts/Makefile                       |    1 +
>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
>  5 files changed, 274 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index f717c7b..5eb6b41 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -9,6 +9,9 @@ HiP04 D01 Board
>  Required root node properties:
>  	- compatible = "hisilicon,hip04-d01";
>  
> +HiKey Board
> +Required root node properties:
> +	- compatible = "hisilicon,hi6220-hikey";
>  
>  Hisilicon system controller
>  
> @@ -62,6 +65,36 @@ Example:
>  	};
>  
>  -----------------------------------------------------------------------
> +Hisilicon Power Always ON domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,aoctrl"
> +- reg : Register address and size
> +
> +Some clock registers are defined in power always on system controller,
> +especially in Hi6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------
> +Hisilicon Media domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,mediactrl"
> +- reg : Register address and size
> +
> +Some clock registers of media module are defined in media system
> +controller, especially in Hi6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------
> +Hisilicon Power Management domain controller
> +
> +Required properties:
> +- compatible : "hisilicon,pmctrl"
> +- reg : Register address and size
> +
> +Some clock registers and PMU registers are defined in power management
> +controller, especially in Hin6220 SoC which is used for mobile platform.
> +
> +-----------------------------------------------------------------------

Looking at the dts below, none of these binding docs are sufficient.

Define _all_ the properties and what they mean.

Please also split documentation into earlier patches.

>  Fabric:
>  
>  Required Properties:
> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
> index c62b0f4..bffd6b7 100644
> --- a/arch/arm64/boot/dts/Makefile
> +++ b/arch/arm64/boot/dts/Makefile
> @@ -2,5 +2,6 @@ dts-dirs += amd
>  dts-dirs += apm
>  dts-dirs += arm
>  dts-dirs += cavium
> +dts-dirs += hisilicon
>  
>  subdir-y	:= $(dts-dirs)
> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
> new file mode 100644
> index 0000000..fa81a6e
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
> @@ -0,0 +1,5 @@
> +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
> +
> +always		:= $(dtb-y)
> +subdir-y	:= $(dts-dirs)
> +clean-files	:= *.dtb
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> new file mode 100644
> index 0000000..a94da84
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> @@ -0,0 +1,31 @@
> +/*
> + * dts file for Hisilicon HiKey Development Board
> + *
> + * Copyright (C) 2015, Hisilicon Ltd.
> + *
> + */
> +
> +/dts-v1/;
> +
> +/memreserve/ 0x0740f000 0x1000;

If you're going to use /memreserve/, please add a comment regarding what
it is intended to protect, and why that's in memory given to the kernel
to begin with.

> +
> +#include "hi6220.dtsi"
> +
> +/ {
> +	model = "HiKey Development Board";
> +	compatible = "hisilicon,hi6220-hikey";
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +	interrupt-parent = <&gic>;
> +
> +	aliases {
> +		serial0 = &uart0;
> +	};
> +
> +	chosen { };

You should use stdout-path here, ideally with the full UART
configuration.

> +
> +	memory at 7400000 {
> +		device_type = "memory";
> +		reg = <0x0 0x07400000 0x0 0x38c00000>;
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> new file mode 100644
> index 0000000..53ba9cf
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
> @@ -0,0 +1,204 @@
> +/*
> + * dts file for Hisilicon Hi6220 SoC
> + *
> + * Copyright (C) 2015, Hisilicon Ltd.
> + */
> +
> +#include <dt-bindings/clock/hi6220-clock.h>
> +
> +/ {
> +	cpu-map {

Per the binding, this must live under /cpus. 

Move this within the /cpus node.

> +		cluster0 {
> +			core0 {
> +				cpu = <&cpu0>;
> +			};
> +			core1 {
> +				cpu = <&cpu1>;
> +			};
> +			core2 {
> +				cpu = <&cpu2>;
> +			};
> +			core3 {
> +				cpu = <&cpu3>;
> +			};
> +		};
> +		cluster1 {
> +			core0 {
> +				cpu = <&cpu4>;
> +			};
> +			core1 {
> +				cpu = <&cpu5>;
> +			};
> +			core2 {
> +				cpu = <&cpu6>;
> +			};
> +			core3 {
> +				cpu = <&cpu7>;
> +			};
> +		};
> +	};
> +
> +	cpus {
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu at 000 {
> +			compatible = "arm,cortex-a53", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x0>;
> +			enable-method = "spin-table";
> +			cpu-release-addr = <0x0 0x740fff8>;

If you _must_ use spin-table, please give each CPU a unique release
address. Using a shared address was a mistake, and we should learn from
it.

Which CPU does the system boot on?

> +			clock-latency = <0>;

Why is this here?

There is no reason for this to be on any CPU node.

> +		};

[...]

> +	gic: interrupt-controller at f6800000 {
> +		compatible = "arm,gic-400", "arm,cortex-a15-gic";

Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
am I missing?

> +		reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */

This doesn't match the unit-address.

> +		      <0x0 0xf6802000 0x0 0x2000>, /* GICC */
> +		      <0x0 0xf6804000 0x0 0x2000>, /* GICH */
> +		      <0x0 0xf6806000 0x0 0x2000>; /* GICV */

I guess no-one's bothered to consider 64k pages?

Given GICH and GICV, I hope that this platform is booted at EL2?

> +		#interrupt-cells = <3>;
> +		#address-cells = <0>;
> +		interrupt-controller;
> +	};
> +
> +
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupt-parent = <&gic>;
> +		interrupts = <1 13 0xff08>,
> +			     <1 14 0xff08>,
> +			     <1 11 0xff08>,
> +			     <1 10 0xff08>;
> +		clock-frequency = <1200000>;
> +	};

NAK. Fix your firmware to configure CNTFRQ, on all CPUs.

That frequency also looks a bit low; timekeeping isn't going to be very
precise.

> +	soc {
> +		compatible = "simple-bus";
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		interrupt-parent = <&gic>;
> +		ranges;
> +
> +		ao_ctrl: ao_ctrl {
> +			compatible = "hisilicon,aoctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7800000 0x0 0x2000>;
> +			ranges = <0 0x0 0xf7800000 0x2000>;
> +
> +			clock_ao: clock0 at 0 {
> +				compatible = "hisilicon,hi6220-clock-ao";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		sys_ctrl: sys_ctrl {
> +			compatible = "hisilicon,sysctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7030000 0x0 0x2000>;
> +			ranges = <0 0x0 0xf7030000 0x2000>;
> +
> +			clock_sys: clock1 at 0 {
> +				compatible = "hisilicon,hi6220-clock-sys";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		media_ctrl: media_ctrl {
> +			compatible = "hisilicon,mediactrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf4410000 0x0 0x1000>;
> +			ranges = <0 0x0 0xf4410000 0x1000>;
> +
> +			clock_media: clock2 at 0 {
> +				compatible = "hisilicon,hi6220-clock-media";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};
> +
> +		pm_ctrl: pm_ctrl {
> +			compatible = "hisilicon,pmctrl", "syscon";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0xf7032000 0x0 0x1000>;
> +			ranges = <0 0x0 0xf7032000 0x1000>;
> +
> +			clock_power: clock3 at 0 {
> +				compatible = "hisilicon,hi6220-clock-power";
> +				reg = <0 0x1000>;
> +				#clock-cells = <1>;
> +			};
> +		};

I really doesn't see the point in having a sub-device that covers the
entirely of the register space of the containing node, and that being
the case I am extremely concerned that the containers are marked as
syscon compatible.

Why are these marked as being syscon devices? Per the dts _all_ their
registers are clearly owned by their child nodes, and shouldn't be poked
by anything else.

Thanks,
Mark.

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 23:52       ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-05 23:52 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Kevin Hilman, Mike Turquette,
	Rob Herring, Zhangfei Gao, Haojian Zhuang, Xu Wei, Jaehoon Chung,
	Haifeng Yan, Stephen Boyd, xuejiancheng, sledge.yanwei,
	Tomeu Vizoso, Russell King - ARM Linux, Guodong Xu, dan.zhao,
	huxinwei, xuyiping, victor.lixin, btw, puck.chen, wangbinghui,
	zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
> On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org> wrote:
>> Hi Bintian,
>>
>> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>>> Hello,
>>>
>>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>>> initial support for Hi6220 SoC and HiKey development board, which
>>> is based on ARM Cortex A53 architecture. Initial support is minimal
>>> and includes just the arch configuration, clock driver, device tree
>>> configuration.
>>>
>>> Many peripheral drivers will be submitted later.
>>>
>>> Any comments will be appreciated!
>>>
>>> Thanks,
>>>
>>> Bintian Wang (3):
>>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>>
>> Thanks for posting these! I've applied this series on top of
>> next-20150204, however there was some fuzz that needed to be cleaned
>> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
>> space without issue.
>
> From ramdisk only, right?

Correct, ramdisk only.

> Given the timing of the posting of this
> patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> there will be some more peripheral support as well -- at least some
> sort of storage device.

Seem fair to me. I also hope to see more patches posted shortly.

>
>
> -Olof

Cheers,

Tyler

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 23:52       ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-05 23:52 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Bintian Wang, linux-arm-kernel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd,
	xuejiancheng-hv44wF8Li93QT0dZR+AlfA,
	sledge.yanwei-hv44wF8Li93QT0dZR+AlfA

On 5 February 2015 at 11:02, Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org> wrote:
> On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
>> Hi Bintian,
>>
>> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
>>> Hello,
>>>
>>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>>> initial support for Hi6220 SoC and HiKey development board, which
>>> is based on ARM Cortex A53 architecture. Initial support is minimal
>>> and includes just the arch configuration, clock driver, device tree
>>> configuration.
>>>
>>> Many peripheral drivers will be submitted later.
>>>
>>> Any comments will be appreciated!
>>>
>>> Thanks,
>>>
>>> Bintian Wang (3):
>>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>>
>> Thanks for posting these! I've applied this series on top of
>> next-20150204, however there was some fuzz that needed to be cleaned
>> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
>> space without issue.
>
> From ramdisk only, right?

Correct, ramdisk only.

> Given the timing of the posting of this
> patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> there will be some more peripheral support as well -- at least some
> sort of storage device.

Seem fair to me. I also hope to see more patches posted shortly.

>
>
> -Olof

Cheers,

Tyler
--
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] 85+ messages in thread

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-05 23:52       ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-05 23:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
> On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org> wrote:
>> Hi Bintian,
>>
>> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>>> Hello,
>>>
>>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>>> initial support for Hi6220 SoC and HiKey development board, which
>>> is based on ARM Cortex A53 architecture. Initial support is minimal
>>> and includes just the arch configuration, clock driver, device tree
>>> configuration.
>>>
>>> Many peripheral drivers will be submitted later.
>>>
>>> Any comments will be appreciated!
>>>
>>> Thanks,
>>>
>>> Bintian Wang (3):
>>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>>
>> Thanks for posting these! I've applied this series on top of
>> next-20150204, however there was some fuzz that needed to be cleaned
>> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
>> space without issue.
>
> From ramdisk only, right?

Correct, ramdisk only.

> Given the timing of the posting of this
> patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> there will be some more peripheral support as well -- at least some
> sort of storage device.

Seem fair to me. I also hope to see more patches posted shortly.

>
>
> -Olof

Cheers,

Tyler

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
  2015-02-05 23:52       ` Tyler Baker
  (?)
  (?)
@ 2015-02-06  4:21       ` Brent Wang
  2015-02-06  6:18           ` Olof Johansson
  -1 siblings, 1 reply; 85+ messages in thread
From: Brent Wang @ 2015-02-06  4:21 UTC (permalink / raw)
  To: Tyler Baker
  Cc: Olof Johansson, Bintian Wang, linux-arm-kernel, linux-kernel,
	Catalin Marinas, Will Deacon, devicetree, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd, xuejiancheng,
	sledge.yanwei, Tomeu Vizoso, Russell King - ARM Linux,
	Guodong Xu, dan.zhao, huxinwei, xuyiping, victor.lixin, btw,
	puck.chen, wangbinghui, zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

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

Hello Olof and Tyler,

2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:

> On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org>
> wrote:
> >> Hi Bintian,
> >>
> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com>
> wrote:
> >>> Hello,
> >>>
> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> >>> initial support for Hi6220 SoC and HiKey development board, which
> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
> >>> and includes just the arch configuration, clock driver, device tree
> >>> configuration.
> >>>
> >>> Many peripheral drivers will be submitted later.
> >>>
> >>> Any comments will be appreciated!
> >>>
> >>> Thanks,
> >>>
> >>> Bintian Wang (3):
> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
> >>
> >> Thanks for posting these! I've applied this series on top of
> >> next-20150204, however there was some fuzz that needed to be cleaned
> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> >> space without issue.
> >
> > From ramdisk only, right?
>
> Correct, ramdisk only.
>
> > Given the timing of the posting of this
> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> > there will be some more peripheral support as well -- at least some
> > sort of storage device.
>
> Seem fair to me. I also hope to see more patches posted shortly.
>
Yes, the mmc and sd drivers will be submitted soon, should they be included
in this patchset?  I have thought submitting this patch first for review,
if there
is no problem for this patchset and then submit other drivers, you know,
other
drivers will depend on this patchset.

Thanks,

>
> >
> > -Olof
>
> Cheers,
>
> Tyler
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>


-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

[-- Attachment #2: Type: text/html, Size: 3688 bytes --]

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-06  6:18           ` Olof Johansson
  0 siblings, 0 replies; 85+ messages in thread
From: Olof Johansson @ 2015-02-06  6:18 UTC (permalink / raw)
  To: Brent Wang
  Cc: Tyler Baker, Bintian Wang, linux-arm-kernel, linux-kernel,
	Catalin Marinas, Will Deacon, devicetree, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd, xuejiancheng,
	sledge.yanwei, Tomeu Vizoso, Russell King - ARM Linux,
	Guodong Xu, dan.zhao, huxinwei, xuyiping, victor.lixin, btw,
	puck.chen, wangbinghui, zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

On Thu, Feb 5, 2015 at 8:21 PM, Brent Wang <wangbintian@gmail.com> wrote:
> Hello Olof and Tyler,
>
> 2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
>>
>> On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
>> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org>
>> > wrote:
>> >> Hi Bintian,
>> >>
>> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com>
>> >> wrote:
>> >>> Hello,
>> >>>
>> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>> >>> initial support for Hi6220 SoC and HiKey development board, which
>> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
>> >>> and includes just the arch configuration, clock driver, device tree
>> >>> configuration.
>> >>>
>> >>> Many peripheral drivers will be submitted later.
>> >>>
>> >>> Any comments will be appreciated!
>> >>>
>> >>> Thanks,
>> >>>
>> >>> Bintian Wang (3):
>> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>> >>
>> >> Thanks for posting these! I've applied this series on top of
>> >> next-20150204, however there was some fuzz that needed to be cleaned
>> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
>> >> space without issue.
>> >
>> > From ramdisk only, right?
>>
>> Correct, ramdisk only.
>>
>> > Given the timing of the posting of this
>> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
>> > there will be some more peripheral support as well -- at least some
>> > sort of storage device.
>>
>> Seem fair to me. I also hope to see more patches posted shortly.
>
> Yes, the mmc and sd drivers will be submitted soon, should they be included
> in this patchset?  I have thought submitting this patch first for review, if
> there
> is no problem for this patchset and then submit other drivers, you know,
> other
> drivers will depend on this patchset.


The drivers should ideally not depend on the SoC patchset -- the
driver can go in independently. The DTS updates to specify the
hardware should go in through arm-soc even if the driver itself (and
the binding document update) should go in through the driver subsystem
instead.


So, you can choose if you want to post everything as a long series,
and cc different maintainers on the various parts of the series -- or
you can post each driver or subsystem as a patchset on its own and let
that get merged through respective maintainer. The latter is most
common these days.


-Olof

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-06  6:18           ` Olof Johansson
  0 siblings, 0 replies; 85+ messages in thread
From: Olof Johansson @ 2015-02-06  6:18 UTC (permalink / raw)
  To: Brent Wang
  Cc: Tyler Baker, Bintian Wang, linux-arm-kernel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd, xuejiancheng

On Thu, Feb 5, 2015 at 8:21 PM, Brent Wang <wangbintian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Hello Olof and Tyler,
>
> 2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
>>
>> On 5 February 2015 at 11:02, Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org> wrote:
>> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> > wrote:
>> >> Hi Bintian,
>> >>
>> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> >> wrote:
>> >>> Hello,
>> >>>
>> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>> >>> initial support for Hi6220 SoC and HiKey development board, which
>> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
>> >>> and includes just the arch configuration, clock driver, device tree
>> >>> configuration.
>> >>>
>> >>> Many peripheral drivers will be submitted later.
>> >>>
>> >>> Any comments will be appreciated!
>> >>>
>> >>> Thanks,
>> >>>
>> >>> Bintian Wang (3):
>> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>> >>
>> >> Thanks for posting these! I've applied this series on top of
>> >> next-20150204, however there was some fuzz that needed to be cleaned
>> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
>> >> space without issue.
>> >
>> > From ramdisk only, right?
>>
>> Correct, ramdisk only.
>>
>> > Given the timing of the posting of this
>> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
>> > there will be some more peripheral support as well -- at least some
>> > sort of storage device.
>>
>> Seem fair to me. I also hope to see more patches posted shortly.
>
> Yes, the mmc and sd drivers will be submitted soon, should they be included
> in this patchset?  I have thought submitting this patch first for review, if
> there
> is no problem for this patchset and then submit other drivers, you know,
> other
> drivers will depend on this patchset.


The drivers should ideally not depend on the SoC patchset -- the
driver can go in independently. The DTS updates to specify the
hardware should go in through arm-soc even if the driver itself (and
the binding document update) should go in through the driver subsystem
instead.


So, you can choose if you want to post everything as a long series,
and cc different maintainers on the various parts of the series -- or
you can post each driver or subsystem as a patchset on its own and let
that get merged through respective maintainer. The latter is most
common these days.


-Olof
--
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] 85+ messages in thread

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-06  6:18           ` Olof Johansson
  0 siblings, 0 replies; 85+ messages in thread
From: Olof Johansson @ 2015-02-06  6:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 5, 2015 at 8:21 PM, Brent Wang <wangbintian@gmail.com> wrote:
> Hello Olof and Tyler,
>
> 2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
>>
>> On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
>> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org>
>> > wrote:
>> >> Hi Bintian,
>> >>
>> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com>
>> >> wrote:
>> >>> Hello,
>> >>>
>> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
>> >>> initial support for Hi6220 SoC and HiKey development board, which
>> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
>> >>> and includes just the arch configuration, clock driver, device tree
>> >>> configuration.
>> >>>
>> >>> Many peripheral drivers will be submitted later.
>> >>>
>> >>> Any comments will be appreciated!
>> >>>
>> >>> Thanks,
>> >>>
>> >>> Bintian Wang (3):
>> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
>> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
>> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
>> >>
>> >> Thanks for posting these! I've applied this series on top of
>> >> next-20150204, however there was some fuzz that needed to be cleaned
>> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
>> >> space without issue.
>> >
>> > From ramdisk only, right?
>>
>> Correct, ramdisk only.
>>
>> > Given the timing of the posting of this
>> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
>> > there will be some more peripheral support as well -- at least some
>> > sort of storage device.
>>
>> Seem fair to me. I also hope to see more patches posted shortly.
>
> Yes, the mmc and sd drivers will be submitted soon, should they be included
> in this patchset?  I have thought submitting this patch first for review, if
> there
> is no problem for this patchset and then submit other drivers, you know,
> other
> drivers will depend on this patchset.


The drivers should ideally not depend on the SoC patchset -- the
driver can go in independently. The DTS updates to specify the
hardware should go in through arm-soc even if the driver itself (and
the binding document update) should go in through the driver subsystem
instead.


So, you can choose if you want to post everything as a long series,
and cc different maintainers on the various parts of the series -- or
you can post each driver or subsystem as a patchset on its own and let
that get merged through respective maintainer. The latter is most
common these days.


-Olof

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-06  6:35             ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  6:35 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Tyler Baker, Bintian Wang, linux-arm-kernel, linux-kernel,
	Catalin Marinas, Will Deacon, devicetree, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd, xuejiancheng,
	sledge.yanwei, Tomeu Vizoso, Russell King - ARM Linux,
	Guodong Xu, dan.zhao, huxinwei, xuyiping, victor.lixin, btw,
	puck.chen, wangbinghui, zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

Hello Olof,

2015-02-06 14:18 GMT+08:00 Olof Johansson <olof@lixom.net>:
>
> On Thu, Feb 5, 2015 at 8:21 PM, Brent Wang <wangbintian@gmail.com> wrote:
> > Hello Olof and Tyler,
> >
> > 2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
> >>
> >> On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
> >> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org>
> >> > wrote:
> >> >> Hi Bintian,
> >> >>
> >> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com>
> >> >> wrote:
> >> >>> Hello,
> >> >>>
> >> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> >> >>> initial support for Hi6220 SoC and HiKey development board, which
> >> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
> >> >>> and includes just the arch configuration, clock driver, device tree
> >> >>> configuration.
> >> >>>
> >> >>> Many peripheral drivers will be submitted later.
> >> >>>
> >> >>> Any comments will be appreciated!
> >> >>>
> >> >>> Thanks,
> >> >>>
> >> >>> Bintian Wang (3):
> >> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
> >> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
> >> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
> >> >>
> >> >> Thanks for posting these! I've applied this series on top of
> >> >> next-20150204, however there was some fuzz that needed to be cleaned
> >> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> >> >> space without issue.
> >> >
> >> > From ramdisk only, right?
> >>
> >> Correct, ramdisk only.
> >>
> >> > Given the timing of the posting of this
> >> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> >> > there will be some more peripheral support as well -- at least some
> >> > sort of storage device.
> >>
> >> Seem fair to me. I also hope to see more patches posted shortly.
> >
> > Yes, the mmc and sd drivers will be submitted soon, should they be included
> > in this patchset?  I have thought submitting this patch first for review, if
> > there
> > is no problem for this patchset and then submit other drivers, you know,
> > other
> > drivers will depend on this patchset.
>
>
> The drivers should ideally not depend on the SoC patchset -- the
> driver can go in independently. The DTS updates to specify the
> hardware should go in through arm-soc even if the driver itself (and
> the binding document update) should go in through the driver subsystem
> instead.
>
>
> So, you can choose if you want to post everything as a long series,
> and cc different maintainers on the various parts of the series -- or
> you can post each driver or subsystem as a patchset on its own and let
> that get merged through respective maintainer. The latter is most
> common these days.
I think the latter is a better way, thank you!

>
>
>
> -Olof

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-06  6:35             ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  6:35 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Tyler Baker, Bintian Wang, linux-arm-kernel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Haifeng Yan, Stephen Boyd, xuejiancheng

Hello Olof,

2015-02-06 14:18 GMT+08:00 Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org>:
>
> On Thu, Feb 5, 2015 at 8:21 PM, Brent Wang <wangbintian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > Hello Olof and Tyler,
> >
> > 2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
> >>
> >> On 5 February 2015 at 11:02, Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org> wrote:
> >> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> >> > wrote:
> >> >> Hi Bintian,
> >> >>
> >> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> >> >> wrote:
> >> >>> Hello,
> >> >>>
> >> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> >> >>> initial support for Hi6220 SoC and HiKey development board, which
> >> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
> >> >>> and includes just the arch configuration, clock driver, device tree
> >> >>> configuration.
> >> >>>
> >> >>> Many peripheral drivers will be submitted later.
> >> >>>
> >> >>> Any comments will be appreciated!
> >> >>>
> >> >>> Thanks,
> >> >>>
> >> >>> Bintian Wang (3):
> >> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
> >> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
> >> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
> >> >>
> >> >> Thanks for posting these! I've applied this series on top of
> >> >> next-20150204, however there was some fuzz that needed to be cleaned
> >> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> >> >> space without issue.
> >> >
> >> > From ramdisk only, right?
> >>
> >> Correct, ramdisk only.
> >>
> >> > Given the timing of the posting of this
> >> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> >> > there will be some more peripheral support as well -- at least some
> >> > sort of storage device.
> >>
> >> Seem fair to me. I also hope to see more patches posted shortly.
> >
> > Yes, the mmc and sd drivers will be submitted soon, should they be included
> > in this patchset?  I have thought submitting this patch first for review, if
> > there
> > is no problem for this patchset and then submit other drivers, you know,
> > other
> > drivers will depend on this patchset.
>
>
> The drivers should ideally not depend on the SoC patchset -- the
> driver can go in independently. The DTS updates to specify the
> hardware should go in through arm-soc even if the driver itself (and
> the binding document update) should go in through the driver subsystem
> instead.
>
>
> So, you can choose if you want to post everything as a long series,
> and cc different maintainers on the various parts of the series -- or
> you can post each driver or subsystem as a patchset on its own and let
> that get merged through respective maintainer. The latter is most
> common these days.
I think the latter is a better way, thank you!

>
>
>
> -Olof

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!
--
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] 85+ messages in thread

* [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC
@ 2015-02-06  6:35             ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  6:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Olof,

2015-02-06 14:18 GMT+08:00 Olof Johansson <olof@lixom.net>:
>
> On Thu, Feb 5, 2015 at 8:21 PM, Brent Wang <wangbintian@gmail.com> wrote:
> > Hello Olof and Tyler,
> >
> > 2015-02-06 7:52 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
> >>
> >> On 5 February 2015 at 11:02, Olof Johansson <olof@lixom.net> wrote:
> >> > On Thu, Feb 5, 2015 at 10:46 AM, Tyler Baker <tyler.baker@linaro.org>
> >> > wrote:
> >> >> Hi Bintian,
> >> >>
> >> >> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com>
> >> >> wrote:
> >> >>> Hello,
> >> >>>
> >> >>> Hi6220 is one mobile solution of Hisilicon, this patchset contains
> >> >>> initial support for Hi6220 SoC and HiKey development board, which
> >> >>> is based on ARM Cortex A53 architecture. Initial support is minimal
> >> >>> and includes just the arch configuration, clock driver, device tree
> >> >>> configuration.
> >> >>>
> >> >>> Many peripheral drivers will be submitted later.
> >> >>>
> >> >>> Any comments will be appreciated!
> >> >>>
> >> >>> Thanks,
> >> >>>
> >> >>> Bintian Wang (3):
> >> >>>   arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig
> >> >>>   clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
> >> >>>   arm64: dts: Add dts files for Hisilicon Hi6220 SoC
> >> >>
> >> >> Thanks for posting these! I've applied this series on top of
> >> >> next-20150204, however there was some fuzz that needed to be cleaned
> >> >> up on 3/3 [1]. I've confirmed the platform is booting to a basic user
> >> >> space without issue.
> >> >
> >> > From ramdisk only, right?
> >>
> >> Correct, ramdisk only.
> >>
> >> > Given the timing of the posting of this
> >> > patch set, I'm not going to merge it for 3.20. Hopefully for 3.21
> >> > there will be some more peripheral support as well -- at least some
> >> > sort of storage device.
> >>
> >> Seem fair to me. I also hope to see more patches posted shortly.
> >
> > Yes, the mmc and sd drivers will be submitted soon, should they be included
> > in this patchset?  I have thought submitting this patch first for review, if
> > there
> > is no problem for this patchset and then submit other drivers, you know,
> > other
> > drivers will depend on this patchset.
>
>
> The drivers should ideally not depend on the SoC patchset -- the
> driver can go in independently. The DTS updates to specify the
> hardware should go in through arm-soc even if the driver itself (and
> the binding document update) should go in through the driver subsystem
> instead.
>
>
> So, you can choose if you want to post everything as a long series,
> and cc different maintainers on the various parts of the series -- or
> you can post each driver or subsystem as a patchset on its own and let
> that get merged through respective maintainer. The latter is most
> common these days.
I think the latter is a better way, thank you!

>
>
>
> -Olof

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  2015-02-05 19:25     ` Mark Rutland
  (?)
@ 2015-02-06  7:32       ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  7:32 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

Hi Mark,

2015-02-06 3:25 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Thu, Feb 05, 2015 at 09:24:36AM +0000, Bintian Wang wrote:
>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>> registers to supply different clocks to different IPs in the SoC.
>>
>> We add one divider clock for hi6220 because the divider in hi6220
>> also has a mask bit but it doesnot obey the rule defined by flag
>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>> to handle it.
>>
>> This patch also enables this clock driver for ARCH_HISI and document
>> devicetree bindings.
>>
>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> ---
>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>  arch/arm64/Kconfig                                 |    1 +
>>  drivers/clk/Kconfig                                |    2 +
>>  drivers/clk/Makefile                               |    4 +-
>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> new file mode 100644
>> index 0000000..a3ddda1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> @@ -0,0 +1,30 @@
>> +* Hisilicon Hi6220 Clock Controller
>> +
>> +The hi6220 clock controller generates and supplies clock to various
>> +controllers within the hi6220 SoC.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be one of the following:
>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>> +     power always on(AO) domain, it is the sub node of SoC power AO
>> +     controller in dts file.
>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>> +     system control domain, it is the sub node of SoC system controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>> +     SoC media control domain, it is the sub node of SoC media controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>> +     SoC power control domain, it is the sub node of SoC power controller
>> +     in dts file.
>
> These all refer to things which aren't documented (yet).
>
> Please sort out your patches so that any documentation you depend on
> comes earlier.
>
> Please also separate documentation from code. Note that dt includes are
> _bindings_ and should be added with the relevant documentation.
Thanks for help to review, I also think separate documentation from
code is better
way, it will be fixed in next version.

Thanks,

Bintian
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-06  7:32       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  7:32 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Pawel Moll,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, khilman-QSEj5FYQhm4dnm+yROfE0A,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	rob.herring-QSEj5FYQhm4dnm+yROfE0A,
	zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A,
	haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, jh80.chung-Sze3O3UU22JBDgjK7y7TUQ

Hi Mark,

2015-02-06 3:25 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
> On Thu, Feb 05, 2015 at 09:24:36AM +0000, Bintian Wang wrote:
>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>> registers to supply different clocks to different IPs in the SoC.
>>
>> We add one divider clock for hi6220 because the divider in hi6220
>> also has a mask bit but it doesnot obey the rule defined by flag
>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>> to handle it.
>>
>> This patch also enables this clock driver for ARCH_HISI and document
>> devicetree bindings.
>>
>> Signed-off-by: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Reviewed-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>  arch/arm64/Kconfig                                 |    1 +
>>  drivers/clk/Kconfig                                |    2 +
>>  drivers/clk/Makefile                               |    4 +-
>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> new file mode 100644
>> index 0000000..a3ddda1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> @@ -0,0 +1,30 @@
>> +* Hisilicon Hi6220 Clock Controller
>> +
>> +The hi6220 clock controller generates and supplies clock to various
>> +controllers within the hi6220 SoC.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be one of the following:
>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>> +     power always on(AO) domain, it is the sub node of SoC power AO
>> +     controller in dts file.
>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>> +     system control domain, it is the sub node of SoC system controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>> +     SoC media control domain, it is the sub node of SoC media controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>> +     SoC power control domain, it is the sub node of SoC power controller
>> +     in dts file.
>
> These all refer to things which aren't documented (yet).
>
> Please sort out your patches so that any documentation you depend on
> comes earlier.
>
> Please also separate documentation from code. Note that dt includes are
> _bindings_ and should be added with the relevant documentation.
Thanks for help to review, I also think separate documentation from
code is better
way, it will be fixed in next version.

Thanks,

Bintian
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
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] 85+ messages in thread

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-06  7:32       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  7:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mark,

2015-02-06 3:25 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Thu, Feb 05, 2015 at 09:24:36AM +0000, Bintian Wang wrote:
>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>> registers to supply different clocks to different IPs in the SoC.
>>
>> We add one divider clock for hi6220 because the divider in hi6220
>> also has a mask bit but it doesnot obey the rule defined by flag
>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>> to handle it.
>>
>> This patch also enables this clock driver for ARCH_HISI and document
>> devicetree bindings.
>>
>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> ---
>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>  arch/arm64/Kconfig                                 |    1 +
>>  drivers/clk/Kconfig                                |    2 +
>>  drivers/clk/Makefile                               |    4 +-
>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> new file mode 100644
>> index 0000000..a3ddda1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> @@ -0,0 +1,30 @@
>> +* Hisilicon Hi6220 Clock Controller
>> +
>> +The hi6220 clock controller generates and supplies clock to various
>> +controllers within the hi6220 SoC.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be one of the following:
>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>> +     power always on(AO) domain, it is the sub node of SoC power AO
>> +     controller in dts file.
>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>> +     system control domain, it is the sub node of SoC system controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>> +     SoC media control domain, it is the sub node of SoC media controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>> +     SoC power control domain, it is the sub node of SoC power controller
>> +     in dts file.
>
> These all refer to things which aren't documented (yet).
>
> Please sort out your patches so that any documentation you depend on
> comes earlier.
>
> Please also separate documentation from code. Note that dt includes are
> _bindings_ and should be added with the relevant documentation.
Thanks for help to review, I also think separate documentation from
code is better
way, it will be fixed in next version.

Thanks,

Bintian
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-05 19:30     ` Mark Rutland
  (?)
@ 2015-02-06  8:42       ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  8:42 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

Hello Mark,

2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> support of Octal core CPUs in two clusters and each cluster
>> has quard Cortex-A53.
>>
>> We now use the "spin-table" method for SMP, and it will be
>> changed to PSCI later.
>
> If that's the case, please don't place the enable-method and related
> properties in this file. Get your bootloader to add the appropriate
> properties for its boot protocol.
>
> When is PSCI likely to appear?
PSCI is under development.

>
> Are we certain of the split between components the PSCI implementation
> must touch and those the kernel must touch?
>
>> Also add dts file to support HiKey development board which
>> based on Hi6220 SoC and document the devicetree bindings.
>>
>> These dts files will be changed later and more nodes will be
>> added to describe other devices.
>
> How is this going to be changed other than the addition of nodes?
>
> Will this DTB continue to work in future? Or do you intend to make
> changes that will break support?
My original idea is: use spin-table for SMP now, when firmware is OK to
support PSCI, we submit another patch to replace the spin-table with PSCI.

If DTB should continue to work in the future, we really need to remove
the spin-table
from current dts file, how about just enable one core now?

Which one do you favor or any other suggestion?

>
>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
>> ---
>>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
>>  arch/arm64/boot/dts/Makefile                       |    1 +
>>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
>>  5 files changed, 274 insertions(+)
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>>
>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> index f717c7b..5eb6b41 100644
>> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> @@ -9,6 +9,9 @@ HiP04 D01 Board
>>  Required root node properties:
>>       - compatible = "hisilicon,hip04-d01";
>>
>> +HiKey Board
>> +Required root node properties:
>> +     - compatible = "hisilicon,hi6220-hikey";
>>
>>  Hisilicon system controller
>>
>> @@ -62,6 +65,36 @@ Example:
>>       };
>>
>>  -----------------------------------------------------------------------
>> +Hisilicon Power Always ON domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,aoctrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers are defined in power always on system controller,
>> +especially in Hi6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>> +Hisilicon Media domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,mediactrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers of media module are defined in media system
>> +controller, especially in Hi6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>> +Hisilicon Power Management domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,pmctrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers and PMU registers are defined in power management
>> +controller, especially in Hin6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>
> Looking at the dts below, none of these binding docs are sufficient.
>
> Define _all_ the properties and what they mean.
In fact, Hisilicon designs several system controllers for different
function domains,
we can control different functions(e.g. clk gate on or off /IP reset)
based on the base
address of controller + offset, I will give more description in next version.

> Please also split documentation into earlier patches.
OK, separate document and code in next version.

>
>>  Fabric:
>>
>>  Required Properties:
>> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
>> index c62b0f4..bffd6b7 100644
>> --- a/arch/arm64/boot/dts/Makefile
>> +++ b/arch/arm64/boot/dts/Makefile
>> @@ -2,5 +2,6 @@ dts-dirs += amd
>>  dts-dirs += apm
>>  dts-dirs += arm
>>  dts-dirs += cavium
>> +dts-dirs += hisilicon
>>
>>  subdir-y     := $(dts-dirs)
>> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
>> new file mode 100644
>> index 0000000..fa81a6e
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
>> @@ -0,0 +1,5 @@
>> +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
>> +
>> +always               := $(dtb-y)
>> +subdir-y     := $(dts-dirs)
>> +clean-files  := *.dtb
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>> new file mode 100644
>> index 0000000..a94da84
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>> @@ -0,0 +1,31 @@
>> +/*
>> + * dts file for Hisilicon HiKey Development Board
>> + *
>> + * Copyright (C) 2015, Hisilicon Ltd.
>> + *
>> + */
>> +
>> +/dts-v1/;
>> +
>> +/memreserve/ 0x0740f000 0x1000;
>
> If you're going to use /memreserve/, please add a comment regarding what
> it is intended to protect, and why that's in memory given to the kernel
> to begin with.
>
>> +
>> +#include "hi6220.dtsi"
>> +
>> +/ {
>> +     model = "HiKey Development Board";
>> +     compatible = "hisilicon,hi6220-hikey";
>> +     #address-cells = <2>;
>> +     #size-cells = <2>;
>> +     interrupt-parent = <&gic>;
>> +
>> +     aliases {
>> +             serial0 = &uart0;
>> +     };
>> +
>> +     chosen { };
>
> You should use stdout-path here, ideally with the full UART
> configuration.
Add in next version.

>> +
>> +     memory@7400000 {
>> +             device_type = "memory";
>> +             reg = <0x0 0x07400000 0x0 0x38c00000>;
>> +     };
>> +};
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>> new file mode 100644
>> index 0000000..53ba9cf
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>> @@ -0,0 +1,204 @@
>> +/*
>> + * dts file for Hisilicon Hi6220 SoC
>> + *
>> + * Copyright (C) 2015, Hisilicon Ltd.
>> + */
>> +
>> +#include <dt-bindings/clock/hi6220-clock.h>
>> +
>> +/ {
>> +     cpu-map {
>
> Per the binding, this must live under /cpus.
>
> Move this within the /cpus node.
>
>> +             cluster0 {
>> +                     core0 {
>> +                             cpu = <&cpu0>;
>> +                     };
>> +                     core1 {
>> +                             cpu = <&cpu1>;
>> +                     };
>> +                     core2 {
>> +                             cpu = <&cpu2>;
>> +                     };
>> +                     core3 {
>> +                             cpu = <&cpu3>;
>> +                     };
>> +             };
>> +             cluster1 {
>> +                     core0 {
>> +                             cpu = <&cpu4>;
>> +                     };
>> +                     core1 {
>> +                             cpu = <&cpu5>;
>> +                     };
>> +                     core2 {
>> +                             cpu = <&cpu6>;
>> +                     };
>> +                     core3 {
>> +                             cpu = <&cpu7>;
>> +                     };
>> +             };
>> +     };
>> +
>> +     cpus {
>> +             #address-cells = <2>;
>> +             #size-cells = <0>;
>> +
>> +             cpu0: cpu@000 {
>> +                     compatible = "arm,cortex-a53", "arm,armv8";
>> +                     device_type = "cpu";
>> +                     reg = <0x0 0x0>;
>> +                     enable-method = "spin-table";
>> +                     cpu-release-addr = <0x0 0x740fff8>;
>
> If you _must_ use spin-table, please give each CPU a unique release
> address. Using a shared address was a mistake, and we should learn from
> it.
>
> Which CPU does the system boot on?
>
>> +                     clock-latency = <0>;
>
> Why is this here?
>
> There is no reason for this to be on any CPU node.
Fix in next version.

>
>> +             };
>
> [...]
>
>> +     gic: interrupt-controller@f6800000 {
>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>
> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
> am I missing?
Remove it in next version.

>
>> +             reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
>
> This doesn't match the unit-address.
Do you mean change to "<0x0 0xf6801000 0 0x1000>" ?

>
>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>
> I guess no-one's bothered to consider 64k pages?
>
> Given GICH and GICV, I hope that this platform is booted at EL2?
Transfer from EL3 to EL1 directly, keep these two just for future use.

>
>> +             #interrupt-cells = <3>;
>> +             #address-cells = <0>;
>> +             interrupt-controller;
>> +     };
>> +
>> +
>> +     timer {
>> +             compatible = "arm,armv8-timer";
>> +             interrupt-parent = <&gic>;
>> +             interrupts = <1 13 0xff08>,
>> +                          <1 14 0xff08>,
>> +                          <1 11 0xff08>,
>> +                          <1 10 0xff08>;
>> +             clock-frequency = <1200000>;
>> +     };
>
> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
Fix in next version, maybe it will take some time to change firmware.

>
> That frequency also looks a bit low; timekeeping isn't going to be very
> precise.
>
>> +     soc {
>> +             compatible = "simple-bus";
>> +             #address-cells = <2>;
>> +             #size-cells = <2>;
>> +             interrupt-parent = <&gic>;
>> +             ranges;
>> +
>> +             ao_ctrl: ao_ctrl {
>> +                     compatible = "hisilicon,aoctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7800000 0x0 0x2000>;
>> +                     ranges = <0 0x0 0xf7800000 0x2000>;
>> +
>> +                     clock_ao: clock0@0 {
>> +                             compatible = "hisilicon,hi6220-clock-ao";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             sys_ctrl: sys_ctrl {
>> +                     compatible = "hisilicon,sysctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7030000 0x0 0x2000>;
>> +                     ranges = <0 0x0 0xf7030000 0x2000>;
>> +
>> +                     clock_sys: clock1@0 {
>> +                             compatible = "hisilicon,hi6220-clock-sys";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             media_ctrl: media_ctrl {
>> +                     compatible = "hisilicon,mediactrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf4410000 0x0 0x1000>;
>> +                     ranges = <0 0x0 0xf4410000 0x1000>;
>> +
>> +                     clock_media: clock2@0 {
>> +                             compatible = "hisilicon,hi6220-clock-media";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             pm_ctrl: pm_ctrl {
>> +                     compatible = "hisilicon,pmctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> +
>> +                     clock_power: clock3@0 {
>> +                             compatible = "hisilicon,hi6220-clock-power";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>
> I really doesn't see the point in having a sub-device that covers the
> entirely of the register space of the containing node, and that being
> the case I am extremely concerned that the containers are marked as
> syscon compatible.
The SoC clocks are designed and placed under different system controllers,
so I define corresponding nodes under different controllers for clock operation.

>
> Why are these marked as being syscon devices? Per the dts _all_ their
> registers are clearly owned by their child nodes, and shouldn't be poked
> by anything else.
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06  8:42       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  8:42 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Pawel Moll,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, khilman-QSEj5FYQhm4dnm+yROfE0A,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	rob.herring-QSEj5FYQhm4dnm+yROfE0A,
	zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A,
	haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, jh80.chung-Sze3O3UU22JBDgjK7y7TUQ

Hello Mark,

2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
> On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> support of Octal core CPUs in two clusters and each cluster
>> has quard Cortex-A53.
>>
>> We now use the "spin-table" method for SMP, and it will be
>> changed to PSCI later.
>
> If that's the case, please don't place the enable-method and related
> properties in this file. Get your bootloader to add the appropriate
> properties for its boot protocol.
>
> When is PSCI likely to appear?
PSCI is under development.

>
> Are we certain of the split between components the PSCI implementation
> must touch and those the kernel must touch?
>
>> Also add dts file to support HiKey development board which
>> based on Hi6220 SoC and document the devicetree bindings.
>>
>> These dts files will be changed later and more nodes will be
>> added to describe other devices.
>
> How is this going to be changed other than the addition of nodes?
>
> Will this DTB continue to work in future? Or do you intend to make
> changes that will break support?
My original idea is: use spin-table for SMP now, when firmware is OK to
support PSCI, we submit another patch to replace the spin-table with PSCI.

If DTB should continue to work in the future, we really need to remove
the spin-table
from current dts file, how about just enable one core now?

Which one do you favor or any other suggestion?

>
>> Signed-off-by: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Reviewed-by: Yiping Xu <xuyiping-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>> ---
>>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
>>  arch/arm64/boot/dts/Makefile                       |    1 +
>>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
>>  5 files changed, 274 insertions(+)
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>>
>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> index f717c7b..5eb6b41 100644
>> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> @@ -9,6 +9,9 @@ HiP04 D01 Board
>>  Required root node properties:
>>       - compatible = "hisilicon,hip04-d01";
>>
>> +HiKey Board
>> +Required root node properties:
>> +     - compatible = "hisilicon,hi6220-hikey";
>>
>>  Hisilicon system controller
>>
>> @@ -62,6 +65,36 @@ Example:
>>       };
>>
>>  -----------------------------------------------------------------------
>> +Hisilicon Power Always ON domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,aoctrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers are defined in power always on system controller,
>> +especially in Hi6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>> +Hisilicon Media domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,mediactrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers of media module are defined in media system
>> +controller, especially in Hi6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>> +Hisilicon Power Management domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,pmctrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers and PMU registers are defined in power management
>> +controller, especially in Hin6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>
> Looking at the dts below, none of these binding docs are sufficient.
>
> Define _all_ the properties and what they mean.
In fact, Hisilicon designs several system controllers for different
function domains,
we can control different functions(e.g. clk gate on or off /IP reset)
based on the base
address of controller + offset, I will give more description in next version.

> Please also split documentation into earlier patches.
OK, separate document and code in next version.

>
>>  Fabric:
>>
>>  Required Properties:
>> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
>> index c62b0f4..bffd6b7 100644
>> --- a/arch/arm64/boot/dts/Makefile
>> +++ b/arch/arm64/boot/dts/Makefile
>> @@ -2,5 +2,6 @@ dts-dirs += amd
>>  dts-dirs += apm
>>  dts-dirs += arm
>>  dts-dirs += cavium
>> +dts-dirs += hisilicon
>>
>>  subdir-y     := $(dts-dirs)
>> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
>> new file mode 100644
>> index 0000000..fa81a6e
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
>> @@ -0,0 +1,5 @@
>> +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
>> +
>> +always               := $(dtb-y)
>> +subdir-y     := $(dts-dirs)
>> +clean-files  := *.dtb
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>> new file mode 100644
>> index 0000000..a94da84
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>> @@ -0,0 +1,31 @@
>> +/*
>> + * dts file for Hisilicon HiKey Development Board
>> + *
>> + * Copyright (C) 2015, Hisilicon Ltd.
>> + *
>> + */
>> +
>> +/dts-v1/;
>> +
>> +/memreserve/ 0x0740f000 0x1000;
>
> If you're going to use /memreserve/, please add a comment regarding what
> it is intended to protect, and why that's in memory given to the kernel
> to begin with.
>
>> +
>> +#include "hi6220.dtsi"
>> +
>> +/ {
>> +     model = "HiKey Development Board";
>> +     compatible = "hisilicon,hi6220-hikey";
>> +     #address-cells = <2>;
>> +     #size-cells = <2>;
>> +     interrupt-parent = <&gic>;
>> +
>> +     aliases {
>> +             serial0 = &uart0;
>> +     };
>> +
>> +     chosen { };
>
> You should use stdout-path here, ideally with the full UART
> configuration.
Add in next version.

>> +
>> +     memory@7400000 {
>> +             device_type = "memory";
>> +             reg = <0x0 0x07400000 0x0 0x38c00000>;
>> +     };
>> +};
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>> new file mode 100644
>> index 0000000..53ba9cf
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>> @@ -0,0 +1,204 @@
>> +/*
>> + * dts file for Hisilicon Hi6220 SoC
>> + *
>> + * Copyright (C) 2015, Hisilicon Ltd.
>> + */
>> +
>> +#include <dt-bindings/clock/hi6220-clock.h>
>> +
>> +/ {
>> +     cpu-map {
>
> Per the binding, this must live under /cpus.
>
> Move this within the /cpus node.
>
>> +             cluster0 {
>> +                     core0 {
>> +                             cpu = <&cpu0>;
>> +                     };
>> +                     core1 {
>> +                             cpu = <&cpu1>;
>> +                     };
>> +                     core2 {
>> +                             cpu = <&cpu2>;
>> +                     };
>> +                     core3 {
>> +                             cpu = <&cpu3>;
>> +                     };
>> +             };
>> +             cluster1 {
>> +                     core0 {
>> +                             cpu = <&cpu4>;
>> +                     };
>> +                     core1 {
>> +                             cpu = <&cpu5>;
>> +                     };
>> +                     core2 {
>> +                             cpu = <&cpu6>;
>> +                     };
>> +                     core3 {
>> +                             cpu = <&cpu7>;
>> +                     };
>> +             };
>> +     };
>> +
>> +     cpus {
>> +             #address-cells = <2>;
>> +             #size-cells = <0>;
>> +
>> +             cpu0: cpu@000 {
>> +                     compatible = "arm,cortex-a53", "arm,armv8";
>> +                     device_type = "cpu";
>> +                     reg = <0x0 0x0>;
>> +                     enable-method = "spin-table";
>> +                     cpu-release-addr = <0x0 0x740fff8>;
>
> If you _must_ use spin-table, please give each CPU a unique release
> address. Using a shared address was a mistake, and we should learn from
> it.
>
> Which CPU does the system boot on?
>
>> +                     clock-latency = <0>;
>
> Why is this here?
>
> There is no reason for this to be on any CPU node.
Fix in next version.

>
>> +             };
>
> [...]
>
>> +     gic: interrupt-controller@f6800000 {
>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>
> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
> am I missing?
Remove it in next version.

>
>> +             reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
>
> This doesn't match the unit-address.
Do you mean change to "<0x0 0xf6801000 0 0x1000>" ?

>
>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>
> I guess no-one's bothered to consider 64k pages?
>
> Given GICH and GICV, I hope that this platform is booted at EL2?
Transfer from EL3 to EL1 directly, keep these two just for future use.

>
>> +             #interrupt-cells = <3>;
>> +             #address-cells = <0>;
>> +             interrupt-controller;
>> +     };
>> +
>> +
>> +     timer {
>> +             compatible = "arm,armv8-timer";
>> +             interrupt-parent = <&gic>;
>> +             interrupts = <1 13 0xff08>,
>> +                          <1 14 0xff08>,
>> +                          <1 11 0xff08>,
>> +                          <1 10 0xff08>;
>> +             clock-frequency = <1200000>;
>> +     };
>
> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
Fix in next version, maybe it will take some time to change firmware.

>
> That frequency also looks a bit low; timekeeping isn't going to be very
> precise.
>
>> +     soc {
>> +             compatible = "simple-bus";
>> +             #address-cells = <2>;
>> +             #size-cells = <2>;
>> +             interrupt-parent = <&gic>;
>> +             ranges;
>> +
>> +             ao_ctrl: ao_ctrl {
>> +                     compatible = "hisilicon,aoctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7800000 0x0 0x2000>;
>> +                     ranges = <0 0x0 0xf7800000 0x2000>;
>> +
>> +                     clock_ao: clock0@0 {
>> +                             compatible = "hisilicon,hi6220-clock-ao";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             sys_ctrl: sys_ctrl {
>> +                     compatible = "hisilicon,sysctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7030000 0x0 0x2000>;
>> +                     ranges = <0 0x0 0xf7030000 0x2000>;
>> +
>> +                     clock_sys: clock1@0 {
>> +                             compatible = "hisilicon,hi6220-clock-sys";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             media_ctrl: media_ctrl {
>> +                     compatible = "hisilicon,mediactrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf4410000 0x0 0x1000>;
>> +                     ranges = <0 0x0 0xf4410000 0x1000>;
>> +
>> +                     clock_media: clock2@0 {
>> +                             compatible = "hisilicon,hi6220-clock-media";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             pm_ctrl: pm_ctrl {
>> +                     compatible = "hisilicon,pmctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> +
>> +                     clock_power: clock3@0 {
>> +                             compatible = "hisilicon,hi6220-clock-power";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>
> I really doesn't see the point in having a sub-device that covers the
> entirely of the register space of the containing node, and that being
> the case I am extremely concerned that the containers are marked as
> syscon compatible.
The SoC clocks are designed and placed under different system controllers,
so I define corresponding nodes under different controllers for clock operation.

>
> Why are these marked as being syscon devices? Per the dts _all_ their
> registers are clearly owned by their child nodes, and shouldn't be poked
> by anything else.
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!
--
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] 85+ messages in thread

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06  8:42       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06  8:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Mark,

2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> support of Octal core CPUs in two clusters and each cluster
>> has quard Cortex-A53.
>>
>> We now use the "spin-table" method for SMP, and it will be
>> changed to PSCI later.
>
> If that's the case, please don't place the enable-method and related
> properties in this file. Get your bootloader to add the appropriate
> properties for its boot protocol.
>
> When is PSCI likely to appear?
PSCI is under development.

>
> Are we certain of the split between components the PSCI implementation
> must touch and those the kernel must touch?
>
>> Also add dts file to support HiKey development board which
>> based on Hi6220 SoC and document the devicetree bindings.
>>
>> These dts files will be changed later and more nodes will be
>> added to describe other devices.
>
> How is this going to be changed other than the addition of nodes?
>
> Will this DTB continue to work in future? Or do you intend to make
> changes that will break support?
My original idea is: use spin-table for SMP now, when firmware is OK to
support PSCI, we submit another patch to replace the spin-table with PSCI.

If DTB should continue to work in the future, we really need to remove
the spin-table
from current dts file, how about just enable one core now?

Which one do you favor or any other suggestion?

>
>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Reviewed-by: Yiping Xu <xuyiping@hisilicon.com>
>> ---
>>  .../bindings/arm/hisilicon/hisilicon.txt           |   33 ++++
>>  arch/arm64/boot/dts/Makefile                       |    1 +
>>  arch/arm64/boot/dts/hisilicon/Makefile             |    5 +
>>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   31 +++
>>  arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  204 ++++++++++++++++++++
>>  5 files changed, 274 insertions(+)
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/Makefile
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>>  create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>>
>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> index f717c7b..5eb6b41 100644
>> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
>> @@ -9,6 +9,9 @@ HiP04 D01 Board
>>  Required root node properties:
>>       - compatible = "hisilicon,hip04-d01";
>>
>> +HiKey Board
>> +Required root node properties:
>> +     - compatible = "hisilicon,hi6220-hikey";
>>
>>  Hisilicon system controller
>>
>> @@ -62,6 +65,36 @@ Example:
>>       };
>>
>>  -----------------------------------------------------------------------
>> +Hisilicon Power Always ON domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,aoctrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers are defined in power always on system controller,
>> +especially in Hi6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>> +Hisilicon Media domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,mediactrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers of media module are defined in media system
>> +controller, especially in Hi6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>> +Hisilicon Power Management domain controller
>> +
>> +Required properties:
>> +- compatible : "hisilicon,pmctrl"
>> +- reg : Register address and size
>> +
>> +Some clock registers and PMU registers are defined in power management
>> +controller, especially in Hin6220 SoC which is used for mobile platform.
>> +
>> +-----------------------------------------------------------------------
>
> Looking at the dts below, none of these binding docs are sufficient.
>
> Define _all_ the properties and what they mean.
In fact, Hisilicon designs several system controllers for different
function domains,
we can control different functions(e.g. clk gate on or off /IP reset)
based on the base
address of controller + offset, I will give more description in next version.

> Please also split documentation into earlier patches.
OK, separate document and code in next version.

>
>>  Fabric:
>>
>>  Required Properties:
>> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
>> index c62b0f4..bffd6b7 100644
>> --- a/arch/arm64/boot/dts/Makefile
>> +++ b/arch/arm64/boot/dts/Makefile
>> @@ -2,5 +2,6 @@ dts-dirs += amd
>>  dts-dirs += apm
>>  dts-dirs += arm
>>  dts-dirs += cavium
>> +dts-dirs += hisilicon
>>
>>  subdir-y     := $(dts-dirs)
>> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
>> new file mode 100644
>> index 0000000..fa81a6e
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
>> @@ -0,0 +1,5 @@
>> +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
>> +
>> +always               := $(dtb-y)
>> +subdir-y     := $(dts-dirs)
>> +clean-files  := *.dtb
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>> new file mode 100644
>> index 0000000..a94da84
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
>> @@ -0,0 +1,31 @@
>> +/*
>> + * dts file for Hisilicon HiKey Development Board
>> + *
>> + * Copyright (C) 2015, Hisilicon Ltd.
>> + *
>> + */
>> +
>> +/dts-v1/;
>> +
>> +/memreserve/ 0x0740f000 0x1000;
>
> If you're going to use /memreserve/, please add a comment regarding what
> it is intended to protect, and why that's in memory given to the kernel
> to begin with.
>
>> +
>> +#include "hi6220.dtsi"
>> +
>> +/ {
>> +     model = "HiKey Development Board";
>> +     compatible = "hisilicon,hi6220-hikey";
>> +     #address-cells = <2>;
>> +     #size-cells = <2>;
>> +     interrupt-parent = <&gic>;
>> +
>> +     aliases {
>> +             serial0 = &uart0;
>> +     };
>> +
>> +     chosen { };
>
> You should use stdout-path here, ideally with the full UART
> configuration.
Add in next version.

>> +
>> +     memory at 7400000 {
>> +             device_type = "memory";
>> +             reg = <0x0 0x07400000 0x0 0x38c00000>;
>> +     };
>> +};
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>> new file mode 100644
>> index 0000000..53ba9cf
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>> @@ -0,0 +1,204 @@
>> +/*
>> + * dts file for Hisilicon Hi6220 SoC
>> + *
>> + * Copyright (C) 2015, Hisilicon Ltd.
>> + */
>> +
>> +#include <dt-bindings/clock/hi6220-clock.h>
>> +
>> +/ {
>> +     cpu-map {
>
> Per the binding, this must live under /cpus.
>
> Move this within the /cpus node.
>
>> +             cluster0 {
>> +                     core0 {
>> +                             cpu = <&cpu0>;
>> +                     };
>> +                     core1 {
>> +                             cpu = <&cpu1>;
>> +                     };
>> +                     core2 {
>> +                             cpu = <&cpu2>;
>> +                     };
>> +                     core3 {
>> +                             cpu = <&cpu3>;
>> +                     };
>> +             };
>> +             cluster1 {
>> +                     core0 {
>> +                             cpu = <&cpu4>;
>> +                     };
>> +                     core1 {
>> +                             cpu = <&cpu5>;
>> +                     };
>> +                     core2 {
>> +                             cpu = <&cpu6>;
>> +                     };
>> +                     core3 {
>> +                             cpu = <&cpu7>;
>> +                     };
>> +             };
>> +     };
>> +
>> +     cpus {
>> +             #address-cells = <2>;
>> +             #size-cells = <0>;
>> +
>> +             cpu0: cpu at 000 {
>> +                     compatible = "arm,cortex-a53", "arm,armv8";
>> +                     device_type = "cpu";
>> +                     reg = <0x0 0x0>;
>> +                     enable-method = "spin-table";
>> +                     cpu-release-addr = <0x0 0x740fff8>;
>
> If you _must_ use spin-table, please give each CPU a unique release
> address. Using a shared address was a mistake, and we should learn from
> it.
>
> Which CPU does the system boot on?
>
>> +                     clock-latency = <0>;
>
> Why is this here?
>
> There is no reason for this to be on any CPU node.
Fix in next version.

>
>> +             };
>
> [...]
>
>> +     gic: interrupt-controller at f6800000 {
>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>
> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
> am I missing?
Remove it in next version.

>
>> +             reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
>
> This doesn't match the unit-address.
Do you mean change to "<0x0 0xf6801000 0 0x1000>" ?

>
>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>
> I guess no-one's bothered to consider 64k pages?
>
> Given GICH and GICV, I hope that this platform is booted at EL2?
Transfer from EL3 to EL1 directly, keep these two just for future use.

>
>> +             #interrupt-cells = <3>;
>> +             #address-cells = <0>;
>> +             interrupt-controller;
>> +     };
>> +
>> +
>> +     timer {
>> +             compatible = "arm,armv8-timer";
>> +             interrupt-parent = <&gic>;
>> +             interrupts = <1 13 0xff08>,
>> +                          <1 14 0xff08>,
>> +                          <1 11 0xff08>,
>> +                          <1 10 0xff08>;
>> +             clock-frequency = <1200000>;
>> +     };
>
> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
Fix in next version, maybe it will take some time to change firmware.

>
> That frequency also looks a bit low; timekeeping isn't going to be very
> precise.
>
>> +     soc {
>> +             compatible = "simple-bus";
>> +             #address-cells = <2>;
>> +             #size-cells = <2>;
>> +             interrupt-parent = <&gic>;
>> +             ranges;
>> +
>> +             ao_ctrl: ao_ctrl {
>> +                     compatible = "hisilicon,aoctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7800000 0x0 0x2000>;
>> +                     ranges = <0 0x0 0xf7800000 0x2000>;
>> +
>> +                     clock_ao: clock0 at 0 {
>> +                             compatible = "hisilicon,hi6220-clock-ao";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             sys_ctrl: sys_ctrl {
>> +                     compatible = "hisilicon,sysctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7030000 0x0 0x2000>;
>> +                     ranges = <0 0x0 0xf7030000 0x2000>;
>> +
>> +                     clock_sys: clock1 at 0 {
>> +                             compatible = "hisilicon,hi6220-clock-sys";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             media_ctrl: media_ctrl {
>> +                     compatible = "hisilicon,mediactrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf4410000 0x0 0x1000>;
>> +                     ranges = <0 0x0 0xf4410000 0x1000>;
>> +
>> +                     clock_media: clock2 at 0 {
>> +                             compatible = "hisilicon,hi6220-clock-media";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>> +
>> +             pm_ctrl: pm_ctrl {
>> +                     compatible = "hisilicon,pmctrl", "syscon";
>> +                     #address-cells = <1>;
>> +                     #size-cells = <1>;
>> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> +
>> +                     clock_power: clock3 at 0 {
>> +                             compatible = "hisilicon,hi6220-clock-power";
>> +                             reg = <0 0x1000>;
>> +                             #clock-cells = <1>;
>> +                     };
>> +             };
>
> I really doesn't see the point in having a sub-device that covers the
> entirely of the register space of the containing node, and that being
> the case I am extremely concerned that the containers are marked as
> syscon compatible.
The SoC clocks are designed and placed under different system controllers,
so I define corresponding nodes under different controllers for clock operation.

>
> Why are these marked as being syscon devices? Per the dts _all_ their
> registers are clearly owned by their child nodes, and shouldn't be poked
> by anything else.
>
> Thanks,
> Mark.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-06  8:42       ` Brent Wang
  (?)
@ 2015-02-06  9:07         ` Marc Zyngier
  -1 siblings, 0 replies; 85+ messages in thread
From: Marc Zyngier @ 2015-02-06  9:07 UTC (permalink / raw)
  To: Brent Wang, Mark Rutland
  Cc: dan.zhao, btw, Catalin Marinas, wangbinghui, Will Deacon,
	huxinwei, khilman, haojian.zhuang, yanhaifeng, rob.herring,
	mturquette, victor.lixin, xuwei5, jh80.chung, sledge.yanwei,
	kong.kongxinwei, heyunlei, w.f, zhangfei.gao, z.liuxinliang,
	devicetree, Bintian Wang, Pawel Moll, ijc+devicetree, puck.chen,
	olof, robh+dt, linux, zhenwei.wang, linux-arm-kernel, guodong.xu,
	tomeu.vizoso, sboyd, linux-kernel, galak, xuejiancheng, xuyiping,
	liguozhu

On 06/02/15 08:42, Brent Wang wrote:

[...]

>>
>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>
>> I guess no-one's bothered to consider 64k pages?
>>
>> Given GICH and GICV, I hope that this platform is booted at EL2?
> Transfer from EL3 to EL1 directly, keep these two just for future use.

That's a real shame, as it keeps users away from some key aspects of the
ARMv8 architecture.

>>
>>> +             #interrupt-cells = <3>;
>>> +             #address-cells = <0>;
>>> +             interrupt-controller;

And if you're keeping GICH/GICV, where is the maintenance interrupt?

>>> +     };
>>> +
>>> +
>>> +     timer {
>>> +             compatible = "arm,armv8-timer";
>>> +             interrupt-parent = <&gic>;
>>> +             interrupts = <1 13 0xff08>,
>>> +                          <1 14 0xff08>,
>>> +                          <1 11 0xff08>,
>>> +                          <1 10 0xff08>;
>>> +             clock-frequency = <1200000>;
>>> +     };
>>
>> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> Fix in next version, maybe it will take some time to change firmware.

While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
before dropping to EL1. This tends to be overlooked.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06  9:07         ` Marc Zyngier
  0 siblings, 0 replies; 85+ messages in thread
From: Marc Zyngier @ 2015-02-06  9:07 UTC (permalink / raw)
  To: Brent Wang, Mark Rutland
  Cc: dan.zhao, btw, Catalin Marinas, wangbinghui, Will Deacon,
	huxinwei, khilman, haojian.zhuang, yanhaifeng, rob.herring,
	mturquette, victor.lixin, xuwei5, jh80.chung, sledge.yanwei,
	kong.kongxinwei, heyunlei, w.f

On 06/02/15 08:42, Brent Wang wrote:

[...]

>>
>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>
>> I guess no-one's bothered to consider 64k pages?
>>
>> Given GICH and GICV, I hope that this platform is booted at EL2?
> Transfer from EL3 to EL1 directly, keep these two just for future use.

That's a real shame, as it keeps users away from some key aspects of the
ARMv8 architecture.

>>
>>> +             #interrupt-cells = <3>;
>>> +             #address-cells = <0>;
>>> +             interrupt-controller;

And if you're keeping GICH/GICV, where is the maintenance interrupt?

>>> +     };
>>> +
>>> +
>>> +     timer {
>>> +             compatible = "arm,armv8-timer";
>>> +             interrupt-parent = <&gic>;
>>> +             interrupts = <1 13 0xff08>,
>>> +                          <1 14 0xff08>,
>>> +                          <1 11 0xff08>,
>>> +                          <1 10 0xff08>;
>>> +             clock-frequency = <1200000>;
>>> +     };
>>
>> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> Fix in next version, maybe it will take some time to change firmware.

While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
before dropping to EL1. This tends to be overlooked.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06  9:07         ` Marc Zyngier
  0 siblings, 0 replies; 85+ messages in thread
From: Marc Zyngier @ 2015-02-06  9:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/02/15 08:42, Brent Wang wrote:

[...]

>>
>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>
>> I guess no-one's bothered to consider 64k pages?
>>
>> Given GICH and GICV, I hope that this platform is booted at EL2?
> Transfer from EL3 to EL1 directly, keep these two just for future use.

That's a real shame, as it keeps users away from some key aspects of the
ARMv8 architecture.

>>
>>> +             #interrupt-cells = <3>;
>>> +             #address-cells = <0>;
>>> +             interrupt-controller;

And if you're keeping GICH/GICV, where is the maintenance interrupt?

>>> +     };
>>> +
>>> +
>>> +     timer {
>>> +             compatible = "arm,armv8-timer";
>>> +             interrupt-parent = <&gic>;
>>> +             interrupts = <1 13 0xff08>,
>>> +                          <1 14 0xff08>,
>>> +                          <1 11 0xff08>,
>>> +                          <1 10 0xff08>;
>>> +             clock-frequency = <1200000>;
>>> +     };
>>
>> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> Fix in next version, maybe it will take some time to change firmware.

While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
before dropping to EL1. This tends to be overlooked.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-06  9:07         ` Marc Zyngier
  (?)
@ 2015-02-06 10:31           ` Mark Rutland
  -1 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-06 10:31 UTC (permalink / raw)
  To: Marc Zyngier, Brent Wang
  Cc: dan.zhao, btw, Catalin Marinas, wangbinghui, Will Deacon,
	huxinwei, khilman, haojian.zhuang, yanhaifeng, rob.herring,
	mturquette, victor.lixin, xuwei5, jh80.chung, sledge.yanwei,
	kong.kongxinwei, heyunlei, w.f, zhangfei.gao, z.liuxinliang,
	devicetree, Bintian Wang, Pawel Moll, ijc+devicetree, puck.chen,
	olof, robh+dt, linux, zhenwei.wang, linux-arm-kernel, guodong.xu,
	tomeu.vizoso, sboyd, linux-kernel, galak, xuejiancheng, xuyiping,
	liguozhu

On Fri, Feb 06, 2015 at 09:07:10AM +0000, Marc Zyngier wrote:
> On 06/02/15 08:42, Brent Wang wrote:
> 
> [...]
> 
> >>
> >>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
> >>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
> >>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
> >>
> >> I guess no-one's bothered to consider 64k pages?
> >>
> >> Given GICH and GICV, I hope that this platform is booted at EL2?
> > Transfer from EL3 to EL1 directly, keep these two just for future use.
> 
> That's a real shame, as it keeps users away from some key aspects of the
> ARMv8 architecture.

More importantly (and regardless of whether you wish to use the features
provided by EL2), booting at EL2 means that the FW/bootloader needs to
set up far less, and that the kernel can fix up some issues that might
not be immediately apparent...

[...]

> >>> +     timer {
> >>> +             compatible = "arm,armv8-timer";
> >>> +             interrupt-parent = <&gic>;
> >>> +             interrupts = <1 13 0xff08>,
> >>> +                          <1 14 0xff08>,
> >>> +                          <1 11 0xff08>,
> >>> +                          <1 10 0xff08>;
> >>> +             clock-frequency = <1200000>;
> >>> +     };
> >>
> >> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> > Fix in next version, maybe it will take some time to change firmware.
> 
> While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
> before dropping to EL1. This tends to be overlooked.

...like differing values of CNTVOFF_EL2.

There seems to be a common misconception that booting at EL2 is a bad
thing to do, when in reality booting at EL1 is more likely to result in
bugs we can't work around.

Is there any reason that you do not wish to boot at EL2, or were you
simply unaware that booting at EL2 was possible/preferred?

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06 10:31           ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-06 10:31 UTC (permalink / raw)
  To: Marc Zyngier, Brent Wang
  Cc: dan.zhao, btw, Catalin Marinas, wangbinghui, Will Deacon,
	huxinwei, khilman, haojian.zhuang, yanhaifeng, rob.herring,
	mturquette, victor.lixin, xuwei5, jh80.chung, sledge.yanwei,
	kong.kongxinwei, heyunlei, w.f

On Fri, Feb 06, 2015 at 09:07:10AM +0000, Marc Zyngier wrote:
> On 06/02/15 08:42, Brent Wang wrote:
> 
> [...]
> 
> >>
> >>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
> >>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
> >>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
> >>
> >> I guess no-one's bothered to consider 64k pages?
> >>
> >> Given GICH and GICV, I hope that this platform is booted at EL2?
> > Transfer from EL3 to EL1 directly, keep these two just for future use.
> 
> That's a real shame, as it keeps users away from some key aspects of the
> ARMv8 architecture.

More importantly (and regardless of whether you wish to use the features
provided by EL2), booting at EL2 means that the FW/bootloader needs to
set up far less, and that the kernel can fix up some issues that might
not be immediately apparent...

[...]

> >>> +     timer {
> >>> +             compatible = "arm,armv8-timer";
> >>> +             interrupt-parent = <&gic>;
> >>> +             interrupts = <1 13 0xff08>,
> >>> +                          <1 14 0xff08>,
> >>> +                          <1 11 0xff08>,
> >>> +                          <1 10 0xff08>;
> >>> +             clock-frequency = <1200000>;
> >>> +     };
> >>
> >> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> > Fix in next version, maybe it will take some time to change firmware.
> 
> While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
> before dropping to EL1. This tends to be overlooked.

...like differing values of CNTVOFF_EL2.

There seems to be a common misconception that booting at EL2 is a bad
thing to do, when in reality booting at EL1 is more likely to result in
bugs we can't work around.

Is there any reason that you do not wish to boot at EL2, or were you
simply unaware that booting at EL2 was possible/preferred?

Thanks,
Mark.

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06 10:31           ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-06 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 06, 2015 at 09:07:10AM +0000, Marc Zyngier wrote:
> On 06/02/15 08:42, Brent Wang wrote:
> 
> [...]
> 
> >>
> >>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
> >>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
> >>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
> >>
> >> I guess no-one's bothered to consider 64k pages?
> >>
> >> Given GICH and GICV, I hope that this platform is booted at EL2?
> > Transfer from EL3 to EL1 directly, keep these two just for future use.
> 
> That's a real shame, as it keeps users away from some key aspects of the
> ARMv8 architecture.

More importantly (and regardless of whether you wish to use the features
provided by EL2), booting at EL2 means that the FW/bootloader needs to
set up far less, and that the kernel can fix up some issues that might
not be immediately apparent...

[...]

> >>> +     timer {
> >>> +             compatible = "arm,armv8-timer";
> >>> +             interrupt-parent = <&gic>;
> >>> +             interrupts = <1 13 0xff08>,
> >>> +                          <1 14 0xff08>,
> >>> +                          <1 11 0xff08>,
> >>> +                          <1 10 0xff08>;
> >>> +             clock-frequency = <1200000>;
> >>> +     };
> >>
> >> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> > Fix in next version, maybe it will take some time to change firmware.
> 
> While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
> before dropping to EL1. This tends to be overlooked.

...like differing values of CNTVOFF_EL2.

There seems to be a common misconception that booting at EL2 is a bad
thing to do, when in reality booting at EL1 is more likely to result in
bugs we can't work around.

Is there any reason that you do not wish to boot at EL2, or were you
simply unaware that booting at EL2 was possible/preferred?

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-06  8:42       ` Brent Wang
  (?)
@ 2015-02-06 10:44         ` Mark Rutland
  -1 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-06 10:44 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
> Hello Mark,
> 
> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> >> support of Octal core CPUs in two clusters and each cluster
> >> has quard Cortex-A53.
> >>
> >> We now use the "spin-table" method for SMP, and it will be
> >> changed to PSCI later.
> >
> > If that's the case, please don't place the enable-method and related
> > properties in this file. Get your bootloader to add the appropriate
> > properties for its boot protocol.
> >
> > When is PSCI likely to appear?
> PSCI is under development.

Sure. Do you have an estimate as to when it will appear?

What are you using for your PSCI implementation? The ARM Trusted
Firmware?

How are you testing it?

> > Are we certain of the split between components the PSCI implementation
> > must touch and those the kernel must touch?
> >
> >> Also add dts file to support HiKey development board which
> >> based on Hi6220 SoC and document the devicetree bindings.
> >>
> >> These dts files will be changed later and more nodes will be
> >> added to describe other devices.
> >
> > How is this going to be changed other than the addition of nodes?
> >
> > Will this DTB continue to work in future? Or do you intend to make
> > changes that will break support?
> My original idea is: use spin-table for SMP now, when firmware is OK to
> support PSCI, we submit another patch to replace the spin-table with PSCI.

For any users who have not updated their FW, this will break booting.

This is why I suggest having hte bootloader/FW fill this in as it should
know what enable-method the FW supports.

> If DTB should continue to work in the future, we really need to remove
> the spin-table
> from current dts file, how about just enable one core now?
> 
> Which one do you favor or any other suggestion?

If spin-table is just for testing while you await PSCI, drop spin-table
from the dts for now.

[...]

> >> +     timer {
> >> +             compatible = "arm,armv8-timer";
> >> +             interrupt-parent = <&gic>;
> >> +             interrupts = <1 13 0xff08>,
> >> +                          <1 14 0xff08>,
> >> +                          <1 11 0xff08>,
> >> +                          <1 10 0xff08>;
> >> +             clock-frequency = <1200000>;
> >> +     };
> >
> > NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> Fix in next version, maybe it will take some time to change firmware.

Thanks. This _must_ be fixed.

[...]

> >> +             pm_ctrl: pm_ctrl {
> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> +                     #address-cells = <1>;
> >> +                     #size-cells = <1>;
> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> +
> >> +                     clock_power: clock3@0 {
> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> +                             reg = <0 0x1000>;
> >> +                             #clock-cells = <1>;
> >> +                     };
> >> +             };
> >
> > I really doesn't see the point in having a sub-device that covers the
> > entirely of the register space of the containing node, and that being
> > the case I am extremely concerned that the containers are marked as
> > syscon compatible.
> The SoC clocks are designed and placed under different system controllers,
> so I define corresponding nodes under different controllers for clock operation.

What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
sub-node have the _exact_ same register space.

Given this should mean that the clock3@0 node owns that register space,
having the container node export this as syscon does not make sense. And
the split between pm_ctrl and clock3@) doesn't seem to make sense given
they cover the same space.

As I asked before, why is pm_ctrl marked as a syscon, and what's the
point of the separate sub-node?

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06 10:44         ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-06 10:44 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung

On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
> Hello Mark,
> 
> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> >> support of Octal core CPUs in two clusters and each cluster
> >> has quard Cortex-A53.
> >>
> >> We now use the "spin-table" method for SMP, and it will be
> >> changed to PSCI later.
> >
> > If that's the case, please don't place the enable-method and related
> > properties in this file. Get your bootloader to add the appropriate
> > properties for its boot protocol.
> >
> > When is PSCI likely to appear?
> PSCI is under development.

Sure. Do you have an estimate as to when it will appear?

What are you using for your PSCI implementation? The ARM Trusted
Firmware?

How are you testing it?

> > Are we certain of the split between components the PSCI implementation
> > must touch and those the kernel must touch?
> >
> >> Also add dts file to support HiKey development board which
> >> based on Hi6220 SoC and document the devicetree bindings.
> >>
> >> These dts files will be changed later and more nodes will be
> >> added to describe other devices.
> >
> > How is this going to be changed other than the addition of nodes?
> >
> > Will this DTB continue to work in future? Or do you intend to make
> > changes that will break support?
> My original idea is: use spin-table for SMP now, when firmware is OK to
> support PSCI, we submit another patch to replace the spin-table with PSCI.

For any users who have not updated their FW, this will break booting.

This is why I suggest having hte bootloader/FW fill this in as it should
know what enable-method the FW supports.

> If DTB should continue to work in the future, we really need to remove
> the spin-table
> from current dts file, how about just enable one core now?
> 
> Which one do you favor or any other suggestion?

If spin-table is just for testing while you await PSCI, drop spin-table
from the dts for now.

[...]

> >> +     timer {
> >> +             compatible = "arm,armv8-timer";
> >> +             interrupt-parent = <&gic>;
> >> +             interrupts = <1 13 0xff08>,
> >> +                          <1 14 0xff08>,
> >> +                          <1 11 0xff08>,
> >> +                          <1 10 0xff08>;
> >> +             clock-frequency = <1200000>;
> >> +     };
> >
> > NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> Fix in next version, maybe it will take some time to change firmware.

Thanks. This _must_ be fixed.

[...]

> >> +             pm_ctrl: pm_ctrl {
> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> +                     #address-cells = <1>;
> >> +                     #size-cells = <1>;
> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> +
> >> +                     clock_power: clock3@0 {
> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> +                             reg = <0 0x1000>;
> >> +                             #clock-cells = <1>;
> >> +                     };
> >> +             };
> >
> > I really doesn't see the point in having a sub-device that covers the
> > entirely of the register space of the containing node, and that being
> > the case I am extremely concerned that the containers are marked as
> > syscon compatible.
> The SoC clocks are designed and placed under different system controllers,
> so I define corresponding nodes under different controllers for clock operation.

What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
sub-node have the _exact_ same register space.

Given this should mean that the clock3@0 node owns that register space,
having the container node export this as syscon does not make sense. And
the split between pm_ctrl and clock3@) doesn't seem to make sense given
they cover the same space.

As I asked before, why is pm_ctrl marked as a syscon, and what's the
point of the separate sub-node?

Thanks,
Mark.

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06 10:44         ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-06 10:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
> Hello Mark,
> 
> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> >> support of Octal core CPUs in two clusters and each cluster
> >> has quard Cortex-A53.
> >>
> >> We now use the "spin-table" method for SMP, and it will be
> >> changed to PSCI later.
> >
> > If that's the case, please don't place the enable-method and related
> > properties in this file. Get your bootloader to add the appropriate
> > properties for its boot protocol.
> >
> > When is PSCI likely to appear?
> PSCI is under development.

Sure. Do you have an estimate as to when it will appear?

What are you using for your PSCI implementation? The ARM Trusted
Firmware?

How are you testing it?

> > Are we certain of the split between components the PSCI implementation
> > must touch and those the kernel must touch?
> >
> >> Also add dts file to support HiKey development board which
> >> based on Hi6220 SoC and document the devicetree bindings.
> >>
> >> These dts files will be changed later and more nodes will be
> >> added to describe other devices.
> >
> > How is this going to be changed other than the addition of nodes?
> >
> > Will this DTB continue to work in future? Or do you intend to make
> > changes that will break support?
> My original idea is: use spin-table for SMP now, when firmware is OK to
> support PSCI, we submit another patch to replace the spin-table with PSCI.

For any users who have not updated their FW, this will break booting.

This is why I suggest having hte bootloader/FW fill this in as it should
know what enable-method the FW supports.

> If DTB should continue to work in the future, we really need to remove
> the spin-table
> from current dts file, how about just enable one core now?
> 
> Which one do you favor or any other suggestion?

If spin-table is just for testing while you await PSCI, drop spin-table
from the dts for now.

[...]

> >> +     timer {
> >> +             compatible = "arm,armv8-timer";
> >> +             interrupt-parent = <&gic>;
> >> +             interrupts = <1 13 0xff08>,
> >> +                          <1 14 0xff08>,
> >> +                          <1 11 0xff08>,
> >> +                          <1 10 0xff08>;
> >> +             clock-frequency = <1200000>;
> >> +     };
> >
> > NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
> Fix in next version, maybe it will take some time to change firmware.

Thanks. This _must_ be fixed.

[...]

> >> +             pm_ctrl: pm_ctrl {
> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> +                     #address-cells = <1>;
> >> +                     #size-cells = <1>;
> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> +
> >> +                     clock_power: clock3 at 0 {
> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> +                             reg = <0 0x1000>;
> >> +                             #clock-cells = <1>;
> >> +                     };
> >> +             };
> >
> > I really doesn't see the point in having a sub-device that covers the
> > entirely of the register space of the containing node, and that being
> > the case I am extremely concerned that the containers are marked as
> > syscon compatible.
> The SoC clocks are designed and placed under different system controllers,
> so I define corresponding nodes under different controllers for clock operation.

What I'm concerned wit hhere is that the pm_ctrl node and the clock3 at 0
sub-node have the _exact_ same register space.

Given this should mean that the clock3 at 0 node owns that register space,
having the container node export this as syscon does not make sense. And
the split between pm_ctrl and clock3@) doesn't seem to make sense given
they cover the same space.

As I asked before, why is pm_ctrl marked as a syscon, and what's the
point of the separate sub-node?

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-06 10:44         ` Mark Rutland
  (?)
@ 2015-02-06 15:37           ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06 15:37 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

Hello Mark,

2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
>> Hello Mark,
>>
>> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> >> support of Octal core CPUs in two clusters and each cluster
>> >> has quard Cortex-A53.
>> >>
>> >> We now use the "spin-table" method for SMP, and it will be
>> >> changed to PSCI later.
>> >
>> > If that's the case, please don't place the enable-method and related
>> > properties in this file. Get your bootloader to add the appropriate
>> > properties for its boot protocol.
>> >
>> > When is PSCI likely to appear?
>> PSCI is under development.
>
> Sure. Do you have an estimate as to when it will appear?
Another team will do the job, I can not give my estimation now.

> What are you using for your PSCI implementation? The ARM Trusted
> Firmware?
Yes, ATF.
>
> How are you testing it?
I think cpu hotplug can test it.

>
>> > Are we certain of the split between components the PSCI implementation
>> > must touch and those the kernel must touch?
>> >
>> >> Also add dts file to support HiKey development board which
>> >> based on Hi6220 SoC and document the devicetree bindings.
>> >>
>> >> These dts files will be changed later and more nodes will be
>> >> added to describe other devices.
>> >
>> > How is this going to be changed other than the addition of nodes?
>> >
>> > Will this DTB continue to work in future? Or do you intend to make
>> > changes that will break support?
>> My original idea is: use spin-table for SMP now, when firmware is OK to
>> support PSCI, we submit another patch to replace the spin-table with PSCI.
>
> For any users who have not updated their FW, this will break booting.
>
> This is why I suggest having hte bootloader/FW fill this in as it should
> know what enable-method the FW supports.
>
>> If DTB should continue to work in the future, we really need to remove
>> the spin-table
>> from current dts file, how about just enable one core now?
>>
>> Which one do you favor or any other suggestion?
>
> If spin-table is just for testing while you await PSCI, drop spin-table
> from the dts for now.
So, just booting one core may be the right choice now, right?

>
> [...]
>
>> >> +     timer {
>> >> +             compatible = "arm,armv8-timer";
>> >> +             interrupt-parent = <&gic>;
>> >> +             interrupts = <1 13 0xff08>,
>> >> +                          <1 14 0xff08>,
>> >> +                          <1 11 0xff08>,
>> >> +                          <1 10 0xff08>;
>> >> +             clock-frequency = <1200000>;
>> >> +     };
>> >
>> > NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
>> Fix in next version, maybe it will take some time to change firmware.
>
> Thanks. This _must_ be fixed.
>
> [...]
>
>> >> +             pm_ctrl: pm_ctrl {
>> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> +                     #address-cells = <1>;
>> >> +                     #size-cells = <1>;
>> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> +
>> >> +                     clock_power: clock3@0 {
>> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> +                             reg = <0 0x1000>;
>> >> +                             #clock-cells = <1>;
>> >> +                     };
>> >> +             };
>> >
>> > I really doesn't see the point in having a sub-device that covers the
>> > entirely of the register space of the containing node, and that being
>> > the case I am extremely concerned that the containers are marked as
>> > syscon compatible.
>> The SoC clocks are designed and placed under different system controllers,
>> so I define corresponding nodes under different controllers for clock operation.
>
> What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
> sub-node have the _exact_ same register space.
>
> Given this should mean that the clock3@0 node owns that register space,
> having the container node export this as syscon does not make sense. And
> the split between pm_ctrl and clock3@) doesn't seem to make sense given
> they cover the same space.
I understand your worry and will find the max offset of those clocks
under this controller.

>
> As I asked before, why is pm_ctrl marked as a syscon, and what's the
> point of the separate sub-node?
There is no big difference between pm_ctrl and other controller,  they
are all designed as
the base address to control some functions of other modules (certainly
include some clock gates).

Maybe only one node is enough, not one node plus one sub-node ?

>
> Thanks,
> Mark.

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06 15:37           ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06 15:37 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Pawel Moll,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, khilman-QSEj5FYQhm4dnm+yROfE0A,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	rob.herring-QSEj5FYQhm4dnm+yROfE0A,
	zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A,
	haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, jh80.chung-Sze3O3UU22JBDgjK7y7TUQ

Hello Mark,

2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
> On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
>> Hello Mark,
>>
>> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
>> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> >> support of Octal core CPUs in two clusters and each cluster
>> >> has quard Cortex-A53.
>> >>
>> >> We now use the "spin-table" method for SMP, and it will be
>> >> changed to PSCI later.
>> >
>> > If that's the case, please don't place the enable-method and related
>> > properties in this file. Get your bootloader to add the appropriate
>> > properties for its boot protocol.
>> >
>> > When is PSCI likely to appear?
>> PSCI is under development.
>
> Sure. Do you have an estimate as to when it will appear?
Another team will do the job, I can not give my estimation now.

> What are you using for your PSCI implementation? The ARM Trusted
> Firmware?
Yes, ATF.
>
> How are you testing it?
I think cpu hotplug can test it.

>
>> > Are we certain of the split between components the PSCI implementation
>> > must touch and those the kernel must touch?
>> >
>> >> Also add dts file to support HiKey development board which
>> >> based on Hi6220 SoC and document the devicetree bindings.
>> >>
>> >> These dts files will be changed later and more nodes will be
>> >> added to describe other devices.
>> >
>> > How is this going to be changed other than the addition of nodes?
>> >
>> > Will this DTB continue to work in future? Or do you intend to make
>> > changes that will break support?
>> My original idea is: use spin-table for SMP now, when firmware is OK to
>> support PSCI, we submit another patch to replace the spin-table with PSCI.
>
> For any users who have not updated their FW, this will break booting.
>
> This is why I suggest having hte bootloader/FW fill this in as it should
> know what enable-method the FW supports.
>
>> If DTB should continue to work in the future, we really need to remove
>> the spin-table
>> from current dts file, how about just enable one core now?
>>
>> Which one do you favor or any other suggestion?
>
> If spin-table is just for testing while you await PSCI, drop spin-table
> from the dts for now.
So, just booting one core may be the right choice now, right?

>
> [...]
>
>> >> +     timer {
>> >> +             compatible = "arm,armv8-timer";
>> >> +             interrupt-parent = <&gic>;
>> >> +             interrupts = <1 13 0xff08>,
>> >> +                          <1 14 0xff08>,
>> >> +                          <1 11 0xff08>,
>> >> +                          <1 10 0xff08>;
>> >> +             clock-frequency = <1200000>;
>> >> +     };
>> >
>> > NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
>> Fix in next version, maybe it will take some time to change firmware.
>
> Thanks. This _must_ be fixed.
>
> [...]
>
>> >> +             pm_ctrl: pm_ctrl {
>> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> +                     #address-cells = <1>;
>> >> +                     #size-cells = <1>;
>> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> +
>> >> +                     clock_power: clock3@0 {
>> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> +                             reg = <0 0x1000>;
>> >> +                             #clock-cells = <1>;
>> >> +                     };
>> >> +             };
>> >
>> > I really doesn't see the point in having a sub-device that covers the
>> > entirely of the register space of the containing node, and that being
>> > the case I am extremely concerned that the containers are marked as
>> > syscon compatible.
>> The SoC clocks are designed and placed under different system controllers,
>> so I define corresponding nodes under different controllers for clock operation.
>
> What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
> sub-node have the _exact_ same register space.
>
> Given this should mean that the clock3@0 node owns that register space,
> having the container node export this as syscon does not make sense. And
> the split between pm_ctrl and clock3@) doesn't seem to make sense given
> they cover the same space.
I understand your worry and will find the max offset of those clocks
under this controller.

>
> As I asked before, why is pm_ctrl marked as a syscon, and what's the
> point of the separate sub-node?
There is no big difference between pm_ctrl and other controller,  they
are all designed as
the base address to control some functions of other modules (certainly
include some clock gates).

Maybe only one node is enough, not one node plus one sub-node ?

>
> Thanks,
> Mark.

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!
--
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] 85+ messages in thread

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-06 15:37           ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-06 15:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Mark,

2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
>> Hello Mark,
>>
>> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> >> support of Octal core CPUs in two clusters and each cluster
>> >> has quard Cortex-A53.
>> >>
>> >> We now use the "spin-table" method for SMP, and it will be
>> >> changed to PSCI later.
>> >
>> > If that's the case, please don't place the enable-method and related
>> > properties in this file. Get your bootloader to add the appropriate
>> > properties for its boot protocol.
>> >
>> > When is PSCI likely to appear?
>> PSCI is under development.
>
> Sure. Do you have an estimate as to when it will appear?
Another team will do the job, I can not give my estimation now.

> What are you using for your PSCI implementation? The ARM Trusted
> Firmware?
Yes, ATF.
>
> How are you testing it?
I think cpu hotplug can test it.

>
>> > Are we certain of the split between components the PSCI implementation
>> > must touch and those the kernel must touch?
>> >
>> >> Also add dts file to support HiKey development board which
>> >> based on Hi6220 SoC and document the devicetree bindings.
>> >>
>> >> These dts files will be changed later and more nodes will be
>> >> added to describe other devices.
>> >
>> > How is this going to be changed other than the addition of nodes?
>> >
>> > Will this DTB continue to work in future? Or do you intend to make
>> > changes that will break support?
>> My original idea is: use spin-table for SMP now, when firmware is OK to
>> support PSCI, we submit another patch to replace the spin-table with PSCI.
>
> For any users who have not updated their FW, this will break booting.
>
> This is why I suggest having hte bootloader/FW fill this in as it should
> know what enable-method the FW supports.
>
>> If DTB should continue to work in the future, we really need to remove
>> the spin-table
>> from current dts file, how about just enable one core now?
>>
>> Which one do you favor or any other suggestion?
>
> If spin-table is just for testing while you await PSCI, drop spin-table
> from the dts for now.
So, just booting one core may be the right choice now, right?

>
> [...]
>
>> >> +     timer {
>> >> +             compatible = "arm,armv8-timer";
>> >> +             interrupt-parent = <&gic>;
>> >> +             interrupts = <1 13 0xff08>,
>> >> +                          <1 14 0xff08>,
>> >> +                          <1 11 0xff08>,
>> >> +                          <1 10 0xff08>;
>> >> +             clock-frequency = <1200000>;
>> >> +     };
>> >
>> > NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
>> Fix in next version, maybe it will take some time to change firmware.
>
> Thanks. This _must_ be fixed.
>
> [...]
>
>> >> +             pm_ctrl: pm_ctrl {
>> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> +                     #address-cells = <1>;
>> >> +                     #size-cells = <1>;
>> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> +
>> >> +                     clock_power: clock3 at 0 {
>> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> +                             reg = <0 0x1000>;
>> >> +                             #clock-cells = <1>;
>> >> +                     };
>> >> +             };
>> >
>> > I really doesn't see the point in having a sub-device that covers the
>> > entirely of the register space of the containing node, and that being
>> > the case I am extremely concerned that the containers are marked as
>> > syscon compatible.
>> The SoC clocks are designed and placed under different system controllers,
>> so I define corresponding nodes under different controllers for clock operation.
>
> What I'm concerned wit hhere is that the pm_ctrl node and the clock3 at 0
> sub-node have the _exact_ same register space.
>
> Given this should mean that the clock3 at 0 node owns that register space,
> having the container node export this as syscon does not make sense. And
> the split between pm_ctrl and clock3@) doesn't seem to make sense given
> they cover the same space.
I understand your worry and will find the max offset of those clocks
under this controller.

>
> As I asked before, why is pm_ctrl marked as a syscon, and what's the
> point of the separate sub-node?
There is no big difference between pm_ctrl and other controller,  they
are all designed as
the base address to control some functions of other modules (certainly
include some clock gates).

Maybe only one node is enough, not one node plus one sub-node ?

>
> Thanks,
> Mark.

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-06 18:10     ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-06 18:10 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel, Catalin Marinas, Will Deacon,
	devicetree, Rob Herring, Paweł Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Kevin Hilman, Mike Turquette,
	Rob Herring, Zhangfei Gao, Haojian Zhuang, Xu Wei, Jaehoon Chung,
	Olof Johansson, Haifeng Yan, Stephen Boyd, xuejiancheng,
	sledge.yanwei, Tomeu Vizoso, Russell King - ARM Linux,
	Guodong Xu, dan.zhao, huxinwei, xuyiping, victor.lixin, btw,
	puck.chen, wangbinghui, zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

Hi Bintian,

This patch applied to next-20150204 is producing build failures on
various ARM defconfigs[1]. I received the following error in all
cases:

drivers/built-in.o: In function `hi6220_clk_register_divider':
:(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
Makefile:925: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1


On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
> Add clock drivers for hi6220 SoC, this driver controls the SoC
> registers to supply different clocks to different IPs in the SoC.
>
> We add one divider clock for hi6220 because the divider in hi6220
> also has a mask bit but it doesnot obey the rule defined by flag
> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
> left shift fixed bits (e.g. 16 bits), so we add this divider clock
> to handle it.
>
> This patch also enables this clock driver for ARCH_HISI and document
> devicetree bindings.
>
> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  11 files changed, 815 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>
> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> new file mode 100644
> index 0000000..a3ddda1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> @@ -0,0 +1,30 @@
> +* Hisilicon Hi6220 Clock Controller
> +
> +The hi6220 clock controller generates and supplies clock to various
> +controllers within the hi6220 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be one of the following:
> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
> +     power always on(AO) domain, it is the sub node of SoC power AO
> +     controller in dts file.
> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
> +     system control domain, it is the sub node of SoC system controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
> +     SoC media control domain, it is the sub node of SoC media controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
> +     SoC power control domain, it is the sub node of SoC power controller
> +     in dts file.
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- #clock-cells: should be 1.
> +
> +Each clock is assigned an identifier and client nodes use this identifier
> +to specify the clock which they consume.
> +
> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 78cd41c8..6efc3e3 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -175,6 +175,7 @@ config ARCH_XGENE
>
>  config ARCH_HISI
>         bool "Hisilicon SoC Family"
> +       select COMMON_CLK_HI6220
>         help
>           This enables support for Hisilicon ARMv8 Family of SoCs.
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3f44f29..b52c95c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>
>  source "drivers/clk/qcom/Kconfig"
>
> +source "drivers/clk/hisilicon/Kconfig"
> +
>  endmenu
>
>  source "drivers/clk/bcm/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index d5fba5b..c58703b 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
> new file mode 100644
> index 0000000..e3ead46
> --- /dev/null
> +++ b/drivers/clk/hisilicon/Kconfig
> @@ -0,0 +1,5 @@
> +config COMMON_CLK_HI6220
> +       tristate "Hi6220 Clock Driver"
> +       depends on OF && ARCH_HISI
> +       help
> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index 038c02f..bbf0539 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
> new file mode 100644
> index 0000000..01d0c46
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clk-hi6220.c
> @@ -0,0 +1,284 @@
> +/*
> + * Hisilicon Hi6220 clock driver
> + *
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#include <dt-bindings/clock/hi6220-clock.h>
> +
> +#include "clk.h"
> +
> +
> +/* clocks in AO (always on) controller */
> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
> +};
> +
> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
> +};
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
> +};
> +
> +static void __init hi6220_clk_ao_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
> +
> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
> +
> +
> +/* clocks in sysctrl */
> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
> +};
> +
> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
> +};
> +
> +static void __init hi6220_clk_sys_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
> +
> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
> +
> +
> +/* clocks in media controller */
> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
> +};
> +
> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
> +};
> +
> +static void __init hi6220_clk_media_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
> +
> +       hisi_clk_register_mux(hi6220_mux_clks_media,
> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_media,
> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
> +
> +
> +/* clocks in pmctrl */
> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
> +};
> +
> +static void __init hi6220_clk_power_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate(hi6220_gate_clks_power,
> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_power,
> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
> index a078e84..5d2305c 100644
> --- a/drivers/clk/hisilicon/clk.c
> +++ b/drivers/clk/hisilicon/clk.c
> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>                 data->clk_data.clks[clks[i].id] = clk;
>         }
>  }
> +
> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
> +                                         int nums, struct hisi_clock_data *data)
> +{
> +       struct clk *clk;
> +       void __iomem *base = data->base;
> +       int i;
> +
> +       for (i = 0; i < nums; i++) {
> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
> +                                               clks[i].parent_name,
> +                                               clks[i].flags,
> +                                               base + clks[i].offset,
> +                                               clks[i].shift,
> +                                               clks[i].width,
> +                                               clks[i].mask_bit,
> +                                               &hisi_clk_lock);
> +               if (IS_ERR(clk)) {
> +                       pr_err("%s: failed to register clock %s\n",
> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +
> +               if (clks[i].alias)
> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
> +
> +               data->clk_data.clks[clks[i].id] = clk;
> +       }
> +}
> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
> index 31083ff..462a570 100644
> --- a/drivers/clk/hisilicon/clk.h
> +++ b/drivers/clk/hisilicon/clk.h
> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>         const char              *alias;
>  };
>
> +struct hi6220_divider_clock {
> +       unsigned int            id;
> +       const char              *name;
> +       const char              *parent_name;
> +       unsigned long           flags;
> +       unsigned long           offset;
> +       u8                      shift;
> +       u8                      width;
> +       u32                     mask_bit;
> +       const char              *alias;
> +};
> +
>  struct hisi_gate_clock {
>         unsigned int            id;
>         const char              *name;
> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>                                 const char *, unsigned long,
>                                 void __iomem *, u8,
>                                 u8, spinlock_t *);
> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
> +       const char *parent_name, unsigned long flags, void __iomem *reg,
> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>
>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>                                         int, struct hisi_clock_data *);
>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>                                         int, struct hisi_clock_data *);
> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
> +                                       int, struct hisi_clock_data *);
>  #endif /* __HISI_CLK_H */
> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
> new file mode 100644
> index 0000000..9e3825b
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
> @@ -0,0 +1,273 @@
> +/*
> + * Hisilicon hi6220 SoC divider clock driver
> + *
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +
> +#define div_mask(width)        ((1 << (width)) - 1)
> +
> +/*
> + * The reverse of DIV_ROUND_UP: The maximum number which
> + * divided by m is r
> + */
> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
> +
> +/**
> + * struct hi6220_clk_divider - divider clock for hi6220
> + *
> + * @hw:                handle between common and hardware-specific interfaces
> + * @reg:       register containing divider
> + * @shift:     shift to the divider bit field
> + * @width:     width of the divider bit field
> + * @mask:      mask for setting divider rate
> + * @table:     the div table that the divider supports
> + * @lock:      register lock
> + */
> +struct hi6220_clk_divider {
> +       struct clk_hw   hw;
> +       void __iomem    *reg;
> +       u8              shift;
> +       u8              width;
> +       u32             mask;
> +       const struct clk_div_table *table;
> +       spinlock_t      *lock;
> +};
> +
> +#define to_hi6220_clk_divider(_hw)     \
> +       container_of(_hw, struct hi6220_clk_divider, hw)
> +
> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
> +{
> +       unsigned int maxdiv = 0;
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div > maxdiv)
> +                       maxdiv = clkt->div;
> +       return maxdiv;
> +}
> +
> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
> +                                       unsigned int val)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->val == val)
> +                       return clkt->div;
> +
> +       return 0;
> +}
> +
> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
> +                                       unsigned int div)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div == div)
> +                       return clkt->val;
> +       return 0;
> +}
> +
> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       unsigned int div, val;
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +
> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
> +       val &= div_mask(dclk->width);
> +
> +       div = hi6220_get_table_div(dclk->table, val);
> +       if (!div) {
> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
> +                          __clk_get_name(hw->clk));
> +               return parent_rate;
> +       }
> +
> +       return parent_rate / div;
> +}
> +
> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
> +                               unsigned int div)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div == div)
> +                       return true;
> +       return false;
> +}
> +
> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
> +                                unsigned long *best_parent_rate)
> +{
> +       unsigned int i, bestdiv = 0;
> +       unsigned long parent_rate, best = 0, now, maxdiv;
> +
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
> +
> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
> +
> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
> +               parent_rate = *best_parent_rate;
> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
> +               return bestdiv;
> +       }
> +
> +       /*
> +        * The maximum divider we can use without overflowing
> +        * unsigned long in rate * i below
> +        */
> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
> +
> +       for (i = 1; i <= maxdiv; i++) {
> +               if (!hi6220_is_valid_div(dclk->table, i))
> +                       continue;
> +               parent_rate = __clk_round_rate(clk_parent,
> +                                       MULT_ROUND_UP(rate, i));
> +               now = parent_rate / i;
> +               if (now <= rate && now > best) {
> +                       bestdiv = i;
> +                       best = now;
> +                       *best_parent_rate = parent_rate;
> +               }
> +       }
> +
> +       if (!bestdiv) {
> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
> +       }
> +
> +       return bestdiv;
> +}
> +
> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
> +                                       unsigned long *prate)
> +{
> +       int div;
> +
> +       if (!rate)
> +               rate = 1;
> +
> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
> +
> +       return *prate / div;
> +}
> +
> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
> +                                       unsigned long parent_rate)
> +{
> +       unsigned int div, value;
> +       unsigned long flags = 0;
> +       u32 data;
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +
> +       div = parent_rate / rate;
> +
> +       if (!hi6220_is_valid_div(dclk->table, div))
> +               return -EINVAL;
> +
> +       value = hi6220_get_table_val(dclk->table, div);
> +
> +       if (value > div_mask(dclk->width))
> +               value = div_mask(dclk->width);
> +
> +       if (dclk->lock)
> +               spin_lock_irqsave(dclk->lock, flags);
> +
> +       data = readl_relaxed(dclk->reg);
> +       data &= ~(div_mask(dclk->width) << dclk->shift);
> +       data |= value << dclk->shift;
> +       data |= dclk->mask;
> +
> +       writel_relaxed(data, dclk->reg);
> +
> +       if (dclk->lock)
> +               spin_unlock_irqrestore(dclk->lock, flags);
> +
> +       return 0;
> +}
> +
> +static struct clk_ops hi6220_clkdiv_ops = {
> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
> +       .round_rate = hi6220_clkdiv_round_rate,
> +       .set_rate = hi6220_clkdiv_set_rate,
> +};
> +
> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
> +       const char *parent_name, unsigned long flags, void __iomem *reg,
> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
> +{
> +       struct hi6220_clk_divider *div;
> +       struct clk *clk;
> +       struct clk_init_data init;
> +       struct clk_div_table *table;
> +       u32 max_div, min_div;
> +       int i;
> +
> +       /* allocate the divider */
> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
> +       if (!div) {
> +               pr_err("%s: could not allocate divider clk\n", __func__);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       /* Init the divider table */
> +       max_div = div_mask(width) + 1;
> +       min_div = 1;
> +
> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
> +       if (!table) {
> +               kfree(div);
> +               pr_err("%s: failed to alloc divider table!\n", __func__);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       for (i = 0; i < max_div; i++) {
> +               table[i].div = min_div + i;
> +               table[i].val = table[i].div - 1;
> +       }
> +
> +       init.name = name;
> +       init.ops = &hi6220_clkdiv_ops;
> +       init.flags = flags | CLK_IS_BASIC;
> +       init.parent_names = parent_name ? &parent_name : NULL;
> +       init.num_parents = parent_name ? 1 : 0;
> +
> +       /* struct hi6220_clk_divider assignments */
> +       div->reg = reg;
> +       div->shift = shift;
> +       div->width = width;
> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
> +       div->lock = lock;
> +       div->hw.init = &init;
> +       div->table = table;
> +
> +       /* register the clock */
> +       clk = clk_register(dev, &div->hw);
> +
> +       if (IS_ERR(clk)) {
> +               kfree(table);
> +               kfree(div);
> +       }
> +
> +       return clk;
> +}
> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
> new file mode 100644
> index 0000000..05033e7
> --- /dev/null
> +++ b/include/dt-bindings/clock/hi6220-clock.h
> @@ -0,0 +1,172 @@
> +/*
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
> +#define __DT_BINDINGS_CLOCK_HI6220_H
> +
> +/* clk in AO (always on) controller */
> +#define HI6220_NONE_CLOCK      0
> +
> +/* fixed rate clocks */
> +#define HI6220_REF32K          1
> +#define HI6220_CLK_TCXO                2
> +#define HI6220_MMC1_PAD                3
> +#define HI6220_MMC2_PAD                4
> +#define HI6220_MMC0_PAD                5
> +#define HI6220_PLL_BBP         6
> +#define HI6220_PLL_GPU         7
> +#define HI6220_PLL1_DDR                8
> +#define HI6220_PLL_SYS         9
> +#define HI6220_PLL_SYS_MEDIA   10
> +#define HI6220_DDR_SRC         11
> +#define HI6220_PLL_MEDIA       12
> +#define HI6220_PLL_DDR         13
> +
> +/* fixed factor clocks */
> +#define HI6220_300M            16
> +#define HI6220_150M            17
> +#define HI6220_PICOPHY_SRC     18
> +#define HI6220_MMC0_SRC_SEL    19
> +#define HI6220_MMC1_SRC_SEL    20
> +#define HI6220_MMC2_SRC_SEL    21
> +#define HI6220_VPU_CODEC       22
> +#define HI6220_MMC0_SMP                23
> +#define HI6220_MMC1_SMP                24
> +#define HI6220_MMC2_SMP                25
> +
> +/* gate clocks */
> +#define HI6220_WDT0_PCLK       28
> +#define HI6220_WDT1_PCLK       29
> +#define HI6220_WDT2_PCLK       30
> +#define HI6220_TIMER0_PCLK     31
> +#define HI6220_TIMER1_PCLK     32
> +#define HI6220_TIMER2_PCLK     33
> +#define HI6220_TIMER3_PCLK     34
> +#define HI6220_TIMER4_PCLK     35
> +#define HI6220_TIMER5_PCLK     36
> +#define HI6220_TIMER6_PCLK     37
> +#define HI6220_TIMER7_PCLK     38
> +#define HI6220_TIMER8_PCLK     39
> +#define HI6220_UART0_PCLK      40
> +
> +#define HI6220_AO_NR_CLKS      48
> +
> +/* clk in systrl */
> +/* gate clock */
> +#define HI6220_MMC0_CLK                1
> +#define HI6220_MMC0_CIUCLK     2
> +#define HI6220_MMC1_CLK                3
> +#define HI6220_MMC1_CIUCLK     4
> +#define HI6220_MMC2_CLK                5
> +#define HI6220_MMC2_CIUCLK     6
> +#define HI6220_USBOTG_HCLK     7
> +#define HI6220_CLK_PICOPHY     8
> +#define HI6220_HIFI            9
> +#define HI6220_DACODEC_PCLK    10
> +#define HI6220_EDMAC_ACLK      11
> +#define HI6220_CS_ATB          12
> +#define HI6220_I2C0_CLK                13
> +#define HI6220_I2C1_CLK                14
> +#define HI6220_I2C2_CLK                15
> +#define HI6220_I2C3_CLK                16
> +#define HI6220_UART1_PCLK      17
> +#define HI6220_UART2_PCLK      18
> +#define HI6220_UART3_PCLK      19
> +#define HI6220_UART4_PCLK      20
> +#define HI6220_SPI_CLK         21
> +#define HI6220_MMU_CLK         22
> +#define HI6220_HIFI_SEL                23
> +#define HI6220_MMC0_SYSPLL     24
> +#define HI6220_MMC1_SYSPLL     25
> +#define HI6220_MMC2_SYSPLL     26
> +#define HI6220_MMC0_SEL                27
> +#define HI6220_MMC1_SEL                28
> +#define HI6220_BBPPLL_SEL      29
> +#define HI6220_MEDIA_PLL_SRC   30
> +#define HI6220_MMC2_SEL                31
> +#define HI6220_CS_ATB_SYSPLL   32
> +
> +/* mux clocks */
> +#define HI6220_MMC0_SRC                35
> +#define HI6220_MMC0_SMP_IN     36
> +#define HI6220_MMC1_SRC                37
> +#define HI6220_MMC1_SMP_IN     38
> +#define HI6220_MMC2_SRC                39
> +#define HI6220_MMC2_SMP_IN     40
> +#define HI6220_HIFI_SRC                41
> +#define HI6220_UART1_SRC       42
> +#define HI6220_UART2_SRC       43
> +#define HI6220_UART3_SRC       44
> +#define HI6220_UART4_SRC       45
> +#define HI6220_MMC0_MUX0       46
> +#define HI6220_MMC1_MUX0       47
> +#define HI6220_MMC2_MUX0       48
> +#define HI6220_MMC0_MUX1       49
> +#define HI6220_MMC1_MUX1       50
> +#define HI6220_MMC2_MUX1       51
> +
> +/* divider clocks */
> +#define HI6220_CLK_BUS         54
> +#define HI6220_MMC0_DIV                55
> +#define HI6220_MMC1_DIV                56
> +#define HI6220_MMC2_DIV                57
> +#define HI6220_HIFI_DIV                58
> +#define HI6220_BBPPLL0_DIV     59
> +#define HI6220_CS_DAPB         60
> +#define HI6220_CS_ATB_DIV      61
> +
> +#define HI6220_SYS_NR_CLKS     64
> +
> +/* clk in media controller */
> +/* gate clocks */
> +#define HI6220_DSI_PCLK                1
> +#define HI6220_G3D_PCLK                2
> +#define HI6220_ACLK_CODEC_VPU  3
> +#define HI6220_ISP_SCLK                4
> +#define HI6220_ADE_CORE                5
> +#define HI6220_MED_MMU         6
> +#define HI6220_CFG_CSI4PHY     7
> +#define HI6220_CFG_CSI2PHY     8
> +#define HI6220_ISP_SCLK_GATE   9
> +#define HI6220_ISP_SCLK_GATE1  10
> +#define HI6220_ADE_CORE_GATE   11
> +#define HI6220_CODEC_VPU_GATE  12
> +#define HI6220_MED_SYSPLL      13
> +
> +/* mux clocks */
> +#define HI6220_1440_1200       20
> +#define HI6220_1000_1200       21
> +#define HI6220_1000_1440       22
> +
> +/* divider clocks */
> +#define HI6220_CODEC_JPEG      30
> +#define HI6220_ISP_SCLK_SRC    31
> +#define HI6220_ISP_SCLK1       32
> +#define HI6220_ADE_CORE_SRC    33
> +#define HI6220_ADE_PIX_SRC     34
> +#define HI6220_G3D_CLK         35
> +#define HI6220_CODEC_VPU_SRC   36
> +
> +#define HI6220_MEDIA_NR_CLKS   40
> +
> +/* clk in power controller */
> +/* gate clocks */
> +#define HI6220_PLL_GPU_GATE    1
> +#define HI6220_PLL1_DDR_GATE   2
> +#define HI6220_PLL_DDR_GATE    3
> +#define HI6220_PLL_MEDIA_GATE  4
> +#define HI6220_PLL0_BBP_GATE   5
> +
> +/* divider clocks */
> +#define HI6220_DDRC_SRC                10
> +#define HI6220_DDRC_AXI1       11
> +
> +#define HI6220_POWER_NR_CLKS   16
> +#endif
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Cheers,

- Tyler

[1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-06 18:10     ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-06 18:10 UTC (permalink / raw)
  To: Bintian Wang
  Cc: linux-arm-kernel, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Catalin Marinas, Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Paweł Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Kevin Hilman, Mike Turquette, Rob Herring,
	Zhangfei Gao, Haojian Zhuang, Xu Wei, Jaehoon Chung,
	Olof Johansson, Haifeng Yan, Stephen Boyd,
	xuejiancheng-hv44wF8Li93QT0dZR+AlfA, sledge.yanwei

Hi Bintian,

This patch applied to next-20150204 is producing build failures on
various ARM defconfigs[1]. I received the following error in all
cases:

drivers/built-in.o: In function `hi6220_clk_register_divider':
:(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
Makefile:925: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1


On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
> Add clock drivers for hi6220 SoC, this driver controls the SoC
> registers to supply different clocks to different IPs in the SoC.
>
> We add one divider clock for hi6220 because the divider in hi6220
> also has a mask bit but it doesnot obey the rule defined by flag
> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
> left shift fixed bits (e.g. 16 bits), so we add this divider clock
> to handle it.
>
> This patch also enables this clock driver for ARCH_HISI and document
> devicetree bindings.
>
> Signed-off-by: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> Reviewed-by: Haojian Zhuang <haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Reviewed-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  11 files changed, 815 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>
> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> new file mode 100644
> index 0000000..a3ddda1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> @@ -0,0 +1,30 @@
> +* Hisilicon Hi6220 Clock Controller
> +
> +The hi6220 clock controller generates and supplies clock to various
> +controllers within the hi6220 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be one of the following:
> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
> +     power always on(AO) domain, it is the sub node of SoC power AO
> +     controller in dts file.
> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
> +     system control domain, it is the sub node of SoC system controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
> +     SoC media control domain, it is the sub node of SoC media controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
> +     SoC power control domain, it is the sub node of SoC power controller
> +     in dts file.
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- #clock-cells: should be 1.
> +
> +Each clock is assigned an identifier and client nodes use this identifier
> +to specify the clock which they consume.
> +
> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 78cd41c8..6efc3e3 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -175,6 +175,7 @@ config ARCH_XGENE
>
>  config ARCH_HISI
>         bool "Hisilicon SoC Family"
> +       select COMMON_CLK_HI6220
>         help
>           This enables support for Hisilicon ARMv8 Family of SoCs.
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3f44f29..b52c95c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>
>  source "drivers/clk/qcom/Kconfig"
>
> +source "drivers/clk/hisilicon/Kconfig"
> +
>  endmenu
>
>  source "drivers/clk/bcm/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index d5fba5b..c58703b 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
> new file mode 100644
> index 0000000..e3ead46
> --- /dev/null
> +++ b/drivers/clk/hisilicon/Kconfig
> @@ -0,0 +1,5 @@
> +config COMMON_CLK_HI6220
> +       tristate "Hi6220 Clock Driver"
> +       depends on OF && ARCH_HISI
> +       help
> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index 038c02f..bbf0539 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
> new file mode 100644
> index 0000000..01d0c46
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clk-hi6220.c
> @@ -0,0 +1,284 @@
> +/*
> + * Hisilicon Hi6220 clock driver
> + *
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#include <dt-bindings/clock/hi6220-clock.h>
> +
> +#include "clk.h"
> +
> +
> +/* clocks in AO (always on) controller */
> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
> +};
> +
> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
> +};
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
> +};
> +
> +static void __init hi6220_clk_ao_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
> +
> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
> +
> +
> +/* clocks in sysctrl */
> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
> +};
> +
> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
> +};
> +
> +static void __init hi6220_clk_sys_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
> +
> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
> +
> +
> +/* clocks in media controller */
> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
> +};
> +
> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
> +};
> +
> +static void __init hi6220_clk_media_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
> +
> +       hisi_clk_register_mux(hi6220_mux_clks_media,
> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_media,
> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
> +
> +
> +/* clocks in pmctrl */
> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
> +};
> +
> +static void __init hi6220_clk_power_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate(hi6220_gate_clks_power,
> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_power,
> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
> index a078e84..5d2305c 100644
> --- a/drivers/clk/hisilicon/clk.c
> +++ b/drivers/clk/hisilicon/clk.c
> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>                 data->clk_data.clks[clks[i].id] = clk;
>         }
>  }
> +
> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
> +                                         int nums, struct hisi_clock_data *data)
> +{
> +       struct clk *clk;
> +       void __iomem *base = data->base;
> +       int i;
> +
> +       for (i = 0; i < nums; i++) {
> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
> +                                               clks[i].parent_name,
> +                                               clks[i].flags,
> +                                               base + clks[i].offset,
> +                                               clks[i].shift,
> +                                               clks[i].width,
> +                                               clks[i].mask_bit,
> +                                               &hisi_clk_lock);
> +               if (IS_ERR(clk)) {
> +                       pr_err("%s: failed to register clock %s\n",
> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +
> +               if (clks[i].alias)
> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
> +
> +               data->clk_data.clks[clks[i].id] = clk;
> +       }
> +}
> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
> index 31083ff..462a570 100644
> --- a/drivers/clk/hisilicon/clk.h
> +++ b/drivers/clk/hisilicon/clk.h
> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>         const char              *alias;
>  };
>
> +struct hi6220_divider_clock {
> +       unsigned int            id;
> +       const char              *name;
> +       const char              *parent_name;
> +       unsigned long           flags;
> +       unsigned long           offset;
> +       u8                      shift;
> +       u8                      width;
> +       u32                     mask_bit;
> +       const char              *alias;
> +};
> +
>  struct hisi_gate_clock {
>         unsigned int            id;
>         const char              *name;
> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>                                 const char *, unsigned long,
>                                 void __iomem *, u8,
>                                 u8, spinlock_t *);
> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
> +       const char *parent_name, unsigned long flags, void __iomem *reg,
> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>
>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>                                         int, struct hisi_clock_data *);
>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>                                         int, struct hisi_clock_data *);
> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
> +                                       int, struct hisi_clock_data *);
>  #endif /* __HISI_CLK_H */
> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
> new file mode 100644
> index 0000000..9e3825b
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
> @@ -0,0 +1,273 @@
> +/*
> + * Hisilicon hi6220 SoC divider clock driver
> + *
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +
> +#define div_mask(width)        ((1 << (width)) - 1)
> +
> +/*
> + * The reverse of DIV_ROUND_UP: The maximum number which
> + * divided by m is r
> + */
> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
> +
> +/**
> + * struct hi6220_clk_divider - divider clock for hi6220
> + *
> + * @hw:                handle between common and hardware-specific interfaces
> + * @reg:       register containing divider
> + * @shift:     shift to the divider bit field
> + * @width:     width of the divider bit field
> + * @mask:      mask for setting divider rate
> + * @table:     the div table that the divider supports
> + * @lock:      register lock
> + */
> +struct hi6220_clk_divider {
> +       struct clk_hw   hw;
> +       void __iomem    *reg;
> +       u8              shift;
> +       u8              width;
> +       u32             mask;
> +       const struct clk_div_table *table;
> +       spinlock_t      *lock;
> +};
> +
> +#define to_hi6220_clk_divider(_hw)     \
> +       container_of(_hw, struct hi6220_clk_divider, hw)
> +
> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
> +{
> +       unsigned int maxdiv = 0;
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div > maxdiv)
> +                       maxdiv = clkt->div;
> +       return maxdiv;
> +}
> +
> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
> +                                       unsigned int val)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->val == val)
> +                       return clkt->div;
> +
> +       return 0;
> +}
> +
> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
> +                                       unsigned int div)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div == div)
> +                       return clkt->val;
> +       return 0;
> +}
> +
> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       unsigned int div, val;
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +
> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
> +       val &= div_mask(dclk->width);
> +
> +       div = hi6220_get_table_div(dclk->table, val);
> +       if (!div) {
> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
> +                          __clk_get_name(hw->clk));
> +               return parent_rate;
> +       }
> +
> +       return parent_rate / div;
> +}
> +
> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
> +                               unsigned int div)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div == div)
> +                       return true;
> +       return false;
> +}
> +
> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
> +                                unsigned long *best_parent_rate)
> +{
> +       unsigned int i, bestdiv = 0;
> +       unsigned long parent_rate, best = 0, now, maxdiv;
> +
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
> +
> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
> +
> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
> +               parent_rate = *best_parent_rate;
> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
> +               return bestdiv;
> +       }
> +
> +       /*
> +        * The maximum divider we can use without overflowing
> +        * unsigned long in rate * i below
> +        */
> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
> +
> +       for (i = 1; i <= maxdiv; i++) {
> +               if (!hi6220_is_valid_div(dclk->table, i))
> +                       continue;
> +               parent_rate = __clk_round_rate(clk_parent,
> +                                       MULT_ROUND_UP(rate, i));
> +               now = parent_rate / i;
> +               if (now <= rate && now > best) {
> +                       bestdiv = i;
> +                       best = now;
> +                       *best_parent_rate = parent_rate;
> +               }
> +       }
> +
> +       if (!bestdiv) {
> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
> +       }
> +
> +       return bestdiv;
> +}
> +
> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
> +                                       unsigned long *prate)
> +{
> +       int div;
> +
> +       if (!rate)
> +               rate = 1;
> +
> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
> +
> +       return *prate / div;
> +}
> +
> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
> +                                       unsigned long parent_rate)
> +{
> +       unsigned int div, value;
> +       unsigned long flags = 0;
> +       u32 data;
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +
> +       div = parent_rate / rate;
> +
> +       if (!hi6220_is_valid_div(dclk->table, div))
> +               return -EINVAL;
> +
> +       value = hi6220_get_table_val(dclk->table, div);
> +
> +       if (value > div_mask(dclk->width))
> +               value = div_mask(dclk->width);
> +
> +       if (dclk->lock)
> +               spin_lock_irqsave(dclk->lock, flags);
> +
> +       data = readl_relaxed(dclk->reg);
> +       data &= ~(div_mask(dclk->width) << dclk->shift);
> +       data |= value << dclk->shift;
> +       data |= dclk->mask;
> +
> +       writel_relaxed(data, dclk->reg);
> +
> +       if (dclk->lock)
> +               spin_unlock_irqrestore(dclk->lock, flags);
> +
> +       return 0;
> +}
> +
> +static struct clk_ops hi6220_clkdiv_ops = {
> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
> +       .round_rate = hi6220_clkdiv_round_rate,
> +       .set_rate = hi6220_clkdiv_set_rate,
> +};
> +
> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
> +       const char *parent_name, unsigned long flags, void __iomem *reg,
> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
> +{
> +       struct hi6220_clk_divider *div;
> +       struct clk *clk;
> +       struct clk_init_data init;
> +       struct clk_div_table *table;
> +       u32 max_div, min_div;
> +       int i;
> +
> +       /* allocate the divider */
> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
> +       if (!div) {
> +               pr_err("%s: could not allocate divider clk\n", __func__);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       /* Init the divider table */
> +       max_div = div_mask(width) + 1;
> +       min_div = 1;
> +
> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
> +       if (!table) {
> +               kfree(div);
> +               pr_err("%s: failed to alloc divider table!\n", __func__);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       for (i = 0; i < max_div; i++) {
> +               table[i].div = min_div + i;
> +               table[i].val = table[i].div - 1;
> +       }
> +
> +       init.name = name;
> +       init.ops = &hi6220_clkdiv_ops;
> +       init.flags = flags | CLK_IS_BASIC;
> +       init.parent_names = parent_name ? &parent_name : NULL;
> +       init.num_parents = parent_name ? 1 : 0;
> +
> +       /* struct hi6220_clk_divider assignments */
> +       div->reg = reg;
> +       div->shift = shift;
> +       div->width = width;
> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
> +       div->lock = lock;
> +       div->hw.init = &init;
> +       div->table = table;
> +
> +       /* register the clock */
> +       clk = clk_register(dev, &div->hw);
> +
> +       if (IS_ERR(clk)) {
> +               kfree(table);
> +               kfree(div);
> +       }
> +
> +       return clk;
> +}
> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
> new file mode 100644
> index 0000000..05033e7
> --- /dev/null
> +++ b/include/dt-bindings/clock/hi6220-clock.h
> @@ -0,0 +1,172 @@
> +/*
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
> +#define __DT_BINDINGS_CLOCK_HI6220_H
> +
> +/* clk in AO (always on) controller */
> +#define HI6220_NONE_CLOCK      0
> +
> +/* fixed rate clocks */
> +#define HI6220_REF32K          1
> +#define HI6220_CLK_TCXO                2
> +#define HI6220_MMC1_PAD                3
> +#define HI6220_MMC2_PAD                4
> +#define HI6220_MMC0_PAD                5
> +#define HI6220_PLL_BBP         6
> +#define HI6220_PLL_GPU         7
> +#define HI6220_PLL1_DDR                8
> +#define HI6220_PLL_SYS         9
> +#define HI6220_PLL_SYS_MEDIA   10
> +#define HI6220_DDR_SRC         11
> +#define HI6220_PLL_MEDIA       12
> +#define HI6220_PLL_DDR         13
> +
> +/* fixed factor clocks */
> +#define HI6220_300M            16
> +#define HI6220_150M            17
> +#define HI6220_PICOPHY_SRC     18
> +#define HI6220_MMC0_SRC_SEL    19
> +#define HI6220_MMC1_SRC_SEL    20
> +#define HI6220_MMC2_SRC_SEL    21
> +#define HI6220_VPU_CODEC       22
> +#define HI6220_MMC0_SMP                23
> +#define HI6220_MMC1_SMP                24
> +#define HI6220_MMC2_SMP                25
> +
> +/* gate clocks */
> +#define HI6220_WDT0_PCLK       28
> +#define HI6220_WDT1_PCLK       29
> +#define HI6220_WDT2_PCLK       30
> +#define HI6220_TIMER0_PCLK     31
> +#define HI6220_TIMER1_PCLK     32
> +#define HI6220_TIMER2_PCLK     33
> +#define HI6220_TIMER3_PCLK     34
> +#define HI6220_TIMER4_PCLK     35
> +#define HI6220_TIMER5_PCLK     36
> +#define HI6220_TIMER6_PCLK     37
> +#define HI6220_TIMER7_PCLK     38
> +#define HI6220_TIMER8_PCLK     39
> +#define HI6220_UART0_PCLK      40
> +
> +#define HI6220_AO_NR_CLKS      48
> +
> +/* clk in systrl */
> +/* gate clock */
> +#define HI6220_MMC0_CLK                1
> +#define HI6220_MMC0_CIUCLK     2
> +#define HI6220_MMC1_CLK                3
> +#define HI6220_MMC1_CIUCLK     4
> +#define HI6220_MMC2_CLK                5
> +#define HI6220_MMC2_CIUCLK     6
> +#define HI6220_USBOTG_HCLK     7
> +#define HI6220_CLK_PICOPHY     8
> +#define HI6220_HIFI            9
> +#define HI6220_DACODEC_PCLK    10
> +#define HI6220_EDMAC_ACLK      11
> +#define HI6220_CS_ATB          12
> +#define HI6220_I2C0_CLK                13
> +#define HI6220_I2C1_CLK                14
> +#define HI6220_I2C2_CLK                15
> +#define HI6220_I2C3_CLK                16
> +#define HI6220_UART1_PCLK      17
> +#define HI6220_UART2_PCLK      18
> +#define HI6220_UART3_PCLK      19
> +#define HI6220_UART4_PCLK      20
> +#define HI6220_SPI_CLK         21
> +#define HI6220_MMU_CLK         22
> +#define HI6220_HIFI_SEL                23
> +#define HI6220_MMC0_SYSPLL     24
> +#define HI6220_MMC1_SYSPLL     25
> +#define HI6220_MMC2_SYSPLL     26
> +#define HI6220_MMC0_SEL                27
> +#define HI6220_MMC1_SEL                28
> +#define HI6220_BBPPLL_SEL      29
> +#define HI6220_MEDIA_PLL_SRC   30
> +#define HI6220_MMC2_SEL                31
> +#define HI6220_CS_ATB_SYSPLL   32
> +
> +/* mux clocks */
> +#define HI6220_MMC0_SRC                35
> +#define HI6220_MMC0_SMP_IN     36
> +#define HI6220_MMC1_SRC                37
> +#define HI6220_MMC1_SMP_IN     38
> +#define HI6220_MMC2_SRC                39
> +#define HI6220_MMC2_SMP_IN     40
> +#define HI6220_HIFI_SRC                41
> +#define HI6220_UART1_SRC       42
> +#define HI6220_UART2_SRC       43
> +#define HI6220_UART3_SRC       44
> +#define HI6220_UART4_SRC       45
> +#define HI6220_MMC0_MUX0       46
> +#define HI6220_MMC1_MUX0       47
> +#define HI6220_MMC2_MUX0       48
> +#define HI6220_MMC0_MUX1       49
> +#define HI6220_MMC1_MUX1       50
> +#define HI6220_MMC2_MUX1       51
> +
> +/* divider clocks */
> +#define HI6220_CLK_BUS         54
> +#define HI6220_MMC0_DIV                55
> +#define HI6220_MMC1_DIV                56
> +#define HI6220_MMC2_DIV                57
> +#define HI6220_HIFI_DIV                58
> +#define HI6220_BBPPLL0_DIV     59
> +#define HI6220_CS_DAPB         60
> +#define HI6220_CS_ATB_DIV      61
> +
> +#define HI6220_SYS_NR_CLKS     64
> +
> +/* clk in media controller */
> +/* gate clocks */
> +#define HI6220_DSI_PCLK                1
> +#define HI6220_G3D_PCLK                2
> +#define HI6220_ACLK_CODEC_VPU  3
> +#define HI6220_ISP_SCLK                4
> +#define HI6220_ADE_CORE                5
> +#define HI6220_MED_MMU         6
> +#define HI6220_CFG_CSI4PHY     7
> +#define HI6220_CFG_CSI2PHY     8
> +#define HI6220_ISP_SCLK_GATE   9
> +#define HI6220_ISP_SCLK_GATE1  10
> +#define HI6220_ADE_CORE_GATE   11
> +#define HI6220_CODEC_VPU_GATE  12
> +#define HI6220_MED_SYSPLL      13
> +
> +/* mux clocks */
> +#define HI6220_1440_1200       20
> +#define HI6220_1000_1200       21
> +#define HI6220_1000_1440       22
> +
> +/* divider clocks */
> +#define HI6220_CODEC_JPEG      30
> +#define HI6220_ISP_SCLK_SRC    31
> +#define HI6220_ISP_SCLK1       32
> +#define HI6220_ADE_CORE_SRC    33
> +#define HI6220_ADE_PIX_SRC     34
> +#define HI6220_G3D_CLK         35
> +#define HI6220_CODEC_VPU_SRC   36
> +
> +#define HI6220_MEDIA_NR_CLKS   40
> +
> +/* clk in power controller */
> +/* gate clocks */
> +#define HI6220_PLL_GPU_GATE    1
> +#define HI6220_PLL1_DDR_GATE   2
> +#define HI6220_PLL_DDR_GATE    3
> +#define HI6220_PLL_MEDIA_GATE  4
> +#define HI6220_PLL0_BBP_GATE   5
> +
> +/* divider clocks */
> +#define HI6220_DDRC_SRC                10
> +#define HI6220_DDRC_AXI1       11
> +
> +#define HI6220_POWER_NR_CLKS   16
> +#endif
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Cheers,

- Tyler

[1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
--
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] 85+ messages in thread

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-06 18:10     ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-06 18:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Bintian,

This patch applied to next-20150204 is producing build failures on
various ARM defconfigs[1]. I received the following error in all
cases:

drivers/built-in.o: In function `hi6220_clk_register_divider':
:(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
Makefile:925: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1


On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
> Add clock drivers for hi6220 SoC, this driver controls the SoC
> registers to supply different clocks to different IPs in the SoC.
>
> We add one divider clock for hi6220 because the divider in hi6220
> also has a mask bit but it doesnot obey the rule defined by flag
> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
> left shift fixed bits (e.g. 16 bits), so we add this divider clock
> to handle it.
>
> This patch also enables this clock driver for ARCH_HISI and document
> devicetree bindings.
>
> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>  arch/arm64/Kconfig                                 |    1 +
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    4 +-
>  drivers/clk/hisilicon/Kconfig                      |    5 +
>  drivers/clk/hisilicon/Makefile                     |    1 +
>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>  drivers/clk/hisilicon/clk.c                        |   29 ++
>  drivers/clk/hisilicon/clk.h                        |   17 ++
>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>  11 files changed, 815 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>  create mode 100644 drivers/clk/hisilicon/Kconfig
>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>
> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> new file mode 100644
> index 0000000..a3ddda1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
> @@ -0,0 +1,30 @@
> +* Hisilicon Hi6220 Clock Controller
> +
> +The hi6220 clock controller generates and supplies clock to various
> +controllers within the hi6220 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be one of the following:
> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
> +     power always on(AO) domain, it is the sub node of SoC power AO
> +     controller in dts file.
> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
> +     system control domain, it is the sub node of SoC system controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
> +     SoC media control domain, it is the sub node of SoC media controller
> +     in dts file.
> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
> +     SoC power control domain, it is the sub node of SoC power controller
> +     in dts file.
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- #clock-cells: should be 1.
> +
> +Each clock is assigned an identifier and client nodes use this identifier
> +to specify the clock which they consume.
> +
> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 78cd41c8..6efc3e3 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -175,6 +175,7 @@ config ARCH_XGENE
>
>  config ARCH_HISI
>         bool "Hisilicon SoC Family"
> +       select COMMON_CLK_HI6220
>         help
>           This enables support for Hisilicon ARMv8 Family of SoCs.
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3f44f29..b52c95c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>
>  source "drivers/clk/qcom/Kconfig"
>
> +source "drivers/clk/hisilicon/Kconfig"
> +
>  endmenu
>
>  source "drivers/clk/bcm/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index d5fba5b..c58703b 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
> new file mode 100644
> index 0000000..e3ead46
> --- /dev/null
> +++ b/drivers/clk/hisilicon/Kconfig
> @@ -0,0 +1,5 @@
> +config COMMON_CLK_HI6220
> +       tristate "Hi6220 Clock Driver"
> +       depends on OF && ARCH_HISI
> +       help
> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index 038c02f..bbf0539 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
> new file mode 100644
> index 0000000..01d0c46
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clk-hi6220.c
> @@ -0,0 +1,284 @@
> +/*
> + * Hisilicon Hi6220 clock driver
> + *
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#include <dt-bindings/clock/hi6220-clock.h>
> +
> +#include "clk.h"
> +
> +
> +/* clocks in AO (always on) controller */
> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
> +};
> +
> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
> +};
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
> +};
> +
> +static void __init hi6220_clk_ao_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
> +
> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
> +
> +
> +/* clocks in sysctrl */
> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
> +};
> +
> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
> +};
> +
> +static void __init hi6220_clk_sys_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
> +
> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
> +
> +
> +/* clocks in media controller */
> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
> +
> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
> +};
> +
> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
> +};
> +
> +static void __init hi6220_clk_media_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
> +
> +       hisi_clk_register_mux(hi6220_mux_clks_media,
> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_media,
> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
> +
> +
> +/* clocks in pmctrl */
> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
> +};
> +
> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
> +};
> +
> +static void __init hi6220_clk_power_init(struct device_node *np)
> +{
> +       struct hisi_clock_data *clk_data;
> +
> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       hisi_clk_register_gate(hi6220_gate_clks_power,
> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
> +
> +       hi6220_clk_register_divider(hi6220_div_clks_power,
> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
> +}
> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
> index a078e84..5d2305c 100644
> --- a/drivers/clk/hisilicon/clk.c
> +++ b/drivers/clk/hisilicon/clk.c
> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>                 data->clk_data.clks[clks[i].id] = clk;
>         }
>  }
> +
> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
> +                                         int nums, struct hisi_clock_data *data)
> +{
> +       struct clk *clk;
> +       void __iomem *base = data->base;
> +       int i;
> +
> +       for (i = 0; i < nums; i++) {
> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
> +                                               clks[i].parent_name,
> +                                               clks[i].flags,
> +                                               base + clks[i].offset,
> +                                               clks[i].shift,
> +                                               clks[i].width,
> +                                               clks[i].mask_bit,
> +                                               &hisi_clk_lock);
> +               if (IS_ERR(clk)) {
> +                       pr_err("%s: failed to register clock %s\n",
> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +
> +               if (clks[i].alias)
> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
> +
> +               data->clk_data.clks[clks[i].id] = clk;
> +       }
> +}
> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
> index 31083ff..462a570 100644
> --- a/drivers/clk/hisilicon/clk.h
> +++ b/drivers/clk/hisilicon/clk.h
> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>         const char              *alias;
>  };
>
> +struct hi6220_divider_clock {
> +       unsigned int            id;
> +       const char              *name;
> +       const char              *parent_name;
> +       unsigned long           flags;
> +       unsigned long           offset;
> +       u8                      shift;
> +       u8                      width;
> +       u32                     mask_bit;
> +       const char              *alias;
> +};
> +
>  struct hisi_gate_clock {
>         unsigned int            id;
>         const char              *name;
> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>                                 const char *, unsigned long,
>                                 void __iomem *, u8,
>                                 u8, spinlock_t *);
> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
> +       const char *parent_name, unsigned long flags, void __iomem *reg,
> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>
>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>                                         int, struct hisi_clock_data *);
>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>                                         int, struct hisi_clock_data *);
> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
> +                                       int, struct hisi_clock_data *);
>  #endif /* __HISI_CLK_H */
> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
> new file mode 100644
> index 0000000..9e3825b
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
> @@ -0,0 +1,273 @@
> +/*
> + * Hisilicon hi6220 SoC divider clock driver
> + *
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +
> +#define div_mask(width)        ((1 << (width)) - 1)
> +
> +/*
> + * The reverse of DIV_ROUND_UP: The maximum number which
> + * divided by m is r
> + */
> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
> +
> +/**
> + * struct hi6220_clk_divider - divider clock for hi6220
> + *
> + * @hw:                handle between common and hardware-specific interfaces
> + * @reg:       register containing divider
> + * @shift:     shift to the divider bit field
> + * @width:     width of the divider bit field
> + * @mask:      mask for setting divider rate
> + * @table:     the div table that the divider supports
> + * @lock:      register lock
> + */
> +struct hi6220_clk_divider {
> +       struct clk_hw   hw;
> +       void __iomem    *reg;
> +       u8              shift;
> +       u8              width;
> +       u32             mask;
> +       const struct clk_div_table *table;
> +       spinlock_t      *lock;
> +};
> +
> +#define to_hi6220_clk_divider(_hw)     \
> +       container_of(_hw, struct hi6220_clk_divider, hw)
> +
> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
> +{
> +       unsigned int maxdiv = 0;
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div > maxdiv)
> +                       maxdiv = clkt->div;
> +       return maxdiv;
> +}
> +
> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
> +                                       unsigned int val)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->val == val)
> +                       return clkt->div;
> +
> +       return 0;
> +}
> +
> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
> +                                       unsigned int div)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div == div)
> +                       return clkt->val;
> +       return 0;
> +}
> +
> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       unsigned int div, val;
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +
> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
> +       val &= div_mask(dclk->width);
> +
> +       div = hi6220_get_table_div(dclk->table, val);
> +       if (!div) {
> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
> +                          __clk_get_name(hw->clk));
> +               return parent_rate;
> +       }
> +
> +       return parent_rate / div;
> +}
> +
> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
> +                               unsigned int div)
> +{
> +       const struct clk_div_table *clkt;
> +
> +       for (clkt = table; clkt->div; clkt++)
> +               if (clkt->div == div)
> +                       return true;
> +       return false;
> +}
> +
> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
> +                                unsigned long *best_parent_rate)
> +{
> +       unsigned int i, bestdiv = 0;
> +       unsigned long parent_rate, best = 0, now, maxdiv;
> +
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
> +
> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
> +
> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
> +               parent_rate = *best_parent_rate;
> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
> +               return bestdiv;
> +       }
> +
> +       /*
> +        * The maximum divider we can use without overflowing
> +        * unsigned long in rate * i below
> +        */
> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
> +
> +       for (i = 1; i <= maxdiv; i++) {
> +               if (!hi6220_is_valid_div(dclk->table, i))
> +                       continue;
> +               parent_rate = __clk_round_rate(clk_parent,
> +                                       MULT_ROUND_UP(rate, i));
> +               now = parent_rate / i;
> +               if (now <= rate && now > best) {
> +                       bestdiv = i;
> +                       best = now;
> +                       *best_parent_rate = parent_rate;
> +               }
> +       }
> +
> +       if (!bestdiv) {
> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
> +       }
> +
> +       return bestdiv;
> +}
> +
> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
> +                                       unsigned long *prate)
> +{
> +       int div;
> +
> +       if (!rate)
> +               rate = 1;
> +
> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
> +
> +       return *prate / div;
> +}
> +
> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
> +                                       unsigned long parent_rate)
> +{
> +       unsigned int div, value;
> +       unsigned long flags = 0;
> +       u32 data;
> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
> +
> +       div = parent_rate / rate;
> +
> +       if (!hi6220_is_valid_div(dclk->table, div))
> +               return -EINVAL;
> +
> +       value = hi6220_get_table_val(dclk->table, div);
> +
> +       if (value > div_mask(dclk->width))
> +               value = div_mask(dclk->width);
> +
> +       if (dclk->lock)
> +               spin_lock_irqsave(dclk->lock, flags);
> +
> +       data = readl_relaxed(dclk->reg);
> +       data &= ~(div_mask(dclk->width) << dclk->shift);
> +       data |= value << dclk->shift;
> +       data |= dclk->mask;
> +
> +       writel_relaxed(data, dclk->reg);
> +
> +       if (dclk->lock)
> +               spin_unlock_irqrestore(dclk->lock, flags);
> +
> +       return 0;
> +}
> +
> +static struct clk_ops hi6220_clkdiv_ops = {
> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
> +       .round_rate = hi6220_clkdiv_round_rate,
> +       .set_rate = hi6220_clkdiv_set_rate,
> +};
> +
> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
> +       const char *parent_name, unsigned long flags, void __iomem *reg,
> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
> +{
> +       struct hi6220_clk_divider *div;
> +       struct clk *clk;
> +       struct clk_init_data init;
> +       struct clk_div_table *table;
> +       u32 max_div, min_div;
> +       int i;
> +
> +       /* allocate the divider */
> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
> +       if (!div) {
> +               pr_err("%s: could not allocate divider clk\n", __func__);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       /* Init the divider table */
> +       max_div = div_mask(width) + 1;
> +       min_div = 1;
> +
> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
> +       if (!table) {
> +               kfree(div);
> +               pr_err("%s: failed to alloc divider table!\n", __func__);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       for (i = 0; i < max_div; i++) {
> +               table[i].div = min_div + i;
> +               table[i].val = table[i].div - 1;
> +       }
> +
> +       init.name = name;
> +       init.ops = &hi6220_clkdiv_ops;
> +       init.flags = flags | CLK_IS_BASIC;
> +       init.parent_names = parent_name ? &parent_name : NULL;
> +       init.num_parents = parent_name ? 1 : 0;
> +
> +       /* struct hi6220_clk_divider assignments */
> +       div->reg = reg;
> +       div->shift = shift;
> +       div->width = width;
> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
> +       div->lock = lock;
> +       div->hw.init = &init;
> +       div->table = table;
> +
> +       /* register the clock */
> +       clk = clk_register(dev, &div->hw);
> +
> +       if (IS_ERR(clk)) {
> +               kfree(table);
> +               kfree(div);
> +       }
> +
> +       return clk;
> +}
> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
> new file mode 100644
> index 0000000..05033e7
> --- /dev/null
> +++ b/include/dt-bindings/clock/hi6220-clock.h
> @@ -0,0 +1,172 @@
> +/*
> + * Copyright (c) 2015 Hisilicon Limited.
> + *
> + * Author: Bintian Wang <bintian.wang@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
> +#define __DT_BINDINGS_CLOCK_HI6220_H
> +
> +/* clk in AO (always on) controller */
> +#define HI6220_NONE_CLOCK      0
> +
> +/* fixed rate clocks */
> +#define HI6220_REF32K          1
> +#define HI6220_CLK_TCXO                2
> +#define HI6220_MMC1_PAD                3
> +#define HI6220_MMC2_PAD                4
> +#define HI6220_MMC0_PAD                5
> +#define HI6220_PLL_BBP         6
> +#define HI6220_PLL_GPU         7
> +#define HI6220_PLL1_DDR                8
> +#define HI6220_PLL_SYS         9
> +#define HI6220_PLL_SYS_MEDIA   10
> +#define HI6220_DDR_SRC         11
> +#define HI6220_PLL_MEDIA       12
> +#define HI6220_PLL_DDR         13
> +
> +/* fixed factor clocks */
> +#define HI6220_300M            16
> +#define HI6220_150M            17
> +#define HI6220_PICOPHY_SRC     18
> +#define HI6220_MMC0_SRC_SEL    19
> +#define HI6220_MMC1_SRC_SEL    20
> +#define HI6220_MMC2_SRC_SEL    21
> +#define HI6220_VPU_CODEC       22
> +#define HI6220_MMC0_SMP                23
> +#define HI6220_MMC1_SMP                24
> +#define HI6220_MMC2_SMP                25
> +
> +/* gate clocks */
> +#define HI6220_WDT0_PCLK       28
> +#define HI6220_WDT1_PCLK       29
> +#define HI6220_WDT2_PCLK       30
> +#define HI6220_TIMER0_PCLK     31
> +#define HI6220_TIMER1_PCLK     32
> +#define HI6220_TIMER2_PCLK     33
> +#define HI6220_TIMER3_PCLK     34
> +#define HI6220_TIMER4_PCLK     35
> +#define HI6220_TIMER5_PCLK     36
> +#define HI6220_TIMER6_PCLK     37
> +#define HI6220_TIMER7_PCLK     38
> +#define HI6220_TIMER8_PCLK     39
> +#define HI6220_UART0_PCLK      40
> +
> +#define HI6220_AO_NR_CLKS      48
> +
> +/* clk in systrl */
> +/* gate clock */
> +#define HI6220_MMC0_CLK                1
> +#define HI6220_MMC0_CIUCLK     2
> +#define HI6220_MMC1_CLK                3
> +#define HI6220_MMC1_CIUCLK     4
> +#define HI6220_MMC2_CLK                5
> +#define HI6220_MMC2_CIUCLK     6
> +#define HI6220_USBOTG_HCLK     7
> +#define HI6220_CLK_PICOPHY     8
> +#define HI6220_HIFI            9
> +#define HI6220_DACODEC_PCLK    10
> +#define HI6220_EDMAC_ACLK      11
> +#define HI6220_CS_ATB          12
> +#define HI6220_I2C0_CLK                13
> +#define HI6220_I2C1_CLK                14
> +#define HI6220_I2C2_CLK                15
> +#define HI6220_I2C3_CLK                16
> +#define HI6220_UART1_PCLK      17
> +#define HI6220_UART2_PCLK      18
> +#define HI6220_UART3_PCLK      19
> +#define HI6220_UART4_PCLK      20
> +#define HI6220_SPI_CLK         21
> +#define HI6220_MMU_CLK         22
> +#define HI6220_HIFI_SEL                23
> +#define HI6220_MMC0_SYSPLL     24
> +#define HI6220_MMC1_SYSPLL     25
> +#define HI6220_MMC2_SYSPLL     26
> +#define HI6220_MMC0_SEL                27
> +#define HI6220_MMC1_SEL                28
> +#define HI6220_BBPPLL_SEL      29
> +#define HI6220_MEDIA_PLL_SRC   30
> +#define HI6220_MMC2_SEL                31
> +#define HI6220_CS_ATB_SYSPLL   32
> +
> +/* mux clocks */
> +#define HI6220_MMC0_SRC                35
> +#define HI6220_MMC0_SMP_IN     36
> +#define HI6220_MMC1_SRC                37
> +#define HI6220_MMC1_SMP_IN     38
> +#define HI6220_MMC2_SRC                39
> +#define HI6220_MMC2_SMP_IN     40
> +#define HI6220_HIFI_SRC                41
> +#define HI6220_UART1_SRC       42
> +#define HI6220_UART2_SRC       43
> +#define HI6220_UART3_SRC       44
> +#define HI6220_UART4_SRC       45
> +#define HI6220_MMC0_MUX0       46
> +#define HI6220_MMC1_MUX0       47
> +#define HI6220_MMC2_MUX0       48
> +#define HI6220_MMC0_MUX1       49
> +#define HI6220_MMC1_MUX1       50
> +#define HI6220_MMC2_MUX1       51
> +
> +/* divider clocks */
> +#define HI6220_CLK_BUS         54
> +#define HI6220_MMC0_DIV                55
> +#define HI6220_MMC1_DIV                56
> +#define HI6220_MMC2_DIV                57
> +#define HI6220_HIFI_DIV                58
> +#define HI6220_BBPPLL0_DIV     59
> +#define HI6220_CS_DAPB         60
> +#define HI6220_CS_ATB_DIV      61
> +
> +#define HI6220_SYS_NR_CLKS     64
> +
> +/* clk in media controller */
> +/* gate clocks */
> +#define HI6220_DSI_PCLK                1
> +#define HI6220_G3D_PCLK                2
> +#define HI6220_ACLK_CODEC_VPU  3
> +#define HI6220_ISP_SCLK                4
> +#define HI6220_ADE_CORE                5
> +#define HI6220_MED_MMU         6
> +#define HI6220_CFG_CSI4PHY     7
> +#define HI6220_CFG_CSI2PHY     8
> +#define HI6220_ISP_SCLK_GATE   9
> +#define HI6220_ISP_SCLK_GATE1  10
> +#define HI6220_ADE_CORE_GATE   11
> +#define HI6220_CODEC_VPU_GATE  12
> +#define HI6220_MED_SYSPLL      13
> +
> +/* mux clocks */
> +#define HI6220_1440_1200       20
> +#define HI6220_1000_1200       21
> +#define HI6220_1000_1440       22
> +
> +/* divider clocks */
> +#define HI6220_CODEC_JPEG      30
> +#define HI6220_ISP_SCLK_SRC    31
> +#define HI6220_ISP_SCLK1       32
> +#define HI6220_ADE_CORE_SRC    33
> +#define HI6220_ADE_PIX_SRC     34
> +#define HI6220_G3D_CLK         35
> +#define HI6220_CODEC_VPU_SRC   36
> +
> +#define HI6220_MEDIA_NR_CLKS   40
> +
> +/* clk in power controller */
> +/* gate clocks */
> +#define HI6220_PLL_GPU_GATE    1
> +#define HI6220_PLL1_DDR_GATE   2
> +#define HI6220_PLL_DDR_GATE    3
> +#define HI6220_PLL_MEDIA_GATE  4
> +#define HI6220_PLL0_BBP_GATE   5
> +
> +/* divider clocks */
> +#define HI6220_DDRC_SRC                10
> +#define HI6220_DDRC_AXI1       11
> +
> +#define HI6220_POWER_NR_CLKS   16
> +#endif
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Cheers,

- Tyler

[1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-07  2:05       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-07  2:05 UTC (permalink / raw)
  To: Tyler Baker
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, Rob Herring, Paweł Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Olof Johansson, Haifeng Yan, Stephen Boyd,
	xuejiancheng, sledge.yanwei, Tomeu Vizoso,
	Russell King - ARM Linux, Guodong Xu, dan.zhao, huxinwei,
	xuyiping, victor.lixin, btw, puck.chen, wangbinghui,
	zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

Hello Tyler,

Thank you very much for helping test this patchset!

2015-02-07 2:10 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
> Hi Bintian,
>
> This patch applied to next-20150204 is producing build failures on
> various ARM defconfigs[1]. I received the following error in all
> cases:
>
> drivers/built-in.o: In function `hi6220_clk_register_divider':
> :(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
> Makefile:925: recipe for target 'vmlinux' failed
> make: *** [vmlinux] Error 1
It's my fault, I just test on ARM64, The following patch can fix this error:
=====================
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index bbf0539..48f0116 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,9 +2,9 @@
 # Hisilicon Clock specific Makefile
 #

-obj-y  += clk.o clkgate-separated.o
+obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o

 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
-obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
+obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
======================

I will fix this problem in next version.

Thanks,

Bintian


>
> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>> registers to supply different clocks to different IPs in the SoC.
>>
>> We add one divider clock for hi6220 because the divider in hi6220
>> also has a mask bit but it doesnot obey the rule defined by flag
>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>> to handle it.
>>
>> This patch also enables this clock driver for ARCH_HISI and document
>> devicetree bindings.
>>
>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> ---
>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>  arch/arm64/Kconfig                                 |    1 +
>>  drivers/clk/Kconfig                                |    2 +
>>  drivers/clk/Makefile                               |    4 +-
>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> new file mode 100644
>> index 0000000..a3ddda1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> @@ -0,0 +1,30 @@
>> +* Hisilicon Hi6220 Clock Controller
>> +
>> +The hi6220 clock controller generates and supplies clock to various
>> +controllers within the hi6220 SoC.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be one of the following:
>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>> +     power always on(AO) domain, it is the sub node of SoC power AO
>> +     controller in dts file.
>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>> +     system control domain, it is the sub node of SoC system controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>> +     SoC media control domain, it is the sub node of SoC media controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>> +     SoC power control domain, it is the sub node of SoC power controller
>> +     in dts file.
>> +
>> +- reg: physical base address of the controller and length of memory mapped
>> +  region.
>> +
>> +- #clock-cells: should be 1.
>> +
>> +Each clock is assigned an identifier and client nodes use this identifier
>> +to specify the clock which they consume.
>> +
>> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 78cd41c8..6efc3e3 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -175,6 +175,7 @@ config ARCH_XGENE
>>
>>  config ARCH_HISI
>>         bool "Hisilicon SoC Family"
>> +       select COMMON_CLK_HI6220
>>         help
>>           This enables support for Hisilicon ARMv8 Family of SoCs.
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index 3f44f29..b52c95c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>>
>>  source "drivers/clk/qcom/Kconfig"
>>
>> +source "drivers/clk/hisilicon/Kconfig"
>> +
>>  endmenu
>>
>>  source "drivers/clk/bcm/Kconfig"
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index d5fba5b..c58703b 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
>> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
>> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>>  ifeq ($(CONFIG_COMMON_CLK), y)
>>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
>> new file mode 100644
>> index 0000000..e3ead46
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/Kconfig
>> @@ -0,0 +1,5 @@
>> +config COMMON_CLK_HI6220
>> +       tristate "Hi6220 Clock Driver"
>> +       depends on OF && ARCH_HISI
>> +       help
>> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
>> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
>> index 038c02f..bbf0539 100644
>> --- a/drivers/clk/hisilicon/Makefile
>> +++ b/drivers/clk/hisilicon/Makefile
>> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
>> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
>> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
>> new file mode 100644
>> index 0000000..01d0c46
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/clk-hi6220.c
>> @@ -0,0 +1,284 @@
>> +/*
>> + * Hisilicon Hi6220 clock driver
>> + *
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk.h>
>> +
>> +#include <dt-bindings/clock/hi6220-clock.h>
>> +
>> +#include "clk.h"
>> +
>> +
>> +/* clocks in AO (always on) controller */
>> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
>> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
>> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
>> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
>> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
>> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
>> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
>> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
>> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
>> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
>> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
>> +};
>> +
>> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
>> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
>> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
>> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
>> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
>> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
>> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
>> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
>> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
>> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
>> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
>> +};
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
>> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
>> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
>> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
>> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
>> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
>> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
>> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
>> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
>> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
>> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
>> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
>> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
>> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
>> +};
>> +
>> +static void __init hi6220_clk_ao_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
>> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
>> +
>> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
>> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
>> +
>> +
>> +/* clocks in sysctrl */
>> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
>> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
>> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
>> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
>> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
>> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
>> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
>> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
>> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
>> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
>> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
>> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
>> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
>> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
>> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
>> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
>> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
>> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
>> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
>> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
>> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
>> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
>> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
>> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
>> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
>> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
>> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
>> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
>> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
>> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
>> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
>> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
>> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
>> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
>> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
>> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
>> +};
>> +
>> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
>> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
>> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
>> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
>> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
>> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
>> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
>> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
>> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
>> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
>> +};
>> +
>> +static void __init hi6220_clk_sys_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
>> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
>> +
>> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
>> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
>> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
>> +
>> +
>> +/* clocks in media controller */
>> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
>> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
>> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
>> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
>> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
>> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
>> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
>> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
>> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
>> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
>> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
>> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
>> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
>> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
>> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
>> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
>> +};
>> +
>> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
>> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
>> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
>> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
>> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
>> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
>> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
>> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
>> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
>> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
>> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
>> +};
>> +
>> +static void __init hi6220_clk_media_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
>> +
>> +       hisi_clk_register_mux(hi6220_mux_clks_media,
>> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_media,
>> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
>> +
>> +
>> +/* clocks in pmctrl */
>> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
>> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
>> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
>> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
>> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
>> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
>> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
>> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
>> +};
>> +
>> +static void __init hi6220_clk_power_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate(hi6220_gate_clks_power,
>> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_power,
>> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
>> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
>> index a078e84..5d2305c 100644
>> --- a/drivers/clk/hisilicon/clk.c
>> +++ b/drivers/clk/hisilicon/clk.c
>> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>>                 data->clk_data.clks[clks[i].id] = clk;
>>         }
>>  }
>> +
>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
>> +                                         int nums, struct hisi_clock_data *data)
>> +{
>> +       struct clk *clk;
>> +       void __iomem *base = data->base;
>> +       int i;
>> +
>> +       for (i = 0; i < nums; i++) {
>> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
>> +                                               clks[i].parent_name,
>> +                                               clks[i].flags,
>> +                                               base + clks[i].offset,
>> +                                               clks[i].shift,
>> +                                               clks[i].width,
>> +                                               clks[i].mask_bit,
>> +                                               &hisi_clk_lock);
>> +               if (IS_ERR(clk)) {
>> +                       pr_err("%s: failed to register clock %s\n",
>> +                              __func__, clks[i].name);
>> +                       continue;
>> +               }
>> +
>> +               if (clks[i].alias)
>> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
>> +
>> +               data->clk_data.clks[clks[i].id] = clk;
>> +       }
>> +}
>> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
>> index 31083ff..462a570 100644
>> --- a/drivers/clk/hisilicon/clk.h
>> +++ b/drivers/clk/hisilicon/clk.h
>> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>>         const char              *alias;
>>  };
>>
>> +struct hi6220_divider_clock {
>> +       unsigned int            id;
>> +       const char              *name;
>> +       const char              *parent_name;
>> +       unsigned long           flags;
>> +       unsigned long           offset;
>> +       u8                      shift;
>> +       u8                      width;
>> +       u32                     mask_bit;
>> +       const char              *alias;
>> +};
>> +
>>  struct hisi_gate_clock {
>>         unsigned int            id;
>>         const char              *name;
>> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>>                                 const char *, unsigned long,
>>                                 void __iomem *, u8,
>>                                 u8, spinlock_t *);
>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>>
>>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
>> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>>                                         int, struct hisi_clock_data *);
>>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>>                                         int, struct hisi_clock_data *);
>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
>> +                                       int, struct hisi_clock_data *);
>>  #endif /* __HISI_CLK_H */
>> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
>> new file mode 100644
>> index 0000000..9e3825b
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
>> @@ -0,0 +1,273 @@
>> +/*
>> + * Hisilicon hi6220 SoC divider clock driver
>> + *
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/err.h>
>> +
>> +#define div_mask(width)        ((1 << (width)) - 1)
>> +
>> +/*
>> + * The reverse of DIV_ROUND_UP: The maximum number which
>> + * divided by m is r
>> + */
>> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
>> +
>> +/**
>> + * struct hi6220_clk_divider - divider clock for hi6220
>> + *
>> + * @hw:                handle between common and hardware-specific interfaces
>> + * @reg:       register containing divider
>> + * @shift:     shift to the divider bit field
>> + * @width:     width of the divider bit field
>> + * @mask:      mask for setting divider rate
>> + * @table:     the div table that the divider supports
>> + * @lock:      register lock
>> + */
>> +struct hi6220_clk_divider {
>> +       struct clk_hw   hw;
>> +       void __iomem    *reg;
>> +       u8              shift;
>> +       u8              width;
>> +       u32             mask;
>> +       const struct clk_div_table *table;
>> +       spinlock_t      *lock;
>> +};
>> +
>> +#define to_hi6220_clk_divider(_hw)     \
>> +       container_of(_hw, struct hi6220_clk_divider, hw)
>> +
>> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
>> +{
>> +       unsigned int maxdiv = 0;
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div > maxdiv)
>> +                       maxdiv = clkt->div;
>> +       return maxdiv;
>> +}
>> +
>> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
>> +                                       unsigned int val)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->val == val)
>> +                       return clkt->div;
>> +
>> +       return 0;
>> +}
>> +
>> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
>> +                                       unsigned int div)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div == div)
>> +                       return clkt->val;
>> +       return 0;
>> +}
>> +
>> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
>> +                                       unsigned long parent_rate)
>> +{
>> +       unsigned int div, val;
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +
>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>> +       val &= div_mask(dclk->width);
>> +
>> +       div = hi6220_get_table_div(dclk->table, val);
>> +       if (!div) {
>> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
>> +                          __clk_get_name(hw->clk));
>> +               return parent_rate;
>> +       }
>> +
>> +       return parent_rate / div;
>> +}
>> +
>> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
>> +                               unsigned int div)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div == div)
>> +                       return true;
>> +       return false;
>> +}
>> +
>> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
>> +                                unsigned long *best_parent_rate)
>> +{
>> +       unsigned int i, bestdiv = 0;
>> +       unsigned long parent_rate, best = 0, now, maxdiv;
>> +
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
>> +
>> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
>> +
>> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>> +               parent_rate = *best_parent_rate;
>> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
>> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
>> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
>> +               return bestdiv;
>> +       }
>> +
>> +       /*
>> +        * The maximum divider we can use without overflowing
>> +        * unsigned long in rate * i below
>> +        */
>> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
>> +
>> +       for (i = 1; i <= maxdiv; i++) {
>> +               if (!hi6220_is_valid_div(dclk->table, i))
>> +                       continue;
>> +               parent_rate = __clk_round_rate(clk_parent,
>> +                                       MULT_ROUND_UP(rate, i));
>> +               now = parent_rate / i;
>> +               if (now <= rate && now > best) {
>> +                       bestdiv = i;
>> +                       best = now;
>> +                       *best_parent_rate = parent_rate;
>> +               }
>> +       }
>> +
>> +       if (!bestdiv) {
>> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
>> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
>> +       }
>> +
>> +       return bestdiv;
>> +}
>> +
>> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>> +                                       unsigned long *prate)
>> +{
>> +       int div;
>> +
>> +       if (!rate)
>> +               rate = 1;
>> +
>> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
>> +
>> +       return *prate / div;
>> +}
>> +
>> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>> +                                       unsigned long parent_rate)
>> +{
>> +       unsigned int div, value;
>> +       unsigned long flags = 0;
>> +       u32 data;
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +
>> +       div = parent_rate / rate;
>> +
>> +       if (!hi6220_is_valid_div(dclk->table, div))
>> +               return -EINVAL;
>> +
>> +       value = hi6220_get_table_val(dclk->table, div);
>> +
>> +       if (value > div_mask(dclk->width))
>> +               value = div_mask(dclk->width);
>> +
>> +       if (dclk->lock)
>> +               spin_lock_irqsave(dclk->lock, flags);
>> +
>> +       data = readl_relaxed(dclk->reg);
>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>> +       data |= value << dclk->shift;
>> +       data |= dclk->mask;
>> +
>> +       writel_relaxed(data, dclk->reg);
>> +
>> +       if (dclk->lock)
>> +               spin_unlock_irqrestore(dclk->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static struct clk_ops hi6220_clkdiv_ops = {
>> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
>> +       .round_rate = hi6220_clkdiv_round_rate,
>> +       .set_rate = hi6220_clkdiv_set_rate,
>> +};
>> +
>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
>> +{
>> +       struct hi6220_clk_divider *div;
>> +       struct clk *clk;
>> +       struct clk_init_data init;
>> +       struct clk_div_table *table;
>> +       u32 max_div, min_div;
>> +       int i;
>> +
>> +       /* allocate the divider */
>> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
>> +       if (!div) {
>> +               pr_err("%s: could not allocate divider clk\n", __func__);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       /* Init the divider table */
>> +       max_div = div_mask(width) + 1;
>> +       min_div = 1;
>> +
>> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
>> +       if (!table) {
>> +               kfree(div);
>> +               pr_err("%s: failed to alloc divider table!\n", __func__);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       for (i = 0; i < max_div; i++) {
>> +               table[i].div = min_div + i;
>> +               table[i].val = table[i].div - 1;
>> +       }
>> +
>> +       init.name = name;
>> +       init.ops = &hi6220_clkdiv_ops;
>> +       init.flags = flags | CLK_IS_BASIC;
>> +       init.parent_names = parent_name ? &parent_name : NULL;
>> +       init.num_parents = parent_name ? 1 : 0;
>> +
>> +       /* struct hi6220_clk_divider assignments */
>> +       div->reg = reg;
>> +       div->shift = shift;
>> +       div->width = width;
>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>> +       div->lock = lock;
>> +       div->hw.init = &init;
>> +       div->table = table;
>> +
>> +       /* register the clock */
>> +       clk = clk_register(dev, &div->hw);
>> +
>> +       if (IS_ERR(clk)) {
>> +               kfree(table);
>> +               kfree(div);
>> +       }
>> +
>> +       return clk;
>> +}
>> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
>> new file mode 100644
>> index 0000000..05033e7
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/hi6220-clock.h
>> @@ -0,0 +1,172 @@
>> +/*
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
>> +#define __DT_BINDINGS_CLOCK_HI6220_H
>> +
>> +/* clk in AO (always on) controller */
>> +#define HI6220_NONE_CLOCK      0
>> +
>> +/* fixed rate clocks */
>> +#define HI6220_REF32K          1
>> +#define HI6220_CLK_TCXO                2
>> +#define HI6220_MMC1_PAD                3
>> +#define HI6220_MMC2_PAD                4
>> +#define HI6220_MMC0_PAD                5
>> +#define HI6220_PLL_BBP         6
>> +#define HI6220_PLL_GPU         7
>> +#define HI6220_PLL1_DDR                8
>> +#define HI6220_PLL_SYS         9
>> +#define HI6220_PLL_SYS_MEDIA   10
>> +#define HI6220_DDR_SRC         11
>> +#define HI6220_PLL_MEDIA       12
>> +#define HI6220_PLL_DDR         13
>> +
>> +/* fixed factor clocks */
>> +#define HI6220_300M            16
>> +#define HI6220_150M            17
>> +#define HI6220_PICOPHY_SRC     18
>> +#define HI6220_MMC0_SRC_SEL    19
>> +#define HI6220_MMC1_SRC_SEL    20
>> +#define HI6220_MMC2_SRC_SEL    21
>> +#define HI6220_VPU_CODEC       22
>> +#define HI6220_MMC0_SMP                23
>> +#define HI6220_MMC1_SMP                24
>> +#define HI6220_MMC2_SMP                25
>> +
>> +/* gate clocks */
>> +#define HI6220_WDT0_PCLK       28
>> +#define HI6220_WDT1_PCLK       29
>> +#define HI6220_WDT2_PCLK       30
>> +#define HI6220_TIMER0_PCLK     31
>> +#define HI6220_TIMER1_PCLK     32
>> +#define HI6220_TIMER2_PCLK     33
>> +#define HI6220_TIMER3_PCLK     34
>> +#define HI6220_TIMER4_PCLK     35
>> +#define HI6220_TIMER5_PCLK     36
>> +#define HI6220_TIMER6_PCLK     37
>> +#define HI6220_TIMER7_PCLK     38
>> +#define HI6220_TIMER8_PCLK     39
>> +#define HI6220_UART0_PCLK      40
>> +
>> +#define HI6220_AO_NR_CLKS      48
>> +
>> +/* clk in systrl */
>> +/* gate clock */
>> +#define HI6220_MMC0_CLK                1
>> +#define HI6220_MMC0_CIUCLK     2
>> +#define HI6220_MMC1_CLK                3
>> +#define HI6220_MMC1_CIUCLK     4
>> +#define HI6220_MMC2_CLK                5
>> +#define HI6220_MMC2_CIUCLK     6
>> +#define HI6220_USBOTG_HCLK     7
>> +#define HI6220_CLK_PICOPHY     8
>> +#define HI6220_HIFI            9
>> +#define HI6220_DACODEC_PCLK    10
>> +#define HI6220_EDMAC_ACLK      11
>> +#define HI6220_CS_ATB          12
>> +#define HI6220_I2C0_CLK                13
>> +#define HI6220_I2C1_CLK                14
>> +#define HI6220_I2C2_CLK                15
>> +#define HI6220_I2C3_CLK                16
>> +#define HI6220_UART1_PCLK      17
>> +#define HI6220_UART2_PCLK      18
>> +#define HI6220_UART3_PCLK      19
>> +#define HI6220_UART4_PCLK      20
>> +#define HI6220_SPI_CLK         21
>> +#define HI6220_MMU_CLK         22
>> +#define HI6220_HIFI_SEL                23
>> +#define HI6220_MMC0_SYSPLL     24
>> +#define HI6220_MMC1_SYSPLL     25
>> +#define HI6220_MMC2_SYSPLL     26
>> +#define HI6220_MMC0_SEL                27
>> +#define HI6220_MMC1_SEL                28
>> +#define HI6220_BBPPLL_SEL      29
>> +#define HI6220_MEDIA_PLL_SRC   30
>> +#define HI6220_MMC2_SEL                31
>> +#define HI6220_CS_ATB_SYSPLL   32
>> +
>> +/* mux clocks */
>> +#define HI6220_MMC0_SRC                35
>> +#define HI6220_MMC0_SMP_IN     36
>> +#define HI6220_MMC1_SRC                37
>> +#define HI6220_MMC1_SMP_IN     38
>> +#define HI6220_MMC2_SRC                39
>> +#define HI6220_MMC2_SMP_IN     40
>> +#define HI6220_HIFI_SRC                41
>> +#define HI6220_UART1_SRC       42
>> +#define HI6220_UART2_SRC       43
>> +#define HI6220_UART3_SRC       44
>> +#define HI6220_UART4_SRC       45
>> +#define HI6220_MMC0_MUX0       46
>> +#define HI6220_MMC1_MUX0       47
>> +#define HI6220_MMC2_MUX0       48
>> +#define HI6220_MMC0_MUX1       49
>> +#define HI6220_MMC1_MUX1       50
>> +#define HI6220_MMC2_MUX1       51
>> +
>> +/* divider clocks */
>> +#define HI6220_CLK_BUS         54
>> +#define HI6220_MMC0_DIV                55
>> +#define HI6220_MMC1_DIV                56
>> +#define HI6220_MMC2_DIV                57
>> +#define HI6220_HIFI_DIV                58
>> +#define HI6220_BBPPLL0_DIV     59
>> +#define HI6220_CS_DAPB         60
>> +#define HI6220_CS_ATB_DIV      61
>> +
>> +#define HI6220_SYS_NR_CLKS     64
>> +
>> +/* clk in media controller */
>> +/* gate clocks */
>> +#define HI6220_DSI_PCLK                1
>> +#define HI6220_G3D_PCLK                2
>> +#define HI6220_ACLK_CODEC_VPU  3
>> +#define HI6220_ISP_SCLK                4
>> +#define HI6220_ADE_CORE                5
>> +#define HI6220_MED_MMU         6
>> +#define HI6220_CFG_CSI4PHY     7
>> +#define HI6220_CFG_CSI2PHY     8
>> +#define HI6220_ISP_SCLK_GATE   9
>> +#define HI6220_ISP_SCLK_GATE1  10
>> +#define HI6220_ADE_CORE_GATE   11
>> +#define HI6220_CODEC_VPU_GATE  12
>> +#define HI6220_MED_SYSPLL      13
>> +
>> +/* mux clocks */
>> +#define HI6220_1440_1200       20
>> +#define HI6220_1000_1200       21
>> +#define HI6220_1000_1440       22
>> +
>> +/* divider clocks */
>> +#define HI6220_CODEC_JPEG      30
>> +#define HI6220_ISP_SCLK_SRC    31
>> +#define HI6220_ISP_SCLK1       32
>> +#define HI6220_ADE_CORE_SRC    33
>> +#define HI6220_ADE_PIX_SRC     34
>> +#define HI6220_G3D_CLK         35
>> +#define HI6220_CODEC_VPU_SRC   36
>> +
>> +#define HI6220_MEDIA_NR_CLKS   40
>> +
>> +/* clk in power controller */
>> +/* gate clocks */
>> +#define HI6220_PLL_GPU_GATE    1
>> +#define HI6220_PLL1_DDR_GATE   2
>> +#define HI6220_PLL_DDR_GATE    3
>> +#define HI6220_PLL_MEDIA_GATE  4
>> +#define HI6220_PLL0_BBP_GATE   5
>> +
>> +/* divider clocks */
>> +#define HI6220_DDRC_SRC                10
>> +#define HI6220_DDRC_AXI1       11
>> +
>> +#define HI6220_POWER_NR_CLKS   16
>> +#endif
>> --
>> 1.7.9.5
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> Cheers,
>
> - Tyler
>
> [1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-07  2:05       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-07  2:05 UTC (permalink / raw)
  To: Tyler Baker
  Cc: Bintian Wang, linux-arm-kernel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Paweł Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Kevin Hilman, Mike Turquette, Rob Herring, Zhangfei Gao,
	Haojian Zhuang, Xu Wei, Jaehoon Chung, Olof Johansson,
	Haifeng Yan, Stephen Boyd

Hello Tyler,

Thank you very much for helping test this patchset!

2015-02-07 2:10 GMT+08:00 Tyler Baker <tyler.baker-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
> Hi Bintian,
>
> This patch applied to next-20150204 is producing build failures on
> various ARM defconfigs[1]. I received the following error in all
> cases:
>
> drivers/built-in.o: In function `hi6220_clk_register_divider':
> :(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
> Makefile:925: recipe for target 'vmlinux' failed
> make: *** [vmlinux] Error 1
It's my fault, I just test on ARM64, The following patch can fix this error:
=====================
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index bbf0539..48f0116 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,9 +2,9 @@
 # Hisilicon Clock specific Makefile
 #

-obj-y  += clk.o clkgate-separated.o
+obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o

 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
-obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
+obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
======================

I will fix this problem in next version.

Thanks,

Bintian


>
> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>> registers to supply different clocks to different IPs in the SoC.
>>
>> We add one divider clock for hi6220 because the divider in hi6220
>> also has a mask bit but it doesnot obey the rule defined by flag
>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>> to handle it.
>>
>> This patch also enables this clock driver for ARCH_HISI and document
>> devicetree bindings.
>>
>> Signed-off-by: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Reviewed-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>  arch/arm64/Kconfig                                 |    1 +
>>  drivers/clk/Kconfig                                |    2 +
>>  drivers/clk/Makefile                               |    4 +-
>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> new file mode 100644
>> index 0000000..a3ddda1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> @@ -0,0 +1,30 @@
>> +* Hisilicon Hi6220 Clock Controller
>> +
>> +The hi6220 clock controller generates and supplies clock to various
>> +controllers within the hi6220 SoC.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be one of the following:
>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>> +     power always on(AO) domain, it is the sub node of SoC power AO
>> +     controller in dts file.
>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>> +     system control domain, it is the sub node of SoC system controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>> +     SoC media control domain, it is the sub node of SoC media controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>> +     SoC power control domain, it is the sub node of SoC power controller
>> +     in dts file.
>> +
>> +- reg: physical base address of the controller and length of memory mapped
>> +  region.
>> +
>> +- #clock-cells: should be 1.
>> +
>> +Each clock is assigned an identifier and client nodes use this identifier
>> +to specify the clock which they consume.
>> +
>> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 78cd41c8..6efc3e3 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -175,6 +175,7 @@ config ARCH_XGENE
>>
>>  config ARCH_HISI
>>         bool "Hisilicon SoC Family"
>> +       select COMMON_CLK_HI6220
>>         help
>>           This enables support for Hisilicon ARMv8 Family of SoCs.
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index 3f44f29..b52c95c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>>
>>  source "drivers/clk/qcom/Kconfig"
>>
>> +source "drivers/clk/hisilicon/Kconfig"
>> +
>>  endmenu
>>
>>  source "drivers/clk/bcm/Kconfig"
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index d5fba5b..c58703b 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
>> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
>> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>>  ifeq ($(CONFIG_COMMON_CLK), y)
>>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
>> new file mode 100644
>> index 0000000..e3ead46
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/Kconfig
>> @@ -0,0 +1,5 @@
>> +config COMMON_CLK_HI6220
>> +       tristate "Hi6220 Clock Driver"
>> +       depends on OF && ARCH_HISI
>> +       help
>> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
>> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
>> index 038c02f..bbf0539 100644
>> --- a/drivers/clk/hisilicon/Makefile
>> +++ b/drivers/clk/hisilicon/Makefile
>> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
>> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
>> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
>> new file mode 100644
>> index 0000000..01d0c46
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/clk-hi6220.c
>> @@ -0,0 +1,284 @@
>> +/*
>> + * Hisilicon Hi6220 clock driver
>> + *
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk.h>
>> +
>> +#include <dt-bindings/clock/hi6220-clock.h>
>> +
>> +#include "clk.h"
>> +
>> +
>> +/* clocks in AO (always on) controller */
>> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
>> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
>> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
>> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
>> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
>> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
>> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
>> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
>> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
>> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
>> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
>> +};
>> +
>> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
>> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
>> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
>> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
>> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
>> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
>> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
>> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
>> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
>> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
>> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
>> +};
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
>> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
>> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
>> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
>> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
>> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
>> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
>> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
>> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
>> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
>> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
>> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
>> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
>> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
>> +};
>> +
>> +static void __init hi6220_clk_ao_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
>> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
>> +
>> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
>> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
>> +
>> +
>> +/* clocks in sysctrl */
>> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
>> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
>> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
>> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
>> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
>> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
>> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
>> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
>> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
>> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
>> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
>> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
>> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
>> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
>> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
>> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
>> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
>> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
>> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
>> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
>> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
>> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
>> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
>> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
>> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
>> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
>> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
>> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
>> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
>> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
>> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
>> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
>> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
>> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
>> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
>> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
>> +};
>> +
>> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
>> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
>> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
>> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
>> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
>> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
>> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
>> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
>> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
>> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
>> +};
>> +
>> +static void __init hi6220_clk_sys_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
>> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
>> +
>> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
>> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
>> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
>> +
>> +
>> +/* clocks in media controller */
>> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
>> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
>> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
>> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
>> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
>> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
>> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
>> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
>> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
>> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
>> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
>> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
>> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
>> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
>> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
>> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
>> +};
>> +
>> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
>> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
>> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
>> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
>> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
>> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
>> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
>> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
>> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
>> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
>> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
>> +};
>> +
>> +static void __init hi6220_clk_media_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
>> +
>> +       hisi_clk_register_mux(hi6220_mux_clks_media,
>> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_media,
>> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
>> +
>> +
>> +/* clocks in pmctrl */
>> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
>> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
>> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
>> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
>> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
>> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
>> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
>> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
>> +};
>> +
>> +static void __init hi6220_clk_power_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate(hi6220_gate_clks_power,
>> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_power,
>> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
>> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
>> index a078e84..5d2305c 100644
>> --- a/drivers/clk/hisilicon/clk.c
>> +++ b/drivers/clk/hisilicon/clk.c
>> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>>                 data->clk_data.clks[clks[i].id] = clk;
>>         }
>>  }
>> +
>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
>> +                                         int nums, struct hisi_clock_data *data)
>> +{
>> +       struct clk *clk;
>> +       void __iomem *base = data->base;
>> +       int i;
>> +
>> +       for (i = 0; i < nums; i++) {
>> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
>> +                                               clks[i].parent_name,
>> +                                               clks[i].flags,
>> +                                               base + clks[i].offset,
>> +                                               clks[i].shift,
>> +                                               clks[i].width,
>> +                                               clks[i].mask_bit,
>> +                                               &hisi_clk_lock);
>> +               if (IS_ERR(clk)) {
>> +                       pr_err("%s: failed to register clock %s\n",
>> +                              __func__, clks[i].name);
>> +                       continue;
>> +               }
>> +
>> +               if (clks[i].alias)
>> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
>> +
>> +               data->clk_data.clks[clks[i].id] = clk;
>> +       }
>> +}
>> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
>> index 31083ff..462a570 100644
>> --- a/drivers/clk/hisilicon/clk.h
>> +++ b/drivers/clk/hisilicon/clk.h
>> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>>         const char              *alias;
>>  };
>>
>> +struct hi6220_divider_clock {
>> +       unsigned int            id;
>> +       const char              *name;
>> +       const char              *parent_name;
>> +       unsigned long           flags;
>> +       unsigned long           offset;
>> +       u8                      shift;
>> +       u8                      width;
>> +       u32                     mask_bit;
>> +       const char              *alias;
>> +};
>> +
>>  struct hisi_gate_clock {
>>         unsigned int            id;
>>         const char              *name;
>> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>>                                 const char *, unsigned long,
>>                                 void __iomem *, u8,
>>                                 u8, spinlock_t *);
>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>>
>>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
>> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>>                                         int, struct hisi_clock_data *);
>>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>>                                         int, struct hisi_clock_data *);
>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
>> +                                       int, struct hisi_clock_data *);
>>  #endif /* __HISI_CLK_H */
>> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
>> new file mode 100644
>> index 0000000..9e3825b
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
>> @@ -0,0 +1,273 @@
>> +/*
>> + * Hisilicon hi6220 SoC divider clock driver
>> + *
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/err.h>
>> +
>> +#define div_mask(width)        ((1 << (width)) - 1)
>> +
>> +/*
>> + * The reverse of DIV_ROUND_UP: The maximum number which
>> + * divided by m is r
>> + */
>> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
>> +
>> +/**
>> + * struct hi6220_clk_divider - divider clock for hi6220
>> + *
>> + * @hw:                handle between common and hardware-specific interfaces
>> + * @reg:       register containing divider
>> + * @shift:     shift to the divider bit field
>> + * @width:     width of the divider bit field
>> + * @mask:      mask for setting divider rate
>> + * @table:     the div table that the divider supports
>> + * @lock:      register lock
>> + */
>> +struct hi6220_clk_divider {
>> +       struct clk_hw   hw;
>> +       void __iomem    *reg;
>> +       u8              shift;
>> +       u8              width;
>> +       u32             mask;
>> +       const struct clk_div_table *table;
>> +       spinlock_t      *lock;
>> +};
>> +
>> +#define to_hi6220_clk_divider(_hw)     \
>> +       container_of(_hw, struct hi6220_clk_divider, hw)
>> +
>> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
>> +{
>> +       unsigned int maxdiv = 0;
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div > maxdiv)
>> +                       maxdiv = clkt->div;
>> +       return maxdiv;
>> +}
>> +
>> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
>> +                                       unsigned int val)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->val == val)
>> +                       return clkt->div;
>> +
>> +       return 0;
>> +}
>> +
>> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
>> +                                       unsigned int div)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div == div)
>> +                       return clkt->val;
>> +       return 0;
>> +}
>> +
>> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
>> +                                       unsigned long parent_rate)
>> +{
>> +       unsigned int div, val;
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +
>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>> +       val &= div_mask(dclk->width);
>> +
>> +       div = hi6220_get_table_div(dclk->table, val);
>> +       if (!div) {
>> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
>> +                          __clk_get_name(hw->clk));
>> +               return parent_rate;
>> +       }
>> +
>> +       return parent_rate / div;
>> +}
>> +
>> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
>> +                               unsigned int div)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div == div)
>> +                       return true;
>> +       return false;
>> +}
>> +
>> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
>> +                                unsigned long *best_parent_rate)
>> +{
>> +       unsigned int i, bestdiv = 0;
>> +       unsigned long parent_rate, best = 0, now, maxdiv;
>> +
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
>> +
>> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
>> +
>> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>> +               parent_rate = *best_parent_rate;
>> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
>> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
>> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
>> +               return bestdiv;
>> +       }
>> +
>> +       /*
>> +        * The maximum divider we can use without overflowing
>> +        * unsigned long in rate * i below
>> +        */
>> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
>> +
>> +       for (i = 1; i <= maxdiv; i++) {
>> +               if (!hi6220_is_valid_div(dclk->table, i))
>> +                       continue;
>> +               parent_rate = __clk_round_rate(clk_parent,
>> +                                       MULT_ROUND_UP(rate, i));
>> +               now = parent_rate / i;
>> +               if (now <= rate && now > best) {
>> +                       bestdiv = i;
>> +                       best = now;
>> +                       *best_parent_rate = parent_rate;
>> +               }
>> +       }
>> +
>> +       if (!bestdiv) {
>> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
>> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
>> +       }
>> +
>> +       return bestdiv;
>> +}
>> +
>> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>> +                                       unsigned long *prate)
>> +{
>> +       int div;
>> +
>> +       if (!rate)
>> +               rate = 1;
>> +
>> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
>> +
>> +       return *prate / div;
>> +}
>> +
>> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>> +                                       unsigned long parent_rate)
>> +{
>> +       unsigned int div, value;
>> +       unsigned long flags = 0;
>> +       u32 data;
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +
>> +       div = parent_rate / rate;
>> +
>> +       if (!hi6220_is_valid_div(dclk->table, div))
>> +               return -EINVAL;
>> +
>> +       value = hi6220_get_table_val(dclk->table, div);
>> +
>> +       if (value > div_mask(dclk->width))
>> +               value = div_mask(dclk->width);
>> +
>> +       if (dclk->lock)
>> +               spin_lock_irqsave(dclk->lock, flags);
>> +
>> +       data = readl_relaxed(dclk->reg);
>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>> +       data |= value << dclk->shift;
>> +       data |= dclk->mask;
>> +
>> +       writel_relaxed(data, dclk->reg);
>> +
>> +       if (dclk->lock)
>> +               spin_unlock_irqrestore(dclk->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static struct clk_ops hi6220_clkdiv_ops = {
>> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
>> +       .round_rate = hi6220_clkdiv_round_rate,
>> +       .set_rate = hi6220_clkdiv_set_rate,
>> +};
>> +
>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
>> +{
>> +       struct hi6220_clk_divider *div;
>> +       struct clk *clk;
>> +       struct clk_init_data init;
>> +       struct clk_div_table *table;
>> +       u32 max_div, min_div;
>> +       int i;
>> +
>> +       /* allocate the divider */
>> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
>> +       if (!div) {
>> +               pr_err("%s: could not allocate divider clk\n", __func__);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       /* Init the divider table */
>> +       max_div = div_mask(width) + 1;
>> +       min_div = 1;
>> +
>> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
>> +       if (!table) {
>> +               kfree(div);
>> +               pr_err("%s: failed to alloc divider table!\n", __func__);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       for (i = 0; i < max_div; i++) {
>> +               table[i].div = min_div + i;
>> +               table[i].val = table[i].div - 1;
>> +       }
>> +
>> +       init.name = name;
>> +       init.ops = &hi6220_clkdiv_ops;
>> +       init.flags = flags | CLK_IS_BASIC;
>> +       init.parent_names = parent_name ? &parent_name : NULL;
>> +       init.num_parents = parent_name ? 1 : 0;
>> +
>> +       /* struct hi6220_clk_divider assignments */
>> +       div->reg = reg;
>> +       div->shift = shift;
>> +       div->width = width;
>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>> +       div->lock = lock;
>> +       div->hw.init = &init;
>> +       div->table = table;
>> +
>> +       /* register the clock */
>> +       clk = clk_register(dev, &div->hw);
>> +
>> +       if (IS_ERR(clk)) {
>> +               kfree(table);
>> +               kfree(div);
>> +       }
>> +
>> +       return clk;
>> +}
>> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
>> new file mode 100644
>> index 0000000..05033e7
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/hi6220-clock.h
>> @@ -0,0 +1,172 @@
>> +/*
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
>> +#define __DT_BINDINGS_CLOCK_HI6220_H
>> +
>> +/* clk in AO (always on) controller */
>> +#define HI6220_NONE_CLOCK      0
>> +
>> +/* fixed rate clocks */
>> +#define HI6220_REF32K          1
>> +#define HI6220_CLK_TCXO                2
>> +#define HI6220_MMC1_PAD                3
>> +#define HI6220_MMC2_PAD                4
>> +#define HI6220_MMC0_PAD                5
>> +#define HI6220_PLL_BBP         6
>> +#define HI6220_PLL_GPU         7
>> +#define HI6220_PLL1_DDR                8
>> +#define HI6220_PLL_SYS         9
>> +#define HI6220_PLL_SYS_MEDIA   10
>> +#define HI6220_DDR_SRC         11
>> +#define HI6220_PLL_MEDIA       12
>> +#define HI6220_PLL_DDR         13
>> +
>> +/* fixed factor clocks */
>> +#define HI6220_300M            16
>> +#define HI6220_150M            17
>> +#define HI6220_PICOPHY_SRC     18
>> +#define HI6220_MMC0_SRC_SEL    19
>> +#define HI6220_MMC1_SRC_SEL    20
>> +#define HI6220_MMC2_SRC_SEL    21
>> +#define HI6220_VPU_CODEC       22
>> +#define HI6220_MMC0_SMP                23
>> +#define HI6220_MMC1_SMP                24
>> +#define HI6220_MMC2_SMP                25
>> +
>> +/* gate clocks */
>> +#define HI6220_WDT0_PCLK       28
>> +#define HI6220_WDT1_PCLK       29
>> +#define HI6220_WDT2_PCLK       30
>> +#define HI6220_TIMER0_PCLK     31
>> +#define HI6220_TIMER1_PCLK     32
>> +#define HI6220_TIMER2_PCLK     33
>> +#define HI6220_TIMER3_PCLK     34
>> +#define HI6220_TIMER4_PCLK     35
>> +#define HI6220_TIMER5_PCLK     36
>> +#define HI6220_TIMER6_PCLK     37
>> +#define HI6220_TIMER7_PCLK     38
>> +#define HI6220_TIMER8_PCLK     39
>> +#define HI6220_UART0_PCLK      40
>> +
>> +#define HI6220_AO_NR_CLKS      48
>> +
>> +/* clk in systrl */
>> +/* gate clock */
>> +#define HI6220_MMC0_CLK                1
>> +#define HI6220_MMC0_CIUCLK     2
>> +#define HI6220_MMC1_CLK                3
>> +#define HI6220_MMC1_CIUCLK     4
>> +#define HI6220_MMC2_CLK                5
>> +#define HI6220_MMC2_CIUCLK     6
>> +#define HI6220_USBOTG_HCLK     7
>> +#define HI6220_CLK_PICOPHY     8
>> +#define HI6220_HIFI            9
>> +#define HI6220_DACODEC_PCLK    10
>> +#define HI6220_EDMAC_ACLK      11
>> +#define HI6220_CS_ATB          12
>> +#define HI6220_I2C0_CLK                13
>> +#define HI6220_I2C1_CLK                14
>> +#define HI6220_I2C2_CLK                15
>> +#define HI6220_I2C3_CLK                16
>> +#define HI6220_UART1_PCLK      17
>> +#define HI6220_UART2_PCLK      18
>> +#define HI6220_UART3_PCLK      19
>> +#define HI6220_UART4_PCLK      20
>> +#define HI6220_SPI_CLK         21
>> +#define HI6220_MMU_CLK         22
>> +#define HI6220_HIFI_SEL                23
>> +#define HI6220_MMC0_SYSPLL     24
>> +#define HI6220_MMC1_SYSPLL     25
>> +#define HI6220_MMC2_SYSPLL     26
>> +#define HI6220_MMC0_SEL                27
>> +#define HI6220_MMC1_SEL                28
>> +#define HI6220_BBPPLL_SEL      29
>> +#define HI6220_MEDIA_PLL_SRC   30
>> +#define HI6220_MMC2_SEL                31
>> +#define HI6220_CS_ATB_SYSPLL   32
>> +
>> +/* mux clocks */
>> +#define HI6220_MMC0_SRC                35
>> +#define HI6220_MMC0_SMP_IN     36
>> +#define HI6220_MMC1_SRC                37
>> +#define HI6220_MMC1_SMP_IN     38
>> +#define HI6220_MMC2_SRC                39
>> +#define HI6220_MMC2_SMP_IN     40
>> +#define HI6220_HIFI_SRC                41
>> +#define HI6220_UART1_SRC       42
>> +#define HI6220_UART2_SRC       43
>> +#define HI6220_UART3_SRC       44
>> +#define HI6220_UART4_SRC       45
>> +#define HI6220_MMC0_MUX0       46
>> +#define HI6220_MMC1_MUX0       47
>> +#define HI6220_MMC2_MUX0       48
>> +#define HI6220_MMC0_MUX1       49
>> +#define HI6220_MMC1_MUX1       50
>> +#define HI6220_MMC2_MUX1       51
>> +
>> +/* divider clocks */
>> +#define HI6220_CLK_BUS         54
>> +#define HI6220_MMC0_DIV                55
>> +#define HI6220_MMC1_DIV                56
>> +#define HI6220_MMC2_DIV                57
>> +#define HI6220_HIFI_DIV                58
>> +#define HI6220_BBPPLL0_DIV     59
>> +#define HI6220_CS_DAPB         60
>> +#define HI6220_CS_ATB_DIV      61
>> +
>> +#define HI6220_SYS_NR_CLKS     64
>> +
>> +/* clk in media controller */
>> +/* gate clocks */
>> +#define HI6220_DSI_PCLK                1
>> +#define HI6220_G3D_PCLK                2
>> +#define HI6220_ACLK_CODEC_VPU  3
>> +#define HI6220_ISP_SCLK                4
>> +#define HI6220_ADE_CORE                5
>> +#define HI6220_MED_MMU         6
>> +#define HI6220_CFG_CSI4PHY     7
>> +#define HI6220_CFG_CSI2PHY     8
>> +#define HI6220_ISP_SCLK_GATE   9
>> +#define HI6220_ISP_SCLK_GATE1  10
>> +#define HI6220_ADE_CORE_GATE   11
>> +#define HI6220_CODEC_VPU_GATE  12
>> +#define HI6220_MED_SYSPLL      13
>> +
>> +/* mux clocks */
>> +#define HI6220_1440_1200       20
>> +#define HI6220_1000_1200       21
>> +#define HI6220_1000_1440       22
>> +
>> +/* divider clocks */
>> +#define HI6220_CODEC_JPEG      30
>> +#define HI6220_ISP_SCLK_SRC    31
>> +#define HI6220_ISP_SCLK1       32
>> +#define HI6220_ADE_CORE_SRC    33
>> +#define HI6220_ADE_PIX_SRC     34
>> +#define HI6220_G3D_CLK         35
>> +#define HI6220_CODEC_VPU_SRC   36
>> +
>> +#define HI6220_MEDIA_NR_CLKS   40
>> +
>> +/* clk in power controller */
>> +/* gate clocks */
>> +#define HI6220_PLL_GPU_GATE    1
>> +#define HI6220_PLL1_DDR_GATE   2
>> +#define HI6220_PLL_DDR_GATE    3
>> +#define HI6220_PLL_MEDIA_GATE  4
>> +#define HI6220_PLL0_BBP_GATE   5
>> +
>> +/* divider clocks */
>> +#define HI6220_DDRC_SRC                10
>> +#define HI6220_DDRC_AXI1       11
>> +
>> +#define HI6220_POWER_NR_CLKS   16
>> +#endif
>> --
>> 1.7.9.5
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> Cheers,
>
> - Tyler
>
> [1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!
--
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 related	[flat|nested] 85+ messages in thread

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-07  2:05       ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-07  2:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Tyler,

Thank you very much for helping test this patchset!

2015-02-07 2:10 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
> Hi Bintian,
>
> This patch applied to next-20150204 is producing build failures on
> various ARM defconfigs[1]. I received the following error in all
> cases:
>
> drivers/built-in.o: In function `hi6220_clk_register_divider':
> :(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
> Makefile:925: recipe for target 'vmlinux' failed
> make: *** [vmlinux] Error 1
It's my fault, I just test on ARM64, The following patch can fix this error:
=====================
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index bbf0539..48f0116 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,9 +2,9 @@
 # Hisilicon Clock specific Makefile
 #

-obj-y  += clk.o clkgate-separated.o
+obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o

 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
-obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
+obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
======================

I will fix this problem in next version.

Thanks,

Bintian


>
> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>> registers to supply different clocks to different IPs in the SoC.
>>
>> We add one divider clock for hi6220 because the divider in hi6220
>> also has a mask bit but it doesnot obey the rule defined by flag
>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>> to handle it.
>>
>> This patch also enables this clock driver for ARCH_HISI and document
>> devicetree bindings.
>>
>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> ---
>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>  arch/arm64/Kconfig                                 |    1 +
>>  drivers/clk/Kconfig                                |    2 +
>>  drivers/clk/Makefile                               |    4 +-
>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> new file mode 100644
>> index 0000000..a3ddda1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>> @@ -0,0 +1,30 @@
>> +* Hisilicon Hi6220 Clock Controller
>> +
>> +The hi6220 clock controller generates and supplies clock to various
>> +controllers within the hi6220 SoC.
>> +
>> +Required Properties:
>> +
>> +- compatible: should be one of the following:
>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>> +     power always on(AO) domain, it is the sub node of SoC power AO
>> +     controller in dts file.
>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>> +     system control domain, it is the sub node of SoC system controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>> +     SoC media control domain, it is the sub node of SoC media controller
>> +     in dts file.
>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>> +     SoC power control domain, it is the sub node of SoC power controller
>> +     in dts file.
>> +
>> +- reg: physical base address of the controller and length of memory mapped
>> +  region.
>> +
>> +- #clock-cells: should be 1.
>> +
>> +Each clock is assigned an identifier and client nodes use this identifier
>> +to specify the clock which they consume.
>> +
>> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 78cd41c8..6efc3e3 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -175,6 +175,7 @@ config ARCH_XGENE
>>
>>  config ARCH_HISI
>>         bool "Hisilicon SoC Family"
>> +       select COMMON_CLK_HI6220
>>         help
>>           This enables support for Hisilicon ARMv8 Family of SoCs.
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index 3f44f29..b52c95c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>>
>>  source "drivers/clk/qcom/Kconfig"
>>
>> +source "drivers/clk/hisilicon/Kconfig"
>> +
>>  endmenu
>>
>>  source "drivers/clk/bcm/Kconfig"
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index d5fba5b..c58703b 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
>> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
>> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>>  ifeq ($(CONFIG_COMMON_CLK), y)
>>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
>> new file mode 100644
>> index 0000000..e3ead46
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/Kconfig
>> @@ -0,0 +1,5 @@
>> +config COMMON_CLK_HI6220
>> +       tristate "Hi6220 Clock Driver"
>> +       depends on OF && ARCH_HISI
>> +       help
>> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
>> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
>> index 038c02f..bbf0539 100644
>> --- a/drivers/clk/hisilicon/Makefile
>> +++ b/drivers/clk/hisilicon/Makefile
>> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
>> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
>> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
>> new file mode 100644
>> index 0000000..01d0c46
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/clk-hi6220.c
>> @@ -0,0 +1,284 @@
>> +/*
>> + * Hisilicon Hi6220 clock driver
>> + *
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk.h>
>> +
>> +#include <dt-bindings/clock/hi6220-clock.h>
>> +
>> +#include "clk.h"
>> +
>> +
>> +/* clocks in AO (always on) controller */
>> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
>> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
>> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
>> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
>> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
>> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
>> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
>> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
>> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
>> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
>> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
>> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
>> +};
>> +
>> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
>> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
>> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
>> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
>> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
>> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
>> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
>> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
>> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
>> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
>> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
>> +};
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
>> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
>> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
>> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
>> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
>> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
>> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
>> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
>> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
>> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
>> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
>> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
>> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
>> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
>> +};
>> +
>> +static void __init hi6220_clk_ao_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
>> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
>> +
>> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
>> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
>> +
>> +
>> +/* clocks in sysctrl */
>> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
>> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
>> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
>> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
>> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
>> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
>> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
>> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
>> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
>> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
>> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
>> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
>> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
>> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
>> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
>> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
>> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
>> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
>> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
>> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
>> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
>> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
>> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
>> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
>> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
>> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
>> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
>> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
>> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
>> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
>> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
>> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
>> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
>> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
>> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
>> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
>> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
>> +};
>> +
>> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
>> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
>> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
>> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
>> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
>> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
>> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
>> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
>> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
>> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
>> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
>> +};
>> +
>> +static void __init hi6220_clk_sys_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
>> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
>> +
>> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
>> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
>> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
>> +
>> +
>> +/* clocks in media controller */
>> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
>> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
>> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
>> +
>> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
>> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
>> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
>> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
>> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
>> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
>> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
>> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
>> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
>> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
>> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
>> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
>> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
>> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
>> +};
>> +
>> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
>> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
>> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
>> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
>> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
>> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
>> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
>> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
>> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
>> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
>> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
>> +};
>> +
>> +static void __init hi6220_clk_media_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
>> +
>> +       hisi_clk_register_mux(hi6220_mux_clks_media,
>> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_media,
>> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
>> +
>> +
>> +/* clocks in pmctrl */
>> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
>> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
>> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
>> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
>> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
>> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
>> +};
>> +
>> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
>> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
>> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
>> +};
>> +
>> +static void __init hi6220_clk_power_init(struct device_node *np)
>> +{
>> +       struct hisi_clock_data *clk_data;
>> +
>> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       hisi_clk_register_gate(hi6220_gate_clks_power,
>> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
>> +
>> +       hi6220_clk_register_divider(hi6220_div_clks_power,
>> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
>> +}
>> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
>> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
>> index a078e84..5d2305c 100644
>> --- a/drivers/clk/hisilicon/clk.c
>> +++ b/drivers/clk/hisilicon/clk.c
>> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>>                 data->clk_data.clks[clks[i].id] = clk;
>>         }
>>  }
>> +
>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
>> +                                         int nums, struct hisi_clock_data *data)
>> +{
>> +       struct clk *clk;
>> +       void __iomem *base = data->base;
>> +       int i;
>> +
>> +       for (i = 0; i < nums; i++) {
>> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
>> +                                               clks[i].parent_name,
>> +                                               clks[i].flags,
>> +                                               base + clks[i].offset,
>> +                                               clks[i].shift,
>> +                                               clks[i].width,
>> +                                               clks[i].mask_bit,
>> +                                               &hisi_clk_lock);
>> +               if (IS_ERR(clk)) {
>> +                       pr_err("%s: failed to register clock %s\n",
>> +                              __func__, clks[i].name);
>> +                       continue;
>> +               }
>> +
>> +               if (clks[i].alias)
>> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
>> +
>> +               data->clk_data.clks[clks[i].id] = clk;
>> +       }
>> +}
>> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
>> index 31083ff..462a570 100644
>> --- a/drivers/clk/hisilicon/clk.h
>> +++ b/drivers/clk/hisilicon/clk.h
>> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>>         const char              *alias;
>>  };
>>
>> +struct hi6220_divider_clock {
>> +       unsigned int            id;
>> +       const char              *name;
>> +       const char              *parent_name;
>> +       unsigned long           flags;
>> +       unsigned long           offset;
>> +       u8                      shift;
>> +       u8                      width;
>> +       u32                     mask_bit;
>> +       const char              *alias;
>> +};
>> +
>>  struct hisi_gate_clock {
>>         unsigned int            id;
>>         const char              *name;
>> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>>                                 const char *, unsigned long,
>>                                 void __iomem *, u8,
>>                                 u8, spinlock_t *);
>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>>
>>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
>> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>>                                         int, struct hisi_clock_data *);
>>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>>                                         int, struct hisi_clock_data *);
>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
>> +                                       int, struct hisi_clock_data *);
>>  #endif /* __HISI_CLK_H */
>> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
>> new file mode 100644
>> index 0000000..9e3825b
>> --- /dev/null
>> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
>> @@ -0,0 +1,273 @@
>> +/*
>> + * Hisilicon hi6220 SoC divider clock driver
>> + *
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/err.h>
>> +
>> +#define div_mask(width)        ((1 << (width)) - 1)
>> +
>> +/*
>> + * The reverse of DIV_ROUND_UP: The maximum number which
>> + * divided by m is r
>> + */
>> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
>> +
>> +/**
>> + * struct hi6220_clk_divider - divider clock for hi6220
>> + *
>> + * @hw:                handle between common and hardware-specific interfaces
>> + * @reg:       register containing divider
>> + * @shift:     shift to the divider bit field
>> + * @width:     width of the divider bit field
>> + * @mask:      mask for setting divider rate
>> + * @table:     the div table that the divider supports
>> + * @lock:      register lock
>> + */
>> +struct hi6220_clk_divider {
>> +       struct clk_hw   hw;
>> +       void __iomem    *reg;
>> +       u8              shift;
>> +       u8              width;
>> +       u32             mask;
>> +       const struct clk_div_table *table;
>> +       spinlock_t      *lock;
>> +};
>> +
>> +#define to_hi6220_clk_divider(_hw)     \
>> +       container_of(_hw, struct hi6220_clk_divider, hw)
>> +
>> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
>> +{
>> +       unsigned int maxdiv = 0;
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div > maxdiv)
>> +                       maxdiv = clkt->div;
>> +       return maxdiv;
>> +}
>> +
>> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
>> +                                       unsigned int val)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->val == val)
>> +                       return clkt->div;
>> +
>> +       return 0;
>> +}
>> +
>> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
>> +                                       unsigned int div)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div == div)
>> +                       return clkt->val;
>> +       return 0;
>> +}
>> +
>> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
>> +                                       unsigned long parent_rate)
>> +{
>> +       unsigned int div, val;
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +
>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>> +       val &= div_mask(dclk->width);
>> +
>> +       div = hi6220_get_table_div(dclk->table, val);
>> +       if (!div) {
>> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
>> +                          __clk_get_name(hw->clk));
>> +               return parent_rate;
>> +       }
>> +
>> +       return parent_rate / div;
>> +}
>> +
>> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
>> +                               unsigned int div)
>> +{
>> +       const struct clk_div_table *clkt;
>> +
>> +       for (clkt = table; clkt->div; clkt++)
>> +               if (clkt->div == div)
>> +                       return true;
>> +       return false;
>> +}
>> +
>> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
>> +                                unsigned long *best_parent_rate)
>> +{
>> +       unsigned int i, bestdiv = 0;
>> +       unsigned long parent_rate, best = 0, now, maxdiv;
>> +
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
>> +
>> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
>> +
>> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>> +               parent_rate = *best_parent_rate;
>> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
>> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
>> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
>> +               return bestdiv;
>> +       }
>> +
>> +       /*
>> +        * The maximum divider we can use without overflowing
>> +        * unsigned long in rate * i below
>> +        */
>> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
>> +
>> +       for (i = 1; i <= maxdiv; i++) {
>> +               if (!hi6220_is_valid_div(dclk->table, i))
>> +                       continue;
>> +               parent_rate = __clk_round_rate(clk_parent,
>> +                                       MULT_ROUND_UP(rate, i));
>> +               now = parent_rate / i;
>> +               if (now <= rate && now > best) {
>> +                       bestdiv = i;
>> +                       best = now;
>> +                       *best_parent_rate = parent_rate;
>> +               }
>> +       }
>> +
>> +       if (!bestdiv) {
>> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
>> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
>> +       }
>> +
>> +       return bestdiv;
>> +}
>> +
>> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>> +                                       unsigned long *prate)
>> +{
>> +       int div;
>> +
>> +       if (!rate)
>> +               rate = 1;
>> +
>> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
>> +
>> +       return *prate / div;
>> +}
>> +
>> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>> +                                       unsigned long parent_rate)
>> +{
>> +       unsigned int div, value;
>> +       unsigned long flags = 0;
>> +       u32 data;
>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>> +
>> +       div = parent_rate / rate;
>> +
>> +       if (!hi6220_is_valid_div(dclk->table, div))
>> +               return -EINVAL;
>> +
>> +       value = hi6220_get_table_val(dclk->table, div);
>> +
>> +       if (value > div_mask(dclk->width))
>> +               value = div_mask(dclk->width);
>> +
>> +       if (dclk->lock)
>> +               spin_lock_irqsave(dclk->lock, flags);
>> +
>> +       data = readl_relaxed(dclk->reg);
>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>> +       data |= value << dclk->shift;
>> +       data |= dclk->mask;
>> +
>> +       writel_relaxed(data, dclk->reg);
>> +
>> +       if (dclk->lock)
>> +               spin_unlock_irqrestore(dclk->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static struct clk_ops hi6220_clkdiv_ops = {
>> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
>> +       .round_rate = hi6220_clkdiv_round_rate,
>> +       .set_rate = hi6220_clkdiv_set_rate,
>> +};
>> +
>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
>> +{
>> +       struct hi6220_clk_divider *div;
>> +       struct clk *clk;
>> +       struct clk_init_data init;
>> +       struct clk_div_table *table;
>> +       u32 max_div, min_div;
>> +       int i;
>> +
>> +       /* allocate the divider */
>> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
>> +       if (!div) {
>> +               pr_err("%s: could not allocate divider clk\n", __func__);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       /* Init the divider table */
>> +       max_div = div_mask(width) + 1;
>> +       min_div = 1;
>> +
>> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
>> +       if (!table) {
>> +               kfree(div);
>> +               pr_err("%s: failed to alloc divider table!\n", __func__);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       for (i = 0; i < max_div; i++) {
>> +               table[i].div = min_div + i;
>> +               table[i].val = table[i].div - 1;
>> +       }
>> +
>> +       init.name = name;
>> +       init.ops = &hi6220_clkdiv_ops;
>> +       init.flags = flags | CLK_IS_BASIC;
>> +       init.parent_names = parent_name ? &parent_name : NULL;
>> +       init.num_parents = parent_name ? 1 : 0;
>> +
>> +       /* struct hi6220_clk_divider assignments */
>> +       div->reg = reg;
>> +       div->shift = shift;
>> +       div->width = width;
>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>> +       div->lock = lock;
>> +       div->hw.init = &init;
>> +       div->table = table;
>> +
>> +       /* register the clock */
>> +       clk = clk_register(dev, &div->hw);
>> +
>> +       if (IS_ERR(clk)) {
>> +               kfree(table);
>> +               kfree(div);
>> +       }
>> +
>> +       return clk;
>> +}
>> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
>> new file mode 100644
>> index 0000000..05033e7
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/hi6220-clock.h
>> @@ -0,0 +1,172 @@
>> +/*
>> + * Copyright (c) 2015 Hisilicon Limited.
>> + *
>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
>> +#define __DT_BINDINGS_CLOCK_HI6220_H
>> +
>> +/* clk in AO (always on) controller */
>> +#define HI6220_NONE_CLOCK      0
>> +
>> +/* fixed rate clocks */
>> +#define HI6220_REF32K          1
>> +#define HI6220_CLK_TCXO                2
>> +#define HI6220_MMC1_PAD                3
>> +#define HI6220_MMC2_PAD                4
>> +#define HI6220_MMC0_PAD                5
>> +#define HI6220_PLL_BBP         6
>> +#define HI6220_PLL_GPU         7
>> +#define HI6220_PLL1_DDR                8
>> +#define HI6220_PLL_SYS         9
>> +#define HI6220_PLL_SYS_MEDIA   10
>> +#define HI6220_DDR_SRC         11
>> +#define HI6220_PLL_MEDIA       12
>> +#define HI6220_PLL_DDR         13
>> +
>> +/* fixed factor clocks */
>> +#define HI6220_300M            16
>> +#define HI6220_150M            17
>> +#define HI6220_PICOPHY_SRC     18
>> +#define HI6220_MMC0_SRC_SEL    19
>> +#define HI6220_MMC1_SRC_SEL    20
>> +#define HI6220_MMC2_SRC_SEL    21
>> +#define HI6220_VPU_CODEC       22
>> +#define HI6220_MMC0_SMP                23
>> +#define HI6220_MMC1_SMP                24
>> +#define HI6220_MMC2_SMP                25
>> +
>> +/* gate clocks */
>> +#define HI6220_WDT0_PCLK       28
>> +#define HI6220_WDT1_PCLK       29
>> +#define HI6220_WDT2_PCLK       30
>> +#define HI6220_TIMER0_PCLK     31
>> +#define HI6220_TIMER1_PCLK     32
>> +#define HI6220_TIMER2_PCLK     33
>> +#define HI6220_TIMER3_PCLK     34
>> +#define HI6220_TIMER4_PCLK     35
>> +#define HI6220_TIMER5_PCLK     36
>> +#define HI6220_TIMER6_PCLK     37
>> +#define HI6220_TIMER7_PCLK     38
>> +#define HI6220_TIMER8_PCLK     39
>> +#define HI6220_UART0_PCLK      40
>> +
>> +#define HI6220_AO_NR_CLKS      48
>> +
>> +/* clk in systrl */
>> +/* gate clock */
>> +#define HI6220_MMC0_CLK                1
>> +#define HI6220_MMC0_CIUCLK     2
>> +#define HI6220_MMC1_CLK                3
>> +#define HI6220_MMC1_CIUCLK     4
>> +#define HI6220_MMC2_CLK                5
>> +#define HI6220_MMC2_CIUCLK     6
>> +#define HI6220_USBOTG_HCLK     7
>> +#define HI6220_CLK_PICOPHY     8
>> +#define HI6220_HIFI            9
>> +#define HI6220_DACODEC_PCLK    10
>> +#define HI6220_EDMAC_ACLK      11
>> +#define HI6220_CS_ATB          12
>> +#define HI6220_I2C0_CLK                13
>> +#define HI6220_I2C1_CLK                14
>> +#define HI6220_I2C2_CLK                15
>> +#define HI6220_I2C3_CLK                16
>> +#define HI6220_UART1_PCLK      17
>> +#define HI6220_UART2_PCLK      18
>> +#define HI6220_UART3_PCLK      19
>> +#define HI6220_UART4_PCLK      20
>> +#define HI6220_SPI_CLK         21
>> +#define HI6220_MMU_CLK         22
>> +#define HI6220_HIFI_SEL                23
>> +#define HI6220_MMC0_SYSPLL     24
>> +#define HI6220_MMC1_SYSPLL     25
>> +#define HI6220_MMC2_SYSPLL     26
>> +#define HI6220_MMC0_SEL                27
>> +#define HI6220_MMC1_SEL                28
>> +#define HI6220_BBPPLL_SEL      29
>> +#define HI6220_MEDIA_PLL_SRC   30
>> +#define HI6220_MMC2_SEL                31
>> +#define HI6220_CS_ATB_SYSPLL   32
>> +
>> +/* mux clocks */
>> +#define HI6220_MMC0_SRC                35
>> +#define HI6220_MMC0_SMP_IN     36
>> +#define HI6220_MMC1_SRC                37
>> +#define HI6220_MMC1_SMP_IN     38
>> +#define HI6220_MMC2_SRC                39
>> +#define HI6220_MMC2_SMP_IN     40
>> +#define HI6220_HIFI_SRC                41
>> +#define HI6220_UART1_SRC       42
>> +#define HI6220_UART2_SRC       43
>> +#define HI6220_UART3_SRC       44
>> +#define HI6220_UART4_SRC       45
>> +#define HI6220_MMC0_MUX0       46
>> +#define HI6220_MMC1_MUX0       47
>> +#define HI6220_MMC2_MUX0       48
>> +#define HI6220_MMC0_MUX1       49
>> +#define HI6220_MMC1_MUX1       50
>> +#define HI6220_MMC2_MUX1       51
>> +
>> +/* divider clocks */
>> +#define HI6220_CLK_BUS         54
>> +#define HI6220_MMC0_DIV                55
>> +#define HI6220_MMC1_DIV                56
>> +#define HI6220_MMC2_DIV                57
>> +#define HI6220_HIFI_DIV                58
>> +#define HI6220_BBPPLL0_DIV     59
>> +#define HI6220_CS_DAPB         60
>> +#define HI6220_CS_ATB_DIV      61
>> +
>> +#define HI6220_SYS_NR_CLKS     64
>> +
>> +/* clk in media controller */
>> +/* gate clocks */
>> +#define HI6220_DSI_PCLK                1
>> +#define HI6220_G3D_PCLK                2
>> +#define HI6220_ACLK_CODEC_VPU  3
>> +#define HI6220_ISP_SCLK                4
>> +#define HI6220_ADE_CORE                5
>> +#define HI6220_MED_MMU         6
>> +#define HI6220_CFG_CSI4PHY     7
>> +#define HI6220_CFG_CSI2PHY     8
>> +#define HI6220_ISP_SCLK_GATE   9
>> +#define HI6220_ISP_SCLK_GATE1  10
>> +#define HI6220_ADE_CORE_GATE   11
>> +#define HI6220_CODEC_VPU_GATE  12
>> +#define HI6220_MED_SYSPLL      13
>> +
>> +/* mux clocks */
>> +#define HI6220_1440_1200       20
>> +#define HI6220_1000_1200       21
>> +#define HI6220_1000_1440       22
>> +
>> +/* divider clocks */
>> +#define HI6220_CODEC_JPEG      30
>> +#define HI6220_ISP_SCLK_SRC    31
>> +#define HI6220_ISP_SCLK1       32
>> +#define HI6220_ADE_CORE_SRC    33
>> +#define HI6220_ADE_PIX_SRC     34
>> +#define HI6220_G3D_CLK         35
>> +#define HI6220_CODEC_VPU_SRC   36
>> +
>> +#define HI6220_MEDIA_NR_CLKS   40
>> +
>> +/* clk in power controller */
>> +/* gate clocks */
>> +#define HI6220_PLL_GPU_GATE    1
>> +#define HI6220_PLL1_DDR_GATE   2
>> +#define HI6220_PLL_DDR_GATE    3
>> +#define HI6220_PLL_MEDIA_GATE  4
>> +#define HI6220_PLL0_BBP_GATE   5
>> +
>> +/* divider clocks */
>> +#define HI6220_DDRC_SRC                10
>> +#define HI6220_DDRC_AXI1       11
>> +
>> +#define HI6220_POWER_NR_CLKS   16
>> +#endif
>> --
>> 1.7.9.5
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> Cheers,
>
> - Tyler
>
> [1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
  2015-02-07  2:05       ` Brent Wang
  (?)
@ 2015-02-07 22:05         ` Tyler Baker
  -1 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-07 22:05 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, Rob Herring, Paweł Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Olof Johansson, Haifeng Yan, Stephen Boyd,
	xuejiancheng, sledge.yanwei, Tomeu Vizoso,
	Russell King - ARM Linux, Guodong Xu, dan.zhao, huxinwei,
	xuyiping, victor.lixin, btw, puck.chen, wangbinghui,
	zhenwei.wang, Liguozhu (Kenneth),
	XinWei Kong, heyunlei, w.f, z.liuxinliang

Hi Bintian,

On 7 February 2015 at 10:05, Brent Wang <wangbintian@gmail.com> wrote:
> Hello Tyler,
>
> Thank you very much for helping test this patchset!

Not a problem.

>
> 2015-02-07 2:10 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
>> Hi Bintian,
>>
>> This patch applied to next-20150204 is producing build failures on
>> various ARM defconfigs[1]. I received the following error in all
>> cases:
>>
>> drivers/built-in.o: In function `hi6220_clk_register_divider':
>> :(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
>> Makefile:925: recipe for target 'vmlinux' failed
>> make: *** [vmlinux] Error 1
> It's my fault, I just test on ARM64, The following patch can fix this error:
> =====================
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index bbf0539..48f0116 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -2,9 +2,9 @@
>  # Hisilicon Clock specific Makefile
>  #
>
> -obj-y  += clk.o clkgate-separated.o
> +obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o
>
>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
> -obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
> ======================
>
> I will fix this problem in next version.

Great, thank you. I quickly tested your change above, and it gets the
ARM defconfigs building again.

>
> Thanks,
>
> Bintian
>
>
>>
>> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>>> registers to supply different clocks to different IPs in the SoC.
>>>
>>> We add one divider clock for hi6220 because the divider in hi6220
>>> also has a mask bit but it doesnot obey the rule defined by flag
>>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>>> to handle it.
>>>
>>> This patch also enables this clock driver for ARCH_HISI and document
>>> devicetree bindings.
>>>
>>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> ---
>>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>>  arch/arm64/Kconfig                                 |    1 +
>>>  drivers/clk/Kconfig                                |    2 +
>>>  drivers/clk/Makefile                               |    4 +-
>>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>>
>>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>> new file mode 100644
>>> index 0000000..a3ddda1
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>> @@ -0,0 +1,30 @@
>>> +* Hisilicon Hi6220 Clock Controller
>>> +
>>> +The hi6220 clock controller generates and supplies clock to various
>>> +controllers within the hi6220 SoC.
>>> +
>>> +Required Properties:
>>> +
>>> +- compatible: should be one of the following:
>>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>>> +     power always on(AO) domain, it is the sub node of SoC power AO
>>> +     controller in dts file.
>>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>>> +     system control domain, it is the sub node of SoC system controller
>>> +     in dts file.
>>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>>> +     SoC media control domain, it is the sub node of SoC media controller
>>> +     in dts file.
>>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>>> +     SoC power control domain, it is the sub node of SoC power controller
>>> +     in dts file.
>>> +
>>> +- reg: physical base address of the controller and length of memory mapped
>>> +  region.
>>> +
>>> +- #clock-cells: should be 1.
>>> +
>>> +Each clock is assigned an identifier and client nodes use this identifier
>>> +to specify the clock which they consume.
>>> +
>>> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 78cd41c8..6efc3e3 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -175,6 +175,7 @@ config ARCH_XGENE
>>>
>>>  config ARCH_HISI
>>>         bool "Hisilicon SoC Family"
>>> +       select COMMON_CLK_HI6220
>>>         help
>>>           This enables support for Hisilicon ARMv8 Family of SoCs.
>>>
>>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>>> index 3f44f29..b52c95c 100644
>>> --- a/drivers/clk/Kconfig
>>> +++ b/drivers/clk/Kconfig
>>> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>>>
>>>  source "drivers/clk/qcom/Kconfig"
>>>
>>> +source "drivers/clk/hisilicon/Kconfig"
>>> +
>>>  endmenu
>>>
>>>  source "drivers/clk/bcm/Kconfig"
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index d5fba5b..c58703b 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>>>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>>>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>>>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
>>> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
>>> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>>> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>>> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>>>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>>>  ifeq ($(CONFIG_COMMON_CLK), y)
>>>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>>> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
>>> new file mode 100644
>>> index 0000000..e3ead46
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/Kconfig
>>> @@ -0,0 +1,5 @@
>>> +config COMMON_CLK_HI6220
>>> +       tristate "Hi6220 Clock Driver"
>>> +       depends on OF && ARCH_HISI
>>> +       help
>>> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
>>> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
>>> index 038c02f..bbf0539 100644
>>> --- a/drivers/clk/hisilicon/Makefile
>>> +++ b/drivers/clk/hisilicon/Makefile
>>> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>>>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>>>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>>>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
>>> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
>>> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
>>> new file mode 100644
>>> index 0000000..01d0c46
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/clk-hi6220.c
>>> @@ -0,0 +1,284 @@
>>> +/*
>>> + * Hisilicon Hi6220 clock driver
>>> + *
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/clkdev.h>
>>> +#include <linux/io.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/clk.h>
>>> +
>>> +#include <dt-bindings/clock/hi6220-clock.h>
>>> +
>>> +#include "clk.h"
>>> +
>>> +
>>> +/* clocks in AO (always on) controller */
>>> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
>>> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
>>> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
>>> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
>>> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
>>> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
>>> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
>>> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
>>> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
>>> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
>>> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
>>> +};
>>> +
>>> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
>>> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
>>> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
>>> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
>>> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
>>> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
>>> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
>>> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
>>> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
>>> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
>>> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
>>> +};
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
>>> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
>>> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
>>> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
>>> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
>>> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
>>> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
>>> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
>>> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
>>> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
>>> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
>>> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
>>> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
>>> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_ao_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
>>> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
>>> +
>>> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
>>> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
>>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
>>> +
>>> +
>>> +/* clocks in sysctrl */
>>> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
>>> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
>>> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
>>> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
>>> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
>>> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
>>> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
>>> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
>>> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
>>> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
>>> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>>> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>>> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>>> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>>> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>>> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>>> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
>>> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
>>> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
>>> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
>>> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
>>> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
>>> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
>>> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
>>> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
>>> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
>>> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
>>> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
>>> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
>>> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
>>> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
>>> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
>>> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
>>> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
>>> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
>>> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
>>> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
>>> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
>>> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
>>> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
>>> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
>>> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
>>> +};
>>> +
>>> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
>>> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>>> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>>> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>>> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>>> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>>> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>>> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
>>> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
>>> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
>>> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
>>> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
>>> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
>>> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
>>> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
>>> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_sys_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
>>> +
>>> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
>>> +
>>> +
>>> +/* clocks in media controller */
>>> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
>>> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
>>> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
>>> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
>>> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
>>> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
>>> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
>>> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
>>> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
>>> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
>>> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
>>> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
>>> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
>>> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
>>> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
>>> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
>>> +};
>>> +
>>> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
>>> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
>>> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
>>> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
>>> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
>>> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
>>> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
>>> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
>>> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
>>> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
>>> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_media_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
>>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
>>> +
>>> +       hisi_clk_register_mux(hi6220_mux_clks_media,
>>> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_media,
>>> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
>>> +
>>> +
>>> +/* clocks in pmctrl */
>>> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
>>> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
>>> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
>>> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
>>> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
>>> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
>>> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
>>> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_power_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate(hi6220_gate_clks_power,
>>> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_power,
>>> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
>>> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
>>> index a078e84..5d2305c 100644
>>> --- a/drivers/clk/hisilicon/clk.c
>>> +++ b/drivers/clk/hisilicon/clk.c
>>> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>>>                 data->clk_data.clks[clks[i].id] = clk;
>>>         }
>>>  }
>>> +
>>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
>>> +                                         int nums, struct hisi_clock_data *data)
>>> +{
>>> +       struct clk *clk;
>>> +       void __iomem *base = data->base;
>>> +       int i;
>>> +
>>> +       for (i = 0; i < nums; i++) {
>>> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
>>> +                                               clks[i].parent_name,
>>> +                                               clks[i].flags,
>>> +                                               base + clks[i].offset,
>>> +                                               clks[i].shift,
>>> +                                               clks[i].width,
>>> +                                               clks[i].mask_bit,
>>> +                                               &hisi_clk_lock);
>>> +               if (IS_ERR(clk)) {
>>> +                       pr_err("%s: failed to register clock %s\n",
>>> +                              __func__, clks[i].name);
>>> +                       continue;
>>> +               }
>>> +
>>> +               if (clks[i].alias)
>>> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
>>> +
>>> +               data->clk_data.clks[clks[i].id] = clk;
>>> +       }
>>> +}
>>> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
>>> index 31083ff..462a570 100644
>>> --- a/drivers/clk/hisilicon/clk.h
>>> +++ b/drivers/clk/hisilicon/clk.h
>>> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>>>         const char              *alias;
>>>  };
>>>
>>> +struct hi6220_divider_clock {
>>> +       unsigned int            id;
>>> +       const char              *name;
>>> +       const char              *parent_name;
>>> +       unsigned long           flags;
>>> +       unsigned long           offset;
>>> +       u8                      shift;
>>> +       u8                      width;
>>> +       u32                     mask_bit;
>>> +       const char              *alias;
>>> +};
>>> +
>>>  struct hisi_gate_clock {
>>>         unsigned int            id;
>>>         const char              *name;
>>> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>>>                                 const char *, unsigned long,
>>>                                 void __iomem *, u8,
>>>                                 u8, spinlock_t *);
>>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>>>
>>>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>>>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
>>> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>>>                                         int, struct hisi_clock_data *);
>>>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>>>                                         int, struct hisi_clock_data *);
>>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
>>> +                                       int, struct hisi_clock_data *);
>>>  #endif /* __HISI_CLK_H */
>>> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
>>> new file mode 100644
>>> index 0000000..9e3825b
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
>>> @@ -0,0 +1,273 @@
>>> +/*
>>> + * Hisilicon hi6220 SoC divider clock driver
>>> + *
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + */
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/io.h>
>>> +#include <linux/err.h>
>>> +
>>> +#define div_mask(width)        ((1 << (width)) - 1)
>>> +
>>> +/*
>>> + * The reverse of DIV_ROUND_UP: The maximum number which
>>> + * divided by m is r
>>> + */
>>> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
>>> +
>>> +/**
>>> + * struct hi6220_clk_divider - divider clock for hi6220
>>> + *
>>> + * @hw:                handle between common and hardware-specific interfaces
>>> + * @reg:       register containing divider
>>> + * @shift:     shift to the divider bit field
>>> + * @width:     width of the divider bit field
>>> + * @mask:      mask for setting divider rate
>>> + * @table:     the div table that the divider supports
>>> + * @lock:      register lock
>>> + */
>>> +struct hi6220_clk_divider {
>>> +       struct clk_hw   hw;
>>> +       void __iomem    *reg;
>>> +       u8              shift;
>>> +       u8              width;
>>> +       u32             mask;
>>> +       const struct clk_div_table *table;
>>> +       spinlock_t      *lock;
>>> +};
>>> +
>>> +#define to_hi6220_clk_divider(_hw)     \
>>> +       container_of(_hw, struct hi6220_clk_divider, hw)
>>> +
>>> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
>>> +{
>>> +       unsigned int maxdiv = 0;
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div > maxdiv)
>>> +                       maxdiv = clkt->div;
>>> +       return maxdiv;
>>> +}
>>> +
>>> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
>>> +                                       unsigned int val)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->val == val)
>>> +                       return clkt->div;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
>>> +                                       unsigned int div)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div == div)
>>> +                       return clkt->val;
>>> +       return 0;
>>> +}
>>> +
>>> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
>>> +                                       unsigned long parent_rate)
>>> +{
>>> +       unsigned int div, val;
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +
>>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>>> +       val &= div_mask(dclk->width);
>>> +
>>> +       div = hi6220_get_table_div(dclk->table, val);
>>> +       if (!div) {
>>> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
>>> +                          __clk_get_name(hw->clk));
>>> +               return parent_rate;
>>> +       }
>>> +
>>> +       return parent_rate / div;
>>> +}
>>> +
>>> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
>>> +                               unsigned int div)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div == div)
>>> +                       return true;
>>> +       return false;
>>> +}
>>> +
>>> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
>>> +                                unsigned long *best_parent_rate)
>>> +{
>>> +       unsigned int i, bestdiv = 0;
>>> +       unsigned long parent_rate, best = 0, now, maxdiv;
>>> +
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
>>> +
>>> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
>>> +
>>> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>>> +               parent_rate = *best_parent_rate;
>>> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
>>> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
>>> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
>>> +               return bestdiv;
>>> +       }
>>> +
>>> +       /*
>>> +        * The maximum divider we can use without overflowing
>>> +        * unsigned long in rate * i below
>>> +        */
>>> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
>>> +
>>> +       for (i = 1; i <= maxdiv; i++) {
>>> +               if (!hi6220_is_valid_div(dclk->table, i))
>>> +                       continue;
>>> +               parent_rate = __clk_round_rate(clk_parent,
>>> +                                       MULT_ROUND_UP(rate, i));
>>> +               now = parent_rate / i;
>>> +               if (now <= rate && now > best) {
>>> +                       bestdiv = i;
>>> +                       best = now;
>>> +                       *best_parent_rate = parent_rate;
>>> +               }
>>> +       }
>>> +
>>> +       if (!bestdiv) {
>>> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
>>> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
>>> +       }
>>> +
>>> +       return bestdiv;
>>> +}
>>> +
>>> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>>> +                                       unsigned long *prate)
>>> +{
>>> +       int div;
>>> +
>>> +       if (!rate)
>>> +               rate = 1;
>>> +
>>> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
>>> +
>>> +       return *prate / div;
>>> +}
>>> +
>>> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>>> +                                       unsigned long parent_rate)
>>> +{
>>> +       unsigned int div, value;
>>> +       unsigned long flags = 0;
>>> +       u32 data;
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +
>>> +       div = parent_rate / rate;
>>> +
>>> +       if (!hi6220_is_valid_div(dclk->table, div))
>>> +               return -EINVAL;
>>> +
>>> +       value = hi6220_get_table_val(dclk->table, div);
>>> +
>>> +       if (value > div_mask(dclk->width))
>>> +               value = div_mask(dclk->width);
>>> +
>>> +       if (dclk->lock)
>>> +               spin_lock_irqsave(dclk->lock, flags);
>>> +
>>> +       data = readl_relaxed(dclk->reg);
>>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>>> +       data |= value << dclk->shift;
>>> +       data |= dclk->mask;
>>> +
>>> +       writel_relaxed(data, dclk->reg);
>>> +
>>> +       if (dclk->lock)
>>> +               spin_unlock_irqrestore(dclk->lock, flags);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static struct clk_ops hi6220_clkdiv_ops = {
>>> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
>>> +       .round_rate = hi6220_clkdiv_round_rate,
>>> +       .set_rate = hi6220_clkdiv_set_rate,
>>> +};
>>> +
>>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
>>> +{
>>> +       struct hi6220_clk_divider *div;
>>> +       struct clk *clk;
>>> +       struct clk_init_data init;
>>> +       struct clk_div_table *table;
>>> +       u32 max_div, min_div;
>>> +       int i;
>>> +
>>> +       /* allocate the divider */
>>> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
>>> +       if (!div) {
>>> +               pr_err("%s: could not allocate divider clk\n", __func__);
>>> +               return ERR_PTR(-ENOMEM);
>>> +       }
>>> +
>>> +       /* Init the divider table */
>>> +       max_div = div_mask(width) + 1;
>>> +       min_div = 1;
>>> +
>>> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
>>> +       if (!table) {
>>> +               kfree(div);
>>> +               pr_err("%s: failed to alloc divider table!\n", __func__);
>>> +               return ERR_PTR(-ENOMEM);
>>> +       }
>>> +
>>> +       for (i = 0; i < max_div; i++) {
>>> +               table[i].div = min_div + i;
>>> +               table[i].val = table[i].div - 1;
>>> +       }
>>> +
>>> +       init.name = name;
>>> +       init.ops = &hi6220_clkdiv_ops;
>>> +       init.flags = flags | CLK_IS_BASIC;
>>> +       init.parent_names = parent_name ? &parent_name : NULL;
>>> +       init.num_parents = parent_name ? 1 : 0;
>>> +
>>> +       /* struct hi6220_clk_divider assignments */
>>> +       div->reg = reg;
>>> +       div->shift = shift;
>>> +       div->width = width;
>>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>>> +       div->lock = lock;
>>> +       div->hw.init = &init;
>>> +       div->table = table;
>>> +
>>> +       /* register the clock */
>>> +       clk = clk_register(dev, &div->hw);
>>> +
>>> +       if (IS_ERR(clk)) {
>>> +               kfree(table);
>>> +               kfree(div);
>>> +       }
>>> +
>>> +       return clk;
>>> +}
>>> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
>>> new file mode 100644
>>> index 0000000..05033e7
>>> --- /dev/null
>>> +++ b/include/dt-bindings/clock/hi6220-clock.h
>>> @@ -0,0 +1,172 @@
>>> +/*
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
>>> +#define __DT_BINDINGS_CLOCK_HI6220_H
>>> +
>>> +/* clk in AO (always on) controller */
>>> +#define HI6220_NONE_CLOCK      0
>>> +
>>> +/* fixed rate clocks */
>>> +#define HI6220_REF32K          1
>>> +#define HI6220_CLK_TCXO                2
>>> +#define HI6220_MMC1_PAD                3
>>> +#define HI6220_MMC2_PAD                4
>>> +#define HI6220_MMC0_PAD                5
>>> +#define HI6220_PLL_BBP         6
>>> +#define HI6220_PLL_GPU         7
>>> +#define HI6220_PLL1_DDR                8
>>> +#define HI6220_PLL_SYS         9
>>> +#define HI6220_PLL_SYS_MEDIA   10
>>> +#define HI6220_DDR_SRC         11
>>> +#define HI6220_PLL_MEDIA       12
>>> +#define HI6220_PLL_DDR         13
>>> +
>>> +/* fixed factor clocks */
>>> +#define HI6220_300M            16
>>> +#define HI6220_150M            17
>>> +#define HI6220_PICOPHY_SRC     18
>>> +#define HI6220_MMC0_SRC_SEL    19
>>> +#define HI6220_MMC1_SRC_SEL    20
>>> +#define HI6220_MMC2_SRC_SEL    21
>>> +#define HI6220_VPU_CODEC       22
>>> +#define HI6220_MMC0_SMP                23
>>> +#define HI6220_MMC1_SMP                24
>>> +#define HI6220_MMC2_SMP                25
>>> +
>>> +/* gate clocks */
>>> +#define HI6220_WDT0_PCLK       28
>>> +#define HI6220_WDT1_PCLK       29
>>> +#define HI6220_WDT2_PCLK       30
>>> +#define HI6220_TIMER0_PCLK     31
>>> +#define HI6220_TIMER1_PCLK     32
>>> +#define HI6220_TIMER2_PCLK     33
>>> +#define HI6220_TIMER3_PCLK     34
>>> +#define HI6220_TIMER4_PCLK     35
>>> +#define HI6220_TIMER5_PCLK     36
>>> +#define HI6220_TIMER6_PCLK     37
>>> +#define HI6220_TIMER7_PCLK     38
>>> +#define HI6220_TIMER8_PCLK     39
>>> +#define HI6220_UART0_PCLK      40
>>> +
>>> +#define HI6220_AO_NR_CLKS      48
>>> +
>>> +/* clk in systrl */
>>> +/* gate clock */
>>> +#define HI6220_MMC0_CLK                1
>>> +#define HI6220_MMC0_CIUCLK     2
>>> +#define HI6220_MMC1_CLK                3
>>> +#define HI6220_MMC1_CIUCLK     4
>>> +#define HI6220_MMC2_CLK                5
>>> +#define HI6220_MMC2_CIUCLK     6
>>> +#define HI6220_USBOTG_HCLK     7
>>> +#define HI6220_CLK_PICOPHY     8
>>> +#define HI6220_HIFI            9
>>> +#define HI6220_DACODEC_PCLK    10
>>> +#define HI6220_EDMAC_ACLK      11
>>> +#define HI6220_CS_ATB          12
>>> +#define HI6220_I2C0_CLK                13
>>> +#define HI6220_I2C1_CLK                14
>>> +#define HI6220_I2C2_CLK                15
>>> +#define HI6220_I2C3_CLK                16
>>> +#define HI6220_UART1_PCLK      17
>>> +#define HI6220_UART2_PCLK      18
>>> +#define HI6220_UART3_PCLK      19
>>> +#define HI6220_UART4_PCLK      20
>>> +#define HI6220_SPI_CLK         21
>>> +#define HI6220_MMU_CLK         22
>>> +#define HI6220_HIFI_SEL                23
>>> +#define HI6220_MMC0_SYSPLL     24
>>> +#define HI6220_MMC1_SYSPLL     25
>>> +#define HI6220_MMC2_SYSPLL     26
>>> +#define HI6220_MMC0_SEL                27
>>> +#define HI6220_MMC1_SEL                28
>>> +#define HI6220_BBPPLL_SEL      29
>>> +#define HI6220_MEDIA_PLL_SRC   30
>>> +#define HI6220_MMC2_SEL                31
>>> +#define HI6220_CS_ATB_SYSPLL   32
>>> +
>>> +/* mux clocks */
>>> +#define HI6220_MMC0_SRC                35
>>> +#define HI6220_MMC0_SMP_IN     36
>>> +#define HI6220_MMC1_SRC                37
>>> +#define HI6220_MMC1_SMP_IN     38
>>> +#define HI6220_MMC2_SRC                39
>>> +#define HI6220_MMC2_SMP_IN     40
>>> +#define HI6220_HIFI_SRC                41
>>> +#define HI6220_UART1_SRC       42
>>> +#define HI6220_UART2_SRC       43
>>> +#define HI6220_UART3_SRC       44
>>> +#define HI6220_UART4_SRC       45
>>> +#define HI6220_MMC0_MUX0       46
>>> +#define HI6220_MMC1_MUX0       47
>>> +#define HI6220_MMC2_MUX0       48
>>> +#define HI6220_MMC0_MUX1       49
>>> +#define HI6220_MMC1_MUX1       50
>>> +#define HI6220_MMC2_MUX1       51
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_CLK_BUS         54
>>> +#define HI6220_MMC0_DIV                55
>>> +#define HI6220_MMC1_DIV                56
>>> +#define HI6220_MMC2_DIV                57
>>> +#define HI6220_HIFI_DIV                58
>>> +#define HI6220_BBPPLL0_DIV     59
>>> +#define HI6220_CS_DAPB         60
>>> +#define HI6220_CS_ATB_DIV      61
>>> +
>>> +#define HI6220_SYS_NR_CLKS     64
>>> +
>>> +/* clk in media controller */
>>> +/* gate clocks */
>>> +#define HI6220_DSI_PCLK                1
>>> +#define HI6220_G3D_PCLK                2
>>> +#define HI6220_ACLK_CODEC_VPU  3
>>> +#define HI6220_ISP_SCLK                4
>>> +#define HI6220_ADE_CORE                5
>>> +#define HI6220_MED_MMU         6
>>> +#define HI6220_CFG_CSI4PHY     7
>>> +#define HI6220_CFG_CSI2PHY     8
>>> +#define HI6220_ISP_SCLK_GATE   9
>>> +#define HI6220_ISP_SCLK_GATE1  10
>>> +#define HI6220_ADE_CORE_GATE   11
>>> +#define HI6220_CODEC_VPU_GATE  12
>>> +#define HI6220_MED_SYSPLL      13
>>> +
>>> +/* mux clocks */
>>> +#define HI6220_1440_1200       20
>>> +#define HI6220_1000_1200       21
>>> +#define HI6220_1000_1440       22
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_CODEC_JPEG      30
>>> +#define HI6220_ISP_SCLK_SRC    31
>>> +#define HI6220_ISP_SCLK1       32
>>> +#define HI6220_ADE_CORE_SRC    33
>>> +#define HI6220_ADE_PIX_SRC     34
>>> +#define HI6220_G3D_CLK         35
>>> +#define HI6220_CODEC_VPU_SRC   36
>>> +
>>> +#define HI6220_MEDIA_NR_CLKS   40
>>> +
>>> +/* clk in power controller */
>>> +/* gate clocks */
>>> +#define HI6220_PLL_GPU_GATE    1
>>> +#define HI6220_PLL1_DDR_GATE   2
>>> +#define HI6220_PLL_DDR_GATE    3
>>> +#define HI6220_PLL_MEDIA_GATE  4
>>> +#define HI6220_PLL0_BBP_GATE   5
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_DDRC_SRC                10
>>> +#define HI6220_DDRC_AXI1       11
>>> +
>>> +#define HI6220_POWER_NR_CLKS   16
>>> +#endif
>>> --
>>> 1.7.9.5
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>> Cheers,
>>
>> - Tyler
>>
>> [1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
>
>
> --
> Best Regards,
>
> Bintian
> ===========================
> Don't be nervous, just be happy!

Cheers,

- Tyler

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

* Re: [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-07 22:05         ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-07 22:05 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, Rob Herring, Paweł Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Kevin Hilman,
	Mike Turquette, Rob Herring, Zhangfei Gao, Haojian Zhuang,
	Xu Wei, Jaehoon Chung, Olof Johansson, Haifeng Yan, Stephen Boyd

Hi Bintian,

On 7 February 2015 at 10:05, Brent Wang <wangbintian@gmail.com> wrote:
> Hello Tyler,
>
> Thank you very much for helping test this patchset!

Not a problem.

>
> 2015-02-07 2:10 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
>> Hi Bintian,
>>
>> This patch applied to next-20150204 is producing build failures on
>> various ARM defconfigs[1]. I received the following error in all
>> cases:
>>
>> drivers/built-in.o: In function `hi6220_clk_register_divider':
>> :(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
>> Makefile:925: recipe for target 'vmlinux' failed
>> make: *** [vmlinux] Error 1
> It's my fault, I just test on ARM64, The following patch can fix this error:
> =====================
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index bbf0539..48f0116 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -2,9 +2,9 @@
>  # Hisilicon Clock specific Makefile
>  #
>
> -obj-y  += clk.o clkgate-separated.o
> +obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o
>
>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
> -obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
> ======================
>
> I will fix this problem in next version.

Great, thank you. I quickly tested your change above, and it gets the
ARM defconfigs building again.

>
> Thanks,
>
> Bintian
>
>
>>
>> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>>> registers to supply different clocks to different IPs in the SoC.
>>>
>>> We add one divider clock for hi6220 because the divider in hi6220
>>> also has a mask bit but it doesnot obey the rule defined by flag
>>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>>> to handle it.
>>>
>>> This patch also enables this clock driver for ARCH_HISI and document
>>> devicetree bindings.
>>>
>>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> ---
>>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>>  arch/arm64/Kconfig                                 |    1 +
>>>  drivers/clk/Kconfig                                |    2 +
>>>  drivers/clk/Makefile                               |    4 +-
>>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>>
>>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>> new file mode 100644
>>> index 0000000..a3ddda1
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>> @@ -0,0 +1,30 @@
>>> +* Hisilicon Hi6220 Clock Controller
>>> +
>>> +The hi6220 clock controller generates and supplies clock to various
>>> +controllers within the hi6220 SoC.
>>> +
>>> +Required Properties:
>>> +
>>> +- compatible: should be one of the following:
>>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>>> +     power always on(AO) domain, it is the sub node of SoC power AO
>>> +     controller in dts file.
>>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>>> +     system control domain, it is the sub node of SoC system controller
>>> +     in dts file.
>>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>>> +     SoC media control domain, it is the sub node of SoC media controller
>>> +     in dts file.
>>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>>> +     SoC power control domain, it is the sub node of SoC power controller
>>> +     in dts file.
>>> +
>>> +- reg: physical base address of the controller and length of memory mapped
>>> +  region.
>>> +
>>> +- #clock-cells: should be 1.
>>> +
>>> +Each clock is assigned an identifier and client nodes use this identifier
>>> +to specify the clock which they consume.
>>> +
>>> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 78cd41c8..6efc3e3 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -175,6 +175,7 @@ config ARCH_XGENE
>>>
>>>  config ARCH_HISI
>>>         bool "Hisilicon SoC Family"
>>> +       select COMMON_CLK_HI6220
>>>         help
>>>           This enables support for Hisilicon ARMv8 Family of SoCs.
>>>
>>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>>> index 3f44f29..b52c95c 100644
>>> --- a/drivers/clk/Kconfig
>>> +++ b/drivers/clk/Kconfig
>>> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>>>
>>>  source "drivers/clk/qcom/Kconfig"
>>>
>>> +source "drivers/clk/hisilicon/Kconfig"
>>> +
>>>  endmenu
>>>
>>>  source "drivers/clk/bcm/Kconfig"
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index d5fba5b..c58703b 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>>>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>>>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>>>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
>>> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
>>> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>>> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>>> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>>>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>>>  ifeq ($(CONFIG_COMMON_CLK), y)
>>>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>>> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
>>> new file mode 100644
>>> index 0000000..e3ead46
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/Kconfig
>>> @@ -0,0 +1,5 @@
>>> +config COMMON_CLK_HI6220
>>> +       tristate "Hi6220 Clock Driver"
>>> +       depends on OF && ARCH_HISI
>>> +       help
>>> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
>>> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
>>> index 038c02f..bbf0539 100644
>>> --- a/drivers/clk/hisilicon/Makefile
>>> +++ b/drivers/clk/hisilicon/Makefile
>>> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>>>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>>>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>>>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
>>> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
>>> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
>>> new file mode 100644
>>> index 0000000..01d0c46
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/clk-hi6220.c
>>> @@ -0,0 +1,284 @@
>>> +/*
>>> + * Hisilicon Hi6220 clock driver
>>> + *
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/clkdev.h>
>>> +#include <linux/io.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/clk.h>
>>> +
>>> +#include <dt-bindings/clock/hi6220-clock.h>
>>> +
>>> +#include "clk.h"
>>> +
>>> +
>>> +/* clocks in AO (always on) controller */
>>> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
>>> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
>>> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
>>> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
>>> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
>>> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
>>> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
>>> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
>>> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
>>> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
>>> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
>>> +};
>>> +
>>> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
>>> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
>>> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
>>> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
>>> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
>>> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
>>> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
>>> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
>>> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
>>> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
>>> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
>>> +};
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
>>> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
>>> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
>>> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
>>> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
>>> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
>>> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
>>> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
>>> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
>>> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
>>> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
>>> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
>>> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
>>> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_ao_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
>>> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
>>> +
>>> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
>>> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
>>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
>>> +
>>> +
>>> +/* clocks in sysctrl */
>>> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
>>> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
>>> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
>>> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
>>> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
>>> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
>>> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
>>> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
>>> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
>>> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
>>> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>>> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>>> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>>> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>>> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>>> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>>> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
>>> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
>>> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
>>> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
>>> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
>>> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
>>> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
>>> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
>>> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
>>> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
>>> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
>>> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
>>> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
>>> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
>>> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
>>> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
>>> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
>>> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
>>> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
>>> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
>>> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
>>> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
>>> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
>>> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
>>> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
>>> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
>>> +};
>>> +
>>> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
>>> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>>> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>>> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>>> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>>> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>>> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>>> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
>>> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
>>> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
>>> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
>>> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
>>> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
>>> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
>>> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
>>> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_sys_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
>>> +
>>> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
>>> +
>>> +
>>> +/* clocks in media controller */
>>> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
>>> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
>>> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
>>> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
>>> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
>>> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
>>> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
>>> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
>>> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
>>> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
>>> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
>>> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
>>> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
>>> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
>>> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
>>> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
>>> +};
>>> +
>>> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
>>> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
>>> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
>>> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
>>> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
>>> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
>>> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
>>> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
>>> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
>>> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
>>> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_media_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
>>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
>>> +
>>> +       hisi_clk_register_mux(hi6220_mux_clks_media,
>>> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_media,
>>> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
>>> +
>>> +
>>> +/* clocks in pmctrl */
>>> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
>>> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
>>> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
>>> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
>>> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
>>> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
>>> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
>>> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_power_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate(hi6220_gate_clks_power,
>>> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_power,
>>> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
>>> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
>>> index a078e84..5d2305c 100644
>>> --- a/drivers/clk/hisilicon/clk.c
>>> +++ b/drivers/clk/hisilicon/clk.c
>>> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>>>                 data->clk_data.clks[clks[i].id] = clk;
>>>         }
>>>  }
>>> +
>>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
>>> +                                         int nums, struct hisi_clock_data *data)
>>> +{
>>> +       struct clk *clk;
>>> +       void __iomem *base = data->base;
>>> +       int i;
>>> +
>>> +       for (i = 0; i < nums; i++) {
>>> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
>>> +                                               clks[i].parent_name,
>>> +                                               clks[i].flags,
>>> +                                               base + clks[i].offset,
>>> +                                               clks[i].shift,
>>> +                                               clks[i].width,
>>> +                                               clks[i].mask_bit,
>>> +                                               &hisi_clk_lock);
>>> +               if (IS_ERR(clk)) {
>>> +                       pr_err("%s: failed to register clock %s\n",
>>> +                              __func__, clks[i].name);
>>> +                       continue;
>>> +               }
>>> +
>>> +               if (clks[i].alias)
>>> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
>>> +
>>> +               data->clk_data.clks[clks[i].id] = clk;
>>> +       }
>>> +}
>>> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
>>> index 31083ff..462a570 100644
>>> --- a/drivers/clk/hisilicon/clk.h
>>> +++ b/drivers/clk/hisilicon/clk.h
>>> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>>>         const char              *alias;
>>>  };
>>>
>>> +struct hi6220_divider_clock {
>>> +       unsigned int            id;
>>> +       const char              *name;
>>> +       const char              *parent_name;
>>> +       unsigned long           flags;
>>> +       unsigned long           offset;
>>> +       u8                      shift;
>>> +       u8                      width;
>>> +       u32                     mask_bit;
>>> +       const char              *alias;
>>> +};
>>> +
>>>  struct hisi_gate_clock {
>>>         unsigned int            id;
>>>         const char              *name;
>>> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>>>                                 const char *, unsigned long,
>>>                                 void __iomem *, u8,
>>>                                 u8, spinlock_t *);
>>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>>>
>>>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>>>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
>>> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>>>                                         int, struct hisi_clock_data *);
>>>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>>>                                         int, struct hisi_clock_data *);
>>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
>>> +                                       int, struct hisi_clock_data *);
>>>  #endif /* __HISI_CLK_H */
>>> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
>>> new file mode 100644
>>> index 0000000..9e3825b
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
>>> @@ -0,0 +1,273 @@
>>> +/*
>>> + * Hisilicon hi6220 SoC divider clock driver
>>> + *
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + */
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/io.h>
>>> +#include <linux/err.h>
>>> +
>>> +#define div_mask(width)        ((1 << (width)) - 1)
>>> +
>>> +/*
>>> + * The reverse of DIV_ROUND_UP: The maximum number which
>>> + * divided by m is r
>>> + */
>>> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
>>> +
>>> +/**
>>> + * struct hi6220_clk_divider - divider clock for hi6220
>>> + *
>>> + * @hw:                handle between common and hardware-specific interfaces
>>> + * @reg:       register containing divider
>>> + * @shift:     shift to the divider bit field
>>> + * @width:     width of the divider bit field
>>> + * @mask:      mask for setting divider rate
>>> + * @table:     the div table that the divider supports
>>> + * @lock:      register lock
>>> + */
>>> +struct hi6220_clk_divider {
>>> +       struct clk_hw   hw;
>>> +       void __iomem    *reg;
>>> +       u8              shift;
>>> +       u8              width;
>>> +       u32             mask;
>>> +       const struct clk_div_table *table;
>>> +       spinlock_t      *lock;
>>> +};
>>> +
>>> +#define to_hi6220_clk_divider(_hw)     \
>>> +       container_of(_hw, struct hi6220_clk_divider, hw)
>>> +
>>> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
>>> +{
>>> +       unsigned int maxdiv = 0;
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div > maxdiv)
>>> +                       maxdiv = clkt->div;
>>> +       return maxdiv;
>>> +}
>>> +
>>> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
>>> +                                       unsigned int val)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->val == val)
>>> +                       return clkt->div;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
>>> +                                       unsigned int div)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div == div)
>>> +                       return clkt->val;
>>> +       return 0;
>>> +}
>>> +
>>> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
>>> +                                       unsigned long parent_rate)
>>> +{
>>> +       unsigned int div, val;
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +
>>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>>> +       val &= div_mask(dclk->width);
>>> +
>>> +       div = hi6220_get_table_div(dclk->table, val);
>>> +       if (!div) {
>>> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
>>> +                          __clk_get_name(hw->clk));
>>> +               return parent_rate;
>>> +       }
>>> +
>>> +       return parent_rate / div;
>>> +}
>>> +
>>> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
>>> +                               unsigned int div)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div == div)
>>> +                       return true;
>>> +       return false;
>>> +}
>>> +
>>> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
>>> +                                unsigned long *best_parent_rate)
>>> +{
>>> +       unsigned int i, bestdiv = 0;
>>> +       unsigned long parent_rate, best = 0, now, maxdiv;
>>> +
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
>>> +
>>> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
>>> +
>>> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>>> +               parent_rate = *best_parent_rate;
>>> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
>>> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
>>> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
>>> +               return bestdiv;
>>> +       }
>>> +
>>> +       /*
>>> +        * The maximum divider we can use without overflowing
>>> +        * unsigned long in rate * i below
>>> +        */
>>> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
>>> +
>>> +       for (i = 1; i <= maxdiv; i++) {
>>> +               if (!hi6220_is_valid_div(dclk->table, i))
>>> +                       continue;
>>> +               parent_rate = __clk_round_rate(clk_parent,
>>> +                                       MULT_ROUND_UP(rate, i));
>>> +               now = parent_rate / i;
>>> +               if (now <= rate && now > best) {
>>> +                       bestdiv = i;
>>> +                       best = now;
>>> +                       *best_parent_rate = parent_rate;
>>> +               }
>>> +       }
>>> +
>>> +       if (!bestdiv) {
>>> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
>>> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
>>> +       }
>>> +
>>> +       return bestdiv;
>>> +}
>>> +
>>> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>>> +                                       unsigned long *prate)
>>> +{
>>> +       int div;
>>> +
>>> +       if (!rate)
>>> +               rate = 1;
>>> +
>>> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
>>> +
>>> +       return *prate / div;
>>> +}
>>> +
>>> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>>> +                                       unsigned long parent_rate)
>>> +{
>>> +       unsigned int div, value;
>>> +       unsigned long flags = 0;
>>> +       u32 data;
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +
>>> +       div = parent_rate / rate;
>>> +
>>> +       if (!hi6220_is_valid_div(dclk->table, div))
>>> +               return -EINVAL;
>>> +
>>> +       value = hi6220_get_table_val(dclk->table, div);
>>> +
>>> +       if (value > div_mask(dclk->width))
>>> +               value = div_mask(dclk->width);
>>> +
>>> +       if (dclk->lock)
>>> +               spin_lock_irqsave(dclk->lock, flags);
>>> +
>>> +       data = readl_relaxed(dclk->reg);
>>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>>> +       data |= value << dclk->shift;
>>> +       data |= dclk->mask;
>>> +
>>> +       writel_relaxed(data, dclk->reg);
>>> +
>>> +       if (dclk->lock)
>>> +               spin_unlock_irqrestore(dclk->lock, flags);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static struct clk_ops hi6220_clkdiv_ops = {
>>> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
>>> +       .round_rate = hi6220_clkdiv_round_rate,
>>> +       .set_rate = hi6220_clkdiv_set_rate,
>>> +};
>>> +
>>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
>>> +{
>>> +       struct hi6220_clk_divider *div;
>>> +       struct clk *clk;
>>> +       struct clk_init_data init;
>>> +       struct clk_div_table *table;
>>> +       u32 max_div, min_div;
>>> +       int i;
>>> +
>>> +       /* allocate the divider */
>>> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
>>> +       if (!div) {
>>> +               pr_err("%s: could not allocate divider clk\n", __func__);
>>> +               return ERR_PTR(-ENOMEM);
>>> +       }
>>> +
>>> +       /* Init the divider table */
>>> +       max_div = div_mask(width) + 1;
>>> +       min_div = 1;
>>> +
>>> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
>>> +       if (!table) {
>>> +               kfree(div);
>>> +               pr_err("%s: failed to alloc divider table!\n", __func__);
>>> +               return ERR_PTR(-ENOMEM);
>>> +       }
>>> +
>>> +       for (i = 0; i < max_div; i++) {
>>> +               table[i].div = min_div + i;
>>> +               table[i].val = table[i].div - 1;
>>> +       }
>>> +
>>> +       init.name = name;
>>> +       init.ops = &hi6220_clkdiv_ops;
>>> +       init.flags = flags | CLK_IS_BASIC;
>>> +       init.parent_names = parent_name ? &parent_name : NULL;
>>> +       init.num_parents = parent_name ? 1 : 0;
>>> +
>>> +       /* struct hi6220_clk_divider assignments */
>>> +       div->reg = reg;
>>> +       div->shift = shift;
>>> +       div->width = width;
>>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>>> +       div->lock = lock;
>>> +       div->hw.init = &init;
>>> +       div->table = table;
>>> +
>>> +       /* register the clock */
>>> +       clk = clk_register(dev, &div->hw);
>>> +
>>> +       if (IS_ERR(clk)) {
>>> +               kfree(table);
>>> +               kfree(div);
>>> +       }
>>> +
>>> +       return clk;
>>> +}
>>> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
>>> new file mode 100644
>>> index 0000000..05033e7
>>> --- /dev/null
>>> +++ b/include/dt-bindings/clock/hi6220-clock.h
>>> @@ -0,0 +1,172 @@
>>> +/*
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
>>> +#define __DT_BINDINGS_CLOCK_HI6220_H
>>> +
>>> +/* clk in AO (always on) controller */
>>> +#define HI6220_NONE_CLOCK      0
>>> +
>>> +/* fixed rate clocks */
>>> +#define HI6220_REF32K          1
>>> +#define HI6220_CLK_TCXO                2
>>> +#define HI6220_MMC1_PAD                3
>>> +#define HI6220_MMC2_PAD                4
>>> +#define HI6220_MMC0_PAD                5
>>> +#define HI6220_PLL_BBP         6
>>> +#define HI6220_PLL_GPU         7
>>> +#define HI6220_PLL1_DDR                8
>>> +#define HI6220_PLL_SYS         9
>>> +#define HI6220_PLL_SYS_MEDIA   10
>>> +#define HI6220_DDR_SRC         11
>>> +#define HI6220_PLL_MEDIA       12
>>> +#define HI6220_PLL_DDR         13
>>> +
>>> +/* fixed factor clocks */
>>> +#define HI6220_300M            16
>>> +#define HI6220_150M            17
>>> +#define HI6220_PICOPHY_SRC     18
>>> +#define HI6220_MMC0_SRC_SEL    19
>>> +#define HI6220_MMC1_SRC_SEL    20
>>> +#define HI6220_MMC2_SRC_SEL    21
>>> +#define HI6220_VPU_CODEC       22
>>> +#define HI6220_MMC0_SMP                23
>>> +#define HI6220_MMC1_SMP                24
>>> +#define HI6220_MMC2_SMP                25
>>> +
>>> +/* gate clocks */
>>> +#define HI6220_WDT0_PCLK       28
>>> +#define HI6220_WDT1_PCLK       29
>>> +#define HI6220_WDT2_PCLK       30
>>> +#define HI6220_TIMER0_PCLK     31
>>> +#define HI6220_TIMER1_PCLK     32
>>> +#define HI6220_TIMER2_PCLK     33
>>> +#define HI6220_TIMER3_PCLK     34
>>> +#define HI6220_TIMER4_PCLK     35
>>> +#define HI6220_TIMER5_PCLK     36
>>> +#define HI6220_TIMER6_PCLK     37
>>> +#define HI6220_TIMER7_PCLK     38
>>> +#define HI6220_TIMER8_PCLK     39
>>> +#define HI6220_UART0_PCLK      40
>>> +
>>> +#define HI6220_AO_NR_CLKS      48
>>> +
>>> +/* clk in systrl */
>>> +/* gate clock */
>>> +#define HI6220_MMC0_CLK                1
>>> +#define HI6220_MMC0_CIUCLK     2
>>> +#define HI6220_MMC1_CLK                3
>>> +#define HI6220_MMC1_CIUCLK     4
>>> +#define HI6220_MMC2_CLK                5
>>> +#define HI6220_MMC2_CIUCLK     6
>>> +#define HI6220_USBOTG_HCLK     7
>>> +#define HI6220_CLK_PICOPHY     8
>>> +#define HI6220_HIFI            9
>>> +#define HI6220_DACODEC_PCLK    10
>>> +#define HI6220_EDMAC_ACLK      11
>>> +#define HI6220_CS_ATB          12
>>> +#define HI6220_I2C0_CLK                13
>>> +#define HI6220_I2C1_CLK                14
>>> +#define HI6220_I2C2_CLK                15
>>> +#define HI6220_I2C3_CLK                16
>>> +#define HI6220_UART1_PCLK      17
>>> +#define HI6220_UART2_PCLK      18
>>> +#define HI6220_UART3_PCLK      19
>>> +#define HI6220_UART4_PCLK      20
>>> +#define HI6220_SPI_CLK         21
>>> +#define HI6220_MMU_CLK         22
>>> +#define HI6220_HIFI_SEL                23
>>> +#define HI6220_MMC0_SYSPLL     24
>>> +#define HI6220_MMC1_SYSPLL     25
>>> +#define HI6220_MMC2_SYSPLL     26
>>> +#define HI6220_MMC0_SEL                27
>>> +#define HI6220_MMC1_SEL                28
>>> +#define HI6220_BBPPLL_SEL      29
>>> +#define HI6220_MEDIA_PLL_SRC   30
>>> +#define HI6220_MMC2_SEL                31
>>> +#define HI6220_CS_ATB_SYSPLL   32
>>> +
>>> +/* mux clocks */
>>> +#define HI6220_MMC0_SRC                35
>>> +#define HI6220_MMC0_SMP_IN     36
>>> +#define HI6220_MMC1_SRC                37
>>> +#define HI6220_MMC1_SMP_IN     38
>>> +#define HI6220_MMC2_SRC                39
>>> +#define HI6220_MMC2_SMP_IN     40
>>> +#define HI6220_HIFI_SRC                41
>>> +#define HI6220_UART1_SRC       42
>>> +#define HI6220_UART2_SRC       43
>>> +#define HI6220_UART3_SRC       44
>>> +#define HI6220_UART4_SRC       45
>>> +#define HI6220_MMC0_MUX0       46
>>> +#define HI6220_MMC1_MUX0       47
>>> +#define HI6220_MMC2_MUX0       48
>>> +#define HI6220_MMC0_MUX1       49
>>> +#define HI6220_MMC1_MUX1       50
>>> +#define HI6220_MMC2_MUX1       51
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_CLK_BUS         54
>>> +#define HI6220_MMC0_DIV                55
>>> +#define HI6220_MMC1_DIV                56
>>> +#define HI6220_MMC2_DIV                57
>>> +#define HI6220_HIFI_DIV                58
>>> +#define HI6220_BBPPLL0_DIV     59
>>> +#define HI6220_CS_DAPB         60
>>> +#define HI6220_CS_ATB_DIV      61
>>> +
>>> +#define HI6220_SYS_NR_CLKS     64
>>> +
>>> +/* clk in media controller */
>>> +/* gate clocks */
>>> +#define HI6220_DSI_PCLK                1
>>> +#define HI6220_G3D_PCLK                2
>>> +#define HI6220_ACLK_CODEC_VPU  3
>>> +#define HI6220_ISP_SCLK                4
>>> +#define HI6220_ADE_CORE                5
>>> +#define HI6220_MED_MMU         6
>>> +#define HI6220_CFG_CSI4PHY     7
>>> +#define HI6220_CFG_CSI2PHY     8
>>> +#define HI6220_ISP_SCLK_GATE   9
>>> +#define HI6220_ISP_SCLK_GATE1  10
>>> +#define HI6220_ADE_CORE_GATE   11
>>> +#define HI6220_CODEC_VPU_GATE  12
>>> +#define HI6220_MED_SYSPLL      13
>>> +
>>> +/* mux clocks */
>>> +#define HI6220_1440_1200       20
>>> +#define HI6220_1000_1200       21
>>> +#define HI6220_1000_1440       22
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_CODEC_JPEG      30
>>> +#define HI6220_ISP_SCLK_SRC    31
>>> +#define HI6220_ISP_SCLK1       32
>>> +#define HI6220_ADE_CORE_SRC    33
>>> +#define HI6220_ADE_PIX_SRC     34
>>> +#define HI6220_G3D_CLK         35
>>> +#define HI6220_CODEC_VPU_SRC   36
>>> +
>>> +#define HI6220_MEDIA_NR_CLKS   40
>>> +
>>> +/* clk in power controller */
>>> +/* gate clocks */
>>> +#define HI6220_PLL_GPU_GATE    1
>>> +#define HI6220_PLL1_DDR_GATE   2
>>> +#define HI6220_PLL_DDR_GATE    3
>>> +#define HI6220_PLL_MEDIA_GATE  4
>>> +#define HI6220_PLL0_BBP_GATE   5
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_DDRC_SRC                10
>>> +#define HI6220_DDRC_AXI1       11
>>> +
>>> +#define HI6220_POWER_NR_CLKS   16
>>> +#endif
>>> --
>>> 1.7.9.5
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>> Cheers,
>>
>> - Tyler
>>
>> [1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
>
>
> --
> Best Regards,
>
> Bintian
> ===========================
> Don't be nervous, just be happy!

Cheers,

- Tyler

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

* [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC
@ 2015-02-07 22:05         ` Tyler Baker
  0 siblings, 0 replies; 85+ messages in thread
From: Tyler Baker @ 2015-02-07 22:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Bintian,

On 7 February 2015 at 10:05, Brent Wang <wangbintian@gmail.com> wrote:
> Hello Tyler,
>
> Thank you very much for helping test this patchset!

Not a problem.

>
> 2015-02-07 2:10 GMT+08:00 Tyler Baker <tyler.baker@linaro.org>:
>> Hi Bintian,
>>
>> This patch applied to next-20150204 is producing build failures on
>> various ARM defconfigs[1]. I received the following error in all
>> cases:
>>
>> drivers/built-in.o: In function `hi6220_clk_register_divider':
>> :(.init.text+0x1a84c): undefined reference to `hi6220_register_clkdiv'
>> Makefile:925: recipe for target 'vmlinux' failed
>> make: *** [vmlinux] Error 1
> It's my fault, I just test on ARM64, The following patch can fix this error:
> =====================
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index bbf0539..48f0116 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -2,9 +2,9 @@
>  # Hisilicon Clock specific Makefile
>  #
>
> -obj-y  += clk.o clkgate-separated.o
> +obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o
>
>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
> -obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
> ======================
>
> I will fix this problem in next version.

Great, thank you. I quickly tested your change above, and it gets the
ARM defconfigs building again.

>
> Thanks,
>
> Bintian
>
>
>>
>> On 5 February 2015 at 01:24, Bintian Wang <bintian.wang@huawei.com> wrote:
>>> Add clock drivers for hi6220 SoC, this driver controls the SoC
>>> registers to supply different clocks to different IPs in the SoC.
>>>
>>> We add one divider clock for hi6220 because the divider in hi6220
>>> also has a mask bit but it doesnot obey the rule defined by flag
>>> "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
>>> left shift fixed bits (e.g. 16 bits), so we add this divider clock
>>> to handle it.
>>>
>>> This patch also enables this clock driver for ARCH_HISI and document
>>> devicetree bindings.
>>>
>>> Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
>>> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> ---
>>>  .../devicetree/bindings/clock/hi6220-clock.txt     |   30 +++
>>>  arch/arm64/Kconfig                                 |    1 +
>>>  drivers/clk/Kconfig                                |    2 +
>>>  drivers/clk/Makefile                               |    4 +-
>>>  drivers/clk/hisilicon/Kconfig                      |    5 +
>>>  drivers/clk/hisilicon/Makefile                     |    1 +
>>>  drivers/clk/hisilicon/clk-hi6220.c                 |  284 ++++++++++++++++++++
>>>  drivers/clk/hisilicon/clk.c                        |   29 ++
>>>  drivers/clk/hisilicon/clk.h                        |   17 ++
>>>  drivers/clk/hisilicon/clkdivider-hi6220.c          |  273 +++++++++++++++++++
>>>  include/dt-bindings/clock/hi6220-clock.h           |  172 ++++++++++++
>>>  11 files changed, 815 insertions(+), 3 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>>  create mode 100644 drivers/clk/hisilicon/Kconfig
>>>  create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
>>>  create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c
>>>  create mode 100644 include/dt-bindings/clock/hi6220-clock.h
>>>
>>> diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>> new file mode 100644
>>> index 0000000..a3ddda1
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt
>>> @@ -0,0 +1,30 @@
>>> +* Hisilicon Hi6220 Clock Controller
>>> +
>>> +The hi6220 clock controller generates and supplies clock to various
>>> +controllers within the hi6220 SoC.
>>> +
>>> +Required Properties:
>>> +
>>> +- compatible: should be one of the following:
>>> +  - "hisilicon,hi6220-clock-ao" - controller for those clocks under SoC
>>> +     power always on(AO) domain, it is the sub node of SoC power AO
>>> +     controller in dts file.
>>> +  - "hisilicon,hi6220-clock-sys" - controller for those clocks under SoC
>>> +     system control domain, it is the sub node of SoC system controller
>>> +     in dts file.
>>> +  - "hisilicon,hi6220-clock-media" - controller for those clocks under
>>> +     SoC media control domain, it is the sub node of SoC media controller
>>> +     in dts file.
>>> +  - "hisilicon,hi6220-clock-power" - controller for those clocks under
>>> +     SoC power control domain, it is the sub node of SoC power controller
>>> +     in dts file.
>>> +
>>> +- reg: physical base address of the controller and length of memory mapped
>>> +  region.
>>> +
>>> +- #clock-cells: should be 1.
>>> +
>>> +Each clock is assigned an identifier and client nodes use this identifier
>>> +to specify the clock which they consume.
>>> +
>>> +All these identifier could be found in <dt-bindings/clock/hi6220-clock.h>.
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 78cd41c8..6efc3e3 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -175,6 +175,7 @@ config ARCH_XGENE
>>>
>>>  config ARCH_HISI
>>>         bool "Hisilicon SoC Family"
>>> +       select COMMON_CLK_HI6220
>>>         help
>>>           This enables support for Hisilicon ARMv8 Family of SoCs.
>>>
>>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>>> index 3f44f29..b52c95c 100644
>>> --- a/drivers/clk/Kconfig
>>> +++ b/drivers/clk/Kconfig
>>> @@ -136,6 +136,8 @@ config COMMON_CLK_PXA
>>>
>>>  source "drivers/clk/qcom/Kconfig"
>>>
>>> +source "drivers/clk/hisilicon/Kconfig"
>>> +
>>>  endmenu
>>>
>>>  source "drivers/clk/bcm/Kconfig"
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index d5fba5b..c58703b 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -43,9 +43,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
>>>  obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
>>>  obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
>>>  obj-$(CONFIG_ARCH_BERLIN)              += berlin/
>>> -obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
>>> -obj-$(CONFIG_ARCH_HIP04)               += hisilicon/
>>> -obj-$(CONFIG_ARCH_HIX5HD2)             += hisilicon/
>>> +obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
>>>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
>>>  ifeq ($(CONFIG_COMMON_CLK), y)
>>>  obj-$(CONFIG_ARCH_MMP)                 += mmp/
>>> diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
>>> new file mode 100644
>>> index 0000000..e3ead46
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/Kconfig
>>> @@ -0,0 +1,5 @@
>>> +config COMMON_CLK_HI6220
>>> +       tristate "Hi6220 Clock Driver"
>>> +       depends on OF && ARCH_HISI
>>> +       help
>>> +         Build the Hisilicon Hi6220 clock driver based on the common clock framework.
>>> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
>>> index 038c02f..bbf0539 100644
>>> --- a/drivers/clk/hisilicon/Makefile
>>> +++ b/drivers/clk/hisilicon/Makefile
>>> @@ -7,3 +7,4 @@ obj-y   += clk.o clkgate-separated.o
>>>  obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
>>>  obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
>>>  obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
>>> +obj-$(CONFIG_COMMON_CLK_HI6220)        += clkdivider-hi6220.o clk-hi6220.o
>>> diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
>>> new file mode 100644
>>> index 0000000..01d0c46
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/clk-hi6220.c
>>> @@ -0,0 +1,284 @@
>>> +/*
>>> + * Hisilicon Hi6220 clock driver
>>> + *
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/clkdev.h>
>>> +#include <linux/io.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/clk.h>
>>> +
>>> +#include <dt-bindings/clock/hi6220-clock.h>
>>> +
>>> +#include "clk.h"
>>> +
>>> +
>>> +/* clocks in AO (always on) controller */
>>> +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
>>> +       { HI6220_REF32K,        "ref32k",       NULL, CLK_IS_ROOT, 32764,     },
>>> +       { HI6220_CLK_TCXO,      "clk_tcxo",     NULL, CLK_IS_ROOT, 19200000,  },
>>> +       { HI6220_MMC1_PAD,      "mmc1_pad",     NULL, CLK_IS_ROOT, 100000000, },
>>> +       { HI6220_MMC2_PAD,      "mmc2_pad",     NULL, CLK_IS_ROOT, 100000000, },
>>> +       { HI6220_MMC0_PAD,      "mmc0_pad",     NULL, CLK_IS_ROOT, 200000000, },
>>> +       { HI6220_PLL_BBP,       "bbppll0",      NULL, CLK_IS_ROOT, 245760000, },
>>> +       { HI6220_PLL_GPU,       "gpupll",       NULL, CLK_IS_ROOT, 1000000000,},
>>> +       { HI6220_PLL1_DDR,      "ddrpll1",      NULL, CLK_IS_ROOT, 1066000000,},
>>> +       { HI6220_PLL_SYS,       "syspll",       NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
>>> +       { HI6220_PLL_MEDIA,     "media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
>>> +       { HI6220_PLL_DDR,       "ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
>>> +};
>>> +
>>> +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
>>> +       { HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
>>> +       { HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
>>> +       { HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
>>> +       { HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
>>> +       { HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
>>> +       { HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
>>> +       { HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
>>> +       { HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
>>> +       { HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
>>> +       { HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
>>> +};
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
>>> +       { HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
>>> +       { HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
>>> +       { HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
>>> +       { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
>>> +       { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
>>> +       { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
>>> +       { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
>>> +       { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
>>> +       { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
>>> +       { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
>>> +       { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
>>> +       { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
>>> +       { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_ao_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
>>> +                               ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data);
>>> +
>>> +       hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
>>> +                               ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data);
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
>>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init);
>>> +
>>> +
>>> +/* clocks in sysctrl */
>>> +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", };
>>> +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", };
>>> +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", };
>>> +static const char *mmc1_src_p[]  __initconst = { "mmc1srcsel", "mmc1_div", };
>>> +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", };
>>> +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", };
>>> +static const char *mmc2_src_p[]  __initconst = { "mmc2srcsel", "mmc2_div", };
>>> +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", };
>>> +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", };
>>> +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", };
>>> +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", };
>>> +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", };
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
>>> +       { HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>>> +       { HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
>>> +       { HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>>> +       { HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
>>> +       { HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>>> +       { HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
>>> +       { HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
>>> +       { HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
>>> +       { HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
>>> +       { HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
>>> +       { HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
>>> +       { HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
>>> +       { HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
>>> +       { HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
>>> +       { HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
>>> +       { HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
>>> +       { HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
>>> +       { HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
>>> +       { HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
>>> +       { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
>>> +       { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
>>> +       { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
>>> +       { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
>>> +       { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
>>> +       { HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
>>> +       { HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
>>> +       { HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
>>> +       { HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
>>> +       { HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
>>> +       { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
>>> +       { HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
>>> +       { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
>>> +};
>>> +
>>> +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
>>> +       { HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>>> +       { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
>>> +       { HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>>> +       { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
>>> +       { HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>>> +       { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
>>> +       { HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
>>> +       { HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
>>> +       { HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
>>> +       { HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
>>> +       { HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
>>> +       { HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
>>> +       { HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
>>> +       { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
>>> +       { HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
>>> +       { HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_sys_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
>>> +
>>> +       hisi_clk_register_mux(hi6220_mux_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_sys,
>>> +                       ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init);
>>> +
>>> +
>>> +/* clocks in media controller */
>>> +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", };
>>> +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", };
>>> +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", };
>>> +
>>> +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
>>> +       { HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
>>> +       { HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
>>> +       { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
>>> +       { HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
>>> +       { HI6220_ADE_CORE,       "ade_core",         "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
>>> +       { HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
>>> +       { HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
>>> +       { HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
>>> +       { HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
>>> +       { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
>>> +       { HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
>>> +       { HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
>>> +       { HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
>>> +};
>>> +
>>> +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
>>> +       { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
>>> +       { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
>>> +       { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
>>> +       { HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
>>> +       { HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
>>> +       { HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
>>> +       { HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
>>> +       { HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
>>> +       { HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
>>> +       { HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_media_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
>>> +                               ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
>>> +
>>> +       hisi_clk_register_mux(hi6220_mux_clks_media,
>>> +                               ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_media,
>>> +                               ARRAY_SIZE(hi6220_div_clks_media), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init);
>>> +
>>> +
>>> +/* clocks in pmctrl */
>>> +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
>>> +       { HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
>>> +       { HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
>>> +       { HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
>>> +       { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
>>> +       { HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
>>> +};
>>> +
>>> +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
>>> +       { HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
>>> +       { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
>>> +};
>>> +
>>> +static void __init hi6220_clk_power_init(struct device_node *np)
>>> +{
>>> +       struct hisi_clock_data *clk_data;
>>> +
>>> +       clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       hisi_clk_register_gate(hi6220_gate_clks_power,
>>> +                               ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
>>> +
>>> +       hi6220_clk_register_divider(hi6220_div_clks_power,
>>> +                               ARRAY_SIZE(hi6220_div_clks_power), clk_data);
>>> +}
>>> +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init);
>>> diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
>>> index a078e84..5d2305c 100644
>>> --- a/drivers/clk/hisilicon/clk.c
>>> +++ b/drivers/clk/hisilicon/clk.c
>>> @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
>>>                 data->clk_data.clks[clks[i].id] = clk;
>>>         }
>>>  }
>>> +
>>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
>>> +                                         int nums, struct hisi_clock_data *data)
>>> +{
>>> +       struct clk *clk;
>>> +       void __iomem *base = data->base;
>>> +       int i;
>>> +
>>> +       for (i = 0; i < nums; i++) {
>>> +               clk = hi6220_register_clkdiv(NULL, clks[i].name,
>>> +                                               clks[i].parent_name,
>>> +                                               clks[i].flags,
>>> +                                               base + clks[i].offset,
>>> +                                               clks[i].shift,
>>> +                                               clks[i].width,
>>> +                                               clks[i].mask_bit,
>>> +                                               &hisi_clk_lock);
>>> +               if (IS_ERR(clk)) {
>>> +                       pr_err("%s: failed to register clock %s\n",
>>> +                              __func__, clks[i].name);
>>> +                       continue;
>>> +               }
>>> +
>>> +               if (clks[i].alias)
>>> +                       clk_register_clkdev(clk, clks[i].alias, NULL);
>>> +
>>> +               data->clk_data.clks[clks[i].id] = clk;
>>> +       }
>>> +}
>>> diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
>>> index 31083ff..462a570 100644
>>> --- a/drivers/clk/hisilicon/clk.h
>>> +++ b/drivers/clk/hisilicon/clk.h
>>> @@ -79,6 +79,18 @@ struct hisi_divider_clock {
>>>         const char              *alias;
>>>  };
>>>
>>> +struct hi6220_divider_clock {
>>> +       unsigned int            id;
>>> +       const char              *name;
>>> +       const char              *parent_name;
>>> +       unsigned long           flags;
>>> +       unsigned long           offset;
>>> +       u8                      shift;
>>> +       u8                      width;
>>> +       u32                     mask_bit;
>>> +       const char              *alias;
>>> +};
>>> +
>>>  struct hisi_gate_clock {
>>>         unsigned int            id;
>>>         const char              *name;
>>> @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
>>>                                 const char *, unsigned long,
>>>                                 void __iomem *, u8,
>>>                                 u8, spinlock_t *);
>>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
>>>
>>>  struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
>>>  void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
>>> @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *,
>>>                                         int, struct hisi_clock_data *);
>>>  void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
>>>                                         int, struct hisi_clock_data *);
>>> +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *,
>>> +                                       int, struct hisi_clock_data *);
>>>  #endif /* __HISI_CLK_H */
>>> diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
>>> new file mode 100644
>>> index 0000000..9e3825b
>>> --- /dev/null
>>> +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
>>> @@ -0,0 +1,273 @@
>>> +/*
>>> + * Hisilicon hi6220 SoC divider clock driver
>>> + *
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + */
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/io.h>
>>> +#include <linux/err.h>
>>> +
>>> +#define div_mask(width)        ((1 << (width)) - 1)
>>> +
>>> +/*
>>> + * The reverse of DIV_ROUND_UP: The maximum number which
>>> + * divided by m is r
>>> + */
>>> +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
>>> +
>>> +/**
>>> + * struct hi6220_clk_divider - divider clock for hi6220
>>> + *
>>> + * @hw:                handle between common and hardware-specific interfaces
>>> + * @reg:       register containing divider
>>> + * @shift:     shift to the divider bit field
>>> + * @width:     width of the divider bit field
>>> + * @mask:      mask for setting divider rate
>>> + * @table:     the div table that the divider supports
>>> + * @lock:      register lock
>>> + */
>>> +struct hi6220_clk_divider {
>>> +       struct clk_hw   hw;
>>> +       void __iomem    *reg;
>>> +       u8              shift;
>>> +       u8              width;
>>> +       u32             mask;
>>> +       const struct clk_div_table *table;
>>> +       spinlock_t      *lock;
>>> +};
>>> +
>>> +#define to_hi6220_clk_divider(_hw)     \
>>> +       container_of(_hw, struct hi6220_clk_divider, hw)
>>> +
>>> +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table)
>>> +{
>>> +       unsigned int maxdiv = 0;
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div > maxdiv)
>>> +                       maxdiv = clkt->div;
>>> +       return maxdiv;
>>> +}
>>> +
>>> +static unsigned int hi6220_get_table_div(const struct clk_div_table *table,
>>> +                                       unsigned int val)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->val == val)
>>> +                       return clkt->div;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static unsigned int hi6220_get_table_val(const struct clk_div_table *table,
>>> +                                       unsigned int div)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div == div)
>>> +                       return clkt->val;
>>> +       return 0;
>>> +}
>>> +
>>> +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
>>> +                                       unsigned long parent_rate)
>>> +{
>>> +       unsigned int div, val;
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +
>>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>>> +       val &= div_mask(dclk->width);
>>> +
>>> +       div = hi6220_get_table_div(dclk->table, val);
>>> +       if (!div) {
>>> +               pr_warn("%s: Invalid divisor for clock %s\n", __func__,
>>> +                          __clk_get_name(hw->clk));
>>> +               return parent_rate;
>>> +       }
>>> +
>>> +       return parent_rate / div;
>>> +}
>>> +
>>> +static bool hi6220_is_valid_div(const struct clk_div_table *table,
>>> +                               unsigned int div)
>>> +{
>>> +       const struct clk_div_table *clkt;
>>> +
>>> +       for (clkt = table; clkt->div; clkt++)
>>> +               if (clkt->div == div)
>>> +                       return true;
>>> +       return false;
>>> +}
>>> +
>>> +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate,
>>> +                                unsigned long *best_parent_rate)
>>> +{
>>> +       unsigned int i, bestdiv = 0;
>>> +       unsigned long parent_rate, best = 0, now, maxdiv;
>>> +
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +       struct clk *clk_parent = __clk_get_parent(hw->clk);
>>> +
>>> +       maxdiv = hi6220_get_table_maxdiv(dclk->table);
>>> +
>>> +       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>>> +               parent_rate = *best_parent_rate;
>>> +               bestdiv = DIV_ROUND_UP(parent_rate, rate);
>>> +               bestdiv = (bestdiv == 0) ? 1 : bestdiv;
>>> +               bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv;
>>> +               return bestdiv;
>>> +       }
>>> +
>>> +       /*
>>> +        * The maximum divider we can use without overflowing
>>> +        * unsigned long in rate * i below
>>> +        */
>>> +       maxdiv = min(ULONG_MAX / rate, maxdiv);
>>> +
>>> +       for (i = 1; i <= maxdiv; i++) {
>>> +               if (!hi6220_is_valid_div(dclk->table, i))
>>> +                       continue;
>>> +               parent_rate = __clk_round_rate(clk_parent,
>>> +                                       MULT_ROUND_UP(rate, i));
>>> +               now = parent_rate / i;
>>> +               if (now <= rate && now > best) {
>>> +                       bestdiv = i;
>>> +                       best = now;
>>> +                       *best_parent_rate = parent_rate;
>>> +               }
>>> +       }
>>> +
>>> +       if (!bestdiv) {
>>> +               bestdiv = hi6220_get_table_maxdiv(dclk->table);
>>> +               *best_parent_rate = __clk_round_rate(clk_parent, 1);
>>> +       }
>>> +
>>> +       return bestdiv;
>>> +}
>>> +
>>> +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>>> +                                       unsigned long *prate)
>>> +{
>>> +       int div;
>>> +
>>> +       if (!rate)
>>> +               rate = 1;
>>> +
>>> +       div = hi6220_clkdiv_bestdiv(hw, rate, prate);
>>> +
>>> +       return *prate / div;
>>> +}
>>> +
>>> +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>>> +                                       unsigned long parent_rate)
>>> +{
>>> +       unsigned int div, value;
>>> +       unsigned long flags = 0;
>>> +       u32 data;
>>> +       struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
>>> +
>>> +       div = parent_rate / rate;
>>> +
>>> +       if (!hi6220_is_valid_div(dclk->table, div))
>>> +               return -EINVAL;
>>> +
>>> +       value = hi6220_get_table_val(dclk->table, div);
>>> +
>>> +       if (value > div_mask(dclk->width))
>>> +               value = div_mask(dclk->width);
>>> +
>>> +       if (dclk->lock)
>>> +               spin_lock_irqsave(dclk->lock, flags);
>>> +
>>> +       data = readl_relaxed(dclk->reg);
>>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>>> +       data |= value << dclk->shift;
>>> +       data |= dclk->mask;
>>> +
>>> +       writel_relaxed(data, dclk->reg);
>>> +
>>> +       if (dclk->lock)
>>> +               spin_unlock_irqrestore(dclk->lock, flags);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static struct clk_ops hi6220_clkdiv_ops = {
>>> +       .recalc_rate = hi6220_clkdiv_recalc_rate,
>>> +       .round_rate = hi6220_clkdiv_round_rate,
>>> +       .set_rate = hi6220_clkdiv_set_rate,
>>> +};
>>> +
>>> +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
>>> +       const char *parent_name, unsigned long flags, void __iomem *reg,
>>> +       u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
>>> +{
>>> +       struct hi6220_clk_divider *div;
>>> +       struct clk *clk;
>>> +       struct clk_init_data init;
>>> +       struct clk_div_table *table;
>>> +       u32 max_div, min_div;
>>> +       int i;
>>> +
>>> +       /* allocate the divider */
>>> +       div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL);
>>> +       if (!div) {
>>> +               pr_err("%s: could not allocate divider clk\n", __func__);
>>> +               return ERR_PTR(-ENOMEM);
>>> +       }
>>> +
>>> +       /* Init the divider table */
>>> +       max_div = div_mask(width) + 1;
>>> +       min_div = 1;
>>> +
>>> +       table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL);
>>> +       if (!table) {
>>> +               kfree(div);
>>> +               pr_err("%s: failed to alloc divider table!\n", __func__);
>>> +               return ERR_PTR(-ENOMEM);
>>> +       }
>>> +
>>> +       for (i = 0; i < max_div; i++) {
>>> +               table[i].div = min_div + i;
>>> +               table[i].val = table[i].div - 1;
>>> +       }
>>> +
>>> +       init.name = name;
>>> +       init.ops = &hi6220_clkdiv_ops;
>>> +       init.flags = flags | CLK_IS_BASIC;
>>> +       init.parent_names = parent_name ? &parent_name : NULL;
>>> +       init.num_parents = parent_name ? 1 : 0;
>>> +
>>> +       /* struct hi6220_clk_divider assignments */
>>> +       div->reg = reg;
>>> +       div->shift = shift;
>>> +       div->width = width;
>>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>>> +       div->lock = lock;
>>> +       div->hw.init = &init;
>>> +       div->table = table;
>>> +
>>> +       /* register the clock */
>>> +       clk = clk_register(dev, &div->hw);
>>> +
>>> +       if (IS_ERR(clk)) {
>>> +               kfree(table);
>>> +               kfree(div);
>>> +       }
>>> +
>>> +       return clk;
>>> +}
>>> diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
>>> new file mode 100644
>>> index 0000000..05033e7
>>> --- /dev/null
>>> +++ b/include/dt-bindings/clock/hi6220-clock.h
>>> @@ -0,0 +1,172 @@
>>> +/*
>>> + * Copyright (c) 2015 Hisilicon Limited.
>>> + *
>>> + * Author: Bintian Wang <bintian.wang@huawei.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#ifndef __DT_BINDINGS_CLOCK_HI6220_H
>>> +#define __DT_BINDINGS_CLOCK_HI6220_H
>>> +
>>> +/* clk in AO (always on) controller */
>>> +#define HI6220_NONE_CLOCK      0
>>> +
>>> +/* fixed rate clocks */
>>> +#define HI6220_REF32K          1
>>> +#define HI6220_CLK_TCXO                2
>>> +#define HI6220_MMC1_PAD                3
>>> +#define HI6220_MMC2_PAD                4
>>> +#define HI6220_MMC0_PAD                5
>>> +#define HI6220_PLL_BBP         6
>>> +#define HI6220_PLL_GPU         7
>>> +#define HI6220_PLL1_DDR                8
>>> +#define HI6220_PLL_SYS         9
>>> +#define HI6220_PLL_SYS_MEDIA   10
>>> +#define HI6220_DDR_SRC         11
>>> +#define HI6220_PLL_MEDIA       12
>>> +#define HI6220_PLL_DDR         13
>>> +
>>> +/* fixed factor clocks */
>>> +#define HI6220_300M            16
>>> +#define HI6220_150M            17
>>> +#define HI6220_PICOPHY_SRC     18
>>> +#define HI6220_MMC0_SRC_SEL    19
>>> +#define HI6220_MMC1_SRC_SEL    20
>>> +#define HI6220_MMC2_SRC_SEL    21
>>> +#define HI6220_VPU_CODEC       22
>>> +#define HI6220_MMC0_SMP                23
>>> +#define HI6220_MMC1_SMP                24
>>> +#define HI6220_MMC2_SMP                25
>>> +
>>> +/* gate clocks */
>>> +#define HI6220_WDT0_PCLK       28
>>> +#define HI6220_WDT1_PCLK       29
>>> +#define HI6220_WDT2_PCLK       30
>>> +#define HI6220_TIMER0_PCLK     31
>>> +#define HI6220_TIMER1_PCLK     32
>>> +#define HI6220_TIMER2_PCLK     33
>>> +#define HI6220_TIMER3_PCLK     34
>>> +#define HI6220_TIMER4_PCLK     35
>>> +#define HI6220_TIMER5_PCLK     36
>>> +#define HI6220_TIMER6_PCLK     37
>>> +#define HI6220_TIMER7_PCLK     38
>>> +#define HI6220_TIMER8_PCLK     39
>>> +#define HI6220_UART0_PCLK      40
>>> +
>>> +#define HI6220_AO_NR_CLKS      48
>>> +
>>> +/* clk in systrl */
>>> +/* gate clock */
>>> +#define HI6220_MMC0_CLK                1
>>> +#define HI6220_MMC0_CIUCLK     2
>>> +#define HI6220_MMC1_CLK                3
>>> +#define HI6220_MMC1_CIUCLK     4
>>> +#define HI6220_MMC2_CLK                5
>>> +#define HI6220_MMC2_CIUCLK     6
>>> +#define HI6220_USBOTG_HCLK     7
>>> +#define HI6220_CLK_PICOPHY     8
>>> +#define HI6220_HIFI            9
>>> +#define HI6220_DACODEC_PCLK    10
>>> +#define HI6220_EDMAC_ACLK      11
>>> +#define HI6220_CS_ATB          12
>>> +#define HI6220_I2C0_CLK                13
>>> +#define HI6220_I2C1_CLK                14
>>> +#define HI6220_I2C2_CLK                15
>>> +#define HI6220_I2C3_CLK                16
>>> +#define HI6220_UART1_PCLK      17
>>> +#define HI6220_UART2_PCLK      18
>>> +#define HI6220_UART3_PCLK      19
>>> +#define HI6220_UART4_PCLK      20
>>> +#define HI6220_SPI_CLK         21
>>> +#define HI6220_MMU_CLK         22
>>> +#define HI6220_HIFI_SEL                23
>>> +#define HI6220_MMC0_SYSPLL     24
>>> +#define HI6220_MMC1_SYSPLL     25
>>> +#define HI6220_MMC2_SYSPLL     26
>>> +#define HI6220_MMC0_SEL                27
>>> +#define HI6220_MMC1_SEL                28
>>> +#define HI6220_BBPPLL_SEL      29
>>> +#define HI6220_MEDIA_PLL_SRC   30
>>> +#define HI6220_MMC2_SEL                31
>>> +#define HI6220_CS_ATB_SYSPLL   32
>>> +
>>> +/* mux clocks */
>>> +#define HI6220_MMC0_SRC                35
>>> +#define HI6220_MMC0_SMP_IN     36
>>> +#define HI6220_MMC1_SRC                37
>>> +#define HI6220_MMC1_SMP_IN     38
>>> +#define HI6220_MMC2_SRC                39
>>> +#define HI6220_MMC2_SMP_IN     40
>>> +#define HI6220_HIFI_SRC                41
>>> +#define HI6220_UART1_SRC       42
>>> +#define HI6220_UART2_SRC       43
>>> +#define HI6220_UART3_SRC       44
>>> +#define HI6220_UART4_SRC       45
>>> +#define HI6220_MMC0_MUX0       46
>>> +#define HI6220_MMC1_MUX0       47
>>> +#define HI6220_MMC2_MUX0       48
>>> +#define HI6220_MMC0_MUX1       49
>>> +#define HI6220_MMC1_MUX1       50
>>> +#define HI6220_MMC2_MUX1       51
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_CLK_BUS         54
>>> +#define HI6220_MMC0_DIV                55
>>> +#define HI6220_MMC1_DIV                56
>>> +#define HI6220_MMC2_DIV                57
>>> +#define HI6220_HIFI_DIV                58
>>> +#define HI6220_BBPPLL0_DIV     59
>>> +#define HI6220_CS_DAPB         60
>>> +#define HI6220_CS_ATB_DIV      61
>>> +
>>> +#define HI6220_SYS_NR_CLKS     64
>>> +
>>> +/* clk in media controller */
>>> +/* gate clocks */
>>> +#define HI6220_DSI_PCLK                1
>>> +#define HI6220_G3D_PCLK                2
>>> +#define HI6220_ACLK_CODEC_VPU  3
>>> +#define HI6220_ISP_SCLK                4
>>> +#define HI6220_ADE_CORE                5
>>> +#define HI6220_MED_MMU         6
>>> +#define HI6220_CFG_CSI4PHY     7
>>> +#define HI6220_CFG_CSI2PHY     8
>>> +#define HI6220_ISP_SCLK_GATE   9
>>> +#define HI6220_ISP_SCLK_GATE1  10
>>> +#define HI6220_ADE_CORE_GATE   11
>>> +#define HI6220_CODEC_VPU_GATE  12
>>> +#define HI6220_MED_SYSPLL      13
>>> +
>>> +/* mux clocks */
>>> +#define HI6220_1440_1200       20
>>> +#define HI6220_1000_1200       21
>>> +#define HI6220_1000_1440       22
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_CODEC_JPEG      30
>>> +#define HI6220_ISP_SCLK_SRC    31
>>> +#define HI6220_ISP_SCLK1       32
>>> +#define HI6220_ADE_CORE_SRC    33
>>> +#define HI6220_ADE_PIX_SRC     34
>>> +#define HI6220_G3D_CLK         35
>>> +#define HI6220_CODEC_VPU_SRC   36
>>> +
>>> +#define HI6220_MEDIA_NR_CLKS   40
>>> +
>>> +/* clk in power controller */
>>> +/* gate clocks */
>>> +#define HI6220_PLL_GPU_GATE    1
>>> +#define HI6220_PLL1_DDR_GATE   2
>>> +#define HI6220_PLL_DDR_GATE    3
>>> +#define HI6220_PLL_MEDIA_GATE  4
>>> +#define HI6220_PLL0_BBP_GATE   5
>>> +
>>> +/* divider clocks */
>>> +#define HI6220_DDRC_SRC                10
>>> +#define HI6220_DDRC_AXI1       11
>>> +
>>> +#define HI6220_POWER_NR_CLKS   16
>>> +#endif
>>> --
>>> 1.7.9.5
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>> Cheers,
>>
>> - Tyler
>>
>> [1] http://kernelci.org/build/tbaker/kernel/v3.19-rc7-8241-g7b08f7b75c01/
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
>
>
> --
> Best Regards,
>
> Bintian
> ===========================
> Don't be nervous, just be happy!

Cheers,

- Tyler

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-06  9:07         ` Marc Zyngier
  (?)
@ 2015-02-09  3:26           ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-09  3:26 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, dan.zhao, btw, Catalin Marinas, wangbinghui,
	Will Deacon, huxinwei, khilman, haojian.zhuang, yanhaifeng,
	rob.herring, mturquette, victor.lixin, xuwei5, jh80.chung,
	sledge.yanwei, kong.kongxinwei, heyunlei, w.f, zhangfei.gao,
	z.liuxinliang, devicetree, Bintian Wang, Pawel Moll,
	ijc+devicetree, puck.chen, olof, robh+dt, linux, zhenwei.wang,
	linux-arm-kernel, guodong.xu, tomeu.vizoso, sboyd, linux-kernel,
	galak, xuejiancheng, xuyiping, liguozhu

Hello Marc,

2015-02-06 17:07 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 06/02/15 08:42, Brent Wang wrote:
>
> [...]
>
>>>
>>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>>
>>> I guess no-one's bothered to consider 64k pages?
>>>
>>> Given GICH and GICV, I hope that this platform is booted at EL2?
>> Transfer from EL3 to EL1 directly, keep these two just for future use.
>
> That's a real shame, as it keeps users away from some key aspects of the
> ARMv8 architecture.
>
>>>
>>>> +             #interrupt-cells = <3>;
>>>> +             #address-cells = <0>;
>>>> +             interrupt-controller;
>
> And if you're keeping GICH/GICV, where is the maintenance interrupt?
>
>>>> +     };
>>>> +
>>>> +
>>>> +     timer {
>>>> +             compatible = "arm,armv8-timer";
>>>> +             interrupt-parent = <&gic>;
>>>> +             interrupts = <1 13 0xff08>,
>>>> +                          <1 14 0xff08>,
>>>> +                          <1 11 0xff08>,
>>>> +                          <1 10 0xff08>;
>>>> +             clock-frequency = <1200000>;
>>>> +     };
>>>
>>> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
>> Fix in next version, maybe it will take some time to change firmware.
>
> While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
> before dropping to EL1. This tends to be overlooked.
Thank you for reminding me, I will keep that in mind.

Thanks,

>
> Thanks,
>
>         M.
> --
> Jazz is not dead. It just smells funny...

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-09  3:26           ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-09  3:26 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, dan.zhao, btw, Catalin Marinas, wangbinghui,
	Will Deacon, huxinwei, khilman, haojian.zhuang, yanhaifeng,
	rob.herring, mturquette, victor.lixin, xuwei5, jh80.chung,
	sledge.yanwei, kong.kongxinwei, heyunlei

Hello Marc,

2015-02-06 17:07 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 06/02/15 08:42, Brent Wang wrote:
>
> [...]
>
>>>
>>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>>
>>> I guess no-one's bothered to consider 64k pages?
>>>
>>> Given GICH and GICV, I hope that this platform is booted at EL2?
>> Transfer from EL3 to EL1 directly, keep these two just for future use.
>
> That's a real shame, as it keeps users away from some key aspects of the
> ARMv8 architecture.
>
>>>
>>>> +             #interrupt-cells = <3>;
>>>> +             #address-cells = <0>;
>>>> +             interrupt-controller;
>
> And if you're keeping GICH/GICV, where is the maintenance interrupt?
>
>>>> +     };
>>>> +
>>>> +
>>>> +     timer {
>>>> +             compatible = "arm,armv8-timer";
>>>> +             interrupt-parent = <&gic>;
>>>> +             interrupts = <1 13 0xff08>,
>>>> +                          <1 14 0xff08>,
>>>> +                          <1 11 0xff08>,
>>>> +                          <1 10 0xff08>;
>>>> +             clock-frequency = <1200000>;
>>>> +     };
>>>
>>> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
>> Fix in next version, maybe it will take some time to change firmware.
>
> While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
> before dropping to EL1. This tends to be overlooked.
Thank you for reminding me, I will keep that in mind.

Thanks,

>
> Thanks,
>
>         M.
> --
> Jazz is not dead. It just smells funny...

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-09  3:26           ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-09  3:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Marc,

2015-02-06 17:07 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 06/02/15 08:42, Brent Wang wrote:
>
> [...]
>
>>>
>>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>>
>>> I guess no-one's bothered to consider 64k pages?
>>>
>>> Given GICH and GICV, I hope that this platform is booted at EL2?
>> Transfer from EL3 to EL1 directly, keep these two just for future use.
>
> That's a real shame, as it keeps users away from some key aspects of the
> ARMv8 architecture.
>
>>>
>>>> +             #interrupt-cells = <3>;
>>>> +             #address-cells = <0>;
>>>> +             interrupt-controller;
>
> And if you're keeping GICH/GICV, where is the maintenance interrupt?
>
>>>> +     };
>>>> +
>>>> +
>>>> +     timer {
>>>> +             compatible = "arm,armv8-timer";
>>>> +             interrupt-parent = <&gic>;
>>>> +             interrupts = <1 13 0xff08>,
>>>> +                          <1 14 0xff08>,
>>>> +                          <1 11 0xff08>,
>>>> +                          <1 10 0xff08>;
>>>> +             clock-frequency = <1200000>;
>>>> +     };
>>>
>>> NAK. Fix your firmware to configure CNTFRQ, on all CPUs.
>> Fix in next version, maybe it will take some time to change firmware.
>
> While you're at it, make sure CNTVOFF_EL2 is set to zero on all CPUs
> before dropping to EL1. This tends to be overlooked.
Thank you for reminding me, I will keep that in mind.

Thanks,

>
> Thanks,
>
>         M.
> --
> Jazz is not dead. It just smells funny...

-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 13:37             ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-10 13:37 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

On Fri, Feb 06, 2015 at 03:37:52PM +0000, Brent Wang wrote:
> Hello Mark,
> 
> 2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
> >> Hello Mark,
> >>
> >> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> >> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> >> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> >> >> support of Octal core CPUs in two clusters and each cluster
> >> >> has quard Cortex-A53.
> >> >>
> >> >> We now use the "spin-table" method for SMP, and it will be
> >> >> changed to PSCI later.
> >> >
> >> > If that's the case, please don't place the enable-method and related
> >> > properties in this file. Get your bootloader to add the appropriate
> >> > properties for its boot protocol.
> >> >
> >> > When is PSCI likely to appear?
> >> PSCI is under development.
> >
> > Sure. Do you have an estimate as to when it will appear?
> Another team will do the job, I can not give my estimation now.

Ok.

> > What are you using for your PSCI implementation? The ARM Trusted
> > Firmware?
> Yes, ATF.
> >
> > How are you testing it?
> I think cpu hotplug can test it.
> 
> >
> >> > Are we certain of the split between components the PSCI implementation
> >> > must touch and those the kernel must touch?
> >> >
> >> >> Also add dts file to support HiKey development board which
> >> >> based on Hi6220 SoC and document the devicetree bindings.
> >> >>
> >> >> These dts files will be changed later and more nodes will be
> >> >> added to describe other devices.
> >> >
> >> > How is this going to be changed other than the addition of nodes?
> >> >
> >> > Will this DTB continue to work in future? Or do you intend to make
> >> > changes that will break support?
> >> My original idea is: use spin-table for SMP now, when firmware is OK to
> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
> >
> > For any users who have not updated their FW, this will break booting.
> >
> > This is why I suggest having hte bootloader/FW fill this in as it should
> > know what enable-method the FW supports.
> >
> >> If DTB should continue to work in the future, we really need to remove
> >> the spin-table
> >> from current dts file, how about just enable one core now?
> >>
> >> Which one do you favor or any other suggestion?
> >
> > If spin-table is just for testing while you await PSCI, drop spin-table
> > from the dts for now.
> So, just booting one core may be the right choice now, right?

Without an enable-method for secondary CPUs, that will be all that's
possible. If your FW/bootlaoder injects the appropriate enable-method,
then you could gain spin-table based SMP bringup while awaiting PSCI,
without there being a DTB compatibility issue.

[...]

> >> >> +             pm_ctrl: pm_ctrl {
> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> >> +                     #address-cells = <1>;
> >> >> +                     #size-cells = <1>;
> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> >> +
> >> >> +                     clock_power: clock3@0 {
> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> >> +                             reg = <0 0x1000>;
> >> >> +                             #clock-cells = <1>;
> >> >> +                     };
> >> >> +             };
> >> >
> >> > I really doesn't see the point in having a sub-device that covers the
> >> > entirely of the register space of the containing node, and that being
> >> > the case I am extremely concerned that the containers are marked as
> >> > syscon compatible.
> >> The SoC clocks are designed and placed under different system controllers,
> >> so I define corresponding nodes under different controllers for clock operation.
> >
> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
> > sub-node have the _exact_ same register space.
> >
> > Given this should mean that the clock3@0 node owns that register space,
> > having the container node export this as syscon does not make sense. And
> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
> > they cover the same space.
> I understand your worry and will find the max offset of those clocks
> under this controller.
> 
> >
> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
> > point of the separate sub-node?
> There is no big difference between pm_ctrl and other controller,  they
> are all designed as
> the base address to control some functions of other modules (certainly
> include some clock gates).

Are they just different instances of the same IP block, or are there
fundamental differences between them?

> Maybe only one node is enough, not one node plus one sub-node ?

At least in the case above, I cannot see a reason to have more than a
single node without a child.

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 13:37             ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-10 13:37 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas,
	Will Deacon, devicetree-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Pawel Moll,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, khilman-QSEj5FYQhm4dnm+yROfE0A,
	mturquette-QSEj5FYQhm4dnm+yROfE0A,
	rob.herring-QSEj5FYQhm4dnm+yROfE0A,
	zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A,
	haojian.zhuang-QSEj5FYQhm4dnm+yROfE0A,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, jh80.chung-Sze3O3UU22JBDgjK7y7TUQ

On Fri, Feb 06, 2015 at 03:37:52PM +0000, Brent Wang wrote:
> Hello Mark,
> 
> 2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
> > On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
> >> Hello Mark,
> >>
> >> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
> >> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> >> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> >> >> support of Octal core CPUs in two clusters and each cluster
> >> >> has quard Cortex-A53.
> >> >>
> >> >> We now use the "spin-table" method for SMP, and it will be
> >> >> changed to PSCI later.
> >> >
> >> > If that's the case, please don't place the enable-method and related
> >> > properties in this file. Get your bootloader to add the appropriate
> >> > properties for its boot protocol.
> >> >
> >> > When is PSCI likely to appear?
> >> PSCI is under development.
> >
> > Sure. Do you have an estimate as to when it will appear?
> Another team will do the job, I can not give my estimation now.

Ok.

> > What are you using for your PSCI implementation? The ARM Trusted
> > Firmware?
> Yes, ATF.
> >
> > How are you testing it?
> I think cpu hotplug can test it.
> 
> >
> >> > Are we certain of the split between components the PSCI implementation
> >> > must touch and those the kernel must touch?
> >> >
> >> >> Also add dts file to support HiKey development board which
> >> >> based on Hi6220 SoC and document the devicetree bindings.
> >> >>
> >> >> These dts files will be changed later and more nodes will be
> >> >> added to describe other devices.
> >> >
> >> > How is this going to be changed other than the addition of nodes?
> >> >
> >> > Will this DTB continue to work in future? Or do you intend to make
> >> > changes that will break support?
> >> My original idea is: use spin-table for SMP now, when firmware is OK to
> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
> >
> > For any users who have not updated their FW, this will break booting.
> >
> > This is why I suggest having hte bootloader/FW fill this in as it should
> > know what enable-method the FW supports.
> >
> >> If DTB should continue to work in the future, we really need to remove
> >> the spin-table
> >> from current dts file, how about just enable one core now?
> >>
> >> Which one do you favor or any other suggestion?
> >
> > If spin-table is just for testing while you await PSCI, drop spin-table
> > from the dts for now.
> So, just booting one core may be the right choice now, right?

Without an enable-method for secondary CPUs, that will be all that's
possible. If your FW/bootlaoder injects the appropriate enable-method,
then you could gain spin-table based SMP bringup while awaiting PSCI,
without there being a DTB compatibility issue.

[...]

> >> >> +             pm_ctrl: pm_ctrl {
> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> >> +                     #address-cells = <1>;
> >> >> +                     #size-cells = <1>;
> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> >> +
> >> >> +                     clock_power: clock3@0 {
> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> >> +                             reg = <0 0x1000>;
> >> >> +                             #clock-cells = <1>;
> >> >> +                     };
> >> >> +             };
> >> >
> >> > I really doesn't see the point in having a sub-device that covers the
> >> > entirely of the register space of the containing node, and that being
> >> > the case I am extremely concerned that the containers are marked as
> >> > syscon compatible.
> >> The SoC clocks are designed and placed under different system controllers,
> >> so I define corresponding nodes under different controllers for clock operation.
> >
> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
> > sub-node have the _exact_ same register space.
> >
> > Given this should mean that the clock3@0 node owns that register space,
> > having the container node export this as syscon does not make sense. And
> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
> > they cover the same space.
> I understand your worry and will find the max offset of those clocks
> under this controller.
> 
> >
> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
> > point of the separate sub-node?
> There is no big difference between pm_ctrl and other controller,  they
> are all designed as
> the base address to control some functions of other modules (certainly
> include some clock gates).

Are they just different instances of the same IP block, or are there
fundamental differences between them?

> Maybe only one node is enough, not one node plus one sub-node ?

At least in the case above, I cannot see a reason to have more than a
single node without a child.

Thanks,
Mark.
--
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] 85+ messages in thread

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 13:37             ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-10 13:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 06, 2015 at 03:37:52PM +0000, Brent Wang wrote:
> Hello Mark,
> 
> 2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
> >> Hello Mark,
> >>
> >> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> >> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
> >> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
> >> >> support of Octal core CPUs in two clusters and each cluster
> >> >> has quard Cortex-A53.
> >> >>
> >> >> We now use the "spin-table" method for SMP, and it will be
> >> >> changed to PSCI later.
> >> >
> >> > If that's the case, please don't place the enable-method and related
> >> > properties in this file. Get your bootloader to add the appropriate
> >> > properties for its boot protocol.
> >> >
> >> > When is PSCI likely to appear?
> >> PSCI is under development.
> >
> > Sure. Do you have an estimate as to when it will appear?
> Another team will do the job, I can not give my estimation now.

Ok.

> > What are you using for your PSCI implementation? The ARM Trusted
> > Firmware?
> Yes, ATF.
> >
> > How are you testing it?
> I think cpu hotplug can test it.
> 
> >
> >> > Are we certain of the split between components the PSCI implementation
> >> > must touch and those the kernel must touch?
> >> >
> >> >> Also add dts file to support HiKey development board which
> >> >> based on Hi6220 SoC and document the devicetree bindings.
> >> >>
> >> >> These dts files will be changed later and more nodes will be
> >> >> added to describe other devices.
> >> >
> >> > How is this going to be changed other than the addition of nodes?
> >> >
> >> > Will this DTB continue to work in future? Or do you intend to make
> >> > changes that will break support?
> >> My original idea is: use spin-table for SMP now, when firmware is OK to
> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
> >
> > For any users who have not updated their FW, this will break booting.
> >
> > This is why I suggest having hte bootloader/FW fill this in as it should
> > know what enable-method the FW supports.
> >
> >> If DTB should continue to work in the future, we really need to remove
> >> the spin-table
> >> from current dts file, how about just enable one core now?
> >>
> >> Which one do you favor or any other suggestion?
> >
> > If spin-table is just for testing while you await PSCI, drop spin-table
> > from the dts for now.
> So, just booting one core may be the right choice now, right?

Without an enable-method for secondary CPUs, that will be all that's
possible. If your FW/bootlaoder injects the appropriate enable-method,
then you could gain spin-table based SMP bringup while awaiting PSCI,
without there being a DTB compatibility issue.

[...]

> >> >> +             pm_ctrl: pm_ctrl {
> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> >> +                     #address-cells = <1>;
> >> >> +                     #size-cells = <1>;
> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> >> +
> >> >> +                     clock_power: clock3 at 0 {
> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> >> +                             reg = <0 0x1000>;
> >> >> +                             #clock-cells = <1>;
> >> >> +                     };
> >> >> +             };
> >> >
> >> > I really doesn't see the point in having a sub-device that covers the
> >> > entirely of the register space of the containing node, and that being
> >> > the case I am extremely concerned that the containers are marked as
> >> > syscon compatible.
> >> The SoC clocks are designed and placed under different system controllers,
> >> so I define corresponding nodes under different controllers for clock operation.
> >
> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3 at 0
> > sub-node have the _exact_ same register space.
> >
> > Given this should mean that the clock3 at 0 node owns that register space,
> > having the container node export this as syscon does not make sense. And
> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
> > they cover the same space.
> I understand your worry and will find the max offset of those clocks
> under this controller.
> 
> >
> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
> > point of the separate sub-node?
> There is no big difference between pm_ctrl and other controller,  they
> are all designed as
> the base address to control some functions of other modules (certainly
> include some clock gates).

Are they just different instances of the same IP block, or are there
fundamental differences between them?

> Maybe only one node is enough, not one node plus one sub-node ?

At least in the case above, I cannot see a reason to have more than a
single node without a child.

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-10 13:37             ` Mark Rutland
  (?)
@ 2015-02-10 14:20               ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-10 14:20 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

Hello Mark,

2015-02-10 21:37 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Fri, Feb 06, 2015 at 03:37:52PM +0000, Brent Wang wrote:
>> Hello Mark,
>>
>> 2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> > On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
>> >> Hello Mark,
>> >>
>> >> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> >> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> >> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> >> >> support of Octal core CPUs in two clusters and each cluster
>> >> >> has quard Cortex-A53.
>> >> >>
>> >> >> We now use the "spin-table" method for SMP, and it will be
>> >> >> changed to PSCI later.
>> >> >
>> >> > If that's the case, please don't place the enable-method and related
>> >> > properties in this file. Get your bootloader to add the appropriate
>> >> > properties for its boot protocol.
>> >> >
>> >> > When is PSCI likely to appear?
>> >> PSCI is under development.
>> >
>> > Sure. Do you have an estimate as to when it will appear?
>> Another team will do the job, I can not give my estimation now.
>
> Ok.
>
>> > What are you using for your PSCI implementation? The ARM Trusted
>> > Firmware?
>> Yes, ATF.
>> >
>> > How are you testing it?
>> I think cpu hotplug can test it.
>>
>> >
>> >> > Are we certain of the split between components the PSCI implementation
>> >> > must touch and those the kernel must touch?
>> >> >
>> >> >> Also add dts file to support HiKey development board which
>> >> >> based on Hi6220 SoC and document the devicetree bindings.
>> >> >>
>> >> >> These dts files will be changed later and more nodes will be
>> >> >> added to describe other devices.
>> >> >
>> >> > How is this going to be changed other than the addition of nodes?
>> >> >
>> >> > Will this DTB continue to work in future? Or do you intend to make
>> >> > changes that will break support?
>> >> My original idea is: use spin-table for SMP now, when firmware is OK to
>> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
>> >
>> > For any users who have not updated their FW, this will break booting.
>> >
>> > This is why I suggest having hte bootloader/FW fill this in as it should
>> > know what enable-method the FW supports.
>> >
>> >> If DTB should continue to work in the future, we really need to remove
>> >> the spin-table
>> >> from current dts file, how about just enable one core now?
>> >>
>> >> Which one do you favor or any other suggestion?
>> >
>> > If spin-table is just for testing while you await PSCI, drop spin-table
>> > from the dts for now.
>> So, just booting one core may be the right choice now, right?
>
> Without an enable-method for secondary CPUs, that will be all that's
> possible. If your FW/bootlaoder injects the appropriate enable-method,
> then you could gain spin-table based SMP bringup while awaiting PSCI,
> without there being a DTB compatibility issue.
For DTB compatibility issue, how about just describe one core in dts
file? when PSCI
is OK, we can add the CPU topology to the dts file again.

>
> [...]
>
>> >> >> +             pm_ctrl: pm_ctrl {
>> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> >> +                     #address-cells = <1>;
>> >> >> +                     #size-cells = <1>;
>> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> >> +
>> >> >> +                     clock_power: clock3@0 {
>> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> >> +                             reg = <0 0x1000>;
>> >> >> +                             #clock-cells = <1>;
>> >> >> +                     };
>> >> >> +             };
>> >> >
>> >> > I really doesn't see the point in having a sub-device that covers the
>> >> > entirely of the register space of the containing node, and that being
>> >> > the case I am extremely concerned that the containers are marked as
>> >> > syscon compatible.
>> >> The SoC clocks are designed and placed under different system controllers,
>> >> so I define corresponding nodes under different controllers for clock operation.
>> >
>> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
>> > sub-node have the _exact_ same register space.
>> >
>> > Given this should mean that the clock3@0 node owns that register space,
>> > having the container node export this as syscon does not make sense. And
>> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
>> > they cover the same space.
>> I understand your worry and will find the max offset of those clocks
>> under this controller.
>>
>> >
>> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
>> > point of the separate sub-node?
>> There is no big difference between pm_ctrl and other controller,  they
>> are all designed as
>> the base address to control some functions of other modules (certainly
>> include some clock gates).
>
> Are they just different instances of the same IP block, or are there
> fundamental differences between them?
You can understand it as a different instance of the same IP block,
there is no fundamental
differences between them.

>
>> Maybe only one node is enough, not one node plus one sub-node ?
>
> At least in the case above, I cannot see a reason to have more than a
> single node without a child.
I will fix to one node in next version.

Thank you Mark,

BR,

Bintian

>
> Thanks,
> Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 14:20               ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-10 14:20 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung

Hello Mark,

2015-02-10 21:37 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Fri, Feb 06, 2015 at 03:37:52PM +0000, Brent Wang wrote:
>> Hello Mark,
>>
>> 2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> > On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
>> >> Hello Mark,
>> >>
>> >> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> >> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> >> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> >> >> support of Octal core CPUs in two clusters and each cluster
>> >> >> has quard Cortex-A53.
>> >> >>
>> >> >> We now use the "spin-table" method for SMP, and it will be
>> >> >> changed to PSCI later.
>> >> >
>> >> > If that's the case, please don't place the enable-method and related
>> >> > properties in this file. Get your bootloader to add the appropriate
>> >> > properties for its boot protocol.
>> >> >
>> >> > When is PSCI likely to appear?
>> >> PSCI is under development.
>> >
>> > Sure. Do you have an estimate as to when it will appear?
>> Another team will do the job, I can not give my estimation now.
>
> Ok.
>
>> > What are you using for your PSCI implementation? The ARM Trusted
>> > Firmware?
>> Yes, ATF.
>> >
>> > How are you testing it?
>> I think cpu hotplug can test it.
>>
>> >
>> >> > Are we certain of the split between components the PSCI implementation
>> >> > must touch and those the kernel must touch?
>> >> >
>> >> >> Also add dts file to support HiKey development board which
>> >> >> based on Hi6220 SoC and document the devicetree bindings.
>> >> >>
>> >> >> These dts files will be changed later and more nodes will be
>> >> >> added to describe other devices.
>> >> >
>> >> > How is this going to be changed other than the addition of nodes?
>> >> >
>> >> > Will this DTB continue to work in future? Or do you intend to make
>> >> > changes that will break support?
>> >> My original idea is: use spin-table for SMP now, when firmware is OK to
>> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
>> >
>> > For any users who have not updated their FW, this will break booting.
>> >
>> > This is why I suggest having hte bootloader/FW fill this in as it should
>> > know what enable-method the FW supports.
>> >
>> >> If DTB should continue to work in the future, we really need to remove
>> >> the spin-table
>> >> from current dts file, how about just enable one core now?
>> >>
>> >> Which one do you favor or any other suggestion?
>> >
>> > If spin-table is just for testing while you await PSCI, drop spin-table
>> > from the dts for now.
>> So, just booting one core may be the right choice now, right?
>
> Without an enable-method for secondary CPUs, that will be all that's
> possible. If your FW/bootlaoder injects the appropriate enable-method,
> then you could gain spin-table based SMP bringup while awaiting PSCI,
> without there being a DTB compatibility issue.
For DTB compatibility issue, how about just describe one core in dts
file? when PSCI
is OK, we can add the CPU topology to the dts file again.

>
> [...]
>
>> >> >> +             pm_ctrl: pm_ctrl {
>> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> >> +                     #address-cells = <1>;
>> >> >> +                     #size-cells = <1>;
>> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> >> +
>> >> >> +                     clock_power: clock3@0 {
>> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> >> +                             reg = <0 0x1000>;
>> >> >> +                             #clock-cells = <1>;
>> >> >> +                     };
>> >> >> +             };
>> >> >
>> >> > I really doesn't see the point in having a sub-device that covers the
>> >> > entirely of the register space of the containing node, and that being
>> >> > the case I am extremely concerned that the containers are marked as
>> >> > syscon compatible.
>> >> The SoC clocks are designed and placed under different system controllers,
>> >> so I define corresponding nodes under different controllers for clock operation.
>> >
>> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
>> > sub-node have the _exact_ same register space.
>> >
>> > Given this should mean that the clock3@0 node owns that register space,
>> > having the container node export this as syscon does not make sense. And
>> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
>> > they cover the same space.
>> I understand your worry and will find the max offset of those clocks
>> under this controller.
>>
>> >
>> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
>> > point of the separate sub-node?
>> There is no big difference between pm_ctrl and other controller,  they
>> are all designed as
>> the base address to control some functions of other modules (certainly
>> include some clock gates).
>
> Are they just different instances of the same IP block, or are there
> fundamental differences between them?
You can understand it as a different instance of the same IP block,
there is no fundamental
differences between them.

>
>> Maybe only one node is enough, not one node plus one sub-node ?
>
> At least in the case above, I cannot see a reason to have more than a
> single node without a child.
I will fix to one node in next version.

Thank you Mark,

BR,

Bintian

>
> Thanks,
> Mark.

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 14:20               ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-10 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Mark,

2015-02-10 21:37 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Fri, Feb 06, 2015 at 03:37:52PM +0000, Brent Wang wrote:
>> Hello Mark,
>>
>> 2015-02-06 18:44 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> > On Fri, Feb 06, 2015 at 08:42:22AM +0000, Brent Wang wrote:
>> >> Hello Mark,
>> >>
>> >> 2015-02-06 3:30 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> >> > On Thu, Feb 05, 2015 at 09:24:37AM +0000, Bintian Wang wrote:
>> >> >> Add initial dtsi file to support Hisilicon Hi6220 SoC with
>> >> >> support of Octal core CPUs in two clusters and each cluster
>> >> >> has quard Cortex-A53.
>> >> >>
>> >> >> We now use the "spin-table" method for SMP, and it will be
>> >> >> changed to PSCI later.
>> >> >
>> >> > If that's the case, please don't place the enable-method and related
>> >> > properties in this file. Get your bootloader to add the appropriate
>> >> > properties for its boot protocol.
>> >> >
>> >> > When is PSCI likely to appear?
>> >> PSCI is under development.
>> >
>> > Sure. Do you have an estimate as to when it will appear?
>> Another team will do the job, I can not give my estimation now.
>
> Ok.
>
>> > What are you using for your PSCI implementation? The ARM Trusted
>> > Firmware?
>> Yes, ATF.
>> >
>> > How are you testing it?
>> I think cpu hotplug can test it.
>>
>> >
>> >> > Are we certain of the split between components the PSCI implementation
>> >> > must touch and those the kernel must touch?
>> >> >
>> >> >> Also add dts file to support HiKey development board which
>> >> >> based on Hi6220 SoC and document the devicetree bindings.
>> >> >>
>> >> >> These dts files will be changed later and more nodes will be
>> >> >> added to describe other devices.
>> >> >
>> >> > How is this going to be changed other than the addition of nodes?
>> >> >
>> >> > Will this DTB continue to work in future? Or do you intend to make
>> >> > changes that will break support?
>> >> My original idea is: use spin-table for SMP now, when firmware is OK to
>> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
>> >
>> > For any users who have not updated their FW, this will break booting.
>> >
>> > This is why I suggest having hte bootloader/FW fill this in as it should
>> > know what enable-method the FW supports.
>> >
>> >> If DTB should continue to work in the future, we really need to remove
>> >> the spin-table
>> >> from current dts file, how about just enable one core now?
>> >>
>> >> Which one do you favor or any other suggestion?
>> >
>> > If spin-table is just for testing while you await PSCI, drop spin-table
>> > from the dts for now.
>> So, just booting one core may be the right choice now, right?
>
> Without an enable-method for secondary CPUs, that will be all that's
> possible. If your FW/bootlaoder injects the appropriate enable-method,
> then you could gain spin-table based SMP bringup while awaiting PSCI,
> without there being a DTB compatibility issue.
For DTB compatibility issue, how about just describe one core in dts
file? when PSCI
is OK, we can add the CPU topology to the dts file again.

>
> [...]
>
>> >> >> +             pm_ctrl: pm_ctrl {
>> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> >> +                     #address-cells = <1>;
>> >> >> +                     #size-cells = <1>;
>> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> >> +
>> >> >> +                     clock_power: clock3 at 0 {
>> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> >> +                             reg = <0 0x1000>;
>> >> >> +                             #clock-cells = <1>;
>> >> >> +                     };
>> >> >> +             };
>> >> >
>> >> > I really doesn't see the point in having a sub-device that covers the
>> >> > entirely of the register space of the containing node, and that being
>> >> > the case I am extremely concerned that the containers are marked as
>> >> > syscon compatible.
>> >> The SoC clocks are designed and placed under different system controllers,
>> >> so I define corresponding nodes under different controllers for clock operation.
>> >
>> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3 at 0
>> > sub-node have the _exact_ same register space.
>> >
>> > Given this should mean that the clock3 at 0 node owns that register space,
>> > having the container node export this as syscon does not make sense. And
>> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
>> > they cover the same space.
>> I understand your worry and will find the max offset of those clocks
>> under this controller.
>>
>> >
>> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
>> > point of the separate sub-node?
>> There is no big difference between pm_ctrl and other controller,  they
>> are all designed as
>> the base address to control some functions of other modules (certainly
>> include some clock gates).
>
> Are they just different instances of the same IP block, or are there
> fundamental differences between them?
You can understand it as a different instance of the same IP block,
there is no fundamental
differences between them.

>
>> Maybe only one node is enough, not one node plus one sub-node ?
>
> At least in the case above, I cannot see a reason to have more than a
> single node without a child.
I will fix to one node in next version.

Thank you Mark,

BR,

Bintian

>
> Thanks,
> Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-10 14:20               ` Brent Wang
  (?)
@ 2015-02-10 15:27                 ` Mark Rutland
  -1 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-10 15:27 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

> >> >> > Are we certain of the split between components the PSCI implementation
> >> >> > must touch and those the kernel must touch?
> >> >> >
> >> >> >> Also add dts file to support HiKey development board which
> >> >> >> based on Hi6220 SoC and document the devicetree bindings.
> >> >> >>
> >> >> >> These dts files will be changed later and more nodes will be
> >> >> >> added to describe other devices.
> >> >> >
> >> >> > How is this going to be changed other than the addition of nodes?
> >> >> >
> >> >> > Will this DTB continue to work in future? Or do you intend to make
> >> >> > changes that will break support?
> >> >> My original idea is: use spin-table for SMP now, when firmware is OK to
> >> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
> >> >
> >> > For any users who have not updated their FW, this will break booting.
> >> >
> >> > This is why I suggest having hte bootloader/FW fill this in as it should
> >> > know what enable-method the FW supports.
> >> >
> >> >> If DTB should continue to work in the future, we really need to remove
> >> >> the spin-table
> >> >> from current dts file, how about just enable one core now?
> >> >>
> >> >> Which one do you favor or any other suggestion?
> >> >
> >> > If spin-table is just for testing while you await PSCI, drop spin-table
> >> > from the dts for now.
> >> So, just booting one core may be the right choice now, right?
> >
> > Without an enable-method for secondary CPUs, that will be all that's
> > possible. If your FW/bootlaoder injects the appropriate enable-method,
> > then you could gain spin-table based SMP bringup while awaiting PSCI,
> > without there being a DTB compatibility issue.
> For DTB compatibility issue, how about just describe one core in dts
> file? when PSCI
> is OK, we can add the CPU topology to the dts file again.

Given that we won't boot secondary CPUs without an enable-method, we
could leave them in, but in a currently-unusable state. That would allow
a bootloader to patch in the relevant properties to boot them.

If you add the nodes later with PSCI properties, users with existing
firmware will expect their board to boot. So I'd recommendd that the
bootloader patches that in, or that the firmware is ready prior to this
being merged. I suspect that the former is more likely to be possible.

> > [...]
> >
> >> >> >> +             pm_ctrl: pm_ctrl {
> >> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> >> >> +                     #address-cells = <1>;
> >> >> >> +                     #size-cells = <1>;
> >> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> >> >> +
> >> >> >> +                     clock_power: clock3@0 {
> >> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> >> >> +                             reg = <0 0x1000>;
> >> >> >> +                             #clock-cells = <1>;
> >> >> >> +                     };
> >> >> >> +             };
> >> >> >
> >> >> > I really doesn't see the point in having a sub-device that covers the
> >> >> > entirely of the register space of the containing node, and that being
> >> >> > the case I am extremely concerned that the containers are marked as
> >> >> > syscon compatible.
> >> >> The SoC clocks are designed and placed under different system controllers,
> >> >> so I define corresponding nodes under different controllers for clock operation.
> >> >
> >> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
> >> > sub-node have the _exact_ same register space.
> >> >
> >> > Given this should mean that the clock3@0 node owns that register space,
> >> > having the container node export this as syscon does not make sense. And
> >> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
> >> > they cover the same space.
> >> I understand your worry and will find the max offset of those clocks
> >> under this controller.
> >>
> >> >
> >> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
> >> > point of the separate sub-node?
> >> There is no big difference between pm_ctrl and other controller,  they
> >> are all designed as
> >> the base address to control some functions of other modules (certainly
> >> include some clock gates).
> >
> > Are they just different instances of the same IP block, or are there
> > fundamental differences between them?
> You can understand it as a different instance of the same IP block,
> there is no fundamental
> differences between them.

Ok. If that's the case each should have the same compatible string.

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 15:27                 ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-10 15:27 UTC (permalink / raw)
  To: Brent Wang
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung

> >> >> > Are we certain of the split between components the PSCI implementation
> >> >> > must touch and those the kernel must touch?
> >> >> >
> >> >> >> Also add dts file to support HiKey development board which
> >> >> >> based on Hi6220 SoC and document the devicetree bindings.
> >> >> >>
> >> >> >> These dts files will be changed later and more nodes will be
> >> >> >> added to describe other devices.
> >> >> >
> >> >> > How is this going to be changed other than the addition of nodes?
> >> >> >
> >> >> > Will this DTB continue to work in future? Or do you intend to make
> >> >> > changes that will break support?
> >> >> My original idea is: use spin-table for SMP now, when firmware is OK to
> >> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
> >> >
> >> > For any users who have not updated their FW, this will break booting.
> >> >
> >> > This is why I suggest having hte bootloader/FW fill this in as it should
> >> > know what enable-method the FW supports.
> >> >
> >> >> If DTB should continue to work in the future, we really need to remove
> >> >> the spin-table
> >> >> from current dts file, how about just enable one core now?
> >> >>
> >> >> Which one do you favor or any other suggestion?
> >> >
> >> > If spin-table is just for testing while you await PSCI, drop spin-table
> >> > from the dts for now.
> >> So, just booting one core may be the right choice now, right?
> >
> > Without an enable-method for secondary CPUs, that will be all that's
> > possible. If your FW/bootlaoder injects the appropriate enable-method,
> > then you could gain spin-table based SMP bringup while awaiting PSCI,
> > without there being a DTB compatibility issue.
> For DTB compatibility issue, how about just describe one core in dts
> file? when PSCI
> is OK, we can add the CPU topology to the dts file again.

Given that we won't boot secondary CPUs without an enable-method, we
could leave them in, but in a currently-unusable state. That would allow
a bootloader to patch in the relevant properties to boot them.

If you add the nodes later with PSCI properties, users with existing
firmware will expect their board to boot. So I'd recommendd that the
bootloader patches that in, or that the firmware is ready prior to this
being merged. I suspect that the former is more likely to be possible.

> > [...]
> >
> >> >> >> +             pm_ctrl: pm_ctrl {
> >> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> >> >> +                     #address-cells = <1>;
> >> >> >> +                     #size-cells = <1>;
> >> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> >> >> +
> >> >> >> +                     clock_power: clock3@0 {
> >> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> >> >> +                             reg = <0 0x1000>;
> >> >> >> +                             #clock-cells = <1>;
> >> >> >> +                     };
> >> >> >> +             };
> >> >> >
> >> >> > I really doesn't see the point in having a sub-device that covers the
> >> >> > entirely of the register space of the containing node, and that being
> >> >> > the case I am extremely concerned that the containers are marked as
> >> >> > syscon compatible.
> >> >> The SoC clocks are designed and placed under different system controllers,
> >> >> so I define corresponding nodes under different controllers for clock operation.
> >> >
> >> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
> >> > sub-node have the _exact_ same register space.
> >> >
> >> > Given this should mean that the clock3@0 node owns that register space,
> >> > having the container node export this as syscon does not make sense. And
> >> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
> >> > they cover the same space.
> >> I understand your worry and will find the max offset of those clocks
> >> under this controller.
> >>
> >> >
> >> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
> >> > point of the separate sub-node?
> >> There is no big difference between pm_ctrl and other controller,  they
> >> are all designed as
> >> the base address to control some functions of other modules (certainly
> >> include some clock gates).
> >
> > Are they just different instances of the same IP block, or are there
> > fundamental differences between them?
> You can understand it as a different instance of the same IP block,
> there is no fundamental
> differences between them.

Ok. If that's the case each should have the same compatible string.

Thanks,
Mark.

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-10 15:27                 ` Mark Rutland
  0 siblings, 0 replies; 85+ messages in thread
From: Mark Rutland @ 2015-02-10 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

> >> >> > Are we certain of the split between components the PSCI implementation
> >> >> > must touch and those the kernel must touch?
> >> >> >
> >> >> >> Also add dts file to support HiKey development board which
> >> >> >> based on Hi6220 SoC and document the devicetree bindings.
> >> >> >>
> >> >> >> These dts files will be changed later and more nodes will be
> >> >> >> added to describe other devices.
> >> >> >
> >> >> > How is this going to be changed other than the addition of nodes?
> >> >> >
> >> >> > Will this DTB continue to work in future? Or do you intend to make
> >> >> > changes that will break support?
> >> >> My original idea is: use spin-table for SMP now, when firmware is OK to
> >> >> support PSCI, we submit another patch to replace the spin-table with PSCI.
> >> >
> >> > For any users who have not updated their FW, this will break booting.
> >> >
> >> > This is why I suggest having hte bootloader/FW fill this in as it should
> >> > know what enable-method the FW supports.
> >> >
> >> >> If DTB should continue to work in the future, we really need to remove
> >> >> the spin-table
> >> >> from current dts file, how about just enable one core now?
> >> >>
> >> >> Which one do you favor or any other suggestion?
> >> >
> >> > If spin-table is just for testing while you await PSCI, drop spin-table
> >> > from the dts for now.
> >> So, just booting one core may be the right choice now, right?
> >
> > Without an enable-method for secondary CPUs, that will be all that's
> > possible. If your FW/bootlaoder injects the appropriate enable-method,
> > then you could gain spin-table based SMP bringup while awaiting PSCI,
> > without there being a DTB compatibility issue.
> For DTB compatibility issue, how about just describe one core in dts
> file? when PSCI
> is OK, we can add the CPU topology to the dts file again.

Given that we won't boot secondary CPUs without an enable-method, we
could leave them in, but in a currently-unusable state. That would allow
a bootloader to patch in the relevant properties to boot them.

If you add the nodes later with PSCI properties, users with existing
firmware will expect their board to boot. So I'd recommendd that the
bootloader patches that in, or that the firmware is ready prior to this
being merged. I suspect that the former is more likely to be possible.

> > [...]
> >
> >> >> >> +             pm_ctrl: pm_ctrl {
> >> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
> >> >> >> +                     #address-cells = <1>;
> >> >> >> +                     #size-cells = <1>;
> >> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
> >> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
> >> >> >> +
> >> >> >> +                     clock_power: clock3 at 0 {
> >> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
> >> >> >> +                             reg = <0 0x1000>;
> >> >> >> +                             #clock-cells = <1>;
> >> >> >> +                     };
> >> >> >> +             };
> >> >> >
> >> >> > I really doesn't see the point in having a sub-device that covers the
> >> >> > entirely of the register space of the containing node, and that being
> >> >> > the case I am extremely concerned that the containers are marked as
> >> >> > syscon compatible.
> >> >> The SoC clocks are designed and placed under different system controllers,
> >> >> so I define corresponding nodes under different controllers for clock operation.
> >> >
> >> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3 at 0
> >> > sub-node have the _exact_ same register space.
> >> >
> >> > Given this should mean that the clock3 at 0 node owns that register space,
> >> > having the container node export this as syscon does not make sense. And
> >> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
> >> > they cover the same space.
> >> I understand your worry and will find the max offset of those clocks
> >> under this controller.
> >>
> >> >
> >> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
> >> > point of the separate sub-node?
> >> There is no big difference between pm_ctrl and other controller,  they
> >> are all designed as
> >> the base address to control some functions of other modules (certainly
> >> include some clock gates).
> >
> > Are they just different instances of the same IP block, or are there
> > fundamental differences between them?
> You can understand it as a different instance of the same IP block,
> there is no fundamental
> differences between them.

Ok. If that's the case each should have the same compatible string.

Thanks,
Mark.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-10 15:27                 ` Mark Rutland
  (?)
@ 2015-02-11  1:49                   ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-11  1:49 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

Hello Mark,

2015-02-10 23:27 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
 [...]
>> >
>> >> >> >> +             pm_ctrl: pm_ctrl {
>> >> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> >> >> +                     #address-cells = <1>;
>> >> >> >> +                     #size-cells = <1>;
>> >> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> >> >> +
>> >> >> >> +                     clock_power: clock3@0 {
>> >> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> >> >> +                             reg = <0 0x1000>;
>> >> >> >> +                             #clock-cells = <1>;
>> >> >> >> +                     };
>> >> >> >> +             };
>> >> >> >
>> >> >> > I really doesn't see the point in having a sub-device that covers the
>> >> >> > entirely of the register space of the containing node, and that being
>> >> >> > the case I am extremely concerned that the containers are marked as
>> >> >> > syscon compatible.
>> >> >> The SoC clocks are designed and placed under different system controllers,
>> >> >> so I define corresponding nodes under different controllers for clock operation.
>> >> >
>> >> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
>> >> > sub-node have the _exact_ same register space.
>> >> >
>> >> > Given this should mean that the clock3@0 node owns that register space,
>> >> > having the container node export this as syscon does not make sense. And
>> >> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
>> >> > they cover the same space.
>> >> I understand your worry and will find the max offset of those clocks
>> >> under this controller.
>> >>
>> >> >
>> >> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
>> >> > point of the separate sub-node?
>> >> There is no big difference between pm_ctrl and other controller,  they
>> >> are all designed as
>> >> the base address to control some functions of other modules (certainly
>> >> include some clock gates).
>> >
>> > Are they just different instances of the same IP block, or are there
>> > fundamental differences between them?
>> You can understand it as a different instance of the same IP block,
>> there is no fundamental
>> differences between them.
>
> Ok. If that's the case each should have the same compatible string.
Although they have same function, they control different domain, I
should use different compatible string to distinguish different
domains.

Thanks,

Bintian
>
> Thanks,
> Mark.



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-11  1:49                   ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-11  1:49 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung

Hello Mark,

2015-02-10 23:27 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
 [...]
>> >
>> >> >> >> +             pm_ctrl: pm_ctrl {
>> >> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> >> >> +                     #address-cells = <1>;
>> >> >> >> +                     #size-cells = <1>;
>> >> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> >> >> +
>> >> >> >> +                     clock_power: clock3@0 {
>> >> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> >> >> +                             reg = <0 0x1000>;
>> >> >> >> +                             #clock-cells = <1>;
>> >> >> >> +                     };
>> >> >> >> +             };
>> >> >> >
>> >> >> > I really doesn't see the point in having a sub-device that covers the
>> >> >> > entirely of the register space of the containing node, and that being
>> >> >> > the case I am extremely concerned that the containers are marked as
>> >> >> > syscon compatible.
>> >> >> The SoC clocks are designed and placed under different system controllers,
>> >> >> so I define corresponding nodes under different controllers for clock operation.
>> >> >
>> >> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3@0
>> >> > sub-node have the _exact_ same register space.
>> >> >
>> >> > Given this should mean that the clock3@0 node owns that register space,
>> >> > having the container node export this as syscon does not make sense. And
>> >> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
>> >> > they cover the same space.
>> >> I understand your worry and will find the max offset of those clocks
>> >> under this controller.
>> >>
>> >> >
>> >> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
>> >> > point of the separate sub-node?
>> >> There is no big difference between pm_ctrl and other controller,  they
>> >> are all designed as
>> >> the base address to control some functions of other modules (certainly
>> >> include some clock gates).
>> >
>> > Are they just different instances of the same IP block, or are there
>> > fundamental differences between them?
>> You can understand it as a different instance of the same IP block,
>> there is no fundamental
>> differences between them.
>
> Ok. If that's the case each should have the same compatible string.
Although they have same function, they control different domain, I
should use different compatible string to distinguish different
domains.

Thanks,

Bintian
>
> Thanks,
> Mark.



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-02-11  1:49                   ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-02-11  1:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Mark,

2015-02-10 23:27 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
 [...]
>> >
>> >> >> >> +             pm_ctrl: pm_ctrl {
>> >> >> >> +                     compatible = "hisilicon,pmctrl", "syscon";
>> >> >> >> +                     #address-cells = <1>;
>> >> >> >> +                     #size-cells = <1>;
>> >> >> >> +                     reg = <0x0 0xf7032000 0x0 0x1000>;
>> >> >> >> +                     ranges = <0 0x0 0xf7032000 0x1000>;
>> >> >> >> +
>> >> >> >> +                     clock_power: clock3 at 0 {
>> >> >> >> +                             compatible = "hisilicon,hi6220-clock-power";
>> >> >> >> +                             reg = <0 0x1000>;
>> >> >> >> +                             #clock-cells = <1>;
>> >> >> >> +                     };
>> >> >> >> +             };
>> >> >> >
>> >> >> > I really doesn't see the point in having a sub-device that covers the
>> >> >> > entirely of the register space of the containing node, and that being
>> >> >> > the case I am extremely concerned that the containers are marked as
>> >> >> > syscon compatible.
>> >> >> The SoC clocks are designed and placed under different system controllers,
>> >> >> so I define corresponding nodes under different controllers for clock operation.
>> >> >
>> >> > What I'm concerned wit hhere is that the pm_ctrl node and the clock3 at 0
>> >> > sub-node have the _exact_ same register space.
>> >> >
>> >> > Given this should mean that the clock3 at 0 node owns that register space,
>> >> > having the container node export this as syscon does not make sense. And
>> >> > the split between pm_ctrl and clock3@) doesn't seem to make sense given
>> >> > they cover the same space.
>> >> I understand your worry and will find the max offset of those clocks
>> >> under this controller.
>> >>
>> >> >
>> >> > As I asked before, why is pm_ctrl marked as a syscon, and what's the
>> >> > point of the separate sub-node?
>> >> There is no big difference between pm_ctrl and other controller,  they
>> >> are all designed as
>> >> the base address to control some functions of other modules (certainly
>> >> include some clock gates).
>> >
>> > Are they just different instances of the same IP block, or are there
>> > fundamental differences between them?
>> You can understand it as a different instance of the same IP block,
>> there is no fundamental
>> differences between them.
>
> Ok. If that's the case each should have the same compatible string.
Although they have same function, they control different domain, I
should use different compatible string to distinguish different
domains.

Thanks,

Bintian
>
> Thanks,
> Mark.



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-02-06  8:42       ` Brent Wang
  (?)
@ 2015-04-12  6:40         ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-04-12  6:40 UTC (permalink / raw)
  To: Mark Rutland, Marc Zyngier
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung, olof, yanhaifeng, sboyd,
	xuejiancheng, sledge.yanwei, tomeu.vizoso, linux, guodong.xu,
	xuyiping, wangbinghui, zhenwei.wang, victor.lixin, puck.chen,
	dan.zhao, huxinwei, z.liuxinliang, heyunlei, kong.kongxinwei,
	btw, w.f, liguozhu

Hello Mark,

2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
[...]
>>
>>> +     gic: interrupt-controller@f6800000 {
>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>
>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
>> am I missing?
> Remove it in next version.
After remove "arm,cortex-a15-gic", I get the following error during
kernel booting:
-----
kvm [1]: Using HYP init bounce page @396d9000
kvm [1]: error: no compatible GIC node found
kvm [1]: error initializing Hyp mode: -19
-----

Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
gicv3 support kvm now,
so I think we should keep it, how about your idea?

Thanks,

Bintian

>>
>>> +             reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
>>
>> This doesn't match the unit-address.
> Do you mean change to "<0x0 0xf6801000 0 0x1000>" ?
>
>>
>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>
>> I guess no-one's bothered to consider 64k pages?
>>
>> Given GICH and GICV, I hope that this platform is booted at EL2?
> Transfer from EL3 to EL1 directly, keep these two just for future use.
>
>>
>>> +             #interrupt-cells = <3>;
>>> +             #address-cells = <0>;
>>> +             interrupt-controller;
>>> +     };
>>> +
>>> +
[...]

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-04-12  6:40         ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-04-12  6:40 UTC (permalink / raw)
  To: Mark Rutland, Marc Zyngier
  Cc: Bintian Wang, linux-arm-kernel, linux-kernel, Catalin Marinas,
	Will Deacon, devicetree, robh+dt, Pawel Moll, ijc+devicetree,
	galak, khilman, mturquette, rob.herring, zhangfei.gao,
	haojian.zhuang, xuwei5, jh80.chung

Hello Mark,

2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
[...]
>>
>>> +     gic: interrupt-controller@f6800000 {
>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>
>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
>> am I missing?
> Remove it in next version.
After remove "arm,cortex-a15-gic", I get the following error during
kernel booting:
-----
kvm [1]: Using HYP init bounce page @396d9000
kvm [1]: error: no compatible GIC node found
kvm [1]: error initializing Hyp mode: -19
-----

Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
gicv3 support kvm now,
so I think we should keep it, how about your idea?

Thanks,

Bintian

>>
>>> +             reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
>>
>> This doesn't match the unit-address.
> Do you mean change to "<0x0 0xf6801000 0 0x1000>" ?
>
>>
>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>
>> I guess no-one's bothered to consider 64k pages?
>>
>> Given GICH and GICV, I hope that this platform is booted at EL2?
> Transfer from EL3 to EL1 directly, keep these two just for future use.
>
>>
>>> +             #interrupt-cells = <3>;
>>> +             #address-cells = <0>;
>>> +             interrupt-controller;
>>> +     };
>>> +
>>> +
[...]

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-04-12  6:40         ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-04-12  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Mark,

2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
[...]
>>
>>> +     gic: interrupt-controller at f6800000 {
>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>
>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
>> am I missing?
> Remove it in next version.
After remove "arm,cortex-a15-gic", I get the following error during
kernel booting:
-----
kvm [1]: Using HYP init bounce page @396d9000
kvm [1]: error: no compatible GIC node found
kvm [1]: error initializing Hyp mode: -19
-----

Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
gicv3 support kvm now,
so I think we should keep it, how about your idea?

Thanks,

Bintian

>>
>>> +             reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */
>>
>> This doesn't match the unit-address.
> Do you mean change to "<0x0 0xf6801000 0 0x1000>" ?
>
>>
>>> +                   <0x0 0xf6802000 0x0 0x2000>, /* GICC */
>>> +                   <0x0 0xf6804000 0x0 0x2000>, /* GICH */
>>> +                   <0x0 0xf6806000 0x0 0x2000>; /* GICV */
>>
>> I guess no-one's bothered to consider 64k pages?
>>
>> Given GICH and GICV, I hope that this platform is booted at EL2?
> Transfer from EL3 to EL1 directly, keep these two just for future use.
>
>>
>>> +             #interrupt-cells = <3>;
>>> +             #address-cells = <0>;
>>> +             interrupt-controller;
>>> +     };
>>> +
>>> +
[...]

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-04-12  6:40         ` Brent Wang
  (?)
@ 2015-04-12 10:57           ` Marc Zyngier
  -1 siblings, 0 replies; 85+ messages in thread
From: Marc Zyngier @ 2015-04-12 10:57 UTC (permalink / raw)
  To: Brent Wang
  Cc: Mark Rutland, dan.zhao, btw, Catalin Marinas, wangbinghui,
	Will Deacon, huxinwei, khilman, haojian.zhuang, yanhaifeng,
	rob.herring, mturquette, victor.lixin, xuwei5, jh80.chung,
	sledge.yanwei, kong.kongxinwei, heyunlei, w.f, zhangfei.gao,
	z.liuxinliang, devicetree, Bintian Wang, Pawel Moll,
	ijc+devicetree, puck.chen, olof, robh+dt, linux, zhenwei.wang,
	linux-arm-kernel, guodong.xu, tomeu.vizoso, sboyd, linux-kernel,
	galak, xuejiancheng, xuyiping, liguozhu

On 2015-04-12 07:40, Brent Wang wrote:
> Hello Mark,
>
> 2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
> [...]
>>>
>>>> +     gic: interrupt-controller@f6800000 {
>>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>>
>>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? 
>>> What
>>> am I missing?
>> Remove it in next version.
> After remove "arm,cortex-a15-gic", I get the following error during
> kernel booting:
> -----
> kvm [1]: Using HYP init bounce page @396d9000
> kvm [1]: error: no compatible GIC node found
> kvm [1]: error initializing Hyp mode: -19
> -----
>
> Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
> gicv3 support kvm now,
> so I think we should keep it, how about your idea?

Please look at commit 0f37247574b3 that is queued for merge in 4.1.
It adds the required compatibility strings to KVM, so Mark is perfectly
right to ask you to drop this "cortex-a15-gic" from your DT.

This DT won't be merged before 4.1 anyway, so there is no point trying
to make it work with older kernels.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-04-12 10:57           ` Marc Zyngier
  0 siblings, 0 replies; 85+ messages in thread
From: Marc Zyngier @ 2015-04-12 10:57 UTC (permalink / raw)
  To: Brent Wang
  Cc: Mark Rutland, dan.zhao, btw, Catalin Marinas, wangbinghui,
	Will Deacon, huxinwei, khilman, haojian.zhuang, yanhaifeng,
	rob.herring, mturquette, victor.lixin, xuwei5, jh80.chung,
	sledge.yanwei, kong.kongxinwei, heyunlei, w.f, zhangfei.gao,
	z.liuxinliang, devicetree, Bintian Wang, Pawel Moll,
	ijc+devicetree, puck.chen, olof, robh+dt, linux, zhenwei.wang,
	linux-arm-kernel, gu

On 2015-04-12 07:40, Brent Wang wrote:
> Hello Mark,
>
> 2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
> [...]
>>>
>>>> +     gic: interrupt-controller@f6800000 {
>>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>>
>>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? 
>>> What
>>> am I missing?
>> Remove it in next version.
> After remove "arm,cortex-a15-gic", I get the following error during
> kernel booting:
> -----
> kvm [1]: Using HYP init bounce page @396d9000
> kvm [1]: error: no compatible GIC node found
> kvm [1]: error initializing Hyp mode: -19
> -----
>
> Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
> gicv3 support kvm now,
> so I think we should keep it, how about your idea?

Please look at commit 0f37247574b3 that is queued for merge in 4.1.
It adds the required compatibility strings to KVM, so Mark is perfectly
right to ask you to drop this "cortex-a15-gic" from your DT.

This DT won't be merged before 4.1 anyway, so there is no point trying
to make it work with older kernels.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-04-12 10:57           ` Marc Zyngier
  0 siblings, 0 replies; 85+ messages in thread
From: Marc Zyngier @ 2015-04-12 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-04-12 07:40, Brent Wang wrote:
> Hello Mark,
>
> 2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
> [...]
>>>
>>>> +     gic: interrupt-controller at f6800000 {
>>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>>
>>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? 
>>> What
>>> am I missing?
>> Remove it in next version.
> After remove "arm,cortex-a15-gic", I get the following error during
> kernel booting:
> -----
> kvm [1]: Using HYP init bounce page @396d9000
> kvm [1]: error: no compatible GIC node found
> kvm [1]: error initializing Hyp mode: -19
> -----
>
> Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
> gicv3 support kvm now,
> so I think we should keep it, how about your idea?

Please look at commit 0f37247574b3 that is queued for merge in 4.1.
It adds the required compatibility strings to KVM, so Mark is perfectly
right to ask you to drop this "cortex-a15-gic" from your DT.

This DT won't be merged before 4.1 anyway, so there is no point trying
to make it work with older kernels.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
  2015-04-12 10:57           ` Marc Zyngier
  (?)
@ 2015-04-12 13:07             ` Brent Wang
  -1 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-04-12 13:07 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, dan.zhao, btw, Catalin Marinas, wangbinghui,
	Will Deacon, huxinwei, Kevin Hilman, Haojian Zhuang, Haifeng Yan,
	Rob Herring, Mike Turquette, victor.lixin, Xu Wei, Jaehoon Chung,
	sledge.yanwei, XinWei Kong, heyunlei, w.f, Zhangfei Gao,
	z.liuxinliang, devicetree, Bintian Wang, Pawel Moll,
	Ian Campbell, puck.chen, Olof Johansson, Rob Herring,
	Russell King - ARM Linux, zhenwei.wang, linux-arm-kernel,
	Guodong Xu, Tomeu Vizoso, Stephen Boyd, linux-kernel, Kumar Gala,
	xuejiancheng, xuyiping, Liguozhu (Kenneth)

Hello Marc,

2015-04-12 18:57 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 2015-04-12 07:40, Brent Wang wrote:
>>
>> Hello Mark,
>>
>> 2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
>> [...]
>>>>
>>>>
>>>>> +     gic: interrupt-controller@f6800000 {
>>>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>>>
>>>>
>>>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
>>>> am I missing?
>>>
>>> Remove it in next version.
>>
>> After remove "arm,cortex-a15-gic", I get the following error during
>> kernel booting:
>> -----
>> kvm [1]: Using HYP init bounce page @396d9000
>> kvm [1]: error: no compatible GIC node found
>> kvm [1]: error initializing Hyp mode: -19
>> -----
>>
>> Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
>> gicv3 support kvm now,
>> so I think we should keep it, how about your idea?
>
>
> Please look at commit 0f37247574b3 that is queued for merge in 4.1.
> It adds the required compatibility strings to KVM, so Mark is perfectly
> right to ask you to drop this "cortex-a15-gic" from your DT.

Thanks for the information.

> This DT won't be merged before 4.1 anyway, so there is no point trying
> to make it work with older kernels.
>
> Thanks,
>
>         M.
> --
> Fast, cheap, reliable. Pick two.



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* Re: [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-04-12 13:07             ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-04-12 13:07 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, dan.zhao, btw, Catalin Marinas, wangbinghui,
	Will Deacon, huxinwei, Kevin Hilman, Haojian Zhuang, Haifeng Yan,
	Rob Herring, Mike Turquette, victor.lixin, Xu Wei, Jaehoon Chung,
	sledge.yanwei, XinWei Kong, heyunlei, w.f, Zhangfei Gao,
	z.liuxinliang

Hello Marc,

2015-04-12 18:57 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 2015-04-12 07:40, Brent Wang wrote:
>>
>> Hello Mark,
>>
>> 2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
>> [...]
>>>>
>>>>
>>>>> +     gic: interrupt-controller@f6800000 {
>>>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>>>
>>>>
>>>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
>>>> am I missing?
>>>
>>> Remove it in next version.
>>
>> After remove "arm,cortex-a15-gic", I get the following error during
>> kernel booting:
>> -----
>> kvm [1]: Using HYP init bounce page @396d9000
>> kvm [1]: error: no compatible GIC node found
>> kvm [1]: error initializing Hyp mode: -19
>> -----
>>
>> Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
>> gicv3 support kvm now,
>> so I think we should keep it, how about your idea?
>
>
> Please look at commit 0f37247574b3 that is queued for merge in 4.1.
> It adds the required compatibility strings to KVM, so Mark is perfectly
> right to ask you to drop this "cortex-a15-gic" from your DT.

Thanks for the information.

> This DT won't be merged before 4.1 anyway, so there is no point trying
> to make it work with older kernels.
>
> Thanks,
>
>         M.
> --
> Fast, cheap, reliable. Pick two.



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

* [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC
@ 2015-04-12 13:07             ` Brent Wang
  0 siblings, 0 replies; 85+ messages in thread
From: Brent Wang @ 2015-04-12 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Marc,

2015-04-12 18:57 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 2015-04-12 07:40, Brent Wang wrote:
>>
>> Hello Mark,
>>
>> 2015-02-06 16:42 GMT+08:00 Brent Wang <wangbintian@gmail.com>:
>> [...]
>>>>
>>>>
>>>>> +     gic: interrupt-controller at f6800000 {
>>>>> +             compatible = "arm,gic-400", "arm,cortex-a15-gic";
>>>>
>>>>
>>>> Surely there's no need for the "arm,cortex-a15-gic" fallback entry? What
>>>> am I missing?
>>>
>>> Remove it in next version.
>>
>> After remove "arm,cortex-a15-gic", I get the following error during
>> kernel booting:
>> -----
>> kvm [1]: Using HYP init bounce page @396d9000
>> kvm [1]: error: no compatible GIC node found
>> kvm [1]: error initializing Hyp mode: -19
>> -----
>>
>> Check code "virt/kvm/arm/vgic.c", gicv2 only "cortex-a15-gic" and
>> gicv3 support kvm now,
>> so I think we should keep it, how about your idea?
>
>
> Please look at commit 0f37247574b3 that is queued for merge in 4.1.
> It adds the required compatibility strings to KVM, so Mark is perfectly
> right to ask you to drop this "cortex-a15-gic" from your DT.

Thanks for the information.

> This DT won't be merged before 4.1 anyway, so there is no point trying
> to make it work with older kernels.
>
> Thanks,
>
>         M.
> --
> Fast, cheap, reliable. Pick two.



-- 
Best Regards,

Bintian
===========================
Don't be nervous, just be happy!

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

end of thread, other threads:[~2015-04-12 13:07 UTC | newest]

Thread overview: 85+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-05  9:24 [PATCH 0/3] arm64,hi6220: Enable Hisilicon Hi6220 SoC Bintian Wang
2015-02-05  9:24 ` Bintian Wang
2015-02-05  9:24 ` Bintian Wang
2015-02-05  9:24 ` [PATCH 1/3] arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig Bintian Wang
2015-02-05  9:24   ` Bintian Wang
2015-02-05  9:24   ` Bintian Wang
2015-02-05  9:24 ` [PATCH 2/3] clk: hi6220: Clock driver support for Hisilicon hi6220 SoC Bintian Wang
2015-02-05  9:24   ` Bintian Wang
2015-02-05  9:24   ` Bintian Wang
2015-02-05 19:25   ` Mark Rutland
2015-02-05 19:25     ` Mark Rutland
2015-02-05 19:25     ` Mark Rutland
2015-02-06  7:32     ` Brent Wang
2015-02-06  7:32       ` Brent Wang
2015-02-06  7:32       ` Brent Wang
2015-02-06 18:10   ` Tyler Baker
2015-02-06 18:10     ` Tyler Baker
2015-02-06 18:10     ` Tyler Baker
2015-02-07  2:05     ` Brent Wang
2015-02-07  2:05       ` Brent Wang
2015-02-07  2:05       ` Brent Wang
2015-02-07 22:05       ` Tyler Baker
2015-02-07 22:05         ` Tyler Baker
2015-02-07 22:05         ` Tyler Baker
2015-02-05  9:24 ` [PATCH 3/3] arm64: dts: Add dts files for Hisilicon Hi6220 SoC Bintian Wang
2015-02-05  9:24   ` Bintian Wang
2015-02-05  9:24   ` Bintian Wang
2015-02-05 19:30   ` Mark Rutland
2015-02-05 19:30     ` Mark Rutland
2015-02-05 19:30     ` Mark Rutland
2015-02-06  8:42     ` Brent Wang
2015-02-06  8:42       ` Brent Wang
2015-02-06  8:42       ` Brent Wang
2015-02-06  9:07       ` Marc Zyngier
2015-02-06  9:07         ` Marc Zyngier
2015-02-06  9:07         ` Marc Zyngier
2015-02-06 10:31         ` Mark Rutland
2015-02-06 10:31           ` Mark Rutland
2015-02-06 10:31           ` Mark Rutland
2015-02-09  3:26         ` Brent Wang
2015-02-09  3:26           ` Brent Wang
2015-02-09  3:26           ` Brent Wang
2015-02-06 10:44       ` Mark Rutland
2015-02-06 10:44         ` Mark Rutland
2015-02-06 10:44         ` Mark Rutland
2015-02-06 15:37         ` Brent Wang
2015-02-06 15:37           ` Brent Wang
2015-02-06 15:37           ` Brent Wang
2015-02-10 13:37           ` Mark Rutland
2015-02-10 13:37             ` Mark Rutland
2015-02-10 13:37             ` Mark Rutland
2015-02-10 14:20             ` Brent Wang
2015-02-10 14:20               ` Brent Wang
2015-02-10 14:20               ` Brent Wang
2015-02-10 15:27               ` Mark Rutland
2015-02-10 15:27                 ` Mark Rutland
2015-02-10 15:27                 ` Mark Rutland
2015-02-11  1:49                 ` Brent Wang
2015-02-11  1:49                   ` Brent Wang
2015-02-11  1:49                   ` Brent Wang
2015-04-12  6:40       ` Brent Wang
2015-04-12  6:40         ` Brent Wang
2015-04-12  6:40         ` Brent Wang
2015-04-12 10:57         ` Marc Zyngier
2015-04-12 10:57           ` Marc Zyngier
2015-04-12 10:57           ` Marc Zyngier
2015-04-12 13:07           ` Brent Wang
2015-04-12 13:07             ` Brent Wang
2015-04-12 13:07             ` Brent Wang
2015-02-05 18:46 ` [PATCH 0/3] arm64,hi6220: Enable " Tyler Baker
2015-02-05 18:46   ` Tyler Baker
2015-02-05 18:46   ` Tyler Baker
2015-02-05 19:02   ` Olof Johansson
2015-02-05 19:02     ` Olof Johansson
2015-02-05 19:02     ` Olof Johansson
2015-02-05 23:52     ` Tyler Baker
2015-02-05 23:52       ` Tyler Baker
2015-02-05 23:52       ` Tyler Baker
2015-02-06  4:21       ` Brent Wang
2015-02-06  6:18         ` Olof Johansson
2015-02-06  6:18           ` Olof Johansson
2015-02-06  6:18           ` Olof Johansson
2015-02-06  6:35           ` Brent Wang
2015-02-06  6:35             ` Brent Wang
2015-02-06  6:35             ` Brent Wang

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.