Merge remote-tracking branch 'clk/clk-next' into clk-next
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 0e4f90a..f463bdc 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -230,30 +230,7 @@
 
 See the basic clock types in drivers/clk/clk-*.c for examples.
 
-	Part 5 - static initialization of clock data
-
-For platforms with many clocks (often numbering into the hundreds) it
-may be desirable to statically initialize some clock data.  This
-presents a problem since the definition of struct clk should be hidden
-from everyone except for the clock core in drivers/clk/clk.c.
-
-To get around this problem struct clk's definition is exposed in
-include/linux/clk-private.h along with some macros for more easily
-initializing instances of the basic clock types.  These clocks must
-still be initialized with the common clock framework via a call to
-__clk_init.
-
-clk-private.h must NEVER be included by code which implements struct
-clk_ops callbacks, nor must it be included by any logic which pokes
-around inside of struct clk at run-time.  To do so is a layering
-violation.
-
-To better enforce this policy, always follow this simple rule: any
-statically initialized clock data MUST be defined in a separate file
-from the logic that implements its ops.  Basically separate the logic
-from the data and all is well.
-
-	Part 6 - Disabling clock gating of unused clocks
+	Part 5 - Disabling clock gating of unused clocks
 
 Sometimes during development it can be useful to be able to bypass the
 default disabling of unused clocks. For example, if drivers aren't enabling
@@ -264,7 +241,7 @@
 To bypass this disabling, include "clk_ignore_unused" in the bootargs to the
 kernel.
 
-	Part 7 - Locking
+	Part 6 - Locking
 
 The common clock framework uses two global locks, the prepare lock and the
 enable lock.
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
new file mode 100644
index 0000000..936166f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -0,0 +1,23 @@
+Mediatek apmixedsys controller
+==============================
+
+The Mediatek apmixedsys controller provides the PLLs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-apmixedsys"
+	- "mediatek,mt8173-apmixedsys"
+- #clock-cells: Must be 1
+
+The apmixedsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+apmixedsys: clock-controller@10209000 {
+	compatible = "mediatek,mt8173-apmixedsys";
+	reg = <0 0x10209000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
new file mode 100644
index 0000000..f6cd3e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -0,0 +1,30 @@
+Mediatek infracfg controller
+============================
+
+The Mediatek infracfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-infracfg", "syscon"
+	- "mediatek,mt8173-infracfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The infracfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+infracfg: power-controller@10001000 {
+	compatible = "mediatek,mt8173-infracfg", "syscon";
+	reg = <0 0x10001000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
new file mode 100644
index 0000000..f25b854
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -0,0 +1,30 @@
+Mediatek pericfg controller
+===========================
+
+The Mediatek pericfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-pericfg", "syscon"
+	- "mediatek,mt8173-pericfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The pericfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+pericfg: power-controller@10003000 {
+	compatible = "mediatek,mt8173-pericfg", "syscon";
+	reg = <0 0x10003000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
new file mode 100644
index 0000000..f9e9179
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -0,0 +1,23 @@
+Mediatek topckgen controller
+============================
+
+The Mediatek topckgen controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-topckgen"
+	- "mediatek,mt8173-topckgen"
+- #clock-cells: Must be 1
+
+The topckgen controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+topckgen: power-controller@10000000 {
+	compatible = "mediatek,mt8173-topckgen";
+	reg = <0 0x10000000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
new file mode 100644
index 0000000..2b7b3fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
@@ -0,0 +1,40 @@
+* Amlogic Meson8b Clock and Reset Unit
+
+The Amlogic Meson8b clock controller generates and supplies clock to various
+controllers within the SoC.
+
+Required Properties:
+
+- compatible: should be "amlogic,meson8b-clkc"
+- reg: it must be composed by two tuples:
+	0) physical base address of the xtal register and length of memory
+	   mapped region.
+	1) physical base address of the clock controller and length of memory
+	   mapped region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
+used in device tree sources.
+
+Example: Clock controller node:
+
+	clkc: clock-controller@c1104000 {
+		#clock-cells = <1>;
+		compatible = "amlogic,meson8b-clkc";
+		reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
+	};
+
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart_AO: serial@c81004c0 {
+		compatible = "amlogic,meson-uart";
+		reg = <0xc81004c0 0x14>;
+		interrupts = <0 90 1>;
+		clocks = <&clkc CLKID_CLK81>;
+		status = "disabled";
+	};
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 06fc6d5..2ec489e 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -138,9 +138,10 @@
 and clock frequencies. Such a configuration can be specified in a device tree
 node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
 properties. The assigned-clock-parents property should contain a list of parent
-clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
-property the list of assigned clock frequency values - corresponding to clocks
-listed in the assigned-clocks property.
+clocks in the form of a phandle and clock specifier pair and the
+assigned-clock-rates property should contain a list of frequencies in Hz. Both
+these properties should correspond to the clocks listed in the assigned-clocks
+property.
 
 To skip setting parent or rate of a clock its corresponding entry should be
 set to 0, or can be omitted if it is not followed by any non-zero entry.
diff --git a/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
new file mode 100644
index 0000000..54d6d13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
@@ -0,0 +1,55 @@
+* Clock and reset bindings for CSR atlas7
+
+Required properties:
+- compatible: Should be "sirf,atlas7-car"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- #reset-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.
+The ID list atlas7_clks defined in drivers/clk/sirf/clk-atlas7.c
+
+The reset consumer should specify the desired reset by having the reset
+ID in its "reset" phandle cell.
+The ID list atlas7_reset_unit defined in drivers/clk/sirf/clk-atlas7.c
+
+Examples: Clock and reset controller node:
+
+car: clock-controller@18620000 {
+	compatible = "sirf,atlas7-car";
+	reg = <0x18620000 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
+
+Examples: Consumers using clock or reset:
+
+timer@10dc0000 {
+	compatible = "sirf,macro-tick";
+	reg = <0x10dc0000 0x1000>;
+	clocks = <&car 54>;
+	interrupts = <0 0 0>,
+		   <0 1 0>,
+		   <0 2 0>,
+		   <0 49 0>,
+		   <0 50 0>,
+		   <0 51 0>;
+};
+
+uart1: uart@18020000 {
+	cell-index = <1>;
+	compatible = "sirf,macro-uart";
+	reg = <0x18020000 0x1000>;
+	clocks = <&clks 95>;
+	interrupts = <0 18 0>;
+	fifosize = <32>;
+};
+
+vpp@13110000 {
+	compatible = "sirf,prima2-vpp";
+	reg = <0x13110000 0x10000>;
+	interrupts = <0 31 0>;
+	clocks = <&car 85>;
+	resets = <&car 29>;
+};
diff --git a/Documentation/devicetree/bindings/clock/emev2-clock.txt b/Documentation/devicetree/bindings/clock/emev2-clock.txt
index 60bbb1a..268ca61 100644
--- a/Documentation/devicetree/bindings/clock/emev2-clock.txt
+++ b/Documentation/devicetree/bindings/clock/emev2-clock.txt
@@ -52,7 +52,7 @@
 
 Example of consumer:
 
-uart@e1020000 {
+serial@e1020000 {
 	compatible = "renesas,em-uart";
 	reg = <0xe1020000 0x38>;
 	interrupts = <0 8 0>;
diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt b/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
new file mode 100644
index 0000000..809c5a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
@@ -0,0 +1,21 @@
+* Marvell PXA1928 Clock Controllers
+
+The PXA1928 clock subsystem generates and supplies clock to various
+controllers within the PXA1928 SoC. The PXA1928 contains 3 clock controller
+blocks called APMU, MPMU, and APBC roughly corresponding to internal buses.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,pxa1928-apmu" - APMU controller compatible
+  - "marvell,pxa1928-mpmu" - MPMU controller compatible
+  - "marvell,pxa1928-apbc" - APBC controller compatible
+- reg: physical base address of the clock controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use the clock controller
+phandle and this identifier to specify the clock which they consume.
+
+All these identifiers can be found in <dt-bindings/clock/marvell,pxa1928.h>.
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
index 31c7c0c..660e649 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -19,6 +19,7 @@
 9	pex1	PCIe Cntrl 1
 15	sata0	SATA Host 0
 17	sdio	SDHCI Host
+23	crypto	CESA (crypto engine)
 25	tdm	Time Division Mplx
 28	ddr	DDR Cntrl
 30	sata1	SATA Host 0
diff --git a/Documentation/devicetree/bindings/clock/ti,cdce925.txt b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
new file mode 100644
index 0000000..4c7669a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
@@ -0,0 +1,42 @@
+Binding for TO CDCE925 programmable I2C clock synthesizers.
+
+Reference
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] http://www.ti.com/product/cdce925
+
+The driver provides clock sources for each output Y1 through Y5.
+
+Required properties:
+ - compatible: Shall be "ti,cdce925"
+ - reg: I2C device address.
+ - clocks: Points to a fixed parent clock that provides the input frequency.
+ - #clock-cells: From common clock bindings: Shall be 1.
+
+Optional properties:
+ - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
+                 board, or to compensate for external influences.
+
+For both PLL1 and PLL2 an optional child node can be used to specify spread
+spectrum clocking parameters for a board.
+  - spread-spectrum: SSC mode as defined in the data sheet.
+  - spread-spectrum-center: Use "centered" mode instead of "max" mode. When
+    present, the clock runs at the requested frequency on average. Otherwise
+    the requested frequency is the maximum value of the SCC range.
+
+
+Example:
+
+	clockgen: cdce925pw@64 {
+		compatible = "cdce925";
+		reg = <0x64>;
+		clocks = <&xtal_27Mhz>;
+		#clock-cells = <1>;
+		xtal-load-pf = <5>;
+		/* PLL options to get SSC 1% centered */
+		PLL2 {
+			spread-spectrum = <4>;
+			spread-spectrum-center;
+		};
+	};
diff --git a/arch/arm/boot/dts/atlas7.dtsi b/arch/arm/boot/dts/atlas7.dtsi
index a753178..5dfd3a4 100644
--- a/arch/arm/boot/dts/atlas7.dtsi
+++ b/arch/arm/boot/dts/atlas7.dtsi
@@ -38,6 +38,21 @@
 		};
 	};
 
+	clocks {
+		xinw {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "xinw";
+		};
+		xin {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+			clock-output-names = "xin";
+		};
+	};
+
 	noc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9897f35..1dd4f9d 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -78,6 +78,23 @@
 	  This driver supports Silicon Labs 570/571/598/599 programmable
 	  clock generators.
 
+config COMMON_CLK_CDCE925
+	tristate "Clock driver for TI CDCE925 devices"
+	depends on I2C
+	depends on OF
+	select REGMAP_I2C
+	help
+	---help---
+	  This driver supports the TI CDCE925 programmable clock synthesizer.
+	  The chip contains two PLLs with spread-spectrum clocking support and
+	  five output dividers. The driver only supports the following setup,
+	  and uses a fixed setting for the output muxes.
+	  Y1 is derived from the input clock
+	  Y2 and Y3 derive from PLL1
+	  Y4 and Y5 derive from PLL2
+	  Given a target output frequency, the driver will set the PLL and
+	  divider to best approximate the desired output.
+
 config COMMON_CLK_S2MPS11
 	tristate "Clock driver for S2MPS1X/S5M8767 MFD"
 	depends on MFD_SEC_CORE
@@ -150,11 +167,12 @@
 	---help---
 	  This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
 
+source "drivers/clk/bcm/Kconfig"
+source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 
 endmenu
 
-source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 
 source "drivers/clk/samsung/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25..3233f0e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -38,6 +38,7 @@
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI570)		+= clk-si570.o
+obj-$(CONFIG_COMMON_CLK_CDCE925)	+= clk-cdce925.o
 obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)			+= clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
@@ -47,14 +48,14 @@
 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/
+obj-$(CONFIG_ARCH_MEDIATEK)		+= mediatek/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
+obj-$(CONFIG_ARCH_MESON)		+= meson/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 59fa3cc..c240045 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -614,7 +614,7 @@
 	const char *name = np->name;
 	int i;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > 2)
 		return;
 
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index c1af80b..f98eafe 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -224,7 +224,7 @@
 	const char *name = np->name;
 	struct clk_master_characteristics *characteristics;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 86c8a07..8c86c0f7 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -237,7 +237,7 @@
 	const char *name;
 	struct device_node *progclknp;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index 2f13bd5..98a84a8 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -373,7 +373,7 @@
 	const char *name = np->name;
 	int i;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > 2)
 		return;
 
@@ -451,7 +451,7 @@
 	const char *name = np->name;
 	int i;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents != 2)
 		return;
 
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
index 144d47e..3817ea8 100644
--- a/drivers/clk/at91/clk-smd.c
+++ b/drivers/clk/at91/clk-smd.c
@@ -150,7 +150,7 @@
 	const char *parent_names[SMD_SOURCE_MAX];
 	const char *name = np->name;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 0b7c3e8..b0cbd2b 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -378,7 +378,7 @@
 	const char *parent_names[USB_SOURCE_MAX];
 	const char *name = np->name;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 3f27d21..39be2be 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -153,7 +153,7 @@
 	return 0;
 }
 
-static struct irq_domain_ops pmc_irq_ops = {
+static const struct irq_domain_ops pmc_irq_ops = {
 	.map	= pmc_irq_map,
 	.xlate	= pmc_irq_domain_xlate,
 };
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index e5aeded..deaa7f9 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -21,8 +21,6 @@
 #define selector_clear_exists(sel)	((sel)->width = 0)
 #define trigger_clear_exists(trig)	FLAG_CLEAR(trig, TRIG, EXISTS)
 
-LIST_HEAD(ccu_list);	/* The list of set up CCUs */
-
 /* Validity checking */
 
 static bool ccu_data_offsets_valid(struct ccu_data *ccu)
@@ -773,7 +771,6 @@
 
 	of_clk_del_provider(ccu->node);	/* safe if never added */
 	ccu_clks_teardown(ccu);
-	list_del(&ccu->links);
 	of_node_put(ccu->node);
 	ccu->node = NULL;
 	iounmap(ccu->base);
@@ -847,7 +844,6 @@
 		goto out_err;
 	}
 	ccu->node = of_node_get(node);
-	list_add_tail(&ccu->links, &ccu_list);
 
 	/*
 	 * Set up each defined kona clock and save the result in
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index a0ef4f7..79a9850 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1240,7 +1240,7 @@
 	default:
 		BUG();
 	}
-	return -EINVAL;
+	return false;
 }
 
 /* Set a CCU and all its clocks into their desired initial state */
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index 6849a64..906576e 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -480,7 +480,6 @@
 	spinlock_t lock;	/* serialization lock */
 	bool write_enabled;	/* write access is currently enabled */
 	struct ccu_policy policy;
-	struct list_head links;	/* for ccu_list */
 	struct device_node *node;
 	struct clk_onecell_data clk_data;
 	const char *name;
@@ -492,7 +491,6 @@
 #define KONA_CCU_COMMON(_prefix, _name, _ccuname)			    \
 	.name		= #_name "_ccu",				    \
 	.lock		= __SPIN_LOCK_UNLOCKED(_name ## _ccu_data.lock),    \
-	.links		= LIST_HEAD_INIT(_name ## _ccu_data.links),	    \
 	.clk_data	= {						    \
 		.clk_num = _prefix ## _ ## _ccuname ## _CCU_CLOCK_COUNT,    \
 	}
diff --git a/drivers/clk/berlin/berlin2-pll.c b/drivers/clk/berlin/berlin2-pll.c
index bdc506b..f4b8d32 100644
--- a/drivers/clk/berlin/berlin2-pll.c
+++ b/drivers/clk/berlin/berlin2-pll.c
@@ -25,14 +25,7 @@
 #include <asm/div64.h>
 
 #include "berlin2-div.h"
-
-struct berlin2_pll_map {
-	const u8 vcodiv[16];
-	u8 mult;
-	u8 fbdiv_shift;
-	u8 rfdiv_shift;
-	u8 divsel_shift;
-};
+#include "berlin2-pll.h"
 
 struct berlin2_pll {
 	struct clk_hw hw;
diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c
index 88f4ff6..90897af 100644
--- a/drivers/clk/clk-asm9260.c
+++ b/drivers/clk/clk-asm9260.c
@@ -274,7 +274,7 @@
 	u32 accuracy = 0;
 
 	base = of_io_request_and_map(np, 0, np->name);
-	if (!base)
+	if (IS_ERR(base))
 		panic("%s: unable to map resource", np->name);
 
 	/* register pll */
diff --git a/drivers/clk/clk-axm5516.c b/drivers/clk/clk-axm5516.c
index 0f6368c..c7c91a5 100644
--- a/drivers/clk/clk-axm5516.c
+++ b/drivers/clk/clk-axm5516.c
@@ -556,7 +556,7 @@
 		return PTR_ERR(regmap);
 
 	num_clks = ARRAY_SIZE(axmclk_clocks);
-	pr_info("axmclk: supporting %u clocks\n", num_clks);
+	pr_info("axmclk: supporting %zu clocks\n", num_clks);
 	priv = devm_kzalloc(dev, sizeof(*priv) + sizeof(*priv->clks) * num_clks,
 			    GFP_KERNEL);
 	if (!priv)
diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index b8e4f8a..f01164f 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -94,7 +94,7 @@
 	"clk_in0", "clk_in1",
 };
 
-static const char *cdce706_clkin_name[] = {
+static const char * const cdce706_clkin_name[] = {
 	"clk_in",
 };
 
@@ -102,7 +102,7 @@
 	"pll1", "pll2", "pll3",
 };
 
-static const char *cdce706_divider_parent_name[] = {
+static const char * const cdce706_divider_parent_name[] = {
 	"clk_in", "pll1", "pll2", "pll2", "pll3",
 };
 
@@ -666,6 +666,7 @@
 
 static int cdce706_remove(struct i2c_client *client)
 {
+	of_clk_del_provider(client->dev.of_node);
 	return 0;
 }
 
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
new file mode 100644
index 0000000..85fafb4
--- /dev/null
+++ b/drivers/clk/clk-cdce925.c
@@ -0,0 +1,749 @@
+/*
+ * Driver for TI Dual PLL CDCE925 clock synthesizer
+ *
+ * This driver always connects the Y1 to the input clock, Y2/Y3 to PLL1
+ * and Y4/Y5 to PLL2. PLL frequency is set on a first-come-first-serve
+ * basis. Clients can directly request any frequency that the chip can
+ * deliver using the standard clk framework. In addition, the device can
+ * be configured and activated via the devicetree.
+ *
+ * Copyright (C) 2014, Topic Embedded Products
+ * Licenced under GPL
+ */
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/gcd.h>
+
+/* The chip has 2 PLLs which can be routed through dividers to 5 outputs.
+ * Model this as 2 PLL clocks which are parents to the outputs.
+ */
+#define NUMBER_OF_PLLS	2
+#define NUMBER_OF_OUTPUTS	5
+
+#define CDCE925_REG_GLOBAL1	0x01
+#define CDCE925_REG_Y1SPIPDIVH	0x02
+#define CDCE925_REG_PDIVL	0x03
+#define CDCE925_REG_XCSEL	0x05
+/* PLL parameters start at 0x10, steps of 0x10 */
+#define CDCE925_OFFSET_PLL	0x10
+/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */
+#define CDCE925_PLL_MUX_OUTPUTS	0x14
+#define CDCE925_PLL_MULDIV	0x18
+
+#define CDCE925_PLL_FREQUENCY_MIN	 80000000ul
+#define CDCE925_PLL_FREQUENCY_MAX	230000000ul
+struct clk_cdce925_chip;
+
+struct clk_cdce925_output {
+	struct clk_hw hw;
+	struct clk_cdce925_chip *chip;
+	u8 index;
+	u16 pdiv; /* 1..127 for Y2-Y5; 1..1023 for Y1 */
+};
+#define to_clk_cdce925_output(_hw) \
+	container_of(_hw, struct clk_cdce925_output, hw)
+
+struct clk_cdce925_pll {
+	struct clk_hw hw;
+	struct clk_cdce925_chip *chip;
+	u8 index;
+	u16 m;   /* 1..511 */
+	u16 n;   /* 1..4095 */
+};
+#define to_clk_cdce925_pll(_hw)	container_of(_hw, struct clk_cdce925_pll, hw)
+
+struct clk_cdce925_chip {
+	struct regmap *regmap;
+	struct i2c_client *i2c_client;
+	struct clk_cdce925_pll pll[NUMBER_OF_PLLS];
+	struct clk_cdce925_output clk[NUMBER_OF_OUTPUTS];
+	struct clk *dt_clk[NUMBER_OF_OUTPUTS];
+	struct clk_onecell_data onecell;
+};
+
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
+
+static unsigned long cdce925_pll_calculate_rate(unsigned long parent_rate,
+	u16 n, u16 m)
+{
+	if ((!m || !n) || (m == n))
+		return parent_rate; /* In bypass mode runs at same frequency */
+	return mult_frac(parent_rate, (unsigned long)n, (unsigned long)m);
+}
+
+static unsigned long cdce925_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	/* Output frequency of PLL is Fout = (Fin/Pdiv)*(N/M) */
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+
+	return cdce925_pll_calculate_rate(parent_rate, data->n, data->m);
+}
+
+static void cdce925_pll_find_rate(unsigned long rate,
+		unsigned long parent_rate, u16 *n, u16 *m)
+{
+	unsigned long un;
+	unsigned long um;
+	unsigned long g;
+
+	if (rate <= parent_rate) {
+		/* Can always deliver parent_rate in bypass mode */
+		rate = parent_rate;
+		*n = 0;
+		*m = 0;
+	} else {
+		/* In PLL mode, need to apply min/max range */
+		if (rate < CDCE925_PLL_FREQUENCY_MIN)
+			rate = CDCE925_PLL_FREQUENCY_MIN;
+		else if (rate > CDCE925_PLL_FREQUENCY_MAX)
+			rate = CDCE925_PLL_FREQUENCY_MAX;
+
+		g = gcd(rate, parent_rate);
+		um = parent_rate / g;
+		un = rate / g;
+		/* When outside hw range, reduce to fit (rounding errors) */
+		while ((un > 4095) || (um > 511)) {
+			un >>= 1;
+			um >>= 1;
+		}
+		if (un == 0)
+			un = 1;
+		if (um == 0)
+			um = 1;
+
+		*n = un;
+		*m = um;
+	}
+}
+
+static long cdce925_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	u16 n, m;
+
+	cdce925_pll_find_rate(rate, *parent_rate, &n, &m);
+	return (long)cdce925_pll_calculate_rate(*parent_rate, n, m);
+}
+
+static int cdce925_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+
+	if (!rate || (rate == parent_rate)) {
+		data->m = 0; /* Bypass mode */
+		data->n = 0;
+		return 0;
+	}
+
+	if ((rate < CDCE925_PLL_FREQUENCY_MIN) ||
+		(rate > CDCE925_PLL_FREQUENCY_MAX)) {
+		pr_debug("%s: rate %lu outside PLL range.\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	if (rate < parent_rate) {
+		pr_debug("%s: rate %lu less than parent rate %lu.\n", __func__,
+			rate, parent_rate);
+		return -EINVAL;
+	}
+
+	cdce925_pll_find_rate(rate, parent_rate, &data->n, &data->m);
+	return 0;
+}
+
+
+/* calculate p = max(0, 4 - int(log2 (n/m))) */
+static u8 cdce925_pll_calc_p(u16 n, u16 m)
+{
+	u8 p;
+	u16 r = n / m;
+
+	if (r >= 16)
+		return 0;
+	p = 4;
+	while (r > 1) {
+		r >>= 1;
+		--p;
+	}
+	return p;
+}
+
+/* Returns VCO range bits for VCO1_0_RANGE */
+static u8 cdce925_pll_calc_range_bits(struct clk_hw *hw, u16 n, u16 m)
+{
+	struct clk *parent = clk_get_parent(hw->clk);
+	unsigned long rate = clk_get_rate(parent);
+
+	rate = mult_frac(rate, (unsigned long)n, (unsigned long)m);
+	if (rate >= 175000000)
+		return 0x3;
+	if (rate >= 150000000)
+		return 0x02;
+	if (rate >= 125000000)
+		return 0x01;
+	return 0x00;
+}
+
+/* I2C clock, hence everything must happen in (un)prepare because this
+ * may sleep */
+static int cdce925_pll_prepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+	u16 n = data->n;
+	u16 m = data->m;
+	u16 r;
+	u8 q;
+	u8 p;
+	u16 nn;
+	u8 pll[4]; /* Bits are spread out over 4 byte registers */
+	u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
+	unsigned i;
+
+	if ((!m || !n) || (m == n)) {
+		/* Set PLL mux to bypass mode, leave the rest as is */
+		regmap_update_bits(data->chip->regmap,
+			reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
+	} else {
+		/* According to data sheet: */
+		/* p = max(0, 4 - int(log2 (n/m))) */
+		p = cdce925_pll_calc_p(n, m);
+		/* nn = n * 2^p */
+		nn = n * BIT(p);
+		/* q = int(nn/m) */
+		q = nn / m;
+		if ((q < 16) || (1 > 64)) {
+			pr_debug("%s invalid q=%d\n", __func__, q);
+			return -EINVAL;
+		}
+		r = nn - (m*q);
+		if (r > 511) {
+			pr_debug("%s invalid r=%d\n", __func__, r);
+			return -EINVAL;
+		}
+		pr_debug("%s n=%d m=%d p=%d q=%d r=%d\n", __func__,
+			n, m, p, q, r);
+		/* encode into register bits */
+		pll[0] = n >> 4;
+		pll[1] = ((n & 0x0F) << 4) | ((r >> 5) & 0x0F);
+		pll[2] = ((r & 0x1F) << 3) | ((q >> 3) & 0x07);
+		pll[3] = ((q & 0x07) << 5) | (p << 2) |
+				cdce925_pll_calc_range_bits(hw, n, m);
+		/* Write to registers */
+		for (i = 0; i < ARRAY_SIZE(pll); ++i)
+			regmap_write(data->chip->regmap,
+				reg_ofs + CDCE925_PLL_MULDIV + i, pll[i]);
+		/* Enable PLL */
+		regmap_update_bits(data->chip->regmap,
+			reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x00);
+	}
+
+	return 0;
+}
+
+static void cdce925_pll_unprepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+	u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
+
+	regmap_update_bits(data->chip->regmap,
+			reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
+}
+
+static const struct clk_ops cdce925_pll_ops = {
+	.prepare = cdce925_pll_prepare,
+	.unprepare = cdce925_pll_unprepare,
+	.recalc_rate = cdce925_pll_recalc_rate,
+	.round_rate = cdce925_pll_round_rate,
+	.set_rate = cdce925_pll_set_rate,
+};
+
+
+static void cdce925_clk_set_pdiv(struct clk_cdce925_output *data, u16 pdiv)
+{
+	switch (data->index) {
+	case 0:
+		regmap_update_bits(data->chip->regmap,
+			CDCE925_REG_Y1SPIPDIVH,
+			0x03, (pdiv >> 8) & 0x03);
+		regmap_write(data->chip->regmap, 0x03, pdiv & 0xFF);
+		break;
+	case 1:
+		regmap_update_bits(data->chip->regmap, 0x16, 0x7F, pdiv);
+		break;
+	case 2:
+		regmap_update_bits(data->chip->regmap, 0x17, 0x7F, pdiv);
+		break;
+	case 3:
+		regmap_update_bits(data->chip->regmap, 0x26, 0x7F, pdiv);
+		break;
+	case 4:
+		regmap_update_bits(data->chip->regmap, 0x27, 0x7F, pdiv);
+		break;
+	}
+}
+
+static void cdce925_clk_activate(struct clk_cdce925_output *data)
+{
+	switch (data->index) {
+	case 0:
+		regmap_update_bits(data->chip->regmap,
+			CDCE925_REG_Y1SPIPDIVH, 0x0c, 0x0c);
+		break;
+	case 1:
+	case 2:
+		regmap_update_bits(data->chip->regmap, 0x14, 0x03, 0x03);
+		break;
+	case 3:
+	case 4:
+		regmap_update_bits(data->chip->regmap, 0x24, 0x03, 0x03);
+		break;
+	}
+}
+
+static int cdce925_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	cdce925_clk_set_pdiv(data, data->pdiv);
+	cdce925_clk_activate(data);
+	return 0;
+}
+
+static void cdce925_clk_unprepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	/* Disable clock by setting divider to "0" */
+	cdce925_clk_set_pdiv(data, 0);
+}
+
+static unsigned long cdce925_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	if (data->pdiv)
+		return parent_rate / data->pdiv;
+	return 0;
+}
+
+static u16 cdce925_calc_divider(unsigned long rate,
+		unsigned long parent_rate)
+{
+	unsigned long divider;
+
+	if (!rate)
+		return 0;
+	if (rate >= parent_rate)
+		return 1;
+
+	divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if (divider > 0x7F)
+		divider = 0x7F;
+
+	return (u16)divider;
+}
+
+static unsigned long cdce925_clk_best_parent_rate(
+	struct clk_hw *hw, unsigned long rate)
+{
+	struct clk *pll = clk_get_parent(hw->clk);
+	struct clk *root = clk_get_parent(pll);
+	unsigned long root_rate = clk_get_rate(root);
+	unsigned long best_rate_error = rate;
+	u16 pdiv_min;
+	u16 pdiv_max;
+	u16 pdiv_best;
+	u16 pdiv_now;
+
+	if (root_rate % rate == 0)
+		return root_rate; /* Don't need the PLL, use bypass */
+
+	pdiv_min = (u16)max(1ul, DIV_ROUND_UP(CDCE925_PLL_FREQUENCY_MIN, rate));
+	pdiv_max = (u16)min(127ul, CDCE925_PLL_FREQUENCY_MAX / rate);
+
+	if (pdiv_min > pdiv_max)
+		return 0; /* No can do? */
+
+	pdiv_best = pdiv_min;
+	for (pdiv_now = pdiv_min; pdiv_now < pdiv_max; ++pdiv_now) {
+		unsigned long target_rate = rate * pdiv_now;
+		long pll_rate = clk_round_rate(pll, target_rate);
+		unsigned long actual_rate;
+		unsigned long rate_error;
+
+		if (pll_rate <= 0)
+			continue;
+		actual_rate = pll_rate / pdiv_now;
+		rate_error = abs((long)actual_rate - (long)rate);
+		if (rate_error < best_rate_error) {
+			pdiv_best = pdiv_now;
+			best_rate_error = rate_error;
+		}
+		/* TODO: Consider PLL frequency based on smaller n/m values
+		 * and pick the better one if the error is equal */
+	}
+
+	return rate * pdiv_best;
+}
+
+static long cdce925_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	unsigned long l_parent_rate = *parent_rate;
+	u16 divider = cdce925_calc_divider(rate, l_parent_rate);
+
+	if (l_parent_rate / divider != rate) {
+		l_parent_rate = cdce925_clk_best_parent_rate(hw, rate);
+		divider = cdce925_calc_divider(rate, l_parent_rate);
+		*parent_rate = l_parent_rate;
+	}
+
+	if (divider)
+		return (long)(l_parent_rate / divider);
+	return 0;
+}
+
+static int cdce925_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	data->pdiv = cdce925_calc_divider(rate, parent_rate);
+
+	return 0;
+}
+
+static const struct clk_ops cdce925_clk_ops = {
+	.prepare = cdce925_clk_prepare,
+	.unprepare = cdce925_clk_unprepare,
+	.recalc_rate = cdce925_clk_recalc_rate,
+	.round_rate = cdce925_clk_round_rate,
+	.set_rate = cdce925_clk_set_rate,
+};
+
+
+static u16 cdce925_y1_calc_divider(unsigned long rate,
+		unsigned long parent_rate)
+{
+	unsigned long divider;
+
+	if (!rate)
+		return 0;
+	if (rate >= parent_rate)
+		return 1;
+
+	divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if (divider > 0x3FF) /* Y1 has 10-bit divider */
+		divider = 0x3FF;
+
+	return (u16)divider;
+}
+
+static long cdce925_clk_y1_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	unsigned long l_parent_rate = *parent_rate;
+	u16 divider = cdce925_y1_calc_divider(rate, l_parent_rate);
+
+	if (divider)
+		return (long)(l_parent_rate / divider);
+	return 0;
+}
+
+static int cdce925_clk_y1_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	data->pdiv = cdce925_y1_calc_divider(rate, parent_rate);
+
+	return 0;
+}
+
+static const struct clk_ops cdce925_clk_y1_ops = {
+	.prepare = cdce925_clk_prepare,
+	.unprepare = cdce925_clk_unprepare,
+	.recalc_rate = cdce925_clk_recalc_rate,
+	.round_rate = cdce925_clk_y1_round_rate,
+	.set_rate = cdce925_clk_y1_set_rate,
+};
+
+
+static struct regmap_config cdce925_regmap_config = {
+	.name = "configuration0",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = 0x2F,
+};
+
+#define CDCE925_I2C_COMMAND_BLOCK_TRANSFER	0x00
+#define CDCE925_I2C_COMMAND_BYTE_TRANSFER	0x80
+
+static int cdce925_regmap_i2c_write(
+	void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+	int ret;
+	u8 reg_data[2];
+
+	if (count != 2)
+		return -ENOTSUPP;
+
+	/* First byte is command code */
+	reg_data[0] = CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)data)[0];
+	reg_data[1] = ((u8 *)data)[1];
+
+	dev_dbg(&i2c->dev, "%s(%zu) %#x %#x\n", __func__, count,
+			reg_data[0], reg_data[1]);
+
+	ret = i2c_master_send(i2c, reg_data, count);
+	if (likely(ret == count))
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int cdce925_regmap_i2c_read(void *context,
+	   const void *reg, size_t reg_size, void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+	struct i2c_msg xfer[2];
+	int ret;
+	u8 reg_data[2];
+
+	if (reg_size != 1)
+		return -ENOTSUPP;
+
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].buf = reg_data;
+	if (val_size == 1) {
+		reg_data[0] =
+			CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)reg)[0];
+		xfer[0].len = 1;
+	} else {
+		reg_data[0] =
+			CDCE925_I2C_COMMAND_BLOCK_TRANSFER | ((u8 *)reg)[0];
+		reg_data[1] = val_size;
+		xfer[0].len = 2;
+	}
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = val_size;
+	xfer[1].buf = val;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
+	if (likely(ret == 2)) {
+		dev_dbg(&i2c->dev, "%s(%zu, %zu) %#x %#x\n", __func__,
+				reg_size, val_size, reg_data[0], *((u8 *)val));
+		return 0;
+	} else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
+ * just weird, so just use the single byte mode exclusively. */
+static struct regmap_bus regmap_cdce925_bus = {
+	.write = cdce925_regmap_i2c_write,
+	.read = cdce925_regmap_i2c_read,
+};
+
+static int cdce925_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct clk_cdce925_chip *data;
+	struct device_node *node = client->dev.of_node;
+	const char *parent_name;
+	const char *pll_clk_name[NUMBER_OF_PLLS] = {NULL,};
+	struct clk_init_data init;
+	struct clk *clk;
+	u32 value;
+	int i;
+	int err;
+	struct device_node *np_output;
+	char child_name[6];
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->i2c_client = client;
+	data->regmap = devm_regmap_init(&client->dev, &regmap_cdce925_bus,
+			&client->dev, &cdce925_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&client->dev, "failed to allocate register map\n");
+		return PTR_ERR(data->regmap);
+	}
+	i2c_set_clientdata(client, data);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		dev_err(&client->dev, "missing parent clock\n");
+		return -ENODEV;
+	}
+	dev_dbg(&client->dev, "parent is: %s\n", parent_name);
+
+	if (of_property_read_u32(node, "xtal-load-pf", &value) == 0)
+		regmap_write(data->regmap,
+			CDCE925_REG_XCSEL, (value << 3) & 0xF8);
+	/* PWDN bit */
+	regmap_update_bits(data->regmap, CDCE925_REG_GLOBAL1, BIT(4), 0);
+
+	/* Set input source for Y1 to be the XTAL */
+	regmap_update_bits(data->regmap, 0x02, BIT(7), 0);
+
+	init.ops = &cdce925_pll_ops;
+	init.flags = 0;
+	init.parent_names = &parent_name;
+	init.num_parents = parent_name ? 1 : 0;
+
+	/* Register PLL clocks */
+	for (i = 0; i < NUMBER_OF_PLLS; ++i) {
+		pll_clk_name[i] = kasprintf(GFP_KERNEL, "%s.pll%d",
+			client->dev.of_node->name, i);
+		init.name = pll_clk_name[i];
+		data->pll[i].chip = data;
+		data->pll[i].hw.init = &init;
+		data->pll[i].index = i;
+		clk = devm_clk_register(&client->dev, &data->pll[i].hw);
+		if (IS_ERR(clk)) {
+			dev_err(&client->dev, "Failed register PLL %d\n", i);
+			err = PTR_ERR(clk);
+			goto error;
+		}
+		sprintf(child_name, "PLL%d", i+1);
+		np_output = of_get_child_by_name(node, child_name);
+		if (!np_output)
+			continue;
+		if (!of_property_read_u32(np_output,
+			"clock-frequency", &value)) {
+			err = clk_set_rate(clk, value);
+			if (err)
+				dev_err(&client->dev,
+					"unable to set PLL frequency %ud\n",
+					value);
+		}
+		if (!of_property_read_u32(np_output,
+			"spread-spectrum", &value)) {
+			u8 flag = of_property_read_bool(np_output,
+				"spread-spectrum-center") ? 0x80 : 0x00;
+			regmap_update_bits(data->regmap,
+				0x16 + (i*CDCE925_OFFSET_PLL),
+				0x80, flag);
+			regmap_update_bits(data->regmap,
+				0x12 + (i*CDCE925_OFFSET_PLL),
+				0x07, value & 0x07);
+		}
+	}
+
+	/* Register output clock Y1 */
+	init.ops = &cdce925_clk_y1_ops;
+	init.flags = 0;
+	init.num_parents = 1;
+	init.parent_names = &parent_name; /* Mux Y1 to input */
+	init.name = kasprintf(GFP_KERNEL, "%s.Y1", client->dev.of_node->name);
+	data->clk[0].chip = data;
+	data->clk[0].hw.init = &init;
+	data->clk[0].index = 0;
+	data->clk[0].pdiv = 1;
+	clk = devm_clk_register(&client->dev, &data->clk[0].hw);
+	kfree(init.name); /* clock framework made a copy of the name */
+	if (IS_ERR(clk)) {
+		dev_err(&client->dev, "clock registration Y1 failed\n");
+		err = PTR_ERR(clk);
+		goto error;
+	}
+	data->dt_clk[0] = clk;
+
+	/* Register output clocks Y2 .. Y5*/
+	init.ops = &cdce925_clk_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.num_parents = 1;
+	for (i = 1; i < NUMBER_OF_OUTPUTS; ++i) {
+		init.name = kasprintf(GFP_KERNEL, "%s.Y%d",
+			client->dev.of_node->name, i+1);
+		data->clk[i].chip = data;
+		data->clk[i].hw.init = &init;
+		data->clk[i].index = i;
+		data->clk[i].pdiv = 1;
+		switch (i) {
+		case 1:
+		case 2:
+			/* Mux Y2/3 to PLL1 */
+			init.parent_names = &pll_clk_name[0];
+			break;
+		case 3:
+		case 4:
+			/* Mux Y4/5 to PLL2 */
+			init.parent_names = &pll_clk_name[1];
+			break;
+		}
+		clk = devm_clk_register(&client->dev, &data->clk[i].hw);
+		kfree(init.name); /* clock framework made a copy of the name */
+		if (IS_ERR(clk)) {
+			dev_err(&client->dev, "clock registration failed\n");
+			err = PTR_ERR(clk);
+			goto error;
+		}
+		data->dt_clk[i] = clk;
+	}
+
+	/* Register the output clocks */
+	data->onecell.clk_num = NUMBER_OF_OUTPUTS;
+	data->onecell.clks = data->dt_clk;
+	err = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
+		&data->onecell);
+	if (err)
+		dev_err(&client->dev, "unable to add OF clock provider\n");
+
+	err = 0;
+
+error:
+	for (i = 0; i < NUMBER_OF_PLLS; ++i)
+		/* clock framework made a copy of the name */
+		kfree(pll_clk_name[i]);
+
+	return err;
+}
+
+static const struct i2c_device_id cdce925_id[] = {
+	{ "cdce925", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cdce925_id);
+
+static const struct of_device_id clk_cdce925_of_match[] = {
+	{ .compatible = "ti,cdce925" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, clk_cdce925_of_match);
+
+static struct i2c_driver cdce925_driver = {
+	.driver = {
+		.name = "cdce925",
+		.of_match_table = of_match_ptr(clk_cdce925_of_match),
+	},
+	.probe		= cdce925_probe,
+	.id_table	= cdce925_id,
+};
+module_i2c_driver(cdce925_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("cdce925 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 956b7e5..616f5ae 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -188,7 +188,7 @@
 }
 
 struct clk *clk_register_composite(struct device *dev, const char *name,
-			const char **parent_names, int num_parents,
+			const char * const *parent_names, int num_parents,
 			struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 			struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
@@ -200,10 +200,8 @@
 	struct clk_ops *clk_composite_ops;
 
 	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
-	if (!composite) {
-		pr_err("%s: could not allocate composite clk\n", __func__);
+	if (!composite)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.flags = flags | CLK_IS_BASIC;
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 48a65b2..43a218f 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -106,8 +106,9 @@
 
 			rc = clk_set_rate(clk, rate);
 			if (rc < 0)
-				pr_err("clk: couldn't set %s clock rate: %d\n",
-				       __clk_get_name(clk), rc);
+				pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
+				       __clk_get_name(clk), rate, rc,
+				       clk_get_rate(clk));
 			clk_put(clk);
 		}
 		index++;
@@ -124,7 +125,7 @@
  * and sets any specified clock parents and rates. The @clk_supplier argument
  * should be set to true if @node may be also a clock supplier of any clock
  * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
- * If @clk_supplier is false the function exits returnning 0 as soon as it
+ * If @clk_supplier is false the function exits returning 0 as soon as it
  * determines the @node is also a supplier of any of the clocks.
  */
 int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 25006a8..706b578 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -430,11 +430,9 @@
 	}
 
 	/* allocate the divider */
-	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
-	if (!div) {
-		pr_err("%s: could not allocate divider clk\n", __func__);
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_divider_ops;
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index d9e3f67..fccabe4 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -55,10 +55,16 @@
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
 				unsigned long parent_rate)
 {
+	/*
+	 * We must report success but we can do so unconditionally because
+	 * clk_factor_round_rate returns values that ensure this call is a
+	 * nop.
+	 */
+
 	return 0;
 }
 
-struct clk_ops clk_fixed_factor_ops = {
+const struct clk_ops clk_fixed_factor_ops = {
 	.round_rate = clk_factor_round_rate,
 	.set_rate = clk_factor_set_rate,
 	.recalc_rate = clk_factor_recalc_rate,
@@ -74,10 +80,8 @@
 	struct clk *clk;
 
 	fix = kmalloc(sizeof(*fix), GFP_KERNEL);
-	if (!fix) {
-		pr_err("%s: could not allocate fixed factor clk\n", __func__);
+	if (!fix)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	/* struct clk_fixed_factor assignments */
 	fix->mult = mult;
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 0fc56ab..f85ec8d 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -65,11 +65,9 @@
 	struct clk_init_data init;
 
 	/* allocate fixed-rate clock */
-	fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
-	if (!fixed) {
-		pr_err("%s: could not allocate fixed clk\n", __func__);
+	fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+	if (!fixed)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_fixed_rate_ops;
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 6aa72d9..140eb58 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -109,10 +109,8 @@
 	struct clk *clk;
 
 	fd = kzalloc(sizeof(*fd), GFP_KERNEL);
-	if (!fd) {
-		dev_err(dev, "could not allocate fractional divider clk\n");
+	if (!fd)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_fractional_divider_ops;
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 3f0e420..551dd06 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -135,11 +135,9 @@
 	}
 
 	/* allocate the gate */
-	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-	if (!gate) {
-		pr_err("%s: could not allocate gated clk\n", __func__);
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_gate_ops;
diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
index a71cabe..f564e62 100644
--- a/drivers/clk/clk-gpio-gate.c
+++ b/drivers/clk/clk-gpio-gate.c
@@ -189,7 +189,7 @@
 /**
  * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
  */
-void __init of_gpio_gate_clk_setup(struct device_node *node)
+static void __init of_gpio_gate_clk_setup(struct device_node *node)
 {
 	struct clk_gpio_gate_delayed_register_data *data;
 
@@ -203,6 +203,5 @@
 
 	of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
 }
-EXPORT_SYMBOL_GPL(of_gpio_gate_clk_setup);
 CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
 #endif
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c
index ca80103..d4c6198 100644
--- a/drivers/clk/clk-ls1x.c
+++ b/drivers/clk/clk-ls1x.c
@@ -80,9 +80,9 @@
 	return clk;
 }
 
-static const char const *cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
-static const char const *ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
-static const char const *dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
+static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
+static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
+static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
 
 void __init ls1x_clk_init(void)
 {
diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c
index 6505049..35af9cb 100644
--- a/drivers/clk/clk-max-gen.c
+++ b/drivers/clk/clk-max-gen.c
@@ -31,6 +31,8 @@
 #include <linux/of.h>
 #include <linux/export.h>
 
+#include "clk-max-gen.h"
+
 struct max_gen_clk {
 	struct regmap *regmap;
 	u32 mask;
diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c
index 30a3b69..5181b89 100644
--- a/drivers/clk/clk-moxart.c
+++ b/drivers/clk/clk-moxart.c
@@ -15,7 +15,7 @@
 #include <linux/of_address.h>
 #include <linux/clkdev.h>
 
-void __init moxart_of_pll_clk_init(struct device_node *node)
+static void __init moxart_of_pll_clk_init(struct device_node *node)
 {
 	static void __iomem *base;
 	struct clk *clk, *ref_clk;
@@ -53,7 +53,7 @@
 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
 	       moxart_of_pll_clk_init);
 
-void __init moxart_of_apb_clk_init(struct device_node *node)
+static void __init moxart_of_apb_clk_init(struct device_node *node)
 {
 	static void __iomem *base;
 	struct clk *clk, *pll_clk;
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 69a094c..6066a01 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -114,7 +114,8 @@
 EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
@@ -166,7 +167,8 @@
 EXPORT_SYMBOL_GPL(clk_register_mux_table);
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock)
 {
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 30335d3..e39e1e6 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -552,7 +552,8 @@
  * MSx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c
  * MSx_P3[19:0] = c
  *
- * MS[6,7] are integer (P1) divide only, P2 = 0, P3 = 0
+ * MS[6,7] are integer (P1) divide only, P1 = divide value,
+ * P2 and P3 are not applicable
  *
  * for 150MHz < fOUT <= 160MHz:
  *
@@ -606,9 +607,6 @@
 	if (!hwdata->params.valid)
 		si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
 
-	if (hwdata->params.p3 == 0)
-		return parent_rate;
-
 	/*
 	 * multisync0-5: fOUT = (128 * P3 * fIN) / (P1*P3 + P2 + 512*P3)
 	 * multisync6-7: fOUT = fIN / P1
@@ -616,6 +614,8 @@
 	rate = parent_rate;
 	if (hwdata->num > 5) {
 		m = hwdata->params.p1;
+	} else if (hwdata->params.p3 == 0) {
+		return parent_rate;
 	} else if ((si5351_reg_read(hwdata->drvdata, reg + 2) &
 		    SI5351_OUTPUT_CLK_DIVBY4) == SI5351_OUTPUT_CLK_DIVBY4) {
 		m = 4;
@@ -679,6 +679,16 @@
 		c = 1;
 
 		*parent_rate = a * rate;
+	} else if (hwdata->num >= 6) {
+		/* determine the closest integer divider */
+		a = DIV_ROUND_CLOSEST(*parent_rate, rate);
+		if (a < SI5351_MULTISYNTH_A_MIN)
+			a = SI5351_MULTISYNTH_A_MIN;
+		if (a > SI5351_MULTISYNTH67_A_MAX)
+			a = SI5351_MULTISYNTH67_A_MAX;
+
+		b = 0;
+		c = 1;
 	} else {
 		unsigned long rfrac, denom;
 
@@ -692,9 +702,7 @@
 		a = *parent_rate / rate;
 		if (a < SI5351_MULTISYNTH_A_MIN)
 			a = SI5351_MULTISYNTH_A_MIN;
-		if (hwdata->num >= 6 && a > SI5351_MULTISYNTH67_A_MAX)
-			a = SI5351_MULTISYNTH67_A_MAX;
-		else if (a > SI5351_MULTISYNTH_A_MAX)
+		if (a > SI5351_MULTISYNTH_A_MAX)
 			a = SI5351_MULTISYNTH_A_MAX;
 
 		/* find best approximation for b/c = fVCO mod fOUT */
@@ -723,6 +731,10 @@
 		hwdata->params.p3 = 1;
 		hwdata->params.p2 = 0;
 		hwdata->params.p1 = 0;
+	} else if (hwdata->num >= 6) {
+		hwdata->params.p3 = 0;
+		hwdata->params.p2 = 0;
+		hwdata->params.p1 = a;
 	} else {
 		hwdata->params.p3  = c;
 		hwdata->params.p2  = (128 * b) % c;
diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
index 406bfc1..18bf5e5 100644
--- a/drivers/clk/clk-u300.c
+++ b/drivers/clk/clk-u300.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 #include <linux/of.h>
+#include <linux/platform_data/clk-u300.h>
 
 /* APP side SYSCON registers */
 /* CLK Control Register 16bit (R/W) */
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index dd8a62d..f26b3ac 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -42,12 +42,12 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static inline u32 xgene_clk_read(void *csr)
+static inline u32 xgene_clk_read(void __iomem *csr)
 {
 	return readl_relaxed(csr);
 }
 
-static inline void xgene_clk_write(u32 data, void *csr)
+static inline void xgene_clk_write(u32 data, void __iomem *csr)
 {
 	return writel_relaxed(data, csr);
 }
@@ -119,7 +119,7 @@
 	return fvco / nout;
 }
 
-const struct clk_ops xgene_clk_pll_ops = {
+static const struct clk_ops xgene_clk_pll_ops = {
 	.is_enabled = xgene_clk_pll_is_enabled,
 	.recalc_rate = xgene_clk_pll_recalc_rate,
 };
@@ -167,7 +167,7 @@
 {
         const char *clk_name = np->full_name;
         struct clk *clk;
-        void *reg;
+        void __iomem *reg;
 
         reg = of_iomap(np, 0);
         if (reg == NULL) {
@@ -222,20 +222,22 @@
 	struct xgene_clk *pclk = to_xgene_clk(hw);
 	unsigned long flags = 0;
 	u32 data;
+	phys_addr_t reg;
 
 	if (pclk->lock)
 		spin_lock_irqsave(pclk->lock, flags);
 
 	if (pclk->param.csr_reg != NULL) {
 		pr_debug("%s clock enabled\n", pclk->name);
+		reg = __pa(pclk->param.csr_reg);
 		/* First enable the clock */
 		data = xgene_clk_read(pclk->param.csr_reg +
 					pclk->param.reg_clk_offset);
 		data |= pclk->param.reg_clk_mask;
 		xgene_clk_write(data, pclk->param.csr_reg +
 					pclk->param.reg_clk_offset);
-		pr_debug("%s clock PADDR base 0x%016LX clk offset 0x%08X mask 0x%08X value 0x%08X\n",
-			pclk->name, __pa(pclk->param.csr_reg),
+		pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
+			pclk->name, &reg,
 			pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
 			data);
 
@@ -245,8 +247,8 @@
 		data &= ~pclk->param.reg_csr_mask;
 		xgene_clk_write(data, pclk->param.csr_reg +
 					pclk->param.reg_csr_offset);
-		pr_debug("%s CSR RESET PADDR base 0x%016LX csr offset 0x%08X mask 0x%08X value 0x%08X\n",
-			pclk->name, __pa(pclk->param.csr_reg),
+		pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
+			pclk->name, &reg,
 			pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
 			data);
 	}
@@ -386,7 +388,7 @@
 	return parent_rate / divider;
 }
 
-const struct clk_ops xgene_clk_ops = {
+static const struct clk_ops xgene_clk_ops = {
 	.enable = xgene_clk_enable,
 	.disable = xgene_clk_disable,
 	.is_enabled = xgene_clk_is_enabled,
@@ -456,7 +458,7 @@
 	parameters.csr_reg = NULL;
 	parameters.divider_reg = NULL;
 	for (i = 0; i < 2; i++) {
-		void *map_res;
+		void __iomem *map_res;
 		rc = of_address_to_resource(np, i, &res);
 		if (rc != 0) {
 			if (i == 0) {
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5b0f418..1cf479b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/clkdev.h>
 
 #include "clk.h"
 
@@ -37,13 +38,6 @@
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
-static long clk_core_get_accuracy(struct clk_core *clk);
-static unsigned long clk_core_get_rate(struct clk_core *clk);
-static int clk_core_get_phase(struct clk_core *clk);
-static bool clk_core_is_prepared(struct clk_core *clk);
-static bool clk_core_is_enabled(struct clk_core *clk);
-static struct clk_core *clk_core_lookup(const char *name);
-
 /***    private data structures    ***/
 
 struct clk_core {
@@ -68,11 +62,11 @@
 	int			phase;
 	struct hlist_head	children;
 	struct hlist_node	child_node;
-	struct hlist_node	debug_node;
 	struct hlist_head	clks;
 	unsigned int		notifier_count;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*dentry;
+	struct hlist_node	debug_node;
 #endif
 	struct kref		ref;
 };
@@ -145,382 +139,71 @@
 	spin_unlock_irqrestore(&enable_lock, flags);
 }
 
-/***        debugfs support        ***/
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-
-static struct dentry *rootdir;
-static int inited = 0;
-static DEFINE_MUTEX(clk_debug_lock);
-static HLIST_HEAD(clk_debug_list);
-
-static struct hlist_head *all_lists[] = {
-	&clk_root_list,
-	&clk_orphan_list,
-	NULL,
-};
-
-static struct hlist_head *orphan_list[] = {
-	&clk_orphan_list,
-	NULL,
-};
-
-static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
-				 int level)
+static bool clk_core_is_prepared(struct clk_core *core)
 {
-	if (!c)
-		return;
+	/*
+	 * .is_prepared is optional for clocks that can prepare
+	 * fall back to software usage counter if it is missing
+	 */
+	if (!core->ops->is_prepared)
+		return core->prepare_count;
 
-	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
-		   level * 3 + 1, "",
-		   30 - level * 3, c->name,
-		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
-		   clk_core_get_accuracy(c), clk_core_get_phase(c));
+	return core->ops->is_prepared(core->hw);
 }
 
-static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
-				     int level)
+static bool clk_core_is_enabled(struct clk_core *core)
 {
-	struct clk_core *child;
+	/*
+	 * .is_enabled is only mandatory for clocks that gate
+	 * fall back to software usage counter if .is_enabled is missing
+	 */
+	if (!core->ops->is_enabled)
+		return core->enable_count;
 
-	if (!c)
-		return;
-
-	clk_summary_show_one(s, c, level);
-
-	hlist_for_each_entry(child, &c->children, child_node)
-		clk_summary_show_subtree(s, child, level + 1);
+	return core->ops->is_enabled(core->hw);
 }
 
-static int clk_summary_show(struct seq_file *s, void *data)
-{
-	struct clk_core *c;
-	struct hlist_head **lists = (struct hlist_head **)s->private;
-
-	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
-	seq_puts(s, "----------------------------------------------------------------------------------------\n");
-
-	clk_prepare_lock();
-
-	for (; *lists; lists++)
-		hlist_for_each_entry(c, *lists, child_node)
-			clk_summary_show_subtree(s, c, 0);
-
-	clk_prepare_unlock();
-
-	return 0;
-}
-
-
-static int clk_summary_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clk_summary_show, inode->i_private);
-}
-
-static const struct file_operations clk_summary_fops = {
-	.open		= clk_summary_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
-{
-	if (!c)
-		return;
-
-	seq_printf(s, "\"%s\": { ", c->name);
-	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
-	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
-	seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
-	seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
-	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
-}
-
-static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
-{
-	struct clk_core *child;
-
-	if (!c)
-		return;
-
-	clk_dump_one(s, c, level);
-
-	hlist_for_each_entry(child, &c->children, child_node) {
-		seq_printf(s, ",");
-		clk_dump_subtree(s, child, level + 1);
-	}
-
-	seq_printf(s, "}");
-}
-
-static int clk_dump(struct seq_file *s, void *data)
-{
-	struct clk_core *c;
-	bool first_node = true;
-	struct hlist_head **lists = (struct hlist_head **)s->private;
-
-	seq_printf(s, "{");
-
-	clk_prepare_lock();
-
-	for (; *lists; lists++) {
-		hlist_for_each_entry(c, *lists, child_node) {
-			if (!first_node)
-				seq_puts(s, ",");
-			first_node = false;
-			clk_dump_subtree(s, c, 0);
-		}
-	}
-
-	clk_prepare_unlock();
-
-	seq_printf(s, "}");
-	return 0;
-}
-
-
-static int clk_dump_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clk_dump, inode->i_private);
-}
-
-static const struct file_operations clk_dump_fops = {
-	.open		= clk_dump_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
-{
-	struct dentry *d;
-	int ret = -ENOMEM;
-
-	if (!clk || !pdentry) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	d = debugfs_create_dir(clk->name, pdentry);
-	if (!d)
-		goto out;
-
-	clk->dentry = d;
-
-	d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
-			(u32 *)&clk->rate);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_accuracy", S_IRUGO, clk->dentry,
-			(u32 *)&clk->accuracy);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
-			(u32 *)&clk->phase);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
-			(u32 *)&clk->flags);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
-			(u32 *)&clk->prepare_count);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
-			(u32 *)&clk->enable_count);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
-			(u32 *)&clk->notifier_count);
-	if (!d)
-		goto err_out;
-
-	if (clk->ops->debug_init) {
-		ret = clk->ops->debug_init(clk->hw, clk->dentry);
-		if (ret)
-			goto err_out;
-	}
-
-	ret = 0;
-	goto out;
-
-err_out:
-	debugfs_remove_recursive(clk->dentry);
-	clk->dentry = NULL;
-out:
-	return ret;
-}
-
-/**
- * clk_debug_register - add a clk node to the debugfs clk tree
- * @clk: the clk being added to the debugfs clk tree
- *
- * Dynamically adds a clk to the debugfs clk tree if debugfs has been
- * initialized.  Otherwise it bails out early since the debugfs clk tree
- * will be created lazily by clk_debug_init as part of a late_initcall.
- */
-static int clk_debug_register(struct clk_core *clk)
-{
-	int ret = 0;
-
-	mutex_lock(&clk_debug_lock);
-	hlist_add_head(&clk->debug_node, &clk_debug_list);
-
-	if (!inited)
-		goto unlock;
-
-	ret = clk_debug_create_one(clk, rootdir);
-unlock:
-	mutex_unlock(&clk_debug_lock);
-
-	return ret;
-}
-
- /**
- * clk_debug_unregister - remove a clk node from the debugfs clk tree
- * @clk: the clk being removed from the debugfs clk tree
- *
- * Dynamically removes a clk and all it's children clk nodes from the
- * debugfs clk tree if clk->dentry points to debugfs created by
- * clk_debug_register in __clk_init.
- */
-static void clk_debug_unregister(struct clk_core *clk)
-{
-	mutex_lock(&clk_debug_lock);
-	hlist_del_init(&clk->debug_node);
-	debugfs_remove_recursive(clk->dentry);
-	clk->dentry = NULL;
-	mutex_unlock(&clk_debug_lock);
-}
-
-struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
-				void *data, const struct file_operations *fops)
-{
-	struct dentry *d = NULL;
-
-	if (hw->core->dentry)
-		d = debugfs_create_file(name, mode, hw->core->dentry, data,
-					fops);
-
-	return d;
-}
-EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
-
-/**
- * clk_debug_init - lazily create the debugfs clk tree visualization
- *
- * clks are often initialized very early during boot before memory can
- * be dynamically allocated and well before debugfs is setup.
- * clk_debug_init walks the clk tree hierarchy while holding
- * prepare_lock and creates the topology as part of a late_initcall,
- * thus insuring that clks initialized very early will still be
- * represented in the debugfs clk tree.  This function should only be
- * called once at boot-time, and all other clks added dynamically will
- * be done so with clk_debug_register.
- */
-static int __init clk_debug_init(void)
-{
-	struct clk_core *clk;
-	struct dentry *d;
-
-	rootdir = debugfs_create_dir("clk", NULL);
-
-	if (!rootdir)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
-				&clk_summary_fops);
-	if (!d)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
-				&clk_dump_fops);
-	if (!d)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
-				&orphan_list, &clk_summary_fops);
-	if (!d)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
-				&orphan_list, &clk_dump_fops);
-	if (!d)
-		return -ENOMEM;
-
-	mutex_lock(&clk_debug_lock);
-	hlist_for_each_entry(clk, &clk_debug_list, debug_node)
-		clk_debug_create_one(clk, rootdir);
-
-	inited = 1;
-	mutex_unlock(&clk_debug_lock);
-
-	return 0;
-}
-late_initcall(clk_debug_init);
-#else
-static inline int clk_debug_register(struct clk_core *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk_core *clk,
-				      struct clk_core *new_parent)
-{
-}
-static inline void clk_debug_unregister(struct clk_core *clk)
-{
-}
-#endif
-
-/* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk_core *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
 
 	lockdep_assert_held(&prepare_lock);
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		clk_unprepare_unused_subtree(child);
 
-	if (clk->prepare_count)
+	if (core->prepare_count)
 		return;
 
-	if (clk->flags & CLK_IGNORE_UNUSED)
+	if (core->flags & CLK_IGNORE_UNUSED)
 		return;
 
-	if (clk_core_is_prepared(clk)) {
-		trace_clk_unprepare(clk);
-		if (clk->ops->unprepare_unused)
-			clk->ops->unprepare_unused(clk->hw);
-		else if (clk->ops->unprepare)
-			clk->ops->unprepare(clk->hw);
-		trace_clk_unprepare_complete(clk);
+	if (clk_core_is_prepared(core)) {
+		trace_clk_unprepare(core);
+		if (core->ops->unprepare_unused)
+			core->ops->unprepare_unused(core->hw);
+		else if (core->ops->unprepare)
+			core->ops->unprepare(core->hw);
+		trace_clk_unprepare_complete(core);
 	}
 }
 
-/* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk_core *clk)
+static void clk_disable_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
 	unsigned long flags;
 
 	lockdep_assert_held(&prepare_lock);
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		clk_disable_unused_subtree(child);
 
 	flags = clk_enable_lock();
 
-	if (clk->enable_count)
+	if (core->enable_count)
 		goto unlock_out;
 
-	if (clk->flags & CLK_IGNORE_UNUSED)
+	if (core->flags & CLK_IGNORE_UNUSED)
 		goto unlock_out;
 
 	/*
@@ -528,13 +211,13 @@
 	 * sequence.  call .disable_unused if available, otherwise fall
 	 * back to .disable
 	 */
-	if (clk_core_is_enabled(clk)) {
-		trace_clk_disable(clk);
-		if (clk->ops->disable_unused)
-			clk->ops->disable_unused(clk->hw);
-		else if (clk->ops->disable)
-			clk->ops->disable(clk->hw);
-		trace_clk_disable_complete(clk);
+	if (clk_core_is_enabled(core)) {
+		trace_clk_disable(core);
+		if (core->ops->disable_unused)
+			core->ops->disable_unused(core->hw);
+		else if (core->ops->disable)
+			core->ops->disable(core->hw);
+		trace_clk_disable_complete(core);
 	}
 
 unlock_out:
@@ -551,7 +234,7 @@
 
 static int clk_disable_unused(void)
 {
-	struct clk_core *clk;
+	struct clk_core *core;
 
 	if (clk_ignore_unused) {
 		pr_warn("clk: Not disabling unused clocks\n");
@@ -560,17 +243,17 @@
 
 	clk_prepare_lock();
 
-	hlist_for_each_entry(clk, &clk_root_list, child_node)
-		clk_disable_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_root_list, child_node)
+		clk_disable_unused_subtree(core);
 
-	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
-		clk_disable_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_orphan_list, child_node)
+		clk_disable_unused_subtree(core);
 
-	hlist_for_each_entry(clk, &clk_root_list, child_node)
-		clk_unprepare_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_root_list, child_node)
+		clk_unprepare_unused_subtree(core);
 
-	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
-		clk_unprepare_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_orphan_list, child_node)
+		clk_unprepare_unused_subtree(core);
 
 	clk_prepare_unlock();
 
@@ -608,151 +291,16 @@
 }
 EXPORT_SYMBOL_GPL(__clk_get_parent);
 
-static struct clk_core *clk_core_get_parent_by_index(struct clk_core *clk,
-							 u8 index)
-{
-	if (!clk || index >= clk->num_parents)
-		return NULL;
-	else if (!clk->parents)
-		return clk_core_lookup(clk->parent_names[index]);
-	else if (!clk->parents[index])
-		return clk->parents[index] =
-			clk_core_lookup(clk->parent_names[index]);
-	else
-		return clk->parents[index];
-}
-
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
-{
-	struct clk_core *parent;
-
-	if (!clk)
-		return NULL;
-
-	parent = clk_core_get_parent_by_index(clk->core, index);
-
-	return !parent ? NULL : parent->hw->clk;
-}
-EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
-
-unsigned int __clk_get_enable_count(struct clk *clk)
-{
-	return !clk ? 0 : clk->core->enable_count;
-}
-
-static unsigned long clk_core_get_rate_nolock(struct clk_core *clk)
-{
-	unsigned long ret;
-
-	if (!clk) {
-		ret = 0;
-		goto out;
-	}
-
-	ret = clk->rate;
-
-	if (clk->flags & CLK_IS_ROOT)
-		goto out;
-
-	if (!clk->parent)
-		ret = 0;
-
-out:
-	return ret;
-}
-
-unsigned long __clk_get_rate(struct clk *clk)
-{
-	if (!clk)
-		return 0;
-
-	return clk_core_get_rate_nolock(clk->core);
-}
-EXPORT_SYMBOL_GPL(__clk_get_rate);
-
-static unsigned long __clk_get_accuracy(struct clk_core *clk)
-{
-	if (!clk)
-		return 0;
-
-	return clk->accuracy;
-}
-
-unsigned long __clk_get_flags(struct clk *clk)
-{
-	return !clk ? 0 : clk->core->flags;
-}
-EXPORT_SYMBOL_GPL(__clk_get_flags);
-
-static bool clk_core_is_prepared(struct clk_core *clk)
-{
-	int ret;
-
-	if (!clk)
-		return false;
-
-	/*
-	 * .is_prepared is optional for clocks that can prepare
-	 * fall back to software usage counter if it is missing
-	 */
-	if (!clk->ops->is_prepared) {
-		ret = clk->prepare_count ? 1 : 0;
-		goto out;
-	}
-
-	ret = clk->ops->is_prepared(clk->hw);
-out:
-	return !!ret;
-}
-
-bool __clk_is_prepared(struct clk *clk)
-{
-	if (!clk)
-		return false;
-
-	return clk_core_is_prepared(clk->core);
-}
-
-static bool clk_core_is_enabled(struct clk_core *clk)
-{
-	int ret;
-
-	if (!clk)
-		return false;
-
-	/*
-	 * .is_enabled is only mandatory for clocks that gate
-	 * fall back to software usage counter if .is_enabled is missing
-	 */
-	if (!clk->ops->is_enabled) {
-		ret = clk->enable_count ? 1 : 0;
-		goto out;
-	}
-
-	ret = clk->ops->is_enabled(clk->hw);
-out:
-	return !!ret;
-}
-
-bool __clk_is_enabled(struct clk *clk)
-{
-	if (!clk)
-		return false;
-
-	return clk_core_is_enabled(clk->core);
-}
-EXPORT_SYMBOL_GPL(__clk_is_enabled);
-
 static struct clk_core *__clk_lookup_subtree(const char *name,
-					     struct clk_core *clk)
+					     struct clk_core *core)
 {
 	struct clk_core *child;
 	struct clk_core *ret;
 
-	if (!strcmp(clk->name, name))
-		return clk;
+	if (!strcmp(core->name, name))
+		return core;
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		ret = __clk_lookup_subtree(name, child);
 		if (ret)
 			return ret;
@@ -786,6 +334,99 @@
 	return NULL;
 }
 
+static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
+							 u8 index)
+{
+	if (!core || index >= core->num_parents)
+		return NULL;
+	else if (!core->parents)
+		return clk_core_lookup(core->parent_names[index]);
+	else if (!core->parents[index])
+		return core->parents[index] =
+			clk_core_lookup(core->parent_names[index]);
+	else
+		return core->parents[index];
+}
+
+struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+{
+	struct clk_core *parent;
+
+	if (!clk)
+		return NULL;
+
+	parent = clk_core_get_parent_by_index(clk->core, index);
+
+	return !parent ? NULL : parent->hw->clk;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
+
+unsigned int __clk_get_enable_count(struct clk *clk)
+{
+	return !clk ? 0 : clk->core->enable_count;
+}
+
+static unsigned long clk_core_get_rate_nolock(struct clk_core *core)
+{
+	unsigned long ret;
+
+	if (!core) {
+		ret = 0;
+		goto out;
+	}
+
+	ret = core->rate;
+
+	if (core->flags & CLK_IS_ROOT)
+		goto out;
+
+	if (!core->parent)
+		ret = 0;
+
+out:
+	return ret;
+}
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_rate_nolock(clk->core);
+}
+EXPORT_SYMBOL_GPL(__clk_get_rate);
+
+static unsigned long __clk_get_accuracy(struct clk_core *core)
+{
+	if (!core)
+		return 0;
+
+	return core->accuracy;
+}
+
+unsigned long __clk_get_flags(struct clk *clk)
+{
+	return !clk ? 0 : clk->core->flags;
+}
+EXPORT_SYMBOL_GPL(__clk_get_flags);
+
+bool __clk_is_prepared(struct clk *clk)
+{
+	if (!clk)
+		return false;
+
+	return clk_core_is_prepared(clk->core);
+}
+
+bool __clk_is_enabled(struct clk *clk)
+{
+	if (!clk)
+		return false;
+
+	return clk_core_is_enabled(clk->core);
+}
+EXPORT_SYMBOL_GPL(__clk_is_enabled);
+
 static bool mux_is_better_rate(unsigned long rate, unsigned long now,
 			   unsigned long best, unsigned long flags)
 {
@@ -853,7 +494,7 @@
 	return !core ? NULL : core->hw->clk;
 }
 
-static void clk_core_get_boundaries(struct clk_core *clk,
+static void clk_core_get_boundaries(struct clk_core *core,
 				    unsigned long *min_rate,
 				    unsigned long *max_rate)
 {
@@ -862,10 +503,10 @@
 	*min_rate = 0;
 	*max_rate = ULONG_MAX;
 
-	hlist_for_each_entry(clk_user, &clk->clks, clks_node)
+	hlist_for_each_entry(clk_user, &core->clks, clks_node)
 		*min_rate = max(*min_rate, clk_user->min_rate);
 
-	hlist_for_each_entry(clk_user, &clk->clks, clks_node)
+	hlist_for_each_entry(clk_user, &core->clks, clks_node)
 		*max_rate = min(*max_rate, clk_user->max_rate);
 }
 
@@ -901,26 +542,28 @@
 
 /***        clk api        ***/
 
-static void clk_core_unprepare(struct clk_core *clk)
+static void clk_core_unprepare(struct clk_core *core)
 {
-	if (!clk)
+	lockdep_assert_held(&prepare_lock);
+
+	if (!core)
 		return;
 
-	if (WARN_ON(clk->prepare_count == 0))
+	if (WARN_ON(core->prepare_count == 0))
 		return;
 
-	if (--clk->prepare_count > 0)
+	if (--core->prepare_count > 0)
 		return;
 
-	WARN_ON(clk->enable_count > 0);
+	WARN_ON(core->enable_count > 0);
 
-	trace_clk_unprepare(clk);
+	trace_clk_unprepare(core);
 
-	if (clk->ops->unprepare)
-		clk->ops->unprepare(clk->hw);
+	if (core->ops->unprepare)
+		core->ops->unprepare(core->hw);
 
-	trace_clk_unprepare_complete(clk);
-	clk_core_unprepare(clk->parent);
+	trace_clk_unprepare_complete(core);
+	clk_core_unprepare(core->parent);
 }
 
 /**
@@ -945,32 +588,34 @@
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
-static int clk_core_prepare(struct clk_core *clk)
+static int clk_core_prepare(struct clk_core *core)
 {
 	int ret = 0;
 
-	if (!clk)
+	lockdep_assert_held(&prepare_lock);
+
+	if (!core)
 		return 0;
 
-	if (clk->prepare_count == 0) {
-		ret = clk_core_prepare(clk->parent);
+	if (core->prepare_count == 0) {
+		ret = clk_core_prepare(core->parent);
 		if (ret)
 			return ret;
 
-		trace_clk_prepare(clk);
+		trace_clk_prepare(core);
 
-		if (clk->ops->prepare)
-			ret = clk->ops->prepare(clk->hw);
+		if (core->ops->prepare)
+			ret = core->ops->prepare(core->hw);
 
-		trace_clk_prepare_complete(clk);
+		trace_clk_prepare_complete(core);
 
 		if (ret) {
-			clk_core_unprepare(clk->parent);
+			clk_core_unprepare(core->parent);
 			return ret;
 		}
 	}
 
-	clk->prepare_count++;
+	core->prepare_count++;
 
 	return 0;
 }
@@ -1002,33 +647,27 @@
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
 
-static void clk_core_disable(struct clk_core *clk)
+static void clk_core_disable(struct clk_core *core)
 {
-	if (!clk)
+	lockdep_assert_held(&enable_lock);
+
+	if (!core)
 		return;
 
-	if (WARN_ON(clk->enable_count == 0))
+	if (WARN_ON(core->enable_count == 0))
 		return;
 
-	if (--clk->enable_count > 0)
+	if (--core->enable_count > 0)
 		return;
 
-	trace_clk_disable(clk);
+	trace_clk_disable(core);
 
-	if (clk->ops->disable)
-		clk->ops->disable(clk->hw);
+	if (core->ops->disable)
+		core->ops->disable(core->hw);
 
-	trace_clk_disable_complete(clk);
+	trace_clk_disable_complete(core);
 
-	clk_core_disable(clk->parent);
-}
-
-static void __clk_disable(struct clk *clk)
-{
-	if (!clk)
-		return;
-
-	clk_core_disable(clk->core);
+	clk_core_disable(core->parent);
 }
 
 /**
@@ -1051,52 +690,46 @@
 		return;
 
 	flags = clk_enable_lock();
-	__clk_disable(clk);
+	clk_core_disable(clk->core);
 	clk_enable_unlock(flags);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
-static int clk_core_enable(struct clk_core *clk)
+static int clk_core_enable(struct clk_core *core)
 {
 	int ret = 0;
 
-	if (!clk)
+	lockdep_assert_held(&enable_lock);
+
+	if (!core)
 		return 0;
 
-	if (WARN_ON(clk->prepare_count == 0))
+	if (WARN_ON(core->prepare_count == 0))
 		return -ESHUTDOWN;
 
-	if (clk->enable_count == 0) {
-		ret = clk_core_enable(clk->parent);
+	if (core->enable_count == 0) {
+		ret = clk_core_enable(core->parent);
 
 		if (ret)
 			return ret;
 
-		trace_clk_enable(clk);
+		trace_clk_enable(core);
 
-		if (clk->ops->enable)
-			ret = clk->ops->enable(clk->hw);
+		if (core->ops->enable)
+			ret = core->ops->enable(core->hw);
 
-		trace_clk_enable_complete(clk);
+		trace_clk_enable_complete(core);
 
 		if (ret) {
-			clk_core_disable(clk->parent);
+			clk_core_disable(core->parent);
 			return ret;
 		}
 	}
 
-	clk->enable_count++;
+	core->enable_count++;
 	return 0;
 }
 
-static int __clk_enable(struct clk *clk)
-{
-	if (!clk)
-		return 0;
-
-	return clk_core_enable(clk->core);
-}
-
 /**
  * clk_enable - ungate a clock
  * @clk: the clk being ungated
@@ -1115,15 +748,18 @@
 	unsigned long flags;
 	int ret;
 
+	if (!clk)
+		return 0;
+
 	flags = clk_enable_lock();
-	ret = __clk_enable(clk);
+	ret = clk_core_enable(clk->core);
 	clk_enable_unlock(flags);
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
-static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
 						unsigned long rate,
 						unsigned long min_rate,
 						unsigned long max_rate)
@@ -1134,25 +770,25 @@
 
 	lockdep_assert_held(&prepare_lock);
 
-	if (!clk)
+	if (!core)
 		return 0;
 
-	parent = clk->parent;
+	parent = core->parent;
 	if (parent)
 		parent_rate = parent->rate;
 
-	if (clk->ops->determine_rate) {
+	if (core->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		return clk->ops->determine_rate(clk->hw, rate,
+		return core->ops->determine_rate(core->hw, rate,
 						min_rate, max_rate,
 						&parent_rate, &parent_hw);
-	} else if (clk->ops->round_rate)
-		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
-	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+	} else if (core->ops->round_rate)
+		return core->ops->round_rate(core->hw, rate, &parent_rate);
+	else if (core->flags & CLK_SET_RATE_PARENT)
+		return clk_core_round_rate_nolock(core->parent, rate, min_rate,
 						  max_rate);
 	else
-		return clk->rate;
+		return core->rate;
 }
 
 /**
@@ -1162,8 +798,7 @@
  * @min_rate: returned rate must be greater than this rate
  * @max_rate: returned rate must be less than this rate
  *
- * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate and
- * .determine_rate.
+ * Useful for clk_ops such as .set_rate and .determine_rate.
  */
 unsigned long __clk_determine_rate(struct clk_hw *hw,
 				   unsigned long rate,
@@ -1182,7 +817,7 @@
  * @clk: round the rate of this clock
  * @rate: the rate which is to be rounded
  *
- * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
+ * Useful for clk_ops such as .set_rate
  */
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 {
@@ -1224,7 +859,7 @@
 
 /**
  * __clk_notify - call clk notifier chain
- * @clk: struct clk * that is changing rate
+ * @core: clk that is changing rate
  * @msg: clk notifier type (see include/linux/clk.h)
  * @old_rate: old clk rate
  * @new_rate: new clk rate
@@ -1236,7 +871,7 @@
  * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
  * a driver returns that.
  */
-static int __clk_notify(struct clk_core *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *core, unsigned long msg,
 		unsigned long old_rate, unsigned long new_rate)
 {
 	struct clk_notifier *cn;
@@ -1247,7 +882,7 @@
 	cnd.new_rate = new_rate;
 
 	list_for_each_entry(cn, &clk_notifier_list, node) {
-		if (cn->clk->core == clk) {
+		if (cn->clk->core == core) {
 			cnd.clk = cn->clk;
 			ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
 					&cnd);
@@ -1259,44 +894,42 @@
 
 /**
  * __clk_recalc_accuracies
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
  *
  * Walks the subtree of clks starting with clk and recalculates accuracies as
  * it goes.  Note that if a clk does not implement the .recalc_accuracy
- * callback then it is assumed that the clock will take on the accuracy of it's
+ * callback then it is assumed that the clock will take on the accuracy of its
  * parent.
- *
- * Caller must hold prepare_lock.
  */
-static void __clk_recalc_accuracies(struct clk_core *clk)
+static void __clk_recalc_accuracies(struct clk_core *core)
 {
 	unsigned long parent_accuracy = 0;
 	struct clk_core *child;
 
 	lockdep_assert_held(&prepare_lock);
 
-	if (clk->parent)
-		parent_accuracy = clk->parent->accuracy;
+	if (core->parent)
+		parent_accuracy = core->parent->accuracy;
 
-	if (clk->ops->recalc_accuracy)
-		clk->accuracy = clk->ops->recalc_accuracy(clk->hw,
+	if (core->ops->recalc_accuracy)
+		core->accuracy = core->ops->recalc_accuracy(core->hw,
 							  parent_accuracy);
 	else
-		clk->accuracy = parent_accuracy;
+		core->accuracy = parent_accuracy;
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		__clk_recalc_accuracies(child);
 }
 
-static long clk_core_get_accuracy(struct clk_core *clk)
+static long clk_core_get_accuracy(struct clk_core *core)
 {
 	unsigned long accuracy;
 
 	clk_prepare_lock();
-	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
-		__clk_recalc_accuracies(clk);
+	if (core && (core->flags & CLK_GET_ACCURACY_NOCACHE))
+		__clk_recalc_accuracies(core);
 
-	accuracy = __clk_get_accuracy(clk);
+	accuracy = __clk_get_accuracy(core);
 	clk_prepare_unlock();
 
 	return accuracy;
@@ -1320,17 +953,17 @@
 }
 EXPORT_SYMBOL_GPL(clk_get_accuracy);
 
-static unsigned long clk_recalc(struct clk_core *clk,
+static unsigned long clk_recalc(struct clk_core *core,
 				unsigned long parent_rate)
 {
-	if (clk->ops->recalc_rate)
-		return clk->ops->recalc_rate(clk->hw, parent_rate);
+	if (core->ops->recalc_rate)
+		return core->ops->recalc_rate(core->hw, parent_rate);
 	return parent_rate;
 }
 
 /**
  * __clk_recalc_rates
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
  * @msg: notification type (see include/linux/clk.h)
  *
  * Walks the subtree of clks starting with clk and recalculates rates as it
@@ -1339,10 +972,8 @@
  *
  * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
  * if necessary.
- *
- * Caller must hold prepare_lock.
  */
-static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
 {
 	unsigned long old_rate;
 	unsigned long parent_rate = 0;
@@ -1350,34 +981,34 @@
 
 	lockdep_assert_held(&prepare_lock);
 
-	old_rate = clk->rate;
+	old_rate = core->rate;
 
-	if (clk->parent)
-		parent_rate = clk->parent->rate;
+	if (core->parent)
+		parent_rate = core->parent->rate;
 
-	clk->rate = clk_recalc(clk, parent_rate);
+	core->rate = clk_recalc(core, parent_rate);
 
 	/*
 	 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
 	 * & ABORT_RATE_CHANGE notifiers
 	 */
-	if (clk->notifier_count && msg)
-		__clk_notify(clk, msg, old_rate, clk->rate);
+	if (core->notifier_count && msg)
+		__clk_notify(core, msg, old_rate, core->rate);
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		__clk_recalc_rates(child, msg);
 }
 
-static unsigned long clk_core_get_rate(struct clk_core *clk)
+static unsigned long clk_core_get_rate(struct clk_core *core)
 {
 	unsigned long rate;
 
 	clk_prepare_lock();
 
-	if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
-		__clk_recalc_rates(clk, 0);
+	if (core && (core->flags & CLK_GET_RATE_NOCACHE))
+		__clk_recalc_rates(core, 0);
 
-	rate = clk_core_get_rate_nolock(clk);
+	rate = clk_core_get_rate_nolock(core);
 	clk_prepare_unlock();
 
 	return rate;
@@ -1400,15 +1031,15 @@
 }
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
-static int clk_fetch_parent_index(struct clk_core *clk,
+static int clk_fetch_parent_index(struct clk_core *core,
 				  struct clk_core *parent)
 {
 	int i;
 
-	if (!clk->parents) {
-		clk->parents = kcalloc(clk->num_parents,
+	if (!core->parents) {
+		core->parents = kcalloc(core->num_parents,
 					sizeof(struct clk *), GFP_KERNEL);
-		if (!clk->parents)
+		if (!core->parents)
 			return -ENOMEM;
 	}
 
@@ -1417,15 +1048,15 @@
 	 * or if not yet cached, use string name comparison and cache
 	 * them now to avoid future calls to clk_core_lookup.
 	 */
-	for (i = 0; i < clk->num_parents; i++) {
-		if (clk->parents[i] == parent)
+	for (i = 0; i < core->num_parents; i++) {
+		if (core->parents[i] == parent)
 			return i;
 
-		if (clk->parents[i])
+		if (core->parents[i])
 			continue;
 
-		if (!strcmp(clk->parent_names[i], parent->name)) {
-			clk->parents[i] = clk_core_lookup(parent->name);
+		if (!strcmp(core->parent_names[i], parent->name)) {
+			core->parents[i] = clk_core_lookup(parent->name);
 			return i;
 		}
 	}
@@ -1433,28 +1064,28 @@
 	return -EINVAL;
 }
 
-static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
+static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
 {
-	hlist_del(&clk->child_node);
+	hlist_del(&core->child_node);
 
 	if (new_parent) {
 		/* avoid duplicate POST_RATE_CHANGE notifications */
-		if (new_parent->new_child == clk)
+		if (new_parent->new_child == core)
 			new_parent->new_child = NULL;
 
-		hlist_add_head(&clk->child_node, &new_parent->children);
+		hlist_add_head(&core->child_node, &new_parent->children);
 	} else {
-		hlist_add_head(&clk->child_node, &clk_orphan_list);
+		hlist_add_head(&core->child_node, &clk_orphan_list);
 	}
 
-	clk->parent = new_parent;
+	core->parent = new_parent;
 }
 
-static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+static struct clk_core *__clk_set_parent_before(struct clk_core *core,
 					   struct clk_core *parent)
 {
 	unsigned long flags;
-	struct clk_core *old_parent = clk->parent;
+	struct clk_core *old_parent = core->parent;
 
 	/*
 	 * Migrate prepare state between parents and prevent race with
@@ -1473,17 +1104,17 @@
 	 *
 	 * See also: Comment for clk_set_parent() below.
 	 */
-	if (clk->prepare_count) {
+	if (core->prepare_count) {
 		clk_core_prepare(parent);
 		flags = clk_enable_lock();
 		clk_core_enable(parent);
-		clk_core_enable(clk);
+		clk_core_enable(core);
 		clk_enable_unlock(flags);
 	}
 
 	/* update the clk tree topology */
 	flags = clk_enable_lock();
-	clk_reparent(clk, parent);
+	clk_reparent(core, parent);
 	clk_enable_unlock(flags);
 
 	return old_parent;
@@ -1508,31 +1139,31 @@
 	}
 }
 
-static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
 			    u8 p_index)
 {
 	unsigned long flags;
 	int ret = 0;
 	struct clk_core *old_parent;
 
-	old_parent = __clk_set_parent_before(clk, parent);
+	old_parent = __clk_set_parent_before(core, parent);
 
-	trace_clk_set_parent(clk, parent);
+	trace_clk_set_parent(core, parent);
 
 	/* change clock input source */
-	if (parent && clk->ops->set_parent)
-		ret = clk->ops->set_parent(clk->hw, p_index);
+	if (parent && core->ops->set_parent)
+		ret = core->ops->set_parent(core->hw, p_index);
 
-	trace_clk_set_parent_complete(clk, parent);
+	trace_clk_set_parent_complete(core, parent);
 
 	if (ret) {
 		flags = clk_enable_lock();
-		clk_reparent(clk, old_parent);
+		clk_reparent(core, old_parent);
 		clk_enable_unlock(flags);
 
-		if (clk->prepare_count) {
+		if (core->prepare_count) {
 			flags = clk_enable_lock();
-			clk_core_disable(clk);
+			clk_core_disable(core);
 			clk_core_disable(parent);
 			clk_enable_unlock(flags);
 			clk_core_unprepare(parent);
@@ -1540,14 +1171,14 @@
 		return ret;
 	}
 
-	__clk_set_parent_after(clk, parent, old_parent);
+	__clk_set_parent_after(core, parent, old_parent);
 
 	return 0;
 }
 
 /**
  * __clk_speculate_rates
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
  * @parent_rate: the "future" rate of clk's parent
  *
  * Walks the subtree of clks starting with clk, speculating rates as it
@@ -1558,10 +1189,8 @@
  * subtree have subscribed to the notifications.  Note that if a clk does not
  * implement the .recalc_rate callback then it is assumed that the clock will
  * take on the rate of its parent.
- *
- * Caller must hold prepare_lock.
  */
-static int __clk_speculate_rates(struct clk_core *clk,
+static int __clk_speculate_rates(struct clk_core *core,
 				 unsigned long parent_rate)
 {
 	struct clk_core *child;
@@ -1570,19 +1199,19 @@
 
 	lockdep_assert_held(&prepare_lock);
 
-	new_rate = clk_recalc(clk, parent_rate);
+	new_rate = clk_recalc(core, parent_rate);
 
 	/* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
-	if (clk->notifier_count)
-		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
+	if (core->notifier_count)
+		ret = __clk_notify(core, PRE_RATE_CHANGE, core->rate, new_rate);
 
 	if (ret & NOTIFY_STOP_MASK) {
 		pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n",
-				__func__, clk->name, ret);
+				__func__, core->name, ret);
 		goto out;
 	}
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		ret = __clk_speculate_rates(child, new_rate);
 		if (ret & NOTIFY_STOP_MASK)
 			break;
@@ -1592,20 +1221,20 @@
 	return ret;
 }
 
-static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
 			     struct clk_core *new_parent, u8 p_index)
 {
 	struct clk_core *child;
 
-	clk->new_rate = new_rate;
-	clk->new_parent = new_parent;
-	clk->new_parent_index = p_index;
+	core->new_rate = new_rate;
+	core->new_parent = new_parent;
+	core->new_parent_index = p_index;
 	/* include clk in new parent's PRE_RATE_CHANGE notifications */
-	clk->new_child = NULL;
-	if (new_parent && new_parent != clk->parent)
-		new_parent->new_child = clk;
+	core->new_child = NULL;
+	if (new_parent && new_parent != core->parent)
+		new_parent->new_child = core;
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		child->new_rate = clk_recalc(child, new_rate);
 		clk_calc_subtree(child, child->new_rate, NULL, 0);
 	}
@@ -1615,10 +1244,10 @@
  * calculate the new rates returning the topmost clock that has to be
  * changed.
  */
-static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 					   unsigned long rate)
 {
-	struct clk_core *top = clk;
+	struct clk_core *top = core;
 	struct clk_core *old_parent, *parent;
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
@@ -1629,20 +1258,20 @@
 	long ret;
 
 	/* sanity */
-	if (IS_ERR_OR_NULL(clk))
+	if (IS_ERR_OR_NULL(core))
 		return NULL;
 
 	/* save parent rate, if it exists */
-	parent = old_parent = clk->parent;
+	parent = old_parent = core->parent;
 	if (parent)
 		best_parent_rate = parent->rate;
 
-	clk_core_get_boundaries(clk, &min_rate, &max_rate);
+	clk_core_get_boundaries(core, &min_rate, &max_rate);
 
 	/* find the closest rate and parent clk/rate */
-	if (clk->ops->determine_rate) {
+	if (core->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		ret = clk->ops->determine_rate(clk->hw, rate,
+		ret = core->ops->determine_rate(core->hw, rate,
 					       min_rate,
 					       max_rate,
 					       &best_parent_rate,
@@ -1652,8 +1281,8 @@
 
 		new_rate = ret;
 		parent = parent_hw ? parent_hw->core : NULL;
-	} else if (clk->ops->round_rate) {
-		ret = clk->ops->round_rate(clk->hw, rate,
+	} else if (core->ops->round_rate) {
+		ret = core->ops->round_rate(core->hw, rate,
 					   &best_parent_rate);
 		if (ret < 0)
 			return NULL;
@@ -1661,9 +1290,9 @@
 		new_rate = ret;
 		if (new_rate < min_rate || new_rate > max_rate)
 			return NULL;
-	} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
+	} else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) {
 		/* pass-through clock without adjustable parent */
-		clk->new_rate = clk->rate;
+		core->new_rate = core->rate;
 		return NULL;
 	} else {
 		/* pass-through clock with adjustable parent */
@@ -1674,28 +1303,28 @@
 
 	/* some clocks must be gated to change parent */
 	if (parent != old_parent &&
-	    (clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
+	    (core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
 		pr_debug("%s: %s not gated but wants to reparent\n",
-			 __func__, clk->name);
+			 __func__, core->name);
 		return NULL;
 	}
 
 	/* try finding the new parent index */
-	if (parent && clk->num_parents > 1) {
-		p_index = clk_fetch_parent_index(clk, parent);
+	if (parent && core->num_parents > 1) {
+		p_index = clk_fetch_parent_index(core, parent);
 		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
-				 __func__, parent->name, clk->name);
+				 __func__, parent->name, core->name);
 			return NULL;
 		}
 	}
 
-	if ((clk->flags & CLK_SET_RATE_PARENT) && parent &&
+	if ((core->flags & CLK_SET_RATE_PARENT) && parent &&
 	    best_parent_rate != parent->rate)
 		top = clk_calc_new_rates(parent, best_parent_rate);
 
 out:
-	clk_calc_subtree(clk, new_rate, parent, p_index);
+	clk_calc_subtree(core, new_rate, parent, p_index);
 
 	return top;
 }
@@ -1705,33 +1334,33 @@
  * so that in case of an error we can walk down the whole tree again and
  * abort the change.
  */
-static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
 						  unsigned long event)
 {
 	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
 	int ret = NOTIFY_DONE;
 
-	if (clk->rate == clk->new_rate)
+	if (core->rate == core->new_rate)
 		return NULL;
 
-	if (clk->notifier_count) {
-		ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
+	if (core->notifier_count) {
+		ret = __clk_notify(core, event, core->rate, core->new_rate);
 		if (ret & NOTIFY_STOP_MASK)
-			fail_clk = clk;
+			fail_clk = core;
 	}
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		/* Skip children who will be reparented to another clock */
-		if (child->new_parent && child->new_parent != clk)
+		if (child->new_parent && child->new_parent != core)
 			continue;
 		tmp_clk = clk_propagate_rate_change(child, event);
 		if (tmp_clk)
 			fail_clk = tmp_clk;
 	}
 
-	/* handle the new child who might not be in clk->children yet */
-	if (clk->new_child) {
-		tmp_clk = clk_propagate_rate_change(clk->new_child, event);
+	/* handle the new child who might not be in core->children yet */
+	if (core->new_child) {
+		tmp_clk = clk_propagate_rate_change(core->new_child, event);
 		if (tmp_clk)
 			fail_clk = tmp_clk;
 	}
@@ -1743,7 +1372,7 @@
  * walk down a subtree and set the new rates notifying the rate
  * change on the way
  */
-static void clk_change_rate(struct clk_core *clk)
+static void clk_change_rate(struct clk_core *core)
 {
 	struct clk_core *child;
 	struct hlist_node *tmp;
@@ -1752,77 +1381,77 @@
 	bool skip_set_rate = false;
 	struct clk_core *old_parent;
 
-	old_rate = clk->rate;
+	old_rate = core->rate;
 
-	if (clk->new_parent)
-		best_parent_rate = clk->new_parent->rate;
-	else if (clk->parent)
-		best_parent_rate = clk->parent->rate;
+	if (core->new_parent)
+		best_parent_rate = core->new_parent->rate;
+	else if (core->parent)
+		best_parent_rate = core->parent->rate;
 
-	if (clk->new_parent && clk->new_parent != clk->parent) {
-		old_parent = __clk_set_parent_before(clk, clk->new_parent);
-		trace_clk_set_parent(clk, clk->new_parent);
+	if (core->new_parent && core->new_parent != core->parent) {
+		old_parent = __clk_set_parent_before(core, core->new_parent);
+		trace_clk_set_parent(core, core->new_parent);
 
-		if (clk->ops->set_rate_and_parent) {
+		if (core->ops->set_rate_and_parent) {
 			skip_set_rate = true;
-			clk->ops->set_rate_and_parent(clk->hw, clk->new_rate,
+			core->ops->set_rate_and_parent(core->hw, core->new_rate,
 					best_parent_rate,
-					clk->new_parent_index);
-		} else if (clk->ops->set_parent) {
-			clk->ops->set_parent(clk->hw, clk->new_parent_index);
+					core->new_parent_index);
+		} else if (core->ops->set_parent) {
+			core->ops->set_parent(core->hw, core->new_parent_index);
 		}
 
-		trace_clk_set_parent_complete(clk, clk->new_parent);
-		__clk_set_parent_after(clk, clk->new_parent, old_parent);
+		trace_clk_set_parent_complete(core, core->new_parent);
+		__clk_set_parent_after(core, core->new_parent, old_parent);
 	}
 
-	trace_clk_set_rate(clk, clk->new_rate);
+	trace_clk_set_rate(core, core->new_rate);
 
-	if (!skip_set_rate && clk->ops->set_rate)
-		clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
+	if (!skip_set_rate && core->ops->set_rate)
+		core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
 
-	trace_clk_set_rate_complete(clk, clk->new_rate);
+	trace_clk_set_rate_complete(core, core->new_rate);
 
-	clk->rate = clk_recalc(clk, best_parent_rate);
+	core->rate = clk_recalc(core, best_parent_rate);
 
-	if (clk->notifier_count && old_rate != clk->rate)
-		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
+	if (core->notifier_count && old_rate != core->rate)
+		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
 
 	/*
 	 * Use safe iteration, as change_rate can actually swap parents
 	 * for certain clock types.
 	 */
-	hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) {
+	hlist_for_each_entry_safe(child, tmp, &core->children, child_node) {
 		/* Skip children who will be reparented to another clock */
-		if (child->new_parent && child->new_parent != clk)
+		if (child->new_parent && child->new_parent != core)
 			continue;
 		clk_change_rate(child);
 	}
 
-	/* handle the new child who might not be in clk->children yet */
-	if (clk->new_child)
-		clk_change_rate(clk->new_child);
+	/* handle the new child who might not be in core->children yet */
+	if (core->new_child)
+		clk_change_rate(core->new_child);
 }
 
-static int clk_core_set_rate_nolock(struct clk_core *clk,
+static int clk_core_set_rate_nolock(struct clk_core *core,
 				    unsigned long req_rate)
 {
 	struct clk_core *top, *fail_clk;
 	unsigned long rate = req_rate;
 	int ret = 0;
 
-	if (!clk)
+	if (!core)
 		return 0;
 
 	/* bail early if nothing to do */
-	if (rate == clk_core_get_rate_nolock(clk))
+	if (rate == clk_core_get_rate_nolock(core))
 		return 0;
 
-	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+	if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
 		return -EBUSY;
 
 	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk, rate);
+	top = clk_calc_new_rates(core, rate);
 	if (!top)
 		return -EINVAL;
 
@@ -1838,7 +1467,7 @@
 	/* change the rates */
 	clk_change_rate(top);
 
-	clk->req_rate = req_rate;
+	core->req_rate = req_rate;
 
 	return ret;
 }
@@ -1977,55 +1606,55 @@
  * .parents array exists, and if so use it to avoid an expensive tree
  * traversal.  If .parents does not exist then walk the tree.
  */
-static struct clk_core *__clk_init_parent(struct clk_core *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *core)
 {
 	struct clk_core *ret = NULL;
 	u8 index;
 
 	/* handle the trivial cases */
 
-	if (!clk->num_parents)
+	if (!core->num_parents)
 		goto out;
 
-	if (clk->num_parents == 1) {
-		if (IS_ERR_OR_NULL(clk->parent))
-			clk->parent = clk_core_lookup(clk->parent_names[0]);
-		ret = clk->parent;
+	if (core->num_parents == 1) {
+		if (IS_ERR_OR_NULL(core->parent))
+			core->parent = clk_core_lookup(core->parent_names[0]);
+		ret = core->parent;
 		goto out;
 	}
 
-	if (!clk->ops->get_parent) {
-		WARN(!clk->ops->get_parent,
+	if (!core->ops->get_parent) {
+		WARN(!core->ops->get_parent,
 			"%s: multi-parent clocks must implement .get_parent\n",
 			__func__);
 		goto out;
 	};
 
 	/*
-	 * Do our best to cache parent clocks in clk->parents.  This prevents
-	 * unnecessary and expensive lookups.  We don't set clk->parent here;
+	 * Do our best to cache parent clocks in core->parents.  This prevents
+	 * unnecessary and expensive lookups.  We don't set core->parent here;
 	 * that is done by the calling function.
 	 */
 
-	index = clk->ops->get_parent(clk->hw);
+	index = core->ops->get_parent(core->hw);
 
-	if (!clk->parents)
-		clk->parents =
-			kcalloc(clk->num_parents, sizeof(struct clk *),
+	if (!core->parents)
+		core->parents =
+			kcalloc(core->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 
-	ret = clk_core_get_parent_by_index(clk, index);
+	ret = clk_core_get_parent_by_index(core, index);
 
 out:
 	return ret;
 }
 
-static void clk_core_reparent(struct clk_core *clk,
+static void clk_core_reparent(struct clk_core *core,
 				  struct clk_core *new_parent)
 {
-	clk_reparent(clk, new_parent);
-	__clk_recalc_accuracies(clk);
-	__clk_recalc_rates(clk, POST_RATE_CHANGE);
+	clk_reparent(core, new_parent);
+	__clk_recalc_accuracies(core);
+	__clk_recalc_rates(core, POST_RATE_CHANGE);
 }
 
 /**
@@ -2062,61 +1691,61 @@
 }
 EXPORT_SYMBOL_GPL(clk_has_parent);
 
-static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
+static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;
 	unsigned long p_rate = 0;
 
-	if (!clk)
+	if (!core)
 		return 0;
 
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
-	if (clk->parent == parent)
+	if (core->parent == parent)
 		goto out;
 
 	/* verify ops for for multi-parent clks */
-	if ((clk->num_parents > 1) && (!clk->ops->set_parent)) {
+	if ((core->num_parents > 1) && (!core->ops->set_parent)) {
 		ret = -ENOSYS;
 		goto out;
 	}
 
 	/* check that we are allowed to re-parent if the clock is in use */
-	if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
+	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	/* try finding the new parent index */
 	if (parent) {
-		p_index = clk_fetch_parent_index(clk, parent);
+		p_index = clk_fetch_parent_index(core, parent);
 		p_rate = parent->rate;
 		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
-					__func__, parent->name, clk->name);
+					__func__, parent->name, core->name);
 			ret = p_index;
 			goto out;
 		}
 	}
 
 	/* propagate PRE_RATE_CHANGE notifications */
-	ret = __clk_speculate_rates(clk, p_rate);
+	ret = __clk_speculate_rates(core, p_rate);
 
 	/* abort if a driver objects */
 	if (ret & NOTIFY_STOP_MASK)
 		goto out;
 
 	/* do the re-parent */
-	ret = __clk_set_parent(clk, parent, p_index);
+	ret = __clk_set_parent(core, parent, p_index);
 
 	/* propagate rate an accuracy recalculation accordingly */
 	if (ret) {
-		__clk_recalc_rates(clk, ABORT_RATE_CHANGE);
+		__clk_recalc_rates(core, ABORT_RATE_CHANGE);
 	} else {
-		__clk_recalc_rates(clk, POST_RATE_CHANGE);
-		__clk_recalc_accuracies(clk);
+		__clk_recalc_rates(core, POST_RATE_CHANGE);
+		__clk_recalc_accuracies(core);
 	}
 
 out:
@@ -2201,21 +1830,16 @@
 }
 EXPORT_SYMBOL_GPL(clk_set_phase);
 
-static int clk_core_get_phase(struct clk_core *clk)
+static int clk_core_get_phase(struct clk_core *core)
 {
-	int ret = 0;
-
-	if (!clk)
-		goto out;
+	int ret;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+	ret = core->phase;
 	clk_prepare_unlock();
 
-out:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_get_phase);
 
 /**
  * clk_get_phase - return the phase shift of a clock signal
@@ -2231,6 +1855,7 @@
 
 	return clk_core_get_phase(clk->core);
 }
+EXPORT_SYMBOL_GPL(clk_get_phase);
 
 /**
  * clk_is_match - check if two clk's point to the same hardware clock
@@ -2258,6 +1883,337 @@
 }
 EXPORT_SYMBOL_GPL(clk_is_match);
 
+/***        debugfs support        ***/
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+
+static struct dentry *rootdir;
+static int inited = 0;
+static DEFINE_MUTEX(clk_debug_lock);
+static HLIST_HEAD(clk_debug_list);
+
+static struct hlist_head *all_lists[] = {
+	&clk_root_list,
+	&clk_orphan_list,
+	NULL,
+};
+
+static struct hlist_head *orphan_list[] = {
+	&clk_orphan_list,
+	NULL,
+};
+
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+				 int level)
+{
+	if (!c)
+		return;
+
+	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
+		   level * 3 + 1, "",
+		   30 - level * 3, c->name,
+		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
+		   clk_core_get_accuracy(c), clk_core_get_phase(c));
+}
+
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
+				     int level)
+{
+	struct clk_core *child;
+
+	if (!c)
+		return;
+
+	clk_summary_show_one(s, c, level);
+
+	hlist_for_each_entry(child, &c->children, child_node)
+		clk_summary_show_subtree(s, child, level + 1);
+}
+
+static int clk_summary_show(struct seq_file *s, void *data)
+{
+	struct clk_core *c;
+	struct hlist_head **lists = (struct hlist_head **)s->private;
+
+	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
+	seq_puts(s, "----------------------------------------------------------------------------------------\n");
+
+	clk_prepare_lock();
+
+	for (; *lists; lists++)
+		hlist_for_each_entry(c, *lists, child_node)
+			clk_summary_show_subtree(s, c, 0);
+
+	clk_prepare_unlock();
+
+	return 0;
+}
+
+
+static int clk_summary_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clk_summary_show, inode->i_private);
+}
+
+static const struct file_operations clk_summary_fops = {
+	.open		= clk_summary_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
+{
+	if (!c)
+		return;
+
+	/* This should be JSON format, i.e. elements separated with a comma */
+	seq_printf(s, "\"%s\": { ", c->name);
+	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
+	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
+	seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
+	seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
+	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+}
+
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
+{
+	struct clk_core *child;
+
+	if (!c)
+		return;
+
+	clk_dump_one(s, c, level);
+
+	hlist_for_each_entry(child, &c->children, child_node) {
+		seq_printf(s, ",");
+		clk_dump_subtree(s, child, level + 1);
+	}
+
+	seq_printf(s, "}");
+}
+
+static int clk_dump(struct seq_file *s, void *data)
+{
+	struct clk_core *c;
+	bool first_node = true;
+	struct hlist_head **lists = (struct hlist_head **)s->private;
+
+	seq_printf(s, "{");
+
+	clk_prepare_lock();
+
+	for (; *lists; lists++) {
+		hlist_for_each_entry(c, *lists, child_node) {
+			if (!first_node)
+				seq_puts(s, ",");
+			first_node = false;
+			clk_dump_subtree(s, c, 0);
+		}
+	}
+
+	clk_prepare_unlock();
+
+	seq_puts(s, "}\n");
+	return 0;
+}
+
+
+static int clk_dump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clk_dump, inode->i_private);
+}
+
+static const struct file_operations clk_dump_fops = {
+	.open		= clk_dump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
+{
+	struct dentry *d;
+	int ret = -ENOMEM;
+
+	if (!core || !pdentry) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	d = debugfs_create_dir(core->name, pdentry);
+	if (!d)
+		goto out;
+
+	core->dentry = d;
+
+	d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry,
+			(u32 *)&core->rate);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry,
+			(u32 *)&core->accuracy);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_phase", S_IRUGO, core->dentry,
+			(u32 *)&core->phase);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_x32("clk_flags", S_IRUGO, core->dentry,
+			(u32 *)&core->flags);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, core->dentry,
+			(u32 *)&core->prepare_count);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry,
+			(u32 *)&core->enable_count);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry,
+			(u32 *)&core->notifier_count);
+	if (!d)
+		goto err_out;
+
+	if (core->ops->debug_init) {
+		ret = core->ops->debug_init(core->hw, core->dentry);
+		if (ret)
+			goto err_out;
+	}
+
+	ret = 0;
+	goto out;
+
+err_out:
+	debugfs_remove_recursive(core->dentry);
+	core->dentry = NULL;
+out:
+	return ret;
+}
+
+/**
+ * clk_debug_register - add a clk node to the debugfs clk directory
+ * @core: the clk being added to the debugfs clk directory
+ *
+ * Dynamically adds a clk to the debugfs clk directory if debugfs has been
+ * initialized.  Otherwise it bails out early since the debugfs clk directory
+ * will be created lazily by clk_debug_init as part of a late_initcall.
+ */
+static int clk_debug_register(struct clk_core *core)
+{
+	int ret = 0;
+
+	mutex_lock(&clk_debug_lock);
+	hlist_add_head(&core->debug_node, &clk_debug_list);
+
+	if (!inited)
+		goto unlock;
+
+	ret = clk_debug_create_one(core, rootdir);
+unlock:
+	mutex_unlock(&clk_debug_lock);
+
+	return ret;
+}
+
+ /**
+ * clk_debug_unregister - remove a clk node from the debugfs clk directory
+ * @core: the clk being removed from the debugfs clk directory
+ *
+ * Dynamically removes a clk and all its child nodes from the
+ * debugfs clk directory if clk->dentry points to debugfs created by
+ * clk_debug_register in __clk_init.
+ */
+static void clk_debug_unregister(struct clk_core *core)
+{
+	mutex_lock(&clk_debug_lock);
+	hlist_del_init(&core->debug_node);
+	debugfs_remove_recursive(core->dentry);
+	core->dentry = NULL;
+	mutex_unlock(&clk_debug_lock);
+}
+
+struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
+				void *data, const struct file_operations *fops)
+{
+	struct dentry *d = NULL;
+
+	if (hw->core->dentry)
+		d = debugfs_create_file(name, mode, hw->core->dentry, data,
+					fops);
+
+	return d;
+}
+EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
+
+/**
+ * clk_debug_init - lazily populate the debugfs clk directory
+ *
+ * clks are often initialized very early during boot before memory can be
+ * dynamically allocated and well before debugfs is setup. This function
+ * populates the debugfs clk directory once at boot-time when we know that
+ * debugfs is setup. It should only be called once at boot-time, all other clks
+ * added dynamically will be done so with clk_debug_register.
+ */
+static int __init clk_debug_init(void)
+{
+	struct clk_core *core;
+	struct dentry *d;
+
+	rootdir = debugfs_create_dir("clk", NULL);
+
+	if (!rootdir)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
+				&clk_summary_fops);
+	if (!d)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
+				&clk_dump_fops);
+	if (!d)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
+				&orphan_list, &clk_summary_fops);
+	if (!d)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
+				&orphan_list, &clk_dump_fops);
+	if (!d)
+		return -ENOMEM;
+
+	mutex_lock(&clk_debug_lock);
+	hlist_for_each_entry(core, &clk_debug_list, debug_node)
+		clk_debug_create_one(core, rootdir);
+
+	inited = 1;
+	mutex_unlock(&clk_debug_lock);
+
+	return 0;
+}
+late_initcall(clk_debug_init);
+#else
+static inline int clk_debug_register(struct clk_core *core) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *core,
+				      struct clk_core *new_parent)
+{
+}
+static inline void clk_debug_unregister(struct clk_core *core)
+{
+}
+#endif
+
 /**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
@@ -2271,67 +2227,67 @@
 	int i, ret = 0;
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
-	struct clk_core *clk;
+	struct clk_core *core;
 	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
 
-	clk = clk_user->core;
+	core = clk_user->core;
 
 	clk_prepare_lock();
 
 	/* check to see if a clock with this name is already registered */
-	if (clk_core_lookup(clk->name)) {
+	if (clk_core_lookup(core->name)) {
 		pr_debug("%s: clk %s already initialized\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EEXIST;
 		goto out;
 	}
 
 	/* check that clk_ops are sane.  See Documentation/clk.txt */
-	if (clk->ops->set_rate &&
-	    !((clk->ops->round_rate || clk->ops->determine_rate) &&
-	      clk->ops->recalc_rate)) {
+	if (core->ops->set_rate &&
+	    !((core->ops->round_rate || core->ops->determine_rate) &&
+	      core->ops->recalc_rate)) {
 		pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (clk->ops->set_parent && !clk->ops->get_parent) {
+	if (core->ops->set_parent && !core->ops->get_parent) {
 		pr_warning("%s: %s must implement .get_parent & .set_parent\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (clk->ops->set_rate_and_parent &&
-			!(clk->ops->set_parent && clk->ops->set_rate)) {
+	if (core->ops->set_rate_and_parent &&
+			!(core->ops->set_parent && core->ops->set_rate)) {
 		pr_warn("%s: %s must implement .set_parent & .set_rate\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* throw a WARN if any entries in parent_names are NULL */
-	for (i = 0; i < clk->num_parents; i++)
-		WARN(!clk->parent_names[i],
+	for (i = 0; i < core->num_parents; i++)
+		WARN(!core->parent_names[i],
 				"%s: invalid NULL in %s's .parent_names\n",
-				__func__, clk->name);
+				__func__, core->name);
 
 	/*
 	 * Allocate an array of struct clk *'s to avoid unnecessary string
 	 * look-ups of clk's possible parents.  This can fail for clocks passed
-	 * in to clk_init during early boot; thus any access to clk->parents[]
+	 * in to clk_init during early boot; thus any access to core->parents[]
 	 * must always check for a NULL pointer and try to populate it if
 	 * necessary.
 	 *
-	 * If clk->parents is not NULL we skip this entire block.  This allows
-	 * for clock drivers to statically initialize clk->parents.
+	 * If core->parents is not NULL we skip this entire block.  This allows
+	 * for clock drivers to statically initialize core->parents.
 	 */
-	if (clk->num_parents > 1 && !clk->parents) {
-		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
+	if (core->num_parents > 1 && !core->parents) {
+		core->parents = kcalloc(core->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 		/*
 		 * clk_core_lookup returns NULL for parents that have not been
@@ -2339,16 +2295,16 @@
 		 * for a NULL pointer.  We can always perform lazy lookups for
 		 * missing parents later on.
 		 */
-		if (clk->parents)
-			for (i = 0; i < clk->num_parents; i++)
-				clk->parents[i] =
-					clk_core_lookup(clk->parent_names[i]);
+		if (core->parents)
+			for (i = 0; i < core->num_parents; i++)
+				core->parents[i] =
+					clk_core_lookup(core->parent_names[i]);
 	}
 
-	clk->parent = __clk_init_parent(clk);
+	core->parent = __clk_init_parent(core);
 
 	/*
-	 * Populate clk->parent if parent has already been __clk_init'd.  If
+	 * Populate core->parent if parent has already been __clk_init'd.  If
 	 * parent has not yet been __clk_init'd then place clk in the orphan
 	 * list.  If clk has set the CLK_IS_ROOT flag then place it in the root
 	 * clk list.
@@ -2357,13 +2313,13 @@
 	 * clocks and re-parent any that are children of the clock currently
 	 * being clk_init'd.
 	 */
-	if (clk->parent)
-		hlist_add_head(&clk->child_node,
-				&clk->parent->children);
-	else if (clk->flags & CLK_IS_ROOT)
-		hlist_add_head(&clk->child_node, &clk_root_list);
+	if (core->parent)
+		hlist_add_head(&core->child_node,
+				&core->parent->children);
+	else if (core->flags & CLK_IS_ROOT)
+		hlist_add_head(&core->child_node, &clk_root_list);
 	else
-		hlist_add_head(&clk->child_node, &clk_orphan_list);
+		hlist_add_head(&core->child_node, &clk_orphan_list);
 
 	/*
 	 * Set clk's accuracy.  The preferred method is to use
@@ -2372,23 +2328,23 @@
 	 * parent (or is orphaned) then accuracy is set to zero (perfect
 	 * clock).
 	 */
-	if (clk->ops->recalc_accuracy)
-		clk->accuracy = clk->ops->recalc_accuracy(clk->hw,
-					__clk_get_accuracy(clk->parent));
-	else if (clk->parent)
-		clk->accuracy = clk->parent->accuracy;
+	if (core->ops->recalc_accuracy)
+		core->accuracy = core->ops->recalc_accuracy(core->hw,
+					__clk_get_accuracy(core->parent));
+	else if (core->parent)
+		core->accuracy = core->parent->accuracy;
 	else
-		clk->accuracy = 0;
+		core->accuracy = 0;
 
 	/*
 	 * Set clk's phase.
 	 * Since a phase is by definition relative to its parent, just
 	 * query the current clock phase, or just assume it's in phase.
 	 */
-	if (clk->ops->get_phase)
-		clk->phase = clk->ops->get_phase(clk->hw);
+	if (core->ops->get_phase)
+		core->phase = core->ops->get_phase(core->hw);
 	else
-		clk->phase = 0;
+		core->phase = 0;
 
 	/*
 	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
@@ -2396,14 +2352,14 @@
 	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
 	 * then rate is set to zero.
 	 */
-	if (clk->ops->recalc_rate)
-		rate = clk->ops->recalc_rate(clk->hw,
-				clk_core_get_rate_nolock(clk->parent));
-	else if (clk->parent)
-		rate = clk->parent->rate;
+	if (core->ops->recalc_rate)
+		rate = core->ops->recalc_rate(core->hw,
+				clk_core_get_rate_nolock(core->parent));
+	else if (core->parent)
+		rate = core->parent->rate;
 	else
 		rate = 0;
-	clk->rate = clk->req_rate = rate;
+	core->rate = core->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
@@ -2412,14 +2368,14 @@
 	hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
 		if (orphan->num_parents && orphan->ops->get_parent) {
 			i = orphan->ops->get_parent(orphan->hw);
-			if (!strcmp(clk->name, orphan->parent_names[i]))
-				clk_core_reparent(orphan, clk);
+			if (!strcmp(core->name, orphan->parent_names[i]))
+				clk_core_reparent(orphan, core);
 			continue;
 		}
 
 		for (i = 0; i < orphan->num_parents; i++)
-			if (!strcmp(clk->name, orphan->parent_names[i])) {
-				clk_core_reparent(orphan, clk);
+			if (!strcmp(core->name, orphan->parent_names[i])) {
+				clk_core_reparent(orphan, core);
 				break;
 			}
 	 }
@@ -2432,15 +2388,15 @@
 	 * Please consider other ways of solving initialization problems before
 	 * using this callback, as its use is discouraged.
 	 */
-	if (clk->ops->init)
-		clk->ops->init(clk->hw);
+	if (core->ops->init)
+		core->ops->init(core->hw);
 
-	kref_init(&clk->ref);
+	kref_init(&core->ref);
 out:
 	clk_prepare_unlock();
 
 	if (!ret)
-		clk_debug_register(clk);
+		clk_debug_register(core);
 
 	return ret;
 }
@@ -2486,63 +2442,58 @@
  *
  * clk_register is the primary interface for populating the clock tree with new
  * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
+ * cannot be dereferenced by driver code but may be used in conjunction with the
  * rest of the clock API.  In the event of an error clk_register will return an
  * error code; drivers must test for an error code after calling clk_register.
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
 	int i, ret;
-	struct clk_core *clk;
+	struct clk_core *core;
 
-	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-	if (!clk) {
-		pr_err("%s: could not allocate clk\n", __func__);
+	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (!core) {
 		ret = -ENOMEM;
 		goto fail_out;
 	}
 
-	clk->name = kstrdup_const(hw->init->name, GFP_KERNEL);
-	if (!clk->name) {
-		pr_err("%s: could not allocate clk->name\n", __func__);
+	core->name = kstrdup_const(hw->init->name, GFP_KERNEL);
+	if (!core->name) {
 		ret = -ENOMEM;
 		goto fail_name;
 	}
-	clk->ops = hw->init->ops;
+	core->ops = hw->init->ops;
 	if (dev && dev->driver)
-		clk->owner = dev->driver->owner;
-	clk->hw = hw;
-	clk->flags = hw->init->flags;
-	clk->num_parents = hw->init->num_parents;
-	hw->core = clk;
+		core->owner = dev->driver->owner;
+	core->hw = hw;
+	core->flags = hw->init->flags;
+	core->num_parents = hw->init->num_parents;
+	hw->core = core;
 
 	/* allocate local copy in case parent_names is __initdata */
-	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
+	core->parent_names = kcalloc(core->num_parents, sizeof(char *),
 					GFP_KERNEL);
 
-	if (!clk->parent_names) {
-		pr_err("%s: could not allocate clk->parent_names\n", __func__);
+	if (!core->parent_names) {
 		ret = -ENOMEM;
 		goto fail_parent_names;
 	}
 
 
 	/* copy each string name in case parent_names is __initdata */
-	for (i = 0; i < clk->num_parents; i++) {
-		clk->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
+	for (i = 0; i < core->num_parents; i++) {
+		core->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
 						GFP_KERNEL);
-		if (!clk->parent_names[i]) {
-			pr_err("%s: could not copy parent_names\n", __func__);
+		if (!core->parent_names[i]) {
 			ret = -ENOMEM;
 			goto fail_parent_names_copy;
 		}
 	}
 
-	INIT_HLIST_HEAD(&clk->clks);
+	INIT_HLIST_HEAD(&core->clks);
 
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
-		pr_err("%s: could not allocate per-user clk\n", __func__);
 		ret = PTR_ERR(hw->clk);
 		goto fail_parent_names_copy;
 	}
@@ -2556,35 +2507,32 @@
 
 fail_parent_names_copy:
 	while (--i >= 0)
-		kfree_const(clk->parent_names[i]);
-	kfree(clk->parent_names);
+		kfree_const(core->parent_names[i]);
+	kfree(core->parent_names);
 fail_parent_names:
-	kfree_const(clk->name);
+	kfree_const(core->name);
 fail_name:
-	kfree(clk);
+	kfree(core);
 fail_out:
 	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
-/*
- * Free memory allocated for a clock.
- * Caller must hold prepare_lock.
- */
+/* Free memory allocated for a clock. */
 static void __clk_release(struct kref *ref)
 {
-	struct clk_core *clk = container_of(ref, struct clk_core, ref);
-	int i = clk->num_parents;
+	struct clk_core *core = container_of(ref, struct clk_core, ref);
+	int i = core->num_parents;
 
 	lockdep_assert_held(&prepare_lock);
 
-	kfree(clk->parents);
+	kfree(core->parents);
 	while (--i >= 0)
-		kfree_const(clk->parent_names[i]);
+		kfree_const(core->parent_names[i]);
 
-	kfree(clk->parent_names);
-	kfree_const(clk->name);
-	kfree(clk);
+	kfree(core->parent_names);
+	kfree_const(core->name);
+	kfree(core);
 }
 
 /*
@@ -3068,6 +3016,27 @@
 }
 EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
 
+/**
+ * of_clk_parent_fill() - Fill @parents with names of @np's parents and return
+ * number of parents
+ * @np: Device node pointer associated with clock provider
+ * @parents: pointer to char array that hold the parents' names
+ * @size: size of the @parents array
+ *
+ * Return: number of parents for the clock node.
+ */
+int of_clk_parent_fill(struct device_node *np, const char **parents,
+		       unsigned int size)
+{
+	unsigned int i = 0;
+
+	while (i < size && (parents[i] = of_clk_get_parent_name(np, i)) != NULL)
+		i++;
+
+	return i;
+}
+EXPORT_SYMBOL_GPL(of_clk_parent_fill);
+
 struct clock_provider {
 	of_clk_init_cb_t clk_init_cb;
 	struct device_node *np;
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 0000000..b4165ba
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,6 @@
+config COMMON_CLK_HI6220
+	bool "Hi6220 Clock Driver"
+	depends on ARCH_HISI || COMPILE_TEST
+	default 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..48f0116 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,8 +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)	+= clk-hi6220.o
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 472dd2c..715d34a 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -38,44 +38,44 @@
 #include "clk.h"
 
 /* clock parent list */
-static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", };
-static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", };
-static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", };
-static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", };
-static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", };
-static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", };
-static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", };
-static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", };
-static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", };
-static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", };
-static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
-static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
-static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
+static const char *const timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
+static const char *const timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
+static const char *const timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
+static const char *const timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
+static const char *const timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
+static const char *const timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
+static const char *const timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
+static const char *const timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
+static const char *const timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
+static const char *const timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
+static const char *const uart0_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart1_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart2_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart3_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart4_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
 /* share axi parent */
-static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", };
-static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", };
-static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", };
-static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", };
-static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4",
+static const char *const saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
+static const char *const pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
+static const char *const pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
+static const char *const sd_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
+static const char *const g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const venc_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
 					     "armpll3", "armpll5", };
-static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4",
+static const char *const edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
 					     "armpll3", "armpll5", };
-static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", };
-static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *const rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
+static const char *const mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
 
 
 /* fixed rate clocks */
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
new file mode 100644
index 0000000..4563343
--- /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 <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_ao;
+
+	clk_data_ao = hisi_clk_init(np, HI6220_AO_NR_CLKS);
+	if (!clk_data_ao)
+		return;
+
+	hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
+				ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data_ao);
+
+	hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
+				ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data_ao);
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
+				ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data_ao);
+}
+CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
+
+
+/* clocks in sysctrl */
+static const char *mmc0_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc0_mux1_p[] __initdata = { "mmc0_mux0", "pll_media_gate", };
+static const char *mmc0_src_p[] __initdata = { "mmc0srcsel", "mmc0_div", };
+static const char *mmc1_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc1_mux1_p[] __initdata = { "mmc1_mux0", "pll_media_gate", };
+static const char *mmc1_src_p[]  __initdata = { "mmc1srcsel", "mmc1_div", };
+static const char *mmc2_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc2_mux1_p[] __initdata = { "mmc2_mux0", "pll_media_gate", };
+static const char *mmc2_src_p[]  __initdata = { "mmc2srcsel", "mmc2_div", };
+static const char *mmc0_sample_in[] __initdata = { "mmc0_sample", "mmc0_pad", };
+static const char *mmc1_sample_in[] __initdata = { "mmc1_sample", "mmc1_pad", };
+static const char *mmc2_sample_in[] __initdata = { "mmc2_sample", "mmc2_pad", };
+static const char *uart1_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart2_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart3_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart4_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *hifi_src[] __initdata = { "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_TSENSOR_CLK,   "tsensor_clk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 12, 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-sysctrl", hi6220_clk_sys_init);
+
+
+/* clocks in media controller */
+static const char *clk_1000_1200_src[] __initdata = { "pll_gpu_gate", "media_syspll_src", };
+static const char *clk_1440_1200_src[] __initdata = { "media_syspll_src", "media_pll_src", };
+static const char *clk_1000_1440_src[] __initdata = { "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-mediactrl", 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-pmctrl", hi6220_clk_power_init);
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index f1d2394..0aaf29d 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -46,15 +46,15 @@
 	{ HIX5HD2_FIXED_83M, "83m", NULL, CLK_IS_ROOT, 83333333, },
 };
 
-static const char *sfc_mux_p[] __initdata = {
+static const char *const sfc_mux_p[] __initconst = {
 		"24m", "150m", "200m", "100m", "75m", };
 static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
 
-static const char *sdio_mux_p[] __initdata = {
+static const char *const sdio_mux_p[] __initconst = {
 		"75m", "100m", "50m", "15m", };
 static u32 sdio_mux_table[] = {0, 1, 2, 3};
 
-static const char *fephy_mux_p[] __initdata = { "25m", "125m"};
+static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
 static u32 fephy_mux_table[] = {0, 1};
 
 
@@ -252,8 +252,9 @@
 	.disable = clk_complex_disable,
 };
 
-void __init hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks,
-					 int nums, struct hisi_clock_data *data)
+static void __init
+hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
+			     struct hisi_clock_data *data)
 {
 	void __iomem *base = data->base;
 	int i;
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84..c90a897 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -232,3 +232,32 @@
 		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..b56fbc1 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -55,7 +55,7 @@
 struct hisi_mux_clock {
 	unsigned int		id;
 	const char		*name;
-	const char		**parent_names;
+	const char		*const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 	unsigned long		offset;
@@ -79,6 +79,18 @@
 	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,18 +106,23 @@
 				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 *,
-					int, struct hisi_clock_data *);
-void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
-					int, struct hisi_clock_data *);
-void __init hisi_clk_register_mux(struct hisi_mux_clock *, int,
-				struct hisi_clock_data *);
-void __init hisi_clk_register_divider(struct hisi_divider_clock *,
+struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
+void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
 				int, struct hisi_clock_data *);
-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 hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_mux(struct hisi_mux_clock *, int,
+				struct hisi_clock_data *);
+void hisi_clk_register_divider(struct hisi_divider_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_gate(struct hisi_gate_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_gate_sep(struct hisi_gate_clock *,
+				int, struct hisi_clock_data *);
+void 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..113eee8
--- /dev/null
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -0,0 +1,156 @@
+/*
+ * 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>
+#include <linux/spinlock.h>
+
+#define div_mask(width)	((1 << (width)) - 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 long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	unsigned int val;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	val = readl_relaxed(dclk->reg) >> dclk->shift;
+	val &= div_mask(dclk->width);
+
+	return divider_recalc_rate(hw, parent_rate, val, dclk->table,
+				   CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *prate)
+{
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	return divider_round_rate(hw, rate, prate, dclk->table,
+				  dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	int value;
+	unsigned long flags = 0;
+	u32 data;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	value = divider_get_val(rate, parent_rate, dclk->table,
+				dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+
+	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 const 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(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	/* Init the divider table */
+	max_div = div_mask(width) + 1;
+	min_div = 1;
+
+	table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
+	if (!table) {
+		kfree(div);
+		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;
+	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/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 0000000..8e4b2a4
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1,4 @@
+obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-y += clk-mt8135.o
+obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
new file mode 100644
index 0000000..5702036
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val == 0;
+}
+
+static int mtk_cg_bit_is_set(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val != 0;
+}
+
+static void mtk_cg_set_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
+}
+
+static void mtk_cg_clr_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
+}
+
+static int mtk_cg_enable(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+}
+
+static int mtk_cg_enable_inv(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+}
+
+const struct clk_ops mtk_clk_gate_ops_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable,
+	.disable	= mtk_cg_disable,
+};
+
+const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv,
+	.disable	= mtk_cg_disable_inv,
+};
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops)
+{
+	struct mtk_clk_gate *cg;
+	struct clk *clk;
+	struct clk_init_data init = {};
+
+	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.ops = ops;
+
+	cg->regmap = regmap;
+	cg->set_ofs = set_ofs;
+	cg->clr_ofs = clr_ofs;
+	cg->sta_ofs = sta_ofs;
+	cg->bit = bit;
+
+	cg->hw.init = &init;
+
+	clk = clk_register(NULL, &cg->hw);
+	if (IS_ERR(clk))
+		kfree(cg);
+
+	return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
new file mode 100644
index 0000000..6b6780b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_GATE_H
+#define __DRV_CLK_GATE_H
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_gate {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+	int		set_ofs;
+	int		clr_ofs;
+	int		sta_ofs;
+	u8		bit;
+};
+
+static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_gate, hw);
+}
+
+extern const struct clk_ops mtk_clk_gate_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops);
+
+#endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
new file mode 100644
index 0000000..08b4b84
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/clock/mt8135-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static DEFINE_SPINLOCK(mt8135_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+	FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
+
+	FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
+
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+	FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
+	FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+	FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+	FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
+	FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
+
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
+	FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
+	FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
+	FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
+
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
+
+	FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
+
+	FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
+
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
+
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
+
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+
+	FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
+	FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
+	FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
+	FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
+	FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
+
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
+	FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
+
+	FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
+
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
+	FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
+
+	FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d4",
+	"syspll_d6",
+	"univpll_d5",
+	"univpll2_d2",
+	"syspll_d3p5"
+};
+
+static const char * const smi_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll1_d6",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7",
+	"vdecpll",
+	"lvdspll"
+};
+
+static const char * const mfg_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d4",
+	"syspll_d2",
+	"syspll_d2p5",
+	"syspll_d3",
+	"univpll_d5",
+	"univpll1_d2",
+	"mmpll_d2",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7"
+};
+
+static const char * const irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll1_d6"
+};
+
+static const char * const cam_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll1_d4"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"univpll_d10"
+};
+
+static const char * const jpg_parents[] __initconst = {
+	"clk26m",
+	"syspll_d5",
+	"syspll_d4",
+	"syspll_d3",
+	"univpll_d7",
+	"univpll2_d2",
+	"univpll_d5"
+};
+
+static const char * const disp_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3p5",
+	"syspll_d3",
+	"univpll2_d2",
+	"univpll_d5",
+	"univpll1_d2",
+	"lvdspll",
+	"vdecpll"
+};
+
+static const char * const msdc30_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d5",
+	"univpll1_d4",
+	"univpll2_d4",
+	"msdcpll"
+};
+
+static const char * const usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"univpll1_d10"
+};
+
+static const char * const venc_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d6",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6"
+};
+
+static const char * const spi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char * const uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const mem_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck"
+};
+
+static const char * const camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll1_d6",
+	"syspll_d16",
+	"syspll_d8"
+};
+
+static const char * const audio_parents[] __initconst = {
+	"clk26m",
+	"syspll_d24"
+};
+
+static const char * const fix_parents[] __initconst = {
+	"rtc32k",
+	"clk26m",
+	"univpll_d5",
+	"univpll_d7",
+	"univpll1_d2",
+	"univpll1_d4",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char * const vdec_parents[] __initconst = {
+	"clk26m",
+	"vdecpll",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"syspll_d5",
+	"syspll_d6",
+	"syspll_d8",
+	"univpll1_d2",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll_d10",
+	"univpll2_d4",
+	"lvdspll"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"syspll_d12"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d10",
+	"mempll_mck_d4",
+	"univpll_d26",
+	"syspll_d24"
+};
+
+static const char * const smi_mfg_as_parents[] __initconst = {
+	"clk26m",
+	"smi_sel",
+	"mfg_sel",
+	"mem_sel"
+};
+
+static const char * const gcpu_parents[] __initconst = {
+	"clk26m",
+	"syspll_d4",
+	"univpll_d7",
+	"syspll_d5",
+	"syspll_d6"
+};
+
+static const char * const dpi1_parents[] __initconst = {
+	"clk26m",
+	"tvhdmi_h_ck",
+	"tvhdmi_d2",
+	"tvhdmi_d4"
+};
+
+static const char * const cci_parents[] __initconst = {
+	"clk26m",
+	"mainpll_537p3m",
+	"univpll_d3",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d5"
+};
+
+static const char * const apll_parents[] __initconst = {
+	"clk26m",
+	"apll_ck",
+	"apll_d4",
+	"apll_d8",
+	"apll_d16",
+	"apll_d24"
+};
+
+static const char * const hdmipll_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_clkdig_cts",
+	"hdmitx_clkdig_d2",
+	"hdmitx_clkdig_d3"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+	/* CLK_CFG_0 */
+	MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0140, 0, 3, INVALID_MUX_GATE_BIT),
+	MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0144, 8, 2, 15),
+	MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
+	MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
+		0x015c, 16, 2, 23),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
+	/* CLK_CFG_8 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
+		0x0164, 16, 2, 23),
+	MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
+	/* CLK_CFG_9 */
+	MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
+	MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
+	GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
+	GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
+	GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
+	GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
+	GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
+	GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
+	GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
+	GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
+	GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate peri_gates[] __initconst = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
+	GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
+	GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
+	GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
+	GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
+	GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
+	GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
+	GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
+	GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
+	GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
+	GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
+	GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
+	GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
+	GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt8135_clk_lock, clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+						clk_data);
+	mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+			&mt8135_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
+
+#define MT8135_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8135_RST_BAR	BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8135_RST_BAR,			\
+		.fmax = MT8135_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
+	PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
new file mode 100644
index 0000000..4b9e04c
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8173-clk.h>
+
+static DEFINE_SPINLOCK(mt8173_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+	FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
+	FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
+
+	FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+
+	FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
+
+	FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+
+	FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
+	FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
+	FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
+
+	FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
+	FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
+
+	FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
+	FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
+
+	FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
+	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
+	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
+	FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
+	FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
+
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
+
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
+	FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
+
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+
+	FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
+	FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
+
+	FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
+	FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
+	FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const mem_parents[] __initconst = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char * const mm_parents[] __initconst = {
+	"clk26m",
+	"vencpll_d2",
+	"main_h364m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2"
+};
+
+static const char * const pwm_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4"
+};
+
+static const char * const vdec_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"mmpll_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const venc_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const mfg_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll_d5",
+	"univpll_d3",
+	"univpll1_d2",
+	"univpll_d5",
+	"univpll2_d2"
+};
+
+static const char * const camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"univpll1_d4"
+};
+
+static const char * const uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const usb30_parents[] __initconst = {
+	"clk26m",
+	"univpll3_d2",
+	"usb_syspll_125m",
+	"univpll2_d4"
+};
+
+static const char * const msdc50_0_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const msdc50_0_parents[] __initconst = {
+	"clk26m",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"msdcpll_d4",
+	"vencpll_d4",
+	"tvdpll_ck",
+	"univpll_d2",
+	"univpll1_d2",
+	"mmpll_ck",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"msdcpll2_d4"
+};
+
+static const char * const msdc30_1_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4"
+};
+
+static const char * const msdc30_2_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d2"
+};
+
+static const char * const msdc30_3_parents[] __initconst = {
+	"clk26m",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"univpll2_d2",
+	"msdcpll2_d4",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"msdcpll_d4"
+};
+
+static const char * const audio_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d4",
+	"syspll4_d4",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d8",
+	"dmpll_d4",
+	"dmpll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll3_d4",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d8",
+	"dmpll_d16"
+};
+
+static const char * const scp_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const atb_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"dmpll_d2"
+};
+
+static const char * const venc_lt_parents[] __initconst = {
+	"clk26m",
+	"univpll_d3",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"syspll1_d2",
+	"univpll_d5",
+	"vcodecpll_370p5",
+	"dmpll_ck"
+};
+
+static const char * const dpi0_parents[] __initconst = {
+	"clk26m",
+	"tvdpll_d2",
+	"tvdpll_d4",
+	"clk26m",
+	"clk26m",
+	"tvdpll_d8",
+	"tvdpll_d16"
+};
+
+static const char * const irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"syspll2_d4"
+};
+
+static const char * const cci400_parents[] __initconst = {
+	"clk26m",
+	"vencpll_ck",
+	"armca7pll_754m",
+	"armca7pll_502m",
+	"univpll_d2",
+	"syspll_d2",
+	"msdcpll_ck",
+	"dmpll_ck"
+};
+
+static const char * const aud_1_parents[] __initconst = {
+	"clk26m",
+	"apll1_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const aud_2_parents[] __initconst = {
+	"clk26m",
+	"apll2_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const mem_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m"
+};
+
+static const char * const axi_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"dmpll_d2"
+};
+
+static const char * const scam_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"univpll2_d4",
+	"dmpll_d4"
+};
+
+static const char * const spinfi_ifr_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll3_d4",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll3_d2",
+	"syspll1_d4",
+	"univpll1_d4"
+};
+
+static const char * const hdmi_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_dig_cts",
+	"hdmitxpll_d2",
+	"hdmitxpll_d3"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8",
+	"fpc_ck"
+};
+
+static const char * const msdc50_2_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const hdcp_parents[] __initconst = {
+	"clk26m",
+	"syspll4_d2",
+	"syspll3_d4",
+	"univpll2_d4"
+};
+
+static const char * const hdcp_24m_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll2_d8"
+};
+
+static const char * const rtc_parents[] __initconst = {
+	"clkrtc_int",
+	"clkrtc_ext",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const i2s0_m_ck_parents[] __initconst = {
+	"apll1_div1",
+	"apll2_div1"
+};
+
+static const char * const i2s1_m_ck_parents[] __initconst = {
+	"apll1_div2",
+	"apll2_div2"
+};
+
+static const char * const i2s2_m_ck_parents[] __initconst = {
+	"apll1_div3",
+	"apll2_div3"
+};
+
+static const char * const i2s3_m_ck_parents[] __initconst = {
+	"apll1_div4",
+	"apll2_div4"
+};
+
+static const char * const i2s3_b_ck_parents[] __initconst = {
+	"apll1_div5",
+	"apll2_div5"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+	/* CLK_CFG_0 */
+	MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
+	MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
+	/* CLK_CFG_5 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
+	MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
+	MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
+	MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
+	/* CLK_CFG_12 */
+	MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
+	/* CLK_CFG_13 */
+	MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
+	MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
+
+	DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
+	DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
+	DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
+	DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
+	DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
+	DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
+
+	DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
+	DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
+	DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
+	DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
+	DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
+	DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
+
+	MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
+	MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
+	MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
+	MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
+	MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
+	GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
+	GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
+	GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
+	GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
+	GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
+	GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
+	GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate peri_gates[] __initconst = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
+	GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
+	GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
+	GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
+	GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
+	GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
+	GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
+	GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
+	GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
+	GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt8173_clk_lock, clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+						clk_data);
+	mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+			&mt8173_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
+
+#define MT8173_PLL_FMAX		(3000UL * MHZ)
+
+#define CON0_MT8173_RST_BAR	BIT(24)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
+			_tuner_reg, _pcw_reg, _pcw_shift) { \
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8173_RST_BAR,			\
+		.fmax = MT8173_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
+	PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
+	PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
+	PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
+	PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+	PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 0000000..18444ae
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
+{
+	int i;
+	struct clk_onecell_data *clk_data;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return NULL;
+
+	clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err_out;
+
+	clk_data->clk_num = clk_num;
+
+	for (i = 0; i < clk_num; i++)
+		clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+	return clk_data;
+err_out:
+	kfree(clk_data);
+
+	return NULL;
+}
+
+void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_fixed_factor *ff = &clks[i];
+
+		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
+				CLK_SET_RATE_PARENT, ff->mult, ff->div);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					ff->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[ff->id] = clk;
+	}
+}
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+		int num, struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+	struct regmap *regmap;
+
+	if (!clk_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(node);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+				PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_gate *gate = &clks[i];
+
+		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
+				regmap,
+				gate->regs->set_ofs,
+				gate->regs->clr_ofs,
+				gate->regs->sta_ofs,
+				gate->shift, gate->ops);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					gate->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[gate->id] = clk;
+	}
+
+	return 0;
+}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+		void __iomem *base, spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
+	const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
+	const char * const *parent_names;
+	const char *parent;
+	int num_parents;
+	int ret;
+
+	if (mc->mux_shift >= 0) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = base + mc->mux_reg;
+		mux->mask = BIT(mc->mux_width) - 1;
+		mux->shift = mc->mux_shift;
+		mux->lock = lock;
+
+		mux_hw = &mux->hw;
+		mux_ops = &clk_mux_ops;
+
+		parent_names = mc->parent_names;
+		num_parents = mc->num_parents;
+	} else {
+		parent = mc->parent;
+		parent_names = &parent;
+		num_parents = 1;
+	}
+
+	if (mc->gate_shift >= 0) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		gate->reg = base + mc->gate_reg;
+		gate->bit_idx = mc->gate_shift;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = lock;
+
+		gate_hw = &gate->hw;
+		gate_ops = &clk_gate_ops;
+	}
+
+	if (mc->divider_shift >= 0) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		div->reg = base + mc->divider_reg;
+		div->shift = mc->divider_shift;
+		div->width = mc->divider_width;
+		div->lock = lock;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
+		mux_hw, mux_ops,
+		div_hw, div_ops,
+		gate_hw, gate_ops,
+		mc->flags);
+
+	if (IS_ERR(clk)) {
+		kfree(gate);
+		kfree(mux);
+	}
+
+	return clk;
+err_out:
+	kfree(mux);
+
+	return ERR_PTR(ret);
+}
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+		int num, void __iomem *base, spinlock_t *lock,
+		struct clk_onecell_data *clk_data)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_composite *mc = &mcs[i];
+
+		clk = mtk_clk_register_composite(mc, base, lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					mc->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mc->id] = clk;
+	}
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 0000000..9dda9d8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_MTK_H
+#define __DRV_CLK_MTK_H
+
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define MAX_MUX_GATE_BIT	31
+#define INVALID_MUX_GATE_BIT	(MAX_MUX_GATE_BIT + 1)
+
+#define MHZ (1000 * 1000)
+
+struct mtk_fixed_factor {
+	int id;
+	const char *name;
+	const char *parent_name;
+	int mult;
+	int div;
+};
+
+#define FACTOR(_id, _name, _parent, _mult, _div) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.mult = _mult,				\
+		.div = _div,				\
+	}
+
+extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+		int num, struct clk_onecell_data *clk_data);
+
+struct mtk_composite {
+	int id;
+	const char *name;
+	const char * const *parent_names;
+	const char *parent;
+	unsigned flags;
+
+	uint32_t mux_reg;
+	uint32_t divider_reg;
+	uint32_t gate_reg;
+
+	signed char mux_shift;
+	signed char mux_width;
+	signed char gate_shift;
+
+	signed char divider_shift;
+	signed char divider_width;
+
+	signed char num_parents;
+};
+
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_reg = _reg,					\
+		.gate_shift = _gate,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_shift = -1,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+		.id = _id,						\
+		.parent = _parent,					\
+		.name = _name,						\
+		.divider_reg = _div_reg,				\
+		.divider_shift = _div_shift,				\
+		.divider_width = _div_width,				\
+		.gate_reg = _gate_reg,					\
+		.gate_shift = _gate_shift,				\
+		.mux_shift = -1,					\
+		.flags = 0,						\
+	}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+		void __iomem *base, spinlock_t *lock);
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+		int num, void __iomem *base, spinlock_t *lock,
+		struct clk_onecell_data *clk_data);
+
+struct mtk_gate_regs {
+	u32 sta_ofs;
+	u32 clr_ofs;
+	u32 set_ofs;
+};
+
+struct mtk_gate {
+	int id;
+	const char *name;
+	const char *parent_name;
+	const struct mtk_gate_regs *regs;
+	int shift;
+	const struct clk_ops *ops;
+};
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+		int num, struct clk_onecell_data *clk_data);
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
+
+#define HAVE_RST_BAR	BIT(0)
+
+struct mtk_pll_data {
+	int id;
+	const char *name;
+	uint32_t reg;
+	uint32_t pwr_reg;
+	uint32_t en_mask;
+	uint32_t pd_reg;
+	uint32_t tuner_reg;
+	int pd_shift;
+	unsigned int flags;
+	const struct clk_ops *ops;
+	u32 rst_bar_mask;
+	unsigned long fmax;
+	int pcwbits;
+	uint32_t pcw_reg;
+	int pcw_shift;
+};
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls,
+		struct clk_onecell_data *clk_data);
+
+#ifdef CONFIG_RESET_CONTROLLER
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs);
+#else
+static inline void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+}
+#endif
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
new file mode 100644
index 0000000..44409e9
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+
+#include "clk-mtk.h"
+
+#define REG_CON0		0
+#define REG_CON1		4
+
+#define CON0_BASE_EN		BIT(0)
+#define CON0_PWR_ON		BIT(0)
+#define CON0_ISO_EN		BIT(1)
+#define CON0_PCW_CHG		BIT(31)
+
+#define AUDPLL_TUNER_EN		BIT(31)
+
+#define POSTDIV_MASK		0x7
+#define INTEGER_BITS		7
+
+/*
+ * MediaTek PLLs are configured through their pcw value. The pcw value describes
+ * a divider in the PLL feedback loop which consists of 7 bits for the integer
+ * part and the remaining bits (if present) for the fractional part. Also they
+ * have a 3 bit power-of-two post divider.
+ */
+
+struct mtk_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*base_addr;
+	void __iomem	*pd_addr;
+	void __iomem	*pwr_addr;
+	void __iomem	*tuner_addr;
+	void __iomem	*pcw_addr;
+	const struct mtk_pll_data *data;
+};
+
+static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_pll, hw);
+}
+
+static int mtk_pll_is_prepared(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
+}
+
+static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
+		u32 pcw, int postdiv)
+{
+	int pcwbits = pll->data->pcwbits;
+	int pcwfbits;
+	u64 vco;
+	u8 c = 0;
+
+	/* The fractional part of the PLL divider. */
+	pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+
+	vco = (u64)fin * pcw;
+
+	if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
+		c = 1;
+
+	vco >>= pcwfbits;
+
+	if (c)
+		vco++;
+
+	return ((unsigned long)vco + postdiv - 1) / postdiv;
+}
+
+static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
+		int postdiv)
+{
+	u32 con1, pd, val;
+	int pll_en;
+
+	/* set postdiv */
+	pd = readl(pll->pd_addr);
+	pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
+	pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+	writel(pd, pll->pd_addr);
+
+	pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
+
+	/* set pcw */
+	val = readl(pll->pcw_addr);
+
+	val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
+			pll->data->pcw_shift);
+	val |= pcw << pll->data->pcw_shift;
+	writel(val, pll->pcw_addr);
+
+	con1 = readl(pll->base_addr + REG_CON1);
+
+	if (pll_en)
+		con1 |= CON0_PCW_CHG;
+
+	writel(con1, pll->base_addr + REG_CON1);
+	if (pll->tuner_addr)
+		writel(con1 + 1, pll->tuner_addr);
+
+	if (pll_en)
+		udelay(20);
+}
+
+/*
+ * mtk_pll_calc_values - calculate good values for a given input frequency.
+ * @pll:	The pll
+ * @pcw:	The pcw value (output)
+ * @postdiv:	The post divider (output)
+ * @freq:	The desired target frequency
+ * @fin:	The input frequency
+ *
+ */
+static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+		u32 freq, u32 fin)
+{
+	unsigned long fmin = 1000 * MHZ;
+	u64 _pcw;
+	u32 val;
+
+	if (freq > pll->data->fmax)
+		freq = pll->data->fmax;
+
+	for (val = 0; val < 4; val++) {
+		*postdiv = 1 << val;
+		if (freq * *postdiv >= fmin)
+			break;
+	}
+
+	/* _pcw = freq * postdiv / fin * 2^pcwfbits */
+	_pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
+	do_div(_pcw, fin);
+
+	*pcw = (u32)_pcw;
+}
+
+static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	u32 postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
+	mtk_pll_set_rate_regs(pll, pcw, postdiv);
+
+	return 0;
+}
+
+static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 postdiv;
+	u32 pcw;
+
+	postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
+	postdiv = 1 << postdiv;
+
+	pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
+	pcw &= GENMASK(pll->data->pcwbits - 1, 0);
+
+	return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
+}
+
+static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	int postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
+
+	return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
+}
+
+static int mtk_pll_prepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	r = readl(pll->pwr_addr) | CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+	udelay(1);
+
+	r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+	udelay(1);
+
+	r = readl(pll->base_addr + REG_CON0);
+	r |= pll->data->en_mask;
+	writel(r, pll->base_addr + REG_CON0);
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	udelay(20);
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr + REG_CON0);
+		r |= pll->data->rst_bar_mask;
+		writel(r, pll->base_addr + REG_CON0);
+	}
+
+	return 0;
+}
+
+static void mtk_pll_unprepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr + REG_CON0);
+		r &= ~pll->data->rst_bar_mask;
+		writel(r, pll->base_addr + REG_CON0);
+	}
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	r = readl(pll->base_addr + REG_CON0);
+	r &= ~CON0_BASE_EN;
+	writel(r, pll->base_addr + REG_CON0);
+
+	r = readl(pll->pwr_addr) | CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+
+	r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+}
+
+static const struct clk_ops mtk_pll_ops = {
+	.is_prepared	= mtk_pll_is_prepared,
+	.prepare	= mtk_pll_prepare,
+	.unprepare	= mtk_pll_unprepare,
+	.recalc_rate	= mtk_pll_recalc_rate,
+	.round_rate	= mtk_pll_round_rate,
+	.set_rate	= mtk_pll_set_rate,
+};
+
+static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
+		void __iomem *base)
+{
+	struct mtk_clk_pll *pll;
+	struct clk_init_data init = {};
+	struct clk *clk;
+	const char *parent_name = "clk26m";
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	pll->base_addr = base + data->reg;
+	pll->pwr_addr = base + data->pwr_reg;
+	pll->pd_addr = base + data->pd_reg;
+	pll->pcw_addr = base + data->pcw_reg;
+	if (data->tuner_reg)
+		pll->tuner_addr = base + data->tuner_reg;
+	pll->hw.init = &init;
+	pll->data = data;
+
+	init.name = data->name;
+	init.ops = &mtk_pll_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
+{
+	void __iomem *base;
+	int r, i;
+	struct clk *clk;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < num_plls; i++) {
+		const struct mtk_pll_data *pll = &plls[i];
+
+		clk = mtk_clk_register_pll(pll, base);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					pll->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[pll->id] = clk;
+	}
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
new file mode 100644
index 0000000..9e9fe4b
--- /dev/null
+++ b/drivers/clk/mediatek/reset.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+
+struct mtk_reset {
+	struct regmap *regmap;
+	int regofs;
+	struct reset_controller_dev rcdev;
+};
+
+static int mtk_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), ~0);
+}
+
+static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), 0);
+}
+
+static int mtk_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int ret;
+
+	ret = mtk_reset_assert(rcdev, id);
+	if (ret)
+		return ret;
+
+	return mtk_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_reset_ops = {
+	.assert = mtk_reset_assert,
+	.deassert = mtk_reset_deassert,
+	.reset = mtk_reset,
+};
+
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+	struct mtk_reset *data;
+	int ret;
+	struct regmap *regmap;
+
+	regmap = syscon_node_to_regmap(np);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
+				PTR_ERR(regmap));
+		return;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return;
+
+	data->regmap = regmap;
+	data->regofs = regofs;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = num_regs * 32;
+	data->rcdev.ops = &mtk_reset_ops;
+	data->rcdev.of_node = np;
+
+	ret = reset_controller_register(&data->rcdev);
+	if (ret) {
+		pr_err("could not register reset controller: %d\n", ret);
+		kfree(data);
+		return;
+	}
+}
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
new file mode 100644
index 0000000..6d45531
--- /dev/null
+++ b/drivers/clk/meson/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Meson specific clk
+#
+
+obj-y += clkc.o clk-pll.o clk-cpu.o
+obj-y += meson8b-clkc.o
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
new file mode 100644
index 0000000..71ad493
--- /dev/null
+++ b/drivers/clk/meson/clk-cpu.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * CPU clock path:
+ *
+ *                           +-[/N]-----|3|
+ *             MUX2  +--[/3]-+----------|2| MUX1
+ * [sys_pll]---|1|   |--[/2]------------|1|-|1|
+ *             | |---+------------------|0| | |----- [a5_clk]
+ *          +--|0|                          | |
+ * [xtal]---+-------------------------------|0|
+ *
+ *
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#define MESON_CPU_CLK_CNTL1		0x00
+#define MESON_CPU_CLK_CNTL		0x40
+
+#define MESON_CPU_CLK_MUX1		BIT(7)
+#define MESON_CPU_CLK_MUX2		BIT(0)
+
+#define MESON_N_WIDTH			9
+#define MESON_N_SHIFT			20
+#define MESON_SEL_WIDTH			2
+#define MESON_SEL_SHIFT			2
+
+#include "clkc.h"
+
+struct meson_clk_cpu {
+	struct notifier_block		clk_nb;
+	const struct clk_div_table	*div_table;
+	struct clk_hw			hw;
+	void __iomem			*base;
+	u16				reg_off;
+};
+#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
+#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
+
+static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+
+	return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
+				  MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+	unsigned int div, sel, N = 0;
+	u32 reg;
+
+	div = DIV_ROUND_UP(parent_rate, rate);
+
+	if (div <= 3) {
+		sel = div - 1;
+	} else {
+		sel = 3;
+		N = div / 2;
+	}
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+	reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
+	writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+	reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
+	writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+
+	return 0;
+}
+
+static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+	unsigned int N, sel;
+	unsigned int div = 1;
+	u32 reg;
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+	N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+	sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
+
+	if (sel < 3)
+		div = sel + 1;
+	else
+		div = 2 * N;
+
+	return parent_rate / div;
+}
+
+static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
+					 struct clk_notifier_data *ndata)
+{
+	u32 cpu_clk_cntl;
+
+	/* switch MUX1 to xtal */
+	cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
+	writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	udelay(100);
+
+	/* switch MUX2 to sys-pll */
+	cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
+	writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+
+	return 0;
+}
+
+static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
+					  struct clk_notifier_data *ndata)
+{
+	u32 cpu_clk_cntl;
+
+	/* switch MUX1 to divisors' output */
+	cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
+	writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	udelay(100);
+
+	return 0;
+}
+
+/*
+ * This clock notifier is called when the frequency of the of the parent
+ * PLL clock is to be changed. We use the xtal input as temporary parent
+ * while the PLL frequency is stabilized.
+ */
+static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
+				     unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
+	int ret = 0;
+
+	if (event == PRE_RATE_CHANGE)
+		ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
+	else if (event == POST_RATE_CHANGE)
+		ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
+
+	return notifier_from_errno(ret);
+}
+
+static const struct clk_ops meson_clk_cpu_ops = {
+	.recalc_rate	= meson_clk_cpu_recalc_rate,
+	.round_rate	= meson_clk_cpu_round_rate,
+	.set_rate	= meson_clk_cpu_set_rate,
+};
+
+struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base,
+				   spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk *pclk;
+	struct meson_clk_cpu *clk_cpu;
+	struct clk_init_data init;
+	int ret;
+
+	clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
+	if (!clk_cpu)
+		return ERR_PTR(-ENOMEM);
+
+	clk_cpu->base = reg_base;
+	clk_cpu->reg_off = clk_conf->reg_off;
+	clk_cpu->div_table = clk_conf->conf.div_table;
+	clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;
+
+	init.name = clk_conf->clk_name;
+	init.ops = &meson_clk_cpu_ops;
+	init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
+	init.flags |= CLK_SET_RATE_PARENT;
+	init.parent_names = clk_conf->clks_parent;
+	init.num_parents = 1;
+
+	clk_cpu->hw.init = &init;
+
+	pclk = __clk_lookup(clk_conf->clks_parent[0]);
+	if (!pclk) {
+		pr_err("%s: could not lookup parent clock %s\n",
+				__func__, clk_conf->clks_parent[0]);
+		ret = -EINVAL;
+		goto free_clk;
+	}
+
+	ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
+	if (ret) {
+		pr_err("%s: failed to register clock notifier for %s\n",
+				__func__, clk_conf->clk_name);
+		goto free_clk;
+	}
+
+	clk = clk_register(NULL, &clk_cpu->hw);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto unregister_clk_nb;
+	}
+
+	return clk;
+
+unregister_clk_nb:
+	clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
+free_clk:
+	kfree(clk_cpu);
+
+	return ERR_PTR(ret);
+}
+
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
new file mode 100644
index 0000000..664edf0
--- /dev/null
+++ b/drivers/clk/meson/clk-pll.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * In the most basic form, a Meson PLL is composed as follows:
+ *
+ *                     PLL
+ *      +------------------------------+
+ *      |                              |
+ * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
+ *      |         ^        ^           |
+ *      +------------------------------+
+ *                |        |
+ *               FREF     VCO
+ *
+ * out = (in * M / N) >> OD
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "clkc.h"
+
+#define MESON_PLL_RESET				BIT(29)
+#define MESON_PLL_LOCK				BIT(31)
+
+struct meson_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*base;
+	struct pll_conf	*conf;
+	unsigned int	rate_count;
+	spinlock_t	*lock;
+};
+#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
+
+static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+	struct parm *p;
+	unsigned long parent_rate_mhz = parent_rate / 1000000;
+	unsigned long rate_mhz;
+	u16 n, m, od;
+	u32 reg;
+
+	p = &pll->conf->n;
+	reg = readl(pll->base + p->reg_off);
+	n = PARM_GET(p->width, p->shift, reg);
+
+	p = &pll->conf->m;
+	reg = readl(pll->base + p->reg_off);
+	m = PARM_GET(p->width, p->shift, reg);
+
+	p = &pll->conf->od;
+	reg = readl(pll->base + p->reg_off);
+	od = PARM_GET(p->width, p->shift, reg);
+
+	rate_mhz = (parent_rate_mhz * m / n) >> od;
+
+	return rate_mhz * 1000000;
+}
+
+static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *parent_rate)
+{
+	struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+	const struct pll_rate_table *rate_table = pll->conf->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate <= rate_table[i].rate)
+			return rate_table[i].rate;
+	}
+
+	/* else return the smallest value */
+	return rate_table[0].rate;
+}
+
+static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
+							       unsigned long rate)
+{
+	const struct pll_rate_table *rate_table = pll->conf->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+	}
+	return NULL;
+}
+
+static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
+				   struct parm *p_n)
+{
+	int delay = 24000000;
+	u32 reg;
+
+	while (delay > 0) {
+		reg = readl(pll->base + p_n->reg_off);
+
+		if (reg & MESON_PLL_LOCK)
+			return 0;
+		delay--;
+	}
+	return -ETIMEDOUT;
+}
+
+static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+	struct parm *p;
+	const struct pll_rate_table *rate_set;
+	unsigned long old_rate;
+	int ret = 0;
+	u32 reg;
+
+	if (parent_rate == 0 || rate == 0)
+		return -EINVAL;
+
+	old_rate = rate;
+
+	rate_set = meson_clk_get_pll_settings(pll, rate);
+	if (!rate_set)
+		return -EINVAL;
+
+	/* PLL reset */
+	p = &pll->conf->n;
+	reg = readl(pll->base + p->reg_off);
+	writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
+
+	reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
+	writel(reg, pll->base + p->reg_off);
+
+	p = &pll->conf->m;
+	reg = readl(pll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
+	writel(reg, pll->base + p->reg_off);
+
+	p = &pll->conf->od;
+	reg = readl(pll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
+	writel(reg, pll->base + p->reg_off);
+
+	p = &pll->conf->n;
+	ret = meson_clk_pll_wait_lock(pll, p);
+	if (ret) {
+		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
+			__func__, old_rate);
+		meson_clk_pll_set_rate(hw, old_rate, parent_rate);
+	}
+
+	return ret;
+}
+
+static const struct clk_ops meson_clk_pll_ops = {
+	.recalc_rate	= meson_clk_pll_recalc_rate,
+	.round_rate	= meson_clk_pll_round_rate,
+	.set_rate	= meson_clk_pll_set_rate,
+};
+
+static const struct clk_ops meson_clk_pll_ro_ops = {
+	.recalc_rate	= meson_clk_pll_recalc_rate,
+};
+
+struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base,
+				   spinlock_t *lock)
+{
+	struct clk *clk;
+	struct meson_clk_pll *clk_pll;
+	struct clk_init_data init;
+
+	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+	if (!clk_pll)
+		return ERR_PTR(-ENOMEM);
+
+	clk_pll->base = reg_base + clk_conf->reg_off;
+	clk_pll->lock = lock;
+	clk_pll->conf = clk_conf->conf.pll;
+
+	init.name = clk_conf->clk_name;
+	init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
+
+	init.parent_names = &clk_conf->clks_parent[0];
+	init.num_parents = 1;
+	init.ops = &meson_clk_pll_ro_ops;
+
+	/* If no rate_table is specified we assume the PLL is read-only */
+	if (clk_pll->conf->rate_table) {
+		int len;
+
+		for (len = 0; clk_pll->conf->rate_table[len].rate != 0; )
+			len++;
+
+		 clk_pll->rate_count = len;
+		 init.ops = &meson_clk_pll_ops;
+	}
+
+	clk_pll->hw.init = &init;
+
+	clk = clk_register(NULL, &clk_pll->hw);
+	if (IS_ERR(clk))
+		kfree(clk_pll);
+
+	return clk;
+}
diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
new file mode 100644
index 0000000..b8c511c
--- /dev/null
+++ b/drivers/clk/meson/clkc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include "clkc.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk **clks;
+static struct clk_onecell_data clk_data;
+
+struct clk ** __init meson_clk_init(struct device_node *np,
+				   unsigned long nr_clks)
+{
+	clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
+	if (!clks)
+		return ERR_PTR(-ENOMEM);
+
+	clk_data.clks = clks;
+	clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	return clks;
+}
+
+static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+	if (clks && id)
+		clks[id] = clk;
+}
+
+static struct clk * __init
+meson_clk_register_composite(const struct clk_conf *clk_conf,
+			     void __iomem *clk_base)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_gate *gate = NULL;
+	const struct clk_ops *mux_ops = NULL;
+	const struct composite_conf *composite_conf;
+
+	composite_conf = clk_conf->conf.composite;
+
+	if (clk_conf->num_parents > 1) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = clk_base + clk_conf->reg_off
+				+ composite_conf->mux_parm.reg_off;
+		mux->shift = composite_conf->mux_parm.shift;
+		mux->mask = BIT(composite_conf->mux_parm.width) - 1;
+		mux->flags = composite_conf->mux_flags;
+		mux->lock = &clk_lock;
+		mux->table = composite_conf->mux_table;
+		mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
+			  &clk_mux_ro_ops : &clk_mux_ops;
+	}
+
+	if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			clk = ERR_PTR(-ENOMEM);
+			goto error;
+		}
+
+		div->reg = clk_base + clk_conf->reg_off
+				+ composite_conf->div_parm.reg_off;
+		div->shift = composite_conf->div_parm.shift;
+		div->width = composite_conf->div_parm.width;
+		div->lock = &clk_lock;
+		div->flags = composite_conf->div_flags;
+		div->table = composite_conf->div_table;
+	}
+
+	if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			clk = ERR_PTR(-ENOMEM);
+			goto error;
+		}
+
+		gate->reg = clk_base + clk_conf->reg_off
+				+ composite_conf->div_parm.reg_off;
+		gate->bit_idx = composite_conf->gate_parm.shift;
+		gate->flags = composite_conf->gate_flags;
+		gate->lock = &clk_lock;
+	}
+
+	clk = clk_register_composite(NULL, clk_conf->clk_name,
+				    clk_conf->clks_parent,
+				    clk_conf->num_parents,
+				    mux ? &mux->hw : NULL, mux_ops,
+				    div ? &div->hw : NULL, &clk_divider_ops,
+				    gate ? &gate->hw : NULL, &clk_gate_ops,
+				    clk_conf->flags);
+	if (IS_ERR(clk))
+		goto error;
+
+	return clk;
+
+error:
+	kfree(gate);
+	kfree(div);
+	kfree(mux);
+
+	return clk;
+}
+
+static struct clk * __init
+meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
+				void __iomem *clk_base)
+{
+	struct clk *clk;
+	const struct fixed_fact_conf *fixed_fact_conf;
+	const struct parm *p;
+	unsigned int mult, div;
+	u32 reg;
+
+	fixed_fact_conf = &clk_conf->conf.fixed_fact;
+
+	mult = clk_conf->conf.fixed_fact.mult;
+	div = clk_conf->conf.fixed_fact.div;
+
+	if (!mult) {
+		mult = 1;
+		p = &fixed_fact_conf->mult_parm;
+		if (MESON_PARM_APPLICABLE(p)) {
+			reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
+			mult = PARM_GET(p->width, p->shift, reg);
+		}
+	}
+
+	if (!div) {
+		div = 1;
+		p = &fixed_fact_conf->div_parm;
+		if (MESON_PARM_APPLICABLE(p)) {
+			reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
+			mult = PARM_GET(p->width, p->shift, reg);
+		}
+	}
+
+	clk = clk_register_fixed_factor(NULL,
+			clk_conf->clk_name,
+			clk_conf->clks_parent[0],
+			clk_conf->flags,
+			mult, div);
+
+	return clk;
+}
+
+static struct clk * __init
+meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
+			      void __iomem *clk_base)
+{
+	struct clk *clk;
+	const struct fixed_rate_conf *fixed_rate_conf;
+	const struct parm *r;
+	unsigned long rate;
+	u32 reg;
+
+	fixed_rate_conf = &clk_conf->conf.fixed_rate;
+	rate = fixed_rate_conf->rate;
+
+	if (!rate) {
+		r = &fixed_rate_conf->rate_parm;
+		reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
+		rate = PARM_GET(r->width, r->shift, reg);
+	}
+
+	rate *= 1000000;
+
+	clk = clk_register_fixed_rate(NULL,
+			clk_conf->clk_name,
+			clk_conf->num_parents
+				? clk_conf->clks_parent[0] : NULL,
+			clk_conf->flags, rate);
+
+	return clk;
+}
+
+void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
+				    size_t nr_confs,
+				    void __iomem *clk_base)
+{
+	unsigned int i;
+	struct clk *clk = NULL;
+
+	for (i = 0; i < nr_confs; i++) {
+		const struct clk_conf *clk_conf = &clk_confs[i];
+
+		switch (clk_conf->clk_type) {
+		case CLK_FIXED_RATE:
+			clk = meson_clk_register_fixed_rate(clk_conf,
+							    clk_base);
+			break;
+		case CLK_FIXED_FACTOR:
+			clk = meson_clk_register_fixed_factor(clk_conf,
+							      clk_base);
+			break;
+		case CLK_COMPOSITE:
+			clk = meson_clk_register_composite(clk_conf,
+							   clk_base);
+			break;
+		case CLK_CPU:
+			clk = meson_clk_register_cpu(clk_conf, clk_base,
+						     &clk_lock);
+			break;
+		case CLK_PLL:
+			clk = meson_clk_register_pll(clk_conf, clk_base,
+						     &clk_lock);
+			break;
+		default:
+			clk = NULL;
+		}
+
+		if (!clk) {
+			pr_err("%s: unknown clock type %d\n", __func__,
+			       clk_conf->clk_type);
+			continue;
+		}
+
+		if (IS_ERR(clk)) {
+			pr_warn("%s: Unable to create %s clock\n", __func__,
+				clk_conf->clk_name);
+			continue;
+		}
+
+		meson_clk_add_lookup(clk, clk_conf->clk_id);
+	}
+}
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
new file mode 100644
index 0000000..609ae92
--- /dev/null
+++ b/drivers/clk/meson/clkc.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CLKC_H
+#define __CLKC_H
+
+#define PMASK(width)			GENMASK(width - 1, 0)
+#define SETPMASK(width, shift)		GENMASK(shift + width - 1, shift)
+#define CLRPMASK(width, shift)		(~SETPMASK(width, shift))
+
+#define PARM_GET(width, shift, reg)					\
+	(((reg) & SETPMASK(width, shift)) >> (shift))
+#define PARM_SET(width, shift, reg, val)				\
+	(((reg) & CLRPMASK(width, shift)) | (val << (shift)))
+
+#define MESON_PARM_APPLICABLE(p)		(!!((p)->width))
+
+struct parm {
+	u16	reg_off;
+	u8	shift;
+	u8	width;
+};
+#define PARM(_r, _s, _w)						\
+	{								\
+		.reg_off	= (_r),					\
+		.shift		= (_s),					\
+		.width		= (_w),					\
+	}								\
+
+struct pll_rate_table {
+	unsigned long	rate;
+	u16		m;
+	u16		n;
+	u16		od;
+};
+#define PLL_RATE(_r, _m, _n, _od)					\
+	{								\
+		.rate		= (_r),					\
+		.m		= (_m),					\
+		.n		= (_n),					\
+		.od		= (_od),				\
+	}								\
+
+struct pll_conf {
+	const struct pll_rate_table	*rate_table;
+	struct parm			m;
+	struct parm			n;
+	struct parm			od;
+};
+
+struct fixed_fact_conf {
+	unsigned int	div;
+	unsigned int	mult;
+	struct parm	div_parm;
+	struct parm	mult_parm;
+};
+
+struct fixed_rate_conf {
+	unsigned long	rate;
+	struct parm	rate_parm;
+};
+
+struct composite_conf {
+	struct parm		mux_parm;
+	struct parm		div_parm;
+	struct parm		gate_parm;
+	struct clk_div_table	*div_table;
+	u32			*mux_table;
+	u8			mux_flags;
+	u8			div_flags;
+	u8			gate_flags;
+};
+
+#define PNAME(x) static const char *x[]
+
+enum clk_type {
+	CLK_FIXED_FACTOR,
+	CLK_FIXED_RATE,
+	CLK_COMPOSITE,
+	CLK_CPU,
+	CLK_PLL,
+};
+
+struct clk_conf {
+	u16				reg_off;
+	enum clk_type			clk_type;
+	unsigned int			clk_id;
+	const char			*clk_name;
+	const char			**clks_parent;
+	int				num_parents;
+	unsigned long			flags;
+	union {
+		struct fixed_fact_conf		fixed_fact;
+		struct fixed_rate_conf		fixed_rate;
+		const struct composite_conf		*composite;
+		struct pll_conf			*pll;
+		const struct clk_div_table	*div_table;
+	} conf;
+};
+
+#define FIXED_RATE_P(_ro, _ci, _cn, _f, _c)				\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_FIXED_RATE,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.flags				= (_f),			\
+		.conf.fixed_rate.rate_parm	= _c,			\
+	}								\
+
+#define FIXED_RATE(_ci, _cn, _f, _r)					\
+	{								\
+		.clk_type			= CLK_FIXED_RATE,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.flags				= (_f),			\
+		.conf.fixed_rate.rate		= (_r),			\
+	}								\
+
+#define PLL(_ro, _ci, _cn, _cp, _f, _c)					\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_PLL,		\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.flags				= (_f),			\
+		.conf.pll			= (_c),			\
+	}								\
+
+#define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d)				\
+	{								\
+		.clk_type			= CLK_FIXED_FACTOR,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.conf.fixed_fact.div		= (_d),			\
+	}								\
+
+#define CPU(_ro, _ci, _cn, _cp, _dt)					\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_CPU,		\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.conf.div_table			= (_dt),		\
+	}								\
+
+#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c)				\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_COMPOSITE,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.flags				= (_f),			\
+		.conf.composite			= (_c),			\
+	}								\
+
+struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
+void meson_clk_register_clks(const struct clk_conf *clk_confs,
+			     unsigned int nr_confs, void __iomem *clk_base);
+struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base, spinlock_t *lock);
+struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base, spinlock_t *lock);
+
+#endif /* __CLKC_H */
diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c
new file mode 100644
index 0000000..61f6d55
--- /dev/null
+++ b/drivers/clk/meson/meson8b-clkc.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/meson8b-clkc.h>
+
+#include "clkc.h"
+
+#define MESON8B_REG_CTL0_ADDR		0x0000
+#define MESON8B_REG_SYS_CPU_CNTL1	0x015c
+#define MESON8B_REG_HHI_MPEG		0x0174
+#define MESON8B_REG_MALI		0x01b0
+#define MESON8B_REG_PLL_FIXED		0x0280
+#define MESON8B_REG_PLL_SYS		0x0300
+#define MESON8B_REG_PLL_VID		0x0320
+
+static const struct pll_rate_table sys_pll_rate_table[] = {
+	PLL_RATE(312000000, 52, 1, 2),
+	PLL_RATE(336000000, 56, 1, 2),
+	PLL_RATE(360000000, 60, 1, 2),
+	PLL_RATE(384000000, 64, 1, 2),
+	PLL_RATE(408000000, 68, 1, 2),
+	PLL_RATE(432000000, 72, 1, 2),
+	PLL_RATE(456000000, 76, 1, 2),
+	PLL_RATE(480000000, 80, 1, 2),
+	PLL_RATE(504000000, 84, 1, 2),
+	PLL_RATE(528000000, 88, 1, 2),
+	PLL_RATE(552000000, 92, 1, 2),
+	PLL_RATE(576000000, 96, 1, 2),
+	PLL_RATE(600000000, 50, 1, 1),
+	PLL_RATE(624000000, 52, 1, 1),
+	PLL_RATE(648000000, 54, 1, 1),
+	PLL_RATE(672000000, 56, 1, 1),
+	PLL_RATE(696000000, 58, 1, 1),
+	PLL_RATE(720000000, 60, 1, 1),
+	PLL_RATE(744000000, 62, 1, 1),
+	PLL_RATE(768000000, 64, 1, 1),
+	PLL_RATE(792000000, 66, 1, 1),
+	PLL_RATE(816000000, 68, 1, 1),
+	PLL_RATE(840000000, 70, 1, 1),
+	PLL_RATE(864000000, 72, 1, 1),
+	PLL_RATE(888000000, 74, 1, 1),
+	PLL_RATE(912000000, 76, 1, 1),
+	PLL_RATE(936000000, 78, 1, 1),
+	PLL_RATE(960000000, 80, 1, 1),
+	PLL_RATE(984000000, 82, 1, 1),
+	PLL_RATE(1008000000, 84, 1, 1),
+	PLL_RATE(1032000000, 86, 1, 1),
+	PLL_RATE(1056000000, 88, 1, 1),
+	PLL_RATE(1080000000, 90, 1, 1),
+	PLL_RATE(1104000000, 92, 1, 1),
+	PLL_RATE(1128000000, 94, 1, 1),
+	PLL_RATE(1152000000, 96, 1, 1),
+	PLL_RATE(1176000000, 98, 1, 1),
+	PLL_RATE(1200000000, 50, 1, 0),
+	PLL_RATE(1224000000, 51, 1, 0),
+	PLL_RATE(1248000000, 52, 1, 0),
+	PLL_RATE(1272000000, 53, 1, 0),
+	PLL_RATE(1296000000, 54, 1, 0),
+	PLL_RATE(1320000000, 55, 1, 0),
+	PLL_RATE(1344000000, 56, 1, 0),
+	PLL_RATE(1368000000, 57, 1, 0),
+	PLL_RATE(1392000000, 58, 1, 0),
+	PLL_RATE(1416000000, 59, 1, 0),
+	PLL_RATE(1440000000, 60, 1, 0),
+	PLL_RATE(1464000000, 61, 1, 0),
+	PLL_RATE(1488000000, 62, 1, 0),
+	PLL_RATE(1512000000, 63, 1, 0),
+	PLL_RATE(1536000000, 64, 1, 0),
+	{ /* sentinel */ },
+};
+
+static const struct clk_div_table cpu_div_table[] = {
+	{ .val = 1, .div = 1 },
+	{ .val = 2, .div = 2 },
+	{ .val = 3, .div = 3 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 6 },
+	{ .val = 4, .div = 8 },
+	{ .val = 5, .div = 10 },
+	{ .val = 6, .div = 12 },
+	{ .val = 7, .div = 14 },
+	{ .val = 8, .div = 16 },
+	{ /* sentinel */ },
+};
+
+PNAME(p_xtal)		= { "xtal" };
+PNAME(p_fclk_div)	= { "fixed_pll" };
+PNAME(p_cpu_clk)	= { "sys_pll" };
+PNAME(p_clk81)		= { "fclk_div3", "fclk_div4", "fclk_div5" };
+PNAME(p_mali)		= { "fclk_div3", "fclk_div4", "fclk_div5",
+			    "fclk_div7", "zero" };
+
+static u32 mux_table_clk81[]	= { 6, 5, 7 };
+static u32 mux_table_mali[]	= { 6, 5, 7, 4, 0 };
+
+static struct pll_conf pll_confs = {
+	.m		= PARM(0x00, 0,  9),
+	.n		= PARM(0x00, 9,  5),
+	.od		= PARM(0x00, 16, 2),
+};
+
+static struct pll_conf sys_pll_conf = {
+	.m		= PARM(0x00, 0,  9),
+	.n		= PARM(0x00, 9,  5),
+	.od		= PARM(0x00, 16, 2),
+	.rate_table	= sys_pll_rate_table,
+};
+
+static const struct composite_conf clk81_conf __initconst = {
+	.mux_table		= mux_table_clk81,
+	.mux_flags		= CLK_MUX_READ_ONLY,
+	.mux_parm		= PARM(0x00, 12, 3),
+	.div_parm		= PARM(0x00, 0, 7),
+	.gate_parm		= PARM(0x00, 7, 1),
+};
+
+static const struct composite_conf mali_conf __initconst = {
+	.mux_table		= mux_table_mali,
+	.mux_parm		= PARM(0x00, 9, 3),
+	.div_parm		= PARM(0x00, 0, 7),
+	.gate_parm		= PARM(0x00, 8, 1),
+};
+
+static const struct clk_conf meson8b_xtal_conf __initconst =
+	FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal",
+		     CLK_IS_ROOT, PARM(0x00, 4, 7));
+
+static const struct clk_conf meson8b_clk_confs[] __initconst = {
+	FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0),
+	PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll",
+	    p_xtal, 0, &pll_confs),
+	PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll",
+	    p_xtal, 0, &pll_confs),
+	PLL(MESON8B_REG_PLL_SYS, CLKID_PLL_SYS, "sys_pll",
+	    p_xtal, 0, &sys_pll_conf),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV5, "fclk_div5", p_fclk_div, 0, 5),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV7, "fclk_div7", p_fclk_div, 0, 7),
+	CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk,
+	    cpu_div_table),
+	COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81,
+		  CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
+	COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
+		  CLK_IGNORE_UNUSED, &mali_conf),
+};
+
+static void __init meson8b_clkc_init(struct device_node *np)
+{
+	void __iomem *clk_base;
+
+	if (!meson_clk_init(np, CLK_NR_CLKS))
+		return;
+
+	/* XTAL */
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("%s: Unable to map xtal base\n", __func__);
+		return;
+	}
+
+	meson_clk_register_clks(&meson8b_xtal_conf, 1, clk_base);
+	iounmap(clk_base);
+
+	/*  Generic clocks and PLLs */
+	clk_base = of_iomap(np, 1);
+	if (!clk_base) {
+		pr_err("%s: Unable to map clk base\n", __func__);
+		return;
+	}
+
+	meson_clk_register_clks(meson8b_clk_confs,
+				ARRAY_SIZE(meson8b_clk_confs),
+				clk_base);
+}
+CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init);
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 3caaf7c..9d4bc41 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -12,3 +12,5 @@
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
+
+obj-y += clk-of-pxa1928.o
diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c
index d14120e..09d41c7 100644
--- a/drivers/clk/mmp/clk-apbc.c
+++ b/drivers/clk/mmp/clk-apbc.c
@@ -115,7 +115,7 @@
 		spin_unlock_irqrestore(apbc->lock, flags);
 }
 
-struct clk_ops clk_apbc_ops = {
+static struct clk_ops clk_apbc_ops = {
 	.prepare = clk_apbc_prepare,
 	.unprepare = clk_apbc_unprepare,
 };
diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c
index abe182b..cdcf2d7 100644
--- a/drivers/clk/mmp/clk-apmu.c
+++ b/drivers/clk/mmp/clk-apmu.c
@@ -61,7 +61,7 @@
 		spin_unlock_irqrestore(apmu->lock, flags);
 }
 
-struct clk_ops clk_apmu_ops = {
+static struct clk_ops clk_apmu_ops = {
 	.enable = clk_apmu_enable,
 	.disable = clk_apmu_disable,
 };
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 5c90a42..09d2832 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -63,10 +63,8 @@
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 14634, .den = 2165},	/*14.745MHZ */
+	{.num = 8125, .den = 1536},	/*14.745MHZ */
 	{.num = 3521, .den = 689},	/*19.23MHZ */
-	{.num = 9679, .den = 5728},	/*58.9824MHZ */
-	{.num = 15850, .den = 9451},	/*59.429MHZ */
 };
 
 static const char *uart_parent[] = {"uart_pll", "vctcxo"};
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 2cbc2b4..251533d 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -30,6 +30,7 @@
 #define APBC_TWSI4	0x7c
 #define APBC_TWSI5	0x80
 #define APBC_KPC	0x18
+#define APBC_TIMER	0x24
 #define APBC_UART0	0x2c
 #define APBC_UART1	0x30
 #define APBC_UART2	0x34
@@ -98,10 +99,8 @@
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 14634, .den = 2165},	/*14.745MHZ */
+	{.num = 8125, .den = 1536},	/*14.745MHZ */
 	{.num = 3521, .den = 689},	/*19.23MHZ */
-	{.num = 9679, .den = 5728},	/*58.9824MHZ */
-	{.num = 15850, .den = 9451},	/*59.429MHZ */
 };
 
 static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
@@ -134,6 +133,9 @@
 static DEFINE_SPINLOCK(ssp3_lock);
 static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -145,6 +147,7 @@
 	{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
 	{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
 	{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
+	{0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 
 static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -170,6 +173,7 @@
 	{MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x7, 0x3, 0x0, 0, &ssp1_lock},
 	{MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x7, 0x3, 0x0, 0, &ssp2_lock},
 	{MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x7, 0x3, 0x0, 0, &ssp3_lock},
+	{MMP2_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x7, 0x3, 0x0, 0, &timer_lock},
 };
 
 static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 5b1810d..64eaf41 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -32,6 +32,7 @@
 #define APBC_PWM1	0x10
 #define APBC_PWM2	0x14
 #define APBC_PWM3	0x18
+#define APBC_TIMER	0x34
 #define APBC_SSP0	0x81c
 #define APBC_SSP1	0x820
 #define APBC_SSP2	0x84c
@@ -58,6 +59,7 @@
 	{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
 	{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
 	{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
+	{PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
@@ -70,6 +72,7 @@
 	{PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
 	{PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
 	{PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+	{PXA168_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
 	{PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
 	{PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
 	{PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -119,6 +122,9 @@
 static DEFINE_SPINLOCK(ssp4_lock);
 static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96", "pll1_192"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -130,6 +136,7 @@
 	{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
 	{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
 	{0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock},
+	{0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 
 static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -151,6 +158,7 @@
 	{PXA168_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x3, 0x3, 0x0, 0, &ssp2_lock},
 	{PXA168_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x3, 0x3, 0x0, 0, &ssp3_lock},
 	{PXA168_CLK_SSP4, "ssp4_clk", "ssp4_mux", CLK_SET_RATE_PARENT, APBC_SSP4, 0x3, 0x3, 0x0, 0, &ssp4_lock},
+	{PXA168_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x3, 0x3, 0x0, 0, &timer_lock},
 };
 
 static void pxa168_apb_periph_clk_init(struct pxa168_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c
new file mode 100644
index 0000000..433a5ae
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa1928.c
@@ -0,0 +1,265 @@
+/*
+ * pxa1928 clock framework source file
+ *
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * Based on drivers/clk/mmp/clk-of-mmp2.c:
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/marvell,pxa1928.h>
+
+#include "clk.h"
+#include "reset.h"
+
+#define MPMU_UART_PLL	0x14
+
+struct pxa1928_clk_unit {
+	struct mmp_clk_unit unit;
+	void __iomem *mpmu_base;
+	void __iomem *apmu_base;
+	void __iomem *apbc_base;
+	void __iomem *apbcp_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+	{0, "clk32", NULL, CLK_IS_ROOT, 32768},
+	{0, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
+	{0, "pll1_624", NULL, CLK_IS_ROOT, 624000000},
+	{0, "pll5p", NULL, CLK_IS_ROOT, 832000000},
+	{0, "pll5", NULL, CLK_IS_ROOT, 1248000000},
+	{0, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+	{0, "pll1_d2", "pll1_624", 1, 2, 0},
+	{0, "pll1_d9", "pll1_624", 1, 9, 0},
+	{0, "pll1_d12", "pll1_624", 1, 12, 0},
+	{0, "pll1_d16", "pll1_624", 1, 16, 0},
+	{0, "pll1_d20", "pll1_624", 1, 20, 0},
+	{0, "pll1_416", "pll1_624", 2, 3, 0},
+	{0, "vctcxo_d2", "vctcxo", 1, 2, 0},
+	{0, "vctcxo_d4", "vctcxo", 1, 4, 0},
+};
+
+static struct mmp_clk_factor_masks uart_factor_masks = {
+	.factor = 2,
+	.num_mask = 0x1fff,
+	.den_mask = 0x1fff,
+	.num_shift = 16,
+	.den_shift = 0,
+};
+
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
+	{.num = 832, .den = 234},	/*58.5MHZ */
+	{.num = 1, .den = 1},		/*26MHZ */
+};
+
+static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
+{
+	struct clk *clk;
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
+					ARRAY_SIZE(fixed_rate_clks));
+
+	mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
+					ARRAY_SIZE(fixed_factor_clks));
+
+	clk = mmp_clk_register_factor("uart_pll", "pll1_416",
+				CLK_SET_RATE_PARENT,
+				pxa_unit->mpmu_base + MPMU_UART_PLL,
+				&uart_factor_masks, uart_factor_tbl,
+				ARRAY_SIZE(uart_factor_tbl), NULL);
+}
+
+static DEFINE_SPINLOCK(uart0_lock);
+static DEFINE_SPINLOCK(uart1_lock);
+static DEFINE_SPINLOCK(uart2_lock);
+static DEFINE_SPINLOCK(uart3_lock);
+static const char *uart_parent_names[] = {"uart_pll", "vctcxo"};
+
+static DEFINE_SPINLOCK(ssp0_lock);
+static DEFINE_SPINLOCK(ssp1_lock);
+static const char *ssp_parent_names[] = {"vctcxo_d4", "vctcxo_d2", "vctcxo", "pll1_d12"};
+
+static DEFINE_SPINLOCK(reset_lock);
+
+static struct mmp_param_mux_clk apbc_mux_clks[] = {
+	{0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 4, 3, 0, &uart0_lock},
+	{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 4, 3, 0, &uart1_lock},
+	{0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 4, 3, 0, &uart2_lock},
+	{0, "uart3_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 4, 3, 0, &uart3_lock},
+	{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 4, 3, 0, &ssp0_lock},
+	{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 4, 3, 0, &ssp1_lock},
+};
+
+static struct mmp_param_gate_clk apbc_gate_clks[] = {
+	{PXA1928_CLK_TWSI0, "twsi0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI1, "twsi1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI2, "twsi2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI3, "twsi3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI4, "twsi4_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI4 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI5, "twsi5_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI5 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_GPIO * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_KPC * 4, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
+	{PXA1928_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_RTC * 4, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
+	{PXA1928_CLK_PWM0, "pwm0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_PWM1, "pwm1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_PWM2, "pwm2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_PWM3, "pwm3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	/* The gate clocks has mux parent. */
+	{PXA1928_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 0x3, 0x3, 0x0, 0, &uart0_lock},
+	{PXA1928_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 0x3, 0x3, 0x0, 0, &uart1_lock},
+	{PXA1928_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 0x3, 0x3, 0x0, 0, &uart2_lock},
+	{PXA1928_CLK_UART3, "uart3_clk", "uart3_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 0x3, 0x3, 0x0, 0, &uart3_lock},
+	{PXA1928_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 0x3, 0x3, 0x0, 0, &ssp0_lock},
+	{PXA1928_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 0x3, 0x3, 0x0, 0, &ssp1_lock},
+};
+
+static void pxa1928_apb_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base,
+				ARRAY_SIZE(apbc_mux_clks));
+
+	mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
+				ARRAY_SIZE(apbc_gate_clks));
+}
+
+static DEFINE_SPINLOCK(sdh0_lock);
+static DEFINE_SPINLOCK(sdh1_lock);
+static DEFINE_SPINLOCK(sdh2_lock);
+static DEFINE_SPINLOCK(sdh3_lock);
+static DEFINE_SPINLOCK(sdh4_lock);
+static const char *sdh_parent_names[] = {"pll1_624", "pll5p", "pll5", "pll1_416"};
+
+static DEFINE_SPINLOCK(usb_lock);
+
+static struct mmp_param_mux_clk apmu_mux_clks[] = {
+	{0, "sdh_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 8, 2, 0, &sdh0_lock},
+};
+
+static struct mmp_param_div_clk apmu_div_clks[] = {
+	{0, "sdh_div", "sdh_mux", 0, PXA1928_CLK_SDH0 * 4, 10, 4, CLK_DIVIDER_ONE_BASED, &sdh0_lock},
+};
+
+static struct mmp_param_gate_clk apmu_gate_clks[] = {
+	{PXA1928_CLK_USB, "usb_clk", "usb_pll", 0, PXA1928_CLK_USB * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
+	{PXA1928_CLK_HSIC, "hsic_clk", "usb_pll", 0, PXA1928_CLK_HSIC * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
+	/* The gate clocks has mux parent. */
+	{PXA1928_CLK_SDH0, "sdh0_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 0x1b, 0x1b, 0x0, 0, &sdh0_lock},
+	{PXA1928_CLK_SDH1, "sdh1_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH1 * 4, 0x1b, 0x1b, 0x0, 0, &sdh1_lock},
+	{PXA1928_CLK_SDH2, "sdh2_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH2 * 4, 0x1b, 0x1b, 0x0, 0, &sdh2_lock},
+	{PXA1928_CLK_SDH3, "sdh3_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH3 * 4, 0x1b, 0x1b, 0x0, 0, &sdh3_lock},
+	{PXA1928_CLK_SDH4, "sdh4_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH4 * 4, 0x1b, 0x1b, 0x0, 0, &sdh4_lock},
+};
+
+static void pxa1928_axi_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base,
+				ARRAY_SIZE(apmu_mux_clks));
+
+	mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base,
+				ARRAY_SIZE(apmu_div_clks));
+
+	mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base,
+				ARRAY_SIZE(apmu_gate_clks));
+}
+
+static void pxa1928_clk_reset_init(struct device_node *np,
+				struct pxa1928_clk_unit *pxa_unit)
+{
+	struct mmp_clk_reset_cell *cells;
+	int i, base, nr_resets;
+
+	nr_resets = ARRAY_SIZE(apbc_gate_clks);
+	cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL);
+	if (!cells)
+		return;
+
+	base = 0;
+	for (i = 0; i < nr_resets; i++) {
+		cells[base + i].clk_id = apbc_gate_clks[i].id;
+		cells[base + i].reg =
+			pxa_unit->apbc_base + apbc_gate_clks[i].offset;
+		cells[base + i].flags = 0;
+		cells[base + i].lock = apbc_gate_clks[i].lock;
+		cells[base + i].bits = 0x4;
+	}
+
+	mmp_clk_reset_register(np, cells, nr_resets);
+}
+
+static void __init pxa1928_mpmu_clk_init(struct device_node *np)
+{
+	struct pxa1928_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->mpmu_base = of_iomap(np, 0);
+	if (!pxa_unit->mpmu_base) {
+		pr_err("failed to map mpmu registers\n");
+		return;
+	}
+
+	pxa1928_pll_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_mpmu_clk, "marvell,pxa1928-mpmu", pxa1928_mpmu_clk_init);
+
+static void __init pxa1928_apmu_clk_init(struct device_node *np)
+{
+	struct pxa1928_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apmu_base = of_iomap(np, 0);
+	if (!pxa_unit->apmu_base) {
+		pr_err("failed to map apmu registers\n");
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, PXA1928_APMU_NR_CLKS);
+
+	pxa1928_axi_periph_clk_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_apmu_clk, "marvell,pxa1928-apmu", pxa1928_apmu_clk_init);
+
+static void __init pxa1928_apbc_clk_init(struct device_node *np)
+{
+	struct pxa1928_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apbc_base = of_iomap(np, 0);
+	if (!pxa_unit->apbc_base) {
+		pr_err("failed to map apbc registers\n");
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, PXA1928_APBC_NR_CLKS);
+
+	pxa1928_apb_periph_clk_init(pxa_unit);
+	pxa1928_clk_reset_init(np, pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_apbc_clk, "marvell,pxa1928-apbc", pxa1928_apbc_clk_init);
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 5e3c80d..13d6173 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -35,6 +35,8 @@
 #define APBC_SSP0	0x1c
 #define APBC_SSP1	0x20
 #define APBC_SSP2	0x4c
+#define APBC_TIMER0	0x30
+#define APBC_TIMER1	0x44
 #define APBCP_TWSI1	0x28
 #define APBCP_UART2	0x1c
 #define APMU_SDH0	0x54
@@ -57,6 +59,7 @@
 	{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
 	{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
 	{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
+	{PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
@@ -69,6 +72,7 @@
 	{PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
 	{PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
 	{PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+	{PXA910_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
 	{PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
 	{PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
 	{PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -115,6 +119,10 @@
 static DEFINE_SPINLOCK(ssp1_lock);
 static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
 
+static DEFINE_SPINLOCK(timer0_lock);
+static DEFINE_SPINLOCK(timer1_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -122,6 +130,8 @@
 	{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
 	{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock},
 	{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
+	{0, "timer0_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER0, 4, 3, 0, &timer0_lock},
+	{0, "timer1_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER1, 4, 3, 0, &timer1_lock},
 };
 
 static struct mmp_param_mux_clk apbcp_mux_clks[] = {
@@ -142,6 +152,8 @@
 	{PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock},
 	{PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock},
 	{PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock},
+	{PXA910_CLK_TIMER0, "timer0_clk", "timer0_mux", CLK_SET_RATE_PARENT, APBC_TIMER0, 0x3, 0x3, 0x0, 0, &timer0_lock},
+	{PXA910_CLK_TIMER1, "timer1_clk", "timer1_mux", CLK_SET_RATE_PARENT, APBC_TIMER1, 0x3, 0x3, 0x0, 0, &timer1_lock},
 };
 
 static struct mmp_param_gate_clk apbcp_gate_clks[] = {
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index 756f0f3..c19fd77 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -163,6 +163,7 @@
 	{ "pex1", "pex1_en", 9, 0 },
 	{ "sata0", NULL, 15, 0 },
 	{ "sdio", NULL, 17, 0 },
+	{ "crypto", NULL, 23, 0 },
 	{ "tdm", NULL, 25, 0 },
 	{ "ddr", NULL, 28, CLK_IGNORE_UNUSED },
 	{ "sata1", NULL, 30, 0 },
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index 22d136aa..32216f9 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -77,12 +77,12 @@
 	writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
 }
 
-static const char *sel_pll[]  __initdata = { "pll", "ref_xtal", };
-static const char *sel_cpu[]  __initdata = { "ref_cpu", "ref_xtal", };
-static const char *sel_pix[]  __initdata = { "ref_pix", "ref_xtal", };
-static const char *sel_io[]   __initdata = { "ref_io", "ref_xtal", };
-static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
+static const char *const sel_pll[]  __initconst = { "pll", "ref_xtal", };
+static const char *const sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
+static const char *const sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
+static const char *const sel_io[]   __initconst = { "ref_io", "ref_xtal", };
+static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
+static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
 
 enum imx23_clk {
 	ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index b1be374..a686708 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -125,15 +125,15 @@
 	writel_relaxed(val, FRAC0);
 }
 
-static const char *sel_cpu[]  __initdata = { "ref_cpu", "ref_xtal", };
-static const char *sel_io0[]  __initdata = { "ref_io0", "ref_xtal", };
-static const char *sel_io1[]  __initdata = { "ref_io1", "ref_xtal", };
-static const char *sel_pix[]  __initdata = { "ref_pix", "ref_xtal", };
-static const char *sel_gpmi[] __initdata = { "ref_gpmi", "ref_xtal", };
-static const char *sel_pll0[] __initdata = { "pll0", "ref_xtal", };
-static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
-static const char *ptp_sels[] __initdata = { "ref_xtal", "pll0", };
+static const char *const sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
+static const char *const sel_io0[]  __initconst = { "ref_io0", "ref_xtal", };
+static const char *const sel_io1[]  __initconst = { "ref_io1", "ref_xtal", };
+static const char *const sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
+static const char *const sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", };
+static const char *const sel_pll0[] __initconst = { "pll0", "ref_xtal", };
+static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
+static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
+static const char *const ptp_sels[] __initconst = { "ref_xtal", "pll0", };
 
 enum imx28_clk {
 	ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1,
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index ef10ad9..f07d821 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -49,7 +49,7 @@
 }
 
 static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parent_names, int num_parents)
+		u8 shift, u8 width, const char *const *parent_names, int num_parents)
 {
 	return clk_register_mux(NULL, name, parent_names, num_parents,
 				CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
diff --git a/drivers/clk/pistachio/clk-pll.c b/drivers/clk/pistachio/clk-pll.c
index de53756..e17dada 100644
--- a/drivers/clk/pistachio/clk-pll.c
+++ b/drivers/clk/pistachio/clk-pll.c
@@ -6,9 +6,12 @@
  * version 2, as published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/printk.h>
 #include <linux/slab.h>
 
 #include "clk.h"
@@ -50,6 +53,18 @@
 #define PLL_CTRL4			0x10
 #define PLL_FRAC_CTRL4_BYPASS		BIT(28)
 
+#define MIN_PFD				9600000UL
+#define MIN_VCO_LA			400000000UL
+#define MAX_VCO_LA			1600000000UL
+#define MIN_VCO_FRAC_INT		600000000UL
+#define MAX_VCO_FRAC_INT		1600000000UL
+#define MIN_VCO_FRAC_FRAC		600000000UL
+#define MAX_VCO_FRAC_FRAC		2400000000UL
+#define MIN_OUTPUT_LA			8000000UL
+#define MAX_OUTPUT_LA			1600000000UL
+#define MIN_OUTPUT_FRAC			12000000UL
+#define MAX_OUTPUT_FRAC			1600000000UL
+
 struct pistachio_clk_pll {
 	struct clk_hw hw;
 	void __iomem *base;
@@ -67,6 +82,12 @@
 	writel(val, pll->base + reg);
 }
 
+static inline void pll_lock(struct pistachio_clk_pll *pll)
+{
+	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
+		cpu_relax();
+}
+
 static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
 {
 	dividend += divisor / 2;
@@ -124,6 +145,8 @@
 	val &= ~PLL_FRAC_CTRL4_BYPASS;
 	pll_writel(pll, val, PLL_CTRL4);
 
+	pll_lock(pll);
+
 	return 0;
 }
 
@@ -149,16 +172,29 @@
 {
 	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 	struct pistachio_pll_rate_table *params;
-	bool was_enabled;
-	u32 val;
+	int enabled = pll_gf40lp_frac_is_enabled(hw);
+	u32 val, vco, old_postdiv1, old_postdiv2;
+	const char *name = __clk_get_name(hw->clk);
 
-	params = pll_get_params(pll, parent_rate, rate);
-	if (!params)
+	if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
 		return -EINVAL;
 
-	was_enabled = pll_gf40lp_frac_is_enabled(hw);
-	if (!was_enabled)
-		pll_gf40lp_frac_enable(hw);
+	params = pll_get_params(pll, parent_rate, rate);
+	if (!params || !params->refdiv)
+		return -EINVAL;
+
+	vco = params->fref * params->fbdiv / params->refdiv;
+	if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
+		pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+			MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
+
+	val = params->fref / params->refdiv;
+	if (val < MIN_PFD)
+		pr_warn("%s: PFD %u is too low (min %lu)\n",
+			name, val, MIN_PFD);
+	if (val > vco / 16)
+		pr_warn("%s: PFD %u is too high (max %u)\n",
+			name, val, vco / 16);
 
 	val = pll_readl(pll, PLL_CTRL1);
 	val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
@@ -168,6 +204,19 @@
 	pll_writel(pll, val, PLL_CTRL1);
 
 	val = pll_readl(pll, PLL_CTRL2);
+
+	old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
+		       PLL_FRAC_CTRL2_POSTDIV1_MASK;
+	old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
+		       PLL_FRAC_CTRL2_POSTDIV2_MASK;
+	if (enabled &&
+	    (params->postdiv1 != old_postdiv1 ||
+	     params->postdiv2 != old_postdiv2))
+		pr_warn("%s: changing postdiv while PLL is enabled\n", name);
+
+	if (params->postdiv2 > params->postdiv1)
+		pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
+
 	val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
 		 (PLL_FRAC_CTRL2_POSTDIV1_MASK <<
 		  PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
@@ -178,11 +227,8 @@
 		(params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
 	pll_writel(pll, val, PLL_CTRL2);
 
-	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
-		cpu_relax();
-
-	if (!was_enabled)
-		pll_gf40lp_frac_disable(hw);
+	if (enabled)
+		pll_lock(pll);
 
 	return 0;
 }
@@ -241,6 +287,8 @@
 	val &= ~PLL_INT_CTRL2_BYPASS;
 	pll_writel(pll, val, PLL_CTRL2);
 
+	pll_lock(pll);
+
 	return 0;
 }
 
@@ -266,18 +314,44 @@
 {
 	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 	struct pistachio_pll_rate_table *params;
-	bool was_enabled;
-	u32 val;
+	int enabled = pll_gf40lp_laint_is_enabled(hw);
+	u32 val, vco, old_postdiv1, old_postdiv2;
+	const char *name = __clk_get_name(hw->clk);
 
-	params = pll_get_params(pll, parent_rate, rate);
-	if (!params)
+	if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
 		return -EINVAL;
 
-	was_enabled = pll_gf40lp_laint_is_enabled(hw);
-	if (!was_enabled)
-		pll_gf40lp_laint_enable(hw);
+	params = pll_get_params(pll, parent_rate, rate);
+	if (!params || !params->refdiv)
+		return -EINVAL;
+
+	vco = params->fref * params->fbdiv / params->refdiv;
+	if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
+		pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+			MIN_VCO_LA, MAX_VCO_LA);
+
+	val = params->fref / params->refdiv;
+	if (val < MIN_PFD)
+		pr_warn("%s: PFD %u is too low (min %lu)\n",
+			name, val, MIN_PFD);
+	if (val > vco / 16)
+		pr_warn("%s: PFD %u is too high (max %u)\n",
+			name, val, vco / 16);
 
 	val = pll_readl(pll, PLL_CTRL1);
+
+	old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
+		       PLL_INT_CTRL1_POSTDIV1_MASK;
+	old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
+		       PLL_INT_CTRL1_POSTDIV2_MASK;
+	if (enabled &&
+	    (params->postdiv1 != old_postdiv1 ||
+	     params->postdiv2 != old_postdiv2))
+		pr_warn("%s: changing postdiv while PLL is enabled\n", name);
+
+	if (params->postdiv2 > params->postdiv1)
+		pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
+
 	val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 		 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
 		 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
@@ -288,11 +362,8 @@
 		(params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
 	pll_writel(pll, val, PLL_CTRL1);
 
-	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
-		cpu_relax();
-
-	if (!was_enabled)
-		pll_gf40lp_laint_disable(hw);
+	if (enabled)
+		pll_lock(pll);
 
 	return 0;
 }
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
index b04c5b9..d1de805 100644
--- a/drivers/clk/pxa/clk-pxa.h
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -14,7 +14,7 @@
 #define _CLK_PXA_
 
 #define PARENTS(name) \
-	static const char *name ## _parents[] __initdata
+	static const char *const name ## _parents[] __initconst
 #define MUX_RO_RATE_RO_OPS(name, clk_name)			\
 	static struct clk_hw name ## _mux_hw;			\
 	static struct clk_hw name ## _rate_hw;			\
@@ -72,7 +72,7 @@
 	const char *name;
 	const char *dev_id;
 	const char *con_id;
-	const char **parent_names;
+	const char * const *parent_names;
 	struct clk_fixed_factor lp;
 	struct clk_fixed_factor hp;
 	struct clk_gate gate;
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 8539c4f..fb7721b 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -231,7 +231,7 @@
 }
 
 struct clk *rockchip_clk_register_cpuclk(const char *name,
-			const char **parent_names, u8 num_parents,
+			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates, void __iomem *reg_base, spinlock_t *lock)
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index c842e3b..e9f8df32 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -120,7 +120,7 @@
 };
 
 struct clk *rockchip_clk_register_mmc(const char *name,
-				const char **parent_names, u8 num_parents,
+				const char *const *parent_names, u8 num_parents,
 				void __iomem *reg, int shift)
 {
 	struct clk_init_data init;
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f8d3baf..7602726 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -329,10 +329,10 @@
  */
 
 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
-		const char *name, const char **parent_names, u8 num_parents,
-		void __iomem *base, int con_offset, int grf_lock_offset,
-		int lock_shift, int mode_offset, int mode_shift,
-		struct rockchip_pll_rate_table *rate_table,
+		const char *name, const char *const *parent_names,
+		u8 num_parents, void __iomem *base, int con_offset,
+		int grf_lock_offset, int lock_shift, int mode_offset,
+		int mode_shift, struct rockchip_pll_rate_table *rate_table,
 		u8 clk_pll_flags, spinlock_t *lock)
 {
 	const char *pll_parents[3];
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index 556ce04..e4f9d47 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -26,7 +26,7 @@
 	apll, cpll, dpll, gpll,
 };
 
-struct rockchip_pll_rate_table rk3188_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
 	RK3066_PLL_RATE(2208000000, 1, 92, 1),
 	RK3066_PLL_RATE(2184000000, 1, 91, 1),
 	RK3066_PLL_RATE(2160000000, 1, 90, 1),
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index d17eb45..4f817ed 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -27,7 +27,7 @@
 	apll, dpll, cpll, gpll, npll,
 };
 
-struct rockchip_pll_rate_table rk3288_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
 	RK3066_PLL_RATE(2208000000, 1, 92, 1),
 	RK3066_PLL_RATE(2184000000, 1, 91, 1),
 	RK3066_PLL_RATE(2160000000, 1, 90, 1),
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index edb5d48..052b94d 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -39,7 +39,7 @@
  * sometimes without one of those components.
  */
 static struct clk *rockchip_clk_register_branch(const char *name,
-		const char **parent_names, u8 num_parents, void __iomem *base,
+		const char *const *parent_names, u8 num_parents, void __iomem *base,
 		int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
 		u8 div_shift, u8 div_width, u8 div_flags,
 		struct clk_div_table *div_table, int gate_offset,
@@ -103,8 +103,8 @@
 }
 
 static struct clk *rockchip_clk_register_frac_branch(const char *name,
-		const char **parent_names, u8 num_parents, void __iomem *base,
-		int muxdiv_offset, u8 div_flags,
+		const char *const *parent_names, u8 num_parents,
+		void __iomem *base, int muxdiv_offset, u8 div_flags,
 		int gate_offset, u8 gate_shift, u8 gate_flags,
 		unsigned long flags, spinlock_t *lock)
 {
@@ -297,7 +297,7 @@
 }
 
 void __init rockchip_clk_register_armclk(unsigned int lookup_id,
-			const char *name, const char **parent_names,
+			const char *name, const char *const *parent_names,
 			u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index e63cafe..6b09267 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -108,7 +108,7 @@
 struct rockchip_pll_clock {
 	unsigned int		id;
 	const char		*name;
-	const char		**parent_names;
+	const char		*const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 	int			con_offset;
@@ -140,10 +140,10 @@
 	}
 
 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
-		const char *name, const char **parent_names, u8 num_parents,
-		void __iomem *base, int con_offset, int grf_lock_offset,
-		int lock_shift, int reg_mode, int mode_shift,
-		struct rockchip_pll_rate_table *rate_table,
+		const char *name, const char *const *parent_names,
+		u8 num_parents, void __iomem *base, int con_offset,
+		int grf_lock_offset, int lock_shift, int reg_mode,
+		int mode_shift, struct rockchip_pll_rate_table *rate_table,
 		u8 clk_pll_flags, spinlock_t *lock);
 
 struct rockchip_cpuclk_clksel {
@@ -173,16 +173,16 @@
 };
 
 struct clk *rockchip_clk_register_cpuclk(const char *name,
-			const char **parent_names, u8 num_parents,
+			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates, void __iomem *reg_base, spinlock_t *lock);
 
 struct clk *rockchip_clk_register_mmc(const char *name,
-				const char **parent_names, u8 num_parents,
+				const char *const *parent_names, u8 num_parents,
 				void __iomem *reg, int shift);
 
-#define PNAME(x) static const char *x[] __initdata
+#define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
 	branch_composite,
@@ -197,7 +197,7 @@
 	unsigned int			id;
 	enum rockchip_clk_branch_type	branch_type;
 	const char			*name;
-	const char			**parent_names;
+	const char			*const *parent_names;
 	u8				num_parents;
 	unsigned long			flags;
 	int				muxdiv_offset;
@@ -403,7 +403,7 @@
 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
 				unsigned int nr_pll, int grf_lock_offset);
 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
-			const char **parent_names, u8 num_parents,
+			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates);
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index e2e5193..06f96eb 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -94,7 +94,7 @@
 PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
 PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
 
-struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static struct samsung_mux_clock aud_mux_clks[] __initdata = {
 	MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
 			MUX_SEL_AUD, 0, 1),
 	MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
@@ -103,7 +103,7 @@
 			MUX_SEL_AUD, 8, 1),
 };
 
-struct samsung_div_clock aud_div_clks[] __initdata = {
+static struct samsung_div_clock aud_div_clks[] __initdata = {
 	DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
 			DIV_AUD0, 0, 4),
 
@@ -115,7 +115,7 @@
 			DIV_AUD1, 12, 4),
 };
 
-struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static struct samsung_gate_clock aud_gate_clks[] __initdata = {
 	GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
 			EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
 	GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
@@ -135,7 +135,7 @@
 
 static void __init exynos5260_clk_aud_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = aud_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks);
@@ -203,7 +203,7 @@
 PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
 			"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static struct samsung_mux_clock disp_mux_clks[] __initdata = {
 	MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
 			mout_aclk_disp_333_user_p,
 			MUX_SEL_DISP0, 0, 1),
@@ -272,7 +272,7 @@
 			MUX_SEL_DISP4, 4, 2),
 };
 
-struct samsung_div_clock disp_div_clks[] __initdata = {
+static struct samsung_div_clock disp_div_clks[] __initdata = {
 	DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
 			"mout_aclk_disp_222_user",
 			DIV_DISP, 8, 4),
@@ -285,7 +285,7 @@
 			DIV_DISP, 16, 4),
 };
 
-struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static struct samsung_gate_clock disp_gate_clks[] __initdata = {
 	GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
 			"mout_phyclk_hdmi_phy_pixel_clko_user",
 			EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
@@ -325,7 +325,7 @@
 
 static void __init exynos5260_clk_disp_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = disp_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks);
@@ -363,13 +363,13 @@
 PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
 PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
 
-struct samsung_mux_clock egl_mux_clks[] __initdata = {
+static struct samsung_mux_clock egl_mux_clks[] __initdata = {
 	MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
 			MUX_SEL_EGL, 4, 1),
 	MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
 };
 
-struct samsung_div_clock egl_div_clks[] __initdata = {
+static struct samsung_div_clock egl_div_clks[] __initdata = {
 	DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
 	DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
 	DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
@@ -389,7 +389,7 @@
 
 static void __init exynos5260_clk_egl_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = egl_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(egl_pll_clks);
@@ -433,7 +433,7 @@
 PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
 			"phyclk_usbdrd30_udrd30_phyclock"};
 
-struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
 	MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
 			"mout_phyclk_usbdrd30_phyclock_user",
 			mout_phyclk_usbdrd30_phyclock_user_p,
@@ -456,7 +456,7 @@
 			MUX_SEL_FSYS1, 16, 1),
 };
 
-struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
 	GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
 			"mout_phyclk_usbdrd30_phyclock_user",
 			EN_SCLK_FSYS, 1, 0, 0),
@@ -491,7 +491,7 @@
 
 static void __init exynos5260_clk_fsys_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = fsys_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks);
@@ -537,18 +537,18 @@
 
 PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
 
-struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
 	MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
 			mout_aclk_g2d_333_user_p,
 			MUX_SEL_G2D, 0, 1),
 };
 
-struct samsung_div_clock g2d_div_clks[] __initdata = {
+static struct samsung_div_clock g2d_div_clks[] __initdata = {
 	DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
 			DIV_G2D, 0, 3),
 };
 
-struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
 	GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
 			EN_IP_G2D, 4, 0, 0),
 	GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
@@ -580,7 +580,7 @@
 
 static void __init exynos5260_clk_g2d_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = g2d_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks);
@@ -617,17 +617,17 @@
 
 PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
 
-struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
 	MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
 			MUX_SEL_G3D, 0, 1),
 };
 
-struct samsung_div_clock g3d_div_clks[] __initdata = {
+static struct samsung_div_clock g3d_div_clks[] __initdata = {
 	DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
 	DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
 };
 
-struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
 	GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
 	GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
 			EN_IP_G3D, 3, 0, 0),
@@ -641,7 +641,7 @@
 
 static void __init exynos5260_clk_g3d_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = g3d_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(g3d_pll_clks);
@@ -694,7 +694,7 @@
 PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
 
-struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
 	MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
 			mout_aclk_gscl_333_user_p,
 			MUX_SEL_GSCL, 0, 1),
@@ -708,7 +708,7 @@
 			MUX_SEL_GSCL, 24, 1),
 };
 
-struct samsung_div_clock gscl_div_clks[] __initdata = {
+static struct samsung_div_clock gscl_div_clks[] __initdata = {
 	DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
 			"mout_aclk_m2m_400_user",
 			DIV_GSCL, 0, 3),
@@ -717,7 +717,7 @@
 			DIV_GSCL, 4, 3),
 };
 
-struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
 	GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
 			EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
 	GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
@@ -776,7 +776,7 @@
 
 static void __init exynos5260_clk_gscl_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = gscl_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks);
@@ -813,14 +813,14 @@
 PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
 PNAME(mout_isp_266_user_p)	 = {"fin_pll", "dout_aclk_isp1_266"};
 
-struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static struct samsung_mux_clock isp_mux_clks[] __initdata = {
 	MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
 			MUX_SEL_ISP0, 0, 1),
 	MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
 			MUX_SEL_ISP0, 4, 1),
 };
 
-struct samsung_div_clock isp_div_clks[] __initdata = {
+static struct samsung_div_clock isp_div_clks[] __initdata = {
 	DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
 			DIV_ISP, 0, 3),
 	DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
@@ -832,7 +832,7 @@
 	DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
 };
 
-struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static struct samsung_gate_clock isp_gate_clks[] __initdata = {
 	GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
 			EN_IP_ISP0, 15, 0, 0),
 
@@ -895,7 +895,7 @@
 
 static void __init exynos5260_clk_isp_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = isp_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks);
@@ -934,13 +934,13 @@
 PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
 PNAME(mout_kfc_p)	 = {"mout_kfc_pll", "dout_media_pll"};
 
-struct samsung_mux_clock kfc_mux_clks[] __initdata = {
+static struct samsung_mux_clock kfc_mux_clks[] __initdata = {
 	MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
 			MUX_SEL_KFC0, 0, 1),
 	MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
 };
 
-struct samsung_div_clock kfc_div_clks[] __initdata = {
+static struct samsung_div_clock kfc_div_clks[] __initdata = {
 	DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
 	DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
 	DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
@@ -959,7 +959,7 @@
 
 static void __init exynos5260_clk_kfc_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = kfc_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(kfc_pll_clks);
@@ -993,18 +993,18 @@
 
 PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
 
-struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
 	MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
 			mout_aclk_mfc_333_user_p,
 			MUX_SEL_MFC, 0, 1),
 };
 
-struct samsung_div_clock mfc_div_clks[] __initdata = {
+static struct samsung_div_clock mfc_div_clks[] __initdata = {
 	DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
 			DIV_MFC, 0, 3),
 };
 
-struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
 	GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
 			EN_IP_MFC, 1, 0, 0),
 	GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
@@ -1015,7 +1015,7 @@
 
 static void __init exynos5260_clk_mfc_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = mfc_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks);
@@ -1078,7 +1078,7 @@
 PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
 PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
 
-struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static struct samsung_mux_clock mif_mux_clks[] __initdata = {
 	MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
 			MUX_SEL_MIF, 0, 1),
 	MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
@@ -1095,7 +1095,7 @@
 			MUX_SEL_MIF, 24, 1),
 };
 
-struct samsung_div_clock mif_div_clks[] __initdata = {
+static struct samsung_div_clock mif_div_clks[] __initdata = {
 	DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
 			DIV_MIF, 0, 3),
 	DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
@@ -1114,7 +1114,7 @@
 			DIV_MIF, 28, 4),
 };
 
-struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static struct samsung_gate_clock mif_gate_clks[] __initdata = {
 	GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
 			EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
 	GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
@@ -1162,7 +1162,7 @@
 
 static void __init exynos5260_clk_mif_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = mif_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(mif_pll_clks);
@@ -1221,7 +1221,7 @@
 PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
 			"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-struct samsung_mux_clock peri_mux_clks[] __initdata = {
+static struct samsung_mux_clock peri_mux_clks[] __initdata = {
 	MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
 			MUX_SEL_PERI1, 4, 2),
 	MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
@@ -1230,12 +1230,12 @@
 			MUX_SEL_PERI1, 20, 2),
 };
 
-struct samsung_div_clock peri_div_clks[] __initdata = {
+static struct samsung_div_clock peri_div_clks[] __initdata = {
 	DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
 	DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
 };
 
-struct samsung_gate_clock peri_gate_clks[] __initdata = {
+static struct samsung_gate_clock peri_gate_clks[] __initdata = {
 	GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
 			CLK_SET_RATE_PARENT, 0),
 	GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
@@ -1370,7 +1370,7 @@
 
 static void __init exynos5260_clk_peri_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = peri_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks);
@@ -1432,7 +1432,7 @@
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
 	FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
 			CLK_IS_ROOT, 270000000),
 	FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
@@ -1519,7 +1519,7 @@
 PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
 			"mout_mediatop_pll_user"};
 
-struct samsung_mux_clock top_mux_clks[] __initdata = {
+static struct samsung_mux_clock top_mux_clks[] __initdata = {
 	MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
 			mout_mediatop_pll_user_p,
 			MUX_SEL_TOP_PLL0, 0, 1),
@@ -1679,7 +1679,7 @@
 			MUX_SEL_TOP_GSCL, 20, 1),
 };
 
-struct samsung_div_clock top_div_clks[] __initdata = {
+static struct samsung_div_clock top_div_clks[] __initdata = {
 	DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
 			DIV_TOP_G2D_MFC, 0, 3),
 	DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
@@ -1800,7 +1800,7 @@
 
 };
 
-struct samsung_gate_clock top_gate_clks[] __initdata = {
+static struct samsung_gate_clock top_gate_clks[] __initdata = {
 	GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
 			"dout_sclk_fsys_mmc0_sdclkin_b",
 			EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
@@ -1826,7 +1826,7 @@
 
 static void __init exynos5260_clk_top_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = top_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(top_pll_clks);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index bea4a17..a1d731c 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -504,7 +504,7 @@
 	FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
 };
 
-struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
 	MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
 	MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
 	MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
@@ -553,7 +553,7 @@
 	MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
 };
 
-struct samsung_div_clock exynos5800_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
 	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3),
 
 	DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
@@ -569,14 +569,14 @@
 	DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
 };
 
-struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
 	GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
 				GATE_BUS_TOP, 24, 0, 0),
 	GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
 				GATE_BUS_TOP, 27, 0, 0),
 };
 
-struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
 	MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
 				TOP_SPARE2, 4, 1),
@@ -606,7 +606,7 @@
 	MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
 };
 
-struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
 	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
 			DIV_TOP0, 16, 3),
 };
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 9e04ae2..39c9564 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -835,6 +835,7 @@
 	MPHY_PLL_CON1,
 	MPHY_PLL_FREQ_DET,
 	MUX_SEL_CPIF0,
+	DIV_CPIF,
 	ENABLE_SCLK_CPIF,
 };
 
@@ -1389,7 +1390,7 @@
 
 	/* ENABLE_ACLK_MIF2 */
 	GATE(CLK_ACLK_MIFND_266, "aclk_mifnd_266", "div_aclk_mif_266",
-			ENABLE_ACLK_MIF2, 20, 0, 0),
+			ENABLE_ACLK_MIF2, 20, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_PPMU_DREX1S3, "aclk_ppmu_drex1s3", "div_aclk_drex1",
 			ENABLE_ACLK_MIF2, 17, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_PPMU_DREX1S1, "aclk_ppmu_drex1s1", "div_aclk_drex1",
@@ -1832,39 +1833,39 @@
 
 	/* ENABLE_PCLK_PERIS_SECURE_TZPC */
 	GATE(CLK_PCLK_TZPC12, "pclk_tzpc12", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 12, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 12, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC11, "pclk_tzpc11", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 11, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 11, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC10, "pclk_tzpc10", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 10, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 10, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC9, "pclk_tzpc9", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 9, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 9, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC8, "pclk_tzpc8", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 8, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 8, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC7, "pclk_tzpc7", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 7, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 7, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC6, "pclk_tzpc6", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 6, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 6, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC5, "pclk_tzpc5", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 5, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 5, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC4, "pclk_tzpc4", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 4, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 4, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC3, "pclk_tzpc3", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 3, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 3, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC2, "pclk_tzpc2", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 2, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 2, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC1, "pclk_tzpc1", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 1, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC0, "pclk_tzpc0", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 0, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF */
 	GATE(CLK_PCLK_SECKEY_APBIF, "pclk_seckey_apbif", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF */
 	GATE(CLK_PCLK_CHIPID_APBIF, "pclk_chipid_apbif", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_PCLK_PERIS_SECURE_TOPRTC */
 	GATE(CLK_PCLK_TOPRTC, "pclk_toprtc", "aclk_peris_66",
@@ -1895,11 +1896,11 @@
 
 	/* ENABLE_SCLK_PERIS_SECURE_SECKEY */
 	GATE(CLK_SCLK_SECKEY, "sclk_seckey", "oscclk_efuse_common",
-			ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, 0, 0),
+			ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_SCLK_PERIS_SECURE_CHIPID */
 	GATE(CLK_SCLK_CHIPID, "sclk_chipid", "oscclk_efuse_common",
-			ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0),
+			ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_SCLK_PERIS_SECURE_TOPRTC */
 	GATE(CLK_SCLK_TOPRTC, "sclk_toprtc", "oscclk_efuse_common",
@@ -3286,10 +3287,10 @@
 
 static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
 	/* MUX_SEL_G3D */
-	MUX(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
-			MUX_SEL_G3D, 8, 1),
-	MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
-			MUX_SEL_G3D, 0, 1),
+	MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
+			MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0),
+	MUX_F(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
+			MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock g3d_div_clks[] __initdata = {
@@ -3298,8 +3299,8 @@
 			8, 2),
 	DIV(CLK_DIV_PCLK_G3D, "div_pclk_g3d", "div_aclk_g3d", DIV_G3D,
 			4, 3),
-	DIV(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
-			0, 3),
+	DIV_F(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
+			0, 3, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
@@ -3309,9 +3310,9 @@
 	GATE(CLK_ACLK_BTS_G3D0, "aclk_bts_g3d0", "div_aclk_g3d",
 			ENABLE_ACLK_G3D, 6, 0, 0),
 	GATE(CLK_ACLK_ASYNCAPBS_G3D, "aclk_asyncapbs_g3d", "div_pclk_g3d",
-			ENABLE_ACLK_G3D, 5, 0, 0),
+			ENABLE_ACLK_G3D, 5, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_ASYNCAPBM_G3D, "aclk_asyncapbm_g3d", "div_aclk_g3d",
-			ENABLE_ACLK_G3D, 4, 0, 0),
+			ENABLE_ACLK_G3D, 4, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_AHB2APB_G3DP, "aclk_ahb2apb_g3dp", "div_pclk_g3d",
 			ENABLE_ACLK_G3D, 3, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_G3DNP_150, "aclk_g3dnp_150", "div_pclk_g3d",
@@ -3319,7 +3320,7 @@
 	GATE(CLK_ACLK_G3DND_600, "aclk_g3dnd_600", "div_aclk_g3d",
 			ENABLE_ACLK_G3D, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_G3D, "aclk_g3d", "div_aclk_g3d",
-			ENABLE_ACLK_G3D, 0, 0, 0),
+			ENABLE_ACLK_G3D, 0, CLK_SET_RATE_PARENT, 0),
 
 	/* ENABLE_PCLK_G3D */
 	GATE(CLK_PCLK_BTS_G3D1, "pclk_bts_g3d1", "div_pclk_g3d",
@@ -3582,7 +3583,7 @@
 static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
 	/* MUX_SEL_APOLLO0 */
 	MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
-			MUX_SEL_APOLLO0, 0, 1, 0, CLK_MUX_READ_ONLY),
+			MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
 
 	/* MUX_SEL_APOLLO1 */
 	MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
@@ -3590,7 +3591,7 @@
 
 	/* MUX_SEL_APOLLO2 */
 	MUX_F(CLK_MOUT_APOLLO, "mout_apollo", mout_apollo_p, MUX_SEL_APOLLO2,
-			0, 1, 0, CLK_MUX_READ_ONLY),
+			0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock apollo_div_clks[] __initdata = {
@@ -3611,11 +3612,9 @@
 			DIV_APOLLO0, 8, 3, CLK_GET_RATE_NOCACHE,
 			CLK_DIVIDER_READ_ONLY),
 	DIV_F(CLK_DIV_APOLLO2, "div_apollo2", "div_apollo1",
-			DIV_APOLLO0, 4, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_APOLLO0, 4, 3, CLK_SET_RATE_PARENT, 0),
 	DIV_F(CLK_DIV_APOLLO1, "div_apollo1", "mout_apollo",
-			DIV_APOLLO0, 0, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_APOLLO0, 0, 3, CLK_SET_RATE_PARENT, 0),
 
 	/* DIV_APOLLO1 */
 	DIV_F(CLK_DIV_SCLK_HPM_APOLLO, "div_sclk_hpm_apollo", "mout_apollo",
@@ -3666,7 +3665,8 @@
 	GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
 			ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2",
-			ENABLE_SCLK_APOLLO, 0, CLK_IGNORE_UNUSED, 0),
+			ENABLE_SCLK_APOLLO, 0,
+			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_cmu_info apollo_cmu_info __initdata = {
@@ -3775,7 +3775,7 @@
 static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
 	/* MUX_SEL_ATLAS0 */
 	MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
-			MUX_SEL_ATLAS0, 0, 1, 0, CLK_MUX_READ_ONLY),
+			MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
 
 	/* MUX_SEL_ATLAS1 */
 	MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
@@ -3783,7 +3783,7 @@
 
 	/* MUX_SEL_ATLAS2 */
 	MUX_F(CLK_MOUT_ATLAS, "mout_atlas", mout_atlas_p, MUX_SEL_ATLAS2,
-			0, 1, 0, CLK_MUX_READ_ONLY),
+			0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock atlas_div_clks[] __initdata = {
@@ -3804,11 +3804,9 @@
 			DIV_ATLAS0, 8, 3, CLK_GET_RATE_NOCACHE,
 			CLK_DIVIDER_READ_ONLY),
 	DIV_F(CLK_DIV_ATLAS2, "div_atlas2", "div_atlas1",
-			DIV_ATLAS0, 4, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_ATLAS0, 4, 3, CLK_SET_RATE_PARENT, 0),
 	DIV_F(CLK_DIV_ATLAS1, "div_atlas1", "mout_atlas",
-			DIV_ATLAS0, 0, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_ATLAS0, 0, 3, CLK_SET_RATE_PARENT, 0),
 
 	/* DIV_ATLAS1 */
 	DIV_F(CLK_DIV_SCLK_HPM_ATLAS, "div_sclk_hpm_atlas", "mout_atlas",
@@ -3885,7 +3883,8 @@
 	GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
 			ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
-			ENABLE_SCLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
+			ENABLE_SCLK_ATLAS, 0,
+			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_cmu_info atlas_cmu_info __initdata = {
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 9d70e5c..bebc61b 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1156,7 +1156,7 @@
 };
 
 static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
-				struct samsung_pll_clock *pll_clk,
+				const struct samsung_pll_clock *pll_clk,
 				void __iomem *base)
 {
 	struct samsung_clk_pll *pll;
@@ -1303,7 +1303,7 @@
 }
 
 void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
-			struct samsung_pll_clock *pll_list,
+			const struct samsung_pll_clock *pll_list,
 			unsigned int nr_pll, void __iomem *base)
 {
 	int cnt;
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index f4f29ed6..e56df50 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -81,13 +81,13 @@
 	return ret;
 }
 
-const struct clk_ops s3c24xx_clkout_ops = {
+static const struct clk_ops s3c24xx_clkout_ops = {
 	.get_parent = s3c24xx_clkout_get_parent,
 	.set_parent = s3c24xx_clkout_set_parent,
 	.determine_rate = __clk_mux_determine_rate,
 };
 
-struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
+static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents,
 		u8 shift, u32 mask)
 {
@@ -404,7 +404,7 @@
 	},
 };
 
-static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
+static const struct platform_device_id s3c24xx_dclk_driver_ids[] = {
 	{
 		.name		= "s3c2410-dclk",
 		.driver_data	= (kernel_ulong_t)&dclk_variants[S3C2410],
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index e668e47..cf7e8fa 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -169,44 +169,44 @@
 #endif
 
 /* Mux parent lists. */
-static const char *fin_pll_p[] __initdata = {
+static const char *const fin_pll_p[] __initconst = {
 	"xxti",
 	"xusbxti"
 };
 
-static const char *mout_apll_p[] __initdata = {
+static const char *const mout_apll_p[] __initconst = {
 	"fin_pll",
 	"fout_apll"
 };
 
-static const char *mout_mpll_p[] __initdata = {
+static const char *const mout_mpll_p[] __initconst = {
 	"fin_pll",
 	"fout_mpll"
 };
 
-static const char *mout_epll_p[] __initdata = {
+static const char *const mout_epll_p[] __initconst = {
 	"fin_pll",
 	"fout_epll"
 };
 
-static const char *mout_vpllsrc_p[] __initdata = {
+static const char *const mout_vpllsrc_p[] __initconst = {
 	"fin_pll",
 	"sclk_hdmi27m"
 };
 
-static const char *mout_vpll_p[] __initdata = {
+static const char *const mout_vpll_p[] __initconst = {
 	"mout_vpllsrc",
 	"fout_vpll"
 };
 
-static const char *mout_group1_p[] __initdata = {
+static const char *const mout_group1_p[] __initconst = {
 	"dout_a2m",
 	"mout_mpll",
 	"mout_epll",
 	"mout_vpll"
 };
 
-static const char *mout_group2_p[] __initdata = {
+static const char *const mout_group2_p[] __initconst = {
 	"xxti",
 	"xusbxti",
 	"sclk_hdmi27m",
@@ -218,7 +218,7 @@
 	"mout_vpll",
 };
 
-static const char *mout_audio0_p[] __initdata = {
+static const char *const mout_audio0_p[] __initconst = {
 	"xxti",
 	"pcmcdclk0",
 	"sclk_hdmi27m",
@@ -230,7 +230,7 @@
 	"mout_vpll",
 };
 
-static const char *mout_audio1_p[] __initdata = {
+static const char *const mout_audio1_p[] __initconst = {
 	"i2scdclk1",
 	"pcmcdclk1",
 	"sclk_hdmi27m",
@@ -242,7 +242,7 @@
 	"mout_vpll",
 };
 
-static const char *mout_audio2_p[] __initdata = {
+static const char *const mout_audio2_p[] __initconst = {
 	"i2scdclk2",
 	"pcmcdclk2",
 	"sclk_hdmi27m",
@@ -254,63 +254,63 @@
 	"mout_vpll",
 };
 
-static const char *mout_spdif_p[] __initdata = {
+static const char *const mout_spdif_p[] __initconst = {
 	"dout_audio0",
 	"dout_audio1",
 	"dout_audio3",
 };
 
-static const char *mout_group3_p[] __initdata = {
+static const char *const mout_group3_p[] __initconst = {
 	"mout_apll",
 	"mout_mpll"
 };
 
-static const char *mout_group4_p[] __initdata = {
+static const char *const mout_group4_p[] __initconst = {
 	"mout_mpll",
 	"dout_a2m"
 };
 
-static const char *mout_flash_p[] __initdata = {
+static const char *const mout_flash_p[] __initconst = {
 	"dout_hclkd",
 	"dout_hclkp"
 };
 
-static const char *mout_dac_p[] __initdata = {
+static const char *const mout_dac_p[] __initconst = {
 	"mout_vpll",
 	"sclk_hdmiphy"
 };
 
-static const char *mout_hdmi_p[] __initdata = {
+static const char *const mout_hdmi_p[] __initconst = {
 	"sclk_hdmiphy",
 	"dout_tblk"
 };
 
-static const char *mout_mixer_p[] __initdata = {
+static const char *const mout_mixer_p[] __initconst = {
 	"mout_dac",
 	"mout_hdmi"
 };
 
-static const char *mout_vpll_6442_p[] __initdata = {
+static const char *const mout_vpll_6442_p[] __initconst = {
 	"fin_pll",
 	"fout_vpll"
 };
 
-static const char *mout_mixer_6442_p[] __initdata = {
+static const char *const mout_mixer_6442_p[] __initconst = {
 	"mout_vpll",
 	"dout_mixer"
 };
 
-static const char *mout_d0sync_6442_p[] __initdata = {
+static const char *const mout_d0sync_6442_p[] __initconst = {
 	"mout_dsys",
 	"div_apll"
 };
 
-static const char *mout_d1sync_6442_p[] __initdata = {
+static const char *const mout_d1sync_6442_p[] __initconst = {
 	"mout_psys",
 	"div_apll"
 };
 
-static const char *mout_group2_6442_p[] __initdata = {
+static const char *const mout_group2_6442_p[] __initconst = {
 	"fin_pll",
 	"none",
 	"none",
@@ -322,7 +322,7 @@
 	"mout_vpll",
 };
 
-static const char *mout_audio0_6442_p[] __initdata = {
+static const char *const mout_audio0_6442_p[] __initconst = {
 	"fin_pll",
 	"pcmcdclk0",
 	"none",
@@ -334,7 +334,7 @@
 	"mout_vpll",
 };
 
-static const char *mout_audio1_6442_p[] __initdata = {
+static const char *const mout_audio1_6442_p[] __initconst = {
 	"i2scdclk1",
 	"pcmcdclk1",
 	"none",
@@ -347,7 +347,7 @@
 	"fin_pll",
 };
 
-static const char *mout_clksel_p[] __initdata = {
+static const char *const mout_clksel_p[] __initconst = {
 	"fout_apll_clkout",
 	"fout_mpll_clkout",
 	"fout_epll",
@@ -370,7 +370,7 @@
 	"div_dclk"
 };
 
-static const char *mout_clksel_6442_p[] __initdata = {
+static const char *const mout_clksel_6442_p[] __initconst = {
 	"fout_apll_clkout",
 	"fout_mpll_clkout",
 	"fout_epll",
@@ -393,7 +393,7 @@
 	"div_dclk"
 };
 
-static const char *mout_clkout_p[] __initdata = {
+static const char *const mout_clkout_p[] __initconst = {
 	"dout_clkout",
 	"none",
 	"xxti",
@@ -401,20 +401,20 @@
 };
 
 /* Common fixed factor clocks. */
-static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock ffactor_clks[] __initconst = {
 	FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
 	FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
 	FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
 };
 
 /* PLL input mux (fin_pll), which needs to be registered before PLLs. */
-static struct samsung_mux_clock early_mux_clks[] __initdata = {
+static const struct samsung_mux_clock early_mux_clks[] __initconst = {
 	MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
 					CLK_MUX_READ_ONLY, 0),
 };
 
 /* Common clock muxes. */
-static struct samsung_mux_clock mux_clks[] __initdata = {
+static const struct samsung_mux_clock mux_clks[] __initconst = {
 	MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
 	MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
 	MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
@@ -427,7 +427,7 @@
 };
 
 /* S5PV210-specific clock muxes. */
-static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
+static const struct samsung_mux_clock s5pv210_mux_clks[] __initconst = {
 	MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
 
 	MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
@@ -472,7 +472,7 @@
 };
 
 /* S5P6442-specific clock muxes. */
-static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
+static const struct samsung_mux_clock s5p6442_mux_clks[] __initconst = {
 	MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
 
 	MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
@@ -504,7 +504,7 @@
 };
 
 /* S5PV210-specific fixed rate clocks generated inside the SoC. */
-static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initconst = {
 	FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
 	FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
 	FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
@@ -512,12 +512,12 @@
 };
 
 /* S5P6442-specific fixed rate clocks generated inside the SoC. */
-static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initconst = {
 	FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
 };
 
 /* Common clock dividers. */
-static struct samsung_div_clock div_clks[] __initdata = {
+static const struct samsung_div_clock div_clks[] __initconst = {
 	DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
 	DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
 	DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
@@ -549,7 +549,7 @@
 };
 
 /* S5PV210-specific clock dividers. */
-static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
+static const struct samsung_div_clock s5pv210_div_clks[] __initconst = {
 	DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
 	DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
 	DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
@@ -578,7 +578,7 @@
 };
 
 /* S5P6442-specific clock dividers. */
-static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
+static const struct samsung_div_clock s5p6442_div_clks[] __initconst = {
 	DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
 	DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
 
@@ -586,7 +586,7 @@
 };
 
 /* Common clock gates. */
-static struct samsung_gate_clock gate_clks[] __initdata = {
+static const struct samsung_gate_clock gate_clks[] __initconst = {
 	GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
 	GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
 	GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
@@ -666,7 +666,7 @@
 };
 
 /* S5PV210-specific clock gates. */
-static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
+static const struct samsung_gate_clock s5pv210_gate_clks[] __initconst = {
 	GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
 	GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
 	GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
@@ -728,7 +728,7 @@
 };
 
 /* S5P6442-specific clock gates. */
-static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
+static const struct samsung_gate_clock s5p6442_gate_clks[] __initconst = {
 	GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
 	GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
 	GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
@@ -748,14 +748,14 @@
  * Clock aliases for legacy clkdev look-up.
  * NOTE: Needed only to support legacy board files.
  */
-static struct samsung_clock_alias s5pv210_aliases[] = {
+static const struct samsung_clock_alias s5pv210_aliases[] __initconst = {
 	ALIAS(DOUT_APLL, NULL, "armclk"),
 	ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
 	ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
 };
 
 /* S5PV210-specific PLLs. */
-static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
+static const struct samsung_pll_clock s5pv210_pll_clks[] __initconst = {
 	[apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
 						APLL_LOCK, APLL_CON0, NULL),
 	[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
@@ -767,7 +767,7 @@
 };
 
 /* S5P6442-specific PLLs. */
-static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
+static const struct samsung_pll_clock s5p6442_pll_clks[] __initconst = {
 	[apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
 						APLL_LOCK, APLL_CON0, NULL),
 	[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 9e1f88c..0117238 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -98,7 +98,7 @@
 
 /* register a list of aliases */
 void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
-				struct samsung_clock_alias *list,
+				const struct samsung_clock_alias *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -132,7 +132,8 @@
 
 /* register a list of fixed clocks */
 void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
-		struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
+		const struct samsung_fixed_rate_clock *list,
+		unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx, ret;
@@ -161,7 +162,7 @@
 
 /* register a list of fixed factor clocks */
 void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
-		struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
+		const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx;
@@ -181,7 +182,7 @@
 
 /* register a list of mux clocks */
 void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
-				struct samsung_mux_clock *list,
+				const struct samsung_mux_clock *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -213,7 +214,7 @@
 
 /* register a list of div clocks */
 void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
-				struct samsung_div_clock *list,
+				const struct samsung_div_clock *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -252,7 +253,7 @@
 
 /* register a list of gate clocks */
 void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
-				struct samsung_gate_clock *list,
+				const struct samsung_gate_clock *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -389,7 +390,7 @@
 
 	ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
 	if (!ctx) {
-		panic("%s: unable to alllocate ctx\n", __func__);
+		panic("%s: unable to allocate ctx\n", __func__);
 		return ctx;
 	}
 
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4c7538..b775fc2 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -121,7 +121,7 @@
 	unsigned int		id;
 	const char		*dev_name;
 	const char		*name;
-	const char		**parent_names;
+	const char		*const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 	unsigned long		offset;
@@ -368,28 +368,28 @@
 extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
 			struct clk *clk, unsigned int id);
 
-extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
-			struct samsung_clock_alias *list,
+extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
+			const struct samsung_clock_alias *list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_fixed_rate(
 			struct samsung_clk_provider *ctx,
-			struct samsung_fixed_rate_clock *clk_list,
+			const struct samsung_fixed_rate_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_fixed_factor(
 			struct samsung_clk_provider *ctx,
-			struct samsung_fixed_factor_clock *list,
+			const struct samsung_fixed_factor_clock *list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
-			struct samsung_mux_clock *clk_list,
+			const struct samsung_mux_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
-			struct samsung_div_clock *clk_list,
+			const struct samsung_div_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
-			struct samsung_gate_clock *clk_list,
+			const struct samsung_gate_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
-			struct samsung_pll_clock *pll_list,
+			const struct samsung_pll_clock *pll_list,
 			unsigned int nr_clk, void __iomem *base);
 
 extern struct samsung_clk_provider __init *samsung_cmu_register_one(
diff --git a/drivers/clk/shmobile/clk-emev2.c b/drivers/clk/shmobile/clk-emev2.c
index 6c7c929..5b60beb 100644
--- a/drivers/clk/shmobile/clk-emev2.c
+++ b/drivers/clk/shmobile/clk-emev2.c
@@ -34,7 +34,7 @@
 static DEFINE_SPINLOCK(lock);
 
 /* not pretty, but hey */
-void __iomem *smu_base;
+static void __iomem *smu_base;
 
 static void __init emev2_smu_write(unsigned long value, int offs)
 {
diff --git a/drivers/clk/sirf/Makefile b/drivers/clk/sirf/Makefile
index 36b8e20..09b4210 100644
--- a/drivers/clk/sirf/Makefile
+++ b/drivers/clk/sirf/Makefile
@@ -2,4 +2,4 @@
 # Makefile for sirf specific clk
 #
 
-obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o
+obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o clk-atlas7.o
diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c
new file mode 100644
index 0000000..db8ab69
--- /dev/null
+++ b/drivers/clk/sirf/clk-atlas7.c
@@ -0,0 +1,1632 @@
+/*
+ * Clock tree for CSR SiRFAtlas7
+ *
+ * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#define SIRFSOC_CLKC_MEMPLL_AB_FREQ          0x0000
+#define SIRFSOC_CLKC_MEMPLL_AB_SSC           0x0004
+#define SIRFSOC_CLKC_MEMPLL_AB_CTRL0         0x0008
+#define SIRFSOC_CLKC_MEMPLL_AB_CTRL1         0x000c
+#define SIRFSOC_CLKC_MEMPLL_AB_STATUS        0x0010
+#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_ADDR    0x0014
+#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_DATA    0x0018
+
+#define SIRFSOC_CLKC_CPUPLL_AB_FREQ          0x001c
+#define SIRFSOC_CLKC_CPUPLL_AB_SSC           0x0020
+#define SIRFSOC_CLKC_CPUPLL_AB_CTRL0         0x0024
+#define SIRFSOC_CLKC_CPUPLL_AB_CTRL1         0x0028
+#define SIRFSOC_CLKC_CPUPLL_AB_STATUS        0x002c
+
+#define SIRFSOC_CLKC_SYS0PLL_AB_FREQ         0x0030
+#define SIRFSOC_CLKC_SYS0PLL_AB_SSC          0x0034
+#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL0        0x0038
+#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL1        0x003c
+#define SIRFSOC_CLKC_SYS0PLL_AB_STATUS       0x0040
+
+#define SIRFSOC_CLKC_SYS1PLL_AB_FREQ         0x0044
+#define SIRFSOC_CLKC_SYS1PLL_AB_SSC          0x0048
+#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL0        0x004c
+#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL1        0x0050
+#define SIRFSOC_CLKC_SYS1PLL_AB_STATUS       0x0054
+
+#define SIRFSOC_CLKC_SYS2PLL_AB_FREQ         0x0058
+#define SIRFSOC_CLKC_SYS2PLL_AB_SSC          0x005c
+#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL0        0x0060
+#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL1        0x0064
+#define SIRFSOC_CLKC_SYS2PLL_AB_STATUS       0x0068
+
+#define SIRFSOC_CLKC_SYS3PLL_AB_FREQ         0x006c
+#define SIRFSOC_CLKC_SYS3PLL_AB_SSC          0x0070
+#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL0        0x0074
+#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL1        0x0078
+#define SIRFSOC_CLKC_SYS3PLL_AB_STATUS       0x007c
+
+#define SIRFSOC_ABPLL_CTRL0_SSEN     0x00001000
+#define SIRFSOC_ABPLL_CTRL0_BYPASS   0x00000010
+#define SIRFSOC_ABPLL_CTRL0_RESET    0x00000001
+
+#define SIRFSOC_CLKC_AUDIO_DTO_INC           0x0088
+#define SIRFSOC_CLKC_DISP0_DTO_INC           0x008c
+#define SIRFSOC_CLKC_DISP1_DTO_INC           0x0090
+
+#define SIRFSOC_CLKC_AUDIO_DTO_SRC           0x0094
+#define SIRFSOC_CLKC_AUDIO_DTO_ENA           0x0098
+#define SIRFSOC_CLKC_AUDIO_DTO_DROFF         0x009c
+
+#define SIRFSOC_CLKC_DISP0_DTO_SRC           0x00a0
+#define SIRFSOC_CLKC_DISP0_DTO_ENA           0x00a4
+#define SIRFSOC_CLKC_DISP0_DTO_DROFF         0x00a8
+
+#define SIRFSOC_CLKC_DISP1_DTO_SRC           0x00ac
+#define SIRFSOC_CLKC_DISP1_DTO_ENA           0x00b0
+#define SIRFSOC_CLKC_DISP1_DTO_DROFF         0x00b4
+
+#define SIRFSOC_CLKC_I2S_CLK_SEL             0x00b8
+#define SIRFSOC_CLKC_I2S_SEL_STAT            0x00bc
+
+#define SIRFSOC_CLKC_USBPHY_CLKDIV_CFG       0x00c0
+#define SIRFSOC_CLKC_USBPHY_CLKDIV_ENA       0x00c4
+#define SIRFSOC_CLKC_USBPHY_CLK_SEL          0x00c8
+#define SIRFSOC_CLKC_USBPHY_CLK_SEL_STAT     0x00cc
+
+#define SIRFSOC_CLKC_BTSS_CLKDIV_CFG         0x00d0
+#define SIRFSOC_CLKC_BTSS_CLKDIV_ENA         0x00d4
+#define SIRFSOC_CLKC_BTSS_CLK_SEL            0x00d8
+#define SIRFSOC_CLKC_BTSS_CLK_SEL_STAT       0x00dc
+
+#define SIRFSOC_CLKC_RGMII_CLKDIV_CFG        0x00e0
+#define SIRFSOC_CLKC_RGMII_CLKDIV_ENA        0x00e4
+#define SIRFSOC_CLKC_RGMII_CLK_SEL           0x00e8
+#define SIRFSOC_CLKC_RGMII_CLK_SEL_STAT      0x00ec
+
+#define SIRFSOC_CLKC_CPU_CLKDIV_CFG          0x00f0
+#define SIRFSOC_CLKC_CPU_CLKDIV_ENA          0x00f4
+#define SIRFSOC_CLKC_CPU_CLK_SEL             0x00f8
+#define SIRFSOC_CLKC_CPU_CLK_SEL_STAT        0x00fc
+
+#define SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG      0x0100
+#define SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA      0x0104
+#define SIRFSOC_CLKC_SDPHY01_CLK_SEL         0x0108
+#define SIRFSOC_CLKC_SDPHY01_CLK_SEL_STAT    0x010c
+
+#define SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG      0x0110
+#define SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA      0x0114
+#define SIRFSOC_CLKC_SDPHY23_CLK_SEL         0x0118
+#define SIRFSOC_CLKC_SDPHY23_CLK_SEL_STAT    0x011c
+
+#define SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG      0x0120
+#define SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA      0x0124
+#define SIRFSOC_CLKC_SDPHY45_CLK_SEL         0x0128
+#define SIRFSOC_CLKC_SDPHY45_CLK_SEL_STAT    0x012c
+
+#define SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG      0x0130
+#define SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA      0x0134
+#define SIRFSOC_CLKC_SDPHY67_CLK_SEL         0x0138
+#define SIRFSOC_CLKC_SDPHY67_CLK_SEL_STAT    0x013c
+
+#define SIRFSOC_CLKC_CAN_CLKDIV_CFG          0x0140
+#define SIRFSOC_CLKC_CAN_CLKDIV_ENA          0x0144
+#define SIRFSOC_CLKC_CAN_CLK_SEL             0x0148
+#define SIRFSOC_CLKC_CAN_CLK_SEL_STAT        0x014c
+
+#define SIRFSOC_CLKC_DEINT_CLKDIV_CFG        0x0150
+#define SIRFSOC_CLKC_DEINT_CLKDIV_ENA        0x0154
+#define SIRFSOC_CLKC_DEINT_CLK_SEL           0x0158
+#define SIRFSOC_CLKC_DEINT_CLK_SEL_STAT      0x015c
+
+#define SIRFSOC_CLKC_NAND_CLKDIV_CFG         0x0160
+#define SIRFSOC_CLKC_NAND_CLKDIV_ENA         0x0164
+#define SIRFSOC_CLKC_NAND_CLK_SEL            0x0168
+#define SIRFSOC_CLKC_NAND_CLK_SEL_STAT       0x016c
+
+#define SIRFSOC_CLKC_DISP0_CLKDIV_CFG        0x0170
+#define SIRFSOC_CLKC_DISP0_CLKDIV_ENA        0x0174
+#define SIRFSOC_CLKC_DISP0_CLK_SEL           0x0178
+#define SIRFSOC_CLKC_DISP0_CLK_SEL_STAT      0x017c
+
+#define SIRFSOC_CLKC_DISP1_CLKDIV_CFG        0x0180
+#define SIRFSOC_CLKC_DISP1_CLKDIV_ENA        0x0184
+#define SIRFSOC_CLKC_DISP1_CLK_SEL           0x0188
+#define SIRFSOC_CLKC_DISP1_CLK_SEL_STAT      0x018c
+
+#define SIRFSOC_CLKC_GPU_CLKDIV_CFG          0x0190
+#define SIRFSOC_CLKC_GPU_CLKDIV_ENA          0x0194
+#define SIRFSOC_CLKC_GPU_CLK_SEL             0x0198
+#define SIRFSOC_CLKC_GPU_CLK_SEL_STAT        0x019c
+
+#define SIRFSOC_CLKC_GNSS_CLKDIV_CFG         0x01a0
+#define SIRFSOC_CLKC_GNSS_CLKDIV_ENA         0x01a4
+#define SIRFSOC_CLKC_GNSS_CLK_SEL            0x01a8
+#define SIRFSOC_CLKC_GNSS_CLK_SEL_STAT       0x01ac
+
+#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG0     0x01b0
+#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG1     0x01b4
+#define SIRFSOC_CLKC_SHARED_DIVIDER_ENA      0x01b8
+
+#define SIRFSOC_CLKC_SYS_CLK_SEL             0x01bc
+#define SIRFSOC_CLKC_SYS_CLK_SEL_STAT        0x01c0
+#define SIRFSOC_CLKC_IO_CLK_SEL              0x01c4
+#define SIRFSOC_CLKC_IO_CLK_SEL_STAT         0x01c8
+#define SIRFSOC_CLKC_G2D_CLK_SEL             0x01cc
+#define SIRFSOC_CLKC_G2D_CLK_SEL_STAT        0x01d0
+#define SIRFSOC_CLKC_JPENC_CLK_SEL           0x01d4
+#define SIRFSOC_CLKC_JPENC_CLK_SEL_STAT      0x01d8
+#define SIRFSOC_CLKC_VDEC_CLK_SEL            0x01dc
+#define SIRFSOC_CLKC_VDEC_CLK_SEL_STAT       0x01e0
+#define SIRFSOC_CLKC_GMAC_CLK_SEL            0x01e4
+#define SIRFSOC_CLKC_GMAC_CLK_SEL_STAT       0x01e8
+#define SIRFSOC_CLKC_USB_CLK_SEL             0x01ec
+#define SIRFSOC_CLKC_USB_CLK_SEL_STAT        0x01f0
+#define SIRFSOC_CLKC_KAS_CLK_SEL             0x01f4
+#define SIRFSOC_CLKC_KAS_CLK_SEL_STAT        0x01f8
+#define SIRFSOC_CLKC_SEC_CLK_SEL             0x01fc
+#define SIRFSOC_CLKC_SEC_CLK_SEL_STAT        0x0200
+#define SIRFSOC_CLKC_SDR_CLK_SEL             0x0204
+#define SIRFSOC_CLKC_SDR_CLK_SEL_STAT        0x0208
+#define SIRFSOC_CLKC_VIP_CLK_SEL             0x020c
+#define SIRFSOC_CLKC_VIP_CLK_SEL_STAT        0x0210
+#define SIRFSOC_CLKC_NOCD_CLK_SEL            0x0214
+#define SIRFSOC_CLKC_NOCD_CLK_SEL_STAT       0x0218
+#define SIRFSOC_CLKC_NOCR_CLK_SEL            0x021c
+#define SIRFSOC_CLKC_NOCR_CLK_SEL_STAT       0x0220
+#define SIRFSOC_CLKC_TPIU_CLK_SEL            0x0224
+#define SIRFSOC_CLKC_TPIU_CLK_SEL_STAT       0x0228
+
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_SET        0x022c
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_CLR        0x0230
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_STAT       0x0234
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_SET        0x0238
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_CLR        0x023c
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_STAT       0x0240
+
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_SET        0x0244
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_CLR        0x0248
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_STAT       0x024c
+
+#define SIRFSOC_CLKC_RSTC_A7_SW_RST          0x0308
+
+#define SIRFSOC_CLKC_LEAF_CLK_EN1_SET        0x04a0
+#define SIRFSOC_CLKC_LEAF_CLK_EN2_SET        0x04b8
+#define SIRFSOC_CLKC_LEAF_CLK_EN3_SET        0x04d0
+#define SIRFSOC_CLKC_LEAF_CLK_EN4_SET        0x04e8
+#define SIRFSOC_CLKC_LEAF_CLK_EN5_SET        0x0500
+#define SIRFSOC_CLKC_LEAF_CLK_EN6_SET        0x0518
+#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET        0x0530
+#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET        0x0548
+
+
+static void __iomem *sirfsoc_clk_vbase;
+static struct clk_onecell_data clk_data;
+
+static const struct clk_div_table pll_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 8 },
+	{ .val = 4, .div = 16 },
+	{ .val = 5, .div = 32 },
+};
+
+struct clk_pll {
+	struct clk_hw hw;
+	u16 regofs;  /* register offset */
+};
+#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw)
+
+struct clk_dto {
+	struct clk_hw hw;
+	u16 inc_offset;  /* dto increment offset */
+	u16 src_offset;  /* dto src offset */
+};
+#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw)
+
+struct clk_unit {
+	struct clk_hw hw;
+	u16 regofs;
+	u16 bit;
+	spinlock_t *lock;
+};
+#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw)
+
+struct atlas7_div_init_data {
+	const char *div_name;
+	const char *parent_name;
+	const char *gate_name;
+	unsigned long flags;
+	u8 divider_flags;
+	u8 gate_flags;
+	u32 div_offset;
+	u8 shift;
+	u8 width;
+	u32 gate_offset;
+	u8 gate_bit;
+	spinlock_t *lock;
+};
+
+struct atlas7_mux_init_data {
+	const char *mux_name;
+	const char * const *parent_names;
+	u8 parent_num;
+	unsigned long flags;
+	u8 mux_flags;
+	u32 mux_offset;
+	u8 shift;
+	u8 width;
+};
+
+struct atlas7_unit_init_data {
+	u32 index;
+	const char *unit_name;
+	const char *parent_name;
+	unsigned long flags;
+	u32 regofs;
+	u8 bit;
+	spinlock_t *lock;
+};
+
+struct atlas7_reset_desc {
+	const char *name;
+	u32 clk_ofs;
+	u8  clk_bit;
+	u32 rst_ofs;
+	u8  rst_bit;
+	spinlock_t *lock;
+};
+
+static DEFINE_SPINLOCK(cpupll_ctrl1_lock);
+static DEFINE_SPINLOCK(mempll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys0pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys1pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys2pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys3pll_ctrl1_lock);
+static DEFINE_SPINLOCK(usbphy_div_lock);
+static DEFINE_SPINLOCK(btss_div_lock);
+static DEFINE_SPINLOCK(rgmii_div_lock);
+static DEFINE_SPINLOCK(cpu_div_lock);
+static DEFINE_SPINLOCK(sdphy01_div_lock);
+static DEFINE_SPINLOCK(sdphy23_div_lock);
+static DEFINE_SPINLOCK(sdphy45_div_lock);
+static DEFINE_SPINLOCK(sdphy67_div_lock);
+static DEFINE_SPINLOCK(can_div_lock);
+static DEFINE_SPINLOCK(deint_div_lock);
+static DEFINE_SPINLOCK(nand_div_lock);
+static DEFINE_SPINLOCK(disp0_div_lock);
+static DEFINE_SPINLOCK(disp1_div_lock);
+static DEFINE_SPINLOCK(gpu_div_lock);
+static DEFINE_SPINLOCK(gnss_div_lock);
+/* gate register shared */
+static DEFINE_SPINLOCK(share_div_lock);
+static DEFINE_SPINLOCK(root0_gate_lock);
+static DEFINE_SPINLOCK(root1_gate_lock);
+static DEFINE_SPINLOCK(leaf0_gate_lock);
+static DEFINE_SPINLOCK(leaf1_gate_lock);
+static DEFINE_SPINLOCK(leaf2_gate_lock);
+static DEFINE_SPINLOCK(leaf3_gate_lock);
+static DEFINE_SPINLOCK(leaf4_gate_lock);
+static DEFINE_SPINLOCK(leaf5_gate_lock);
+static DEFINE_SPINLOCK(leaf6_gate_lock);
+static DEFINE_SPINLOCK(leaf7_gate_lock);
+static DEFINE_SPINLOCK(leaf8_gate_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+	return readl(sirfsoc_clk_vbase + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+	writel(val, sirfsoc_clk_vbase + reg);
+}
+
+/*
+*  ABPLL
+*  integer mode: Fvco = Fin * 2 * NF / NR
+*  Spread Spectrum mode: Fvco = Fin * SSN / NR
+*  SSN = 2^24 / (256 * ((ssdiv >> ssdepth) << ssdepth) + (ssmod << ssdepth))
+*/
+static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
+	unsigned long parent_rate)
+{
+	unsigned long fin = parent_rate;
+	struct clk_pll *clk = to_pllclk(hw);
+	u64 rate;
+	u32 regctrl0 = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_CTRL0 -
+			SIRFSOC_CLKC_MEMPLL_AB_FREQ);
+	u32 regfreq = clkc_readl(clk->regofs);
+	u32 regssc = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_SSC -
+			SIRFSOC_CLKC_MEMPLL_AB_FREQ);
+	u32 nr = (regfreq  >> 16 & (BIT(3) - 1)) + 1;
+	u32 nf = (regfreq & (BIT(9) - 1)) + 1;
+	u32 ssdiv = regssc >> 8 & (BIT(12) - 1);
+	u32 ssdepth = regssc >> 20 & (BIT(2) - 1);
+	u32 ssmod = regssc & (BIT(8) - 1);
+
+	if (regctrl0 & SIRFSOC_ABPLL_CTRL0_BYPASS)
+		return fin;
+
+	if (regctrl0 & SIRFSOC_ABPLL_CTRL0_SSEN) {
+		rate = fin;
+		rate *= 1 << 24;
+		do_div(rate, (256 * ((ssdiv >> ssdepth) << ssdepth)
+			+ (ssmod << ssdepth)));
+	} else {
+		rate = 2 * fin;
+		rate *= nf;
+		do_div(rate, nr);
+	}
+	return rate;
+}
+
+static const struct clk_ops ab_pll_ops = {
+	.recalc_rate = pll_clk_recalc_rate,
+};
+
+static const char * const pll_clk_parents[] = {
+	"xin",
+};
+
+static struct clk_init_data clk_cpupll_init = {
+	.name = "cpupll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_cpupll = {
+	.regofs = SIRFSOC_CLKC_CPUPLL_AB_FREQ,
+	.hw = {
+		.init = &clk_cpupll_init,
+	},
+};
+
+static struct clk_init_data clk_mempll_init = {
+	.name = "mempll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_mempll = {
+	.regofs = SIRFSOC_CLKC_MEMPLL_AB_FREQ,
+	.hw = {
+		.init = &clk_mempll_init,
+	},
+};
+
+static struct clk_init_data clk_sys0pll_init = {
+	.name = "sys0pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys0pll = {
+	.regofs = SIRFSOC_CLKC_SYS0PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys0pll_init,
+	},
+};
+
+static struct clk_init_data clk_sys1pll_init = {
+	.name = "sys1pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys1pll = {
+	.regofs = SIRFSOC_CLKC_SYS1PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys1pll_init,
+	},
+};
+
+static struct clk_init_data clk_sys2pll_init = {
+	.name = "sys2pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys2pll = {
+	.regofs = SIRFSOC_CLKC_SYS2PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys2pll_init,
+	},
+};
+
+static struct clk_init_data clk_sys3pll_init = {
+	.name = "sys3pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys3pll = {
+	.regofs = SIRFSOC_CLKC_SYS3PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys3pll_init,
+	},
+};
+
+/*
+ *  DTO in clkc, default enable double resolution mode
+ *  double resolution mode:fout = fin * finc / 2^29
+ *  normal mode:fout = fin * finc / 2^28
+ */
+static int dto_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_dto *clk = to_dtoclk(hw);
+	int reg;
+
+	reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+	return !!(clkc_readl(reg) & BIT(0));
+}
+
+static int dto_clk_enable(struct clk_hw *hw)
+{
+	u32 val, reg;
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+	val = clkc_readl(reg) | BIT(0);
+	clkc_writel(val, reg);
+	return 0;
+}
+
+static void dto_clk_disable(struct clk_hw *hw)
+{
+	u32 val, reg;
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+	val = clkc_readl(reg) & ~BIT(0);
+	clkc_writel(val, reg);
+}
+
+static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
+	unsigned long parent_rate)
+{
+	u64 rate = parent_rate;
+	struct clk_dto *clk = to_dtoclk(hw);
+	u32 finc = clkc_readl(clk->inc_offset);
+	u32 droff = clkc_readl(clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC);
+
+	rate *= finc;
+	if (droff & BIT(0))
+		/* Double resolution off */
+		do_div(rate, 1 << 28);
+	else
+		do_div(rate, 1 << 29);
+
+	return rate;
+}
+
+static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long *parent_rate)
+{
+	u64 dividend = rate * (1 << 29);
+
+	do_div(dividend, *parent_rate);
+	dividend *= *parent_rate;
+	do_div(dividend, 1 << 29);
+
+	return dividend;
+}
+
+static int dto_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long parent_rate)
+{
+	u64 dividend = rate * (1 << 29);
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	do_div(dividend, parent_rate);
+	clkc_writel(0, clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC);
+	clkc_writel(dividend, clk->inc_offset);
+
+	return 0;
+}
+
+static u8 dto_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	return clkc_readl(clk->src_offset);
+}
+
+/*
+ *   dto need CLK_SET_PARENT_GATE
+ */
+static int dto_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	clkc_writel(index, clk->src_offset);
+	return 0;
+}
+
+static const struct clk_ops dto_ops = {
+	.is_enabled = dto_clk_is_enabled,
+	.enable = dto_clk_enable,
+	.disable = dto_clk_disable,
+	.recalc_rate = dto_clk_recalc_rate,
+	.round_rate = dto_clk_round_rate,
+	.set_rate = dto_clk_set_rate,
+	.get_parent = dto_clk_get_parent,
+	.set_parent = dto_clk_set_parent,
+};
+
+/* dto parent clock as syspllvco/clk1 */
+static const char * const audiodto_clk_parents[] = {
+	"sys0pll_clk1",
+	"sys1pll_clk1",
+	"sys3pll_clk1",
+};
+
+static struct clk_init_data clk_audiodto_init = {
+	.name = "audio_dto",
+	.ops = &dto_ops,
+	.parent_names = audiodto_clk_parents,
+	.num_parents = ARRAY_SIZE(audiodto_clk_parents),
+};
+
+static struct clk_dto clk_audio_dto = {
+	.inc_offset = SIRFSOC_CLKC_AUDIO_DTO_INC,
+	.src_offset = SIRFSOC_CLKC_AUDIO_DTO_SRC,
+	.hw = {
+		.init = &clk_audiodto_init,
+	},
+};
+
+static const char * const disp0dto_clk_parents[] = {
+	"sys0pll_clk1",
+	"sys1pll_clk1",
+	"sys3pll_clk1",
+};
+
+static struct clk_init_data clk_disp0dto_init = {
+	.name = "disp0_dto",
+	.ops = &dto_ops,
+	.parent_names = disp0dto_clk_parents,
+	.num_parents = ARRAY_SIZE(disp0dto_clk_parents),
+};
+
+static struct clk_dto clk_disp0_dto = {
+	.inc_offset = SIRFSOC_CLKC_DISP0_DTO_INC,
+	.src_offset = SIRFSOC_CLKC_DISP0_DTO_SRC,
+	.hw = {
+		.init = &clk_disp0dto_init,
+	},
+};
+
+static const char * const disp1dto_clk_parents[] = {
+	"sys0pll_clk1",
+	"sys1pll_clk1",
+	"sys3pll_clk1",
+};
+
+static struct clk_init_data clk_disp1dto_init = {
+	.name = "disp1_dto",
+	.ops = &dto_ops,
+	.parent_names = disp1dto_clk_parents,
+	.num_parents = ARRAY_SIZE(disp1dto_clk_parents),
+};
+
+static struct clk_dto clk_disp1_dto = {
+	.inc_offset = SIRFSOC_CLKC_DISP1_DTO_INC,
+	.src_offset = SIRFSOC_CLKC_DISP1_DTO_SRC,
+	.hw = {
+		.init = &clk_disp1dto_init,
+	},
+};
+
+static struct atlas7_div_init_data divider_list[] __initdata = {
+	/* div_name, parent_name, gate_name, clk_flag, divider_flag, gate_flag, div_offset, shift, wdith, gate_offset, bit_enable, lock */
+	{ "sys0pll_qa1", "sys0pll_fixdiv", "sys0pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 0, &usbphy_div_lock },
+	{ "sys1pll_qa1", "sys1pll_fixdiv", "sys1pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 4, &usbphy_div_lock },
+	{ "sys2pll_qa1", "sys2pll_fixdiv", "sys2pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 8, &usbphy_div_lock },
+	{ "sys3pll_qa1", "sys3pll_fixdiv", "sys3pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 12, &usbphy_div_lock },
+	{ "sys0pll_qa2", "sys0pll_fixdiv", "sys0pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 0, &btss_div_lock },
+	{ "sys1pll_qa2", "sys1pll_fixdiv", "sys1pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 4, &btss_div_lock },
+	{ "sys2pll_qa2", "sys2pll_fixdiv", "sys2pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 8, &btss_div_lock },
+	{ "sys3pll_qa2", "sys3pll_fixdiv", "sys3pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 12, &btss_div_lock },
+	{ "sys0pll_qa3", "sys0pll_fixdiv", "sys0pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 0, &rgmii_div_lock },
+	{ "sys1pll_qa3", "sys1pll_fixdiv", "sys1pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 4, &rgmii_div_lock },
+	{ "sys2pll_qa3", "sys2pll_fixdiv", "sys2pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 8, &rgmii_div_lock },
+	{ "sys3pll_qa3", "sys3pll_fixdiv", "sys3pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 12, &rgmii_div_lock },
+	{ "sys0pll_qa4", "sys0pll_fixdiv", "sys0pll_a4", 0, 0, 0, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 0, &cpu_div_lock },
+	{ "sys1pll_qa4", "sys1pll_fixdiv", "sys1pll_a4", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 4, &cpu_div_lock },
+	{ "sys0pll_qa5", "sys0pll_fixdiv", "sys0pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 0, &sdphy01_div_lock },
+	{ "sys1pll_qa5", "sys1pll_fixdiv", "sys1pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 4, &sdphy01_div_lock },
+	{ "sys2pll_qa5", "sys2pll_fixdiv", "sys2pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 8, &sdphy01_div_lock },
+	{ "sys3pll_qa5", "sys3pll_fixdiv", "sys3pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 12, &sdphy01_div_lock },
+	{ "sys0pll_qa6", "sys0pll_fixdiv", "sys0pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 0, &sdphy23_div_lock },
+	{ "sys1pll_qa6", "sys1pll_fixdiv", "sys1pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 4, &sdphy23_div_lock },
+	{ "sys2pll_qa6", "sys2pll_fixdiv", "sys2pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 8, &sdphy23_div_lock },
+	{ "sys3pll_qa6", "sys3pll_fixdiv", "sys3pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 12, &sdphy23_div_lock },
+	{ "sys0pll_qa7", "sys0pll_fixdiv", "sys0pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 0, &sdphy45_div_lock },
+	{ "sys1pll_qa7", "sys1pll_fixdiv", "sys1pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 4, &sdphy45_div_lock },
+	{ "sys2pll_qa7", "sys2pll_fixdiv", "sys2pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 8, &sdphy45_div_lock },
+	{ "sys3pll_qa7", "sys3pll_fixdiv", "sys3pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 12, &sdphy45_div_lock },
+	{ "sys0pll_qa8", "sys0pll_fixdiv", "sys0pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 0, &sdphy67_div_lock },
+	{ "sys1pll_qa8", "sys1pll_fixdiv", "sys1pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 4, &sdphy67_div_lock },
+	{ "sys2pll_qa8", "sys2pll_fixdiv", "sys2pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 8, &sdphy67_div_lock },
+	{ "sys3pll_qa8", "sys3pll_fixdiv", "sys3pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 12, &sdphy67_div_lock },
+	{ "sys0pll_qa9", "sys0pll_fixdiv", "sys0pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 0, &can_div_lock },
+	{ "sys1pll_qa9", "sys1pll_fixdiv", "sys1pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 4, &can_div_lock },
+	{ "sys2pll_qa9", "sys2pll_fixdiv", "sys2pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 8, &can_div_lock },
+	{ "sys3pll_qa9", "sys3pll_fixdiv", "sys3pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 12, &can_div_lock },
+	{ "sys0pll_qa10", "sys0pll_fixdiv", "sys0pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 0, &deint_div_lock },
+	{ "sys1pll_qa10", "sys1pll_fixdiv", "sys1pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 4, &deint_div_lock },
+	{ "sys2pll_qa10", "sys2pll_fixdiv", "sys2pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 8, &deint_div_lock },
+	{ "sys3pll_qa10", "sys3pll_fixdiv", "sys3pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 12, &deint_div_lock },
+	{ "sys0pll_qa11", "sys0pll_fixdiv", "sys0pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 0, &nand_div_lock },
+	{ "sys1pll_qa11", "sys1pll_fixdiv", "sys1pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 4, &nand_div_lock },
+	{ "sys2pll_qa11", "sys2pll_fixdiv", "sys2pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 8, &nand_div_lock },
+	{ "sys3pll_qa11", "sys3pll_fixdiv", "sys3pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 12, &nand_div_lock },
+	{ "sys0pll_qa12", "sys0pll_fixdiv", "sys0pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 0, &disp0_div_lock },
+	{ "sys1pll_qa12", "sys1pll_fixdiv", "sys1pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 4, &disp0_div_lock },
+	{ "sys2pll_qa12", "sys2pll_fixdiv", "sys2pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 8, &disp0_div_lock },
+	{ "sys3pll_qa12", "sys3pll_fixdiv", "sys3pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 12, &disp0_div_lock },
+	{ "sys0pll_qa13", "sys0pll_fixdiv", "sys0pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 0, &disp1_div_lock },
+	{ "sys1pll_qa13", "sys1pll_fixdiv", "sys1pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 4, &disp1_div_lock },
+	{ "sys2pll_qa13", "sys2pll_fixdiv", "sys2pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 8, &disp1_div_lock },
+	{ "sys3pll_qa13", "sys3pll_fixdiv", "sys3pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 12, &disp1_div_lock },
+	{ "sys0pll_qa14", "sys0pll_fixdiv", "sys0pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 0, &gpu_div_lock },
+	{ "sys1pll_qa14", "sys1pll_fixdiv", "sys1pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 4, &gpu_div_lock },
+	{ "sys2pll_qa14", "sys2pll_fixdiv", "sys2pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 8, &gpu_div_lock },
+	{ "sys3pll_qa14", "sys3pll_fixdiv", "sys3pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 12, &gpu_div_lock },
+	{ "sys0pll_qa15", "sys0pll_fixdiv", "sys0pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 0, &gnss_div_lock },
+	{ "sys1pll_qa15", "sys1pll_fixdiv", "sys1pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 4, &gnss_div_lock },
+	{ "sys2pll_qa15", "sys2pll_fixdiv", "sys2pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 8, &gnss_div_lock },
+	{ "sys3pll_qa15", "sys3pll_fixdiv", "sys3pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 12, &gnss_div_lock },
+	{ "sys1pll_qa18", "sys1pll_fixdiv", "sys1pll_a18", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 24, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 12, &share_div_lock },
+	{ "sys1pll_qa19", "sys1pll_fixdiv", "sys1pll_a19", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 16, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 8, &share_div_lock },
+	{ "sys1pll_qa20", "sys1pll_fixdiv", "sys1pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 4, &share_div_lock },
+	{ "sys2pll_qa20", "sys2pll_fixdiv", "sys2pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 0, &share_div_lock },
+	{ "sys1pll_qa17", "sys1pll_fixdiv", "sys1pll_a17", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 20, &share_div_lock },
+	{ "sys0pll_qa20", "sys0pll_fixdiv", "sys0pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 16, &share_div_lock },
+};
+
+static const char * const i2s_clk_parents[] = {
+	"xin",
+	"xinw",
+	"audio_dto",
+	/* "pwm_i2s01" */
+};
+
+static const char * const usbphy_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a1",
+	"sys1pll_a1",
+	"sys2pll_a1",
+	"sys3pll_a1",
+};
+
+static const char * const btss_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a2",
+	"sys1pll_a2",
+	"sys2pll_a2",
+	"sys3pll_a2",
+};
+
+static const char * const rgmii_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a3",
+	"sys1pll_a3",
+	"sys2pll_a3",
+	"sys3pll_a3",
+};
+
+static const char * const cpu_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a4",
+	"sys1pll_a4",
+	"cpupll_clk1",
+};
+
+static const char * const sdphy01_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a5",
+	"sys1pll_a5",
+	"sys2pll_a5",
+	"sys3pll_a5",
+};
+
+static const char * const sdphy23_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a6",
+	"sys1pll_a6",
+	"sys2pll_a6",
+	"sys3pll_a6",
+};
+
+static const char * const sdphy45_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a7",
+	"sys1pll_a7",
+	"sys2pll_a7",
+	"sys3pll_a7",
+};
+
+static const char * const sdphy67_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a8",
+	"sys1pll_a8",
+	"sys2pll_a8",
+	"sys3pll_a8",
+};
+
+static const char * const can_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a9",
+	"sys1pll_a9",
+	"sys2pll_a9",
+	"sys3pll_a9",
+};
+
+static const char * const deint_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a10",
+	"sys1pll_a10",
+	"sys2pll_a10",
+	"sys3pll_a10",
+};
+
+static const char * const nand_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a11",
+	"sys1pll_a11",
+	"sys2pll_a11",
+	"sys3pll_a11",
+};
+
+static const char * const disp0_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a12",
+	"sys1pll_a12",
+	"sys2pll_a12",
+	"sys3pll_a12",
+	"disp0_dto",
+};
+
+static const char * const disp1_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a13",
+	"sys1pll_a13",
+	"sys2pll_a13",
+	"sys3pll_a13",
+	"disp1_dto",
+};
+
+static const char * const gpu_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a14",
+	"sys1pll_a14",
+	"sys2pll_a14",
+	"sys3pll_a14",
+};
+
+static const char * const gnss_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a15",
+	"sys1pll_a15",
+	"sys2pll_a15",
+	"sys3pll_a15",
+};
+
+static const char * const sys_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const io_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const g2d_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const jpenc_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const vdec_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const gmac_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const usb_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const kas_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const sec_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const sdr_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const vip_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const nocd_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const nocr_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const tpiu_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static struct atlas7_mux_init_data mux_list[] __initdata = {
+	/* mux_name, parent_names, parent_num, flags, mux_flags, mux_offset, shift, width */
+	{ "i2s_mux", i2s_clk_parents, ARRAY_SIZE(i2s_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 2 },
+	{ "usbphy_mux", usbphy_clk_parents, ARRAY_SIZE(usbphy_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 3 },
+	{ "btss_mux", btss_clk_parents, ARRAY_SIZE(btss_clk_parents), 0, 0, SIRFSOC_CLKC_BTSS_CLK_SEL, 0, 3 },
+	{ "rgmii_mux", rgmii_clk_parents, ARRAY_SIZE(rgmii_clk_parents), 0, 0, SIRFSOC_CLKC_RGMII_CLK_SEL, 0, 3 },
+	{ "cpu_mux", cpu_clk_parents, ARRAY_SIZE(cpu_clk_parents), 0, 0, SIRFSOC_CLKC_CPU_CLK_SEL, 0, 3 },
+	{ "sdphy01_mux", sdphy01_clk_parents, ARRAY_SIZE(sdphy01_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY01_CLK_SEL, 0, 3 },
+	{ "sdphy23_mux", sdphy23_clk_parents, ARRAY_SIZE(sdphy23_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY23_CLK_SEL, 0, 3 },
+	{ "sdphy45_mux", sdphy45_clk_parents, ARRAY_SIZE(sdphy45_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY45_CLK_SEL, 0, 3 },
+	{ "sdphy67_mux", sdphy67_clk_parents, ARRAY_SIZE(sdphy67_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY67_CLK_SEL, 0, 3 },
+	{ "can_mux", can_clk_parents, ARRAY_SIZE(can_clk_parents), 0, 0, SIRFSOC_CLKC_CAN_CLK_SEL, 0, 3 },
+	{ "deint_mux", deint_clk_parents, ARRAY_SIZE(deint_clk_parents), 0, 0, SIRFSOC_CLKC_DEINT_CLK_SEL, 0, 3 },
+	{ "nand_mux", nand_clk_parents, ARRAY_SIZE(nand_clk_parents), 0, 0, SIRFSOC_CLKC_NAND_CLK_SEL, 0, 3 },
+	{ "disp0_mux", disp0_clk_parents, ARRAY_SIZE(disp0_clk_parents), 0, 0, SIRFSOC_CLKC_DISP0_CLK_SEL, 0, 3 },
+	{ "disp1_mux", disp1_clk_parents, ARRAY_SIZE(disp1_clk_parents), 0, 0, SIRFSOC_CLKC_DISP1_CLK_SEL, 0, 3 },
+	{ "gpu_mux", gpu_clk_parents, ARRAY_SIZE(gpu_clk_parents), 0, 0, SIRFSOC_CLKC_GPU_CLK_SEL, 0, 3 },
+	{ "gnss_mux", gnss_clk_parents, ARRAY_SIZE(gnss_clk_parents), 0, 0, SIRFSOC_CLKC_GNSS_CLK_SEL, 0, 3 },
+	{ "sys_mux", sys_clk_parents, ARRAY_SIZE(sys_clk_parents), 0, 0, SIRFSOC_CLKC_SYS_CLK_SEL, 0, 3 },
+	{ "io_mux", io_clk_parents, ARRAY_SIZE(io_clk_parents), 0, 0, SIRFSOC_CLKC_IO_CLK_SEL, 0, 3 },
+	{ "g2d_mux", g2d_clk_parents, ARRAY_SIZE(g2d_clk_parents), 0, 0, SIRFSOC_CLKC_G2D_CLK_SEL, 0, 3 },
+	{ "jpenc_mux", jpenc_clk_parents, ARRAY_SIZE(jpenc_clk_parents), 0, 0, SIRFSOC_CLKC_JPENC_CLK_SEL, 0, 3 },
+	{ "vdec_mux", vdec_clk_parents, ARRAY_SIZE(vdec_clk_parents), 0, 0, SIRFSOC_CLKC_VDEC_CLK_SEL, 0, 3 },
+	{ "gmac_mux", gmac_clk_parents, ARRAY_SIZE(gmac_clk_parents), 0, 0, SIRFSOC_CLKC_GMAC_CLK_SEL, 0, 3 },
+	{ "usb_mux", usb_clk_parents, ARRAY_SIZE(usb_clk_parents), 0, 0, SIRFSOC_CLKC_USB_CLK_SEL, 0, 3 },
+	{ "kas_mux", kas_clk_parents, ARRAY_SIZE(kas_clk_parents), 0, 0, SIRFSOC_CLKC_KAS_CLK_SEL, 0, 3 },
+	{ "sec_mux", sec_clk_parents, ARRAY_SIZE(sec_clk_parents), 0, 0, SIRFSOC_CLKC_SEC_CLK_SEL, 0, 3 },
+	{ "sdr_mux", sdr_clk_parents, ARRAY_SIZE(sdr_clk_parents), 0, 0, SIRFSOC_CLKC_SDR_CLK_SEL, 0, 3 },
+	{ "vip_mux", vip_clk_parents, ARRAY_SIZE(vip_clk_parents), 0, 0, SIRFSOC_CLKC_VIP_CLK_SEL, 0, 3 },
+	{ "nocd_mux", nocd_clk_parents, ARRAY_SIZE(nocd_clk_parents), 0, 0, SIRFSOC_CLKC_NOCD_CLK_SEL, 0, 3 },
+	{ "nocr_mux", nocr_clk_parents, ARRAY_SIZE(nocr_clk_parents), 0, 0, SIRFSOC_CLKC_NOCR_CLK_SEL, 0, 3 },
+	{ "tpiu_mux", tpiu_clk_parents, ARRAY_SIZE(tpiu_clk_parents), 0, 0, SIRFSOC_CLKC_TPIU_CLK_SEL, 0, 3 },
+};
+
+	/* new unit should add start from the tail of list */
+static struct atlas7_unit_init_data unit_list[] __initdata = {
+	/* unit_name, parent_name, flags, regofs, bit, lock */
+	{ 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, &root0_gate_lock },
+	{ 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, &root0_gate_lock },
+	{ 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, &root0_gate_lock },
+	{ 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, &root0_gate_lock },
+	{ 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, &root0_gate_lock },
+	{ 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, &root0_gate_lock },
+	{ 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, &root0_gate_lock },
+	{ 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, &root0_gate_lock },
+	{ 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, &root0_gate_lock },
+	{ 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, &root0_gate_lock },
+	{ 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, &root0_gate_lock },
+	{ 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, &root0_gate_lock },
+	{ 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, &root0_gate_lock },
+	{ 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, &root0_gate_lock },
+	{ 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, &root0_gate_lock },
+	{ 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, &root0_gate_lock },
+	{ 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, &root0_gate_lock },
+	{ 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, &root0_gate_lock },
+	{ 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, &root0_gate_lock },
+	{ 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, &root0_gate_lock },
+	{ 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, &root0_gate_lock },
+	{ 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, &root0_gate_lock },
+	{ 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, &root0_gate_lock },
+	{ 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, &root1_gate_lock },
+	{ 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, &root1_gate_lock },
+	{ 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, &root1_gate_lock },
+	{ 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, &root1_gate_lock },
+	{ 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, &root1_gate_lock },
+	{ 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, &root1_gate_lock },
+	{ 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, &root1_gate_lock },
+	{ 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, &root1_gate_lock },
+	{ 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, &root1_gate_lock },
+	{ 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, &root1_gate_lock },
+	{ 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, &root1_gate_lock },
+	{ 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, &root1_gate_lock },
+	{ 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, &root1_gate_lock },
+	{ 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, &root1_gate_lock },
+	{ 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, &root1_gate_lock },
+	{ 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, &root1_gate_lock },
+	{ 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, &root1_gate_lock },
+	{ 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, &root1_gate_lock },
+	{ 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, &root1_gate_lock },
+	{ 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, &root1_gate_lock },
+	{ 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, &root1_gate_lock },
+	{ 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, &root1_gate_lock },
+	{ 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, &root1_gate_lock },
+	{ 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, &leaf1_gate_lock },
+	{ 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, &leaf1_gate_lock },
+	{ 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, &leaf1_gate_lock },
+	{ 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, &leaf1_gate_lock },
+	{ 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, &leaf1_gate_lock },
+	{ 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, &leaf1_gate_lock },
+	{ 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, &leaf1_gate_lock },
+	{ 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, &leaf1_gate_lock },
+	{ 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, &leaf1_gate_lock },
+	{ 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, &leaf1_gate_lock },
+	{ 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, &leaf1_gate_lock },
+	{ 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, &leaf1_gate_lock },
+	{ 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, &leaf1_gate_lock },
+	{ 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, &leaf1_gate_lock },
+	{ 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, &leaf1_gate_lock },
+	{ 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, &leaf1_gate_lock },
+	{ 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, &leaf1_gate_lock },
+	{ 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, &leaf1_gate_lock },
+	{ 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, &leaf1_gate_lock },
+	{ 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, &leaf1_gate_lock },
+	{ 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, &leaf2_gate_lock },
+	{ 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, &leaf2_gate_lock },
+	{ 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, &leaf2_gate_lock },
+	{ 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, &leaf2_gate_lock },
+	{ 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, &leaf2_gate_lock },
+	{ 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, &leaf2_gate_lock },
+	{ 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, &leaf2_gate_lock },
+	{ 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, &leaf2_gate_lock },
+	{ 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, &leaf2_gate_lock },
+	{ 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, &leaf2_gate_lock },
+	{ 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, &leaf2_gate_lock },
+	{ 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, &leaf2_gate_lock },
+	{ 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, &leaf2_gate_lock },
+	{ 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, &leaf2_gate_lock },
+	{ 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, &leaf2_gate_lock },
+	{ 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, &leaf2_gate_lock },
+	{ 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, &leaf2_gate_lock },
+	{ 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, &leaf2_gate_lock },
+	{ 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, &leaf2_gate_lock },
+	{ 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, &leaf2_gate_lock },
+	{ 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, &leaf3_gate_lock },
+	{ 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, &leaf3_gate_lock },
+	{ 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, &leaf3_gate_lock },
+	{ 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, &leaf3_gate_lock },
+	{ 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, &leaf3_gate_lock },
+	{ 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, &leaf3_gate_lock },
+	{ 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, &leaf3_gate_lock },
+	{ 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, &leaf3_gate_lock },
+	{ 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, &leaf3_gate_lock },
+	{ 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, &leaf3_gate_lock },
+	{ 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, &leaf3_gate_lock },
+	{ 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, &leaf3_gate_lock },
+	{ 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, &leaf3_gate_lock },
+	{ 99,  "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, &leaf3_gate_lock },
+	{ 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, &leaf3_gate_lock },
+	{ 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, &leaf3_gate_lock },
+	{ 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, &leaf4_gate_lock },
+	{ 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, &leaf4_gate_lock },
+	{ 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, &leaf4_gate_lock },
+	{ 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, &leaf4_gate_lock },
+	{ 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, &leaf4_gate_lock },
+	{ 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, &leaf4_gate_lock },
+	{ 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, &leaf4_gate_lock },
+	{ 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, &leaf4_gate_lock },
+	{ 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, &leaf4_gate_lock },
+	{ 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, &leaf4_gate_lock },
+	{ 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, &leaf4_gate_lock },
+	{ 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, &leaf4_gate_lock },
+	{ 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, &leaf4_gate_lock },
+	{ 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, &leaf4_gate_lock },
+	{ 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, &leaf4_gate_lock },
+	{ 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, &leaf4_gate_lock },
+	{ 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, &leaf5_gate_lock },
+	{ 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, &leaf5_gate_lock },
+	{ 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, &leaf5_gate_lock },
+	{ 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, &leaf5_gate_lock },
+	{ 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
+	{ 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
+	{ 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
+	{ 125, "thcpum_cpudiv4", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
+	{ 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
+	{ 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
+	{ 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
+	{ 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, &leaf8_gate_lock },
+	{ 130, "dmac4_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, &leaf8_gate_lock },
+	{ 131, "uart6_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, &leaf8_gate_lock },
+	{ 132, "usp3_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, &leaf8_gate_lock },
+	{ 133, "a7ca_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, &leaf8_gate_lock },
+	{ 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, &leaf8_gate_lock },
+	{ 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
+	{ 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
+	{ 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
+};
+
+static struct clk *atlas7_clks[ARRAY_SIZE(unit_list)];
+
+static int unit_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_unit *clk = to_unitclk(hw);
+	u32 reg;
+
+	reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_STAT - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
+
+	return !!(clkc_readl(reg) & BIT(clk->bit));
+}
+
+static int unit_clk_enable(struct clk_hw *hw)
+{
+	u32 reg;
+	struct clk_unit *clk = to_unitclk(hw);
+	unsigned long flags;
+
+	reg = clk->regofs;
+
+	spin_lock_irqsave(clk->lock, flags);
+	clkc_writel(BIT(clk->bit), reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+	return 0;
+}
+
+static void unit_clk_disable(struct clk_hw *hw)
+{
+	u32  reg;
+	struct clk_unit *clk = to_unitclk(hw);
+	unsigned long flags;
+
+	reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
+
+	spin_lock_irqsave(clk->lock, flags);
+	clkc_writel(BIT(clk->bit), reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+}
+
+static const struct clk_ops unit_clk_ops = {
+	.is_enabled = unit_clk_is_enabled,
+	.enable = unit_clk_enable,
+	.disable = unit_clk_disable,
+};
+
+static struct clk * __init
+atlas7_unit_clk_register(struct device *dev, const char *name,
+		 const char * const parent_name, unsigned long flags,
+		 u32 regofs, u8 bit, spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_unit *unit;
+	struct clk_init_data init;
+
+	unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+	if (!unit)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+	init.ops = &unit_clk_ops;
+	init.flags = flags;
+
+	unit->hw.init = &init;
+	unit->regofs = regofs;
+	unit->bit = bit;
+	unit->lock = lock;
+
+	clk = clk_register(dev, &unit->hw);
+	if (IS_ERR(clk))
+		kfree(unit);
+
+	return clk;
+}
+
+static struct atlas7_reset_desc atlas7_reset_unit[] = {
+	{ "PWM", 0x0244, 0, 0x0320, 0, &leaf0_gate_lock }, /* 0-5 */
+	{ "THCGUM", 0x0244, 3, 0x0320, 1, &leaf0_gate_lock },
+	{ "CVD", 0x04A0, 0, 0x032C, 0, &leaf1_gate_lock },
+	{ "TIMER", 0x04A0, 1, 0x032C, 1, &leaf1_gate_lock },
+	{ "PULSEC", 0x04A0, 2, 0x032C, 2, &leaf1_gate_lock },
+	{ "TSC", 0x04A0, 3, 0x032C, 3, &leaf1_gate_lock },
+	{ "IOCTOP", 0x04A0, 4, 0x032C, 4, &leaf1_gate_lock }, /* 6-10 */
+	{ "RSC", 0x04A0, 5, 0x032C, 5, &leaf1_gate_lock },
+	{ "DVM", 0x04A0, 6, 0x032C, 6, &leaf1_gate_lock },
+	{ "LVDS", 0x04A0, 7, 0x032C, 7, &leaf1_gate_lock },
+	{ "KAS", 0x04A0, 8, 0x032C, 8, &leaf1_gate_lock },
+	{ "AC97", 0x04A0, 9, 0x032C, 9, &leaf1_gate_lock }, /* 11-15 */
+	{ "USP0", 0x04A0, 10, 0x032C, 10, &leaf1_gate_lock },
+	{ "USP1", 0x04A0, 11, 0x032C, 11, &leaf1_gate_lock },
+	{ "USP2", 0x04A0, 12, 0x032C, 12, &leaf1_gate_lock },
+	{ "DMAC2", 0x04A0, 13, 0x032C, 13, &leaf1_gate_lock },
+	{ "DMAC3", 0x04A0, 14, 0x032C, 14, &leaf1_gate_lock }, /* 16-20 */
+	{ "AUDIO", 0x04A0, 15, 0x032C, 15, &leaf1_gate_lock },
+	{ "I2S1", 0x04A0, 17, 0x032C, 16, &leaf1_gate_lock },
+	{ "PMU_AUDIO", 0x04A0, 22, 0x032C, 17, &leaf1_gate_lock },
+	{ "THAUDMSCM", 0x04A0, 23, 0x032C, 18, &leaf1_gate_lock },
+	{ "SYS2PCI", 0x04B8, 0, 0x0338, 0, &leaf2_gate_lock }, /* 21-25 */
+	{ "PCIARB", 0x04B8, 1, 0x0338, 1, &leaf2_gate_lock },
+	{ "PCICOPY", 0x04B8, 2, 0x0338, 2, &leaf2_gate_lock },
+	{ "ROM", 0x04B8, 3, 0x0338, 3, &leaf2_gate_lock },
+	{ "SDIO23", 0x04B8, 4, 0x0338, 4, &leaf2_gate_lock },
+	{ "SDIO45", 0x04B8, 5, 0x0338, 5, &leaf2_gate_lock }, /* 26-30 */
+	{ "SDIO67", 0x04B8, 6, 0x0338, 6, &leaf2_gate_lock },
+	{ "VIP1", 0x04B8, 7, 0x0338, 7, &leaf2_gate_lock },
+	{ "VPP0", 0x04B8, 11, 0x0338, 8, &leaf2_gate_lock },
+	{ "LCD0", 0x04B8, 12, 0x0338, 9, &leaf2_gate_lock },
+	{ "VPP1", 0x04B8, 13, 0x0338, 10, &leaf2_gate_lock }, /* 31-35 */
+	{ "LCD1", 0x04B8, 14, 0x0338, 11, &leaf2_gate_lock },
+	{ "DCU", 0x04B8, 15, 0x0338, 12, &leaf2_gate_lock },
+	{ "GPIO", 0x04B8, 18, 0x0338, 13, &leaf2_gate_lock },
+	{ "DAPA_VDIFM", 0x04B8, 17, 0x0338, 15, &leaf2_gate_lock },
+	{ "THVDIFM", 0x04B8, 19, 0x0338, 16, &leaf2_gate_lock }, /* 36-40 */
+	{ "RGMII", 0x04D0, 0, 0x0344, 0, &leaf3_gate_lock },
+	{ "GMAC", 0x04D0, 1, 0x0344, 1, &leaf3_gate_lock },
+	{ "UART1", 0x04D0, 2, 0x0344, 2, &leaf3_gate_lock },
+	{ "DMAC0", 0x04D0, 3, 0x0344, 3, &leaf3_gate_lock },
+	{ "UART0", 0x04D0, 4, 0x0344, 4, &leaf3_gate_lock }, /* 41-45 */
+	{ "UART2", 0x04D0, 5, 0x0344, 5, &leaf3_gate_lock },
+	{ "UART3", 0x04D0, 6, 0x0344, 6, &leaf3_gate_lock },
+	{ "UART4", 0x04D0, 7, 0x0344, 7, &leaf3_gate_lock },
+	{ "UART5", 0x04D0, 8, 0x0344, 8, &leaf3_gate_lock },
+	{ "SPI1", 0x04D0, 9, 0x0344, 9, &leaf3_gate_lock }, /* 46-50 */
+	{ "GNSS_SYS_M0", 0x04D0, 10, 0x0344, 10, &leaf3_gate_lock },
+	{ "CANBUS1", 0x04D0, 12, 0x0344, 11, &leaf3_gate_lock },
+	{ "CCSEC", 0x04D0, 15, 0x0344, 12, &leaf3_gate_lock },
+	{ "CCPUB", 0x04D0, 16, 0x0344, 13, &leaf3_gate_lock },
+	{ "DAPA_GNSSM", 0x04D0, 13, 0x0344, 14, &leaf3_gate_lock }, /* 51-55 */
+	{ "THGNSSM", 0x04D0, 14, 0x0344, 15, &leaf3_gate_lock },
+	{ "VDEC", 0x04E8, 0, 0x0350, 0, &leaf4_gate_lock },
+	{ "JPENC", 0x04E8, 1, 0x0350, 1, &leaf4_gate_lock },
+	{ "G2D", 0x04E8, 2, 0x0350, 2, &leaf4_gate_lock },
+	{ "I2C0", 0x04E8, 3, 0x0350, 3, &leaf4_gate_lock }, /* 56-60 */
+	{ "I2C1", 0x04E8, 4, 0x0350, 4, &leaf4_gate_lock },
+	{ "GPIO0", 0x04E8, 5, 0x0350, 5, &leaf4_gate_lock },
+	{ "NAND", 0x04E8, 6, 0x0350, 6, &leaf4_gate_lock },
+	{ "SDIO01", 0x04E8, 7, 0x0350, 7, &leaf4_gate_lock },
+	{ "SYS2PCI2", 0x04E8, 8, 0x0350, 8, &leaf4_gate_lock }, /* 61-65 */
+	{ "USB0", 0x04E8, 11, 0x0350, 9, &leaf4_gate_lock },
+	{ "USB1", 0x04E8, 12, 0x0350, 10, &leaf4_gate_lock },
+	{ "THMEDIAM", 0x04E8, 15, 0x0350, 11, &leaf4_gate_lock },
+	{ "MEMC_DDRPHY", 0x0500, 0, 0x035C, 0, &leaf5_gate_lock },
+	{ "MEMC_UPCTL", 0x0500, 0, 0x035C, 1, &leaf5_gate_lock }, /* 66-70 */
+	{ "DAPA_MEM", 0x0500, 1, 0x035C, 2, &leaf5_gate_lock },
+	{ "MEMC_MEMDIV", 0x0500, 0, 0x035C, 3, &leaf5_gate_lock },
+	{ "THDDRM", 0x0500, 3, 0x035C, 4, &leaf5_gate_lock },
+	{ "CORESIGHT", 0x0518, 3, 0x0368, 13, &leaf6_gate_lock },
+	{ "THCPUM", 0x0518, 4, 0x0368, 17, &leaf6_gate_lock }, /* 71-75 */
+	{ "GRAPHIC", 0x0530, 0, 0x0374, 0, &leaf7_gate_lock },
+	{ "VSS_SDR", 0x0530, 1, 0x0374, 1, &leaf7_gate_lock },
+	{ "THGPUM", 0x0530, 2, 0x0374, 2, &leaf7_gate_lock },
+	{ "DMAC4", 0x0548, 2, 0x0380, 1, &leaf8_gate_lock },
+	{ "UART6", 0x0548, 3, 0x0380, 2, &leaf8_gate_lock }, /* 76- */
+	{ "USP3", 0x0548, 4, 0x0380, 3, &leaf8_gate_lock },
+	{ "THBTM", 0x0548, 5, 0x0380, 5, &leaf8_gate_lock },
+	{ "A7CA", 0x0548, 1, 0x0380, 0, &leaf8_gate_lock },
+	{ "A7CA_APB", 0x0548, 5, 0x0380, 4, &leaf8_gate_lock },
+};
+
+static int atlas7_reset_module(struct reset_controller_dev *rcdev,
+					unsigned long reset_idx)
+{
+	struct atlas7_reset_desc *reset = &atlas7_reset_unit[reset_idx];
+	unsigned long flags;
+
+	/*
+	 * HW suggest unit reset sequence:
+	 * assert sw reset (0)
+	 * setting sw clk_en to if the clock was disabled before reset
+	 * delay 16 clocks
+	 * disable clock (sw clk_en = 0)
+	 * de-assert reset (1)
+	 * after this sequence, restore clock or not is decided by SW
+	 */
+
+	spin_lock_irqsave(reset->lock, flags);
+	/* clock enable or not */
+	if (clkc_readl(reset->clk_ofs + 8) & (1 << reset->clk_bit)) {
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4);
+		udelay(2);
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4);
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs);
+		/* restore clock enable */
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs);
+	} else {
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4);
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs);
+		udelay(2);
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4);
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs);
+	}
+	spin_unlock_irqrestore(reset->lock, flags);
+
+	return 0;
+}
+
+static struct reset_control_ops atlas7_rst_ops = {
+	.reset = atlas7_reset_module,
+};
+
+static struct reset_controller_dev atlas7_rst_ctlr = {
+	.ops = &atlas7_rst_ops,
+	.owner = THIS_MODULE,
+	.of_reset_n_cells = 1,
+};
+
+static void __init atlas7_clk_init(struct device_node *np)
+{
+	struct clk *clk;
+	struct atlas7_div_init_data *div;
+	struct atlas7_mux_init_data *mux;
+	struct atlas7_unit_init_data *unit;
+	int i;
+	int ret;
+
+	sirfsoc_clk_vbase = of_iomap(np, 0);
+	if (!sirfsoc_clk_vbase)
+		panic("unable to map clkc registers\n");
+
+	of_node_put(np);
+
+	clk = clk_register(NULL, &clk_cpupll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_mempll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys0pll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys1pll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys2pll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys3pll.hw);
+	BUG_ON(!clk);
+
+	clk = clk_register_divider_table(NULL, "cpupll_div1", "cpupll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "cpupll_div2", "cpupll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "cpupll_div3", "cpupll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_divider_table(NULL, "mempll_div1", "mempll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "mempll_div2", "mempll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "mempll_div3", "mempll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_divider_table(NULL, "sys0pll_div1", "sys0pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys0pll_div2", "sys0pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys0pll_div3", "sys0pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys0pll_fixdiv", "sys0pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	clk = clk_register_divider_table(NULL, "sys1pll_div1", "sys1pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys1pll_div2", "sys1pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys1pll_div3", "sys1pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys1pll_fixdiv", "sys1pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	clk = clk_register_divider_table(NULL, "sys2pll_div1", "sys2pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys2pll_div2", "sys2pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys2pll_div3", "sys2pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys2pll_fixdiv", "sys2pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	clk = clk_register_divider_table(NULL, "sys3pll_div1", "sys3pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys3pll_div2", "sys3pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys3pll_div3", "sys3pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys3pll_fixdiv", "sys3pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "xinw_fixdiv_btslow", "xinw",
+					CLK_SET_RATE_PARENT, 1, 4);
+
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "cpupll_clk1", "cpupll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+				12, 0, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "cpupll_clk2", "cpupll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+				13, 0, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "cpupll_clk3", "cpupll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+				14, 0, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "mempll_clk1", "mempll_div1",
+		CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+		sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+		12, 0, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "mempll_clk2", "mempll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+				13, 0, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "mempll_clk3", "mempll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+				14, 0, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys0pll_clk1", "sys0pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+				12, 0, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys0pll_clk2", "sys0pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+				13, 0, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys0pll_clk3", "sys0pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+				14, 0, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys1pll_clk1", "sys1pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+				12, 0, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys1pll_clk2", "sys1pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+				13, 0, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys1pll_clk3", "sys1pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+				14, 0, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys2pll_clk1", "sys2pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+				12, 0, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys2pll_clk2", "sys2pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+				13, 0, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys2pll_clk3", "sys2pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+				14, 0, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys3pll_clk1", "sys3pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+				12, 0, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys3pll_clk2", "sys3pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+				13, 0, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys3pll_clk3", "sys3pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+				14, 0, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_audio_dto.hw);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_disp0_dto.hw);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_disp1_dto.hw);
+	BUG_ON(!clk);
+
+	for (i = 0; i < ARRAY_SIZE(divider_list); i++) {
+		div = &divider_list[i];
+		clk = clk_register_divider(NULL, div->div_name,
+			div->parent_name, div->divider_flags, sirfsoc_clk_vbase + div->div_offset,
+			div->shift, div->width, 0, div->lock);
+		BUG_ON(!clk);
+		clk = clk_register_gate(NULL, div->gate_name, div->div_name,
+			div->gate_flags, sirfsoc_clk_vbase + div->gate_offset,
+				div->gate_bit, 0, div->lock);
+		BUG_ON(!clk);
+	}
+	/* ignore selector status register check */
+	for (i = 0; i < ARRAY_SIZE(mux_list); i++) {
+		mux = &mux_list[i];
+		clk = clk_register_mux(NULL, mux->mux_name, mux->parent_names,
+			       mux->parent_num, mux->flags,
+			       sirfsoc_clk_vbase + mux->mux_offset,
+			       mux->shift, mux->width,
+			       mux->mux_flags, NULL);
+		BUG_ON(!clk);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(unit_list); i++) {
+		unit = &unit_list[i];
+		atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name,
+				unit->flags, unit->regofs, unit->bit, unit->lock);
+		BUG_ON(!atlas7_clks[i]);
+	}
+
+	clk_data.clks = atlas7_clks;
+	clk_data.clk_num = ARRAY_SIZE(unit_list);
+
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	BUG_ON(ret);
+
+	atlas7_rst_ctlr.of_node = np;
+	atlas7_rst_ctlr.nr_resets = ARRAY_SIZE(atlas7_reset_unit);
+	reset_controller_register(&atlas7_rst_ctlr);
+}
+CLK_OF_DECLARE(atlas7_clk, "sirf,atlas7-car", atlas7_clk_init);
diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c
index 37af51c..9fc285d 100644
--- a/drivers/clk/sirf/clk-common.c
+++ b/drivers/clk/sirf/clk-common.c
@@ -10,8 +10,8 @@
 #define KHZ     1000
 #define MHZ     (KHZ * KHZ)
 
-static void *sirfsoc_clk_vbase;
-static void *sirfsoc_rsc_vbase;
+static void __iomem *sirfsoc_clk_vbase;
+static void __iomem *sirfsoc_rsc_vbase;
 static struct clk_onecell_data clk_data;
 
 /*
@@ -188,7 +188,7 @@
 	.set_rate = pll_clk_set_rate,
 };
 
-static const char *pll_clk_parents[] = {
+static const char * const pll_clk_parents[] = {
 	"osc",
 };
 
@@ -284,7 +284,7 @@
  * clock domains - cpu, mem, sys/io, dsp, gfx
  */
 
-static const char *dmn_clk_parents[] = {
+static const char * const dmn_clk_parents[] = {
 	"rtc",
 	"osc",
 	"pll1",
@@ -673,7 +673,7 @@
 	clkc_writel(val, reg);
 }
 
-static const char *std_clk_io_parents[] = {
+static const char * const std_clk_io_parents[] = {
 	"io",
 };
 
@@ -949,7 +949,7 @@
 	},
 };
 
-static const char *std_clk_dsp_parents[] = {
+static const char * const std_clk_dsp_parents[] = {
 	"dsp",
 };
 
@@ -981,7 +981,7 @@
 	},
 };
 
-static const char *std_clk_sys_parents[] = {
+static const char * const std_clk_sys_parents[] = {
 	"sys",
 };
 
@@ -999,7 +999,7 @@
 	},
 };
 
-static const char *std_clk_usb_parents[] = {
+static const char * const std_clk_usb_parents[] = {
 	"usb_pll",
 };
 
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 7e2d15a..d8bb239 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -2,3 +2,4 @@
 obj-y += clk-gate.o
 obj-y += clk-pll.o
 obj-y += clk-periph.o
+obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c
new file mode 100644
index 0000000..83c6780
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-a10.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2015 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#include "clk.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+/* SDMMC Group for System Manager defines */
+#define SYSMGR_SDMMCGRP_CTRL_OFFSET	0x28
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+	unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	if (socfpgaclk->fixed_div)
+		div = socfpgaclk->fixed_div;
+	else if (socfpgaclk->div_reg) {
+		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		val &= div_mask(socfpgaclk->width);
+		div = (1 << val);
+	}
+
+	return parent_rate / div;
+}
+
+static int socfpga_clk_prepare(struct clk_hw *hwclk)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	int i;
+	u32 hs_timing;
+	u32 clk_phase[2];
+
+	if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
+		for (i = 0; i < ARRAY_SIZE(clk_phase); i++) {
+			switch (socfpgaclk->clk_phase[i]) {
+			case 0:
+				clk_phase[i] = 0;
+				break;
+			case 45:
+				clk_phase[i] = 1;
+				break;
+			case 90:
+				clk_phase[i] = 2;
+				break;
+			case 135:
+				clk_phase[i] = 3;
+				break;
+			case 180:
+				clk_phase[i] = 4;
+				break;
+			case 225:
+				clk_phase[i] = 5;
+				break;
+			case 270:
+				clk_phase[i] = 6;
+				break;
+			case 315:
+				clk_phase[i] = 7;
+				break;
+			default:
+				clk_phase[i] = 0;
+				break;
+			}
+		}
+
+		hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+		if (!IS_ERR(socfpgaclk->sys_mgr_base_addr))
+			regmap_write(socfpgaclk->sys_mgr_base_addr,
+				     SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing);
+		else
+			pr_err("%s: cannot set clk_phase because sys_mgr_base_addr is not available!\n",
+					__func__);
+	}
+	return 0;
+}
+
+static struct clk_ops gateclk_ops = {
+	.prepare = socfpga_clk_prepare,
+	.recalc_rate = socfpga_gate_clk_recalc_rate,
+};
+
+static void __init __socfpga_gate_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 clk_gate[2];
+	u32 div_reg[3];
+	u32 clk_phase[2];
+	u32 fixed_div;
+	struct clk *clk;
+	struct socfpga_gate_clk *socfpga_clk;
+	const char *clk_name = node->name;
+	const char *parent_name[SOCFPGA_MAX_PARENTS];
+	struct clk_init_data init;
+	int rc;
+	int i = 0;
+
+	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+	if (WARN_ON(!socfpga_clk))
+		return;
+
+	rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
+	if (rc)
+		clk_gate[0] = 0;
+
+	if (clk_gate[0]) {
+		socfpga_clk->hw.reg = clk_mgr_a10_base_addr + clk_gate[0];
+		socfpga_clk->hw.bit_idx = clk_gate[1];
+
+		gateclk_ops.enable = clk_gate_ops.enable;
+		gateclk_ops.disable = clk_gate_ops.disable;
+	}
+
+	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+	if (rc)
+		socfpga_clk->fixed_div = 0;
+	else
+		socfpga_clk->fixed_div = fixed_div;
+
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		socfpga_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
+		socfpga_clk->shift = div_reg[1];
+		socfpga_clk->width = div_reg[2];
+	} else {
+		socfpga_clk->div_reg = NULL;
+	}
+
+	rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
+	if (!rc) {
+		socfpga_clk->clk_phase[0] = clk_phase[0];
+		socfpga_clk->clk_phase[1] = clk_phase[1];
+
+		socfpga_clk->sys_mgr_base_addr =
+			syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+		if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) {
+			pr_err("%s: failed to find altr,sys-mgr regmap!\n",
+					__func__);
+			return;
+		}
+	}
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
+			of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	init.parent_names = parent_name;
+	init.num_parents = i;
+	socfpga_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &socfpga_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(socfpga_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (WARN_ON(rc))
+		return;
+}
+
+void __init socfpga_a10_gate_init(struct device_node *node)
+{
+	__socfpga_gate_init(node, &gateclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index dd3a78c..82449cd 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -32,14 +32,10 @@
 #define SOCFPGA_MMC_CLK			"sdmmc_clk"
 #define SOCFPGA_GPIO_DB_CLK_OFFSET	0xA8
 
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
 #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
 
 /* SDMMC Group for System Manager defines */
 #define SYSMGR_SDMMCGRP_CTRL_OFFSET    0x108
-#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
-	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
 
 static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
 {
@@ -194,7 +190,6 @@
 	const char *parent_name[SOCFPGA_MAX_PARENTS];
 	struct clk_init_data init;
 	int rc;
-	int i = 0;
 
 	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
 	if (WARN_ON(!socfpga_clk))
@@ -224,7 +219,7 @@
 		socfpga_clk->shift = div_reg[1];
 		socfpga_clk->width = div_reg[2];
 	} else {
-		socfpga_clk->div_reg = 0;
+		socfpga_clk->div_reg = NULL;
 	}
 
 	rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
@@ -238,12 +233,9 @@
 	init.name = clk_name;
 	init.ops = ops;
 	init.flags = 0;
-	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
-			of_clk_get_parent_name(node, i)) != NULL)
-		i++;
 
+	init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
 	init.parent_names = parent_name;
-	init.num_parents = i;
 	socfpga_clk->hw.hw.init = &init;
 
 	clk = clk_register(NULL, &socfpga_clk->hw.hw);
diff --git a/drivers/clk/socfpga/clk-periph-a10.c b/drivers/clk/socfpga/clk-periph-a10.c
new file mode 100644
index 0000000..9d0181b
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-a10.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT		16
+#define CLK_MGR_FREE_MASK		0x7
+
+#define SOCFPGA_MPU_FREE_CLK		"mpu_free_clk"
+#define SOCFPGA_NOC_FREE_CLK		"noc_free_clk"
+#define SOCFPGA_SDMMC_FREE_CLK		"sdmmc_free_clk"
+#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+	u32 div;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else if (socfpgaclk->div_reg) {
+		div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		div &= div_mask(socfpgaclk->width);
+		div += 1;
+	} else {
+		div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+	}
+
+	return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+	u32 clk_src;
+
+	clk_src = readl(socfpgaclk->hw.reg);
+	if (streq(hwclk->init->name, SOCFPGA_MPU_FREE_CLK) ||
+	    streq(hwclk->init->name, SOCFPGA_NOC_FREE_CLK) ||
+	    streq(hwclk->init->name, SOCFPGA_SDMMC_FREE_CLK))
+		return (clk_src >> CLK_MGR_FREE_SHIFT) &
+			CLK_MGR_FREE_MASK;
+	else
+		return 0;
+}
+
+static const struct clk_ops periclk_ops = {
+	.recalc_rate = clk_periclk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+static __init void __socfpga_periph_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_init_data init;
+	int rc;
+	u32 fixed_div;
+	u32 div_reg[3];
+
+	of_property_read_u32(node, "reg", &reg);
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return;
+
+	periph_clk->hw.reg = clk_mgr_a10_base_addr + reg;
+
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		periph_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
+		periph_clk->shift = div_reg[1];
+		periph_clk->width = div_reg[2];
+	} else {
+		periph_clk->div_reg = NULL;
+	}
+
+	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+	if (rc)
+		periph_clk->fixed_div = 0;
+	else
+		periph_clk->fixed_div = fixed_div;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.num_parents = 1;
+	init.parent_names = &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (rc < 0) {
+		pr_err("Could not register clock provider for node:%s\n",
+		       clk_name);
+		goto err_clk;
+	}
+
+	return;
+
+err_clk:
+	clk_unregister(clk);
+}
+
+void __init socfpga_a10_periph_init(struct device_node *node)
+{
+	__socfpga_periph_init(node, &periclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c
index 46531c3..83aeaa2 100644
--- a/drivers/clk/socfpga/clk-periph.c
+++ b/drivers/clk/socfpga/clk-periph.c
@@ -76,7 +76,7 @@
 		periph_clk->shift = div_reg[1];
 		periph_clk->width = div_reg[2];
 	} else {
-		periph_clk->div_reg = 0;
+		periph_clk->div_reg = NULL;
 	}
 
 	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c
new file mode 100644
index 0000000..1178b11b
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-a10.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT	8
+#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
+
+/* Clock bypass bits */
+#define SOCFPGA_PLL_BG_PWRDWN		0
+#define SOCFPGA_PLL_PWR_DOWN		1
+#define SOCFPGA_PLL_EXT_ENA		2
+#define SOCFPGA_PLL_DIVF_MASK		0x00001FFF
+#define SOCFPGA_PLL_DIVF_SHIFT	0
+#define SOCFPGA_PLL_DIVQ_MASK		0x003F0000
+#define SOCFPGA_PLL_DIVQ_SHIFT	16
+#define SOCFGPA_MAX_PARENTS	5
+
+#define SOCFPGA_MAIN_PLL_CLK		"main_pll"
+#define SOCFPGA_PERIP_PLL_CLK		"periph_pll"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+void __iomem *clk_mgr_a10_base_addr;
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	unsigned long divf, divq, reg;
+	unsigned long long vco_freq;
+
+	/* read VCO1 reg for numerator and denominator */
+	reg = readl(socfpgaclk->hw.reg + 0x4);
+	divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
+	divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
+	vco_freq = (unsigned long long)parent_rate * (divf + 1);
+	do_div(vco_freq, (1 + divq));
+	return (unsigned long)vco_freq;
+}
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+
+	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+		CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.get_parent = clk_pll_get_parent,
+};
+
+static struct __init clk * __socfpga_pll_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct socfpga_pll *pll_clk;
+	const char *clk_name = node->name;
+	const char *parent_name[SOCFGPA_MAX_PARENTS];
+	struct clk_init_data init;
+	struct device_node *clkmgr_np;
+	int rc;
+	int i = 0;
+
+	of_property_read_u32(node, "reg", &reg);
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return NULL;
+
+	clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
+	clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0);
+	BUG_ON(!clk_mgr_a10_base_addr);
+	pll_clk->hw.reg = clk_mgr_a10_base_addr + reg;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+
+	while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] =
+			of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+	init.num_parents = i;
+	init.parent_names = parent_name;
+	pll_clk->hw.hw.init = &init;
+
+	pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
+	clk_pll_ops.enable = clk_gate_ops.enable;
+	clk_pll_ops.disable = clk_gate_ops.disable;
+
+	clk = clk_register(NULL, &pll_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return NULL;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return clk;
+}
+
+void __init socfpga_a10_pll_init(struct device_node *node)
+{
+	__socfpga_pll_init(node, &clk_pll_ops);
+}
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
index de6da95..8f26b52 100644
--- a/drivers/clk/socfpga/clk-pll.c
+++ b/drivers/clk/socfpga/clk-pll.c
@@ -92,7 +92,6 @@
 	struct clk_init_data init;
 	struct device_node *clkmgr_np;
 	int rc;
-	int i = 0;
 
 	of_property_read_u32(node, "reg", &reg);
 
@@ -111,11 +110,7 @@
 	init.ops = ops;
 	init.flags = 0;
 
-	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
-			of_clk_get_parent_name(node, i)) != NULL)
-		i++;
-
-	init.num_parents = i;
+	init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
 	init.parent_names = parent_name;
 	pll_clk->hw.hw.init = &init;
 
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 43db947..7564d2e 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -24,4 +24,9 @@
 CLK_OF_DECLARE(socfpga_pll_clk, "altr,socfpga-pll-clock", socfpga_pll_init);
 CLK_OF_DECLARE(socfpga_perip_clk, "altr,socfpga-perip-clk", socfpga_periph_init);
 CLK_OF_DECLARE(socfpga_gate_clk, "altr,socfpga-gate-clk", socfpga_gate_init);
-
+CLK_OF_DECLARE(socfpga_a10_pll_clk, "altr,socfpga-a10-pll-clock",
+	       socfpga_a10_pll_init);
+CLK_OF_DECLARE(socfpga_a10_perip_clk, "altr,socfpga-a10-perip-clk",
+	       socfpga_a10_periph_init);
+CLK_OF_DECLARE(socfpga_a10_gate_clk, "altr,socfpga-a10-gate-clk",
+	       socfpga_a10_gate_init);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index d291f60..603973a 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -26,14 +26,22 @@
 #define CLKMGR_L4SRC		0x70
 #define CLKMGR_PERPLL_SRC	0xAC
 
-#define SOCFPGA_MAX_PARENTS		3
+#define SOCFPGA_MAX_PARENTS		5
 #define div_mask(width) ((1 << (width)) - 1)
 
+#define streq(a, b) (strcmp((a), (b)) == 0)
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
+
 extern void __iomem *clk_mgr_base_addr;
+extern void __iomem *clk_mgr_a10_base_addr;
 
 void __init socfpga_pll_init(struct device_node *node);
 void __init socfpga_periph_init(struct device_node *node);
 void __init socfpga_gate_init(struct device_node *node);
+void socfpga_a10_pll_init(struct device_node *node);
+void socfpga_a10_periph_init(struct device_node *node);
+void socfpga_a10_gate_init(struct device_node *node);
 
 struct socfpga_pll {
 	struct clk_gate	hw;
@@ -44,6 +52,7 @@
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	struct regmap *sys_mgr_base_addr;
 	u32 width;	/* only valid if div_reg != 0 */
 	u32 shift;	/* only valid if div_reg != 0 */
 	u32 clk_phase[2];
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index bf12a25..657ca14 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -116,7 +116,7 @@
 	return *prate / div;
 }
 
-unsigned long flexgen_recalc_rate(struct clk_hw *hw,
+static unsigned long flexgen_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct flexgen *flexgen = to_flexgen(hw);
@@ -174,7 +174,7 @@
 	.set_rate = flexgen_set_rate,
 };
 
-struct clk *clk_register_flexgen(const char *name,
+static struct clk *clk_register_flexgen(const char *name,
 				const char **parent_names, u8 num_parents,
 				void __iomem *reg, spinlock_t *lock, u32 idx,
 				unsigned long flexgen_flags) {
@@ -245,7 +245,7 @@
 	const char **parents;
 	int nparents, i;
 
-	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	nparents = of_clk_get_parent_count(np);
 	if (WARN_ON(nparents <= 0))
 		return NULL;
 
@@ -260,7 +260,7 @@
 	return parents;
 }
 
-void __init st_of_flexgen_setup(struct device_node *np)
+static void __init st_of_flexgen_setup(struct device_node *np)
 {
 	struct device_node *pnode;
 	void __iomem *reg;
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index a917c4c..e94197f 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -492,7 +492,7 @@
 	return !!npda;
 }
 
-int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
 			   unsigned long *rate)
 {
 	unsigned long nd = fs->ndiv + 16; /* ndiv value */
@@ -519,7 +519,7 @@
 	return rate;
 }
 
-int clk_fs660c32_vco_get_params(unsigned long input,
+static int clk_fs660c32_vco_get_params(unsigned long input,
 				unsigned long output, struct stm_fs *fs)
 {
 /* Formula
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index fdcff10..4fbe6e0 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -26,7 +26,7 @@
 	const char **parents;
 	int nparents, i;
 
-	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	nparents = of_clk_get_parent_count(np);
 	if (WARN_ON(nparents <= 0))
 		return ERR_PTR(-EINVAL);
 
@@ -131,7 +131,7 @@
 	return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
 }
 
-u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+static u8 clkgena_divmux_get_parent(struct clk_hw *hw)
 {
 	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
 	struct clk_hw *mux_hw = &genamux->mux.hw;
@@ -168,7 +168,7 @@
 	return 0;
 }
 
-unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+static unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
@@ -215,7 +215,7 @@
 /**
  * clk_register_genamux - register a genamux clock with the clock framework
  */
-struct clk *clk_register_genamux(const char *name,
+static struct clk *clk_register_genamux(const char *name,
 				const char **parent_names, u8 num_parents,
 				void __iomem *reg,
 				const struct clkgena_divmux_data *muxdata,
@@ -385,7 +385,7 @@
 	return reg;
 }
 
-void __init st_of_clkgena_divmux_setup(struct device_node *np)
+static void __init st_of_clkgena_divmux_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	const struct clkgena_divmux_data *data;
@@ -485,7 +485,7 @@
 	{}
 };
 
-void __init st_of_clkgena_prediv_setup(struct device_node *np)
+static void __init st_of_clkgena_prediv_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	void __iomem *reg;
@@ -622,7 +622,7 @@
 	{}
 };
 
-void __init st_of_clkgen_mux_setup(struct device_node *np)
+static void __init st_of_clkgen_mux_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	struct clk *clk;
@@ -699,7 +699,7 @@
 	{}
 };
 
-void __init st_of_clkgen_vcc_setup(struct device_node *np)
+static void __init st_of_clkgen_vcc_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	void __iomem *reg;
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index d204ba8..1065322 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -270,7 +270,7 @@
 	return !poweroff;
 }
 
-unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
+static unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -297,7 +297,7 @@
 
 }
 
-unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
+static unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -321,7 +321,7 @@
 	return rate;
 }
 
-unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
+static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -343,7 +343,7 @@
 	return rate;
 }
 
-unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
+static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -544,7 +544,7 @@
 	       "st,clkgena-plls-c65", clkgena_c65_pll_setup);
 
 static struct clk * __init clkgen_odf_register(const char *parent_name,
-					       void * __iomem reg,
+					       void __iomem *reg,
 					       struct clkgen_pll_data *pll_data,
 					       int odf,
 					       spinlock_t *odf_lock,
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index d86bc46..19e543a 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -155,7 +155,7 @@
 	return 0;
 }
 
-const struct clk_ops atl_clk_ops = {
+static const struct clk_ops atl_clk_ops = {
 	.enable		= atl_clk_enable,
 	.disable	= atl_clk_disable,
 	.is_enabled	= atl_clk_is_enabled,
@@ -167,7 +167,7 @@
 static void __init of_dra7_atl_clock_setup(struct device_node *node)
 {
 	struct dra7_atl_desc *clk_hw = NULL;
-	struct clk_init_data init = { 0 };
+	struct clk_init_data init = { NULL };
 	const char **parent_names = NULL;
 	struct clk *clk;
 
@@ -252,6 +252,11 @@
 		}
 
 		clk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to get atl clock %d from provider\n",
+			       __func__, i);
+			return PTR_ERR(clk);
+		}
 
 		cdesc = to_atl_desc(__clk_get_hw(clk));
 		cdesc->cinfo = cinfo;
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 0ebe5c5..64bb5e8 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -122,14 +122,14 @@
 
 	if (i == CLK_MAX_MEMMAPS) {
 		pr_err("clk-provider not found for %s!\n", node->name);
-		return ERR_PTR(-ENOENT);
+		return IOMEM_ERR_PTR(-ENOENT);
 	}
 
 	reg->index = i;
 
 	if (of_property_read_u32_index(node, "reg", index, &val)) {
 		pr_err("%s must have reg[%d]!\n", node->name, index);
-		return ERR_PTR(-EINVAL);
+		return IOMEM_ERR_PTR(-EINVAL);
 	}
 
 	reg->offset = val;
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index 35fe108..b82ef07 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -32,7 +32,7 @@
 	int i;
 	int num_clks;
 
-	num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+	num_clks = of_clk_get_parent_count(node);
 
 	for (i = 0; i < num_clks; i++) {
 		clk = of_clk_get(node, i);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 11478a5..2aacf7a 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -177,7 +177,7 @@
 }
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
-void __iomem *_get_reg(u8 module, u16 offset)
+static void __iomem *_get_reg(u8 module, u16 offset)
 {
 	u32 reg;
 	struct clk_omap_reg *reg_setup;
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index ffcd8e0..730aa62 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -621,13 +621,13 @@
 
 		/* Check for hardwired audio_pll_clk1 */
 		if (is_audio_pll_clk1(freq)) {
-			freq = 0;
-			div = 0;
+			freq = NULL;
+			div = NULL;
 		} else {
 			/* Does the synthesizer have a FREQ register? */
 			v = readl_relaxed(freq);
 			if (!v)
-				freq = 0;
+				freq = NULL;
 		}
 		synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance,
 						 output_name, node->name,
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index 80069c3..4626b97 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -116,11 +116,12 @@
 	clk_register_clkdev(clk, NULL, "hdmi");
 	clk_register_clkdev(clk, "hdmi", "mcde");
 
-	clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
+	clk = clk_reg_prcmu_scalable("apeatclk", NULL, PRCMU_APEATCLK, 0,
+				     CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	clk_register_clkdev(clk, NULL, "apeat");
 
-	clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
-				CLK_IS_ROOT);
+	clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	clk_register_clkdev(clk, NULL, "apetrace");
 
 	clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 7b55ef8..e319ef9 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -166,8 +166,8 @@
 	clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
 	prcmu_clk[PRCMU_APEATCLK] = clk;
 
-	clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
-				CLK_IS_ROOT);
+	clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	prcmu_clk[PRCMU_APETRACECLK] = clk;
 
 	clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c
index c6e86a9..a96dd8e 100644
--- a/drivers/clk/versatile/clk-sp810.c
+++ b/drivers/clk/versatile/clk-sp810.c
@@ -135,7 +135,7 @@
 	return sp810->timerclken[clkspec->args[0]].clk;
 }
 
-void __init clk_sp810_of_setup(struct device_node *node)
+static void __init clk_sp810_of_setup(struct device_node *node)
 {
 	struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL);
 	const char *parent_names[2];
@@ -156,7 +156,7 @@
 			"timclk");
 	parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index);
 
-	if (parent_names[0] <= 0 || parent_names[1] <= 0) {
+	if (!parent_names[0] || !parent_names[1]) {
 		pr_warn("Failed to obtain parent clocks for SP810!\n");
 		return;
 	}
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 40cb113..de61438 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -85,22 +85,29 @@
 static DEFINE_SPINLOCK(dbgclk_lock);
 static DEFINE_SPINLOCK(aperclk_lock);
 
-static const char *armpll_parents[] __initdata = {"armpll_int", "ps_clk"};
-static const char *ddrpll_parents[] __initdata = {"ddrpll_int", "ps_clk"};
-static const char *iopll_parents[] __initdata = {"iopll_int", "ps_clk"};
+static const char *const armpll_parents[] __initconst = {"armpll_int",
+	"ps_clk"};
+static const char *const ddrpll_parents[] __initconst = {"ddrpll_int",
+	"ps_clk"};
+static const char *const iopll_parents[] __initconst = {"iopll_int",
+	"ps_clk"};
 static const char *gem0_mux_parents[] __initdata = {"gem0_div1", "dummy_name"};
 static const char *gem1_mux_parents[] __initdata = {"gem1_div1", "dummy_name"};
-static const char *can0_mio_mux2_parents[] __initdata = {"can0_gate",
+static const char *const can0_mio_mux2_parents[] __initconst = {"can0_gate",
 	"can0_mio_mux"};
-static const char *can1_mio_mux2_parents[] __initdata = {"can1_gate",
+static const char *const can1_mio_mux2_parents[] __initconst = {"can1_gate",
 	"can1_mio_mux"};
 static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div",
 	"dummy_name"};
 
-static const char *dbgtrc_emio_input_names[] __initdata = {"trace_emio_clk"};
-static const char *gem0_emio_input_names[] __initdata = {"gem0_emio_clk"};
-static const char *gem1_emio_input_names[] __initdata = {"gem1_emio_clk"};
-static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"};
+static const char *const dbgtrc_emio_input_names[] __initconst = {
+	"trace_emio_clk"};
+static const char *const gem0_emio_input_names[] __initconst = {
+	"gem0_emio_clk"};
+static const char *const gem1_emio_input_names[] __initconst = {
+	"gem1_emio_clk"};
+static const char *const swdt_ext_clk_input_names[] __initconst = {
+	"swdt_ext_clk"};
 
 static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
 		const char *clk_name, void __iomem *fclk_ctrl_reg,
diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
new file mode 100644
index 0000000..70ee383
--- /dev/null
+++ b/include/dt-bindings/clock/hi6220-clock.h
@@ -0,0 +1,173 @@
+/*
+ * 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 Hi6220 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		14
+#define HI6220_150M		15
+#define HI6220_PICOPHY_SRC	16
+#define HI6220_MMC0_SRC_SEL	17
+#define HI6220_MMC1_SRC_SEL	18
+#define HI6220_MMC2_SRC_SEL	19
+#define HI6220_VPU_CODEC	20
+#define HI6220_MMC0_SMP		21
+#define HI6220_MMC1_SMP		22
+#define HI6220_MMC2_SMP		23
+
+/* gate clocks */
+#define HI6220_WDT0_PCLK	24
+#define HI6220_WDT1_PCLK	25
+#define HI6220_WDT2_PCLK	26
+#define HI6220_TIMER0_PCLK	27
+#define HI6220_TIMER1_PCLK	28
+#define HI6220_TIMER2_PCLK	29
+#define HI6220_TIMER3_PCLK	30
+#define HI6220_TIMER4_PCLK	31
+#define HI6220_TIMER5_PCLK	32
+#define HI6220_TIMER6_PCLK	33
+#define HI6220_TIMER7_PCLK	34
+#define HI6220_TIMER8_PCLK	35
+#define HI6220_UART0_PCLK	36
+
+#define HI6220_AO_NR_CLKS	37
+
+/* clk in Hi6220 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_TSENSOR_CLK	22
+#define HI6220_MMU_CLK		23
+#define HI6220_HIFI_SEL		24
+#define HI6220_MMC0_SYSPLL	25
+#define HI6220_MMC1_SYSPLL	26
+#define HI6220_MMC2_SYSPLL	27
+#define HI6220_MMC0_SEL		28
+#define HI6220_MMC1_SEL		29
+#define HI6220_BBPPLL_SEL	30
+#define HI6220_MEDIA_PLL_SRC	31
+#define HI6220_MMC2_SEL		32
+#define HI6220_CS_ATB_SYSPLL	33
+
+/* mux clocks */
+#define HI6220_MMC0_SRC		34
+#define HI6220_MMC0_SMP_IN	35
+#define HI6220_MMC1_SRC		36
+#define HI6220_MMC1_SMP_IN	37
+#define HI6220_MMC2_SRC		38
+#define HI6220_MMC2_SMP_IN	39
+#define HI6220_HIFI_SRC		40
+#define HI6220_UART1_SRC	41
+#define HI6220_UART2_SRC	42
+#define HI6220_UART3_SRC	43
+#define HI6220_UART4_SRC	44
+#define HI6220_MMC0_MUX0	45
+#define HI6220_MMC1_MUX0	46
+#define HI6220_MMC2_MUX0	47
+#define HI6220_MMC0_MUX1	48
+#define HI6220_MMC1_MUX1	49
+#define HI6220_MMC2_MUX1	50
+
+/* divider clocks */
+#define HI6220_CLK_BUS		51
+#define HI6220_MMC0_DIV		52
+#define HI6220_MMC1_DIV		53
+#define HI6220_MMC2_DIV		54
+#define HI6220_HIFI_DIV		55
+#define HI6220_BBPPLL0_DIV	56
+#define HI6220_CS_DAPB		57
+#define HI6220_CS_ATB_DIV	58
+
+#define HI6220_SYS_NR_CLKS	59
+
+/* clk in Hi6220 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	14
+#define HI6220_1000_1200	15
+#define HI6220_1000_1440	16
+
+/* divider clocks */
+#define HI6220_CODEC_JPEG	17
+#define HI6220_ISP_SCLK_SRC	18
+#define HI6220_ISP_SCLK1	19
+#define HI6220_ADE_CORE_SRC	20
+#define HI6220_ADE_PIX_SRC	21
+#define HI6220_G3D_CLK		22
+#define HI6220_CODEC_VPU_SRC	23
+
+#define HI6220_MEDIA_NR_CLKS	24
+
+/* clk in Hi6220 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		6
+#define HI6220_DDRC_AXI1	7
+
+#define HI6220_POWER_NR_CLKS	8
+#endif
diff --git a/include/dt-bindings/clock/marvell,mmp2.h b/include/dt-bindings/clock/marvell,mmp2.h
index 591f7fb..7a51038 100644
--- a/include/dt-bindings/clock/marvell,mmp2.h
+++ b/include/dt-bindings/clock/marvell,mmp2.h
@@ -48,6 +48,7 @@
 #define MMP2_CLK_SSP1			78
 #define MMP2_CLK_SSP2			79
 #define MMP2_CLK_SSP3			80
+#define MMP2_CLK_TIMER			81
 
 /* axi periphrals */
 #define MMP2_CLK_SDH0			101
diff --git a/include/dt-bindings/clock/marvell,pxa168.h b/include/dt-bindings/clock/marvell,pxa168.h
index 79630b9..3e45bdf 100644
--- a/include/dt-bindings/clock/marvell,pxa168.h
+++ b/include/dt-bindings/clock/marvell,pxa168.h
@@ -18,7 +18,9 @@
 #define PXA168_CLK_PLL1_13_1_5		18
 #define PXA168_CLK_PLL1_2_1_5		19
 #define PXA168_CLK_PLL1_3_16		20
+#define PXA168_CLK_PLL1_192		21
 #define PXA168_CLK_UART_PLL		27
+#define PXA168_CLK_USB_PLL		28
 
 /* apb periphrals */
 #define PXA168_CLK_TWSI0		60
@@ -40,6 +42,7 @@
 #define PXA168_CLK_SSP2			76
 #define PXA168_CLK_SSP3			77
 #define PXA168_CLK_SSP4			78
+#define PXA168_CLK_TIMER		79
 
 /* axi periphrals */
 #define PXA168_CLK_DFC			100
diff --git a/include/dt-bindings/clock/marvell,pxa1928.h b/include/dt-bindings/clock/marvell,pxa1928.h
new file mode 100644
index 0000000..d4f2e18
--- /dev/null
+++ b/include/dt-bindings/clock/marvell,pxa1928.h
@@ -0,0 +1,57 @@
+#ifndef __DTS_MARVELL_PXA1928_CLOCK_H
+#define __DTS_MARVELL_PXA1928_CLOCK_H
+
+/*
+ * Clock ID values here correspond to the control register offset/4.
+ */
+
+/* apb peripherals */
+#define PXA1928_CLK_RTC			0x00
+#define PXA1928_CLK_TWSI0		0x01
+#define PXA1928_CLK_TWSI1		0x02
+#define PXA1928_CLK_TWSI2		0x03
+#define PXA1928_CLK_TWSI3		0x04
+#define PXA1928_CLK_OWIRE		0x05
+#define PXA1928_CLK_KPC			0x06
+#define PXA1928_CLK_TB_ROTARY		0x07
+#define PXA1928_CLK_SW_JTAG		0x08
+#define PXA1928_CLK_TIMER1		0x09
+#define PXA1928_CLK_UART0		0x0b
+#define PXA1928_CLK_UART1		0x0c
+#define PXA1928_CLK_UART2		0x0d
+#define PXA1928_CLK_GPIO		0x0e
+#define PXA1928_CLK_PWM0		0x0f
+#define PXA1928_CLK_PWM1		0x10
+#define PXA1928_CLK_PWM2		0x11
+#define PXA1928_CLK_PWM3		0x12
+#define PXA1928_CLK_SSP0		0x13
+#define PXA1928_CLK_SSP1		0x14
+#define PXA1928_CLK_SSP2		0x15
+
+#define PXA1928_CLK_TWSI4		0x1f
+#define PXA1928_CLK_TWSI5		0x20
+#define PXA1928_CLK_UART3		0x22
+#define PXA1928_CLK_THSENS_GLOB		0x24
+#define PXA1928_CLK_THSENS_CPU		0x26
+#define PXA1928_CLK_THSENS_VPU		0x27
+#define PXA1928_CLK_THSENS_GC		0x28
+#define PXA1928_APBC_NR_CLKS		0x30
+
+
+/* axi peripherals */
+#define PXA1928_CLK_SDH0		0x15
+#define PXA1928_CLK_SDH1		0x16
+#define PXA1928_CLK_USB			0x17
+#define PXA1928_CLK_NAND		0x18
+#define PXA1928_CLK_DMA			0x19
+
+#define PXA1928_CLK_SDH2		0x3a
+#define PXA1928_CLK_SDH3		0x3b
+#define PXA1928_CLK_HSIC		0x3e
+#define PXA1928_CLK_SDH4		0x57
+#define PXA1928_CLK_GC3D		0x5d
+#define PXA1928_CLK_GC2D		0x5f
+
+#define PXA1928_APMU_NR_CLKS		0x60
+
+#endif
diff --git a/include/dt-bindings/clock/marvell,pxa910.h b/include/dt-bindings/clock/marvell,pxa910.h
index 719cffb..135082a 100644
--- a/include/dt-bindings/clock/marvell,pxa910.h
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -18,7 +18,9 @@
 #define PXA910_CLK_PLL1_13_1_5		18
 #define PXA910_CLK_PLL1_2_1_5		19
 #define PXA910_CLK_PLL1_3_16		20
+#define PXA910_CLK_PLL1_192		21
 #define PXA910_CLK_UART_PLL		27
+#define PXA910_CLK_USB_PLL		28
 
 /* apb periphrals */
 #define PXA910_CLK_TWSI0		60
@@ -37,6 +39,8 @@
 #define PXA910_CLK_UART2		73
 #define PXA910_CLK_SSP0			74
 #define PXA910_CLK_SSP1			75
+#define PXA910_CLK_TIMER0		76
+#define PXA910_CLK_TIMER1		77
 
 /* axi periphrals */
 #define PXA910_CLK_DFC			100
diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h
new file mode 100644
index 0000000..bd2720d
--- /dev/null
+++ b/include/dt-bindings/clock/meson8b-clkc.h
@@ -0,0 +1,25 @@
+/*
+ * Meson8b clock tree IDs
+ */
+
+#ifndef __MESON8B_CLKC_H
+#define __MESON8B_CLKC_H
+
+#define CLKID_UNUSED		0
+#define CLKID_XTAL		1
+#define CLKID_PLL_FIXED		2
+#define CLKID_PLL_VID		3
+#define CLKID_PLL_SYS		4
+#define CLKID_FCLK_DIV2		5
+#define CLKID_FCLK_DIV3		6
+#define CLKID_FCLK_DIV4		7
+#define CLKID_FCLK_DIV5		8
+#define CLKID_FCLK_DIV7		9
+#define CLKID_CLK81		10
+#define CLKID_MALI		11
+#define CLKID_CPUCLK		12
+#define CLKID_ZERO		13
+
+#define CLK_NR_CLKS		(CLKID_ZERO + 1)
+
+#endif /* __MESON8B_CLKC_H */
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
new file mode 100644
index 0000000..6dac6c0
--- /dev/null
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8135_H
+#define _DT_BINDINGS_CLK_MT8135_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_DSI0_LNTC_DSICLK	1
+#define CLK_TOP_HDMITX_CLKDIG_CTS	2
+#define CLK_TOP_CLKPH_MCK		3
+#define CLK_TOP_CPUM_TCK_IN		4
+#define CLK_TOP_MAINPLL_806M		5
+#define CLK_TOP_MAINPLL_537P3M		6
+#define CLK_TOP_MAINPLL_322P4M		7
+#define CLK_TOP_MAINPLL_230P3M		8
+#define CLK_TOP_UNIVPLL_624M		9
+#define CLK_TOP_UNIVPLL_416M		10
+#define CLK_TOP_UNIVPLL_249P6M		11
+#define CLK_TOP_UNIVPLL_178P3M		12
+#define CLK_TOP_UNIVPLL_48M		13
+#define CLK_TOP_MMPLL_D2		14
+#define CLK_TOP_MMPLL_D3		15
+#define CLK_TOP_MMPLL_D5		16
+#define CLK_TOP_MMPLL_D7		17
+#define CLK_TOP_MMPLL_D4		18
+#define CLK_TOP_MMPLL_D6		19
+#define CLK_TOP_SYSPLL_D2		20
+#define CLK_TOP_SYSPLL_D4		21
+#define CLK_TOP_SYSPLL_D6		22
+#define CLK_TOP_SYSPLL_D8		23
+#define CLK_TOP_SYSPLL_D10		24
+#define CLK_TOP_SYSPLL_D12		25
+#define CLK_TOP_SYSPLL_D16		26
+#define CLK_TOP_SYSPLL_D24		27
+#define CLK_TOP_SYSPLL_D3		28
+#define CLK_TOP_SYSPLL_D2P5		29
+#define CLK_TOP_SYSPLL_D5		30
+#define CLK_TOP_SYSPLL_D3P5		31
+#define CLK_TOP_UNIVPLL1_D2		32
+#define CLK_TOP_UNIVPLL1_D4		33
+#define CLK_TOP_UNIVPLL1_D6		34
+#define CLK_TOP_UNIVPLL1_D8		35
+#define CLK_TOP_UNIVPLL1_D10		36
+#define CLK_TOP_UNIVPLL2_D2		37
+#define CLK_TOP_UNIVPLL2_D4		38
+#define CLK_TOP_UNIVPLL2_D6		39
+#define CLK_TOP_UNIVPLL2_D8		40
+#define CLK_TOP_UNIVPLL_D3		41
+#define CLK_TOP_UNIVPLL_D5		42
+#define CLK_TOP_UNIVPLL_D7		43
+#define CLK_TOP_UNIVPLL_D10		44
+#define CLK_TOP_UNIVPLL_D26		45
+#define CLK_TOP_APLL			46
+#define CLK_TOP_APLL_D4			47
+#define CLK_TOP_APLL_D8			48
+#define CLK_TOP_APLL_D16		49
+#define CLK_TOP_APLL_D24		50
+#define CLK_TOP_LVDSPLL_D2		51
+#define CLK_TOP_LVDSPLL_D4		52
+#define CLK_TOP_LVDSPLL_D8		53
+#define CLK_TOP_LVDSTX_CLKDIG_CT	54
+#define CLK_TOP_VPLL_DPIX		55
+#define CLK_TOP_TVHDMI_H		56
+#define CLK_TOP_HDMITX_CLKDIG_D2	57
+#define CLK_TOP_HDMITX_CLKDIG_D3	58
+#define CLK_TOP_TVHDMI_D2		59
+#define CLK_TOP_TVHDMI_D4		60
+#define CLK_TOP_MEMPLL_MCK_D4		61
+#define CLK_TOP_AXI_SEL			62
+#define CLK_TOP_SMI_SEL			63
+#define CLK_TOP_MFG_SEL			64
+#define CLK_TOP_IRDA_SEL		65
+#define CLK_TOP_CAM_SEL			66
+#define CLK_TOP_AUD_INTBUS_SEL		67
+#define CLK_TOP_JPG_SEL			68
+#define CLK_TOP_DISP_SEL		69
+#define CLK_TOP_MSDC30_1_SEL		70
+#define CLK_TOP_MSDC30_2_SEL		71
+#define CLK_TOP_MSDC30_3_SEL		72
+#define CLK_TOP_MSDC30_4_SEL		73
+#define CLK_TOP_USB20_SEL		74
+#define CLK_TOP_VENC_SEL		75
+#define CLK_TOP_SPI_SEL			76
+#define CLK_TOP_UART_SEL		77
+#define CLK_TOP_MEM_SEL			78
+#define CLK_TOP_CAMTG_SEL		79
+#define CLK_TOP_AUDIO_SEL		80
+#define CLK_TOP_FIX_SEL			81
+#define CLK_TOP_VDEC_SEL		82
+#define CLK_TOP_DDRPHYCFG_SEL		83
+#define CLK_TOP_DPILVDS_SEL		84
+#define CLK_TOP_PMICSPI_SEL		85
+#define CLK_TOP_MSDC30_0_SEL		86
+#define CLK_TOP_SMI_MFG_AS_SEL		87
+#define CLK_TOP_GCPU_SEL		88
+#define CLK_TOP_DPI1_SEL		89
+#define CLK_TOP_CCI_SEL			90
+#define CLK_TOP_APLL_SEL		91
+#define CLK_TOP_HDMIPLL_SEL		92
+#define CLK_TOP_NR_CLK			93
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMPLL1		1
+#define CLK_APMIXED_ARMPLL2		2
+#define CLK_APMIXED_MAINPLL		3
+#define CLK_APMIXED_UNIVPLL		4
+#define CLK_APMIXED_MMPLL		5
+#define CLK_APMIXED_MSDCPLL		6
+#define CLK_APMIXED_TVDPLL		7
+#define CLK_APMIXED_LVDSPLL		8
+#define CLK_APMIXED_AUDPLL		9
+#define CLK_APMIXED_VDECPLL		10
+#define CLK_APMIXED_NR_CLK		11
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_PMIC_WRAP		1
+#define CLK_INFRA_PMICSPI		2
+#define CLK_INFRA_CCIF1_AP_CTRL		3
+#define CLK_INFRA_CCIF0_AP_CTRL		4
+#define CLK_INFRA_KP			5
+#define CLK_INFRA_CPUM			6
+#define CLK_INFRA_M4U			7
+#define CLK_INFRA_MFGAXI		8
+#define CLK_INFRA_DEVAPC		9
+#define CLK_INFRA_AUDIO			10
+#define CLK_INFRA_MFG_BUS		11
+#define CLK_INFRA_SMI			12
+#define CLK_INFRA_DBGCLK		13
+#define CLK_INFRA_NR_CLK		14
+
+/* PERI_SYS */
+
+#define CLK_PERI_I2C5			1
+#define CLK_PERI_I2C4			2
+#define CLK_PERI_I2C3			3
+#define CLK_PERI_I2C2			4
+#define CLK_PERI_I2C1			5
+#define CLK_PERI_I2C0			6
+#define CLK_PERI_UART3			7
+#define CLK_PERI_UART2			8
+#define CLK_PERI_UART1			9
+#define CLK_PERI_UART0			10
+#define CLK_PERI_IRDA			11
+#define CLK_PERI_NLI			12
+#define CLK_PERI_MD_HIF			13
+#define CLK_PERI_AP_HIF			14
+#define CLK_PERI_MSDC30_3		15
+#define CLK_PERI_MSDC30_2		16
+#define CLK_PERI_MSDC30_1		17
+#define CLK_PERI_MSDC20_2		18
+#define CLK_PERI_MSDC20_1		19
+#define CLK_PERI_AP_DMA			20
+#define CLK_PERI_USB1			21
+#define CLK_PERI_USB0			22
+#define CLK_PERI_PWM			23
+#define CLK_PERI_PWM7			24
+#define CLK_PERI_PWM6			25
+#define CLK_PERI_PWM5			26
+#define CLK_PERI_PWM4			27
+#define CLK_PERI_PWM3			28
+#define CLK_PERI_PWM2			29
+#define CLK_PERI_PWM1			30
+#define CLK_PERI_THERM			31
+#define CLK_PERI_NFI			32
+#define CLK_PERI_USBSLV			33
+#define CLK_PERI_USB1_MCU		34
+#define CLK_PERI_USB0_MCU		35
+#define CLK_PERI_GCPU			36
+#define CLK_PERI_FHCTL			37
+#define CLK_PERI_SPI1			38
+#define CLK_PERI_AUXADC			39
+#define CLK_PERI_PERI_PWRAP		40
+#define CLK_PERI_I2C6			41
+#define CLK_PERI_UART0_SEL		42
+#define CLK_PERI_UART1_SEL		43
+#define CLK_PERI_UART2_SEL		44
+#define CLK_PERI_UART3_SEL		45
+#define CLK_PERI_NR_CLK			46
+
+#endif /* _DT_BINDINGS_CLK_MT8135_H */
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
new file mode 100644
index 0000000..4ad76ed
--- /dev/null
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8173_H
+#define _DT_BINDINGS_CLK_MT8173_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_CLKPH_MCK_O		1
+#define CLK_TOP_DPI			2
+#define CLK_TOP_USB_SYSPLL_125M		3
+#define CLK_TOP_HDMITX_DIG_CTS		4
+#define CLK_TOP_ARMCA7PLL_754M		5
+#define CLK_TOP_ARMCA7PLL_502M		6
+#define CLK_TOP_MAIN_H546M		7
+#define CLK_TOP_MAIN_H364M		8
+#define CLK_TOP_MAIN_H218P4M		9
+#define CLK_TOP_MAIN_H156M		10
+#define CLK_TOP_TVDPLL_445P5M		11
+#define CLK_TOP_TVDPLL_594M		12
+#define CLK_TOP_UNIV_624M		13
+#define CLK_TOP_UNIV_416M		14
+#define CLK_TOP_UNIV_249P6M		15
+#define CLK_TOP_UNIV_178P3M		16
+#define CLK_TOP_UNIV_48M		17
+#define CLK_TOP_CLKRTC_EXT		18
+#define CLK_TOP_CLKRTC_INT		19
+#define CLK_TOP_FPC			20
+#define CLK_TOP_HDMITXPLL_D2		21
+#define CLK_TOP_HDMITXPLL_D3		22
+#define CLK_TOP_ARMCA7PLL_D2		23
+#define CLK_TOP_ARMCA7PLL_D3		24
+#define CLK_TOP_APLL1			25
+#define CLK_TOP_APLL2			26
+#define CLK_TOP_DMPLL			27
+#define CLK_TOP_DMPLL_D2		28
+#define CLK_TOP_DMPLL_D4		29
+#define CLK_TOP_DMPLL_D8		30
+#define CLK_TOP_DMPLL_D16		31
+#define CLK_TOP_LVDSPLL_D2		32
+#define CLK_TOP_LVDSPLL_D4		33
+#define CLK_TOP_LVDSPLL_D8		34
+#define CLK_TOP_MMPLL			35
+#define CLK_TOP_MMPLL_D2		36
+#define CLK_TOP_MSDCPLL			37
+#define CLK_TOP_MSDCPLL_D2		38
+#define CLK_TOP_MSDCPLL_D4		39
+#define CLK_TOP_MSDCPLL2		40
+#define CLK_TOP_MSDCPLL2_D2		41
+#define CLK_TOP_MSDCPLL2_D4		42
+#define CLK_TOP_SYSPLL_D2		43
+#define CLK_TOP_SYSPLL1_D2		44
+#define CLK_TOP_SYSPLL1_D4		45
+#define CLK_TOP_SYSPLL1_D8		46
+#define CLK_TOP_SYSPLL1_D16		47
+#define CLK_TOP_SYSPLL_D3		48
+#define CLK_TOP_SYSPLL2_D2		49
+#define CLK_TOP_SYSPLL2_D4		50
+#define CLK_TOP_SYSPLL_D5		51
+#define CLK_TOP_SYSPLL3_D2		52
+#define CLK_TOP_SYSPLL3_D4		53
+#define CLK_TOP_SYSPLL_D7		54
+#define CLK_TOP_SYSPLL4_D2		55
+#define CLK_TOP_SYSPLL4_D4		56
+#define CLK_TOP_TVDPLL			57
+#define CLK_TOP_TVDPLL_D2		58
+#define CLK_TOP_TVDPLL_D4		59
+#define CLK_TOP_TVDPLL_D8		60
+#define CLK_TOP_TVDPLL_D16		61
+#define CLK_TOP_UNIVPLL_D2		62
+#define CLK_TOP_UNIVPLL1_D2		63
+#define CLK_TOP_UNIVPLL1_D4		64
+#define CLK_TOP_UNIVPLL1_D8		65
+#define CLK_TOP_UNIVPLL_D3		66
+#define CLK_TOP_UNIVPLL2_D2		67
+#define CLK_TOP_UNIVPLL2_D4		68
+#define CLK_TOP_UNIVPLL2_D8		69
+#define CLK_TOP_UNIVPLL_D5		70
+#define CLK_TOP_UNIVPLL3_D2		71
+#define CLK_TOP_UNIVPLL3_D4		72
+#define CLK_TOP_UNIVPLL3_D8		73
+#define CLK_TOP_UNIVPLL_D7		74
+#define CLK_TOP_UNIVPLL_D26		75
+#define CLK_TOP_UNIVPLL_D52		76
+#define CLK_TOP_VCODECPLL		77
+#define CLK_TOP_VCODECPLL_370P5		78
+#define CLK_TOP_VENCPLL			79
+#define CLK_TOP_VENCPLL_D2		80
+#define CLK_TOP_VENCPLL_D4		81
+#define CLK_TOP_AXI_SEL			82
+#define CLK_TOP_MEM_SEL			83
+#define CLK_TOP_DDRPHYCFG_SEL		84
+#define CLK_TOP_MM_SEL			85
+#define CLK_TOP_PWM_SEL			86
+#define CLK_TOP_VDEC_SEL		87
+#define CLK_TOP_VENC_SEL		88
+#define CLK_TOP_MFG_SEL			89
+#define CLK_TOP_CAMTG_SEL		90
+#define CLK_TOP_UART_SEL		91
+#define CLK_TOP_SPI_SEL			92
+#define CLK_TOP_USB20_SEL		93
+#define CLK_TOP_USB30_SEL		94
+#define CLK_TOP_MSDC50_0_H_SEL		95
+#define CLK_TOP_MSDC50_0_SEL		96
+#define CLK_TOP_MSDC30_1_SEL		97
+#define CLK_TOP_MSDC30_2_SEL		98
+#define CLK_TOP_MSDC30_3_SEL		99
+#define CLK_TOP_AUDIO_SEL		100
+#define CLK_TOP_AUD_INTBUS_SEL		101
+#define CLK_TOP_PMICSPI_SEL		102
+#define CLK_TOP_SCP_SEL			103
+#define CLK_TOP_ATB_SEL			104
+#define CLK_TOP_VENC_LT_SEL		105
+#define CLK_TOP_DPI0_SEL		106
+#define CLK_TOP_IRDA_SEL		107
+#define CLK_TOP_CCI400_SEL		108
+#define CLK_TOP_AUD_1_SEL		109
+#define CLK_TOP_AUD_2_SEL		110
+#define CLK_TOP_MEM_MFG_IN_SEL		111
+#define CLK_TOP_AXI_MFG_IN_SEL		112
+#define CLK_TOP_SCAM_SEL		113
+#define CLK_TOP_SPINFI_IFR_SEL		114
+#define CLK_TOP_HDMI_SEL		115
+#define CLK_TOP_DPILVDS_SEL		116
+#define CLK_TOP_MSDC50_2_H_SEL		117
+#define CLK_TOP_HDCP_SEL		118
+#define CLK_TOP_HDCP_24M_SEL		119
+#define CLK_TOP_RTC_SEL			120
+#define CLK_TOP_APLL1_DIV0		121
+#define CLK_TOP_APLL1_DIV1		122
+#define CLK_TOP_APLL1_DIV2		123
+#define CLK_TOP_APLL1_DIV3		124
+#define CLK_TOP_APLL1_DIV4		125
+#define CLK_TOP_APLL1_DIV5		126
+#define CLK_TOP_APLL2_DIV0		127
+#define CLK_TOP_APLL2_DIV1		128
+#define CLK_TOP_APLL2_DIV2		129
+#define CLK_TOP_APLL2_DIV3		130
+#define CLK_TOP_APLL2_DIV4		131
+#define CLK_TOP_APLL2_DIV5		132
+#define CLK_TOP_I2S0_M_SEL		133
+#define CLK_TOP_I2S1_M_SEL		134
+#define CLK_TOP_I2S2_M_SEL		135
+#define CLK_TOP_I2S3_M_SEL		136
+#define CLK_TOP_I2S3_B_SEL		137
+#define CLK_TOP_NR_CLK			138
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMCA15PLL	1
+#define CLK_APMIXED_ARMCA7PLL	2
+#define CLK_APMIXED_MAINPLL		3
+#define CLK_APMIXED_UNIVPLL		4
+#define CLK_APMIXED_MMPLL		5
+#define CLK_APMIXED_MSDCPLL		6
+#define CLK_APMIXED_VENCPLL		7
+#define CLK_APMIXED_TVDPLL		8
+#define CLK_APMIXED_MPLL		9
+#define CLK_APMIXED_VCODECPLL		10
+#define CLK_APMIXED_APLL1		11
+#define CLK_APMIXED_APLL2		12
+#define CLK_APMIXED_LVDSPLL		13
+#define CLK_APMIXED_MSDCPLL2		14
+#define CLK_APMIXED_NR_CLK		15
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_DBGCLK		1
+#define CLK_INFRA_SMI			2
+#define CLK_INFRA_AUDIO			3
+#define CLK_INFRA_GCE			4
+#define CLK_INFRA_L2C_SRAM		5
+#define CLK_INFRA_M4U			6
+#define CLK_INFRA_CPUM			7
+#define CLK_INFRA_KP			8
+#define CLK_INFRA_CEC			9
+#define CLK_INFRA_PMICSPI		10
+#define CLK_INFRA_PMICWRAP		11
+#define CLK_INFRA_NR_CLK		12
+
+/* PERI_SYS */
+
+#define CLK_PERI_NFI			1
+#define CLK_PERI_THERM			2
+#define CLK_PERI_PWM1			3
+#define CLK_PERI_PWM2			4
+#define CLK_PERI_PWM3			5
+#define CLK_PERI_PWM4			6
+#define CLK_PERI_PWM5			7
+#define CLK_PERI_PWM6			8
+#define CLK_PERI_PWM7			9
+#define CLK_PERI_PWM			10
+#define CLK_PERI_USB0			11
+#define CLK_PERI_USB1			12
+#define CLK_PERI_AP_DMA			13
+#define CLK_PERI_MSDC30_0		14
+#define CLK_PERI_MSDC30_1		15
+#define CLK_PERI_MSDC30_2		16
+#define CLK_PERI_MSDC30_3		17
+#define CLK_PERI_NLI_ARB		18
+#define CLK_PERI_IRDA			19
+#define CLK_PERI_UART0			20
+#define CLK_PERI_UART1			21
+#define CLK_PERI_UART2			22
+#define CLK_PERI_UART3			23
+#define CLK_PERI_I2C0			24
+#define CLK_PERI_I2C1			25
+#define CLK_PERI_I2C2			26
+#define CLK_PERI_I2C3			27
+#define CLK_PERI_I2C4			28
+#define CLK_PERI_AUXADC			29
+#define CLK_PERI_SPI0			30
+#define CLK_PERI_I2C5			31
+#define CLK_PERI_NFIECC			32
+#define CLK_PERI_SPI			33
+#define CLK_PERI_IRRX			34
+#define CLK_PERI_I2C6			35
+#define CLK_PERI_UART0_SEL		36
+#define CLK_PERI_UART1_SEL		37
+#define CLK_PERI_UART2_SEL		38
+#define CLK_PERI_UART3_SEL		39
+#define CLK_PERI_NR_CLK			40
+
+#endif /* _DT_BINDINGS_CLK_MT8173_H */
diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
new file mode 100644
index 0000000..1fb6295
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
+
+/* INFRACFG resets */
+#define MT8135_INFRA_EMI_REG_RST        0
+#define MT8135_INFRA_DRAMC0_A0_RST      1
+#define MT8135_INFRA_CCIF0_RST          2
+#define MT8135_INFRA_APCIRQ_EINT_RST    3
+#define MT8135_INFRA_APXGPT_RST         4
+#define MT8135_INFRA_SCPSYS_RST         5
+#define MT8135_INFRA_CCIF1_RST          6
+#define MT8135_INFRA_PMIC_WRAP_RST      7
+#define MT8135_INFRA_KP_RST             8
+#define MT8135_INFRA_EMI_RST            32
+#define MT8135_INFRA_DRAMC0_RST         34
+#define MT8135_INFRA_SMI_RST            35
+#define MT8135_INFRA_M4U_RST            36
+
+/*  PERICFG resets */
+#define MT8135_PERI_UART0_SW_RST        0
+#define MT8135_PERI_UART1_SW_RST        1
+#define MT8135_PERI_UART2_SW_RST        2
+#define MT8135_PERI_UART3_SW_RST        3
+#define MT8135_PERI_IRDA_SW_RST         4
+#define MT8135_PERI_PTP_SW_RST          5
+#define MT8135_PERI_AP_HIF_SW_RST       6
+#define MT8135_PERI_GPCU_SW_RST         7
+#define MT8135_PERI_MD_HIF_SW_RST       8
+#define MT8135_PERI_NLI_SW_RST          9
+#define MT8135_PERI_AUXADC_SW_RST       10
+#define MT8135_PERI_DMA_SW_RST          11
+#define MT8135_PERI_NFI_SW_RST          14
+#define MT8135_PERI_PWM_SW_RST          15
+#define MT8135_PERI_THERM_SW_RST        16
+#define MT8135_PERI_MSDC0_SW_RST        17
+#define MT8135_PERI_MSDC1_SW_RST        18
+#define MT8135_PERI_MSDC2_SW_RST        19
+#define MT8135_PERI_MSDC3_SW_RST        20
+#define MT8135_PERI_I2C0_SW_RST         22
+#define MT8135_PERI_I2C1_SW_RST         23
+#define MT8135_PERI_I2C2_SW_RST         24
+#define MT8135_PERI_I2C3_SW_RST         25
+#define MT8135_PERI_I2C4_SW_RST         26
+#define MT8135_PERI_I2C5_SW_RST         27
+#define MT8135_PERI_I2C6_SW_RST         28
+#define MT8135_PERI_USB_SW_RST          29
+#define MT8135_PERI_SPI1_SW_RST         33
+#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
new file mode 100644
index 0000000..9464b37
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
+
+/* INFRACFG resets */
+#define MT8173_INFRA_EMI_REG_RST        0
+#define MT8173_INFRA_DRAMC0_A0_RST      1
+#define MT8173_INFRA_APCIRQ_EINT_RST    3
+#define MT8173_INFRA_APXGPT_RST         4
+#define MT8173_INFRA_SCPSYS_RST         5
+#define MT8173_INFRA_KP_RST             6
+#define MT8173_INFRA_PMIC_WRAP_RST      7
+#define MT8173_INFRA_MPIP_RST           8
+#define MT8173_INFRA_CEC_RST            9
+#define MT8173_INFRA_EMI_RST            32
+#define MT8173_INFRA_DRAMC0_RST         34
+#define MT8173_INFRA_APMIXEDSYS_RST     35
+#define MT8173_INFRA_MIPI_DSI_RST       36
+#define MT8173_INFRA_TRNG_RST           37
+#define MT8173_INFRA_SYSIRQ_RST         38
+#define MT8173_INFRA_MIPI_CSI_RST       39
+#define MT8173_INFRA_GCE_FAXI_RST       40
+#define MT8173_INFRA_MMIOMMURST         47
+
+
+/*  PERICFG resets */
+#define MT8173_PERI_UART0_SW_RST        0
+#define MT8173_PERI_UART1_SW_RST        1
+#define MT8173_PERI_UART2_SW_RST        2
+#define MT8173_PERI_UART3_SW_RST        3
+#define MT8173_PERI_IRRX_SW_RST         4
+#define MT8173_PERI_PWM_SW_RST          8
+#define MT8173_PERI_AUXADC_SW_RST       10
+#define MT8173_PERI_DMA_SW_RST          11
+#define MT8173_PERI_I2C6_SW_RST         13
+#define MT8173_PERI_NFI_SW_RST          14
+#define MT8173_PERI_THERM_SW_RST        16
+#define MT8173_PERI_MSDC2_SW_RST        17
+#define MT8173_PERI_MSDC3_SW_RST        18
+#define MT8173_PERI_MSDC0_SW_RST        19
+#define MT8173_PERI_MSDC1_SW_RST        20
+#define MT8173_PERI_I2C0_SW_RST         22
+#define MT8173_PERI_I2C1_SW_RST         23
+#define MT8173_PERI_I2C2_SW_RST         24
+#define MT8173_PERI_I2C3_SW_RST         25
+#define MT8173_PERI_I2C4_SW_RST         26
+#define MT8173_PERI_HDMI_SW_RST         29
+#define MT8173_PERI_SPI0_SW_RST         33
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index df69531..4a943d1 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -209,7 +209,7 @@
 struct clk_init_data {
 	const char		*name;
 	const struct clk_ops	*ops;
-	const char		**parent_names;
+	const char		* const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 };
@@ -426,12 +426,14 @@
 extern const struct clk_ops clk_mux_ro_ops;
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
@@ -457,7 +459,7 @@
 	unsigned int	div;
 };
 
-extern struct clk_ops clk_fixed_factor_ops;
+extern const struct clk_ops clk_fixed_factor_ops;
 struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div);
@@ -518,7 +520,7 @@
 };
 
 struct clk *clk_register_composite(struct device *dev, const char *name,
-		const char **parent_names, int num_parents,
+		const char * const *parent_names, int num_parents,
 		struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 		struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 		struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
@@ -624,6 +626,8 @@
 				  void *data);
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
 int of_clk_get_parent_count(struct device_node *np);
+int of_clk_parent_fill(struct device_node *np, const char **parents,
+		       unsigned int size);
 const char *of_clk_get_parent_name(struct device_node *np, int index);
 
 void of_clk_init(const struct of_device_id *matches);