summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 18:21:28 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 18:21:28 -0800
commitece6267878aed4eadff766112f1079984315d8c8 (patch)
treed8d225e7d9d7fe2fda283791c7501ff38f21d564
parentd45187aaf0e256d23da2f7694a7826524499aa31 (diff)
parent3da834e3e5a4a5d26882955298b55a9ed37a00bc (diff)
downloadlinux-ece6267878aed4eadff766112f1079984315d8c8.tar.gz
Merge tag 'clk-for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk framework updates from Michael Turquette:
 "The clk framework and driver changes for 4.5 look pretty typical.  The
  bulk of the changes are to clk controller drivers, though some
  improvements to the core and some re-usable blocks/templates also
  received some love.

  In this past cycle the clk maintainers developed a good workflow for
  handling the common case of patch submissions containing a new
  drivers, new shared Device Tree header and a new Device Tree binding
  description.  This requires coordination with the Device Tree
  maintainers and with the architecture maintainers (typically the
  arm-soc tree in our case).

  This explains the increase in changes to include/dt-bindings/... and
  to Documentation/devicetree/bindings/clock/... coming from the clk
  tree.  The same commits can be expected to come through those trees on
  occasion, through the use of shared, immutable branches"

* tag 'clk-for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (125 commits)
  clk: remove duplicated COMMON_CLK_NXP record from clk/Kconfig
  clk: fix clk-gpio.c with optional clock= DT property
  clk: rockchip: fix section mismatches with new child-clocks
  clk: gpio: handle error codes for of_clk_get_parent_count()
  clk: gpio: fix memory leak
  clk: shmobile: r8a7795: Add SATA0 clock
  clk: bcm2835: Add PWM clock support
  clk: bcm2835: Support for clock parent selection
  clk: bcm2835: add a round up ability to the clock divisor
  clk: lpc32xx: add common clock framework driver
  clk: lpc18xx: add NXP specific COMMON_CLK_NXP configuration symbol
  dt-bindings: clock: add NXP LPC32xx clock list for consumers
  dt-bindings: clock: add description of LPC32xx USB clock controller
  dt-bindings: clock: add description of LPC32xx clock controller
  clk: rockchip: rk3036: include downstream muxes into fractional dividers
  clk: add flag for clocks that need to be enabled on rate changes
  clk: rockchip: Allow the RK3288 SPDIF clocks to change their parent
  clk: rockchip: include downstream muxes into fractional dividers
  clk: rockchip: handle mux dependency of fractional dividers
  clk: bcm2835: Add a driver for the auxiliary peripheral clock gates.
  ...
-rw-r--r--Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt31
-rw-r--r--Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt5
-rw-r--r--Documentation/devicetree/bindings/clock/cs2000-cp.txt22
-rw-r--r--Documentation/devicetree/bindings/clock/nvidia,tegra210-car.txt56
-rw-r--r--Documentation/devicetree/bindings/clock/nxp,lpc3220-clk.txt30
-rw-r--r--Documentation/devicetree/bindings/clock/nxp,lpc3220-usb-clk.txt22
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,mmcc.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt56
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt58
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt10
-rw-r--r--Documentation/devicetree/bindings/clock/tango4-clock.txt23
-rw-r--r--arch/arm/mach-omap2/clock.c4
-rw-r--r--drivers/clk/Kconfig12
-rw-r--r--drivers/clk/Makefile5
-rw-r--r--drivers/clk/at91/clk-slow.c29
-rw-r--r--drivers/clk/bcm/Kconfig10
-rw-r--r--drivers/clk/bcm/Makefile2
-rw-r--r--drivers/clk/bcm/clk-bcm2835-aux.c85
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c155
-rw-r--r--drivers/clk/bcm/clk-bcm63xx.c22
-rw-r--r--drivers/clk/clk-cs2000-cp.c510
-rw-r--r--drivers/clk/clk-divider.c9
-rw-r--r--drivers/clk/clk-gpio.c28
-rw-r--r--drivers/clk/clk-mux.c5
-rw-r--r--drivers/clk/clk-si5351.c7
-rw-r--r--drivers/clk/clk-tango4.c61
-rw-r--r--drivers/clk/clk-xgene.c3
-rw-r--r--drivers/clk/clk.c35
-rw-r--r--drivers/clk/imx/clk-imx25.c18
-rw-r--r--drivers/clk/imx/clk-imx51-imx53.c8
-rw-r--r--drivers/clk/imx/clk-imx6q.c3
-rw-r--r--drivers/clk/imx/clk-imx6ul.c4
-rw-r--r--drivers/clk/imx/clk-imx7d.c11
-rw-r--r--drivers/clk/imx/clk-pllv3.c14
-rw-r--r--drivers/clk/mvebu/Makefile2
-rw-r--r--drivers/clk/mvebu/dove-divider.c262
-rw-r--r--drivers/clk/mvebu/dove-divider.h6
-rw-r--r--drivers/clk/mvebu/dove.c6
-rw-r--r--drivers/clk/nxp/Makefile1
-rw-r--r--drivers/clk/nxp/clk-lpc32xx.c1569
-rw-r--r--drivers/clk/qcom/Kconfig17
-rw-r--r--drivers/clk/qcom/Makefile3
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c355
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h57
-rw-r--r--drivers/clk/qcom/clk-rcg.h1
-rw-r--r--drivers/clk/qcom/clk-rcg2.c87
-rw-r--r--drivers/clk/qcom/common.c87
-rw-r--r--drivers/clk/qcom/common.h4
-rw-r--r--drivers/clk/qcom/gcc-apq8084.c17
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c15
-rw-r--r--drivers/clk/qcom/gcc-msm8660.c16
-rw-r--r--drivers/clk/qcom/gcc-msm8916.c17
-rw-r--r--drivers/clk/qcom/gcc-msm8960.c16
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c18
-rw-r--r--drivers/clk/qcom/gcc-msm8996.c3422
-rw-r--r--drivers/clk/qcom/lcc-ipq806x.c1
-rw-r--r--drivers/clk/qcom/lcc-msm8960.c1
-rw-r--r--drivers/clk/qcom/mmcc-apq8084.c1
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c2
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c1
-rw-r--r--drivers/clk/qcom/mmcc-msm8996.c3217
-rw-r--r--drivers/clk/rockchip/Makefile2
-rw-r--r--drivers/clk/rockchip/clk-cpu.c4
-rw-r--r--drivers/clk/rockchip/clk-pll.c258
-rw-r--r--drivers/clk/rockchip/clk-rk3036.c493
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c112
-rw-r--r--drivers/clk/rockchip/clk-rk3228.c678
-rw-r--r--drivers/clk/rockchip/clk-rk3288.c136
-rw-r--r--drivers/clk/rockchip/clk-rk3368.c13
-rw-r--r--drivers/clk/rockchip/clk.c144
-rw-r--r--drivers/clk/rockchip/clk.h62
-rw-r--r--drivers/clk/samsung/clk-cpu.c10
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c98
-rw-r--r--drivers/clk/samsung/clk-s3c2410-dclk.c3
-rw-r--r--drivers/clk/shmobile/Makefile24
-rw-r--r--drivers/clk/shmobile/clk-div6.c137
-rw-r--r--drivers/clk/shmobile/clk-div6.h7
-rw-r--r--drivers/clk/shmobile/clk-rcar-gen2.c4
-rw-r--r--drivers/clk/shmobile/r8a7795-cpg-mssr.c383
-rw-r--r--drivers/clk/shmobile/renesas-cpg-mssr.c596
-rw-r--r--drivers/clk/shmobile/renesas-cpg-mssr.h132
-rw-r--r--drivers/clk/st/clkgen-fsyn.c17
-rw-r--r--drivers/clk/sunxi/Makefile5
-rw-r--r--drivers/clk/sunxi/clk-a10-ve.c171
-rw-r--r--drivers/clk/sunxi/clk-simple-gates.c14
-rw-r--r--drivers/clk/sunxi/clk-sun8i-apb0.c80
-rw-r--r--drivers/clk/sunxi/clk-sun8i-bus-gates.c112
-rw-r--r--drivers/clk/sunxi/clk-sun9i-cpus.c240
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c6
-rw-r--r--drivers/clk/sunxi/clk-usb.c12
-rw-r--r--drivers/clk/tegra/Makefile1
-rw-r--r--drivers/clk/tegra/clk-id.h75
-rw-r--r--drivers/clk/tegra/clk-pll.c834
-rw-r--r--drivers/clk/tegra/clk-tegra-periph.c371
-rw-r--r--drivers/clk/tegra/clk-tegra-super-gen4.c142
-rw-r--r--drivers/clk/tegra/clk-tegra114.c339
-rw-r--r--drivers/clk/tegra/clk-tegra124.c453
-rw-r--r--drivers/clk/tegra/clk-tegra20.c314
-rw-r--r--drivers/clk/tegra/clk-tegra210.c2852
-rw-r--r--drivers/clk/tegra/clk-tegra30.c426
-rw-r--r--drivers/clk/tegra/clk.h101
-rw-r--r--drivers/clk/ti/apll.c2
-rw-r--r--drivers/clk/ti/dpll3xxx.c25
-rw-r--r--drivers/clk/versatile/clk-sp810.c5
-rw-r--r--include/dt-bindings/clock/bcm2835-aux.h17
-rw-r--r--include/dt-bindings/clock/bcm2835.h3
-rw-r--r--include/dt-bindings/clock/exynos5420.h4
-rw-r--r--include/dt-bindings/clock/imx7d-clock.h3
-rw-r--r--include/dt-bindings/clock/lpc32xx-clock.h56
-rw-r--r--include/dt-bindings/clock/qcom,gcc-msm8996.h339
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-msm8996.h285
-rw-r--r--include/dt-bindings/clock/rk3036-cru.h193
-rw-r--r--include/dt-bindings/clock/rk3228-cru.h220
-rw-r--r--include/dt-bindings/clock/rk3288-cru.h4
-rw-r--r--include/dt-bindings/clock/tegra210-car.h401
-rw-r--r--include/linux/clk-provider.h9
-rw-r--r--include/linux/clk/ti.h1
119 files changed, 20637 insertions, 1351 deletions
diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt
new file mode 100644
index 000000000000..7a837d2182ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-aux-clock.txt
@@ -0,0 +1,31 @@
+Broadcom BCM2835 auxiliary peripheral support
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The auxiliary peripherals (UART, SPI1, and SPI2) have a small register
+area controlling clock gating to the peripherals, and providing an IRQ
+status register.
+
+Required properties:
+- compatible:	Should be "brcm,bcm2835-aux"
+- #clock-cells:	Should be <1>. The permitted clock-specifier values can be
+		  found in include/dt-bindings/clock/bcm2835-aux.h
+- reg:		Specifies base physical address and size of the registers
+- clocks:	The parent clock phandle
+
+Example:
+
+	clocks: cprman@7e101000 {
+		compatible = "brcm,bcm2835-cprman";
+		#clock-cells = <1>;
+		reg = <0x7e101000 0x2000>;
+		clocks = <&clk_osc>;
+	};
+
+	aux: aux@0x7e215004 {
+		compatible = "brcm,bcm2835-aux";
+		#clock-cells = <1>;
+		reg = <0x7e215000 0x8>;
+		clocks = <&clocks BCM2835_CLOCK_VPU>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
index ede65a55e21b..0b35e71b39e8 100644
--- a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
@@ -208,3 +208,8 @@ These clock IDs are defined in:
     ch3_unused	lcpll_ports	4	BCM_NS2_LCPLL_PORTS_CH3_UNUSED
     ch4_unused	lcpll_ports	5	BCM_NS2_LCPLL_PORTS_CH4_UNUSED
     ch5_unused	lcpll_ports	6	BCM_NS2_LCPLL_PORTS_CH5_UNUSED
+
+BCM63138
+--------
+PLL and leaf clock compatible strings for BCM63138 are:
+    "brcm,bcm63138-armpll"
diff --git a/Documentation/devicetree/bindings/clock/cs2000-cp.txt b/Documentation/devicetree/bindings/clock/cs2000-cp.txt
new file mode 100644
index 000000000000..54e6df0bee8a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/cs2000-cp.txt
@@ -0,0 +1,22 @@
+CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier
+
+Required properties:
+
+- compatible:		"cirrus,cs2000-cp"
+- reg:			The chip select number on the I2C bus
+- clocks:		common clock binding for CLK_IN, XTI/REF_CLK
+- clock-names:		CLK_IN : clk_in, XTI/REF_CLK : ref_clk
+- #clock-cells:		must be <0>
+
+Example:
+
+&i2c2 {
+	...
+	cs2000: clk_multiplier@4f {
+		#clock-cells = <0>;
+		compatible = "cirrus,cs2000-cp";
+		reg = <0x4f>;
+		clocks = <&rcar_sound 0>, <&x12_clk>;
+		clock-names = "clk_in", "ref_clk";
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra210-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra210-car.txt
new file mode 100644
index 000000000000..26f237f641b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra210-car.txt
@@ -0,0 +1,56 @@
+NVIDIA Tegra210 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra210-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+  the 32 KHz "32k_in".
+- #clock-cells : Should be 1.
+  In clock consumers, this cell represents the clock ID exposed by the
+  CAR. The assignments may be found in header file
+  <dt-bindings/clock/tegra210-car.h>.
+- #reset-cells : Should be 1.
+  In clock consumers, this cell represents the bit number in the CAR's
+  array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
+
+Example SoC include file:
+
+/ {
+	tegra_car: clock {
+		compatible = "nvidia,tegra210-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	usb@c5004000 {
+		clocks = <&tegra_car TEGRA210_CLK_USB2>;
+	};
+};
+
+Example board file:
+
+/ {
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk_32k: clock@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	&tegra_car {
+		clocks = <&clk_32k>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/nxp,lpc3220-clk.txt b/Documentation/devicetree/bindings/clock/nxp,lpc3220-clk.txt
new file mode 100644
index 000000000000..20cbca3f41d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nxp,lpc3220-clk.txt
@@ -0,0 +1,30 @@
+NXP LPC32xx Clock Controller
+
+Required properties:
+- compatible: should be "nxp,lpc3220-clk"
+- reg:  should contain clock controller registers location and length
+- #clock-cells: must be 1, the cell holds id of a clock provided by the
+  clock controller
+- clocks: phandles of external oscillators, the list must contain one
+  32768 Hz oscillator and may have one optional high frequency oscillator
+- clock-names: list of external oscillator clock names, must contain
+  "xtal_32k" and may have optional "xtal"
+
+Examples:
+
+	/* System Control Block */
+	scb {
+		compatible = "simple-bus";
+		ranges = <0x0 0x040004000 0x00001000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		clk: clock-controller@0 {
+			compatible = "nxp,lpc3220-clk";
+			reg = <0x00 0x114>;
+			#clock-cells = <1>;
+
+			clocks = <&xtal_32k>, <&xtal>;
+			clock-names = "xtal_32k", "xtal";
+		};
+	};
diff --git a/Documentation/devicetree/bindings/clock/nxp,lpc3220-usb-clk.txt b/Documentation/devicetree/bindings/clock/nxp,lpc3220-usb-clk.txt
new file mode 100644
index 000000000000..0aa249409b51
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nxp,lpc3220-usb-clk.txt
@@ -0,0 +1,22 @@
+NXP LPC32xx USB Clock Controller
+
+Required properties:
+- compatible: should be "nxp,lpc3220-usb-clk"
+- reg:  should contain clock controller registers location and length
+- #clock-cells: must be 1, the cell holds id of a clock provided by the
+  USB clock controller
+
+Examples:
+
+	usb {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x0 0x31020000 0x00001000>;
+
+		usbclk: clock-controller@f00 {
+			compatible = "nxp,lpc3220-usb-clk";
+			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 152dfaab2575..72f82f444091 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -13,6 +13,7 @@ Required properties :
 			"qcom,gcc-msm8974"
 			"qcom,gcc-msm8974pro"
 			"qcom,gcc-msm8974pro-ac"
+			"qcom,gcc-msm8996"
 
 - reg : shall contain base register location and length
 - #clock-cells : shall contain 1
diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
index 34e7614d5074..8b0f7841af8d 100644
--- a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
@@ -9,6 +9,7 @@ Required properties :
 			"qcom,mmcc-msm8660"
 			"qcom,mmcc-msm8960"
 			"qcom,mmcc-msm8974"
+			"qcom,mmcc-msm8996"
 
 - reg : shall contain base register location and length
 - #clock-cells : shall contain 1
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
index 38dcf0370143..ae36ab842919 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
@@ -20,6 +20,10 @@ Required Properties:
     clocks must be specified.  For clocks with multiple parents, invalid
     settings must be specified as "<0>".
   - #clock-cells: Must be 0
+
+
+Optional Properties:
+
   - clock-output-names: The name of the clock as a free-form string
 
 
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
new file mode 100644
index 000000000000..ace05992a262
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
@@ -0,0 +1,56 @@
+* Rockchip RK3036 Clock and Reset Unit
+
+The RK3036 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3036-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changeable, due to the missing pll lock status.
+
+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/rk3036-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_gmac" - external GMAC clock - optional
+
+Example: Clock controller node:
+
+	cru: cru@20000000 {
+		compatible = "rockchip,rk3036-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial@20060000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x20060000 0x100>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART0>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt
new file mode 100644
index 000000000000..f323048127eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt
@@ -0,0 +1,58 @@
+* Rockchip RK3228 Clock and Reset Unit
+
+The RK3228 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3228-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changeable, due to the missing pll lock status.
+
+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/rk3228-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_gmac" - external GMAC clock - optional
+ - "ext_hsadc" - external HSADC clock - optional
+ - "phy_50m_out" - output clock of the pll in the mac phy
+
+Example: Clock controller node:
+
+	cru: cru@20000000 {
+		compatible = "rockchip,rk3228-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial@10110000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10110000 0x100>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART0>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 8a47b77abfca..e59f57b24777 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -27,7 +27,9 @@ Required properties:
 	"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
 	"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
 	"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
+	"allwinner,sun9i-a80-cpus-clk" - for the CPUS on A80
 	"allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
+	"allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
 	"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
 	"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
 	"allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
@@ -55,6 +57,9 @@ Required properties:
 	"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
 	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
+	"allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
+	"allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80
+	"allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10
 	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
 	"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
 	"allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
@@ -68,8 +73,10 @@ Required properties:
 	"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
 	"allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
 	"allwinner,sun8i-a23-usb-clk" - for usb gates + resets on A23
+	"allwinner,sun8i-h3-usb-clk" - for usb gates + resets on H3
 	"allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80
 	"allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80
+	"allwinner,sun4i-a10-ve-clk" - for the Video Engine clock
 
 Required properties for all clocks:
 - reg : shall be the control register address for the clock.
@@ -89,6 +96,9 @@ Required properties for all clocks:
 And "allwinner,*-usb-clk" clocks also require:
 - reset-cells : shall be set to 1
 
+The "allwinner,sun4i-a10-ve-clk" clock also requires:
+- reset-cells : shall be set to 0
+
 The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
 - #reset-cells : shall be set to 1
 - resets : shall be the reset control phandle for the mmc block.
diff --git a/Documentation/devicetree/bindings/clock/tango4-clock.txt b/Documentation/devicetree/bindings/clock/tango4-clock.txt
new file mode 100644
index 000000000000..19c580a7bda2
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/tango4-clock.txt
@@ -0,0 +1,23 @@
+* Sigma Designs Tango4 Clock Generator
+
+The Tango4 clock generator outputs cpu_clk and sys_clk (the latter is used
+for RAM and various peripheral devices). The clock binding described here
+is applicable to all Tango4 SoCs.
+
+Required Properties:
+
+- compatible: should be "sigma,tango4-clkgen".
+- reg: physical base address of the device and length of memory mapped region.
+- clocks: phandle of the input clock (crystal oscillator).
+- clock-output-names: should be "cpuclk" and "sysclk".
+- #clock-cells: should be set to 1.
+
+Example:
+
+	clkgen: clkgen@10000 {
+		compatible = "sigma,tango4-clkgen";
+		reg = <0x10000 0x40>;
+		clocks = <&xtal>;
+		clock-output-names = "cpuclk", "sysclk";
+		#clock-cells = <1>;
+	};
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index acb60ed17273..d058125876d8 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -225,5 +225,9 @@ void __init ti_clk_init_features(void)
 	if (omap_rev() == OMAP3430_REV_ES1_0)
 		features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
 
+	/* Errata I810 for omap5 / dra7 */
+	if (soc_is_omap54xx() || soc_is_dra7xx())
+		features.flags |= TI_CLK_ERRATA_I810;
+
 	ti_clk_setup_features(&features);
 }
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c3e3a02f7f1f..eca8e019e005 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -116,6 +116,12 @@ config COMMON_CLK_CDCE925
 	  Given a target output frequency, the driver will set the PLL and
 	  divider to best approximate the desired output.
 
+config COMMON_CLK_CS2000_CP
+	tristate "Clock driver for CS2000 Fractional-N Clock Synthesizer & Clock Multiplier"
+	depends on I2C
+	help
+	  If you say yes here you get support for the CS2000 clock multiplier.
+
 config COMMON_CLK_S2MPS11
 	tristate "Clock driver for S2MPS1X/S5M8767 MFD"
 	depends on MFD_SEC_CORE
@@ -161,6 +167,12 @@ config COMMON_CLK_KEYSTONE
           Supports clock drivers for Keystone based SOCs. These SOCs have local
 	  a power sleep control module that gate the clock to the IPs and PLLs.
 
+config COMMON_CLK_NXP
+	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
+	select REGMAP_MMIO if ARCH_LPC32XX
+	---help---
+	  Support for clock providers on NXP platforms.
+
 config COMMON_CLK_PALMAS
 	tristate "Clock driver for TI Palmas devices"
 	depends on MFD_PALMAS
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 820714c72d36..b038e3666058 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_MACH_ASM9260)		+= clk-asm9260.o
 obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN)	+= clk-axi-clkgen.o
 obj-$(CONFIG_ARCH_AXXIA)		+= clk-axm5516.o
 obj-$(CONFIG_COMMON_CLK_CDCE706)	+= clk-cdce706.o
+obj-$(CONFIG_COMMON_CLK_CS2000_CP)	+= clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_CLPS711X)		+= clk-clps711x.o
 obj-$(CONFIG_ARCH_EFM32)		+= clk-efm32gg.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
@@ -42,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_SI514)		+= clk-si514.o
 obj-$(CONFIG_COMMON_CLK_SI570)		+= clk-si570.o
 obj-$(CONFIG_COMMON_CLK_CDCE925)	+= clk-cdce925.o
 obj-$(CONFIG_ARCH_STM32)		+= clk-stm32f4.o
+obj-$(CONFIG_ARCH_TANGOX)		+= clk-tango4.o
 obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)			+= clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
@@ -62,13 +64,14 @@ endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
 obj-$(CONFIG_ARCH_MESON)		+= meson/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
-obj-$(CONFIG_ARCH_LPC18XX)		+= nxp/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
+obj-$(CONFIG_COMMON_CLK_NXP)		+= nxp/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
 obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= shmobile/
+obj-$(CONFIG_ARCH_RENESAS)		+= shmobile/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index d0d5076a9b94..6f99a530ead6 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -10,7 +10,6 @@
  *
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/slab.h>
@@ -72,8 +71,6 @@ struct clk_sam9x5_slow {
 
 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
 
-static struct clk *slow_clk;
-
 static int clk_slow_osc_prepare(struct clk_hw *hw)
 {
 	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
@@ -360,8 +357,6 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr,
 	clk = clk_register(NULL, &slowck->hw);
 	if (IS_ERR(clk))
 		kfree(slowck);
-	else
-		slow_clk = clk;
 
 	return clk;
 }
@@ -433,8 +428,6 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
 	clk = clk_register(NULL, &slowck->hw);
 	if (IS_ERR(clk))
 		kfree(slowck);
-	else
-		slow_clk = clk;
 
 	return clk;
 }
@@ -462,25 +455,3 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
 
 	of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
-
-/*
- * FIXME: All slow clk users are not properly claiming it (get + prepare +
- * enable) before using it.
- * If all users properly claiming this clock decide that they don't need it
- * anymore (or are removed), it is disabled while faulty users are still
- * requiring it, and the system hangs.
- * Prevent this clock from being disabled until all users are properly
- * requesting it.
- * Once this is done we should remove this function and the slow_clk variable.
- */
-static int __init of_at91_clk_slow_retain(void)
-{
-	if (!slow_clk)
-		return 0;
-
-	__clk_get(slow_clk);
-	clk_prepare_enable(slow_clk);
-
-	return 0;
-}
-arch_initcall(of_at91_clk_slow_retain);
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index 85260fb96b36..f2878459199a 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -1,3 +1,13 @@
+config CLK_BCM_63XX
+	bool "Broadcom BCM63xx clock support"
+	depends on ARCH_BCM_63XX || COMPILE_TEST
+	depends on COMMON_CLK
+	select COMMON_CLK_IPROC
+	default ARCH_BCM_63XX
+	help
+	  Enable common clock framework support for Broadcom BCM63xx DSL SoCs
+	  based on the ARM architecture
+
 config CLK_BCM_KONA
 	bool "Broadcom Kona CCU clock support"
 	depends on ARCH_BCM_MOBILE || COMPILE_TEST
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 3fc95060d875..1d79bd2c36f0 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -1,9 +1,11 @@
+obj-$(CONFIG_CLK_BCM_63XX)	+= clk-bcm63xx.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona-setup.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm281xx.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm21664.o
 obj-$(CONFIG_COMMON_CLK_IPROC)	+= clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
+obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835-aux.o
 obj-$(CONFIG_COMMON_CLK_IPROC)	+= clk-ns2.o
 obj-$(CONFIG_ARCH_BCM_CYGNUS)	+= clk-cygnus.o
 obj-$(CONFIG_ARCH_BCM_NSP)	+= clk-nsp.o
diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c
new file mode 100644
index 000000000000..e4f89e28b5ec
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm2835-aux.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/bcm2835.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/bcm2835-aux.h>
+
+#define BCM2835_AUXIRQ		0x00
+#define BCM2835_AUXENB		0x04
+
+static int bcm2835_aux_clk_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct clk_onecell_data *onecell;
+	const char *parent;
+	struct clk *parent_clk;
+	struct resource *res;
+	void __iomem *reg, *gate;
+
+	parent_clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(parent_clk))
+		return PTR_ERR(parent_clk);
+	parent = __clk_get_name(parent_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(dev, res);
+	if (!reg)
+		return -ENODEV;
+
+	onecell = devm_kmalloc(dev, sizeof(*onecell), GFP_KERNEL);
+	if (!onecell)
+		return -ENOMEM;
+	onecell->clk_num = BCM2835_AUX_CLOCK_COUNT;
+	onecell->clks = devm_kcalloc(dev, BCM2835_AUX_CLOCK_COUNT,
+				     sizeof(*onecell->clks), GFP_KERNEL);
+	if (!onecell->clks)
+		return -ENOMEM;
+
+	gate = reg + BCM2835_AUXENB;
+	onecell->clks[BCM2835_AUX_CLOCK_UART] =
+		clk_register_gate(dev, "aux_uart", parent, 0, gate, 0, 0, NULL);
+
+	onecell->clks[BCM2835_AUX_CLOCK_SPI1] =
+		clk_register_gate(dev, "aux_spi1", parent, 0, gate, 1, 0, NULL);
+
+	onecell->clks[BCM2835_AUX_CLOCK_SPI2] =
+		clk_register_gate(dev, "aux_spi2", parent, 0, gate, 2, 0, NULL);
+
+	of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, onecell);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_aux_clk_of_match[] = {
+	{ .compatible = "brcm,bcm2835-aux", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_aux_clk_of_match);
+
+static struct platform_driver bcm2835_aux_clk_driver = {
+	.driver = {
+		.name = "bcm2835-aux-clk",
+		.of_match_table = bcm2835_aux_clk_of_match,
+	},
+	.probe          = bcm2835_aux_clk_probe,
+};
+builtin_platform_driver(bcm2835_aux_clk_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 39bf5820297e..015e687ffabe 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -807,6 +807,16 @@ static const struct bcm2835_clock_data bcm2835_clock_emmc_data = {
 	.frac_bits = 8,
 };
 
+static const struct bcm2835_clock_data bcm2835_clock_pwm_data = {
+	.name = "pwm",
+	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
+	.parents = bcm2835_clock_per_parents,
+	.ctl_reg = CM_PWMCTL,
+	.div_reg = CM_PWMDIV,
+	.int_bits = 12,
+	.frac_bits = 12,
+};
+
 struct bcm2835_pll {
 	struct clk_hw hw;
 	struct bcm2835_cprman *cprman;
@@ -1148,22 +1158,24 @@ static int bcm2835_clock_is_on(struct clk_hw *hw)
 
 static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
 				    unsigned long rate,
-				    unsigned long parent_rate)
+				    unsigned long parent_rate,
+				    bool round_up)
 {
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	const struct bcm2835_clock_data *data = clock->data;
-	u32 unused_frac_mask = GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0);
+	u32 unused_frac_mask =
+		GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
 	u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
+	u64 rem;
 	u32 div;
 
-	do_div(temp, rate);
+	rem = do_div(temp, rate);
 	div = temp;
 
-	/* Round and mask off the unused bits */
-	if (unused_frac_mask != 0) {
-		div += unused_frac_mask >> 1;
-		div &= ~unused_frac_mask;
-	}
+	/* Round up and mask off the unused bits */
+	if (round_up && ((div & unused_frac_mask) != 0 || rem != 0))
+		div += unused_frac_mask + 1;
+	div &= ~unused_frac_mask;
 
 	/* Clamp to the limits. */
 	div = max(div, unused_frac_mask + 1);
@@ -1197,16 +1209,6 @@ static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
 	return temp;
 }
 
-static long bcm2835_clock_round_rate(struct clk_hw *hw,
-				     unsigned long rate,
-				     unsigned long *parent_rate)
-{
-	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
-	u32 div = bcm2835_clock_choose_div(hw, rate, *parent_rate);
-
-	return bcm2835_clock_rate_from_divisor(clock, *parent_rate, div);
-}
-
 static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
 					    unsigned long parent_rate)
 {
@@ -1271,20 +1273,82 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	struct bcm2835_cprman *cprman = clock->cprman;
 	const struct bcm2835_clock_data *data = clock->data;
-	u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
+	u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
 
 	cprman_write(cprman, data->div_reg, div);
 
 	return 0;
 }
 
+static int bcm2835_clock_determine_rate(struct clk_hw *hw,
+		struct clk_rate_request *req)
+{
+	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+	struct clk_hw *parent, *best_parent = NULL;
+	unsigned long rate, best_rate = 0;
+	unsigned long prate, best_prate = 0;
+	size_t i;
+	u32 div;
+
+	/*
+	 * Select parent clock that results in the closest but lower rate
+	 */
+	for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (!parent)
+			continue;
+		prate = clk_hw_get_rate(parent);
+		div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
+		rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
+		if (rate > best_rate && rate <= req->rate) {
+			best_parent = parent;
+			best_prate = prate;
+			best_rate = rate;
+		}
+	}
+
+	if (!best_parent)
+		return -EINVAL;
+
+	req->best_parent_hw = best_parent;
+	req->best_parent_rate = best_prate;
+
+	req->rate = best_rate;
+
+	return 0;
+}
+
+static int bcm2835_clock_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+	struct bcm2835_cprman *cprman = clock->cprman;
+	const struct bcm2835_clock_data *data = clock->data;
+	u8 src = (index << CM_SRC_SHIFT) & CM_SRC_MASK;
+
+	cprman_write(cprman, data->ctl_reg, src);
+	return 0;
+}
+
+static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
+{
+	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+	struct bcm2835_cprman *cprman = clock->cprman;
+	const struct bcm2835_clock_data *data = clock->data;
+	u32 src = cprman_read(cprman, data->ctl_reg);
+
+	return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
+}
+
+
 static const struct clk_ops bcm2835_clock_clk_ops = {
 	.is_prepared = bcm2835_clock_is_on,
 	.prepare = bcm2835_clock_on,
 	.unprepare = bcm2835_clock_off,
 	.recalc_rate = bcm2835_clock_get_rate,
 	.set_rate = bcm2835_clock_set_rate,
-	.round_rate = bcm2835_clock_round_rate,
+	.determine_rate = bcm2835_clock_determine_rate,
+	.set_parent = bcm2835_clock_set_parent,
+	.get_parent = bcm2835_clock_get_parent,
 };
 
 static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
@@ -1300,7 +1364,9 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
 	.is_prepared = bcm2835_vpu_clock_is_on,
 	.recalc_rate = bcm2835_clock_get_rate,
 	.set_rate = bcm2835_clock_set_rate,
-	.round_rate = bcm2835_clock_round_rate,
+	.determine_rate = bcm2835_clock_determine_rate,
+	.set_parent = bcm2835_clock_set_parent,
+	.get_parent = bcm2835_clock_get_parent,
 };
 
 static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
@@ -1394,45 +1460,23 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
 {
 	struct bcm2835_clock *clock;
 	struct clk_init_data init;
-	const char *parent;
+	const char *parents[1 << CM_SRC_BITS];
+	size_t i;
 
 	/*
-	 * Most of the clock generators have a mux field, so we
-	 * instantiate a generic mux as our parent to handle it.
+	 * Replace our "xosc" references with the oscillator's
+	 * actual name.
 	 */
-	if (data->num_mux_parents) {
-		const char *parents[1 << CM_SRC_BITS];
-		int i;
-
-		parent = devm_kasprintf(cprman->dev, GFP_KERNEL,
-					"mux_%s", data->name);
-		if (!parent)
-			return NULL;
-
-		/*
-		 * Replace our "xosc" references with the oscillator's
-		 * actual name.
-		 */
-		for (i = 0; i < data->num_mux_parents; i++) {
-			if (strcmp(data->parents[i], "xosc") == 0)
-				parents[i] = cprman->osc_name;
-			else
-				parents[i] = data->parents[i];
-		}
-
-		clk_register_mux(cprman->dev, parent,
-				 parents, data->num_mux_parents,
-				 CLK_SET_RATE_PARENT,
-				 cprman->regs + data->ctl_reg,
-				 CM_SRC_SHIFT, CM_SRC_BITS,
-				 0, &cprman->regs_lock);
-	} else {
-		parent = data->parents[0];
+	for (i = 0; i < data->num_mux_parents; i++) {
+		if (strcmp(data->parents[i], "xosc") == 0)
+			parents[i] = cprman->osc_name;
+		else
+			parents[i] = data->parents[i];
 	}
 
 	memset(&init, 0, sizeof(init));
-	init.parent_names = &parent;
-	init.num_parents = 1;
+	init.parent_names = parents;
+	init.num_parents = data->num_mux_parents;
 	init.name = data->name;
 	init.flags = CLK_IGNORE_UNUSED;
 
@@ -1550,6 +1594,9 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
 				  cprman->regs + CM_PERIICTL, CM_GATE_BIT,
 				  0, &cprman->regs_lock);
 
+	clks[BCM2835_CLOCK_PWM] =
+		bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data);
+
 	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
 				   &cprman->onecell);
 }
diff --git a/drivers/clk/bcm/clk-bcm63xx.c b/drivers/clk/bcm/clk-bcm63xx.c
new file mode 100644
index 000000000000..fbc17ae5ff2b
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm63xx.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include "clk-iproc.h"
+
+static void __init bcm63138_armpll_init(struct device_node *node)
+{
+	iproc_armpll_setup(node);
+}
+CLK_OF_DECLARE(bcm63138_armpll, "brcm,bcm63138-armpll", bcm63138_armpll_init);
diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c
new file mode 100644
index 000000000000..7379de8dc894
--- /dev/null
+++ b/drivers/clk/clk-cs2000-cp.c
@@ -0,0 +1,510 @@
+/*
+ * CS2000  --  CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+
+#define CH_MAX 4
+#define RATIO_REG_SIZE 4
+
+#define DEVICE_ID	0x1
+#define DEVICE_CTRL	0x2
+#define DEVICE_CFG1	0x3
+#define DEVICE_CFG2	0x4
+#define GLOBAL_CFG	0x5
+#define Ratio_Add(x, nth)	(6 + (x * 4) + (nth))
+#define Ratio_Val(x, nth)	((x >> (24 - (8 * nth))) & 0xFF)
+#define Val_Ratio(x, nth)	((x & 0xFF) << (24 - (8 * nth)))
+#define FUNC_CFG1	0x16
+#define FUNC_CFG2	0x17
+
+/* DEVICE_ID */
+#define REVISION_MASK	(0x7)
+#define REVISION_B2_B3	(0x4)
+#define REVISION_C1	(0x6)
+
+/* DEVICE_CTRL */
+#define PLL_UNLOCK	(1 << 7)
+
+/* DEVICE_CFG1 */
+#define RSEL(x)		(((x) & 0x3) << 3)
+#define RSEL_MASK	RSEL(0x3)
+#define ENDEV1		(0x1)
+
+/* GLOBAL_CFG */
+#define ENDEV2		(0x1)
+
+#define CH_SIZE_ERR(ch)		((ch < 0) || (ch >= CH_MAX))
+#define hw_to_priv(_hw)		container_of(_hw, struct cs2000_priv, hw)
+#define priv_to_client(priv)	(priv->client)
+#define priv_to_dev(priv)	(&(priv_to_client(priv)->dev))
+
+#define CLK_IN	0
+#define REF_CLK	1
+#define CLK_MAX 2
+
+struct cs2000_priv {
+	struct clk_hw hw;
+	struct i2c_client *client;
+	struct clk *clk_in;
+	struct clk *ref_clk;
+	struct clk *clk_out;
+};
+
+static const struct of_device_id cs2000_of_match[] = {
+	{ .compatible = "cirrus,cs2000-cp", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cs2000_of_match);
+
+static const struct i2c_device_id cs2000_id[] = {
+	{ "cs2000-cp", },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, cs2000_id);
+
+#define cs2000_read(priv, addr) \
+	i2c_smbus_read_byte_data(priv_to_client(priv), addr)
+#define cs2000_write(priv, addr, val) \
+	i2c_smbus_write_byte_data(priv_to_client(priv), addr, val)
+
+static int cs2000_bset(struct cs2000_priv *priv, u8 addr, u8 mask, u8 val)
+{
+	s32 data;
+
+	data = cs2000_read(priv, addr);
+	if (data < 0)
+		return data;
+
+	data &= ~mask;
+	data |= (val & mask);
+
+	return cs2000_write(priv, addr, data);
+}
+
+static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
+{
+	int ret;
+
+	ret = cs2000_bset(priv, DEVICE_CFG1, ENDEV1,
+			  enable ? ENDEV1 : 0);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_bset(priv, GLOBAL_CFG,  ENDEV2,
+			  enable ? ENDEV2 : 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv,
+				    u32 rate_in)
+{
+	u32 val;
+
+	if (rate_in >= 32000000 && rate_in < 56000000)
+		val = 0x0;
+	else if (rate_in >= 16000000 && rate_in < 28000000)
+		val = 0x1;
+	else if (rate_in >= 8000000 && rate_in < 14000000)
+		val = 0x2;
+	else
+		return -EINVAL;
+
+	return cs2000_bset(priv, FUNC_CFG1, 0x3 << 3, val << 3);
+}
+
+static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
+{
+	struct device *dev = priv_to_dev(priv);
+	s32 val;
+	unsigned int i;
+
+	for (i = 0; i < 256; i++) {
+		val = cs2000_read(priv, DEVICE_CTRL);
+		if (val < 0)
+			return val;
+		if (!(val & PLL_UNLOCK))
+			return 0;
+		udelay(1);
+	}
+
+	dev_err(dev, "pll lock failed\n");
+
+	return -ETIMEDOUT;
+}
+
+static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable)
+{
+	/* enable both AUX_OUT, CLK_OUT */
+	return cs2000_write(priv, DEVICE_CTRL, enable ? 0 : 0x3);
+}
+
+static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out)
+{
+	u64 ratio;
+
+	/*
+	 * ratio = rate_out / rate_in * 2^20
+	 *
+	 * To avoid over flow, rate_out is u64.
+	 * The result should be u32.
+	 */
+	ratio = (u64)rate_out << 20;
+	do_div(ratio, rate_in);
+
+	return ratio;
+}
+
+static unsigned long cs2000_ratio_to_rate(u32 ratio, u32 rate_in)
+{
+	u64 rate_out;
+
+	/*
+	 * ratio = rate_out / rate_in * 2^20
+	 *
+	 * To avoid over flow, rate_out is u64.
+	 * The result should be u32 or unsigned long.
+	 */
+
+	rate_out = (u64)ratio * rate_in;
+	return rate_out >> 20;
+}
+
+static int cs2000_ratio_set(struct cs2000_priv *priv,
+			    int ch, u32 rate_in, u32 rate_out)
+{
+	u32 val;
+	unsigned int i;
+	int ret;
+
+	if (CH_SIZE_ERR(ch))
+		return -EINVAL;
+
+	val = cs2000_rate_to_ratio(rate_in, rate_out);
+	for (i = 0; i < RATIO_REG_SIZE; i++) {
+		ret = cs2000_write(priv,
+				   Ratio_Add(ch, i),
+				   Ratio_Val(val, i));
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch)
+{
+	s32 tmp;
+	u32 val;
+	unsigned int i;
+
+	val = 0;
+	for (i = 0; i < RATIO_REG_SIZE; i++) {
+		tmp = cs2000_read(priv, Ratio_Add(ch, i));
+		if (tmp < 0)
+			return 0;
+
+		val |= Val_Ratio(tmp, i);
+	}
+
+	return val;
+}
+
+static int cs2000_ratio_select(struct cs2000_priv *priv, int ch)
+{
+	int ret;
+
+	if (CH_SIZE_ERR(ch))
+		return -EINVAL;
+
+	/*
+	 * FIXME
+	 *
+	 * this driver supports static ratio mode only at this point.
+	 */
+	ret = cs2000_bset(priv, DEVICE_CFG1, RSEL_MASK, RSEL(ch));
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_write(priv, DEVICE_CFG2, 0x0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static unsigned long cs2000_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct cs2000_priv *priv = hw_to_priv(hw);
+	int ch = 0; /* it uses ch0 only at this point */
+	u32 ratio;
+
+	ratio = cs2000_ratio_get(priv, ch);
+
+	return cs2000_ratio_to_rate(ratio, parent_rate);
+}
+
+static long cs2000_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	u32 ratio;
+
+	ratio = cs2000_rate_to_ratio(*parent_rate, rate);
+
+	return cs2000_ratio_to_rate(ratio, *parent_rate);
+}
+
+static int __cs2000_set_rate(struct cs2000_priv *priv, int ch,
+			     unsigned long rate, unsigned long parent_rate)
+
+{
+	int ret;
+
+	ret = cs2000_clk_in_bound_rate(priv, parent_rate);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_ratio_set(priv, ch, parent_rate, rate);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_ratio_select(priv, ch);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int cs2000_set_rate(struct clk_hw *hw,
+			   unsigned long rate, unsigned long parent_rate)
+{
+	struct cs2000_priv *priv = hw_to_priv(hw);
+	int ch = 0; /* it uses ch0 only at this point */
+
+	return __cs2000_set_rate(priv, ch, rate, parent_rate);
+}
+
+static int cs2000_enable(struct clk_hw *hw)
+{
+	struct cs2000_priv *priv = hw_to_priv(hw);
+	int ret;
+
+	ret = cs2000_enable_dev_config(priv, true);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_clk_out_enable(priv, true);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_wait_pll_lock(priv);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static void cs2000_disable(struct clk_hw *hw)
+{
+	struct cs2000_priv *priv = hw_to_priv(hw);
+
+	cs2000_enable_dev_config(priv, false);
+
+	cs2000_clk_out_enable(priv, false);
+}
+
+static u8 cs2000_get_parent(struct clk_hw *hw)
+{
+	/* always return REF_CLK */
+	return REF_CLK;
+}
+
+static const struct clk_ops cs2000_ops = {
+	.get_parent	= cs2000_get_parent,
+	.recalc_rate	= cs2000_recalc_rate,
+	.round_rate	= cs2000_round_rate,
+	.set_rate	= cs2000_set_rate,
+	.prepare	= cs2000_enable,
+	.unprepare	= cs2000_disable,
+};
+
+static int cs2000_clk_get(struct cs2000_priv *priv)
+{
+	struct i2c_client *client = priv_to_client(priv);
+	struct device *dev = &client->dev;
+	struct clk *clk_in, *ref_clk;
+
+	clk_in = devm_clk_get(dev, "clk_in");
+	/* not yet provided */
+	if (IS_ERR(clk_in))
+		return -EPROBE_DEFER;
+
+	ref_clk = devm_clk_get(dev, "ref_clk");
+	/* not yet provided */
+	if (IS_ERR(ref_clk))
+		return -EPROBE_DEFER;
+
+	priv->clk_in	= clk_in;
+	priv->ref_clk	= ref_clk;
+
+	return 0;
+}
+
+static int cs2000_clk_register(struct cs2000_priv *priv)
+{
+	struct device *dev = priv_to_dev(priv);
+	struct device_node *np = dev->of_node;
+	struct clk_init_data init;
+	const char *name = np->name;
+	struct clk *clk;
+	static const char *parent_names[CLK_MAX];
+	int ch = 0; /* it uses ch0 only at this point */
+	int rate;
+	int ret;
+
+	of_property_read_string(np, "clock-output-names", &name);
+
+	/*
+	 * set default rate as 1/1.
+	 * otherwise .set_rate which setup ratio
+	 * is never called if user requests 1/1 rate
+	 */
+	rate = clk_get_rate(priv->ref_clk);
+	ret = __cs2000_set_rate(priv, ch, rate, rate);
+	if (ret < 0)
+		return ret;
+
+	parent_names[CLK_IN]	= __clk_get_name(priv->clk_in);
+	parent_names[REF_CLK]	= __clk_get_name(priv->ref_clk);
+
+	init.name		= name;
+	init.ops		= &cs2000_ops;
+	init.flags		= CLK_SET_RATE_GATE;
+	init.parent_names	= parent_names;
+	init.num_parents	= ARRAY_SIZE(parent_names);
+
+	priv->hw.init = &init;
+
+	clk = clk_register(dev, &priv->hw);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	if (ret < 0) {
+		clk_unregister(clk);
+		return ret;
+	}
+
+	priv->clk_out = clk;
+
+	return 0;
+}
+
+static int cs2000_version_print(struct cs2000_priv *priv)
+{
+	struct i2c_client *client = priv_to_client(priv);
+	struct device *dev = &client->dev;
+	s32 val;
+	const char *revision;
+
+	val = cs2000_read(priv, DEVICE_ID);
+	if (val < 0)
+		return val;
+
+	/* CS2000 should be 0x0 */
+	if (val >> 3)
+		return -EIO;
+
+	switch (val & REVISION_MASK) {
+	case REVISION_B2_B3:
+		revision = "B2 / B3";
+		break;
+	case REVISION_C1:
+		revision = "C1";
+		break;
+	default:
+		return -EIO;
+	}
+
+	dev_info(dev, "revision - %s\n", revision);
+
+	return 0;
+}
+
+static int cs2000_remove(struct i2c_client *client)
+{
+	struct cs2000_priv *priv = i2c_get_clientdata(client);
+	struct device *dev = &client->dev;
+	struct device_node *np = dev->of_node;
+
+	of_clk_del_provider(np);
+
+	clk_unregister(priv->clk_out);
+
+	return 0;
+}
+
+static int cs2000_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct cs2000_priv *priv;
+	struct device *dev = &client->dev;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+	i2c_set_clientdata(client, priv);
+
+	ret = cs2000_clk_get(priv);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_clk_register(priv);
+	if (ret < 0)
+		return ret;
+
+	ret = cs2000_version_print(priv);
+	if (ret < 0)
+		goto probe_err;
+
+	return 0;
+
+probe_err:
+	cs2000_remove(client);
+
+	return ret;
+}
+
+static struct i2c_driver cs2000_driver = {
+	.driver = {
+		.name = "cs2000-cp",
+		.of_match_table = cs2000_of_match,
+	},
+	.probe		= cs2000_probe,
+	.remove		= cs2000_remove,
+	.id_table	= cs2000_id,
+};
+
+module_i2c_driver(cs2000_driver);
+
+MODULE_DESCRIPTION("CS2000-CP driver");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 3ace102a2a0a..ded3ff4b91b9 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -32,13 +32,14 @@
 
 #define div_mask(width)	((1 << (width)) - 1)
 
-static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
+static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
+				      u8 width)
 {
-	unsigned int maxdiv = 0;
+	unsigned int maxdiv = 0, mask = div_mask(width);
 	const struct clk_div_table *clkt;
 
 	for (clkt = table; clkt->div; clkt++)
-		if (clkt->div > maxdiv)
+		if (clkt->div > maxdiv && clkt->val <= mask)
 			maxdiv = clkt->div;
 	return maxdiv;
 }
@@ -62,7 +63,7 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
 	if (flags & CLK_DIVIDER_POWER_OF_TWO)
 		return 1 << div_mask(width);
 	if (table)
-		return _get_table_maxdiv(table);
+		return _get_table_maxdiv(table, width);
 	return div_mask(width) + 1;
 }
 
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 335322dc403f..19fed65587e8 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -264,8 +264,8 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name,
 		const char * const *parent_names, u8 num_parents,
 		unsigned gpio, bool active_low)
 {
-	return clk_register_gpio_gate(NULL, name, parent_names[0],
-			gpio, active_low, 0);
+	return clk_register_gpio_gate(NULL, name, parent_names ?
+			parent_names[0] : NULL, gpio, active_low, 0);
 }
 
 static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name,
@@ -287,18 +287,26 @@ static void __init of_gpio_clk_setup(struct device_node *node,
 	const char **parent_names;
 	int i, num_parents;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return;
-
 	num_parents = of_clk_get_parent_count(node);
+	if (num_parents < 0)
+		return;
 
-	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
-	if (!parent_names)
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
 		return;
 
-	for (i = 0; i < num_parents; i++)
-		parent_names[i] = of_clk_get_parent_name(node, i);
+	if (num_parents) {
+		parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+		if (!parent_names) {
+			kfree(data);
+			return;
+		}
+
+		for (i = 0; i < num_parents; i++)
+			parent_names[i] = of_clk_get_parent_name(node, i);
+	} else {
+		parent_names = NULL;
+	}
 
 	data->num_parents = num_parents;
 	data->parent_names = parent_names;
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 7129c86a79db..5ed03c8a8df9 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -71,10 +71,9 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	u32 val;
 	unsigned long flags = 0;
 
-	if (mux->table)
+	if (mux->table) {
 		index = mux->table[index];
-
-	else {
+	} else {
 		if (mux->flags & CLK_MUX_INDEX_BIT)
 			index = 1 << index;
 
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index e346b223199d..850316ac8831 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -1091,6 +1091,13 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 	si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
 			SI5351_CLK_POWERDOWN, 0);
 
+	/*
+	 * Do a pll soft reset on both plls, needed in some cases to get
+	 * all outputs running.
+	 */
+	si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET,
+			 SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
+
 	dev_dbg(&hwdata->drvdata->client->dev,
 		"%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
 		__func__, clk_hw_get_name(hw), (1 << rdiv),
diff --git a/drivers/clk/clk-tango4.c b/drivers/clk/clk-tango4.c
new file mode 100644
index 000000000000..004ab7dfcfe3
--- /dev/null
+++ b/drivers/clk/clk-tango4.c
@@ -0,0 +1,61 @@
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+static struct clk *out[2];
+static struct clk_onecell_data clk_data = { out, 2 };
+
+#define SYSCLK_CTRL	0x20
+#define CPUCLK_CTRL	0x24
+#define LEGACY_DIV	0x3c
+
+#define PLL_N(val)	(((val) >>  0) & 0x7f)
+#define PLL_K(val)	(((val) >> 13) & 0x7)
+#define PLL_M(val)	(((val) >> 16) & 0x7)
+#define DIV_INDEX(val)	(((val) >>  8) & 0xf)
+
+static void __init make_pll(int idx, const char *parent, void __iomem *base)
+{
+	char name[8];
+	u32 val, mul, div;
+
+	sprintf(name, "pll%d", idx);
+	val = readl_relaxed(base + idx*8);
+	mul =  PLL_N(val) + 1;
+	div = (PLL_M(val) + 1) << PLL_K(val);
+	clk_register_fixed_factor(NULL, name, parent, 0, mul, div);
+}
+
+static int __init get_div(void __iomem *base)
+{
+	u8 sysclk_tab[16] = { 2, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 };
+	int idx = DIV_INDEX(readl_relaxed(base + LEGACY_DIV));
+
+	return sysclk_tab[idx];
+}
+
+static void __init tango4_clkgen_setup(struct device_node *np)
+{
+	int div, ret;
+	void __iomem *base = of_iomap(np, 0);
+	const char *parent = of_clk_get_parent_name(np, 0);
+
+	if (!base)
+		panic("%s: invalid address\n", np->full_name);
+
+	make_pll(0, parent, base);
+	make_pll(1, parent, base);
+
+	out[0] = clk_register_divider(NULL, "cpuclk", "pll0", 0,
+			base + CPUCLK_CTRL, 8, 8, CLK_DIVIDER_ONE_BASED, NULL);
+
+	div = readl_relaxed(base + SYSCLK_CTRL) & BIT(23) ? get_div(base) : 4;
+	out[1] = clk_register_fixed_factor(NULL, "sysclk", "pll1", 0, 1, div);
+
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	if (IS_ERR(out[0]) || IS_ERR(out[1]) || ret < 0)
+		panic("%s: clk registration failed\n", np->full_name);
+}
+CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup);
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index 27c0da29eca3..10224b01b97c 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -351,7 +351,8 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 		/* Set new divider */
 		data = xgene_clk_read(pclk->param.divider_reg +
 				pclk->param.reg_divider_offset);
-		data &= ~((1 << pclk->param.reg_divider_width) - 1);
+		data &= ~((1 << pclk->param.reg_divider_width) - 1)
+				<< pclk->param.reg_divider_shift;
 		data |= divider;
 		xgene_clk_write(data, pclk->param.divider_reg +
 					pclk->param.reg_divider_offset);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f13c3f4228d4..b4db67a446c8 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1443,6 +1443,15 @@ static void clk_change_rate(struct clk_core *core)
 	else if (core->parent)
 		best_parent_rate = core->parent->rate;
 
+	if (core->flags & CLK_SET_RATE_UNGATE) {
+		unsigned long flags;
+
+		clk_core_prepare(core);
+		flags = clk_enable_lock();
+		clk_core_enable(core);
+		clk_enable_unlock(flags);
+	}
+
 	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);
@@ -1469,6 +1478,15 @@ static void clk_change_rate(struct clk_core *core)
 
 	core->rate = clk_recalc(core, best_parent_rate);
 
+	if (core->flags & CLK_SET_RATE_UNGATE) {
+		unsigned long flags;
+
+		flags = clk_enable_lock();
+		clk_core_disable(core);
+		clk_enable_unlock(flags);
+		clk_core_unprepare(core);
+	}
+
 	if (core->notifier_count && old_rate != core->rate)
 		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
 
@@ -1944,7 +1962,7 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
 	if (p == q)
 		return true;
 
-	/* true if clk->core pointers match. Avoid derefing garbage */
+	/* true if clk->core pointers match. Avoid dereferencing garbage */
 	if (!IS_ERR_OR_NULL(p) && !IS_ERR_OR_NULL(q))
 		if (p->core == q->core)
 			return true;
@@ -2482,7 +2500,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
 	struct clk *clk;
 
 	/* This is to allow this function to be chained to others */
-	if (!hw || IS_ERR(hw))
+	if (IS_ERR_OR_NULL(hw))
 		return (struct clk *) hw;
 
 	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
@@ -2806,10 +2824,9 @@ void __clk_put(struct clk *clk)
  * re-enter into the clk framework by calling any top-level clk APIs;
  * this will cause a nested prepare_lock mutex.
  *
- * In all notification cases cases (pre, post and abort rate change) the
- * original clock rate is passed to the callback via struct
- * clk_notifier_data.old_rate and the new frequency is passed via struct
- * clk_notifier_data.new_rate.
+ * In all notification cases (pre, post and abort rate change) the original
+ * clock rate is passed to the callback via struct clk_notifier_data.old_rate
+ * and the new frequency is passed via struct clk_notifier_data.new_rate.
  *
  * clk_notifier_register() must be called from non-atomic context.
  * Returns -EINVAL if called with null arguments, -ENOMEM upon
@@ -3062,9 +3079,6 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
 	int count;
 	struct clk *clk;
 
-	if (index < 0)
-		return NULL;
-
 	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
 					&clkspec);
 	if (rc)
@@ -3083,6 +3097,9 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
 		}
 		count++;
 	}
+	/* We went off the end of 'clock-indices' without finding it */
+	if (prop && !vp)
+		return NULL;
 
 	if (of_property_read_string_index(clkspec.np, "clock-output-names",
 					  index,
diff --git a/drivers/clk/imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c
index c4c141cab444..23686f756b5e 100644
--- a/drivers/clk/imx/clk-imx25.c
+++ b/drivers/clk/imx/clk-imx25.c
@@ -96,13 +96,11 @@ static struct clk ** const uart_clks[] __initconst = {
 	NULL
 };
 
-static int __init __mx25_clocks_init(unsigned long osc_rate,
-				     void __iomem *ccm_base)
+static int __init __mx25_clocks_init(void __iomem *ccm_base)
 {
 	BUG_ON(!ccm_base);
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
-	clk[osc] = imx_clk_fixed("osc", osc_rate);
 	clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "mpll", "osc", ccm(CCM_MPCTL));
 	clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "upll", "osc", ccm(CCM_UPCTL));
 	clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
@@ -250,22 +248,10 @@ static int __init __mx25_clocks_init(unsigned long osc_rate,
 
 static void __init mx25_clocks_init_dt(struct device_node *np)
 {
-	struct device_node *refnp;
-	unsigned long osc_rate = 24000000;
 	void __iomem *ccm;
 
-	/* retrieve the freqency of fixed clocks from device tree */
-	for_each_compatible_node(refnp, NULL, "fixed-clock") {
-		u32 rate;
-		if (of_property_read_u32(refnp, "clock-frequency", &rate))
-			continue;
-
-		if (of_device_is_compatible(refnp, "fsl,imx-osc"))
-			osc_rate = rate;
-	}
-
 	ccm = of_iomap(np, 0);
-	__mx25_clocks_init(osc_rate, ccm);
+	__mx25_clocks_init(ccm);
 
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c
index c6770348d2ab..29d4c44ef356 100644
--- a/drivers/clk/imx/clk-imx51-imx53.c
+++ b/drivers/clk/imx/clk-imx51-imx53.c
@@ -519,10 +519,10 @@ static void __init mx53_clocks_init(struct device_node *np)
 						mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
 	clk[IMX5_CLK_LDB_DI0_GATE]	= imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
 	clk[IMX5_CLK_LDB_DI1_GATE]	= imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
-	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
-						mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel));
-	clk[IMX5_CLK_IPU_DI1_SEL]	= imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
-						mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel));
+	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
+						mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_IPU_DI1_SEL]	= imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
+						mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel), CLK_SET_RATE_PARENT);
 	clk[IMX5_CLK_TVE_EXT_SEL]	= imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
 						mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
 	clk[IMX5_CLK_TVE_GATE]		= imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index c1935081d34a..f0efc6feeec2 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -70,7 +70,8 @@ static const char *cko_sels[] = { "cko1", "cko2", };
 static const char *lvds_sels[] = {
 	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
 	"pll4_audio", "pll5_video", "pll8_mlb", "enet_ref",
-	"pcie_ref_125m", "sata_ref_100m",
+	"pcie_ref_125m", "sata_ref_100m",  "usbphy1", "usbphy2",
+	"dummy", "dummy", "dummy", "dummy", "osc",
 };
 static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", };
 static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index 01718d05e952..08692d74b884 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -399,9 +399,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 	/* mask handshake of mmdc */
 	writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
 
-	for (i = 0; i < ARRAY_SIZE(clks); i++)
-		if (IS_ERR(clks[i]))
-			pr_err("i.MX6UL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+	imx_check_clocks(clks, ARRAY_SIZE(clks));
 
 	clk_data.clks = clks;
 	clk_data.clk_num = ARRAY_SIZE(clks);
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 448ef321948b..fbb6a8c8653d 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -833,10 +833,13 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 
 	clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
 
-	for (i = 0; i < ARRAY_SIZE(clks); i++)
-		if (IS_ERR(clks[i]))
-			pr_err("i.MX7D clk %d: register failed with %ld\n",
-					i, PTR_ERR(clks[i]));
+	clks[IMX7D_CLK_ARM] = imx_clk_cpu("arm", "arm_a7_root_clk",
+					 clks[IMX7D_ARM_A7_ROOT_CLK],
+					 clks[IMX7D_ARM_A7_ROOT_SRC],
+					 clks[IMX7D_PLL_ARM_MAIN_CLK],
+					 clks[IMX7D_PLL_SYS_MAIN_CLK]);
+
+	imx_check_clocks(clks, ARRAY_SIZE(clks));
 
 	clk_data.clks = clks;
 	clk_data.clk_num = ARRAY_SIZE(clks);
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index 6addf8f58b97..c05c43d56a94 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -97,6 +97,16 @@ static void clk_pllv3_unprepare(struct clk_hw *hw)
 	writel_relaxed(val, pll->base);
 }
 
+static int clk_pllv3_is_prepared(struct clk_hw *hw)
+{
+	struct clk_pllv3 *pll = to_clk_pllv3(hw);
+
+	if (readl_relaxed(pll->base) & BM_PLL_LOCK)
+		return 1;
+
+	return 0;
+}
+
 static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
 					   unsigned long parent_rate)
 {
@@ -139,6 +149,7 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
 static const struct clk_ops clk_pllv3_ops = {
 	.prepare	= clk_pllv3_prepare,
 	.unprepare	= clk_pllv3_unprepare,
+	.is_prepared	= clk_pllv3_is_prepared,
 	.recalc_rate	= clk_pllv3_recalc_rate,
 	.round_rate	= clk_pllv3_round_rate,
 	.set_rate	= clk_pllv3_set_rate,
@@ -193,6 +204,7 @@ static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
 static const struct clk_ops clk_pllv3_sys_ops = {
 	.prepare	= clk_pllv3_prepare,
 	.unprepare	= clk_pllv3_unprepare,
+	.is_prepared	= clk_pllv3_is_prepared,
 	.recalc_rate	= clk_pllv3_sys_recalc_rate,
 	.round_rate	= clk_pllv3_sys_round_rate,
 	.set_rate	= clk_pllv3_sys_set_rate,
@@ -265,6 +277,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
 static const struct clk_ops clk_pllv3_av_ops = {
 	.prepare	= clk_pllv3_prepare,
 	.unprepare	= clk_pllv3_unprepare,
+	.is_prepared	= clk_pllv3_is_prepared,
 	.recalc_rate	= clk_pllv3_av_recalc_rate,
 	.round_rate	= clk_pllv3_av_round_rate,
 	.set_rate	= clk_pllv3_av_set_rate,
@@ -279,6 +292,7 @@ static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
 static const struct clk_ops clk_pllv3_enet_ops = {
 	.prepare	= clk_pllv3_prepare,
 	.unprepare	= clk_pllv3_unprepare,
+	.is_prepared	= clk_pllv3_is_prepared,
 	.recalc_rate	= clk_pllv3_enet_recalc_rate,
 };
 
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index 645ac7ea3565..8866115486f7 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -7,6 +7,6 @@ obj-$(CONFIG_ARMADA_375_CLK)	+= armada-375.o
 obj-$(CONFIG_ARMADA_38X_CLK)	+= armada-38x.o
 obj-$(CONFIG_ARMADA_39X_CLK)	+= armada-39x.o
 obj-$(CONFIG_ARMADA_XP_CLK)	+= armada-xp.o
-obj-$(CONFIG_DOVE_CLK)		+= dove.o
+obj-$(CONFIG_DOVE_CLK)		+= dove.o dove-divider.o
 obj-$(CONFIG_KIRKWOOD_CLK)	+= kirkwood.o
 obj-$(CONFIG_ORION_CLK)		+= orion.o
diff --git a/drivers/clk/mvebu/dove-divider.c b/drivers/clk/mvebu/dove-divider.c
new file mode 100644
index 000000000000..d5c5bfa35a5a
--- /dev/null
+++ b/drivers/clk/mvebu/dove-divider.c
@@ -0,0 +1,262 @@
+/*
+ * Marvell Dove PMU Core PLL divider driver
+ *
+ * Cleaned up by substantially rewriting, and converted to DT by
+ * Russell King.  Origin is not known.
+ */
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "dove-divider.h"
+
+struct dove_clk {
+	const char *name;
+	struct clk_hw hw;
+	void __iomem *base;
+	spinlock_t *lock;
+	u8 div_bit_start;
+	u8 div_bit_end;
+	u8 div_bit_load;
+	u8 div_bit_size;
+	u32 *divider_table;
+};
+
+enum {
+	DIV_CTRL0 = 0,
+	DIV_CTRL1 = 4,
+	DIV_CTRL1_N_RESET_MASK = BIT(10),
+};
+
+#define to_dove_clk(hw) container_of(hw, struct dove_clk, hw)
+
+static void dove_load_divider(void __iomem *base, u32 val, u32 mask, u32 load)
+{
+	u32 v;
+
+	v = readl_relaxed(base + DIV_CTRL1) | DIV_CTRL1_N_RESET_MASK;
+	writel_relaxed(v, base + DIV_CTRL1);
+
+	v = (readl_relaxed(base + DIV_CTRL0) & ~(mask | load)) | val;
+	writel_relaxed(v, base + DIV_CTRL0);
+	writel_relaxed(v | load, base + DIV_CTRL0);
+	ndelay(250);
+	writel_relaxed(v, base + DIV_CTRL0);
+}
+
+static unsigned int dove_get_divider(struct dove_clk *dc)
+{
+	unsigned int divider;
+	u32 val;
+
+	val = readl_relaxed(dc->base + DIV_CTRL0);
+	val >>= dc->div_bit_start;
+
+	divider = val & ~(~0 << dc->div_bit_size);
+
+	if (dc->divider_table)
+		divider = dc->divider_table[divider];
+
+	return divider;
+}
+
+static int dove_calc_divider(const struct dove_clk *dc, unsigned long rate,
+			     unsigned long parent_rate, bool set)
+{
+	unsigned int divider, max;
+
+	divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+	if (dc->divider_table) {
+		unsigned int i;
+
+		for (i = 0; dc->divider_table[i]; i++)
+			if (divider == dc->divider_table[i]) {
+				divider = i;
+				break;
+			}
+
+		if (!dc->divider_table[i])
+			return -EINVAL;
+	} else {
+		max = 1 << dc->div_bit_size;
+
+		if (set && (divider == 0 || divider >= max))
+			return -EINVAL;
+		if (divider >= max)
+			divider = max - 1;
+		else if (divider == 0)
+			divider = 1;
+	}
+
+	return divider;
+}
+
+static unsigned long dove_recalc_rate(struct clk_hw *hw, unsigned long parent)
+{
+	struct dove_clk *dc = to_dove_clk(hw);
+	unsigned int divider = dove_get_divider(dc);
+	unsigned long rate = DIV_ROUND_CLOSEST(parent, divider);
+
+	pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
+		 __func__, dc->name, divider, parent, rate);
+
+	return rate;
+}
+
+static long dove_round_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long *parent)
+{
+	struct dove_clk *dc = to_dove_clk(hw);
+	unsigned long parent_rate = *parent;
+	int divider;
+
+	divider = dove_calc_divider(dc, rate, parent_rate, false);
+	if (divider < 0)
+		return divider;
+
+	rate = DIV_ROUND_CLOSEST(parent_rate, divider);
+
+	pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
+		 __func__, dc->name, divider, parent_rate, rate);
+
+	return rate;
+}
+
+static int dove_set_clock(struct clk_hw *hw, unsigned long rate,
+			  unsigned long parent_rate)
+{
+	struct dove_clk *dc = to_dove_clk(hw);
+	u32 mask, load, div;
+	int divider;
+
+	divider = dove_calc_divider(dc, rate, parent_rate, true);
+	if (divider < 0)
+		return divider;
+
+	pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
+		 __func__, dc->name, divider, parent_rate, rate);
+
+	div = (u32)divider << dc->div_bit_start;
+	mask = ~(~0 << dc->div_bit_size) << dc->div_bit_start;
+	load = BIT(dc->div_bit_load);
+
+	spin_lock(dc->lock);
+	dove_load_divider(dc->base, div, mask, load);
+	spin_unlock(dc->lock);
+
+	return 0;
+}
+
+static const struct clk_ops dove_divider_ops = {
+	.set_rate	= dove_set_clock,
+	.round_rate	= dove_round_rate,
+	.recalc_rate	= dove_recalc_rate,
+};
+
+static struct clk *clk_register_dove_divider(struct device *dev,
+	struct dove_clk *dc, const char **parent_names, size_t num_parents,
+	void __iomem *base)
+{
+	char name[32];
+	struct clk_init_data init = {
+		.name = name,
+		.ops = &dove_divider_ops,
+		.parent_names = parent_names,
+		.num_parents = num_parents,
+	};
+
+	strlcpy(name, dc->name, sizeof(name));
+
+	dc->hw.init = &init;
+	dc->base = base;
+	dc->div_bit_size = dc->div_bit_end - dc->div_bit_start + 1;
+
+	return clk_register(dev, &dc->hw);
+}
+
+static DEFINE_SPINLOCK(dove_divider_lock);
+
+static u32 axi_divider[] = {-1, 2, 1, 3, 4, 6, 5, 7, 8, 10, 9, 0};
+
+static struct dove_clk dove_hw_clocks[4] = {
+	{
+		.name = "axi",
+		.lock = &dove_divider_lock,
+		.div_bit_start = 1,
+		.div_bit_end = 6,
+		.div_bit_load = 7,
+		.divider_table = axi_divider,
+	}, {
+		.name = "gpu",
+		.lock = &dove_divider_lock,
+		.div_bit_start = 8,
+		.div_bit_end = 13,
+		.div_bit_load = 14,
+	}, {
+		.name = "vmeta",
+		.lock = &dove_divider_lock,
+		.div_bit_start = 15,
+		.div_bit_end = 20,
+		.div_bit_load = 21,
+	}, {
+		.name = "lcd",
+		.lock = &dove_divider_lock,
+		.div_bit_start = 22,
+		.div_bit_end = 27,
+		.div_bit_load = 28,
+	},
+};
+
+static const char *core_pll[] = {
+	"core-pll",
+};
+
+static int dove_divider_init(struct device *dev, void __iomem *base,
+	struct clk **clks)
+{
+	struct clk *clk;
+	int i;
+
+	/*
+	 * Create the core PLL clock.  We treat this as a fixed rate
+	 * clock as we don't know any better, and documentation is sparse.
+	 */
+	clk = clk_register_fixed_rate(dev, core_pll[0], NULL, CLK_IS_ROOT,
+				      2000000000UL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	for (i = 0; i < ARRAY_SIZE(dove_hw_clocks); i++)
+		clks[i] = clk_register_dove_divider(dev, &dove_hw_clocks[i],
+						    core_pll,
+						    ARRAY_SIZE(core_pll), base);
+
+	return 0;
+}
+
+static struct clk *dove_divider_clocks[4];
+
+static struct clk_onecell_data dove_divider_data = {
+	.clks = dove_divider_clocks,
+	.clk_num = ARRAY_SIZE(dove_divider_clocks),
+};
+
+void __init dove_divider_clk_init(struct device_node *np)
+{
+	void *base;
+
+	base = of_iomap(np, 0);
+	if (WARN_ON(!base))
+		return;
+
+	if (WARN_ON(dove_divider_init(NULL, base, dove_divider_clocks))) {
+		iounmap(base);
+		return;
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &dove_divider_data);
+}
diff --git a/drivers/clk/mvebu/dove-divider.h b/drivers/clk/mvebu/dove-divider.h
new file mode 100644
index 000000000000..4f2f718deb8e
--- /dev/null
+++ b/drivers/clk/mvebu/dove-divider.h
@@ -0,0 +1,6 @@
+#ifndef DOVE_DIVIDER_H
+#define DOVE_DIVIDER_H
+
+void __init dove_divider_clk_init(struct device_node *np);
+
+#endif
diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c
index b8c2424ac926..59fad9546c84 100644
--- a/drivers/clk/mvebu/dove.c
+++ b/drivers/clk/mvebu/dove.c
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include "common.h"
+#include "dove-divider.h"
 
 /*
  * Core Clocks
@@ -184,9 +185,14 @@ static void __init dove_clk_init(struct device_node *np)
 {
 	struct device_node *cgnp =
 		of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock");
+	struct device_node *ddnp =
+		of_find_compatible_node(NULL, NULL, "marvell,dove-divider-clock");
 
 	mvebu_coreclk_setup(np, &dove_coreclks);
 
+	if (ddnp)
+		dove_divider_clk_init(ddnp);
+
 	if (cgnp)
 		mvebu_clk_gating_setup(cgnp, dove_gating_desc);
 }
diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
index 7f608b0ad7b4..607bd48c6563 100644
--- a/drivers/clk/nxp/Makefile
+++ b/drivers/clk/nxp/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
 obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-ccu.o
+obj-$(CONFIG_ARCH_LPC32XX)	+= clk-lpc32xx.o
diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
new file mode 100644
index 000000000000..10dd0fdaa474
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -0,0 +1,1569 @@
+/*
+ * Copyright 2015 Vladimir Zapolskiy <vz@mleia.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/lpc32xx-clock.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+/* Common bitfield definitions for x397 PLL (lock), USB PLL and HCLK PLL */
+#define PLL_CTRL_ENABLE			BIT(16)
+#define PLL_CTRL_BYPASS			BIT(15)
+#define PLL_CTRL_DIRECT			BIT(14)
+#define PLL_CTRL_FEEDBACK		BIT(13)
+#define PLL_CTRL_POSTDIV		(BIT(12)|BIT(11))
+#define PLL_CTRL_PREDIV			(BIT(10)|BIT(9))
+#define PLL_CTRL_FEEDDIV		(0xFF << 1)
+#define PLL_CTRL_LOCK			BIT(0)
+
+/* Clock registers on System Control Block */
+#define LPC32XX_CLKPWR_DEBUG_CTRL	0x00
+#define LPC32XX_CLKPWR_USB_DIV		0x1C
+#define LPC32XX_CLKPWR_HCLKDIV_CTRL	0x40
+#define LPC32XX_CLKPWR_PWR_CTRL		0x44
+#define LPC32XX_CLKPWR_PLL397_CTRL	0x48
+#define LPC32XX_CLKPWR_OSC_CTRL		0x4C
+#define LPC32XX_CLKPWR_SYSCLK_CTRL	0x50
+#define LPC32XX_CLKPWR_LCDCLK_CTRL	0x54
+#define LPC32XX_CLKPWR_HCLKPLL_CTRL	0x58
+#define LPC32XX_CLKPWR_ADCCLK_CTRL1	0x60
+#define LPC32XX_CLKPWR_USB_CTRL		0x64
+#define LPC32XX_CLKPWR_SSP_CTRL		0x78
+#define LPC32XX_CLKPWR_I2S_CTRL		0x7C
+#define LPC32XX_CLKPWR_MS_CTRL		0x80
+#define LPC32XX_CLKPWR_MACCLK_CTRL	0x90
+#define LPC32XX_CLKPWR_TEST_CLK_CTRL	0xA4
+#define LPC32XX_CLKPWR_I2CCLK_CTRL	0xAC
+#define LPC32XX_CLKPWR_KEYCLK_CTRL	0xB0
+#define LPC32XX_CLKPWR_ADCCLK_CTRL	0xB4
+#define LPC32XX_CLKPWR_PWMCLK_CTRL	0xB8
+#define LPC32XX_CLKPWR_TIMCLK_CTRL	0xBC
+#define LPC32XX_CLKPWR_TIMCLK_CTRL1	0xC0
+#define LPC32XX_CLKPWR_SPI_CTRL		0xC4
+#define LPC32XX_CLKPWR_FLASHCLK_CTRL	0xC8
+#define LPC32XX_CLKPWR_UART3_CLK_CTRL	0xD0
+#define LPC32XX_CLKPWR_UART4_CLK_CTRL	0xD4
+#define LPC32XX_CLKPWR_UART5_CLK_CTRL	0xD8
+#define LPC32XX_CLKPWR_UART6_CLK_CTRL	0xDC
+#define LPC32XX_CLKPWR_IRDA_CLK_CTRL	0xE0
+#define LPC32XX_CLKPWR_UART_CLK_CTRL	0xE4
+#define LPC32XX_CLKPWR_DMA_CLK_CTRL	0xE8
+
+/* Clock registers on USB controller */
+#define LPC32XX_USB_CLK_CTRL		0xF4
+#define LPC32XX_USB_CLK_STS		0xF8
+
+static struct regmap_config lpc32xx_scb_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
+	.max_register = 0x114,
+	.fast_io = true,
+};
+
+static struct regmap *clk_regmap;
+static void __iomem *usb_clk_vbase;
+
+enum {
+	LPC32XX_USB_CLK_OTG = LPC32XX_USB_CLK_HOST + 1,
+	LPC32XX_USB_CLK_AHB,
+
+	LPC32XX_USB_CLK_MAX = LPC32XX_USB_CLK_AHB + 1,
+};
+
+enum {
+	/* Start from the last defined clock in dt bindings */
+	LPC32XX_CLK_ADC_DIV = LPC32XX_CLK_ADC + 1,
+	LPC32XX_CLK_ADC_RTC,
+	LPC32XX_CLK_TEST1,
+	LPC32XX_CLK_TEST2,
+
+	/* System clocks, PLL 397x and HCLK PLL clocks */
+	LPC32XX_CLK_OSC,
+	LPC32XX_CLK_SYS,
+	LPC32XX_CLK_PLL397X,
+	LPC32XX_CLK_HCLK_PLL,
+	LPC32XX_CLK_HCLK_DIV_PERIPH,
+	LPC32XX_CLK_HCLK_DIV,
+	LPC32XX_CLK_HCLK,
+	LPC32XX_CLK_PERIPH,
+	LPC32XX_CLK_ARM,
+	LPC32XX_CLK_ARM_VFP,
+
+	/* USB clocks */
+	LPC32XX_CLK_USB_PLL,
+	LPC32XX_CLK_USB_DIV,
+	LPC32XX_CLK_USB,
+
+	/* Only one control PWR_CTRL[10] for both muxes */
+	LPC32XX_CLK_PERIPH_HCLK_MUX,
+	LPC32XX_CLK_PERIPH_ARM_MUX,
+
+	/* Only one control PWR_CTRL[2] for all three muxes */
+	LPC32XX_CLK_SYSCLK_PERIPH_MUX,
+	LPC32XX_CLK_SYSCLK_HCLK_MUX,
+	LPC32XX_CLK_SYSCLK_ARM_MUX,
+
+	/* Two clock sources external to the driver */
+	LPC32XX_CLK_XTAL_32K,
+	LPC32XX_CLK_XTAL,
+
+	/* Renumbered USB clocks, may have a parent from SCB table */
+	LPC32XX_CLK_USB_OFFSET,
+	LPC32XX_CLK_USB_I2C = LPC32XX_USB_CLK_I2C + LPC32XX_CLK_USB_OFFSET,
+	LPC32XX_CLK_USB_DEV = LPC32XX_USB_CLK_DEVICE + LPC32XX_CLK_USB_OFFSET,
+	LPC32XX_CLK_USB_HOST = LPC32XX_USB_CLK_HOST + LPC32XX_CLK_USB_OFFSET,
+	LPC32XX_CLK_USB_OTG = LPC32XX_USB_CLK_OTG + LPC32XX_CLK_USB_OFFSET,
+	LPC32XX_CLK_USB_AHB = LPC32XX_USB_CLK_AHB + LPC32XX_CLK_USB_OFFSET,
+
+	/* Stub for composite clocks */
+	LPC32XX_CLK__NULL,
+
+	/* Subclocks of composite clocks, clocks above are for CCF */
+	LPC32XX_CLK_PWM1_MUX,
+	LPC32XX_CLK_PWM1_DIV,
+	LPC32XX_CLK_PWM1_GATE,
+	LPC32XX_CLK_PWM2_MUX,
+	LPC32XX_CLK_PWM2_DIV,
+	LPC32XX_CLK_PWM2_GATE,
+	LPC32XX_CLK_UART3_MUX,
+	LPC32XX_CLK_UART3_DIV,
+	LPC32XX_CLK_UART3_GATE,
+	LPC32XX_CLK_UART4_MUX,
+	LPC32XX_CLK_UART4_DIV,
+	LPC32XX_CLK_UART4_GATE,
+	LPC32XX_CLK_UART5_MUX,
+	LPC32XX_CLK_UART5_DIV,
+	LPC32XX_CLK_UART5_GATE,
+	LPC32XX_CLK_UART6_MUX,
+	LPC32XX_CLK_UART6_DIV,
+	LPC32XX_CLK_UART6_GATE,
+	LPC32XX_CLK_TEST1_MUX,
+	LPC32XX_CLK_TEST1_GATE,
+	LPC32XX_CLK_TEST2_MUX,
+	LPC32XX_CLK_TEST2_GATE,
+	LPC32XX_CLK_USB_DIV_DIV,
+	LPC32XX_CLK_USB_DIV_GATE,
+	LPC32XX_CLK_SD_DIV,
+	LPC32XX_CLK_SD_GATE,
+	LPC32XX_CLK_LCD_DIV,
+	LPC32XX_CLK_LCD_GATE,
+
+	LPC32XX_CLK_HW_MAX,
+	LPC32XX_CLK_MAX = LPC32XX_CLK_SYSCLK_ARM_MUX + 1,
+	LPC32XX_CLK_CCF_MAX = LPC32XX_CLK_USB_AHB + 1,
+};
+
+static struct clk *clk[LPC32XX_CLK_MAX];
+static struct clk_onecell_data clk_data = {
+	.clks = clk,
+	.clk_num = LPC32XX_CLK_MAX,
+};
+
+static struct clk *usb_clk[LPC32XX_USB_CLK_MAX];
+static struct clk_onecell_data usb_clk_data = {
+	.clks = usb_clk,
+	.clk_num = LPC32XX_USB_CLK_MAX,
+};
+
+#define LPC32XX_CLK_PARENTS_MAX			5
+
+struct clk_proto_t {
+	const char *name;
+	const u8 parents[LPC32XX_CLK_PARENTS_MAX];
+	u8 num_parents;
+	unsigned long flags;
+};
+
+#define CLK_PREFIX(LITERAL)		LPC32XX_CLK_ ## LITERAL
+#define NUMARGS(...)	(sizeof((int[]){__VA_ARGS__})/sizeof(int))
+
+#define LPC32XX_CLK_DEFINE(_idx, _name, _flags, ...)		\
+	[CLK_PREFIX(_idx)] = {					\
+		.name = _name,					\
+		.flags = _flags,				\
+		.parents = { __VA_ARGS__ },			\
+		.num_parents = NUMARGS(__VA_ARGS__),		\
+	 }
+
+static const struct clk_proto_t clk_proto[LPC32XX_CLK_CCF_MAX] __initconst = {
+	LPC32XX_CLK_DEFINE(XTAL, "xtal", 0x0),
+	LPC32XX_CLK_DEFINE(XTAL_32K, "xtal_32k", 0x0),
+
+	LPC32XX_CLK_DEFINE(RTC, "rtc", 0x0, LPC32XX_CLK_XTAL_32K),
+	LPC32XX_CLK_DEFINE(OSC, "osc", CLK_IGNORE_UNUSED, LPC32XX_CLK_XTAL),
+	LPC32XX_CLK_DEFINE(SYS, "sys", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_OSC, LPC32XX_CLK_PLL397X),
+	LPC32XX_CLK_DEFINE(PLL397X, "pll_397x", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_RTC),
+	LPC32XX_CLK_DEFINE(HCLK_PLL, "hclk_pll", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYS),
+	LPC32XX_CLK_DEFINE(HCLK_DIV_PERIPH, "hclk_div_periph",
+		CLK_IGNORE_UNUSED, LPC32XX_CLK_HCLK_PLL),
+	LPC32XX_CLK_DEFINE(HCLK_DIV, "hclk_div", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_HCLK_PLL),
+	LPC32XX_CLK_DEFINE(HCLK, "hclk", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_PERIPH_HCLK_MUX),
+	LPC32XX_CLK_DEFINE(PERIPH, "pclk", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYSCLK_PERIPH_MUX),
+	LPC32XX_CLK_DEFINE(ARM, "arm", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_PERIPH_ARM_MUX),
+
+	LPC32XX_CLK_DEFINE(PERIPH_HCLK_MUX, "periph_hclk_mux",
+		CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYSCLK_HCLK_MUX, LPC32XX_CLK_SYSCLK_PERIPH_MUX),
+	LPC32XX_CLK_DEFINE(PERIPH_ARM_MUX, "periph_arm_mux", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYSCLK_ARM_MUX, LPC32XX_CLK_SYSCLK_PERIPH_MUX),
+	LPC32XX_CLK_DEFINE(SYSCLK_PERIPH_MUX, "sysclk_periph_mux",
+		CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYS, LPC32XX_CLK_HCLK_DIV_PERIPH),
+	LPC32XX_CLK_DEFINE(SYSCLK_HCLK_MUX, "sysclk_hclk_mux",
+		CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYS, LPC32XX_CLK_HCLK_DIV),
+	LPC32XX_CLK_DEFINE(SYSCLK_ARM_MUX, "sysclk_arm_mux", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_SYS, LPC32XX_CLK_HCLK_PLL),
+
+	LPC32XX_CLK_DEFINE(ARM_VFP, "vfp9", CLK_IGNORE_UNUSED,
+		LPC32XX_CLK_ARM),
+	LPC32XX_CLK_DEFINE(USB_PLL, "usb_pll",
+		CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT, LPC32XX_CLK_USB_DIV),
+	LPC32XX_CLK_DEFINE(USB_DIV, "usb_div", 0x0, LPC32XX_CLK_OSC),
+	LPC32XX_CLK_DEFINE(USB, "usb", 0x0, LPC32XX_CLK_USB_PLL),
+	LPC32XX_CLK_DEFINE(DMA, "dma", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(MLC, "mlc", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(SLC, "slc", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(LCD, "lcd", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(MAC, "mac", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(SD, "sd", 0x0, LPC32XX_CLK_ARM),
+	LPC32XX_CLK_DEFINE(DDRAM, "ddram", CLK_GET_RATE_NOCACHE,
+		LPC32XX_CLK_SYSCLK_ARM_MUX),
+	LPC32XX_CLK_DEFINE(SSP0, "ssp0", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(SSP1, "ssp1", 0x0, LPC32XX_CLK_HCLK),
+
+	/*
+	 * CLK_GET_RATE_NOCACHE is needed, if UART clock is disabled, its
+	 * divider register does not contain information about selected rate.
+	 */
+	LPC32XX_CLK_DEFINE(UART3, "uart3", CLK_GET_RATE_NOCACHE,
+		LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(UART4, "uart4", CLK_GET_RATE_NOCACHE,
+		LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(UART5, "uart5", CLK_GET_RATE_NOCACHE,
+		LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(UART6, "uart6", CLK_GET_RATE_NOCACHE,
+		LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(IRDA, "irda", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(I2C1, "i2c1", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(I2C2, "i2c2", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(TIMER0, "timer0", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(TIMER1, "timer1", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(TIMER2, "timer2", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(TIMER3, "timer3", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(TIMER4, "timer4", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(TIMER5, "timer5", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(WDOG, "watchdog", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(I2S0, "i2s0", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(I2S1, "i2s1", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(SPI1, "spi1", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(SPI2, "spi2", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(MCPWM, "mcpwm", 0x0, LPC32XX_CLK_HCLK),
+	LPC32XX_CLK_DEFINE(HSTIMER, "hstimer", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(KEY, "key", 0x0, LPC32XX_CLK_RTC),
+	LPC32XX_CLK_DEFINE(PWM1, "pwm1", 0x0,
+		LPC32XX_CLK_RTC, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(PWM2, "pwm2", 0x0,
+		LPC32XX_CLK_RTC, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(ADC, "adc", 0x0,
+		LPC32XX_CLK_ADC_RTC, LPC32XX_CLK_ADC_DIV),
+	LPC32XX_CLK_DEFINE(ADC_DIV, "adc_div", 0x0, LPC32XX_CLK_PERIPH),
+	LPC32XX_CLK_DEFINE(ADC_RTC, "adc_rtc", 0x0, LPC32XX_CLK_RTC),
+	LPC32XX_CLK_DEFINE(TEST1, "test1", 0x0,
+		LPC32XX_CLK_PERIPH, LPC32XX_CLK_RTC, LPC32XX_CLK_OSC),
+	LPC32XX_CLK_DEFINE(TEST2, "test2", 0x0,
+		LPC32XX_CLK_HCLK, LPC32XX_CLK_PERIPH, LPC32XX_CLK_USB,
+		LPC32XX_CLK_OSC, LPC32XX_CLK_PLL397X),
+
+	/* USB controller clocks */
+	LPC32XX_CLK_DEFINE(USB_AHB, "usb_ahb", 0x0, LPC32XX_CLK_USB),
+	LPC32XX_CLK_DEFINE(USB_OTG, "usb_otg", 0x0, LPC32XX_CLK_USB_AHB),
+	LPC32XX_CLK_DEFINE(USB_I2C, "usb_i2c", 0x0, LPC32XX_CLK_USB_AHB),
+	LPC32XX_CLK_DEFINE(USB_DEV, "usb_dev", 0x0, LPC32XX_CLK_USB_OTG),
+	LPC32XX_CLK_DEFINE(USB_HOST, "usb_host", 0x0, LPC32XX_CLK_USB_OTG),
+};
+
+struct lpc32xx_clk {
+	struct clk_hw hw;
+	u32 reg;
+	u32 enable;
+	u32 enable_mask;
+	u32 disable;
+	u32 disable_mask;
+	u32 busy;
+	u32 busy_mask;
+};
+
+enum clk_pll_mode {
+	PLL_UNKNOWN,
+	PLL_DIRECT,
+	PLL_BYPASS,
+	PLL_DIRECT_BYPASS,
+	PLL_INTEGER,
+	PLL_NON_INTEGER,
+};
+
+struct lpc32xx_pll_clk {
+	struct clk_hw hw;
+	u32 reg;
+	u32 enable;
+	unsigned long m_div;
+	unsigned long n_div;
+	unsigned long p_div;
+	enum clk_pll_mode mode;
+};
+
+struct lpc32xx_usb_clk {
+	struct clk_hw hw;
+	u32 ctrl_enable;
+	u32 ctrl_disable;
+	u32 ctrl_mask;
+	u32 enable;
+	u32 busy;
+};
+
+struct lpc32xx_clk_mux {
+	struct clk_hw	hw;
+	u32		reg;
+	u32		mask;
+	u8		shift;
+	u32		*table;
+	u8		flags;
+};
+
+struct lpc32xx_clk_div {
+	struct clk_hw	hw;
+	u32		reg;
+	u8		shift;
+	u8		width;
+	const struct clk_div_table	*table;
+	u8		flags;
+};
+
+struct lpc32xx_clk_gate {
+	struct clk_hw	hw;
+	u32		reg;
+	u8		bit_idx;
+	u8		flags;
+};
+
+#define to_lpc32xx_clk(_hw)	container_of(_hw, struct lpc32xx_clk, hw)
+#define to_lpc32xx_pll_clk(_hw)	container_of(_hw, struct lpc32xx_pll_clk, hw)
+#define to_lpc32xx_usb_clk(_hw)	container_of(_hw, struct lpc32xx_usb_clk, hw)
+#define to_lpc32xx_mux(_hw)	container_of(_hw, struct lpc32xx_clk_mux, hw)
+#define to_lpc32xx_div(_hw)	container_of(_hw, struct lpc32xx_clk_div, hw)
+#define to_lpc32xx_gate(_hw)	container_of(_hw, struct lpc32xx_clk_gate, hw)
+
+static inline bool pll_is_valid(u64 val0, u64 val1, u64 min, u64 max)
+{
+	return (val0 >= (val1 * min) && val0 <= (val1 * max));
+}
+
+static inline u32 lpc32xx_usb_clk_read(struct lpc32xx_usb_clk *clk)
+{
+	return readl(usb_clk_vbase + LPC32XX_USB_CLK_STS);
+}
+
+static inline void lpc32xx_usb_clk_write(struct lpc32xx_usb_clk *clk, u32 val)
+{
+	writel(val, usb_clk_vbase + LPC32XX_USB_CLK_CTRL);
+}
+
+static int clk_mask_enable(struct clk_hw *hw)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+	u32 val;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+
+	if (clk->busy_mask && (val & clk->busy_mask) == clk->busy)
+		return -EBUSY;
+
+	return regmap_update_bits(clk_regmap, clk->reg,
+				  clk->enable_mask, clk->enable);
+}
+
+static void clk_mask_disable(struct clk_hw *hw)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+
+	regmap_update_bits(clk_regmap, clk->reg,
+			   clk->disable_mask, clk->disable);
+}
+
+static int clk_mask_is_enabled(struct clk_hw *hw)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+	u32 val;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+
+	return ((val & clk->enable_mask) == clk->enable);
+}
+
+static const struct clk_ops clk_mask_ops = {
+	.enable = clk_mask_enable,
+	.disable = clk_mask_disable,
+	.is_enabled = clk_mask_is_enabled,
+};
+
+static int clk_pll_enable(struct clk_hw *hw)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+	u32 val, count;
+
+	regmap_update_bits(clk_regmap, clk->reg, clk->enable, clk->enable);
+
+	for (count = 0; count < 1000; count++) {
+		regmap_read(clk_regmap, clk->reg, &val);
+		if (val & PLL_CTRL_LOCK)
+			break;
+	}
+
+	if (val & PLL_CTRL_LOCK)
+		return 0;
+
+	return -ETIMEDOUT;
+}
+
+static void clk_pll_disable(struct clk_hw *hw)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+
+	regmap_update_bits(clk_regmap, clk->reg, clk->enable, 0x0);
+}
+
+static int clk_pll_is_enabled(struct clk_hw *hw)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+	u32 val;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+
+	val &= clk->enable | PLL_CTRL_LOCK;
+	if (val == (clk->enable | PLL_CTRL_LOCK))
+		return 1;
+
+	return 0;
+}
+
+static unsigned long clk_pll_397x_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	return parent_rate * 397;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+	bool is_direct, is_bypass, is_feedback;
+	unsigned long rate, cco_rate, ref_rate;
+	u32 val;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+	is_direct = val & PLL_CTRL_DIRECT;
+	is_bypass = val & PLL_CTRL_BYPASS;
+	is_feedback = val & PLL_CTRL_FEEDBACK;
+
+	clk->m_div = ((val & PLL_CTRL_FEEDDIV) >> 1) + 1;
+	clk->n_div = ((val & PLL_CTRL_PREDIV) >> 9) + 1;
+	clk->p_div = ((val & PLL_CTRL_POSTDIV) >> 11) + 1;
+
+	if (is_direct && is_bypass) {
+		clk->p_div = 0;
+		clk->mode = PLL_DIRECT_BYPASS;
+		return parent_rate;
+	}
+	if (is_bypass) {
+		clk->mode = PLL_BYPASS;
+		return parent_rate / (1 << clk->p_div);
+	}
+	if (is_direct) {
+		clk->p_div = 0;
+		clk->mode = PLL_DIRECT;
+	}
+
+	ref_rate = parent_rate / clk->n_div;
+	rate = cco_rate = ref_rate * clk->m_div;
+
+	if (!is_direct) {
+		if (is_feedback) {
+			cco_rate *= (1 << clk->p_div);
+			clk->mode = PLL_INTEGER;
+		} else {
+			rate /= (1 << clk->p_div);
+			clk->mode = PLL_NON_INTEGER;
+		}
+	}
+
+	pr_debug("%s: %lu: 0x%x: %d/%d/%d, %lu/%lu/%d => %lu\n",
+		 clk_hw_get_name(hw),
+		 parent_rate, val, is_direct, is_bypass, is_feedback,
+		 clk->n_div, clk->m_div, (1 << clk->p_div), rate);
+
+	if (clk_pll_is_enabled(hw) &&
+	    !(pll_is_valid(parent_rate, 1, 1000000, 20000000)
+	      && pll_is_valid(cco_rate, 1, 156000000, 320000000)
+	      && pll_is_valid(ref_rate, 1, 1000000, 27000000)))
+		pr_err("%s: PLL clocks are not in valid ranges: %lu/%lu/%lu",
+		       clk_hw_get_name(hw),
+		       parent_rate, cco_rate, ref_rate);
+
+	return rate;
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+	u32 val;
+	unsigned long new_rate;
+
+	/* Validate PLL clock parameters computed on round rate stage */
+	switch (clk->mode) {
+	case PLL_DIRECT:
+		val = PLL_CTRL_DIRECT;
+		val |= (clk->m_div - 1) << 1;
+		val |= (clk->n_div - 1) << 9;
+		new_rate = (parent_rate * clk->m_div) / clk->n_div;
+		break;
+	case PLL_BYPASS:
+		val = PLL_CTRL_BYPASS;
+		val |= (clk->p_div - 1) << 11;
+		new_rate = parent_rate / (1 << (clk->p_div));
+		break;
+	case PLL_DIRECT_BYPASS:
+		val = PLL_CTRL_DIRECT | PLL_CTRL_BYPASS;
+		new_rate = parent_rate;
+		break;
+	case PLL_INTEGER:
+		val = PLL_CTRL_FEEDBACK;
+		val |= (clk->m_div - 1) << 1;
+		val |= (clk->n_div - 1) << 9;
+		val |= (clk->p_div - 1) << 11;
+		new_rate = (parent_rate * clk->m_div) / clk->n_div;
+		break;
+	case PLL_NON_INTEGER:
+		val = 0x0;
+		val |= (clk->m_div - 1) << 1;
+		val |= (clk->n_div - 1) << 9;
+		val |= (clk->p_div - 1) << 11;
+		new_rate = (parent_rate * clk->m_div) /
+				(clk->n_div * (1 << clk->p_div));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Sanity check that round rate is equal to the requested one */
+	if (new_rate != rate)
+		return -EINVAL;
+
+	return regmap_update_bits(clk_regmap, clk->reg, 0x1FFFF, val);
+}
+
+static long clk_hclk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+	u64 m_i, m, n, p, o = rate, i = *parent_rate, d = (u64)rate << 6;
+	int p_i, n_i;
+
+	pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), *parent_rate, rate);
+
+	if (rate > 266500000)
+		return -EINVAL;
+
+	/* Have to check all 20 possibilities to find the minimal M */
+	for (p_i = 4; p_i >= 0; p_i--) {
+		for (n_i = 4; n_i > 0; n_i--) {
+			m_i = div64_u64(o * n_i * (1 << p_i), i);
+
+			/* Check for valid PLL parameter constraints */
+			if (!(m_i && m_i <= 256
+			      && pll_is_valid(i, n_i, 1000000, 27000000)
+			      && pll_is_valid(i * m_i * (1 << p_i), n_i,
+					      156000000, 320000000)))
+				continue;
+
+			/* Store some intermediate valid parameters */
+			if (o * n_i * (1 << p_i) - i * m_i <= d) {
+				m = m_i;
+				n = n_i;
+				p = p_i;
+				d = o * n_i * (1 << p_i) - i * m_i;
+			}
+		}
+	}
+
+	if (d == (u64)rate << 6) {
+		pr_err("%s: %lu: no valid PLL parameters are found\n",
+		       clk_hw_get_name(hw), rate);
+		return -EINVAL;
+	}
+
+	clk->m_div = m;
+	clk->n_div = n;
+	clk->p_div = p;
+
+	/* Set only direct or non-integer mode of PLL */
+	if (!p)
+		clk->mode = PLL_DIRECT;
+	else
+		clk->mode = PLL_NON_INTEGER;
+
+	o = div64_u64(i * m, n * (1 << p));
+
+	if (!d)
+		pr_debug("%s: %lu: found exact match: %llu/%llu/%llu\n",
+			 clk_hw_get_name(hw), rate, m, n, p);
+	else
+		pr_debug("%s: %lu: found closest: %llu/%llu/%llu - %llu\n",
+			 clk_hw_get_name(hw), rate, m, n, p, o);
+
+	return o;
+}
+
+static long clk_usb_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *parent_rate)
+{
+	struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
+	struct clk_hw *usb_div_hw, *osc_hw;
+	u64 d_i, n_i, m, o;
+
+	pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), *parent_rate, rate);
+
+	/*
+	 * The only supported USB clock is 48MHz, with PLL internal constraints
+	 * on Fclkin, Fcco and Fref this implies that Fcco must be 192MHz
+	 * and post-divider must be 4, this slightly simplifies calculation of
+	 * USB divider, USB PLL N and M parameters.
+	 */
+	if (rate != 48000000)
+		return -EINVAL;
+
+	/* USB divider clock */
+	usb_div_hw = clk_hw_get_parent_by_index(hw, 0);
+	if (!usb_div_hw)
+		return -EINVAL;
+
+	/* Main oscillator clock */
+	osc_hw = clk_hw_get_parent_by_index(usb_div_hw, 0);
+	if (!osc_hw)
+		return -EINVAL;
+	o = clk_hw_get_rate(osc_hw);	/* must be in range 1..20 MHz */
+
+	/* Check if valid USB divider and USB PLL parameters exists */
+	for (d_i = 16; d_i >= 1; d_i--) {
+		for (n_i = 1; n_i <= 4; n_i++) {
+			m = div64_u64(192000000 * d_i * n_i, o);
+			if (!(m && m <= 256
+			      && m * o == 192000000 * d_i * n_i
+			      && pll_is_valid(o, d_i, 1000000, 20000000)
+			      && pll_is_valid(o, d_i * n_i, 1000000, 27000000)))
+				continue;
+
+			clk->n_div = n_i;
+			clk->m_div = m;
+			clk->p_div = 2;
+			clk->mode = PLL_NON_INTEGER;
+			*parent_rate = div64_u64(o, d_i);
+
+			return rate;
+		}
+	}
+
+	return -EINVAL;
+}
+
+#define LPC32XX_DEFINE_PLL_OPS(_name, _rc, _sr, _rr)			\
+	static const struct clk_ops clk_ ##_name ## _ops = {		\
+		.enable = clk_pll_enable,				\
+		.disable = clk_pll_disable,				\
+		.is_enabled = clk_pll_is_enabled,			\
+		.recalc_rate = _rc,					\
+		.set_rate = _sr,					\
+		.round_rate = _rr,					\
+	}
+
+LPC32XX_DEFINE_PLL_OPS(pll_397x, clk_pll_397x_recalc_rate, NULL, NULL);
+LPC32XX_DEFINE_PLL_OPS(hclk_pll, clk_pll_recalc_rate,
+		       clk_pll_set_rate, clk_hclk_pll_round_rate);
+LPC32XX_DEFINE_PLL_OPS(usb_pll,  clk_pll_recalc_rate,
+		       clk_pll_set_rate, clk_usb_pll_round_rate);
+
+static int clk_ddram_is_enabled(struct clk_hw *hw)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+	u32 val;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+	val &= clk->enable_mask | clk->busy_mask;
+
+	return (val == (BIT(7) | BIT(0)) ||
+		val == (BIT(8) | BIT(1)));
+}
+
+static int clk_ddram_enable(struct clk_hw *hw)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+	u32 val, hclk_div;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+	hclk_div = val & clk->busy_mask;
+
+	/*
+	 * DDRAM clock must be 2 times higher than HCLK,
+	 * this implies DDRAM clock can not be enabled,
+	 * if HCLK clock rate is equal to ARM clock rate
+	 */
+	if (hclk_div == 0x0 || hclk_div == (BIT(1) | BIT(0)))
+		return -EINVAL;
+
+	return regmap_update_bits(clk_regmap, clk->reg,
+				  clk->enable_mask, hclk_div << 7);
+}
+
+static unsigned long clk_ddram_recalc_rate(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+	u32 val;
+
+	if (!clk_ddram_is_enabled(hw))
+		return 0;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+	val &= clk->enable_mask;
+
+	return parent_rate / (val >> 7);
+}
+
+static const struct clk_ops clk_ddram_ops = {
+	.enable = clk_ddram_enable,
+	.disable = clk_mask_disable,
+	.is_enabled = clk_ddram_is_enabled,
+	.recalc_rate = clk_ddram_recalc_rate,
+};
+
+static unsigned long lpc32xx_clk_uart_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct lpc32xx_clk *clk = to_lpc32xx_clk(hw);
+	u32 val, x, y;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+	x = (val & 0xFF00) >> 8;
+	y = val & 0xFF;
+
+	if (x && y)
+		return (parent_rate * x) / y;
+	else
+		return 0;
+}
+
+static const struct clk_ops lpc32xx_uart_div_ops = {
+	.recalc_rate = lpc32xx_clk_uart_recalc_rate,
+};
+
+static const struct clk_div_table clk_hclk_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ },
+};
+
+static u32 test1_mux_table[] = { 0, 1, 2, };
+static u32 test2_mux_table[] = { 0, 1, 2, 5, 7, };
+
+static int clk_usb_enable(struct clk_hw *hw)
+{
+	struct lpc32xx_usb_clk *clk = to_lpc32xx_usb_clk(hw);
+	u32 val, ctrl_val, count;
+
+	pr_debug("%s: 0x%x\n", clk_hw_get_name(hw), clk->enable);
+
+	if (clk->ctrl_mask) {
+		regmap_read(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, &ctrl_val);
+		regmap_update_bits(clk_regmap, LPC32XX_CLKPWR_USB_CTRL,
+				   clk->ctrl_mask, clk->ctrl_enable);
+	}
+
+	val = lpc32xx_usb_clk_read(clk);
+	if (clk->busy && (val & clk->busy) == clk->busy) {
+		if (clk->ctrl_mask)
+			regmap_write(clk_regmap, LPC32XX_CLKPWR_USB_CTRL,
+				     ctrl_val);
+		return -EBUSY;
+	}
+
+	val |= clk->enable;
+	lpc32xx_usb_clk_write(clk, val);
+
+	for (count = 0; count < 1000; count++) {
+		val = lpc32xx_usb_clk_read(clk);
+		if ((val & clk->enable) == clk->enable)
+			break;
+	}
+
+	if ((val & clk->enable) == clk->enable)
+		return 0;
+
+	if (clk->ctrl_mask)
+		regmap_write(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, ctrl_val);
+
+	return -ETIMEDOUT;
+}
+
+static void clk_usb_disable(struct clk_hw *hw)
+{
+	struct lpc32xx_usb_clk *clk = to_lpc32xx_usb_clk(hw);
+	u32 val = lpc32xx_usb_clk_read(clk);
+
+	val &= ~clk->enable;
+	lpc32xx_usb_clk_write(clk, val);
+
+	if (clk->ctrl_mask)
+		regmap_update_bits(clk_regmap, LPC32XX_CLKPWR_USB_CTRL,
+				   clk->ctrl_mask, clk->ctrl_disable);
+}
+
+static int clk_usb_is_enabled(struct clk_hw *hw)
+{
+	struct lpc32xx_usb_clk *clk = to_lpc32xx_usb_clk(hw);
+	u32 ctrl_val, val;
+
+	if (clk->ctrl_mask) {
+		regmap_read(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, &ctrl_val);
+		if ((ctrl_val & clk->ctrl_mask) != clk->ctrl_enable)
+			return 0;
+	}
+
+	val = lpc32xx_usb_clk_read(clk);
+
+	return ((val & clk->enable) == clk->enable);
+}
+
+static unsigned long clk_usb_i2c_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	return clk_get_rate(clk[LPC32XX_CLK_PERIPH]);
+}
+
+static const struct clk_ops clk_usb_ops = {
+	.enable = clk_usb_enable,
+	.disable = clk_usb_disable,
+	.is_enabled = clk_usb_is_enabled,
+};
+
+static const struct clk_ops clk_usb_i2c_ops = {
+	.enable = clk_usb_enable,
+	.disable = clk_usb_disable,
+	.is_enabled = clk_usb_is_enabled,
+	.recalc_rate = clk_usb_i2c_recalc_rate,
+};
+
+static int clk_gate_enable(struct clk_hw *hw)
+{
+	struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw);
+	u32 mask = BIT(clk->bit_idx);
+	u32 val = (clk->flags & CLK_GATE_SET_TO_DISABLE ? 0x0 : mask);
+
+	return regmap_update_bits(clk_regmap, clk->reg, mask, val);
+}
+
+static void clk_gate_disable(struct clk_hw *hw)
+{
+	struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw);
+	u32 mask = BIT(clk->bit_idx);
+	u32 val = (clk->flags & CLK_GATE_SET_TO_DISABLE ? mask : 0x0);
+
+	regmap_update_bits(clk_regmap, clk->reg, mask, val);
+}
+
+static int clk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw);
+	u32 val;
+	bool is_set;
+
+	regmap_read(clk_regmap, clk->reg, &val);
+	is_set = val & BIT(clk->bit_idx);
+
+	return (clk->flags & CLK_GATE_SET_TO_DISABLE ? !is_set : is_set);
+}
+
+static const struct clk_ops lpc32xx_clk_gate_ops = {
+	.enable = clk_gate_enable,
+	.disable = clk_gate_disable,
+	.is_enabled = clk_gate_is_enabled,
+};
+
+#define div_mask(width)	((1 << (width)) - 1)
+
+static unsigned int _get_table_div(const struct clk_div_table *table,
+							unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+	return 0;
+}
+
+static unsigned int _get_div(const struct clk_div_table *table,
+			     unsigned int val, unsigned long flags, u8 width)
+{
+	if (flags & CLK_DIVIDER_ONE_BASED)
+		return val;
+	if (table)
+		return _get_table_div(table, val);
+	return val + 1;
+}
+
+static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw);
+	unsigned int val;
+
+	regmap_read(clk_regmap, divider->reg, &val);
+
+	val >>= divider->shift;
+	val &= div_mask(divider->width);
+
+	return divider_recalc_rate(hw, parent_rate, val, divider->table,
+				   divider->flags);
+}
+
+static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw);
+	unsigned int bestdiv;
+
+	/* if read only, just return current value */
+	if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+		regmap_read(clk_regmap, divider->reg, &bestdiv);
+		bestdiv >>= divider->shift;
+		bestdiv &= div_mask(divider->width);
+		bestdiv = _get_div(divider->table, bestdiv, divider->flags,
+			divider->width);
+		return DIV_ROUND_UP(*prate, bestdiv);
+	}
+
+	return divider_round_rate(hw, rate, prate, divider->table,
+				  divider->width, divider->flags);
+}
+
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw);
+	unsigned int value;
+
+	value = divider_get_val(rate, parent_rate, divider->table,
+				divider->width, divider->flags);
+
+	return regmap_update_bits(clk_regmap, divider->reg,
+				  div_mask(divider->width) << divider->shift,
+				  value << divider->shift);
+}
+
+static const struct clk_ops lpc32xx_clk_divider_ops = {
+	.recalc_rate = clk_divider_recalc_rate,
+	.round_rate = clk_divider_round_rate,
+	.set_rate = clk_divider_set_rate,
+};
+
+static u8 clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct lpc32xx_clk_mux *mux = to_lpc32xx_mux(hw);
+	u32 num_parents = clk_hw_get_num_parents(hw);
+	u32 val;
+
+	regmap_read(clk_regmap, mux->reg, &val);
+	val >>= mux->shift;
+	val &= mux->mask;
+
+	if (mux->table) {
+		u32 i;
+
+		for (i = 0; i < num_parents; i++)
+			if (mux->table[i] == val)
+				return i;
+		return -EINVAL;
+	}
+
+	if (val >= num_parents)
+		return -EINVAL;
+
+	return val;
+}
+
+static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct lpc32xx_clk_mux *mux = to_lpc32xx_mux(hw);
+
+	if (mux->table)
+		index = mux->table[index];
+
+	return regmap_update_bits(clk_regmap, mux->reg,
+			  mux->mask << mux->shift, index << mux->shift);
+}
+
+static const struct clk_ops lpc32xx_clk_mux_ro_ops = {
+	.get_parent = clk_mux_get_parent,
+};
+
+static const struct clk_ops lpc32xx_clk_mux_ops = {
+	.get_parent = clk_mux_get_parent,
+	.set_parent = clk_mux_set_parent,
+	.determine_rate = __clk_mux_determine_rate,
+};
+
+enum lpc32xx_clk_type {
+	CLK_FIXED,
+	CLK_MUX,
+	CLK_DIV,
+	CLK_GATE,
+	CLK_COMPOSITE,
+	CLK_LPC32XX,
+	CLK_LPC32XX_PLL,
+	CLK_LPC32XX_USB,
+};
+
+struct clk_hw_proto0 {
+	const struct clk_ops *ops;
+	union {
+		struct lpc32xx_pll_clk pll;
+		struct lpc32xx_clk clk;
+		struct lpc32xx_usb_clk usb_clk;
+		struct lpc32xx_clk_mux mux;
+		struct lpc32xx_clk_div div;
+		struct lpc32xx_clk_gate gate;
+	};
+};
+
+struct clk_hw_proto1 {
+	struct clk_hw_proto0 *mux;
+	struct clk_hw_proto0 *div;
+	struct clk_hw_proto0 *gate;
+};
+
+struct clk_hw_proto {
+	enum lpc32xx_clk_type type;
+
+	union {
+		struct clk_fixed_rate f;
+		struct clk_hw_proto0 hw0;
+		struct clk_hw_proto1 hw1;
+	};
+};
+
+#define LPC32XX_DEFINE_FIXED(_idx, _rate, _flags)			\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_FIXED,						\
+	{								\
+		.f = {							\
+			.fixed_rate = (_rate),				\
+			.flags = (_flags),				\
+		},							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_PLL(_idx, _name, _reg, _enable)			\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_LPC32XX_PLL,					\
+	{								\
+		.hw0 = {						\
+			.ops = &clk_ ##_name ## _ops,			\
+			{						\
+				.pll = {				\
+					.reg = LPC32XX_CLKPWR_ ## _reg,	\
+					.enable = (_enable),		\
+				},					\
+			},						\
+		},							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_MUX(_idx, _reg, _shift, _mask, _table, _flags)	\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_MUX,						\
+	{								\
+		.hw0 = {						\
+			.ops = (_flags & CLK_MUX_READ_ONLY ?		\
+				&lpc32xx_clk_mux_ro_ops :		\
+				&lpc32xx_clk_mux_ops),			\
+			{						\
+				.mux = {				\
+					.reg = LPC32XX_CLKPWR_ ## _reg,	\
+					.mask = (_mask),		\
+					.shift = (_shift),		\
+					.table = (_table),		\
+					.flags = (_flags),		\
+				},					\
+			},						\
+		},							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_DIV(_idx, _reg, _shift, _width, _table, _flags)	\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_DIV,						\
+	{								\
+		.hw0 = {						\
+			.ops = &lpc32xx_clk_divider_ops,		\
+			{						\
+				.div = {				\
+					.reg = LPC32XX_CLKPWR_ ## _reg,	\
+					.shift = (_shift),		\
+					.width = (_width),		\
+					.table = (_table),		\
+					.flags = (_flags),		\
+				 },					\
+			},						\
+		 },							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_GATE(_idx, _reg, _bit, _flags)			\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_GATE,						\
+	{								\
+		.hw0 = {						\
+			.ops = &lpc32xx_clk_gate_ops,			\
+			{						\
+				.gate = {				\
+					.reg = LPC32XX_CLKPWR_ ## _reg,	\
+					.bit_idx = (_bit),		\
+					.flags = (_flags),		\
+				},					\
+			},						\
+		},							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_CLK(_idx, _reg, _e, _em, _d, _dm, _b, _bm, _ops)	\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_LPC32XX,						\
+	{								\
+		.hw0 = {						\
+			.ops = &(_ops),					\
+			{						\
+				.clk = {				\
+					.reg = LPC32XX_CLKPWR_ ## _reg,	\
+					.enable = (_e),			\
+					.enable_mask = (_em),		\
+					.disable = (_d),		\
+					.disable_mask = (_dm),		\
+					.busy = (_b),			\
+					.busy_mask = (_bm),		\
+				},					\
+			},						\
+		},							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_USB(_idx, _ce, _cd, _cm, _e, _b, _ops)		\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_LPC32XX_USB,					\
+	{								\
+		.hw0 = {						\
+			.ops = &(_ops),					\
+			{						\
+				.usb_clk = {				\
+					.ctrl_enable = (_ce),		\
+					.ctrl_disable = (_cd),		\
+					.ctrl_mask = (_cm),		\
+					.enable = (_e),			\
+					.busy = (_b),			\
+				}					\
+			},						\
+		}							\
+	},								\
+}
+
+#define LPC32XX_DEFINE_COMPOSITE(_idx, _mux, _div, _gate)		\
+[CLK_PREFIX(_idx)] = {							\
+	.type = CLK_COMPOSITE,						\
+	{								\
+		.hw1 = {						\
+		.mux = (CLK_PREFIX(_mux) == LPC32XX_CLK__NULL ? NULL :	\
+			&clk_hw_proto[CLK_PREFIX(_mux)].hw0),		\
+		.div = (CLK_PREFIX(_div) == LPC32XX_CLK__NULL ? NULL :	\
+			&clk_hw_proto[CLK_PREFIX(_div)].hw0),		\
+		.gate = (CLK_PREFIX(_gate) == LPC32XX_CLK__NULL ? NULL :\
+			 &clk_hw_proto[CLK_PREFIX(_gate)].hw0),		\
+		},							\
+	},								\
+}
+
+static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
+	LPC32XX_DEFINE_FIXED(RTC, 32768, 0),
+	LPC32XX_DEFINE_PLL(PLL397X, pll_397x, HCLKPLL_CTRL, BIT(1)),
+	LPC32XX_DEFINE_PLL(HCLK_PLL, hclk_pll, HCLKPLL_CTRL, PLL_CTRL_ENABLE),
+	LPC32XX_DEFINE_PLL(USB_PLL, usb_pll, USB_CTRL, PLL_CTRL_ENABLE),
+	LPC32XX_DEFINE_GATE(OSC, OSC_CTRL, 0, CLK_GATE_SET_TO_DISABLE),
+	LPC32XX_DEFINE_GATE(USB, USB_CTRL, 18, 0),
+
+	LPC32XX_DEFINE_DIV(HCLK_DIV_PERIPH, HCLKDIV_CTRL, 2, 5, NULL,
+			   CLK_DIVIDER_READ_ONLY),
+	LPC32XX_DEFINE_DIV(HCLK_DIV, HCLKDIV_CTRL, 0, 2, clk_hclk_div_table,
+			   CLK_DIVIDER_READ_ONLY),
+
+	/* Register 3 read-only muxes with a single control PWR_CTRL[2] */
+	LPC32XX_DEFINE_MUX(SYSCLK_PERIPH_MUX, PWR_CTRL, 2, 0x1, NULL,
+			   CLK_MUX_READ_ONLY),
+	LPC32XX_DEFINE_MUX(SYSCLK_HCLK_MUX, PWR_CTRL, 2, 0x1, NULL,
+			   CLK_MUX_READ_ONLY),
+	LPC32XX_DEFINE_MUX(SYSCLK_ARM_MUX, PWR_CTRL, 2, 0x1, NULL,
+			   CLK_MUX_READ_ONLY),
+	/* Register 2 read-only muxes with a single control PWR_CTRL[10] */
+	LPC32XX_DEFINE_MUX(PERIPH_HCLK_MUX, PWR_CTRL, 10, 0x1, NULL,
+			   CLK_MUX_READ_ONLY),
+	LPC32XX_DEFINE_MUX(PERIPH_ARM_MUX, PWR_CTRL, 10, 0x1, NULL,
+			   CLK_MUX_READ_ONLY),
+
+	/* 3 always on gates with a single control PWR_CTRL[0] same as OSC */
+	LPC32XX_DEFINE_GATE(PERIPH, PWR_CTRL, 0, CLK_GATE_SET_TO_DISABLE),
+	LPC32XX_DEFINE_GATE(HCLK, PWR_CTRL, 0, CLK_GATE_SET_TO_DISABLE),
+	LPC32XX_DEFINE_GATE(ARM, PWR_CTRL, 0, CLK_GATE_SET_TO_DISABLE),
+
+	LPC32XX_DEFINE_GATE(ARM_VFP, DEBUG_CTRL, 4, 0),
+	LPC32XX_DEFINE_GATE(DMA, DMA_CLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_CLK(DDRAM, HCLKDIV_CTRL, 0x0, BIT(8) | BIT(7),
+		   0x0, BIT(8) | BIT(7), 0x0, BIT(1) | BIT(0), clk_ddram_ops),
+
+	LPC32XX_DEFINE_GATE(TIMER0, TIMCLK_CTRL1, 2, 0),
+	LPC32XX_DEFINE_GATE(TIMER1, TIMCLK_CTRL1, 3, 0),
+	LPC32XX_DEFINE_GATE(TIMER2, TIMCLK_CTRL1, 4, 0),
+	LPC32XX_DEFINE_GATE(TIMER3, TIMCLK_CTRL1, 5, 0),
+	LPC32XX_DEFINE_GATE(TIMER4, TIMCLK_CTRL1, 0, 0),
+	LPC32XX_DEFINE_GATE(TIMER5, TIMCLK_CTRL1, 1, 0),
+
+	LPC32XX_DEFINE_GATE(SSP0, SSP_CTRL, 0, 0),
+	LPC32XX_DEFINE_GATE(SSP1, SSP_CTRL, 1, 0),
+	LPC32XX_DEFINE_GATE(SPI1, SPI_CTRL, 0, 0),
+	LPC32XX_DEFINE_GATE(SPI2, SPI_CTRL, 4, 0),
+	LPC32XX_DEFINE_GATE(I2S0, I2S_CTRL, 0, 0),
+	LPC32XX_DEFINE_GATE(I2S1, I2S_CTRL, 1, 0),
+	LPC32XX_DEFINE_GATE(I2C1, I2CCLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_GATE(I2C2, I2CCLK_CTRL, 1, 0),
+	LPC32XX_DEFINE_GATE(WDOG, TIMCLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_GATE(HSTIMER, TIMCLK_CTRL, 1, 0),
+
+	LPC32XX_DEFINE_GATE(KEY, KEYCLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_GATE(MCPWM, TIMCLK_CTRL1, 6, 0),
+
+	LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0),
+	LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
+			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+	LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE),
+
+	LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0),
+	LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
+			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+	LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0),
+	LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE),
+
+	LPC32XX_DEFINE_MUX(UART3_MUX, UART3_CLK_CTRL, 16, 0x1, NULL, 0),
+	LPC32XX_DEFINE_CLK(UART3_DIV, UART3_CLK_CTRL,
+			   0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops),
+	LPC32XX_DEFINE_GATE(UART3_GATE, UART_CLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_COMPOSITE(UART3, UART3_MUX, UART3_DIV, UART3_GATE),
+
+	LPC32XX_DEFINE_MUX(UART4_MUX, UART4_CLK_CTRL, 16, 0x1, NULL, 0),
+	LPC32XX_DEFINE_CLK(UART4_DIV, UART4_CLK_CTRL,
+			   0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops),
+	LPC32XX_DEFINE_GATE(UART4_GATE, UART_CLK_CTRL, 1, 0),
+	LPC32XX_DEFINE_COMPOSITE(UART4, UART4_MUX, UART4_DIV, UART4_GATE),
+
+	LPC32XX_DEFINE_MUX(UART5_MUX, UART5_CLK_CTRL, 16, 0x1, NULL, 0),
+	LPC32XX_DEFINE_CLK(UART5_DIV, UART5_CLK_CTRL,
+			   0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops),
+	LPC32XX_DEFINE_GATE(UART5_GATE, UART_CLK_CTRL, 2, 0),
+	LPC32XX_DEFINE_COMPOSITE(UART5, UART5_MUX, UART5_DIV, UART5_GATE),
+
+	LPC32XX_DEFINE_MUX(UART6_MUX, UART6_CLK_CTRL, 16, 0x1, NULL, 0),
+	LPC32XX_DEFINE_CLK(UART6_DIV, UART6_CLK_CTRL,
+			   0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops),
+	LPC32XX_DEFINE_GATE(UART6_GATE, UART_CLK_CTRL, 3, 0),
+	LPC32XX_DEFINE_COMPOSITE(UART6, UART6_MUX, UART6_DIV, UART6_GATE),
+
+	LPC32XX_DEFINE_CLK(IRDA, IRDA_CLK_CTRL,
+			   0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops),
+
+	LPC32XX_DEFINE_MUX(TEST1_MUX, TEST_CLK_CTRL, 5, 0x3,
+			   test1_mux_table, 0),
+	LPC32XX_DEFINE_GATE(TEST1_GATE, TEST_CLK_CTRL, 4, 0),
+	LPC32XX_DEFINE_COMPOSITE(TEST1, TEST1_MUX, _NULL, TEST1_GATE),
+
+	LPC32XX_DEFINE_MUX(TEST2_MUX, TEST_CLK_CTRL, 1, 0x7,
+			   test2_mux_table, 0),
+	LPC32XX_DEFINE_GATE(TEST2_GATE, TEST_CLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_COMPOSITE(TEST2, TEST2_MUX, _NULL, TEST2_GATE),
+
+	LPC32XX_DEFINE_MUX(SYS, SYSCLK_CTRL, 0, 0x1, NULL, CLK_MUX_READ_ONLY),
+
+	LPC32XX_DEFINE_DIV(USB_DIV_DIV, USB_DIV, 0, 4, NULL, 0),
+	LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0),
+	LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE),
+
+	LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL,
+			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+	LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9),
+			   0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops),
+	LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE),
+
+	LPC32XX_DEFINE_DIV(LCD_DIV, LCDCLK_CTRL, 0, 5, NULL, 0),
+	LPC32XX_DEFINE_GATE(LCD_GATE, LCDCLK_CTRL, 5, 0),
+	LPC32XX_DEFINE_COMPOSITE(LCD, _NULL, LCD_DIV, LCD_GATE),
+
+	LPC32XX_DEFINE_CLK(MAC, MACCLK_CTRL,
+			   BIT(2) | BIT(1) | BIT(0), BIT(2) | BIT(1) | BIT(0),
+			   BIT(2) | BIT(1) | BIT(0), BIT(2) | BIT(1) | BIT(0),
+			   0x0, 0x0, clk_mask_ops),
+	LPC32XX_DEFINE_CLK(SLC, FLASHCLK_CTRL,
+			   BIT(2) | BIT(0), BIT(2) | BIT(0), 0x0,
+			   BIT(0), BIT(1), BIT(2) | BIT(1), clk_mask_ops),
+	LPC32XX_DEFINE_CLK(MLC, FLASHCLK_CTRL,
+			   BIT(1), BIT(2) | BIT(1), 0x0, BIT(1),
+			   BIT(2) | BIT(0), BIT(2) | BIT(0), clk_mask_ops),
+	/*
+	 * ADC/TS clock unfortunately cannot be registered as a composite one
+	 * due to a different connection of gate, div and mux, e.g. gating it
+	 * won't mean that the clock is off, if peripheral clock is its parent:
+	 *
+	 * rtc-->[gate]-->|     |
+	 *                | mux |--> adc/ts
+	 * pclk-->[div]-->|     |
+	 *
+	 * Constraints:
+	 * ADC --- resulting clock must be <= 4.5 MHz
+	 * TS  --- resulting clock must be <= 400 KHz
+	 */
+	LPC32XX_DEFINE_DIV(ADC_DIV, ADCCLK_CTRL1, 0, 8, NULL, 0),
+	LPC32XX_DEFINE_GATE(ADC_RTC, ADCCLK_CTRL, 0, 0),
+	LPC32XX_DEFINE_MUX(ADC, ADCCLK_CTRL1, 8, 0x1, NULL, 0),
+
+	/* USB controller clocks */
+	LPC32XX_DEFINE_USB(USB_AHB,
+			   BIT(24), 0x0, BIT(24), BIT(4), 0, clk_usb_ops),
+	LPC32XX_DEFINE_USB(USB_OTG,
+			   0x0, 0x0, 0x0, BIT(3), 0, clk_usb_ops),
+	LPC32XX_DEFINE_USB(USB_I2C,
+			   0x0, BIT(23), BIT(23), BIT(2), 0, clk_usb_i2c_ops),
+	LPC32XX_DEFINE_USB(USB_DEV,
+			   BIT(22), 0x0, BIT(22), BIT(1), BIT(0), clk_usb_ops),
+	LPC32XX_DEFINE_USB(USB_HOST,
+			   BIT(21), 0x0, BIT(21), BIT(0), BIT(1), clk_usb_ops),
+};
+
+static struct clk * __init lpc32xx_clk_register(u32 id)
+{
+	const struct clk_proto_t *lpc32xx_clk = &clk_proto[id];
+	struct clk_hw_proto *clk_hw = &clk_hw_proto[id];
+	const char *parents[LPC32XX_CLK_PARENTS_MAX];
+	struct clk *clk;
+	unsigned int i;
+
+	for (i = 0; i < lpc32xx_clk->num_parents; i++)
+		parents[i] = clk_proto[lpc32xx_clk->parents[i]].name;
+
+	pr_debug("%s: derived from '%s', clock type %d\n", lpc32xx_clk->name,
+		 parents[0], clk_hw->type);
+
+	switch (clk_hw->type) {
+	case CLK_LPC32XX:
+	case CLK_LPC32XX_PLL:
+	case CLK_LPC32XX_USB:
+	case CLK_MUX:
+	case CLK_DIV:
+	case CLK_GATE:
+	{
+		struct clk_init_data clk_init = {
+			.name = lpc32xx_clk->name,
+			.parent_names = parents,
+			.num_parents = lpc32xx_clk->num_parents,
+			.flags = lpc32xx_clk->flags,
+			.ops = clk_hw->hw0.ops,
+		};
+		struct clk_hw *hw;
+
+		if (clk_hw->type == CLK_LPC32XX)
+			hw = &clk_hw->hw0.clk.hw;
+		else if (clk_hw->type == CLK_LPC32XX_PLL)
+			hw = &clk_hw->hw0.pll.hw;
+		else if (clk_hw->type == CLK_LPC32XX_USB)
+			hw = &clk_hw->hw0.usb_clk.hw;
+		else if (clk_hw->type == CLK_MUX)
+			hw = &clk_hw->hw0.mux.hw;
+		else if (clk_hw->type == CLK_DIV)
+			hw = &clk_hw->hw0.div.hw;
+		else if (clk_hw->type == CLK_GATE)
+			hw = &clk_hw->hw0.gate.hw;
+
+		hw->init = &clk_init;
+		clk = clk_register(NULL, hw);
+		break;
+	}
+	case CLK_COMPOSITE:
+	{
+		struct clk_hw *mux_hw = NULL, *div_hw = NULL, *gate_hw = NULL;
+		const struct clk_ops *mops = NULL, *dops = NULL, *gops = NULL;
+		struct clk_hw_proto0 *mux0, *div0, *gate0;
+
+		mux0 = clk_hw->hw1.mux;
+		div0 = clk_hw->hw1.div;
+		gate0 = clk_hw->hw1.gate;
+		if (mux0) {
+			mops = mux0->ops;
+			mux_hw = &mux0->clk.hw;
+		}
+		if (div0) {
+			dops = div0->ops;
+			div_hw = &div0->clk.hw;
+		}
+		if (gate0) {
+			gops = gate0->ops;
+			gate_hw = &gate0->clk.hw;
+		}
+
+		clk = clk_register_composite(NULL, lpc32xx_clk->name,
+				parents, lpc32xx_clk->num_parents,
+				mux_hw, mops, div_hw, dops,
+				gate_hw, gops, lpc32xx_clk->flags);
+		break;
+	}
+	case CLK_FIXED:
+	{
+		struct clk_fixed_rate *fixed = &clk_hw->f;
+
+		clk = clk_register_fixed_rate(NULL, lpc32xx_clk->name,
+			parents[0], fixed->flags, fixed->fixed_rate);
+		break;
+	}
+	default:
+		clk = ERR_PTR(-EINVAL);
+	}
+
+	return clk;
+}
+
+static void __init lpc32xx_clk_init(struct device_node *np)
+{
+	unsigned int i;
+	struct clk *clk_osc, *clk_32k;
+	void __iomem *base = NULL;
+
+	/* Ensure that parent clocks are available and valid */
+	clk_32k = of_clk_get_by_name(np, clk_proto[LPC32XX_CLK_XTAL_32K].name);
+	if (IS_ERR(clk_32k)) {
+		pr_err("failed to find external 32KHz clock: %ld\n",
+		       PTR_ERR(clk_32k));
+		return;
+	}
+	if (clk_get_rate(clk_32k) != 32768) {
+		pr_err("invalid clock rate of external 32KHz oscillator");
+		return;
+	}
+
+	clk_osc = of_clk_get_by_name(np, clk_proto[LPC32XX_CLK_XTAL].name);
+	if (IS_ERR(clk_osc)) {
+		pr_err("failed to find external main oscillator clock: %ld\n",
+		       PTR_ERR(clk_osc));
+		return;
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("failed to map system control block registers\n");
+		return;
+	}
+
+	clk_regmap = regmap_init_mmio(NULL, base, &lpc32xx_scb_regmap_config);
+	if (IS_ERR(clk_regmap)) {
+		pr_err("failed to regmap system control block: %ld\n",
+			PTR_ERR(clk_regmap));
+		return;
+	}
+
+	for (i = 0; i < LPC32XX_CLK_MAX; i++) {
+		clk[i] = lpc32xx_clk_register(i);
+		if (IS_ERR(clk[i])) {
+			pr_err("failed to register %s clock: %ld\n",
+				clk_proto[i].name, PTR_ERR(clk[i]));
+			clk[i] = NULL;
+		}
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	/* For 13MHz osc valid output range of PLL is from 156MHz to 266.5MHz */
+	clk_set_rate(clk[LPC32XX_CLK_HCLK_PLL], 208000000);
+
+	/* Set 48MHz rate of USB PLL clock */
+	clk_set_rate(clk[LPC32XX_CLK_USB_PLL], 48000000);
+
+	/* These two clocks must be always on independently on consumers */
+	clk_prepare_enable(clk[LPC32XX_CLK_ARM]);
+	clk_prepare_enable(clk[LPC32XX_CLK_HCLK]);
+
+	/* Enable ARM VFP by default */
+	clk_prepare_enable(clk[LPC32XX_CLK_ARM_VFP]);
+
+	/* Disable enabled by default clocks for NAND MLC and SLC */
+	clk_mask_disable(&clk_hw_proto[LPC32XX_CLK_SLC].hw0.clk.hw);
+	clk_mask_disable(&clk_hw_proto[LPC32XX_CLK_MLC].hw0.clk.hw);
+}
+CLK_OF_DECLARE(lpc32xx_clk, "nxp,lpc3220-clk", lpc32xx_clk_init);
+
+static void __init lpc32xx_usb_clk_init(struct device_node *np)
+{
+	unsigned int i;
+
+	usb_clk_vbase = of_iomap(np, 0);
+	if (!usb_clk_vbase) {
+		pr_err("failed to map address range\n");
+		return;
+	}
+
+	for (i = 0; i < LPC32XX_USB_CLK_MAX; i++) {
+		usb_clk[i] = lpc32xx_clk_register(i + LPC32XX_CLK_USB_OFFSET);
+		if (IS_ERR(usb_clk[i])) {
+			pr_err("failed to register %s clock: %ld\n",
+				clk_proto[i].name, PTR_ERR(usb_clk[i]));
+			usb_clk[i] = NULL;
+		}
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &usb_clk_data);
+}
+CLK_OF_DECLARE(lpc32xx_usb_clk, "nxp,lpc3220-usb-clk", lpc32xx_usb_clk_init);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index ee4c83aab4f4..b552eceec2be 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -106,3 +106,20 @@ config MSM_MMCC_8974
 	  Support for the multimedia clock controller on msm8974 devices.
 	  Say Y if you want to support multimedia devices such as display,
 	  graphics, video encode/decode, camera, etc.
+
+config MSM_GCC_8996
+	tristate "MSM8996 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on msm8996 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, UFS, SD/eMMC, PCIe, etc.
+
+config MSM_MMCC_8996
+	tristate "MSM8996 Multimedia Clock Controller"
+	select MSM_GCC_8996
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the multimedia clock controller on msm8996 devices.
+	  Say Y if you want to support multimedia devices such as display,
+	  graphics, video encode/decode, camera, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index fe6252349e55..dc4280b85db1 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
 
 clk-qcom-y += common.o
 clk-qcom-y += clk-regmap.o
+clk-qcom-y += clk-alpha-pll.o
 clk-qcom-y += clk-pll.o
 clk-qcom-y += clk-rcg.o
 clk-qcom-y += clk-rcg2.o
@@ -20,5 +21,7 @@ obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
+obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
+obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
new file mode 100644
index 000000000000..e6a03eaf7a93
--- /dev/null
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/kernel.h>
+#include <linux/export.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+
+#include "clk-alpha-pll.h"
+
+#define PLL_MODE		0x00
+# define PLL_OUTCTRL		BIT(0)
+# define PLL_BYPASSNL		BIT(1)
+# define PLL_RESET_N		BIT(2)
+# define PLL_LOCK_COUNT_SHIFT	8
+# define PLL_LOCK_COUNT_MASK	0x3f
+# define PLL_BIAS_COUNT_SHIFT	14
+# define PLL_BIAS_COUNT_MASK	0x3f
+# define PLL_VOTE_FSM_ENA	BIT(20)
+# define PLL_VOTE_FSM_RESET	BIT(21)
+# define PLL_ACTIVE_FLAG	BIT(30)
+# define PLL_LOCK_DET		BIT(31)
+
+#define PLL_L_VAL		0x04
+#define PLL_ALPHA_VAL		0x08
+#define PLL_ALPHA_VAL_U		0x0c
+
+#define PLL_USER_CTL		0x10
+# define PLL_POST_DIV_SHIFT	8
+# define PLL_POST_DIV_MASK	0xf
+# define PLL_ALPHA_EN		BIT(24)
+# define PLL_VCO_SHIFT		20
+# define PLL_VCO_MASK		0x3
+
+#define PLL_USER_CTL_U		0x14
+
+#define PLL_CONFIG_CTL		0x18
+#define PLL_TEST_CTL		0x1c
+#define PLL_TEST_CTL_U		0x20
+#define PLL_STATUS		0x24
+
+/*
+ * Even though 40 bits are present, use only 32 for ease of calculation.
+ */
+#define ALPHA_REG_BITWIDTH	40
+#define ALPHA_BITWIDTH		32
+
+#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
+					   struct clk_alpha_pll, clkr)
+
+#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
+					   struct clk_alpha_pll_postdiv, clkr)
+
+static int wait_for_pll(struct clk_alpha_pll *pll)
+{
+	u32 val, mask, off;
+	int count;
+	int ret;
+	const char *name = clk_hw_get_name(&pll->clkr.hw);
+
+	off = pll->offset;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return ret;
+
+	if (val & PLL_VOTE_FSM_ENA)
+		mask = PLL_ACTIVE_FLAG;
+	else
+		mask = PLL_LOCK_DET;
+
+	/* Wait for pll to enable. */
+	for (count = 100; count > 0; count--) {
+		ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+		if (ret)
+			return ret;
+		if ((val & mask) == mask)
+			return 0;
+
+		udelay(1);
+	}
+
+	WARN(1, "%s didn't enable after voting for it!\n", name);
+	return -ETIMEDOUT;
+}
+
+static int clk_alpha_pll_enable(struct clk_hw *hw)
+{
+	int ret;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 val, mask, off;
+
+	off = pll->offset;
+
+	mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return ret;
+
+	/* If in FSM mode, just vote for it */
+	if (val & PLL_VOTE_FSM_ENA) {
+		ret = clk_enable_regmap(hw);
+		if (ret)
+			return ret;
+		return wait_for_pll(pll);
+	}
+
+	/* Skip if already enabled */
+	if ((val & mask) == mask)
+		return 0;
+
+	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+				 PLL_BYPASSNL, PLL_BYPASSNL);
+	if (ret)
+		return ret;
+
+	/*
+	 * H/W requires a 5us delay between disabling the bypass and
+	 * de-asserting the reset.
+	 */
+	mb();
+	udelay(5);
+
+	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+				 PLL_RESET_N, PLL_RESET_N);
+	if (ret)
+		return ret;
+
+	ret = wait_for_pll(pll);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+				 PLL_OUTCTRL, PLL_OUTCTRL);
+
+	/* Ensure that the write above goes through before returning. */
+	mb();
+	return ret;
+}
+
+static void clk_alpha_pll_disable(struct clk_hw *hw)
+{
+	int ret;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 val, mask, off;
+
+	off = pll->offset;
+
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return;
+
+	/* If in FSM mode, just unvote it */
+	if (val & PLL_VOTE_FSM_ENA) {
+		clk_disable_regmap(hw);
+		return;
+	}
+
+	mask = PLL_OUTCTRL;
+	regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
+
+	/* Delay of 2 output clock ticks required until output is disabled */
+	mb();
+	udelay(1);
+
+	mask = PLL_RESET_N | PLL_BYPASSNL;
+	regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
+}
+
+static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
+{
+	return (prate * l) + ((prate * a) >> ALPHA_BITWIDTH);
+}
+
+static unsigned long
+alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a)
+{
+	u64 remainder;
+	u64 quotient;
+
+	quotient = rate;
+	remainder = do_div(quotient, prate);
+	*l = quotient;
+
+	if (!remainder) {
+		*a = 0;
+		return rate;
+	}
+
+	/* Upper ALPHA_BITWIDTH bits of Alpha */
+	quotient = remainder << ALPHA_BITWIDTH;
+	remainder = do_div(quotient, prate);
+
+	if (remainder)
+		quotient++;
+
+	*a = quotient;
+	return alpha_pll_calc_rate(prate, *l, *a);
+}
+
+static const struct pll_vco *
+alpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate)
+{
+	const struct pll_vco *v = pll->vco_table;
+	const struct pll_vco *end = v + pll->num_vco;
+
+	for (; v < end; v++)
+		if (rate >= v->min_freq && rate <= v->max_freq)
+			return v;
+
+	return NULL;
+}
+
+static unsigned long
+clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	u32 l, low, high, ctl;
+	u64 a = 0, prate = parent_rate;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 off = pll->offset;
+
+	regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l);
+
+	regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
+	if (ctl & PLL_ALPHA_EN) {
+		regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
+		regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high);
+		a = (u64)high << 32 | low;
+		a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+	}
+
+	return alpha_pll_calc_rate(prate, l, a);
+}
+
+static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long prate)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	const struct pll_vco *vco;
+	u32 l, off = pll->offset;
+	u64 a;
+
+	rate = alpha_pll_round_rate(rate, prate, &l, &a);
+	vco = alpha_pll_find_vco(pll, rate);
+	if (!vco) {
+		pr_err("alpha pll not in a valid vco range\n");
+		return -EINVAL;
+	}
+
+	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
+	regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a);
+	regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+
+	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
+			   PLL_VCO_MASK << PLL_VCO_SHIFT,
+			   vco->val << PLL_VCO_SHIFT);
+
+	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
+			   PLL_ALPHA_EN);
+
+	return 0;
+}
+
+static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 l;
+	u64 a;
+	unsigned long min_freq, max_freq;
+
+	rate = alpha_pll_round_rate(rate, *prate, &l, &a);
+	if (alpha_pll_find_vco(pll, rate))
+		return rate;
+
+	min_freq = pll->vco_table[0].min_freq;
+	max_freq = pll->vco_table[pll->num_vco - 1].max_freq;
+
+	return clamp(rate, min_freq, max_freq);
+}
+
+const struct clk_ops clk_alpha_pll_ops = {
+	.enable = clk_alpha_pll_enable,
+	.disable = clk_alpha_pll_disable,
+	.recalc_rate = clk_alpha_pll_recalc_rate,
+	.round_rate = clk_alpha_pll_round_rate,
+	.set_rate = clk_alpha_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
+
+static unsigned long
+clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+	u32 ctl;
+
+	regmap_read(pll->clkr.regmap, pll->offset + PLL_USER_CTL, &ctl);
+
+	ctl >>= PLL_POST_DIV_SHIFT;
+	ctl &= PLL_POST_DIV_MASK;
+
+	return parent_rate >> fls(ctl);
+}
+
+static const struct clk_div_table clk_alpha_div_table[] = {
+	{ 0x0, 1 },
+	{ 0x1, 2 },
+	{ 0x3, 4 },
+	{ 0x7, 8 },
+	{ 0xf, 16 },
+	{ }
+};
+
+static long
+clk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *prate)
+{
+	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+
+	return divider_round_rate(hw, rate, prate, clk_alpha_div_table,
+				  pll->width, CLK_DIVIDER_POWER_OF_TWO);
+}
+
+static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					  unsigned long parent_rate)
+{
+	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+	int div;
+
+	/* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */
+	div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
+
+	return regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
+				  PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
+				  div << PLL_POST_DIV_SHIFT);
+}
+
+const struct clk_ops clk_alpha_pll_postdiv_ops = {
+	.recalc_rate = clk_alpha_pll_postdiv_recalc_rate,
+	.round_rate = clk_alpha_pll_postdiv_round_rate,
+	.set_rate = clk_alpha_pll_postdiv_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
new file mode 100644
index 000000000000..90ce2016e1a0
--- /dev/null
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 __QCOM_CLK_ALPHA_PLL_H__
+#define __QCOM_CLK_ALPHA_PLL_H__
+
+#include <linux/clk-provider.h>
+#include "clk-regmap.h"
+
+struct pll_vco {
+	unsigned long min_freq;
+	unsigned long max_freq;
+	u32 val;
+};
+
+/**
+ * struct clk_alpha_pll - phase locked loop (PLL)
+ * @offset: base address of registers
+ * @vco_table: array of VCO settings
+ * @clkr: regmap clock handle
+ */
+struct clk_alpha_pll {
+	u32 offset;
+
+	const struct pll_vco *vco_table;
+	size_t num_vco;
+
+	struct clk_regmap clkr;
+};
+
+/**
+ * struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
+ * @offset: base address of registers
+ * @width: width of post-divider
+ * @clkr: regmap clock handle
+ */
+struct clk_alpha_pll_postdiv {
+	u32 offset;
+	u8 width;
+
+	struct clk_regmap clkr;
+};
+
+extern const struct clk_ops clk_alpha_pll_ops;
+extern const struct clk_ops clk_alpha_pll_postdiv_ops;
+
+#endif
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 4b1e94bdf29e..b904c335cda4 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -178,5 +178,6 @@ extern const struct clk_ops clk_edp_pixel_ops;
 extern const struct clk_ops clk_byte_ops;
 extern const struct clk_ops clk_byte2_ops;
 extern const struct clk_ops clk_pixel_ops;
+extern const struct clk_ops clk_gfx3d_ops;
 
 #endif
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index b544bb302f79..a071bba8018c 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -723,3 +723,90 @@ const struct clk_ops clk_pixel_ops = {
 	.determine_rate = clk_pixel_determine_rate,
 };
 EXPORT_SYMBOL_GPL(clk_pixel_ops);
+
+static int clk_gfx3d_determine_rate(struct clk_hw *hw,
+				    struct clk_rate_request *req)
+{
+	struct clk_rate_request parent_req = { };
+	struct clk_hw *p2, *p8, *p9, *xo;
+	unsigned long p9_rate;
+	int ret;
+
+	xo = clk_hw_get_parent_by_index(hw, 0);
+	if (req->rate == clk_hw_get_rate(xo)) {
+		req->best_parent_hw = xo;
+		return 0;
+	}
+
+	p9 = clk_hw_get_parent_by_index(hw, 2);
+	p2 = clk_hw_get_parent_by_index(hw, 3);
+	p8 = clk_hw_get_parent_by_index(hw, 4);
+
+	/* PLL9 is a fixed rate PLL */
+	p9_rate = clk_hw_get_rate(p9);
+
+	parent_req.rate = req->rate = min(req->rate, p9_rate);
+	if (req->rate == p9_rate) {
+		req->rate = req->best_parent_rate = p9_rate;
+		req->best_parent_hw = p9;
+		return 0;
+	}
+
+	if (req->best_parent_hw == p9) {
+		/* Are we going back to a previously used rate? */
+		if (clk_hw_get_rate(p8) == req->rate)
+			req->best_parent_hw = p8;
+		else
+			req->best_parent_hw = p2;
+	} else if (req->best_parent_hw == p8) {
+		req->best_parent_hw = p2;
+	} else {
+		req->best_parent_hw = p8;
+	}
+
+	ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
+	if (ret)
+		return ret;
+
+	req->rate = req->best_parent_rate = parent_req.rate;
+
+	return 0;
+}
+
+static int clk_gfx3d_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate, u8 index)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	u32 cfg;
+	int ret;
+
+	/* Just mux it, we don't use the division or m/n hardware */
+	cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
+	ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg);
+	if (ret)
+		return ret;
+
+	return update_config(rcg);
+}
+
+static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long parent_rate)
+{
+	/*
+	 * We should never get here; clk_gfx3d_determine_rate() should always
+	 * make us use a different parent than what we're currently using, so
+	 * clk_gfx3d_set_rate_and_parent() should always be called.
+	 */
+	return 0;
+}
+
+const struct clk_ops clk_gfx3d_ops = {
+	.is_enabled = clk_rcg2_is_enabled,
+	.get_parent = clk_rcg2_get_parent,
+	.set_parent = clk_rcg2_set_parent,
+	.recalc_rate = clk_rcg2_recalc_rate,
+	.set_rate = clk_gfx3d_set_rate,
+	.set_rate_and_parent = clk_gfx3d_set_rate_and_parent,
+	.determine_rate = clk_gfx3d_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_gfx3d_ops);
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 8fa477293ae0..c112ebaba70d 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
 #include <linux/reset-controller.h>
+#include <linux/of.h>
 
 #include "common.h"
 #include "clk-rcg.h"
@@ -88,6 +89,92 @@ static void qcom_cc_gdsc_unregister(void *data)
 	gdsc_unregister(data);
 }
 
+/*
+ * Backwards compatibility with old DTs. Register a pass-through factor 1/1
+ * clock to translate 'path' clk into 'name' clk and regsiter the 'path'
+ * clk as a fixed rate clock if it isn't present.
+ */
+static int _qcom_cc_register_board_clk(struct device *dev, const char *path,
+				       const char *name, unsigned long rate,
+				       bool add_factor)
+{
+	struct device_node *node = NULL;
+	struct device_node *clocks_node;
+	struct clk_fixed_factor *factor;
+	struct clk_fixed_rate *fixed;
+	struct clk *clk;
+	struct clk_init_data init_data = { };
+
+	clocks_node = of_find_node_by_path("/clocks");
+	if (clocks_node)
+		node = of_find_node_by_name(clocks_node, path);
+	of_node_put(clocks_node);
+
+	if (!node) {
+		fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
+		if (!fixed)
+			return -EINVAL;
+
+		fixed->fixed_rate = rate;
+		fixed->hw.init = &init_data;
+
+		init_data.name = path;
+		init_data.flags = CLK_IS_ROOT;
+		init_data.ops = &clk_fixed_rate_ops;
+
+		clk = devm_clk_register(dev, &fixed->hw);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+	}
+	of_node_put(node);
+
+	if (add_factor) {
+		factor = devm_kzalloc(dev, sizeof(*factor), GFP_KERNEL);
+		if (!factor)
+			return -EINVAL;
+
+		factor->mult = factor->div = 1;
+		factor->hw.init = &init_data;
+
+		init_data.name = name;
+		init_data.parent_names = &path;
+		init_data.num_parents = 1;
+		init_data.flags = 0;
+		init_data.ops = &clk_fixed_factor_ops;
+
+		clk = devm_clk_register(dev, &factor->hw);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+	}
+
+	return 0;
+}
+
+int qcom_cc_register_board_clk(struct device *dev, const char *path,
+			       const char *name, unsigned long rate)
+{
+	bool add_factor = true;
+	struct device_node *node;
+
+	/* The RPM clock driver will add the factor clock if present */
+	if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {
+		node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");
+		if (of_device_is_available(node))
+			add_factor = false;
+		of_node_put(node);
+	}
+
+	return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);
+}
+EXPORT_SYMBOL_GPL(qcom_cc_register_board_clk);
+
+int qcom_cc_register_sleep_clk(struct device *dev)
+{
+	return _qcom_cc_register_board_clk(dev, "sleep_clk", "sleep_clk_src",
+					   32768, true);
+}
+EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk);
+
 int qcom_cc_really_probe(struct platform_device *pdev,
 			 const struct qcom_cc_desc *desc, struct regmap *regmap)
 {
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 7c1fba3ebc03..ae9bdeb21f29 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -37,6 +37,10 @@ extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
 extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
 			       u8 src);
 
+extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
+				      const char *name, unsigned long rate);
+extern int qcom_cc_register_sleep_clk(struct device *dev);
+
 extern struct regmap *qcom_cc_map(struct platform_device *pdev,
 				  const struct qcom_cc_desc *desc);
 extern int qcom_cc_really_probe(struct platform_device *pdev,
diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c
index 1567c3a79534..cf73e539e9f6 100644
--- a/drivers/clk/qcom/gcc-apq8084.c
+++ b/drivers/clk/qcom/gcc-apq8084.c
@@ -3587,6 +3587,7 @@ static const struct regmap_config gcc_apq8084_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x1fc0,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_apq8084_desc = {
@@ -3607,18 +3608,16 @@ MODULE_DEVICE_TABLE(of, gcc_apq8084_match_table);
 
 static int gcc_apq8084_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
+	int ret;
 	struct device *dev = &pdev->dev;
 
-	/* Temporary until RPM clocks supported */
-	clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000);
+	if (ret)
+		return ret;
 
-	clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
-				      CLK_IS_ROOT, 32768);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_sleep_clk(dev);
+	if (ret)
+		return ret;
 
 	return qcom_cc_probe(pdev, &gcc_apq8084_desc);
 }
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 16fc64c082a5..b692ae881d6a 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -3005,6 +3005,7 @@ static const struct regmap_config gcc_ipq806x_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x3e40,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_ipq806x_desc = {
@@ -3023,19 +3024,17 @@ MODULE_DEVICE_TABLE(of, gcc_ipq806x_match_table);
 
 static int gcc_ipq806x_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
 	struct device *dev = &pdev->dev;
 	struct regmap *regmap;
 	int ret;
 
-	/* Temporary until RPM clocks supported */
-	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
+	if (ret)
+		return ret;
 
-	clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 25000000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
+	if (ret)
+		return ret;
 
 	ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc);
 	if (ret)
diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c
index f110bb5a1df3..f6a2b14dfec4 100644
--- a/drivers/clk/qcom/gcc-msm8660.c
+++ b/drivers/clk/qcom/gcc-msm8660.c
@@ -2702,6 +2702,7 @@ static const struct regmap_config gcc_msm8660_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x363c,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8660_desc = {
@@ -2720,17 +2721,16 @@ MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table);
 
 static int gcc_msm8660_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
+	int ret;
 	struct device *dev = &pdev->dev;
 
-	/* Temporary until RPM clocks supported */
-	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
+	if (ret)
+		return ret;
 
-	clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
+	if (ret)
+		return ret;
 
 	return qcom_cc_probe(pdev, &gcc_msm8660_desc);
 }
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index d0a0313d6bef..e3bf09d7d0ef 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -3336,6 +3336,7 @@ static const struct regmap_config gcc_msm8916_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x80000,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8916_desc = {
@@ -3356,18 +3357,16 @@ MODULE_DEVICE_TABLE(of, gcc_msm8916_match_table);
 
 static int gcc_msm8916_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
+	int ret;
 	struct device *dev = &pdev->dev;
 
-	/* Temporary until RPM clocks supported */
-	clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000);
+	if (ret)
+		return ret;
 
-	clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
-				      CLK_IS_ROOT, 32768);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_sleep_clk(dev);
+	if (ret)
+		return ret;
 
 	return qcom_cc_probe(pdev, &gcc_msm8916_desc);
 }
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index 66c18bc97857..f31111e32d44 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -3468,6 +3468,7 @@ static const struct regmap_config gcc_msm8960_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x3660,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct regmap_config gcc_apq8064_regmap_config = {
@@ -3476,6 +3477,7 @@ static const struct regmap_config gcc_apq8064_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x3880,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8960_desc = {
@@ -3503,7 +3505,6 @@ MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table);
 
 static int gcc_msm8960_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
 	struct device *dev = &pdev->dev;
 	const struct of_device_id *match;
 	struct platform_device *tsens;
@@ -3513,14 +3514,13 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
 	if (!match)
 		return -EINVAL;
 
-	/* Temporary until RPM clocks supported */
-	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
+	if (ret)
+		return ret;
 
-	clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
+	if (ret)
+		return ret;
 
 	ret = qcom_cc_probe(pdev, match->data);
 	if (ret)
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index 28abb8f8f293..df164d618e34 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -2680,6 +2680,7 @@ static const struct regmap_config gcc_msm8974_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x1fc0,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8974_desc = {
@@ -2717,7 +2718,7 @@ static void msm8974_pro_clock_override(void)
 
 static int gcc_msm8974_probe(struct platform_device *pdev)
 {
-	struct clk *clk;
+	int ret;
 	struct device *dev = &pdev->dev;
 	bool pro;
 	const struct of_device_id *id;
@@ -2730,16 +2731,13 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
 	if (pro)
 		msm8974_pro_clock_override();
 
-	/* Temporary until RPM clocks supported */
-	clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000);
+	if (ret)
+		return ret;
 
-	/* Should move to DT node? */
-	clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
-				      CLK_IS_ROOT, 32768);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	ret = qcom_cc_register_sleep_clk(dev);
+	if (ret)
+		return ret;
 
 	return qcom_cc_probe(pdev, &gcc_msm8974_desc);
 }
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
new file mode 100644
index 000000000000..16d7c323db49
--- /dev/null
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -0,0 +1,3422 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8996.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+	P_XO,
+	P_GPLL0,
+	P_GPLL2,
+	P_GPLL3,
+	P_GPLL1,
+	P_GPLL2_EARLY,
+	P_GPLL0_EARLY_DIV,
+	P_SLEEP_CLK,
+	P_GPLL4,
+	P_AUD_REF_CLK,
+	P_GPLL1_EARLY_DIV
+};
+
+static const struct parent_map gcc_sleep_clk_map[] = {
+	{ P_SLEEP_CLK, 5 }
+};
+
+static const char * const gcc_sleep_clk[] = {
+	"sleep_clk"
+};
+
+static const struct parent_map gcc_xo_gpll0_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 }
+};
+
+static const char * const gcc_xo_gpll0[] = {
+	"xo",
+	"gpll0"
+};
+
+static const struct parent_map gcc_xo_sleep_clk_map[] = {
+	{ P_XO, 0 },
+	{ P_SLEEP_CLK, 5 }
+};
+
+static const char * const gcc_xo_sleep_clk[] = {
+	"xo",
+	"sleep_clk"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"gpll0_early_div"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL4, 5 }
+};
+
+static const char * const gcc_xo_gpll0_gpll4[] = {
+	"xo",
+	"gpll0",
+	"gpll4"
+};
+
+static const struct parent_map gcc_xo_gpll0_aud_ref_clk_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_AUD_REF_CLK, 2 }
+};
+
+static const char * const gcc_xo_gpll0_aud_ref_clk[] = {
+	"xo",
+	"gpll0",
+	"aud_ref_clk"
+};
+
+static const struct parent_map gcc_xo_gpll0_sleep_clk_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_SLEEP_CLK, 5 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"sleep_clk",
+	"gpll0_early_div"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL4, 5 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"gpll4",
+	"gpll0_early_div"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL2, 2 },
+	{ P_GPLL3, 3 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"gpll2",
+	"gpll3",
+	"gpll0_early_div"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL1_EARLY_DIV, 3 },
+	{ P_GPLL1, 4 },
+	{ P_GPLL4, 5 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"gpll1_early_div",
+	"gpll1",
+	"gpll4",
+	"gpll0_early_div"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL2, 2 },
+	{ P_GPLL3, 3 },
+	{ P_GPLL1, 4 },
+	{ P_GPLL2_EARLY, 5 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"gpll2",
+	"gpll3",
+	"gpll1",
+	"gpll2_early",
+	"gpll0_early_div"
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL2, 2 },
+	{ P_GPLL3, 3 },
+	{ P_GPLL1, 4 },
+	{ P_GPLL4, 5 },
+	{ P_GPLL0_EARLY_DIV, 6 }
+};
+
+static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div[] = {
+	"xo",
+	"gpll0",
+	"gpll2",
+	"gpll3",
+	"gpll1",
+	"gpll4",
+	"gpll0_early_div"
+};
+
+static struct clk_fixed_factor xo = {
+	.mult = 1,
+	.div = 1,
+	.hw.init = &(struct clk_init_data){
+		.name = "xo",
+		.parent_names = (const char *[]){ "xo_board" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct clk_alpha_pll gpll0_early = {
+	.offset = 0x00000,
+	.clkr = {
+		.enable_reg = 0x52000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpll0_early",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static struct clk_fixed_factor gpll0_early_div = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll0_early_div",
+		.parent_names = (const char *[]){ "gpll0_early" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+	.offset = 0x00000,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gpll0",
+		.parent_names = (const char *[]){ "gpll0_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+	},
+};
+
+static struct clk_alpha_pll gpll4_early = {
+	.offset = 0x77000,
+	.clkr = {
+		.enable_reg = 0x52000,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpll4_early",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+	.offset = 0x77000,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gpll4",
+		.parent_names = (const char *[]){ "gpll4_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_system_noc_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(240000000, P_GPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 system_noc_clk_src = {
+	.cmd_rcgr = 0x0401c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map,
+	.freq_tbl = ftbl_system_noc_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "system_noc_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_config_noc_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 config_noc_clk_src = {
+	.cmd_rcgr = 0x0500c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_config_noc_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "config_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_periph_noc_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 periph_noc_clk_src = {
+	.cmd_rcgr = 0x06014,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_periph_noc_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "periph_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(120000000, P_GPLL0, 5, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+	.cmd_rcgr = 0x0f014,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_early_div_map,
+	.freq_tbl = ftbl_usb30_master_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb30_master_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_early_div,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+	.cmd_rcgr = 0x0f028,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_early_div_map,
+	.freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb30_mock_utmi_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_early_div,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+	F(1200000, P_XO, 16, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+	.cmd_rcgr = 0x5000c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_sleep_clk_map,
+	.freq_tbl = ftbl_usb3_phy_aux_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb3_phy_aux_clk_src",
+		.parent_names = gcc_xo_sleep_clk,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
+	F(120000000, P_GPLL0, 5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb20_master_clk_src = {
+	.cmd_rcgr = 0x12010,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_early_div_map,
+	.freq_tbl = ftbl_usb20_master_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb20_master_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_early_div,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 usb20_mock_utmi_clk_src = {
+	.cmd_rcgr = 0x12024,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_early_div_map,
+	.freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb20_mock_utmi_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_early_div,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+	F(144000, P_XO, 16, 3, 25),
+	F(400000, P_XO, 12, 1, 4),
+	F(20000000, P_GPLL0, 15, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(96000000, P_GPLL4, 4, 0, 0),
+	F(192000000, P_GPLL4, 2, 0, 0),
+	F(384000000, P_GPLL4, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+	.cmd_rcgr = 0x13010,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map,
+	.freq_tbl = ftbl_sdcc1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+	.cmd_rcgr = 0x13024,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc1_ice_core_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
+	F(144000, P_XO, 16, 3, 25),
+	F(400000, P_XO, 12, 1, 4),
+	F(20000000, P_GPLL0, 15, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+	.cmd_rcgr = 0x14010,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll4_map,
+	.freq_tbl = ftbl_sdcc2_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll4,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc3_apps_clk_src = {
+	.cmd_rcgr = 0x15010,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll4_map,
+	.freq_tbl = ftbl_sdcc2_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll4,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_sdcc4_apps_clk_src[] = {
+	F(144000, P_XO, 16, 3, 25),
+	F(400000, P_XO, 12, 1, 4),
+	F(20000000, P_GPLL0, 15, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sdcc4_apps_clk_src = {
+	.cmd_rcgr = 0x16010,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_sdcc4_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
+	F(960000, P_XO, 10, 1, 2),
+	F(4800000, P_XO, 4, 0, 0),
+	F(9600000, P_XO, 2, 0, 0),
+	F(15000000, P_GPLL0, 10, 1, 4),
+	F(19200000, P_XO, 1, 0, 0),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x1900c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x19020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
+	F(3686400, P_GPLL0, 1, 96, 15625),
+	F(7372800, P_GPLL0, 1, 192, 15625),
+	F(14745600, P_GPLL0, 1, 384, 15625),
+	F(16000000, P_GPLL0, 5, 2, 15),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	F(32000000, P_GPLL0, 1, 4, 75),
+	F(40000000, P_GPLL0, 15, 0, 0),
+	F(46400000, P_GPLL0, 1, 29, 375),
+	F(48000000, P_GPLL0, 12.5, 0, 0),
+	F(51200000, P_GPLL0, 1, 32, 375),
+	F(56000000, P_GPLL0, 1, 7, 75),
+	F(58982400, P_GPLL0, 1, 1536, 15625),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(63157895, P_GPLL0, 9.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x1a00c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x1b00c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x1b020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x1c00c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x1d00c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x1d020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x1e00c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x1f00c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x1f020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x2000c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2100c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x21020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x2200c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2300c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x23020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x2400c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2600c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x26020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x2700c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2800c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x28020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x2900c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2a00c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x2a020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x2b00c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2c00c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x2c020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x2d00c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x2e00c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x2e020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x2f00c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x3000c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x30020,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x3100c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_pdm2_clk_src[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+	.cmd_rcgr = 0x33010,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_pdm2_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pdm2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_tsif_ref_clk_src[] = {
+	F(105495, P_XO, 1, 1, 182),
+	{ }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+	.cmd_rcgr = 0x36010,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_aud_ref_clk_map,
+	.freq_tbl = ftbl_tsif_ref_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "tsif_ref_clk_src",
+		.parent_names = gcc_xo_gpll0_aud_ref_clk,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gcc_sleep_clk_src = {
+	.cmd_rcgr = 0x43014,
+	.hid_width = 5,
+	.parent_map = gcc_sleep_clk_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gcc_sleep_clk_src",
+		.parent_names = gcc_sleep_clk,
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 hmss_rbcpr_clk_src = {
+	.cmd_rcgr = 0x48040,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "hmss_rbcpr_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 hmss_gpll0_clk_src = {
+	.cmd_rcgr = 0x48058,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "hmss_gpll0_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gp1_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+	.cmd_rcgr = 0x64004,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_sleep_clk_gpll0_early_div_map,
+	.freq_tbl = ftbl_gp1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gp1_clk_src",
+		.parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+	.cmd_rcgr = 0x65004,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_sleep_clk_gpll0_early_div_map,
+	.freq_tbl = ftbl_gp1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gp2_clk_src",
+		.parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+	.cmd_rcgr = 0x66004,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_sleep_clk_gpll0_early_div_map,
+	.freq_tbl = ftbl_gp1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gp3_clk_src",
+		.parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
+	F(1010526, P_XO, 1, 1, 19),
+	{ }
+};
+
+static struct clk_rcg2 pcie_aux_clk_src = {
+	.cmd_rcgr = 0x6c000,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_sleep_clk_map,
+	.freq_tbl = ftbl_pcie_aux_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pcie_aux_clk_src",
+		.parent_names = gcc_xo_sleep_clk,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(240000000, P_GPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+	.cmd_rcgr = 0x75024,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_ufs_axi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ufs_axi_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 ufs_ice_core_clk_src = {
+	.cmd_rcgr = 0x76014,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ufs_ice_core_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 qspi_ser_clk_src = {
+	.cmd_rcgr = 0x8b00c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "qspi_ser_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+	.halt_reg = 0x0f03c,
+	.clkr = {
+		.enable_reg = 0x0f03c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sys_noc_usb3_axi_clk",
+			.parent_names = (const char *[]){ "usb30_master_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sys_noc_ufs_axi_clk = {
+	.halt_reg = 0x75038,
+	.clkr = {
+		.enable_reg = 0x75038,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sys_noc_ufs_axi_clk",
+			.parent_names = (const char *[]){ "ufs_axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_periph_noc_usb20_ahb_clk = {
+	.halt_reg = 0x6010,
+	.clkr = {
+		.enable_reg = 0x6010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_periph_noc_usb20_ahb_clk",
+			.parent_names = (const char *[]){ "usb20_master_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+	.halt_reg = 0x9008,
+	.clkr = {
+		.enable_reg = 0x9008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_mmss_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_mmss_bimc_gfx_clk = {
+	.halt_reg = 0x9010,
+	.clkr = {
+		.enable_reg = 0x9010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_mmss_bimc_gfx_clk",
+			.flags = CLK_SET_RATE_PARENT | CLK_IS_ROOT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+	.halt_reg = 0x0f008,
+	.clkr = {
+		.enable_reg = 0x0f008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_master_clk",
+			.parent_names = (const char *[]){ "usb30_master_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+	.halt_reg = 0x0f00c,
+	.clkr = {
+		.enable_reg = 0x0f00c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_sleep_clk",
+			.parent_names = (const char *[]){ "gcc_sleep_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+	.halt_reg = 0x0f010,
+	.clkr = {
+		.enable_reg = 0x0f010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_mock_utmi_clk",
+			.parent_names = (const char *[]){ "usb30_mock_utmi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+	.halt_reg = 0x50000,
+	.clkr = {
+		.enable_reg = 0x50000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb3_phy_aux_clk",
+			.parent_names = (const char *[]){ "usb3_phy_aux_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+	.halt_reg = 0x50004,
+	.clkr = {
+		.enable_reg = 0x50004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb3_phy_pipe_clk",
+			.parent_names = (const char *[]){ "usb3_phy_pipe_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb20_master_clk = {
+	.halt_reg = 0x12004,
+	.clkr = {
+		.enable_reg = 0x12004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb20_master_clk",
+			.parent_names = (const char *[]){ "usb20_master_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb20_sleep_clk = {
+	.halt_reg = 0x12008,
+	.clkr = {
+		.enable_reg = 0x12008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb20_sleep_clk",
+			.parent_names = (const char *[]){ "gcc_sleep_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb20_mock_utmi_clk = {
+	.halt_reg = 0x1200c,
+	.clkr = {
+		.enable_reg = 0x1200c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb20_mock_utmi_clk",
+			.parent_names = (const char *[]){ "usb20_mock_utmi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+	.halt_reg = 0x6a004,
+	.clkr = {
+		.enable_reg = 0x6a004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_phy_cfg_ahb2phy_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+	.halt_reg = 0x13004,
+	.clkr = {
+		.enable_reg = 0x13004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_apps_clk",
+			.parent_names = (const char *[]){ "sdcc1_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+	.halt_reg = 0x13008,
+	.clkr = {
+		.enable_reg = 0x13008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+	.halt_reg = 0x13038,
+	.clkr = {
+		.enable_reg = 0x13038,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_ice_core_clk",
+			.parent_names = (const char *[]){ "sdcc1_ice_core_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+	.halt_reg = 0x14004,
+	.clkr = {
+		.enable_reg = 0x14004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc2_apps_clk",
+			.parent_names = (const char *[]){ "sdcc2_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+	.halt_reg = 0x14008,
+	.clkr = {
+		.enable_reg = 0x14008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc2_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc3_apps_clk = {
+	.halt_reg = 0x15004,
+	.clkr = {
+		.enable_reg = 0x15004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc3_apps_clk",
+			.parent_names = (const char *[]){ "sdcc3_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc3_ahb_clk = {
+	.halt_reg = 0x15008,
+	.clkr = {
+		.enable_reg = 0x15008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc3_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+	.halt_reg = 0x16004,
+	.clkr = {
+		.enable_reg = 0x16004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc4_apps_clk",
+			.parent_names = (const char *[]){ "sdcc4_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc4_ahb_clk = {
+	.halt_reg = 0x16008,
+	.clkr = {
+		.enable_reg = 0x16008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc4_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+	.halt_reg = 0x17004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(17),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_sleep_clk = {
+	.halt_reg = 0x17008,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(16),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_sleep_clk",
+			.parent_names = (const char *[]){ "gcc_sleep_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+	.halt_reg = 0x19004,
+	.clkr = {
+		.enable_reg = 0x19004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup1_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup1_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+	.halt_reg = 0x19008,
+	.clkr = {
+		.enable_reg = 0x19008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup1_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+	.halt_reg = 0x1a004,
+	.clkr = {
+		.enable_reg = 0x1a004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart1_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_uart1_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+	.halt_reg = 0x1b004,
+	.clkr = {
+		.enable_reg = 0x1b004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup2_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup2_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+	.halt_reg = 0x1b008,
+	.clkr = {
+		.enable_reg = 0x1b008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup2_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+	.halt_reg = 0x1c004,
+	.clkr = {
+		.enable_reg = 0x1c004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart2_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_uart2_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+	.halt_reg = 0x1d004,
+	.clkr = {
+		.enable_reg = 0x1d004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup3_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup3_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+	.halt_reg = 0x1d008,
+	.clkr = {
+		.enable_reg = 0x1d008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup3_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+	.halt_reg = 0x1e004,
+	.clkr = {
+		.enable_reg = 0x1e004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart3_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_uart3_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+	.halt_reg = 0x1f004,
+	.clkr = {
+		.enable_reg = 0x1f004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup4_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup4_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+	.halt_reg = 0x1f008,
+	.clkr = {
+		.enable_reg = 0x1f008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup4_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+	.halt_reg = 0x20004,
+	.clkr = {
+		.enable_reg = 0x20004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart4_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_uart4_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+	.halt_reg = 0x21004,
+	.clkr = {
+		.enable_reg = 0x21004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup5_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup5_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+	.halt_reg = 0x21008,
+	.clkr = {
+		.enable_reg = 0x21008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup5_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+	.halt_reg = 0x22004,
+	.clkr = {
+		.enable_reg = 0x22004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart5_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_uart5_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+	.halt_reg = 0x23004,
+	.clkr = {
+		.enable_reg = 0x23004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup6_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup6_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+	.halt_reg = 0x23008,
+	.clkr = {
+		.enable_reg = 0x23008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_qup6_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+	.halt_reg = 0x24004,
+	.clkr = {
+		.enable_reg = 0x24004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart6_apps_clk",
+			.parent_names = (const char *[]){ "blsp1_uart6_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+	.halt_reg = 0x25004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(15),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_sleep_clk = {
+	.halt_reg = 0x25008,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(14),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_sleep_clk",
+			.parent_names = (const char *[]){ "gcc_sleep_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+	.halt_reg = 0x26004,
+	.clkr = {
+		.enable_reg = 0x26004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup1_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup1_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+	.halt_reg = 0x26008,
+	.clkr = {
+		.enable_reg = 0x26008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup1_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+	.halt_reg = 0x27004,
+	.clkr = {
+		.enable_reg = 0x27004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart1_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_uart1_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+	.halt_reg = 0x28004,
+	.clkr = {
+		.enable_reg = 0x28004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup2_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup2_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+	.halt_reg = 0x28008,
+	.clkr = {
+		.enable_reg = 0x28008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup2_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+	.halt_reg = 0x29004,
+	.clkr = {
+		.enable_reg = 0x29004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart2_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_uart2_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+	.halt_reg = 0x2a004,
+	.clkr = {
+		.enable_reg = 0x2a004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup3_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup3_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+	.halt_reg = 0x2a008,
+	.clkr = {
+		.enable_reg = 0x2a008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup3_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+	.halt_reg = 0x2b004,
+	.clkr = {
+		.enable_reg = 0x2b004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart3_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_uart3_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+	.halt_reg = 0x2c004,
+	.clkr = {
+		.enable_reg = 0x2c004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup4_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup4_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+	.halt_reg = 0x2c008,
+	.clkr = {
+		.enable_reg = 0x2c008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup4_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+	.halt_reg = 0x2d004,
+	.clkr = {
+		.enable_reg = 0x2d004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart4_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_uart4_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+	.halt_reg = 0x2e004,
+	.clkr = {
+		.enable_reg = 0x2e004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup5_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup5_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+	.halt_reg = 0x2e008,
+	.clkr = {
+		.enable_reg = 0x2e008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup5_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+	.halt_reg = 0x2f004,
+	.clkr = {
+		.enable_reg = 0x2f004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart5_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_uart5_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+	.halt_reg = 0x30004,
+	.clkr = {
+		.enable_reg = 0x30004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup6_spi_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup6_spi_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+	.halt_reg = 0x30008,
+	.clkr = {
+		.enable_reg = 0x30008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_qup6_i2c_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+	.halt_reg = 0x31004,
+	.clkr = {
+		.enable_reg = 0x31004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart6_apps_clk",
+			.parent_names = (const char *[]){ "blsp2_uart6_apps_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+	.halt_reg = 0x33004,
+	.clkr = {
+		.enable_reg = 0x33004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pdm_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+	.halt_reg = 0x3300c,
+	.clkr = {
+		.enable_reg = 0x3300c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pdm2_clk",
+			.parent_names = (const char *[]){ "pdm2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+	.halt_reg = 0x34004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(13),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_prng_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_ahb_clk = {
+	.halt_reg = 0x36004,
+	.clkr = {
+		.enable_reg = 0x36004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_tsif_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_ref_clk = {
+	.halt_reg = 0x36008,
+	.clkr = {
+		.enable_reg = 0x36008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_tsif_ref_clk",
+			.parent_names = (const char *[]){ "tsif_ref_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_inactivity_timers_clk = {
+	.halt_reg = 0x3600c,
+	.clkr = {
+		.enable_reg = 0x3600c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_tsif_inactivity_timers_clk",
+			.parent_names = (const char *[]){ "gcc_sleep_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+	.halt_reg = 0x38004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(10),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_boot_rom_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_bimc_gfx_clk = {
+	.halt_reg = 0x46018,
+	.clkr = {
+		.enable_reg = 0x46018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_bimc_gfx_clk",
+			.flags = CLK_SET_RATE_PARENT | CLK_IS_ROOT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_hmss_rbcpr_clk = {
+	.halt_reg = 0x4800c,
+	.clkr = {
+		.enable_reg = 0x4800c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_hmss_rbcpr_clk",
+			.parent_names = (const char *[]){ "hmss_rbcpr_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp1_clk = {
+	.halt_reg = 0x64000,
+	.clkr = {
+		.enable_reg = 0x64000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_gp1_clk",
+			.parent_names = (const char *[]){ "gp1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp2_clk = {
+	.halt_reg = 0x65000,
+	.clkr = {
+		.enable_reg = 0x65000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_gp2_clk",
+			.parent_names = (const char *[]){ "gp2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp3_clk = {
+	.halt_reg = 0x66000,
+	.clkr = {
+		.enable_reg = 0x66000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_gp3_clk",
+			.parent_names = (const char *[]){ "gp3_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_slv_axi_clk = {
+	.halt_reg = 0x6b008,
+	.clkr = {
+		.enable_reg = 0x6b008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_slv_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+	.halt_reg = 0x6b00c,
+	.clkr = {
+		.enable_reg = 0x6b00c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_mstr_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
+	.halt_reg = 0x6b010,
+	.clkr = {
+		.enable_reg = 0x6b010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+	.halt_reg = 0x6b014,
+	.clkr = {
+		.enable_reg = 0x6b014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_aux_clk",
+			.parent_names = (const char *[]){ "pcie_aux_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+	.halt_reg = 0x6b018,
+	.clkr = {
+		.enable_reg = 0x6b018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_pipe_clk",
+			.parent_names = (const char *[]){ "pcie_0_pipe_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_slv_axi_clk = {
+	.halt_reg = 0x6d008,
+	.clkr = {
+		.enable_reg = 0x6d008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_slv_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+	.halt_reg = 0x6d00c,
+	.clkr = {
+		.enable_reg = 0x6d00c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_mstr_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
+	.halt_reg = 0x6d010,
+	.clkr = {
+		.enable_reg = 0x6d010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+	.halt_reg = 0x6d014,
+	.clkr = {
+		.enable_reg = 0x6d014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_aux_clk",
+			.parent_names = (const char *[]){ "pcie_aux_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+	.halt_reg = 0x6d018,
+	.clkr = {
+		.enable_reg = 0x6d018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_pipe_clk",
+			.parent_names = (const char *[]){ "pcie_1_pipe_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_2_slv_axi_clk = {
+	.halt_reg = 0x6e008,
+	.clkr = {
+		.enable_reg = 0x6e008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_2_slv_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_2_mstr_axi_clk = {
+	.halt_reg = 0x6e00c,
+	.clkr = {
+		.enable_reg = 0x6e00c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_2_mstr_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_2_cfg_ahb_clk = {
+	.halt_reg = 0x6e010,
+	.clkr = {
+		.enable_reg = 0x6e010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_2_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_2_aux_clk = {
+	.halt_reg = 0x6e014,
+	.clkr = {
+		.enable_reg = 0x6e014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_2_aux_clk",
+			.parent_names = (const char *[]){ "pcie_aux_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_2_pipe_clk = {
+	.halt_reg = 0x6e108,
+	.clkr = {
+		.enable_reg = 0x6e108,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_2_pipe_clk",
+			.parent_names = (const char *[]){ "pcie_2_pipe_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = {
+	.halt_reg = 0x6f004,
+	.clkr = {
+		.enable_reg = 0x6f004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_phy_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_phy_aux_clk = {
+	.halt_reg = 0x6f008,
+	.clkr = {
+		.enable_reg = 0x6f008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_phy_aux_clk",
+			.parent_names = (const char *[]){ "pcie_aux_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+	.halt_reg = 0x75008,
+	.clkr = {
+		.enable_reg = 0x75008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_axi_clk",
+			.parent_names = (const char *[]){ "ufs_axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_ahb_clk = {
+	.halt_reg = 0x7500c,
+	.clkr = {
+		.enable_reg = 0x7500c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_fixed_factor ufs_tx_cfg_clk_src = {
+	.mult = 1,
+	.div = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "ufs_tx_cfg_clk_src",
+		.parent_names = (const char *[]){ "ufs_axi_clk_src" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct clk_branch gcc_ufs_tx_cfg_clk = {
+	.halt_reg = 0x75010,
+	.clkr = {
+		.enable_reg = 0x75010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_tx_cfg_clk",
+			.parent_names = (const char *[]){ "ufs_tx_cfg_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_fixed_factor ufs_rx_cfg_clk_src = {
+	.mult = 1,
+	.div = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "ufs_rx_cfg_clk_src",
+		.parent_names = (const char *[]){ "ufs_axi_clk_src" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct clk_branch gcc_ufs_rx_cfg_clk = {
+	.halt_reg = 0x75014,
+	.clkr = {
+		.enable_reg = 0x75014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_rx_cfg_clk",
+			.parent_names = (const char *[]){ "ufs_rx_cfg_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
+	.halt_reg = 0x75018,
+	.clkr = {
+		.enable_reg = 0x75018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_tx_symbol_0_clk",
+			.parent_names = (const char *[]){ "ufs_tx_symbol_0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
+	.halt_reg = 0x7501c,
+	.clkr = {
+		.enable_reg = 0x7501c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_rx_symbol_0_clk",
+			.parent_names = (const char *[]){ "ufs_rx_symbol_0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+	.halt_reg = 0x75020,
+	.clkr = {
+		.enable_reg = 0x75020,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_rx_symbol_1_clk",
+			.parent_names = (const char *[]){ "ufs_rx_symbol_1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_fixed_factor ufs_ice_core_postdiv_clk_src = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "ufs_ice_core_postdiv_clk_src",
+		.parent_names = (const char *[]){ "ufs_ice_core_clk_src" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct clk_branch gcc_ufs_unipro_core_clk = {
+	.halt_reg = 0x7600c,
+	.clkr = {
+		.enable_reg = 0x7600c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_unipro_core_clk",
+			.parent_names = (const char *[]){ "ufs_ice_core_postdiv_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_ice_core_clk = {
+	.halt_reg = 0x76010,
+	.clkr = {
+		.enable_reg = 0x76010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_ice_core_clk",
+			.parent_names = (const char *[]){ "ufs_ice_core_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_sys_clk_core_clk = {
+	.halt_check = BRANCH_HALT_DELAY,
+	.clkr = {
+		.enable_reg = 0x76030,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_sys_clk_core_clk",
+			.ops = &clk_branch2_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_clk_core_clk = {
+	.halt_check = BRANCH_HALT_DELAY,
+	.clkr = {
+		.enable_reg = 0x76034,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_tx_symbol_clk_core_clk",
+			.ops = &clk_branch2_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gcc_aggre0_snoc_axi_clk = {
+	.halt_reg = 0x81008,
+	.clkr = {
+		.enable_reg = 0x81008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_aggre0_snoc_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_aggre0_cnoc_ahb_clk = {
+	.halt_reg = 0x8100c,
+	.clkr = {
+		.enable_reg = 0x8100c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_aggre0_cnoc_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_smmu_aggre0_axi_clk = {
+	.halt_reg = 0x81014,
+	.clkr = {
+		.enable_reg = 0x81014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_smmu_aggre0_axi_clk",
+			.parent_names = (const char *[]){ "system_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
+	.halt_reg = 0x81018,
+	.clkr = {
+		.enable_reg = 0x81018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_smmu_aggre0_ahb_clk",
+			.parent_names = (const char *[]){ "config_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_aggre1_pnoc_ahb_clk = {
+	.halt_reg = 0x82014,
+	.clkr = {
+		.enable_reg = 0x82014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_aggre1_pnoc_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_aggre2_ufs_axi_clk = {
+	.halt_reg = 0x83014,
+	.clkr = {
+		.enable_reg = 0x83014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_aggre2_ufs_axi_clk",
+			.parent_names = (const char *[]){ "ufs_axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_aggre2_usb3_axi_clk = {
+	.halt_reg = 0x83018,
+	.clkr = {
+		.enable_reg = 0x83018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_aggre2_usb3_axi_clk",
+			.parent_names = (const char *[]){ "usb30_master_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_qspi_ahb_clk = {
+	.halt_reg = 0x8b004,
+	.clkr = {
+		.enable_reg = 0x8b004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_qspi_ahb_clk",
+			.parent_names = (const char *[]){ "periph_noc_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_qspi_ser_clk = {
+	.halt_reg = 0x8b008,
+	.clkr = {
+		.enable_reg = 0x8b008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_qspi_ser_clk",
+			.parent_names = (const char *[]){ "qspi_ser_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb3_clkref_clk = {
+	.halt_reg = 0x8800C,
+	.clkr = {
+		.enable_reg = 0x8800C,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb3_clkref_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_hdmi_clkref_clk = {
+	.halt_reg = 0x88000,
+	.clkr = {
+		.enable_reg = 0x88000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_hdmi_clkref_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_clkref_clk = {
+	.halt_reg = 0x88008,
+	.clkr = {
+		.enable_reg = 0x88008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_clkref_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_clkref_clk = {
+	.halt_reg = 0x88010,
+	.clkr = {
+		.enable_reg = 0x88010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_clkref_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_rx2_usb2_clkref_clk = {
+	.halt_reg = 0x88014,
+	.clkr = {
+		.enable_reg = 0x88014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_rx2_usb2_clkref_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_rx1_usb2_clkref_clk = {
+	.halt_reg = 0x88018,
+	.clkr = {
+		.enable_reg = 0x88018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_rx1_usb2_clkref_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_hw *gcc_msm8996_hws[] = {
+	&xo.hw,
+	&gpll0_early_div.hw,
+	&ufs_tx_cfg_clk_src.hw,
+	&ufs_rx_cfg_clk_src.hw,
+	&ufs_ice_core_postdiv_clk_src.hw,
+};
+
+static struct clk_regmap *gcc_msm8996_clocks[] = {
+	[GPLL0_EARLY] = &gpll0_early.clkr,
+	[GPLL0] = &gpll0.clkr,
+	[GPLL4_EARLY] = &gpll4_early.clkr,
+	[GPLL4] = &gpll4.clkr,
+	[SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr,
+	[CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr,
+	[PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr,
+	[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+	[USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+	[USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+	[USB20_MASTER_CLK_SRC] = &usb20_master_clk_src.clkr,
+	[USB20_MOCK_UTMI_CLK_SRC] = &usb20_mock_utmi_clk_src.clkr,
+	[SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+	[SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr,
+	[SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+	[SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr,
+	[SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
+	[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+	[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+	[BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+	[BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+	[BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+	[BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+	[BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+	[BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+	[BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr,
+	[BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+	[BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+	[BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr,
+	[BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+	[BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+	[BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr,
+	[BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+	[BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+	[BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr,
+	[BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+	[BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+	[BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+	[BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+	[BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+	[BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+	[BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+	[BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+	[BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.clkr,
+	[BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+	[BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+	[BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.clkr,
+	[BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.clkr,
+	[BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.clkr,
+	[BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.clkr,
+	[BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.clkr,
+	[BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.clkr,
+	[BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr,
+	[PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+	[TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
+	[GCC_SLEEP_CLK_SRC] = &gcc_sleep_clk_src.clkr,
+	[HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
+	[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
+	[GP1_CLK_SRC] = &gp1_clk_src.clkr,
+	[GP2_CLK_SRC] = &gp2_clk_src.clkr,
+	[GP3_CLK_SRC] = &gp3_clk_src.clkr,
+	[PCIE_AUX_CLK_SRC] = &pcie_aux_clk_src.clkr,
+	[UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+	[UFS_ICE_CORE_CLK_SRC] = &ufs_ice_core_clk_src.clkr,
+	[QSPI_SER_CLK_SRC] = &qspi_ser_clk_src.clkr,
+	[GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
+	[GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
+	[GCC_PERIPH_NOC_USB20_AHB_CLK] = &gcc_periph_noc_usb20_ahb_clk.clkr,
+	[GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.clkr,
+	[GCC_MMSS_BIMC_GFX_CLK] = &gcc_mmss_bimc_gfx_clk.clkr,
+	[GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+	[GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+	[GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+	[GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+	[GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
+	[GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr,
+	[GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr,
+	[GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr,
+	[GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
+	[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+	[GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+	[GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+	[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+	[GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+	[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
+	[GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr,
+	[GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+	[GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr,
+	[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+	[GCC_BLSP1_SLEEP_CLK] = &gcc_blsp1_sleep_clk.clkr,
+	[GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+	[GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+	[GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+	[GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+	[GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+	[GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+	[GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+	[GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+	[GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+	[GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
+	[GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+	[GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+	[GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+	[GCC_BLSP2_SLEEP_CLK] = &gcc_blsp2_sleep_clk.clkr,
+	[GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+	[GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+	[GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+	[GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+	[GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+	[GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.clkr,
+	[GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+	[GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.clkr,
+	[GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.clkr,
+	[GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.clkr,
+	[GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.clkr,
+	[GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.clkr,
+	[GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+	[GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+	[GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+	[GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr,
+	[GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
+	[GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr,
+	[GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+	[GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+	[GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr,
+	[GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+	[GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+	[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+	[GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr,
+	[GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr,
+	[GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr,
+	[GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+	[GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+	[GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr,
+	[GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr,
+	[GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr,
+	[GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+	[GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+	[GCC_PCIE_2_SLV_AXI_CLK] = &gcc_pcie_2_slv_axi_clk.clkr,
+	[GCC_PCIE_2_MSTR_AXI_CLK] = &gcc_pcie_2_mstr_axi_clk.clkr,
+	[GCC_PCIE_2_CFG_AHB_CLK] = &gcc_pcie_2_cfg_ahb_clk.clkr,
+	[GCC_PCIE_2_AUX_CLK] = &gcc_pcie_2_aux_clk.clkr,
+	[GCC_PCIE_2_PIPE_CLK] = &gcc_pcie_2_pipe_clk.clkr,
+	[GCC_PCIE_PHY_CFG_AHB_CLK] = &gcc_pcie_phy_cfg_ahb_clk.clkr,
+	[GCC_PCIE_PHY_AUX_CLK] = &gcc_pcie_phy_aux_clk.clkr,
+	[GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+	[GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
+	[GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
+	[GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
+	[GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
+	[GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
+	[GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
+	[GCC_UFS_UNIPRO_CORE_CLK] = &gcc_ufs_unipro_core_clk.clkr,
+	[GCC_UFS_ICE_CORE_CLK] = &gcc_ufs_ice_core_clk.clkr,
+	[GCC_UFS_SYS_CLK_CORE_CLK] = &gcc_ufs_sys_clk_core_clk.clkr,
+	[GCC_UFS_TX_SYMBOL_CLK_CORE_CLK] = &gcc_ufs_tx_symbol_clk_core_clk.clkr,
+	[GCC_AGGRE0_SNOC_AXI_CLK] = &gcc_aggre0_snoc_axi_clk.clkr,
+	[GCC_AGGRE0_CNOC_AHB_CLK] = &gcc_aggre0_cnoc_ahb_clk.clkr,
+	[GCC_SMMU_AGGRE0_AXI_CLK] = &gcc_smmu_aggre0_axi_clk.clkr,
+	[GCC_SMMU_AGGRE0_AHB_CLK] = &gcc_smmu_aggre0_ahb_clk.clkr,
+	[GCC_AGGRE1_PNOC_AHB_CLK] = &gcc_aggre1_pnoc_ahb_clk.clkr,
+	[GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr,
+	[GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr,
+	[GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr,
+	[GCC_QSPI_SER_CLK] = &gcc_qspi_ser_clk.clkr,
+	[GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr,
+	[GCC_HDMI_CLKREF_CLK] = &gcc_hdmi_clkref_clk.clkr,
+	[GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr,
+	[GCC_PCIE_CLKREF_CLK] = &gcc_pcie_clkref_clk.clkr,
+	[GCC_RX2_USB2_CLKREF_CLK] = &gcc_rx2_usb2_clkref_clk.clkr,
+	[GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_msm8996_resets[] = {
+	[GCC_SYSTEM_NOC_BCR] = { 0x4000 },
+	[GCC_CONFIG_NOC_BCR] = { 0x5000 },
+	[GCC_PERIPH_NOC_BCR] = { 0x6000 },
+	[GCC_IMEM_BCR] = { 0x8000 },
+	[GCC_MMSS_BCR] = { 0x9000 },
+	[GCC_PIMEM_BCR] = { 0x0a000 },
+	[GCC_QDSS_BCR] = { 0x0c000 },
+	[GCC_USB_30_BCR] = { 0x0f000 },
+	[GCC_USB_20_BCR] = { 0x12000 },
+	[GCC_QUSB2PHY_PRIM_BCR] = { 0x12038 },
+	[GCC_QUSB2PHY_SEC_BCR] = { 0x1203c },
+	[GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+	[GCC_SDCC1_BCR] = { 0x13000 },
+	[GCC_SDCC2_BCR] = { 0x14000 },
+	[GCC_SDCC3_BCR] = { 0x15000 },
+	[GCC_SDCC4_BCR] = { 0x16000 },
+	[GCC_BLSP1_BCR] = { 0x17000 },
+	[GCC_BLSP1_QUP1_BCR] = { 0x19000 },
+	[GCC_BLSP1_UART1_BCR] = { 0x1a000 },
+	[GCC_BLSP1_QUP2_BCR] = { 0x1b000 },
+	[GCC_BLSP1_UART2_BCR] = { 0x1c000 },
+	[GCC_BLSP1_QUP3_BCR] = { 0x1d000 },
+	[GCC_BLSP1_UART3_BCR] = { 0x1e000 },
+	[GCC_BLSP1_QUP4_BCR] = { 0x1f000 },
+	[GCC_BLSP1_UART4_BCR] = { 0x20000 },
+	[GCC_BLSP1_QUP5_BCR] = { 0x21000 },
+	[GCC_BLSP1_UART5_BCR] = { 0x22000 },
+	[GCC_BLSP1_QUP6_BCR] = { 0x23000 },
+	[GCC_BLSP1_UART6_BCR] = { 0x24000 },
+	[GCC_BLSP2_BCR] = { 0x25000 },
+	[GCC_BLSP2_QUP1_BCR] = { 0x26000 },
+	[GCC_BLSP2_UART1_BCR] = { 0x27000 },
+	[GCC_BLSP2_QUP2_BCR] = { 0x28000 },
+	[GCC_BLSP2_UART2_BCR] = { 0x29000 },
+	[GCC_BLSP2_QUP3_BCR] = { 0x2a000 },
+	[GCC_BLSP2_UART3_BCR] = { 0x2b000 },
+	[GCC_BLSP2_QUP4_BCR] = { 0x2c000 },
+	[GCC_BLSP2_UART4_BCR] = { 0x2d000 },
+	[GCC_BLSP2_QUP5_BCR] = { 0x2e000 },
+	[GCC_BLSP2_UART5_BCR] = { 0x2f000 },
+	[GCC_BLSP2_QUP6_BCR] = { 0x30000 },
+	[GCC_BLSP2_UART6_BCR] = { 0x31000 },
+	[GCC_PDM_BCR] = { 0x33000 },
+	[GCC_PRNG_BCR] = { 0x34000 },
+	[GCC_TSIF_BCR] = { 0x36000 },
+	[GCC_TCSR_BCR] = { 0x37000 },
+	[GCC_BOOT_ROM_BCR] = { 0x38000 },
+	[GCC_MSG_RAM_BCR] = { 0x39000 },
+	[GCC_TLMM_BCR] = { 0x3a000 },
+	[GCC_MPM_BCR] = { 0x3b000 },
+	[GCC_SEC_CTRL_BCR] = { 0x3d000 },
+	[GCC_SPMI_BCR] = { 0x3f000 },
+	[GCC_SPDM_BCR] = { 0x40000 },
+	[GCC_CE1_BCR] = { 0x41000 },
+	[GCC_BIMC_BCR] = { 0x44000 },
+	[GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x49000 },
+	[GCC_SNOC_BUS_TIMEOUT2_BCR] = { 0x49008 },
+	[GCC_SNOC_BUS_TIMEOUT1_BCR] = { 0x49010 },
+	[GCC_SNOC_BUS_TIMEOUT3_BCR] = { 0x49018 },
+	[GCC_SNOC_BUS_TIMEOUT_EXTREF_BCR] = { 0x49020 },
+	[GCC_PNOC_BUS_TIMEOUT0_BCR] = { 0x4a000 },
+	[GCC_PNOC_BUS_TIMEOUT1_BCR] = { 0x4a008 },
+	[GCC_PNOC_BUS_TIMEOUT2_BCR] = { 0x4a010 },
+	[GCC_PNOC_BUS_TIMEOUT3_BCR] = { 0x4a018 },
+	[GCC_PNOC_BUS_TIMEOUT4_BCR] = { 0x4a020 },
+	[GCC_CNOC_BUS_TIMEOUT0_BCR] = { 0x4b000 },
+	[GCC_CNOC_BUS_TIMEOUT1_BCR] = { 0x4b008 },
+	[GCC_CNOC_BUS_TIMEOUT2_BCR] = { 0x4b010 },
+	[GCC_CNOC_BUS_TIMEOUT3_BCR] = { 0x4b018 },
+	[GCC_CNOC_BUS_TIMEOUT4_BCR] = { 0x4b020 },
+	[GCC_CNOC_BUS_TIMEOUT5_BCR] = { 0x4b028 },
+	[GCC_CNOC_BUS_TIMEOUT6_BCR] = { 0x4b030 },
+	[GCC_CNOC_BUS_TIMEOUT7_BCR] = { 0x4b038 },
+	[GCC_CNOC_BUS_TIMEOUT8_BCR] = { 0x80000 },
+	[GCC_CNOC_BUS_TIMEOUT9_BCR] = { 0x80008 },
+	[GCC_CNOC_BUS_TIMEOUT_EXTREF_BCR] = { 0x80010 },
+	[GCC_APB2JTAG_BCR] = { 0x4c000 },
+	[GCC_RBCPR_CX_BCR] = { 0x4e000 },
+	[GCC_RBCPR_MX_BCR] = { 0x4f000 },
+	[GCC_PCIE_0_BCR] = { 0x6b000 },
+	[GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+	[GCC_PCIE_1_BCR] = { 0x6d000 },
+	[GCC_PCIE_1_PHY_BCR] = { 0x6d038 },
+	[GCC_PCIE_2_BCR] = { 0x6e000 },
+	[GCC_PCIE_2_PHY_BCR] = { 0x6e038 },
+	[GCC_PCIE_PHY_BCR] = { 0x6f000 },
+	[GCC_DCD_BCR] = { 0x70000 },
+	[GCC_OBT_ODT_BCR] = { 0x73000 },
+	[GCC_UFS_BCR] = { 0x75000 },
+	[GCC_SSC_BCR] = { 0x63000 },
+	[GCC_VS_BCR] = { 0x7a000 },
+	[GCC_AGGRE0_NOC_BCR] = { 0x81000 },
+	[GCC_AGGRE1_NOC_BCR] = { 0x82000 },
+	[GCC_AGGRE2_NOC_BCR] = { 0x83000 },
+	[GCC_DCC_BCR] = { 0x84000 },
+	[GCC_IPA_BCR] = { 0x89000 },
+	[GCC_QSPI_BCR] = { 0x8b000 },
+	[GCC_SKL_BCR] = { 0x8c000 },
+	[GCC_MSMPU_BCR] = { 0x8d000 },
+	[GCC_MSS_Q6_BCR] = { 0x8e000 },
+	[GCC_QREFS_VBG_CAL_BCR] = { 0x88020 },
+};
+
+static const struct regmap_config gcc_msm8996_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x8f010,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc gcc_msm8996_desc = {
+	.config = &gcc_msm8996_regmap_config,
+	.clks = gcc_msm8996_clocks,
+	.num_clks = ARRAY_SIZE(gcc_msm8996_clocks),
+	.resets = gcc_msm8996_resets,
+	.num_resets = ARRAY_SIZE(gcc_msm8996_resets),
+};
+
+static const struct of_device_id gcc_msm8996_match_table[] = {
+	{ .compatible = "qcom,gcc-msm8996" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8996_match_table);
+
+static int gcc_msm8996_probe(struct platform_device *pdev)
+{
+	struct clk *clk;
+	struct device *dev = &pdev->dev;
+	int i;
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, &gcc_msm8996_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	/*
+	 * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be
+	 * turned off by hardware during certain apps low power modes.
+	 */
+	regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
+
+	for (i = 0; i < ARRAY_SIZE(gcc_msm8996_hws); i++) {
+		clk = devm_clk_register(dev, gcc_msm8996_hws[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+	}
+
+	return qcom_cc_really_probe(pdev, &gcc_msm8996_desc, regmap);
+}
+
+static struct platform_driver gcc_msm8996_driver = {
+	.probe		= gcc_msm8996_probe,
+	.driver		= {
+		.name	= "gcc-msm8996",
+		.of_match_table = gcc_msm8996_match_table,
+	},
+};
+
+static int __init gcc_msm8996_init(void)
+{
+	return platform_driver_register(&gcc_msm8996_driver);
+}
+core_initcall(gcc_msm8996_init);
+
+static void __exit gcc_msm8996_exit(void)
+{
+	platform_driver_unregister(&gcc_msm8996_driver);
+}
+module_exit(gcc_msm8996_exit);
+
+MODULE_DESCRIPTION("QCOM GCC MSM8996 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8996");
diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c
index db3998e5e2d8..62e79fadd5f7 100644
--- a/drivers/clk/qcom/lcc-ipq806x.c
+++ b/drivers/clk/qcom/lcc-ipq806x.c
@@ -419,6 +419,7 @@ static const struct regmap_config lcc_ipq806x_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0xfc,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc lcc_ipq806x_desc = {
diff --git a/drivers/clk/qcom/lcc-msm8960.c b/drivers/clk/qcom/lcc-msm8960.c
index 4fcf9d1d233c..bf95bb0ea1b8 100644
--- a/drivers/clk/qcom/lcc-msm8960.c
+++ b/drivers/clk/qcom/lcc-msm8960.c
@@ -524,6 +524,7 @@ static const struct regmap_config lcc_msm8960_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0xfc,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc lcc_msm8960_desc = {
diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c
index 30777f9f1a43..1e703fda8a0f 100644
--- a/drivers/clk/qcom/mmcc-apq8084.c
+++ b/drivers/clk/qcom/mmcc-apq8084.c
@@ -3368,6 +3368,7 @@ static const struct regmap_config mmcc_apq8084_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x5104,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc mmcc_apq8084_desc = {
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index 00e36192a1de..d73a048d3b9d 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -3029,6 +3029,7 @@ static const struct regmap_config mmcc_msm8960_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x334,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct regmap_config mmcc_apq8064_regmap_config = {
@@ -3037,6 +3038,7 @@ static const struct regmap_config mmcc_apq8064_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x350,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc mmcc_msm8960_desc = {
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index 9d790bcadf25..bbe28ed93669 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -2594,6 +2594,7 @@ static const struct regmap_config mmcc_msm8974_regmap_config = {
 	.val_bits	= 32,
 	.max_register	= 0x5104,
 	.fast_io	= true,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc mmcc_msm8974_desc = {
diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c
new file mode 100644
index 000000000000..064f3eaa39d0
--- /dev/null
+++ b/drivers/clk/qcom/mmcc-msm8996.c
@@ -0,0 +1,3217 @@
+/*x
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/clock/qcom,mmcc-msm8996.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+	P_XO,
+	P_MMPLL0,
+	P_GPLL0,
+	P_GPLL0_DIV,
+	P_MMPLL1,
+	P_MMPLL9,
+	P_MMPLL2,
+	P_MMPLL8,
+	P_MMPLL3,
+	P_DSI0PLL,
+	P_DSI1PLL,
+	P_MMPLL5,
+	P_HDMIPLL,
+	P_DSI0PLL_BYTE,
+	P_DSI1PLL_BYTE,
+	P_MMPLL4,
+};
+
+static const struct parent_map mmss_xo_hdmi_map[] = {
+	{ P_XO, 0 },
+	{ P_HDMIPLL, 1 }
+};
+
+static const char * const mmss_xo_hdmi[] = {
+	"xo",
+	"hdmipll"
+};
+
+static const struct parent_map mmss_xo_dsi0pll_dsi1pll_map[] = {
+	{ P_XO, 0 },
+	{ P_DSI0PLL, 1 },
+	{ P_DSI1PLL, 2 }
+};
+
+static const char * const mmss_xo_dsi0pll_dsi1pll[] = {
+	"xo",
+	"dsi0pll",
+	"dsi1pll"
+};
+
+static const struct parent_map mmss_xo_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_gpll0_gpll0_div[] = {
+	"xo",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_dsibyte_map[] = {
+	{ P_XO, 0 },
+	{ P_DSI0PLL_BYTE, 1 },
+	{ P_DSI1PLL_BYTE, 2 }
+};
+
+static const char * const mmss_xo_dsibyte[] = {
+	"xo",
+	"dsi0pllbyte",
+	"dsi1pllbyte"
+};
+
+static const struct parent_map mmss_xo_mmpll0_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL1, 2 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"mmpll1",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL3, 3 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"mmpll3",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL5, 2 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"mmpll5",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL4, 3 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"mmpll4",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL9, 2 },
+	{ P_MMPLL2, 3 },
+	{ P_MMPLL8, 4 },
+	{ P_GPLL0, 5 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0[] = {
+	"xo",
+	"mmpll0",
+	"mmpll9",
+	"mmpll2",
+	"mmpll8",
+	"gpll0"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL9, 2 },
+	{ P_MMPLL2, 3 },
+	{ P_MMPLL8, 4 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"mmpll9",
+	"mmpll2",
+	"mmpll8",
+	"gpll0",
+	"gpll0_div"
+};
+
+static const struct parent_map mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map[] = {
+	{ P_XO, 0 },
+	{ P_MMPLL0, 1 },
+	{ P_MMPLL1, 2 },
+	{ P_MMPLL4, 3 },
+	{ P_MMPLL3, 4 },
+	{ P_GPLL0, 5 },
+	{ P_GPLL0_DIV, 6 }
+};
+
+static const char * const mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div[] = {
+	"xo",
+	"mmpll0",
+	"mmpll1",
+	"mmpll4",
+	"mmpll3",
+	"gpll0",
+	"gpll0_div"
+};
+
+static struct clk_fixed_factor gpll0_div = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll0_div",
+		.parent_names = (const char *[]){ "gpll0" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct pll_vco mmpll_p_vco[] = {
+	{ 250000000, 500000000, 3 },
+	{ 500000000, 1000000000, 2 },
+	{ 1000000000, 1500000000, 1 },
+	{ 1500000000, 2000000000, 0 },
+};
+
+static struct pll_vco mmpll_gfx_vco[] = {
+	{ 400000000, 1000000000, 2 },
+	{ 1000000000, 1500000000, 1 },
+	{ 1500000000, 2000000000, 0 },
+};
+
+static struct pll_vco mmpll_t_vco[] = {
+	{ 500000000, 1500000000, 0 },
+};
+
+static struct clk_alpha_pll mmpll0_early = {
+	.offset = 0x0,
+	.vco_table = mmpll_p_vco,
+	.num_vco = ARRAY_SIZE(mmpll_p_vco),
+	.clkr = {
+		.enable_reg = 0x100,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmpll0_early",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll0 = {
+	.offset = 0x0,
+	.width = 4,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll0",
+		.parent_names = (const char *[]){ "mmpll0_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll1_early = {
+	.offset = 0x30,
+	.vco_table = mmpll_p_vco,
+	.num_vco = ARRAY_SIZE(mmpll_p_vco),
+	.clkr = {
+		.enable_reg = 0x100,
+		.enable_mask = BIT(1),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmpll1_early",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		}
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll1 = {
+	.offset = 0x30,
+	.width = 4,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll1",
+		.parent_names = (const char *[]){ "mmpll1_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll2_early = {
+	.offset = 0x4100,
+	.vco_table = mmpll_gfx_vco,
+	.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll2_early",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll2 = {
+	.offset = 0x4100,
+	.width = 4,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll2",
+		.parent_names = (const char *[]){ "mmpll2_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll3_early = {
+	.offset = 0x60,
+	.vco_table = mmpll_p_vco,
+	.num_vco = ARRAY_SIZE(mmpll_p_vco),
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll3_early",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll3 = {
+	.offset = 0x60,
+	.width = 4,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll3",
+		.parent_names = (const char *[]){ "mmpll3_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll4_early = {
+	.offset = 0x90,
+	.vco_table = mmpll_t_vco,
+	.num_vco = ARRAY_SIZE(mmpll_t_vco),
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll4_early",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll4 = {
+	.offset = 0x90,
+	.width = 2,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll4",
+		.parent_names = (const char *[]){ "mmpll4_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll5_early = {
+	.offset = 0xc0,
+	.vco_table = mmpll_p_vco,
+	.num_vco = ARRAY_SIZE(mmpll_p_vco),
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll5_early",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll5 = {
+	.offset = 0xc0,
+	.width = 4,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll5",
+		.parent_names = (const char *[]){ "mmpll5_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll8_early = {
+	.offset = 0x4130,
+	.vco_table = mmpll_gfx_vco,
+	.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll8_early",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll8 = {
+	.offset = 0x4130,
+	.width = 4,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll8",
+		.parent_names = (const char *[]){ "mmpll8_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll mmpll9_early = {
+	.offset = 0x4200,
+	.vco_table = mmpll_t_vco,
+	.num_vco = ARRAY_SIZE(mmpll_t_vco),
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll9_early",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_ops,
+	},
+};
+
+static struct clk_alpha_pll_postdiv mmpll9 = {
+	.offset = 0x4200,
+	.width = 2,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll9",
+		.parent_names = (const char *[]){ "mmpll9_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct freq_tbl ftbl_ahb_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(40000000, P_GPLL0_DIV, 7.5, 0, 0),
+	F(80000000, P_MMPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ahb_clk_src = {
+	.cmd_rcgr = 0x5000,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_ahb_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ahb_clk_src",
+		.parent_names = mmss_xo_mmpll0_gpll0_gpll0_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_axi_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(75000000, P_GPLL0_DIV, 4, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(171430000, P_GPLL0, 3.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 axi_clk_src = {
+	.cmd_rcgr = 0x5040,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_axi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "axi_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 maxi_clk_src = {
+	.cmd_rcgr = 0x5090,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_axi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "maxi_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+	.cmd_rcgr = 0x4000,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gfx3d_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0,
+		.num_parents = 6,
+		.ops = &clk_gfx3d_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 rbbmtimer_clk_src = {
+	.cmd_rcgr = 0x4090,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_rbbmtimer_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "rbbmtimer_clk_src",
+		.parent_names = mmss_xo_mmpll0_gpll0_gpll0_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 isense_clk_src = {
+	.cmd_rcgr = 0x4010,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "isense_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_rbcpr_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 rbcpr_clk_src = {
+	.cmd_rcgr = 0x4060,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_rbcpr_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "rbcpr_clk_src",
+		.parent_names = mmss_xo_mmpll0_gpll0_gpll0_div,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_video_core_clk_src[] = {
+	F(75000000, P_GPLL0_DIV, 4, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(346666667, P_MMPLL3, 3, 0, 0),
+	F(520000000, P_MMPLL3, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 video_core_clk_src = {
+	.cmd_rcgr = 0x1000,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_video_core_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "video_core_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 video_subcore0_clk_src = {
+	.cmd_rcgr = 0x1060,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_video_core_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "video_subcore0_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 video_subcore1_clk_src = {
+	.cmd_rcgr = 0x1080,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_video_core_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "video_subcore1_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+	.cmd_rcgr = 0x2000,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_dsi0pll_dsi1pll_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pclk0_clk_src",
+		.parent_names = mmss_xo_dsi0pll_dsi1pll,
+		.num_parents = 3,
+		.ops = &clk_pixel_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_rcg2 pclk1_clk_src = {
+	.cmd_rcgr = 0x2020,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_dsi0pll_dsi1pll_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pclk1_clk_src",
+		.parent_names = mmss_xo_dsi0pll_dsi1pll,
+		.num_parents = 3,
+		.ops = &clk_pixel_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct freq_tbl ftbl_mdp_clk_src[] = {
+	F(85714286, P_GPLL0, 7, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(171428571, P_GPLL0, 3.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(275000000, P_MMPLL5, 3, 0, 0),
+	F(300000000, P_GPLL0, 2, 0, 0),
+	F(330000000, P_MMPLL5, 2.5, 0, 0),
+	F(412500000, P_MMPLL5, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+	.cmd_rcgr = 0x2040,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mdp_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mdp_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl extpclk_freq_tbl[] = {
+	{ .src = P_HDMIPLL },
+	{ }
+};
+
+static struct clk_rcg2 extpclk_clk_src = {
+	.cmd_rcgr = 0x2060,
+	.hid_width = 5,
+	.parent_map = mmss_xo_hdmi_map,
+	.freq_tbl = extpclk_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "extpclk_clk_src",
+		.parent_names = mmss_xo_hdmi,
+		.num_parents = 2,
+		.ops = &clk_byte_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_vsync_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+	.cmd_rcgr = 0x2080,
+	.hid_width = 5,
+	.parent_map = mmss_xo_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vsync_clk_src",
+		.parent_names = mmss_xo_gpll0_gpll0_div,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_hdmi_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 hdmi_clk_src = {
+	.cmd_rcgr = 0x2100,
+	.hid_width = 5,
+	.parent_map = mmss_xo_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mdss_hdmi_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "hdmi_clk_src",
+		.parent_names = mmss_xo_gpll0_gpll0_div,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+	.cmd_rcgr = 0x2120,
+	.hid_width = 5,
+	.parent_map = mmss_xo_dsibyte_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "byte0_clk_src",
+		.parent_names = mmss_xo_dsibyte,
+		.num_parents = 3,
+		.ops = &clk_byte2_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_rcg2 byte1_clk_src = {
+	.cmd_rcgr = 0x2140,
+	.hid_width = 5,
+	.parent_map = mmss_xo_dsibyte_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "byte1_clk_src",
+		.parent_names = mmss_xo_dsibyte,
+		.num_parents = 3,
+		.ops = &clk_byte2_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_esc0_1_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+	.cmd_rcgr = 0x2160,
+	.hid_width = 5,
+	.parent_map = mmss_xo_dsibyte_map,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "esc0_clk_src",
+		.parent_names = mmss_xo_dsibyte,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 esc1_clk_src = {
+	.cmd_rcgr = 0x2180,
+	.hid_width = 5,
+	.parent_map = mmss_xo_dsibyte_map,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "esc1_clk_src",
+		.parent_names = mmss_xo_dsibyte,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_camss_gp0_clk_src[] = {
+	F(10000, P_XO, 16, 1, 120),
+	F(24000, P_XO, 16, 1, 50),
+	F(6000000, P_GPLL0_DIV, 10, 1, 5),
+	F(12000000, P_GPLL0_DIV, 1, 1, 25),
+	F(13000000, P_GPLL0_DIV, 2, 13, 150),
+	F(24000000, P_GPLL0_DIV, 1, 2, 25),
+	{ }
+};
+
+static struct clk_rcg2 camss_gp0_clk_src = {
+	.cmd_rcgr = 0x3420,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_camss_gp0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "camss_gp0_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 camss_gp1_clk_src = {
+	.cmd_rcgr = 0x3450,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_camss_gp0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "camss_gp1_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_mclk0_clk_src[] = {
+	F(4800000, P_XO, 4, 0, 0),
+	F(6000000, P_GPLL0_DIV, 10, 1, 5),
+	F(8000000, P_GPLL0_DIV, 1, 2, 75),
+	F(9600000, P_XO, 2, 0, 0),
+	F(16666667, P_GPLL0_DIV, 2, 1, 9),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0_DIV, 1, 2, 25),
+	F(33333333, P_GPLL0_DIV, 1, 1, 9),
+	F(48000000, P_GPLL0, 1, 2, 25),
+	F(66666667, P_GPLL0, 1, 1, 9),
+	{ }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+	.cmd_rcgr = 0x3360,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mclk0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk0_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+	.cmd_rcgr = 0x3390,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mclk0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk1_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk2_clk_src = {
+	.cmd_rcgr = 0x33c0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mclk0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk2_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk3_clk_src = {
+	.cmd_rcgr = 0x33f0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_mclk0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk3_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cci_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+	.cmd_rcgr = 0x3300,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_cci_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "cci_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_csi0phytimer_clk_src[] = {
+	F(100000000, P_GPLL0_DIV, 3, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(266666667, P_MMPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+	.cmd_rcgr = 0x3000,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0phytimer_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi0phytimer_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+	.cmd_rcgr = 0x3030,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0phytimer_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi1phytimer_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi2phytimer_clk_src = {
+	.cmd_rcgr = 0x3060,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0phytimer_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi2phytimer_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_csiphy0_3p_clk_src[] = {
+	F(100000000, P_GPLL0_DIV, 3, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL4, 3, 0, 0),
+	F(384000000, P_MMPLL4, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csiphy0_3p_clk_src = {
+	.cmd_rcgr = 0x3240,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csiphy0_3p_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csiphy0_3p_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csiphy1_3p_clk_src = {
+	.cmd_rcgr = 0x3260,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csiphy0_3p_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csiphy1_3p_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csiphy2_3p_clk_src = {
+	.cmd_rcgr = 0x3280,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csiphy0_3p_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csiphy2_3p_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_jpeg0_clk_src[] = {
+	F(75000000, P_GPLL0_DIV, 4, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(228571429, P_MMPLL0, 3.5, 0, 0),
+	F(266666667, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(480000000, P_MMPLL4, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+	.cmd_rcgr = 0x3500,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_jpeg0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "jpeg0_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_jpeg2_clk_src[] = {
+	F(75000000, P_GPLL0_DIV, 4, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(228571429, P_MMPLL0, 3.5, 0, 0),
+	F(266666667, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 jpeg2_clk_src = {
+	.cmd_rcgr = 0x3540,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_jpeg2_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "jpeg2_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 jpeg_dma_clk_src = {
+	.cmd_rcgr = 0x3560,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_jpeg0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "jpeg_dma_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_vfe0_clk_src[] = {
+	F(75000000, P_GPLL0_DIV, 4, 0, 0),
+	F(100000000, P_GPLL0_DIV, 3, 0, 0),
+	F(300000000, P_GPLL0, 2, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(480000000, P_MMPLL4, 2, 0, 0),
+	F(600000000, P_GPLL0, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+	.cmd_rcgr = 0x3600,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_vfe0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vfe0_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 vfe1_clk_src = {
+	.cmd_rcgr = 0x3620,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_vfe0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vfe1_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_cpp_clk_src[] = {
+	F(100000000, P_GPLL0_DIV, 3, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(480000000, P_MMPLL4, 2, 0, 0),
+	F(640000000, P_MMPLL4, 1.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+	.cmd_rcgr = 0x3640,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_cpp_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "cpp_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_csi0_clk_src[] = {
+	F(100000000, P_GPLL0_DIV, 3, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(266666667, P_MMPLL0, 3, 0, 0),
+	F(480000000, P_MMPLL4, 2, 0, 0),
+	F(600000000, P_GPLL0, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+	.cmd_rcgr = 0x3090,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi0_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+	.cmd_rcgr = 0x3100,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi1_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi2_clk_src = {
+	.cmd_rcgr = 0x3160,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi2_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi3_clk_src = {
+	.cmd_rcgr = 0x31c0,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_csi0_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi3_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_fd_core_clk_src[] = {
+	F(100000000, P_GPLL0_DIV, 3, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 fd_core_clk_src = {
+	.cmd_rcgr = 0x3b00,
+	.hid_width = 5,
+	.parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map,
+	.freq_tbl = ftbl_fd_core_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "fd_core_clk_src",
+		.parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch mmss_mmagic_ahb_clk = {
+	.halt_reg = 0x5024,
+	.clkr = {
+		.enable_reg = 0x5024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmagic_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmagic_cfg_ahb_clk = {
+	.halt_reg = 0x5054,
+	.clkr = {
+		.enable_reg = 0x5054,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmagic_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_misc_ahb_clk = {
+	.halt_reg = 0x5018,
+	.clkr = {
+		.enable_reg = 0x5018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_misc_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_misc_cxo_clk = {
+	.halt_reg = 0x5014,
+	.clkr = {
+		.enable_reg = 0x5014,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_misc_cxo_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmagic_axi_clk = {
+	.halt_reg = 0x506c,
+	.clkr = {
+		.enable_reg = 0x506c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmagic_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmagic_maxi_clk = {
+	.halt_reg = 0x5074,
+	.clkr = {
+		.enable_reg = 0x5074,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmagic_maxi_clk",
+			.parent_names = (const char *[]){ "maxi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_camss_axi_clk = {
+	.halt_reg = 0x3c44,
+	.clkr = {
+		.enable_reg = 0x3c44,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_camss_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_camss_noc_cfg_ahb_clk = {
+	.halt_reg = 0x3c48,
+	.clkr = {
+		.enable_reg = 0x3c48,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_camss_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_vfe_ahb_clk = {
+	.halt_reg = 0x3c04,
+	.clkr = {
+		.enable_reg = 0x3c04,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_vfe_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_vfe_axi_clk = {
+	.halt_reg = 0x3c08,
+	.clkr = {
+		.enable_reg = 0x3c08,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_vfe_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_cpp_ahb_clk = {
+	.halt_reg = 0x3c14,
+	.clkr = {
+		.enable_reg = 0x3c14,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_cpp_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_cpp_axi_clk = {
+	.halt_reg = 0x3c18,
+	.clkr = {
+		.enable_reg = 0x3c18,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_cpp_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_jpeg_ahb_clk = {
+	.halt_reg = 0x3c24,
+	.clkr = {
+		.enable_reg = 0x3c24,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_jpeg_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_jpeg_axi_clk = {
+	.halt_reg = 0x3c28,
+	.clkr = {
+		.enable_reg = 0x3c28,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_jpeg_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_mdss_axi_clk = {
+	.halt_reg = 0x2474,
+	.clkr = {
+		.enable_reg = 0x2474,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_mdss_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_mdss_noc_cfg_ahb_clk = {
+	.halt_reg = 0x2478,
+	.clkr = {
+		.enable_reg = 0x2478,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_mdss_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_rot_ahb_clk = {
+	.halt_reg = 0x2444,
+	.clkr = {
+		.enable_reg = 0x2444,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_rot_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_rot_axi_clk = {
+	.halt_reg = 0x2448,
+	.clkr = {
+		.enable_reg = 0x2448,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_rot_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_mdp_ahb_clk = {
+	.halt_reg = 0x2454,
+	.clkr = {
+		.enable_reg = 0x2454,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_mdp_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_mdp_axi_clk = {
+	.halt_reg = 0x2458,
+	.clkr = {
+		.enable_reg = 0x2458,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_mdp_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_video_axi_clk = {
+	.halt_reg = 0x1194,
+	.clkr = {
+		.enable_reg = 0x1194,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_video_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_video_noc_cfg_ahb_clk = {
+	.halt_reg = 0x1198,
+	.clkr = {
+		.enable_reg = 0x1198,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_video_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_video_ahb_clk = {
+	.halt_reg = 0x1174,
+	.clkr = {
+		.enable_reg = 0x1174,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_video_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch smmu_video_axi_clk = {
+	.halt_reg = 0x1178,
+	.clkr = {
+		.enable_reg = 0x1178,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "smmu_video_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_bimc_axi_clk = {
+	.halt_reg = 0x5294,
+	.clkr = {
+		.enable_reg = 0x5294,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_bimc_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmagic_bimc_noc_cfg_ahb_clk = {
+	.halt_reg = 0x5298,
+	.clkr = {
+		.enable_reg = 0x5298,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmagic_bimc_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_gx_gfx3d_clk = {
+	.halt_reg = 0x4028,
+	.clkr = {
+		.enable_reg = 0x4028,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_gx_gfx3d_clk",
+			.parent_names = (const char *[]){ "gfx3d_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_gx_rbbmtimer_clk = {
+	.halt_reg = 0x40b0,
+	.clkr = {
+		.enable_reg = 0x40b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_gx_rbbmtimer_clk",
+			.parent_names = (const char *[]){ "rbbmtimer_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_ahb_clk = {
+	.halt_reg = 0x403c,
+	.clkr = {
+		.enable_reg = 0x403c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gpu_aon_isense_clk = {
+	.halt_reg = 0x4044,
+	.clkr = {
+		.enable_reg = 0x4044,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_aon_isense_clk",
+			.parent_names = (const char *[]){ "isense_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vmem_maxi_clk = {
+	.halt_reg = 0x1204,
+	.clkr = {
+		.enable_reg = 0x1204,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vmem_maxi_clk",
+			.parent_names = (const char *[]){ "maxi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vmem_ahb_clk = {
+	.halt_reg = 0x1208,
+	.clkr = {
+		.enable_reg = 0x1208,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vmem_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_rbcpr_clk = {
+	.halt_reg = 0x4084,
+	.clkr = {
+		.enable_reg = 0x4084,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_rbcpr_clk",
+			.parent_names = (const char *[]){ "rbcpr_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_rbcpr_ahb_clk = {
+	.halt_reg = 0x4088,
+	.clkr = {
+		.enable_reg = 0x4088,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_rbcpr_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_core_clk = {
+	.halt_reg = 0x1028,
+	.clkr = {
+		.enable_reg = 0x1028,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_core_clk",
+			.parent_names = (const char *[]){ "video_core_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_axi_clk = {
+	.halt_reg = 0x1034,
+	.clkr = {
+		.enable_reg = 0x1034,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_maxi_clk = {
+	.halt_reg = 0x1038,
+	.clkr = {
+		.enable_reg = 0x1038,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_maxi_clk",
+			.parent_names = (const char *[]){ "maxi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_ahb_clk = {
+	.halt_reg = 0x1030,
+	.clkr = {
+		.enable_reg = 0x1030,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_subcore0_clk = {
+	.halt_reg = 0x1048,
+	.clkr = {
+		.enable_reg = 0x1048,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_subcore0_clk",
+			.parent_names = (const char *[]){ "video_subcore0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch video_subcore1_clk = {
+	.halt_reg = 0x104c,
+	.clkr = {
+		.enable_reg = 0x104c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "video_subcore1_clk",
+			.parent_names = (const char *[]){ "video_subcore1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_ahb_clk = {
+	.halt_reg = 0x2308,
+	.clkr = {
+		.enable_reg = 0x2308,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_hdmi_ahb_clk = {
+	.halt_reg = 0x230c,
+	.clkr = {
+		.enable_reg = 0x230c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_hdmi_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_axi_clk = {
+	.halt_reg = 0x2310,
+	.clkr = {
+		.enable_reg = 0x2310,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_pclk0_clk = {
+	.halt_reg = 0x2314,
+	.clkr = {
+		.enable_reg = 0x2314,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_pclk0_clk",
+			.parent_names = (const char *[]){ "pclk0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_pclk1_clk = {
+	.halt_reg = 0x2318,
+	.clkr = {
+		.enable_reg = 0x2318,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_pclk1_clk",
+			.parent_names = (const char *[]){ "pclk1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_mdp_clk = {
+	.halt_reg = 0x231c,
+	.clkr = {
+		.enable_reg = 0x231c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_mdp_clk",
+			.parent_names = (const char *[]){ "mdp_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_extpclk_clk = {
+	.halt_reg = 0x2324,
+	.clkr = {
+		.enable_reg = 0x2324,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_extpclk_clk",
+			.parent_names = (const char *[]){ "extpclk_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_vsync_clk = {
+	.halt_reg = 0x2328,
+	.clkr = {
+		.enable_reg = 0x2328,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_vsync_clk",
+			.parent_names = (const char *[]){ "vsync_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_hdmi_clk = {
+	.halt_reg = 0x2338,
+	.clkr = {
+		.enable_reg = 0x2338,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_hdmi_clk",
+			.parent_names = (const char *[]){ "hdmi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_byte0_clk = {
+	.halt_reg = 0x233c,
+	.clkr = {
+		.enable_reg = 0x233c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_byte0_clk",
+			.parent_names = (const char *[]){ "byte0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_byte1_clk = {
+	.halt_reg = 0x2340,
+	.clkr = {
+		.enable_reg = 0x2340,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_byte1_clk",
+			.parent_names = (const char *[]){ "byte1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_esc0_clk = {
+	.halt_reg = 0x2344,
+	.clkr = {
+		.enable_reg = 0x2344,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_esc0_clk",
+			.parent_names = (const char *[]){ "esc0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_esc1_clk = {
+	.halt_reg = 0x2348,
+	.clkr = {
+		.enable_reg = 0x2348,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_esc1_clk",
+			.parent_names = (const char *[]){ "esc1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_top_ahb_clk = {
+	.halt_reg = 0x3484,
+	.clkr = {
+		.enable_reg = 0x3484,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_top_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_ahb_clk = {
+	.halt_reg = 0x348c,
+	.clkr = {
+		.enable_reg = 0x348c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_micro_ahb_clk = {
+	.halt_reg = 0x3494,
+	.clkr = {
+		.enable_reg = 0x3494,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_micro_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_gp0_clk = {
+	.halt_reg = 0x3444,
+	.clkr = {
+		.enable_reg = 0x3444,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_gp0_clk",
+			.parent_names = (const char *[]){ "camss_gp0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_gp1_clk = {
+	.halt_reg = 0x3474,
+	.clkr = {
+		.enable_reg = 0x3474,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_gp1_clk",
+			.parent_names = (const char *[]){ "camss_gp1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk0_clk = {
+	.halt_reg = 0x3384,
+	.clkr = {
+		.enable_reg = 0x3384,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk0_clk",
+			.parent_names = (const char *[]){ "mclk0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk1_clk = {
+	.halt_reg = 0x33b4,
+	.clkr = {
+		.enable_reg = 0x33b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk1_clk",
+			.parent_names = (const char *[]){ "mclk1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk2_clk = {
+	.halt_reg = 0x33e4,
+	.clkr = {
+		.enable_reg = 0x33e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk2_clk",
+			.parent_names = (const char *[]){ "mclk2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk3_clk = {
+	.halt_reg = 0x3414,
+	.clkr = {
+		.enable_reg = 0x3414,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk3_clk",
+			.parent_names = (const char *[]){ "mclk3_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cci_clk = {
+	.halt_reg = 0x3344,
+	.clkr = {
+		.enable_reg = 0x3344,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cci_clk",
+			.parent_names = (const char *[]){ "cci_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cci_ahb_clk = {
+	.halt_reg = 0x3348,
+	.clkr = {
+		.enable_reg = 0x3348,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cci_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0phytimer_clk = {
+	.halt_reg = 0x3024,
+	.clkr = {
+		.enable_reg = 0x3024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0phytimer_clk",
+			.parent_names = (const char *[]){ "csi0phytimer_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1phytimer_clk = {
+	.halt_reg = 0x3054,
+	.clkr = {
+		.enable_reg = 0x3054,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1phytimer_clk",
+			.parent_names = (const char *[]){ "csi1phytimer_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2phytimer_clk = {
+	.halt_reg = 0x3084,
+	.clkr = {
+		.enable_reg = 0x3084,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2phytimer_clk",
+			.parent_names = (const char *[]){ "csi2phytimer_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csiphy0_3p_clk = {
+	.halt_reg = 0x3234,
+	.clkr = {
+		.enable_reg = 0x3234,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csiphy0_3p_clk",
+			.parent_names = (const char *[]){ "csiphy0_3p_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csiphy1_3p_clk = {
+	.halt_reg = 0x3254,
+	.clkr = {
+		.enable_reg = 0x3254,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csiphy1_3p_clk",
+			.parent_names = (const char *[]){ "csiphy1_3p_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csiphy2_3p_clk = {
+	.halt_reg = 0x3274,
+	.clkr = {
+		.enable_reg = 0x3274,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csiphy2_3p_clk",
+			.parent_names = (const char *[]){ "csiphy2_3p_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg0_clk = {
+	.halt_reg = 0x35a8,
+	.clkr = {
+		.enable_reg = 0x35a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg0_clk",
+			.parent_names = (const char *[]){ "jpeg0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg2_clk = {
+	.halt_reg = 0x35b0,
+	.clkr = {
+		.enable_reg = 0x35b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg2_clk",
+			.parent_names = (const char *[]){ "jpeg2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_dma_clk = {
+	.halt_reg = 0x35c0,
+	.clkr = {
+		.enable_reg = 0x35c0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_dma_clk",
+			.parent_names = (const char *[]){ "jpeg_dma_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_ahb_clk = {
+	.halt_reg = 0x35b4,
+	.clkr = {
+		.enable_reg = 0x35b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_axi_clk = {
+	.halt_reg = 0x35b8,
+	.clkr = {
+		.enable_reg = 0x35b8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_ahb_clk = {
+	.halt_reg = 0x36b8,
+	.clkr = {
+		.enable_reg = 0x36b8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_axi_clk = {
+	.halt_reg = 0x36bc,
+	.clkr = {
+		.enable_reg = 0x36bc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe0_clk = {
+	.halt_reg = 0x36a8,
+	.clkr = {
+		.enable_reg = 0x36a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe0_clk",
+			.parent_names = (const char *[]){ "vfe0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe0_stream_clk = {
+	.halt_reg = 0x3720,
+	.clkr = {
+		.enable_reg = 0x3720,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe0_stream_clk",
+			.parent_names = (const char *[]){ "vfe0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe0_ahb_clk = {
+	.halt_reg = 0x3668,
+	.clkr = {
+		.enable_reg = 0x3668,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe0_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe1_clk = {
+	.halt_reg = 0x36ac,
+	.clkr = {
+		.enable_reg = 0x36ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe1_clk",
+			.parent_names = (const char *[]){ "vfe1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe1_stream_clk = {
+	.halt_reg = 0x3724,
+	.clkr = {
+		.enable_reg = 0x3724,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe1_stream_clk",
+			.parent_names = (const char *[]){ "vfe1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe1_ahb_clk = {
+	.halt_reg = 0x3678,
+	.clkr = {
+		.enable_reg = 0x3678,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe1_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi_vfe0_clk = {
+	.halt_reg = 0x3704,
+	.clkr = {
+		.enable_reg = 0x3704,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi_vfe0_clk",
+			.parent_names = (const char *[]){ "vfe0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi_vfe1_clk = {
+	.halt_reg = 0x3714,
+	.clkr = {
+		.enable_reg = 0x3714,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi_vfe1_clk",
+			.parent_names = (const char *[]){ "vfe1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cpp_vbif_ahb_clk = {
+	.halt_reg = 0x36c8,
+	.clkr = {
+		.enable_reg = 0x36c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cpp_vbif_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cpp_axi_clk = {
+	.halt_reg = 0x36c4,
+	.clkr = {
+		.enable_reg = 0x36c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cpp_axi_clk",
+			.parent_names = (const char *[]){ "axi_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cpp_clk = {
+	.halt_reg = 0x36b0,
+	.clkr = {
+		.enable_reg = 0x36b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cpp_clk",
+			.parent_names = (const char *[]){ "cpp_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cpp_ahb_clk = {
+	.halt_reg = 0x36b4,
+	.clkr = {
+		.enable_reg = 0x36b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cpp_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0_clk = {
+	.halt_reg = 0x30b4,
+	.clkr = {
+		.enable_reg = 0x30b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0_clk",
+			.parent_names = (const char *[]){ "csi0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0_ahb_clk = {
+	.halt_reg = 0x30bc,
+	.clkr = {
+		.enable_reg = 0x30bc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0phy_clk = {
+	.halt_reg = 0x30c4,
+	.clkr = {
+		.enable_reg = 0x30c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0phy_clk",
+			.parent_names = (const char *[]){ "csi0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0rdi_clk = {
+	.halt_reg = 0x30d4,
+	.clkr = {
+		.enable_reg = 0x30d4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0rdi_clk",
+			.parent_names = (const char *[]){ "csi0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0pix_clk = {
+	.halt_reg = 0x30e4,
+	.clkr = {
+		.enable_reg = 0x30e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0pix_clk",
+			.parent_names = (const char *[]){ "csi0_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1_clk = {
+	.halt_reg = 0x3124,
+	.clkr = {
+		.enable_reg = 0x3124,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1_clk",
+			.parent_names = (const char *[]){ "csi1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1_ahb_clk = {
+	.halt_reg = 0x3128,
+	.clkr = {
+		.enable_reg = 0x3128,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1phy_clk = {
+	.halt_reg = 0x3134,
+	.clkr = {
+		.enable_reg = 0x3134,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1phy_clk",
+			.parent_names = (const char *[]){ "csi1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1rdi_clk = {
+	.halt_reg = 0x3144,
+	.clkr = {
+		.enable_reg = 0x3144,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1rdi_clk",
+			.parent_names = (const char *[]){ "csi1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1pix_clk = {
+	.halt_reg = 0x3154,
+	.clkr = {
+		.enable_reg = 0x3154,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1pix_clk",
+			.parent_names = (const char *[]){ "csi1_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2_clk = {
+	.halt_reg = 0x3184,
+	.clkr = {
+		.enable_reg = 0x3184,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2_clk",
+			.parent_names = (const char *[]){ "csi2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2_ahb_clk = {
+	.halt_reg = 0x3188,
+	.clkr = {
+		.enable_reg = 0x3188,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2phy_clk = {
+	.halt_reg = 0x3194,
+	.clkr = {
+		.enable_reg = 0x3194,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2phy_clk",
+			.parent_names = (const char *[]){ "csi2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2rdi_clk = {
+	.halt_reg = 0x31a4,
+	.clkr = {
+		.enable_reg = 0x31a4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2rdi_clk",
+			.parent_names = (const char *[]){ "csi2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2pix_clk = {
+	.halt_reg = 0x31b4,
+	.clkr = {
+		.enable_reg = 0x31b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2pix_clk",
+			.parent_names = (const char *[]){ "csi2_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3_clk = {
+	.halt_reg = 0x31e4,
+	.clkr = {
+		.enable_reg = 0x31e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3_clk",
+			.parent_names = (const char *[]){ "csi3_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3_ahb_clk = {
+	.halt_reg = 0x31e8,
+	.clkr = {
+		.enable_reg = 0x31e8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3phy_clk = {
+	.halt_reg = 0x31f4,
+	.clkr = {
+		.enable_reg = 0x31f4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3phy_clk",
+			.parent_names = (const char *[]){ "csi3_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3rdi_clk = {
+	.halt_reg = 0x3204,
+	.clkr = {
+		.enable_reg = 0x3204,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3rdi_clk",
+			.parent_names = (const char *[]){ "csi3_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3pix_clk = {
+	.halt_reg = 0x3214,
+	.clkr = {
+		.enable_reg = 0x3214,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3pix_clk",
+			.parent_names = (const char *[]){ "csi3_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_ispif_ahb_clk = {
+	.halt_reg = 0x3224,
+	.clkr = {
+		.enable_reg = 0x3224,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_ispif_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch fd_core_clk = {
+	.halt_reg = 0x3b68,
+	.clkr = {
+		.enable_reg = 0x3b68,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "fd_core_clk",
+			.parent_names = (const char *[]){ "fd_core_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch fd_core_uar_clk = {
+	.halt_reg = 0x3b6c,
+	.clkr = {
+		.enable_reg = 0x3b6c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "fd_core_uar_clk",
+			.parent_names = (const char *[]){ "fd_core_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch fd_ahb_clk = {
+	.halt_reg = 0x3ba74,
+	.clkr = {
+		.enable_reg = 0x3ba74,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "fd_ahb_clk",
+			.parent_names = (const char *[]){ "ahb_clk_src" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_hw *mmcc_msm8996_hws[] = {
+	&gpll0_div.hw,
+};
+
+static struct clk_regmap *mmcc_msm8996_clocks[] = {
+	[MMPLL0_EARLY] = &mmpll0_early.clkr,
+	[MMPLL0_PLL] = &mmpll0.clkr,
+	[MMPLL1_EARLY] = &mmpll1_early.clkr,
+	[MMPLL1_PLL] = &mmpll1.clkr,
+	[MMPLL2_EARLY] = &mmpll2_early.clkr,
+	[MMPLL2_PLL] = &mmpll2.clkr,
+	[MMPLL3_EARLY] = &mmpll3_early.clkr,
+	[MMPLL3_PLL] = &mmpll3.clkr,
+	[MMPLL4_EARLY] = &mmpll4_early.clkr,
+	[MMPLL4_PLL] = &mmpll4.clkr,
+	[MMPLL5_EARLY] = &mmpll5_early.clkr,
+	[MMPLL5_PLL] = &mmpll5.clkr,
+	[MMPLL8_EARLY] = &mmpll8_early.clkr,
+	[MMPLL8_PLL] = &mmpll8.clkr,
+	[MMPLL9_EARLY] = &mmpll9_early.clkr,
+	[MMPLL9_PLL] = &mmpll9.clkr,
+	[AHB_CLK_SRC] = &ahb_clk_src.clkr,
+	[AXI_CLK_SRC] = &axi_clk_src.clkr,
+	[MAXI_CLK_SRC] = &maxi_clk_src.clkr,
+	[GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,
+	[RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
+	[ISENSE_CLK_SRC] = &isense_clk_src.clkr,
+	[RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
+	[VIDEO_CORE_CLK_SRC] = &video_core_clk_src.clkr,
+	[VIDEO_SUBCORE0_CLK_SRC] = &video_subcore0_clk_src.clkr,
+	[VIDEO_SUBCORE1_CLK_SRC] = &video_subcore1_clk_src.clkr,
+	[PCLK0_CLK_SRC] = &pclk0_clk_src.clkr,
+	[PCLK1_CLK_SRC] = &pclk1_clk_src.clkr,
+	[MDP_CLK_SRC] = &mdp_clk_src.clkr,
+	[EXTPCLK_CLK_SRC] = &extpclk_clk_src.clkr,
+	[VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+	[HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
+	[BYTE0_CLK_SRC] = &byte0_clk_src.clkr,
+	[BYTE1_CLK_SRC] = &byte1_clk_src.clkr,
+	[ESC0_CLK_SRC] = &esc0_clk_src.clkr,
+	[ESC1_CLK_SRC] = &esc1_clk_src.clkr,
+	[CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.clkr,
+	[CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.clkr,
+	[MCLK0_CLK_SRC] = &mclk0_clk_src.clkr,
+	[MCLK1_CLK_SRC] = &mclk1_clk_src.clkr,
+	[MCLK2_CLK_SRC] = &mclk2_clk_src.clkr,
+	[MCLK3_CLK_SRC] = &mclk3_clk_src.clkr,
+	[CCI_CLK_SRC] = &cci_clk_src.clkr,
+	[CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr,
+	[CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr,
+	[CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.clkr,
+	[CSIPHY0_3P_CLK_SRC] = &csiphy0_3p_clk_src.clkr,
+	[CSIPHY1_3P_CLK_SRC] = &csiphy1_3p_clk_src.clkr,
+	[CSIPHY2_3P_CLK_SRC] = &csiphy2_3p_clk_src.clkr,
+	[JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr,
+	[JPEG2_CLK_SRC] = &jpeg2_clk_src.clkr,
+	[JPEG_DMA_CLK_SRC] = &jpeg_dma_clk_src.clkr,
+	[VFE0_CLK_SRC] = &vfe0_clk_src.clkr,
+	[VFE1_CLK_SRC] = &vfe1_clk_src.clkr,
+	[CPP_CLK_SRC] = &cpp_clk_src.clkr,
+	[CSI0_CLK_SRC] = &csi0_clk_src.clkr,
+	[CSI1_CLK_SRC] = &csi1_clk_src.clkr,
+	[CSI2_CLK_SRC] = &csi2_clk_src.clkr,
+	[CSI3_CLK_SRC] = &csi3_clk_src.clkr,
+	[FD_CORE_CLK_SRC] = &fd_core_clk_src.clkr,
+	[MMSS_MMAGIC_AHB_CLK] = &mmss_mmagic_ahb_clk.clkr,
+	[MMSS_MMAGIC_CFG_AHB_CLK] = &mmss_mmagic_cfg_ahb_clk.clkr,
+	[MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr,
+	[MMSS_MISC_CXO_CLK] = &mmss_misc_cxo_clk.clkr,
+	[MMSS_MMAGIC_AXI_CLK] = &mmss_mmagic_axi_clk.clkr,
+	[MMSS_MMAGIC_MAXI_CLK] = &mmss_mmagic_maxi_clk.clkr,
+	[MMAGIC_CAMSS_AXI_CLK] = &mmagic_camss_axi_clk.clkr,
+	[MMAGIC_CAMSS_NOC_CFG_AHB_CLK] = &mmagic_camss_noc_cfg_ahb_clk.clkr,
+	[SMMU_VFE_AHB_CLK] = &smmu_vfe_ahb_clk.clkr,
+	[SMMU_VFE_AXI_CLK] = &smmu_vfe_axi_clk.clkr,
+	[SMMU_CPP_AHB_CLK] = &smmu_cpp_ahb_clk.clkr,
+	[SMMU_CPP_AXI_CLK] = &smmu_cpp_axi_clk.clkr,
+	[SMMU_JPEG_AHB_CLK] = &smmu_jpeg_ahb_clk.clkr,
+	[SMMU_JPEG_AXI_CLK] = &smmu_jpeg_axi_clk.clkr,
+	[MMAGIC_MDSS_AXI_CLK] = &mmagic_mdss_axi_clk.clkr,
+	[MMAGIC_MDSS_NOC_CFG_AHB_CLK] = &mmagic_mdss_noc_cfg_ahb_clk.clkr,
+	[SMMU_ROT_AHB_CLK] = &smmu_rot_ahb_clk.clkr,
+	[SMMU_ROT_AXI_CLK] = &smmu_rot_axi_clk.clkr,
+	[SMMU_MDP_AHB_CLK] = &smmu_mdp_ahb_clk.clkr,
+	[SMMU_MDP_AXI_CLK] = &smmu_mdp_axi_clk.clkr,
+	[MMAGIC_VIDEO_AXI_CLK] = &mmagic_video_axi_clk.clkr,
+	[MMAGIC_VIDEO_NOC_CFG_AHB_CLK] = &mmagic_video_noc_cfg_ahb_clk.clkr,
+	[SMMU_VIDEO_AHB_CLK] = &smmu_video_ahb_clk.clkr,
+	[SMMU_VIDEO_AXI_CLK] = &smmu_video_axi_clk.clkr,
+	[MMAGIC_BIMC_AXI_CLK] = &mmagic_bimc_axi_clk.clkr,
+	[MMAGIC_BIMC_NOC_CFG_AHB_CLK] = &mmagic_bimc_noc_cfg_ahb_clk.clkr,
+	[GPU_GX_GFX3D_CLK] = &gpu_gx_gfx3d_clk.clkr,
+	[GPU_GX_RBBMTIMER_CLK] = &gpu_gx_rbbmtimer_clk.clkr,
+	[GPU_AHB_CLK] = &gpu_ahb_clk.clkr,
+	[GPU_AON_ISENSE_CLK] = &gpu_aon_isense_clk.clkr,
+	[VMEM_MAXI_CLK] = &vmem_maxi_clk.clkr,
+	[VMEM_AHB_CLK] = &vmem_ahb_clk.clkr,
+	[MMSS_RBCPR_CLK] = &mmss_rbcpr_clk.clkr,
+	[MMSS_RBCPR_AHB_CLK] = &mmss_rbcpr_ahb_clk.clkr,
+	[VIDEO_CORE_CLK] = &video_core_clk.clkr,
+	[VIDEO_AXI_CLK] = &video_axi_clk.clkr,
+	[VIDEO_MAXI_CLK] = &video_maxi_clk.clkr,
+	[VIDEO_AHB_CLK] = &video_ahb_clk.clkr,
+	[VIDEO_SUBCORE0_CLK] = &video_subcore0_clk.clkr,
+	[VIDEO_SUBCORE1_CLK] = &video_subcore1_clk.clkr,
+	[MDSS_AHB_CLK] = &mdss_ahb_clk.clkr,
+	[MDSS_HDMI_AHB_CLK] = &mdss_hdmi_ahb_clk.clkr,
+	[MDSS_AXI_CLK] = &mdss_axi_clk.clkr,
+	[MDSS_PCLK0_CLK] = &mdss_pclk0_clk.clkr,
+	[MDSS_PCLK1_CLK] = &mdss_pclk1_clk.clkr,
+	[MDSS_MDP_CLK] = &mdss_mdp_clk.clkr,
+	[MDSS_EXTPCLK_CLK] = &mdss_extpclk_clk.clkr,
+	[MDSS_VSYNC_CLK] = &mdss_vsync_clk.clkr,
+	[MDSS_HDMI_CLK] = &mdss_hdmi_clk.clkr,
+	[MDSS_BYTE0_CLK] = &mdss_byte0_clk.clkr,
+	[MDSS_BYTE1_CLK] = &mdss_byte1_clk.clkr,
+	[MDSS_ESC0_CLK] = &mdss_esc0_clk.clkr,
+	[MDSS_ESC1_CLK] = &mdss_esc1_clk.clkr,
+	[CAMSS_TOP_AHB_CLK] = &camss_top_ahb_clk.clkr,
+	[CAMSS_AHB_CLK] = &camss_ahb_clk.clkr,
+	[CAMSS_MICRO_AHB_CLK] = &camss_micro_ahb_clk.clkr,
+	[CAMSS_GP0_CLK] = &camss_gp0_clk.clkr,
+	[CAMSS_GP1_CLK] = &camss_gp1_clk.clkr,
+	[CAMSS_MCLK0_CLK] = &camss_mclk0_clk.clkr,
+	[CAMSS_MCLK1_CLK] = &camss_mclk1_clk.clkr,
+	[CAMSS_MCLK2_CLK] = &camss_mclk2_clk.clkr,
+	[CAMSS_MCLK3_CLK] = &camss_mclk3_clk.clkr,
+	[CAMSS_CCI_CLK] = &camss_cci_clk.clkr,
+	[CAMSS_CCI_AHB_CLK] = &camss_cci_ahb_clk.clkr,
+	[CAMSS_CSI0PHYTIMER_CLK] = &camss_csi0phytimer_clk.clkr,
+	[CAMSS_CSI1PHYTIMER_CLK] = &camss_csi1phytimer_clk.clkr,
+	[CAMSS_CSI2PHYTIMER_CLK] = &camss_csi2phytimer_clk.clkr,
+	[CAMSS_CSIPHY0_3P_CLK] = &camss_csiphy0_3p_clk.clkr,
+	[CAMSS_CSIPHY1_3P_CLK] = &camss_csiphy1_3p_clk.clkr,
+	[CAMSS_CSIPHY2_3P_CLK] = &camss_csiphy2_3p_clk.clkr,
+	[CAMSS_JPEG0_CLK] = &camss_jpeg0_clk.clkr,
+	[CAMSS_JPEG2_CLK] = &camss_jpeg2_clk.clkr,
+	[CAMSS_JPEG_DMA_CLK] = &camss_jpeg_dma_clk.clkr,
+	[CAMSS_JPEG_AHB_CLK] = &camss_jpeg_ahb_clk.clkr,
+	[CAMSS_JPEG_AXI_CLK] = &camss_jpeg_axi_clk.clkr,
+	[CAMSS_VFE_AHB_CLK] = &camss_vfe_ahb_clk.clkr,
+	[CAMSS_VFE_AXI_CLK] = &camss_vfe_axi_clk.clkr,
+	[CAMSS_VFE0_CLK] = &camss_vfe0_clk.clkr,
+	[CAMSS_VFE0_STREAM_CLK] = &camss_vfe0_stream_clk.clkr,
+	[CAMSS_VFE0_AHB_CLK] = &camss_vfe0_ahb_clk.clkr,
+	[CAMSS_VFE1_CLK] = &camss_vfe1_clk.clkr,
+	[CAMSS_VFE1_STREAM_CLK] = &camss_vfe1_stream_clk.clkr,
+	[CAMSS_VFE1_AHB_CLK] = &camss_vfe1_ahb_clk.clkr,
+	[CAMSS_CSI_VFE0_CLK] = &camss_csi_vfe0_clk.clkr,
+	[CAMSS_CSI_VFE1_CLK] = &camss_csi_vfe1_clk.clkr,
+	[CAMSS_CPP_VBIF_AHB_CLK] = &camss_cpp_vbif_ahb_clk.clkr,
+	[CAMSS_CPP_AXI_CLK] = &camss_cpp_axi_clk.clkr,
+	[CAMSS_CPP_CLK] = &camss_cpp_clk.clkr,
+	[CAMSS_CPP_AHB_CLK] = &camss_cpp_ahb_clk.clkr,
+	[CAMSS_CSI0_CLK] = &camss_csi0_clk.clkr,
+	[CAMSS_CSI0_AHB_CLK] = &camss_csi0_ahb_clk.clkr,
+	[CAMSS_CSI0PHY_CLK] = &camss_csi0phy_clk.clkr,
+	[CAMSS_CSI0RDI_CLK] = &camss_csi0rdi_clk.clkr,
+	[CAMSS_CSI0PIX_CLK] = &camss_csi0pix_clk.clkr,
+	[CAMSS_CSI1_CLK] = &camss_csi1_clk.clkr,
+	[CAMSS_CSI1_AHB_CLK] = &camss_csi1_ahb_clk.clkr,
+	[CAMSS_CSI1PHY_CLK] = &camss_csi1phy_clk.clkr,
+	[CAMSS_CSI1RDI_CLK] = &camss_csi1rdi_clk.clkr,
+	[CAMSS_CSI1PIX_CLK] = &camss_csi1pix_clk.clkr,
+	[CAMSS_CSI2_CLK] = &camss_csi2_clk.clkr,
+	[CAMSS_CSI2_AHB_CLK] = &camss_csi2_ahb_clk.clkr,
+	[CAMSS_CSI2PHY_CLK] = &camss_csi2phy_clk.clkr,
+	[CAMSS_CSI2RDI_CLK] = &camss_csi2rdi_clk.clkr,
+	[CAMSS_CSI2PIX_CLK] = &camss_csi2pix_clk.clkr,
+	[CAMSS_CSI3_CLK] = &camss_csi3_clk.clkr,
+	[CAMSS_CSI3_AHB_CLK] = &camss_csi3_ahb_clk.clkr,
+	[CAMSS_CSI3PHY_CLK] = &camss_csi3phy_clk.clkr,
+	[CAMSS_CSI3RDI_CLK] = &camss_csi3rdi_clk.clkr,
+	[CAMSS_CSI3PIX_CLK] = &camss_csi3pix_clk.clkr,
+	[CAMSS_ISPIF_AHB_CLK] = &camss_ispif_ahb_clk.clkr,
+	[FD_CORE_CLK] = &fd_core_clk.clkr,
+	[FD_CORE_UAR_CLK] = &fd_core_uar_clk.clkr,
+	[FD_AHB_CLK] = &fd_ahb_clk.clkr,
+};
+
+static const struct qcom_reset_map mmcc_msm8996_resets[] = {
+	[MMAGICAHB_BCR] = { 0x5020 },
+	[MMAGIC_CFG_BCR] = { 0x5050 },
+	[MISC_BCR] = { 0x5010 },
+	[BTO_BCR] = { 0x5030 },
+	[MMAGICAXI_BCR] = { 0x5060 },
+	[MMAGICMAXI_BCR] = { 0x5070 },
+	[DSA_BCR] = { 0x50a0 },
+	[MMAGIC_CAMSS_BCR] = { 0x3c40 },
+	[THROTTLE_CAMSS_BCR] = { 0x3c30 },
+	[SMMU_VFE_BCR] = { 0x3c00 },
+	[SMMU_CPP_BCR] = { 0x3c10 },
+	[SMMU_JPEG_BCR] = { 0x3c20 },
+	[MMAGIC_MDSS_BCR] = { 0x2470 },
+	[THROTTLE_MDSS_BCR] = { 0x2460 },
+	[SMMU_ROT_BCR] = { 0x2440 },
+	[SMMU_MDP_BCR] = { 0x2450 },
+	[MMAGIC_VIDEO_BCR] = { 0x1190 },
+	[THROTTLE_VIDEO_BCR] = { 0x1180 },
+	[SMMU_VIDEO_BCR] = { 0x1170 },
+	[MMAGIC_BIMC_BCR] = { 0x5290 },
+	[GPU_GX_BCR] = { 0x4020 },
+	[GPU_BCR] = { 0x4030 },
+	[GPU_AON_BCR] = { 0x4040 },
+	[VMEM_BCR] = { 0x1200 },
+	[MMSS_RBCPR_BCR] = { 0x4080 },
+	[VIDEO_BCR] = { 0x1020 },
+	[MDSS_BCR] = { 0x2300 },
+	[CAMSS_TOP_BCR] = { 0x3480 },
+	[CAMSS_AHB_BCR] = { 0x3488 },
+	[CAMSS_MICRO_BCR] = { 0x3490 },
+	[CAMSS_CCI_BCR] = { 0x3340 },
+	[CAMSS_PHY0_BCR] = { 0x3020 },
+	[CAMSS_PHY1_BCR] = { 0x3050 },
+	[CAMSS_PHY2_BCR] = { 0x3080 },
+	[CAMSS_CSIPHY0_3P_BCR] = { 0x3230 },
+	[CAMSS_CSIPHY1_3P_BCR] = { 0x3250 },
+	[CAMSS_CSIPHY2_3P_BCR] = { 0x3270 },
+	[CAMSS_JPEG_BCR] = { 0x35a0 },
+	[CAMSS_VFE_BCR] = { 0x36a0 },
+	[CAMSS_VFE0_BCR] = { 0x3660 },
+	[CAMSS_VFE1_BCR] = { 0x3670 },
+	[CAMSS_CSI_VFE0_BCR] = { 0x3700 },
+	[CAMSS_CSI_VFE1_BCR] = { 0x3710 },
+	[CAMSS_CPP_TOP_BCR] = { 0x36c0 },
+	[CAMSS_CPP_BCR] = { 0x36d0 },
+	[CAMSS_CSI0_BCR] = { 0x30b0 },
+	[CAMSS_CSI0RDI_BCR] = { 0x30d0 },
+	[CAMSS_CSI0PIX_BCR] = { 0x30e0 },
+	[CAMSS_CSI1_BCR] = { 0x3120 },
+	[CAMSS_CSI1RDI_BCR] = { 0x3140 },
+	[CAMSS_CSI1PIX_BCR] = { 0x3150 },
+	[CAMSS_CSI2_BCR] = { 0x3180 },
+	[CAMSS_CSI2RDI_BCR] = { 0x31a0 },
+	[CAMSS_CSI2PIX_BCR] = { 0x31b0 },
+	[CAMSS_CSI3_BCR] = { 0x31e0 },
+	[CAMSS_CSI3RDI_BCR] = { 0x3200 },
+	[CAMSS_CSI3PIX_BCR] = { 0x3210 },
+	[CAMSS_ISPIF_BCR] = { 0x3220 },
+	[FD_BCR] = { 0x3b60 },
+	[MMSS_SPDM_RM_BCR] = { 0x300 },
+};
+
+static const struct regmap_config mmcc_msm8996_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0xb008,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc mmcc_msm8996_desc = {
+	.config = &mmcc_msm8996_regmap_config,
+	.clks = mmcc_msm8996_clocks,
+	.num_clks = ARRAY_SIZE(mmcc_msm8996_clocks),
+	.resets = mmcc_msm8996_resets,
+	.num_resets = ARRAY_SIZE(mmcc_msm8996_resets),
+};
+
+static const struct of_device_id mmcc_msm8996_match_table[] = {
+	{ .compatible = "qcom,mmcc-msm8996" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mmcc_msm8996_match_table);
+
+static int mmcc_msm8996_probe(struct platform_device *pdev)
+{
+	struct clk *clk;
+	struct device *dev = &pdev->dev;
+	int i;
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, &mmcc_msm8996_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	/* Disable the AHB DCD */
+	regmap_update_bits(regmap, 0x50d8, BIT(31), 0);
+	/* Disable the NoC FSM for mmss_mmagic_cfg_ahb_clk */
+	regmap_update_bits(regmap, 0x5054, BIT(15), 0);
+
+	for (i = 0; i < ARRAY_SIZE(mmcc_msm8996_hws); i++) {
+		clk = devm_clk_register(dev, mmcc_msm8996_hws[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+	}
+
+	return qcom_cc_really_probe(pdev, &mmcc_msm8996_desc, regmap);
+}
+
+static struct platform_driver mmcc_msm8996_driver = {
+	.probe		= mmcc_msm8996_probe,
+	.driver		= {
+		.name	= "mmcc-msm8996",
+		.of_match_table = mmcc_msm8996_match_table,
+	},
+};
+module_platform_driver(mmcc_msm8996_driver);
+
+MODULE_DESCRIPTION("QCOM MMCC MSM8996 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mmcc-msm8996");
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index b27edd6c8183..80b9a379beb4 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -10,6 +10,8 @@ obj-y	+= clk-inverter.o
 obj-y	+= clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
+obj-y	+= clk-rk3036.o
 obj-y	+= clk-rk3188.o
+obj-y	+= clk-rk3228.o
 obj-y	+= clk-rk3288.o
 obj-y	+= clk-rk3368.o
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 330870a6d8bf..d07374f48caf 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -242,8 +242,8 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
 	struct clk *clk, *cclk;
 	int ret;
 
-	if (num_parents != 2) {
-		pr_err("%s: needs two parent clocks\n", __func__);
+	if (num_parents < 2) {
+		pr_err("%s: needs at least two parent clocks\n", __func__);
 		return ERR_PTR(-EINVAL);
 	}
 
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 4881eb8a1576..b7e66c9dd9f2 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -2,6 +2,9 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -19,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
+#include <linux/clk.h>
 #include "clk.h"
 
 #define PLL_MODE_MASK		0x3
@@ -108,6 +112,252 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
 }
 
 /**
+ * PLL used in RK3036
+ */
+
+#define RK3036_PLLCON(i)			(i * 0x4)
+#define RK3036_PLLCON0_FBDIV_MASK		0xfff
+#define RK3036_PLLCON0_FBDIV_SHIFT		0
+#define RK3036_PLLCON0_POSTDIV1_MASK		0x7
+#define RK3036_PLLCON0_POSTDIV1_SHIFT		12
+#define RK3036_PLLCON1_REFDIV_MASK		0x3f
+#define RK3036_PLLCON1_REFDIV_SHIFT		0
+#define RK3036_PLLCON1_POSTDIV2_MASK		0x7
+#define RK3036_PLLCON1_POSTDIV2_SHIFT		6
+#define RK3036_PLLCON1_DSMPD_MASK		0x1
+#define RK3036_PLLCON1_DSMPD_SHIFT		12
+#define RK3036_PLLCON2_FRAC_MASK		0xffffff
+#define RK3036_PLLCON2_FRAC_SHIFT		0
+
+#define RK3036_PLLCON1_PWRDOWN			(1 << 13)
+
+static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,
+					struct rockchip_pll_rate_table *rate)
+{
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
+	rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT)
+				& RK3036_PLLCON0_FBDIV_MASK);
+	rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT)
+				& RK3036_PLLCON0_POSTDIV1_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
+	rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT)
+				& RK3036_PLLCON1_REFDIV_MASK);
+	rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT)
+				& RK3036_PLLCON1_POSTDIV2_MASK);
+	rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT)
+				& RK3036_PLLCON1_DSMPD_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+	rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT)
+				& RK3036_PLLCON2_FRAC_MASK);
+}
+
+static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	struct rockchip_pll_rate_table cur;
+	u64 rate64 = prate;
+
+	rockchip_rk3036_pll_get_params(pll, &cur);
+
+	rate64 *= cur.fbdiv;
+	do_div(rate64, cur.refdiv);
+
+	if (cur.dsmpd == 0) {
+		/* fractional mode */
+		u64 frac_rate64 = prate * cur.frac;
+
+		do_div(frac_rate64, cur.refdiv);
+		rate64 += frac_rate64 >> 24;
+	}
+
+	do_div(rate64, cur.postdiv1);
+	do_div(rate64, cur.postdiv2);
+
+	return (unsigned long)rate64;
+}
+
+static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
+				const struct rockchip_pll_rate_table *rate)
+{
+	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+	struct clk_mux *pll_mux = &pll->pll_mux;
+	struct rockchip_pll_rate_table cur;
+	u32 pllcon;
+	int rate_change_remuxed = 0;
+	int cur_parent;
+	int ret;
+
+	pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		__func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
+		rate->postdiv2, rate->dsmpd, rate->frac);
+
+	rockchip_rk3036_pll_get_params(pll, &cur);
+	cur.rate = 0;
+
+	cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+	if (cur_parent == PLL_MODE_NORM) {
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+		rate_change_remuxed = 1;
+	}
+
+	/* update pll values */
+	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
+					  RK3036_PLLCON0_FBDIV_SHIFT) |
+		       HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK,
+					     RK3036_PLLCON0_POSTDIV1_SHIFT),
+		       pll->reg_base + RK3036_PLLCON(0));
+
+	writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK,
+						   RK3036_PLLCON1_REFDIV_SHIFT) |
+		       HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK,
+						     RK3036_PLLCON1_POSTDIV2_SHIFT) |
+		       HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK,
+						  RK3036_PLLCON1_DSMPD_SHIFT),
+		       pll->reg_base + RK3036_PLLCON(1));
+
+	/* GPLL CON2 is not HIWORD_MASK */
+	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+	pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);
+	pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
+	writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
+
+	/* wait for the pll to lock */
+	ret = rockchip_pll_wait_lock(pll);
+	if (ret) {
+		pr_warn("%s: pll update unsucessful, trying to restore old params\n",
+			__func__);
+		rockchip_rk3036_pll_set_params(pll, &cur);
+	}
+
+	if (rate_change_remuxed)
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+	return ret;
+}
+
+static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate);
+	struct regmap *grf = rockchip_clk_get_grf();
+
+	if (IS_ERR(grf)) {
+		pr_debug("%s: grf regmap not available, aborting rate change\n",
+			 __func__);
+		return PTR_ERR(grf);
+	}
+
+	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
+		 __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+
+	/* Get required rate settings from table */
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	return rockchip_rk3036_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3036_PLLCON(1));
+
+	return 0;
+}
+
+static void rockchip_rk3036_pll_disable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
+			     RK3036_PLLCON1_PWRDOWN, 0),
+	       pll->reg_base + RK3036_PLLCON(1));
+}
+
+static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));
+
+	return !(pllcon & RK3036_PLLCON1_PWRDOWN);
+}
+
+static void rockchip_rk3036_pll_init(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	struct rockchip_pll_rate_table cur;
+	unsigned long drate;
+
+	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+		return;
+
+	drate = clk_hw_get_rate(hw);
+	rate = rockchip_get_pll_settings(pll, drate);
+
+	/* when no rate setting for the current rate, rely on clk_set_rate */
+	if (!rate)
+		return;
+
+	rockchip_rk3036_pll_get_params(pll, &cur);
+
+	pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),
+		 drate);
+	pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		 cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
+		 cur.dsmpd, cur.frac);
+	pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		 rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
+		 rate->dsmpd, rate->frac);
+
+	if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
+		rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
+		rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+		struct clk *parent = clk_get_parent(hw->clk);
+
+		if (!parent) {
+			pr_warn("%s: parent of %s not available\n",
+				__func__, __clk_get_name(hw->clk));
+			return;
+		}
+
+		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
+			 __func__, __clk_get_name(hw->clk));
+		rockchip_rk3036_pll_set_params(pll, rate);
+	}
+}
+
+static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
+	.recalc_rate = rockchip_rk3036_pll_recalc_rate,
+	.enable = rockchip_rk3036_pll_enable,
+	.disable = rockchip_rk3036_pll_disable,
+	.is_enabled = rockchip_rk3036_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
+	.recalc_rate = rockchip_rk3036_pll_recalc_rate,
+	.round_rate = rockchip_pll_round_rate,
+	.set_rate = rockchip_rk3036_pll_set_rate,
+	.enable = rockchip_rk3036_pll_enable,
+	.disable = rockchip_rk3036_pll_disable,
+	.is_enabled = rockchip_rk3036_pll_is_enabled,
+	.init = rockchip_rk3036_pll_init,
+};
+
+/**
  * PLL used in RK3066, RK3188 and RK3288
  */
 
@@ -376,7 +626,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
 	pll_mux->lock = lock;
 	pll_mux->hw.init = &init;
 
-	if (pll_type == pll_rk3066)
+	if (pll_type == pll_rk3036 || pll_type == pll_rk3066)
 		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
 
 	/* the actual muxing is xin24m, pll-output, xin32k */
@@ -421,6 +671,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
 	}
 
 	switch (pll_type) {
+	case pll_rk3036:
+		if (!pll->rate_table)
+			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
+		else
+			init.ops = &rockchip_rk3036_pll_clk_ops;
+		break;
 	case pll_rk3066:
 		if (!pll->rate_table)
 			init.ops = &rockchip_rk3066_pll_clk_norate_ops;
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
new file mode 100644
index 000000000000..ebce98033fbb
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3036.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk3036-cru.h>
+#include "clk.h"
+
+#define RK3036_GRF_SOC_STATUS0	0x14c
+
+enum rk3036_plls {
+	apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk3036_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+	{ /* sentinel */ },
+};
+
+#define RK3036_DIV_CPU_MASK		0x1f
+#define RK3036_DIV_CPU_SHIFT		8
+
+#define RK3036_DIV_PERI_MASK		0xf
+#define RK3036_DIV_PERI_SHIFT		0
+#define RK3036_DIV_ACLK_MASK		0x7
+#define RK3036_DIV_ACLK_SHIFT		4
+#define RK3036_DIV_HCLK_MASK		0x3
+#define RK3036_DIV_HCLK_SHIFT		8
+#define RK3036_DIV_PCLK_MASK		0x7
+#define RK3036_DIV_PCLK_SHIFT		12
+
+#define RK3036_CLKSEL1(_core_periph_div)					\
+	{									\
+		.reg = RK2928_CLKSEL_CON(1),					\
+		.val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK,	\
+				RK3036_DIV_PERI_SHIFT)				\
+	}
+
+#define RK3036_CPUCLK_RATE(_prate, _core_periph_div)			\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3036_CLKSEL1(_core_periph_div),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata = {
+	RK3036_CPUCLK_RATE(816000000, 4),
+	RK3036_CPUCLK_RATE(600000000, 4),
+	RK3036_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
+	.core_reg = RK2928_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 7,
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin24m" };
+
+PNAME(mux_armclk_p)		= { "apll", "gpll_armclk" };
+PNAME(mux_busclk_p)		= { "apll", "dpll_cpu", "gpll_cpu" };
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_pll_src_3plls_p)	= { "apll", "dpll", "gpll" };
+PNAME(mux_timer_p)		= { "xin24m", "pclk_peri_src" };
+
+PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p)	= { "apll", "dpll", "gpll" "usb480m" };
+
+PNAME(mux_mmc_src_p)	= { "apll", "dpll", "gpll", "xin24m" };
+PNAME(mux_i2s_pre_p)	= { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_clkout_p)	= { "i2s_pre", "xin12m" };
+PNAME(mux_spdif_p)	= { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_uart0_p)	= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)	= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)	= { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_mac_p)	= { "mac_pll_src", "ext_gmac" };
+PNAME(mux_dclk_p)	= { "dclk_lcdc", "dclk_cru" };
+
+static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
+		     RK2928_MODE_CON, 0, 5, 0, rk3036_pll_rates),
+	[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
+		     RK2928_MODE_CON, 4, 4, 0, NULL),
+	[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
+		     RK2928_MODE_CON, 12, 6, ROCKCHIP_PLL_SYNC_RATE, rk3036_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3036_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3036_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3036_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3036_i2s_fracmux __initdata =
+	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3036_spdif_fracmux __initdata =
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
+			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 1
+	 */
+
+	GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+
+	COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_core_pre", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+
+	GATE(0, "dpll_cpu", "dpll", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(0, "gpll_cpu", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_busclk_p, 0,
+			RK2928_CLKSEL_CON(0), 14, 2, MFLAGS, 8, 5, DFLAGS),
+	GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 4, GFLAGS),
+
+	COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 1, GFLAGS),
+	DIV(0, "pclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	GATE(PCLK_PERI, "pclk_peri", "pclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 3, GFLAGS),
+	DIV(0, "hclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	GATE(HCLK_PERI, "hclk_peri", "hclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 2, GFLAGS),
+
+	COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 4, 1, DFLAGS,
+			RK2928_CLKGATE_CON(1), 0, GFLAGS),
+	COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 5, 1, DFLAGS,
+			RK2928_CLKGATE_CON(1), 1, GFLAGS),
+	COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 6, 1, DFLAGS,
+			RK2928_CLKGATE_CON(2), 4, GFLAGS),
+	COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(2), 7, 1, DFLAGS,
+			RK2928_CLKGATE_CON(2), 5, GFLAGS),
+
+	MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(13), 10, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(17), 0,
+			RK2928_CLKGATE_CON(1), 9, GFLAGS,
+			&rk3036_uart0_fracmux),
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(18), 0,
+			RK2928_CLKGATE_CON(1), 11, GFLAGS,
+			&rk3036_uart1_fracmux),
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(19), 0,
+			RK2928_CLKGATE_CON(1), 13, GFLAGS,
+			&rk3036_uart2_fracmux),
+
+	COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 11, GFLAGS),
+
+	COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 6, GFLAGS),
+
+	COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 4, GFLAGS),
+	COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(0), 11, GFLAGS),
+	COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 8, 2, DFLAGS,
+			RK2928_CLKGATE_CON(2), 11, GFLAGS),
+	DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0,
+			RK2928_CLKSEL_CON(11), 0, 7, DFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 10, 2, DFLAGS,
+			RK2928_CLKGATE_CON(2), 13, GFLAGS),
+	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+			RK2928_CLKSEL_CON(11), 8, 7, DFLAGS),
+
+	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 14, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3036_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3036_SDMMC_CON1, 0),
+
+	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK3036_SDIO_CON0, 1),
+	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK3036_SDIO_CON1, 0),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3036_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3036_EMMC_CON1,  0),
+
+	COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(7), 0,
+			RK2928_CLKGATE_CON(0), 10, GFLAGS,
+			&rk3036_i2s_fracmux),
+	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_clkout", mux_i2s_clkout_p, 0,
+			RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
+			RK2928_CLKGATE_CON(0), 13, GFLAGS),
+	GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT,
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+
+	COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
+			RK2928_CLKSEL_CON(9), 0,
+			RK2928_CLKGATE_CON(2), 12, GFLAGS,
+			&rk3036_spdif_fracmux),
+
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(1), 5, GFLAGS),
+
+	COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+
+	COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 9, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 4, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 5, GFLAGS),
+
+	COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS),
+	MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(21), 3, 1, MFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0,
+			RK2928_CLKSEL_CON(21), 9, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 6, GFLAGS),
+
+	MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0,
+			RK2928_CLKSEL_CON(31), 0, 1, MFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	/* aclk_cpu gates */
+	GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS),
+	GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS),
+
+	/* hclk_cpu gates */
+	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS),
+
+	/* pclk_cpu gates */
+	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
+	GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
+	GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
+
+	/* aclk_vio gates */
+	GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS),
+	GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
+
+	GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
+
+	/* hclk_video gates */
+	GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS),
+
+	/* xin24m gates */
+	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS),
+
+	/* aclk_peri gates */
+	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS),
+	GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS),
+	GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS),
+
+	/* hclk_peri gates */
+	GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
+	GATE(0, "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
+	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
+	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS),
+	GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+	GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+	GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS),
+	GATE(0, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS),
+
+	/* pclk_peri gates */
+	GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS),
+	GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
+	GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
+	GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+};
+
+static const char *const rk3036_critical_clocks[] __initconst = {
+	"aclk_cpu",
+	"aclk_peri",
+	"hclk_peri",
+	"pclk_peri",
+};
+
+static void __init rk3036_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock usb480m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock ddrphy: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
+					"aclk_vcodec", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
+					"hclk_peri_src", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	rockchip_clk_register_plls(rk3036_pll_clks,
+				   ARRAY_SIZE(rk3036_pll_clks),
+				   RK3036_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(rk3036_clk_branches,
+				  ARRAY_SIZE(rk3036_clk_branches));
+	rockchip_clk_protect_critical(rk3036_critical_clocks,
+				      ARRAY_SIZE(rk3036_critical_clocks));
+
+	rockchip_clk_register_armclk(ARMCLK, "armclk",
+			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
+			ARRAY_SIZE(rk3036_cpuclk_rates));
+
+	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
+}
+CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index abb47608713b..7f7444cbf6fc 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -247,6 +247,30 @@ static struct clk_div_table div_core_peri_t[] = {
 	{ /* sentinel */ },
 };
 
+static struct rockchip_clk_branch common_hsadc_out_fracmux __initdata =
+	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
+			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_spdif_fracmux __initdata =
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart3_fracmux __initdata =
+	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
+			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS);
+
 static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	/*
 	 * Clock-Architecture Diagram 2
@@ -335,11 +359,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
 			RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
 			RK2928_CLKGATE_CON(2), 6, GFLAGS),
-	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
+	COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
 			RK2928_CLKSEL_CON(23), 0,
-			RK2928_CLKGATE_CON(2), 7, GFLAGS),
-	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
-			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+			RK2928_CLKGATE_CON(2), 7, GFLAGS,
+			&common_hsadc_out_fracmux),
 	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
 			RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
@@ -350,11 +373,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 13, GFLAGS),
-	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pll", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(9), 0,
-			RK2928_CLKGATE_CON(0), 14, GFLAGS),
-	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 14, GFLAGS,
+			&common_spdif_fracmux),
 
 	/*
 	 * Clock-Architecture Diagram 4
@@ -385,35 +407,31 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
 			RK2928_CLKSEL_CON(17), 0,
-			RK2928_CLKGATE_CON(1), 9, GFLAGS),
-	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
-			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 9, GFLAGS,
+			&common_uart0_fracmux),
 	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
 			RK2928_CLKSEL_CON(18), 0,
-			RK2928_CLKGATE_CON(1), 11, GFLAGS),
-	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
-			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 11, GFLAGS,
+			&common_uart1_fracmux),
 	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
 			RK2928_CLKSEL_CON(19), 0,
-			RK2928_CLKGATE_CON(1), 13, GFLAGS),
-	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
-			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 13, GFLAGS,
+			&common_uart2_fracmux),
 	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 14, GFLAGS),
-	COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
 			RK2928_CLKSEL_CON(20), 0,
-			RK2928_CLKGATE_CON(1), 15, GFLAGS),
-	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
-			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 15, GFLAGS,
+			&common_uart3_fracmux),
 
 	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
 
@@ -523,6 +541,18 @@ static struct clk_div_table div_aclk_cpu_t[] = {
 	{ /* sentinel */ },
 };
 
+static struct rockchip_clk_branch rk3066a_i2s0_fracmux __initdata =
+	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3066a_i2s1_fracmux __initdata =
+	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3066a_i2s2_fracmux __initdata =
+	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
+			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS);
+
 static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 	DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
 			RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t),
@@ -584,27 +614,24 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 7, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(6), 0,
-			RK2928_CLKGATE_CON(0), 8, GFLAGS),
-	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
-			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 8, GFLAGS,
+			&rk3066a_i2s0_fracmux),
 	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS),
-	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 10, GFLAGS,
+			&rk3066a_i2s1_fracmux),
 	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 11, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
 			RK2928_CLKSEL_CON(8), 0,
-			RK2928_CLKGATE_CON(0), 12, GFLAGS),
-	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
-			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 12, GFLAGS,
+			&rk3066a_i2s2_fracmux),
 
 	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
 	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
@@ -638,6 +665,10 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
 PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
 				    "gpll", "cpll" };
 
+static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata =
+	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
 static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
 			RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
@@ -691,11 +722,10 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS),
-	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 10, GFLAGS,
+			&rk3188_i2s0_fracmux),
 
 	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
 	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
@@ -750,7 +780,7 @@ static void __init rk3188_common_clk_init(struct device_node *np)
 	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
+	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
 }
 
 static void __init rk3066a_clk_init(struct device_node *np)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
new file mode 100644
index 000000000000..981a50205339
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *         Jeffy Chen <jeffy.chen@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk3228-cru.h>
+#include "clk.h"
+
+#define RK3228_GRF_SOC_STATUS0	0x480
+
+enum rk3228_plls {
+	apll, dpll, cpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk3228_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+	{ /* sentinel */ },
+};
+
+#define RK3228_DIV_CPU_MASK		0x1f
+#define RK3228_DIV_CPU_SHIFT		8
+
+#define RK3228_DIV_PERI_MASK		0xf
+#define RK3228_DIV_PERI_SHIFT		0
+#define RK3228_DIV_ACLK_MASK		0x7
+#define RK3228_DIV_ACLK_SHIFT		4
+#define RK3228_DIV_HCLK_MASK		0x3
+#define RK3228_DIV_HCLK_SHIFT		8
+#define RK3228_DIV_PCLK_MASK		0x7
+#define RK3228_DIV_PCLK_SHIFT		12
+
+#define RK3228_CLKSEL1(_core_peri_div)					\
+	{									\
+		.reg = RK2928_CLKSEL_CON(1),					\
+		.val = HIWORD_UPDATE(_core_peri_div, RK3228_DIV_PERI_MASK,	\
+				RK3228_DIV_PERI_SHIFT)				\
+	}
+
+#define RK3228_CPUCLK_RATE(_prate, _core_peri_div)			\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3228_CLKSEL1(_core_peri_div),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk3228_cpuclk_rates[] __initdata = {
+	RK3228_CPUCLK_RATE(816000000, 4),
+	RK3228_CPUCLK_RATE(600000000, 4),
+	RK3228_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = {
+	.core_reg = RK2928_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 6,
+};
+
+PNAME(mux_pll_p)		= { "clk_24m", "xin24m" };
+
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_armclk_p)		= { "apll_core", "gpll_core", "dpll_core" };
+PNAME(mux_usb480m_phy_p)	= { "usb480m_phy0", "usb480m_phy1" };
+PNAME(mux_usb480m_p)		= { "usb480m_phy", "xin24m" };
+PNAME(mux_hdmiphy_p)		= { "hdmiphy_phy", "xin24m" };
+PNAME(mux_aclk_cpu_src_p)	= { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" };
+
+PNAME(mux_pll_src_4plls_p)	= { "cpll", "gpll", "hdmiphy" "usb480m" };
+PNAME(mux_pll_src_3plls_p)	= { "cpll", "gpll", "hdmiphy" };
+PNAME(mux_pll_src_2plls_p)	= { "cpll", "gpll" };
+PNAME(mux_sclk_hdmi_cec_p)	= { "cpll", "gpll", "xin24m" };
+PNAME(mux_aclk_peri_src_p)	= { "cpll_peri", "gpll_peri", "hdmiphy_peri" };
+PNAME(mux_mmc_src_p)		= { "cpll", "gpll", "xin24m", "usb480m" };
+PNAME(mux_pll_src_cpll_gpll_usb480m_p)	= { "cpll", "gpll", "usb480m" };
+
+PNAME(mux_sclk_rga_p)		= { "gpll", "cpll", "sclk_rga_src" };
+
+PNAME(mux_sclk_vop_src_p)	= { "gpll_vop", "cpll_vop" };
+PNAME(mux_dclk_vop_p)		= { "hdmiphy", "sclk_vop_pre" };
+
+PNAME(mux_i2s0_p)		= { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s1_pre_p)		= { "i2s1_src", "i2s1_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p)		= { "i2s1_pre", "xin12m" };
+PNAME(mux_i2s2_p)		= { "i2s2_src", "i2s2_frac", "xin12m" };
+PNAME(mux_sclk_spdif_p)		= { "sclk_spdif_src", "spdif_frac", "xin12m" };
+
+PNAME(mux_aclk_gpu_pre_p)	= { "cpll_gpu", "gpll_gpu", "hdmiphy_gpu", "usb480m_gpu" };
+
+PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)		= { "uart2_src", "uart2_frac", "xin24m" };
+
+PNAME(mux_sclk_macphy_50m_p)	= { "ext_gmac", "phy_50m_out" };
+PNAME(mux_sclk_gmac_pre_p)	= { "sclk_gmac_src", "sclk_macphy_50m" };
+PNAME(mux_sclk_macphy_p)	= { "sclk_gmac_src", "ext_gmac" };
+
+static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
+		     RK2928_MODE_CON, 0, 7, 0, rk3228_pll_rates),
+	[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(3),
+		     RK2928_MODE_CON, 4, 6, 0, NULL),
+	[cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6),
+		     RK2928_MODE_CON, 8, 8, 0, NULL),
+	[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9),
+		     RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 1
+	 */
+
+	DIV(0, "clk_24m", "xin24m", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),
+
+	/* PD_DDR */
+	GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK2928_CLKGATE_CON(7), 1, GFLAGS),
+	GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(8), 5, GFLAGS),
+	GATE(0, "ddrphy", "ddrphy_pre", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(7), 0, GFLAGS),
+
+	/* PD_CORE */
+	GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+	GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+	GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(4), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "armcore", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(4), 0, GFLAGS),
+
+	/* PD_MISC */
+	MUX(0, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
+			RK2928_MISC_CON, 13, 1, MFLAGS),
+	MUX(0, "usb480m_phy", mux_usb480m_phy_p, CLK_SET_RATE_PARENT,
+			RK2928_MISC_CON, 14, 1, MFLAGS),
+	MUX(0, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
+			RK2928_MISC_CON, 15, 1, MFLAGS),
+
+	/* PD_BUS */
+	GATE(0, "hdmiphy_aclk_cpu", "hdmiphy", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 1, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
+			RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS),
+	GATE(ARMCLK, "aclk_cpu", "aclk_cpu_src", 0,
+			RK2928_CLKGATE_CON(6), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_cpu", "aclk_cpu_src", 0,
+			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS,
+			RK2928_CLKGATE_CON(6), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_bus_src", "aclk_cpu_src", 0,
+			RK2928_CLKSEL_CON(1), 12, 3, DFLAGS,
+			RK2928_CLKGATE_CON(6), 2, GFLAGS),
+	GATE(0, "pclk_cpu", "pclk_bus_src", 0,
+			RK2928_CLKGATE_CON(6), 3, GFLAGS),
+	GATE(0, "pclk_phy_pre", "pclk_bus_src", 0,
+			RK2928_CLKGATE_CON(6), 4, GFLAGS),
+	GATE(0, "pclk_ddr_pre", "pclk_bus_src", 0,
+			RK2928_CLKGATE_CON(6), 13, GFLAGS),
+
+	/* PD_VIDEO */
+	COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(32), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 11, GFLAGS),
+	GATE(0, "hclk_vpu_src", "aclk_vpu_pre", 0,
+			RK2928_CLKGATE_CON(4), 4, GFLAGS),
+
+	COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+	GATE(0, "hclk_rkvdec_src", "aclk_rkvdec_pre", 0,
+			RK2928_CLKGATE_CON(4), 5, GFLAGS),
+
+	COMPOSITE(0, "sclk_vdec_cabac", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(28), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 3, GFLAGS),
+
+	COMPOSITE(0, "sclk_vdec_core", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(34), 13, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 4, GFLAGS),
+
+	/* PD_VIO */
+	COMPOSITE(0, "aclk_iep_pre", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(31), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 0, GFLAGS),
+	DIV(0, "hclk_vio_pre", "aclk_iep_pre", 0,
+			RK2928_CLKSEL_CON(2), 0, 5, DFLAGS),
+
+	COMPOSITE(0, "aclk_hdcp_pre", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(31), 13, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 4, GFLAGS),
+
+	MUX(0, "sclk_rga_src", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(33), 13, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_rga_pre", "sclk_rga_src", 0,
+			RK2928_CLKSEL_CON(33), 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 2, GFLAGS),
+	COMPOSITE(0, "sclk_rga", mux_sclk_rga_p, 0,
+			RK2928_CLKSEL_CON(22), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 6, GFLAGS),
+
+	COMPOSITE(0, "aclk_vop_pre", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(33), 5, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 1, GFLAGS),
+
+	COMPOSITE(0, "sclk_hdcp", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(23), 14, 2, MFLAGS, 8, 6, DFLAGS,
+			RK2928_CLKGATE_CON(3), 5, GFLAGS),
+
+	GATE(0, "sclk_hdmi_hdcp", "xin24m", 0,
+			RK2928_CLKGATE_CON(3), 7, GFLAGS),
+
+	COMPOSITE(0, "sclk_hdmi_cec", mux_sclk_hdmi_cec_p, 0,
+			RK2928_CLKSEL_CON(21), 14, 2, MFLAGS, 0, 14, DFLAGS,
+			RK2928_CLKGATE_CON(3), 8, GFLAGS),
+
+	/* PD_PERI */
+	GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0,
+			RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKSEL_CON(10), 12, 3, DFLAGS,
+			RK2928_CLKGATE_CON(5), 2, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKSEL_CON(10), 8, 2, DFLAGS,
+			RK2928_CLKGATE_CON(5), 1, GFLAGS),
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKGATE_CON(5), 0, GFLAGS),
+
+	GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
+			RK2928_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
+			RK2928_CLKGATE_CON(6), 6, GFLAGS),
+	GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
+			RK2928_CLKGATE_CON(6), 7, GFLAGS),
+	GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
+			RK2928_CLKGATE_CON(6), 8, GFLAGS),
+	GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
+			RK2928_CLKGATE_CON(6), 9, GFLAGS),
+	GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
+			RK2928_CLKGATE_CON(6), 10, GFLAGS),
+
+	COMPOSITE(0, "sclk_crypto", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(24), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 7, GFLAGS),
+
+	COMPOSITE(0, "sclk_tsp", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(22), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 6, GFLAGS),
+
+	GATE(0, "sclk_hsadc", "ext_hsadc", 0,
+			RK3288_CLKGATE_CON(10), 12, GFLAGS),
+
+	COMPOSITE(0, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 15, GFLAGS),
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK2928_CLKGATE_CON(2), 11, GFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(11), 10, 2, MFLAGS,
+			RK2928_CLKGATE_CON(2), 13, GFLAGS),
+	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+			RK2928_CLKSEL_CON(12), 0, 8, DFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(11), 12, 2, MFLAGS,
+			RK2928_CLKGATE_CON(2), 14, GFLAGS),
+	DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
+			RK2928_CLKSEL_CON(12), 8, 8, DFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	GATE(0, "gpll_vop", "gpll", 0,
+			RK2928_CLKGATE_CON(3), 1, GFLAGS),
+	GATE(0, "cpll_vop", "cpll", 0,
+			RK2928_CLKGATE_CON(3), 1, GFLAGS),
+	MUX(0, "sclk_vop_src", mux_sclk_vop_src_p, 0,
+			RK2928_CLKSEL_CON(27), 0, 1, MFLAGS),
+	DIV(0, "dclk_hdmiphy", "sclk_vop_src", 0,
+			RK2928_CLKSEL_CON(29), 0, 3, DFLAGS),
+	DIV(0, "sclk_vop_pre", "sclk_vop_src", 0,
+			RK2928_CLKSEL_CON(27), 8, 8, DFLAGS),
+	MUX(0, "dclk_vop", mux_dclk_vop_p, 0,
+			RK2928_CLKSEL_CON(27), 1, 1, MFLAGS),
+
+	COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(9), 15, 1, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(8), 0,
+			RK3288_CLKGATE_CON(0), 4, GFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S0, "sclk_i2s0", mux_i2s0_p, 0,
+			RK2928_CLKSEL_CON(9), 8, 2, MFLAGS,
+			RK2928_CLKGATE_CON(0), 5, GFLAGS),
+
+	COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(3), 15, 1, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 10, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(7), 0,
+			RK3288_CLKGATE_CON(0), 11, GFLAGS),
+	MUX(0, "i2s1_pre", mux_i2s1_pre_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", 0,
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0,
+			RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
+			RK2928_CLKGATE_CON(0), 13, GFLAGS),
+
+	COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(16), 15, 1, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(30), 0,
+			RK3288_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S2, "sclk_i2s2", mux_i2s2_p, 0,
+			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS,
+			RK2928_CLKGATE_CON(0), 9, GFLAGS),
+
+	COMPOSITE(0, "sclk_spdif_src", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(6), 15, 1, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(20), 0,
+			RK3288_CLKGATE_CON(2), 12, GFLAGS),
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+			RK2928_CLKSEL_CON(6), 8, 2, MFLAGS),
+
+	GATE(0, "jtag", "ext_jtag", 0,
+			RK2928_CLKGATE_CON(1), 3, GFLAGS),
+
+	GATE(0, "sclk_otgphy0", "xin24m", 0,
+			RK2928_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(0, "sclk_otgphy1", "xin24m", 0,
+			RK2928_CLKGATE_CON(1), 6, GFLAGS),
+
+	COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0,
+			RK2928_CLKSEL_CON(24), 6, 10, DFLAGS,
+			RK2928_CLKGATE_CON(2), 8, GFLAGS),
+
+	GATE(0, "cpll_gpu", "cpll", 0,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	GATE(0, "gpll_gpu", "gpll", 0,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	GATE(0, "hdmiphy_gpu", "hdmiphy", 0,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	GATE(0, "usb480m_gpu", "usb480m", 0,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_gpu_pre", mux_aclk_gpu_pre_p, 0,
+			RK2928_CLKSEL_CON(34), 5, 2, MFLAGS, 0, 5, DFLAGS),
+
+	COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(25), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 9, GFLAGS),
+
+	/* PD_UART */
+	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE(0, "uart1_src", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK2928_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 10, GFLAGS),
+	COMPOSITE(0, "uart2_src", mux_pll_src_cpll_gpll_usb480m_p,
+			0, RK2928_CLKSEL_CON(15), 12, 2,
+			MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 12, GFLAGS),
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(17), 0,
+			RK2928_CLKGATE_CON(1), 9, GFLAGS),
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(18), 0,
+			RK2928_CLKGATE_CON(1), 11, GFLAGS),
+	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(19), 0,
+			RK2928_CLKGATE_CON(1), 13, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+
+	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(2), 14, 1, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 0, GFLAGS),
+
+	COMPOSITE(0, "sclk_gmac_src", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(5), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 7, GFLAGS),
+	MUX(0, "sclk_macphy_50m", mux_sclk_macphy_50m_p, 0,
+			RK2928_CLKSEL_CON(29), 10, 1, MFLAGS),
+	MUX(0, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0,
+			RK2928_CLKSEL_CON(5), 5, 1, MFLAGS),
+	GATE(0, "sclk_mac_refout", "sclk_gmac_pre", 0,
+			RK2928_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(0, "sclk_mac_ref", "sclk_gmac_pre", 0,
+			RK2928_CLKGATE_CON(5), 3, GFLAGS),
+	GATE(0, "sclk_mac_rx", "sclk_gmac_pre", 0,
+			RK2928_CLKGATE_CON(5), 5, GFLAGS),
+	GATE(0, "sclk_mac_tx", "sclk_gmac_pre", 0,
+			RK2928_CLKGATE_CON(5), 6, GFLAGS),
+	COMPOSITE(0, "sclk_macphy", mux_sclk_macphy_p, 0,
+			RK2928_CLKSEL_CON(29), 12, 1, MFLAGS, 8, 2, DFLAGS,
+			RK2928_CLKGATE_CON(5), 7, GFLAGS),
+	COMPOSITE(0, "sclk_gmac_out", mux_pll_src_2plls_p, 0,
+			RK2928_CLKSEL_CON(5), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 2, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	/* PD_VOP */
+	GATE(0, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS),
+	GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS),
+	GATE(0, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS),
+	GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS),
+
+	GATE(0, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS),
+	GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS),
+
+	GATE(0, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS),
+	GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS),
+
+	GATE(0, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS),
+	GATE(0, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS),
+	GATE(0, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS),
+	GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS),
+	GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS),
+	GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS),
+	GATE(0, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS),
+	GATE(0, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS),
+	GATE(0, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS),
+	GATE(0, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(0, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS),
+
+	/* PD_PERI */
+	GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 0, GFLAGS),
+	GATE(0, "aclk_gmac", "aclk_peri", 0, RK2928_CLKGATE_CON(11), 4, GFLAGS),
+
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 0, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 1, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS),
+	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS),
+	GATE(0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS),
+	GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS),
+	GATE(0, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS),
+	GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS),
+	GATE(0, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS),
+	GATE(0, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS),
+	GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS),
+	GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS),
+	GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS),
+
+	GATE(0, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS),
+	GATE(0, "pclk_peri_noc", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 2, GFLAGS),
+
+	/* PD_GPU */
+	GATE(0, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 14, GFLAGS),
+	GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 15, GFLAGS),
+
+	/* PD_BUS */
+	GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+	GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
+	GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS),
+
+	GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS),
+	GATE(0, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS),
+	GATE(0, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS),
+	GATE(0, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+	GATE(0, "hclk_spdif_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
+	GATE(0, "hclk_tsp", "hclk_cpu", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS),
+	GATE(0, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+	GATE(0, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
+
+	GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+	GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+	GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS),
+
+	GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
+	GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS),
+	GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS),
+	GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
+	GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 9, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 10, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 11, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 12, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 13, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 14, GFLAGS),
+	GATE(0, "pclk_tsadc", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 15, GFLAGS),
+	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS),
+	GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS),
+	GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS),
+
+	GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS),
+	GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS),
+	GATE(0, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS),
+	GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
+
+	GATE(0, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS),
+	GATE(0, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS),
+	GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS),
+	GATE(0, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS),
+	GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS),
+	GATE(0, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS),
+	GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS),
+
+	/* PD_MMC */
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3228_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1),
+
+	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK3228_SDIO_CON0,  1),
+	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK3228_SDIO_CON1,  1),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3228_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3228_EMMC_CON1,  1),
+};
+
+static const char *const rk3228_critical_clocks[] __initconst = {
+	"aclk_cpu",
+	"aclk_peri",
+	"hclk_peri",
+	"pclk_peri",
+};
+
+static void __init rk3228_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+				__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "ddrphy_pre", "ddrphy4x", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock ddrphy_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "hclk_vpu_pre",
+					"hclk_vpu_src", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock hclk_vpu_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "hclk_rkvdec_pre",
+					"hclk_rkvdec_src", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock hclk_rkvdec_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	rockchip_clk_register_plls(rk3228_pll_clks,
+				   ARRAY_SIZE(rk3228_pll_clks),
+				   RK3228_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(rk3228_clk_branches,
+				  ARRAY_SIZE(rk3228_clk_branches));
+	rockchip_clk_protect_critical(rk3228_critical_clocks,
+				      ARRAY_SIZE(rk3228_critical_clocks));
+
+	rockchip_clk_register_armclk(ARMCLK, "armclk",
+			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+			&rk3228_cpuclk_data, rk3228_cpuclk_rates,
+			ARRAY_SIZE(rk3228_cpuclk_rates));
+
+	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL);
+}
+CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 9040878e3e2b..984fc187d12e 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -225,6 +225,38 @@ static struct clk_div_table div_hclk_cpu_t[] = {
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
 #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
+static struct rockchip_clk_branch rk3288_i2s_fracmux __initdata =
+	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_spdif_fracmux __initdata =
+	MUX(0, "spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_spdif_8ch_fracmux __initdata =
+	MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart3_fracmux __initdata =
+	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart4_fracmux __initdata =
+	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS);
+
 static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	/*
 	 * Clock-Architecture Diagram 1
@@ -295,7 +327,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 			RK3288_CLKGATE_CON(0), 4, GFLAGS),
 	GATE(0, "c2c_host", "aclk_cpu_src", 0,
 			RK3288_CLKGATE_CON(13), 8, GFLAGS),
-	COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0,
+	COMPOSITE_NOMUX(SCLK_CRYPTO, "crypto", "aclk_cpu_pre", 0,
 			RK3288_CLKSEL_CON(26), 6, 2, DFLAGS,
 			RK3288_CLKGATE_CON(5), 4, GFLAGS),
 	GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED,
@@ -304,11 +336,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 1, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(8), 0,
-			RK3288_CLKGATE_CON(4), 2, GFLAGS),
-	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(4), 2, GFLAGS,
+			&rk3288_i2s_fracmux),
 	COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
 			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
 			RK3288_CLKGATE_CON(4), 0, GFLAGS),
@@ -317,23 +348,23 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 
 	MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(5), 15, 1, MFLAGS),
-	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
+	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 4, GFLAGS),
-	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
+	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(9), 0,
-			RK3288_CLKGATE_CON(4), 5, GFLAGS),
-	COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
-			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
+			RK3288_CLKGATE_CON(4), 5, GFLAGS,
+			&rk3288_spdif_fracmux),
+	GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", CLK_SET_RATE_PARENT,
 			RK3288_CLKGATE_CON(4), 6, GFLAGS),
-	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
+	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 7, GFLAGS),
-	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
+	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(41), 0,
-			RK3288_CLKGATE_CON(4), 8, GFLAGS),
-	COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
-			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
+			RK3288_CLKGATE_CON(4), 8, GFLAGS,
+			&rk3288_spdif_8ch_fracmux),
+	GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", CLK_SET_RATE_PARENT,
 			RK3288_CLKGATE_CON(4), 9, GFLAGS),
 
 	GATE(0, "sclk_acc_efuse", "xin24m", 0,
@@ -536,45 +567,40 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
 			RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(17), 0,
-			RK3288_CLKGATE_CON(1), 9, GFLAGS),
-	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 9, GFLAGS,
+			&rk3288_uart0_fracmux),
 	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(18), 0,
-			RK3288_CLKGATE_CON(1), 11, GFLAGS),
-	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 11, GFLAGS,
+			&rk3288_uart1_fracmux),
 	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(19), 0,
-			RK3288_CLKGATE_CON(1), 13, GFLAGS),
-	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 13, GFLAGS,
+			&rk3288_uart2_fracmux),
 	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 14, GFLAGS),
-	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(20), 0,
-			RK3288_CLKGATE_CON(1), 15, GFLAGS),
-	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 15, GFLAGS,
+			&rk3288_uart3_fracmux),
 	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(2), 12, GFLAGS),
-	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(7), 0,
-			RK3288_CLKGATE_CON(2), 13, GFLAGS),
-	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(2), 13, GFLAGS,
+			&rk3288_uart4_fracmux),
 
 	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
@@ -644,10 +670,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
 	GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
 	GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
-	GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
+	GATE(PCLK_EFUSE1024, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
 	GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
 	GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
-	GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
+	GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
 	GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS),
 
 	/* ddrctrl [DDR Controller PHY clock] gates */
@@ -709,7 +735,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS),
 	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
 	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
-	GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
+	GATE(SCLK_MIPIDSI_24M, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
 
 	/* sclk_gpu gates */
 	GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS),
@@ -783,10 +809,10 @@ static const char *const rk3288_critical_clocks[] __initconst = {
 	"pclk_pd_pmu",
 };
 
-#ifdef CONFIG_PM_SLEEP
 static void __iomem *rk3288_cru_base;
 
-/* Some CRU registers will be reset in maskrom when the system
+/*
+ * Some CRU registers will be reset in maskrom when the system
  * wakes up from fastboot.
  * So save them before suspend, restore them after resume.
  */
@@ -840,33 +866,27 @@ static void rk3288_clk_resume(void)
 	}
 }
 
+static void rk3288_clk_shutdown(void)
+{
+	writel_relaxed(0xf3030000, rk3288_cru_base + RK3288_MODE_CON);
+}
+
 static struct syscore_ops rk3288_clk_syscore_ops = {
 	.suspend = rk3288_clk_suspend,
 	.resume = rk3288_clk_resume,
 };
 
-static void rk3288_clk_sleep_init(void __iomem *reg_base)
-{
-	rk3288_cru_base = reg_base;
-	register_syscore_ops(&rk3288_clk_syscore_ops);
-}
-
-#else /* CONFIG_PM_SLEEP */
-static void rk3288_clk_sleep_init(void __iomem *reg_base) {}
-#endif
-
 static void __init rk3288_clk_init(struct device_node *np)
 {
-	void __iomem *reg_base;
 	struct clk *clk;
 
-	reg_base = of_iomap(np, 0);
-	if (!reg_base) {
+	rk3288_cru_base = of_iomap(np, 0);
+	if (!rk3288_cru_base) {
 		pr_err("%s: could not map cru region\n", __func__);
 		return;
 	}
 
-	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS);
 
 	/* xin12m is created by an cru-internal divider */
 	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
@@ -907,10 +927,12 @@ static void __init rk3288_clk_init(struct device_node *np)
 			&rk3288_cpuclk_data, rk3288_cpuclk_rates,
 			ARRAY_SIZE(rk3288_cpuclk_rates));
 
-	rockchip_register_softrst(np, 12, reg_base + RK3288_SOFTRST_CON(0),
+	rockchip_register_softrst(np, 12,
+				  rk3288_cru_base + RK3288_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK3288_GLB_SRST_FST);
-	rk3288_clk_sleep_init(reg_base);
+	rockchip_register_restart_notifier(RK3288_GLB_SRST_FST,
+					   rk3288_clk_shutdown);
+	register_syscore_ops(&rk3288_clk_syscore_ops);
 }
 CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
index 7e6b783e6eee..be0ede522269 100644
--- a/drivers/clk/rockchip/clk-rk3368.c
+++ b/drivers/clk/rockchip/clk-rk3368.c
@@ -184,13 +184,13 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
 
 #define RK3368_CLKSEL0(_offs, _aclkm)					\
 	{								\
-		.reg = RK3288_CLKSEL_CON(0 + _offs),			\
+		.reg = RK3368_CLKSEL_CON(0 + _offs),			\
 		.val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK,	\
 				RK3368_DIV_ACLKM_SHIFT),		\
 	}
 #define RK3368_CLKSEL1(_offs, _atclk, _pdbg)				\
 	{								\
-		.reg = RK3288_CLKSEL_CON(1 + _offs),			\
+		.reg = RK3368_CLKSEL_CON(1 + _offs),			\
 		.val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK,	\
 				RK3368_DIV_ATCLK_SHIFT) |		\
 		       HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK,	\
@@ -819,6 +819,13 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
 };
 
 static const char *const rk3368_critical_clocks[] __initconst = {
+	"aclk_bus",
+	"aclk_peri",
+	/*
+	 * pwm1 supplies vdd_logic on a lot of boards, is currently unhandled
+	 * but needs to stay enabled there (including its parents) at all times.
+	 */
+	"pclk_pwm1",
 	"pclk_pd_pmu",
 };
 
@@ -882,6 +889,6 @@ static void __init rk3368_clk_init(struct device_node *np)
 	rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK3368_GLB_SRST_FST);
+	rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL);
 }
 CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index be6c7fd8315d..d9a0b5d4d47f 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -102,22 +102,82 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 	return clk;
 }
 
+struct rockchip_clk_frac {
+	struct notifier_block			clk_nb;
+	struct clk_fractional_divider		div;
+	struct clk_gate				gate;
+
+	struct clk_mux				mux;
+	const struct clk_ops			*mux_ops;
+	int					mux_frac_idx;
+
+	bool					rate_change_remuxed;
+	int					rate_change_idx;
+};
+
+#define to_rockchip_clk_frac_nb(nb) \
+			container_of(nb, struct rockchip_clk_frac, clk_nb)
+
+static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
+					 unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
+	struct clk_mux *frac_mux = &frac->mux;
+	int ret = 0;
+
+	pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
+		 __func__, event, ndata->old_rate, ndata->new_rate);
+	if (event == PRE_RATE_CHANGE) {
+		frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw);
+		if (frac->rate_change_idx != frac->mux_frac_idx) {
+			frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx);
+			frac->rate_change_remuxed = 1;
+		}
+	} else if (event == POST_RATE_CHANGE) {
+		/*
+		 * The POST_RATE_CHANGE notifier runs directly after the
+		 * divider clock is set in clk_change_rate, so we'll have
+		 * remuxed back to the original parent before clk_change_rate
+		 * reaches the mux itself.
+		 */
+		if (frac->rate_change_remuxed) {
+			frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx);
+			frac->rate_change_remuxed = 0;
+		}
+	}
+
+	return notifier_from_errno(ret);
+}
+
 static struct clk *rockchip_clk_register_frac_branch(const char *name,
 		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)
+		unsigned long flags, struct rockchip_clk_branch *child,
+		spinlock_t *lock)
 {
+	struct rockchip_clk_frac *frac;
 	struct clk *clk;
 	struct clk_gate *gate = NULL;
 	struct clk_fractional_divider *div = NULL;
 	const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
 
-	if (gate_offset >= 0) {
-		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
-		if (!gate)
-			return ERR_PTR(-ENOMEM);
+	if (muxdiv_offset < 0)
+		return ERR_PTR(-EINVAL);
+
+	if (child && child->branch_type != branch_mux) {
+		pr_err("%s: fractional child clock for %s can only be a mux\n",
+		       __func__, name);
+		return ERR_PTR(-EINVAL);
+	}
 
+	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
+	if (!frac)
+		return ERR_PTR(-ENOMEM);
+
+	if (gate_offset >= 0) {
+		gate = &frac->gate;
 		gate->flags = gate_flags;
 		gate->reg = base + gate_offset;
 		gate->bit_idx = gate_shift;
@@ -125,13 +185,7 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
 		gate_ops = &clk_gate_ops;
 	}
 
-	if (muxdiv_offset < 0)
-		return ERR_PTR(-EINVAL);
-
-	div = kzalloc(sizeof(*div), GFP_KERNEL);
-	if (!div)
-		return ERR_PTR(-ENOMEM);
-
+	div = &frac->div;
 	div->flags = div_flags;
 	div->reg = base + muxdiv_offset;
 	div->mshift = 16;
@@ -147,7 +201,61 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
 				     NULL, NULL,
 				     &div->hw, div_ops,
 				     gate ? &gate->hw : NULL, gate_ops,
-				     flags);
+				     flags | CLK_SET_RATE_UNGATE);
+	if (IS_ERR(clk)) {
+		kfree(frac);
+		return clk;
+	}
+
+	if (child) {
+		struct clk_mux *frac_mux = &frac->mux;
+		struct clk_init_data init;
+		struct clk *mux_clk;
+		int i, ret;
+
+		frac->mux_frac_idx = -1;
+		for (i = 0; i < child->num_parents; i++) {
+			if (!strcmp(name, child->parent_names[i])) {
+				pr_debug("%s: found fractional parent in mux at pos %d\n",
+					 __func__, i);
+				frac->mux_frac_idx = i;
+				break;
+			}
+		}
+
+		frac->mux_ops = &clk_mux_ops;
+		frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
+
+		frac_mux->reg = base + child->muxdiv_offset;
+		frac_mux->shift = child->mux_shift;
+		frac_mux->mask = BIT(child->mux_width) - 1;
+		frac_mux->flags = child->mux_flags;
+		frac_mux->lock = lock;
+		frac_mux->hw.init = &init;
+
+		init.name = child->name;
+		init.flags = child->flags | CLK_SET_RATE_PARENT;
+		init.ops = frac->mux_ops;
+		init.parent_names = child->parent_names;
+		init.num_parents = child->num_parents;
+
+		mux_clk = clk_register(NULL, &frac_mux->hw);
+		if (IS_ERR(mux_clk))
+			return clk;
+
+		rockchip_clk_add_lookup(mux_clk, child->id);
+
+		/* notifier on the fraction divider to catch rate changes */
+		if (frac->mux_frac_idx >= 0) {
+			ret = clk_notifier_register(clk, &frac->clk_nb);
+			if (ret)
+				pr_err("%s: failed to register clock notifier for %s\n",
+						__func__, name);
+		} else {
+			pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
+				__func__, name, child->name);
+		}
+	}
 
 	return clk;
 }
@@ -251,7 +359,8 @@ void __init rockchip_clk_register_branches(
 				list->parent_names, list->num_parents,
 				reg_base, list->muxdiv_offset, list->div_flags,
 				list->gate_offset, list->gate_shift,
-				list->gate_flags, flags, &clk_lock);
+				list->gate_flags, flags, list->child,
+				&clk_lock);
 			break;
 		case branch_gate:
 			flags |= CLK_SET_RATE_PARENT;
@@ -341,9 +450,13 @@ void __init rockchip_clk_protect_critical(const char *const clocks[],
 }
 
 static unsigned int reg_restart;
+static void (*cb_restart)(void);
 static int rockchip_restart_notify(struct notifier_block *this,
 				   unsigned long mode, void *cmd)
 {
+	if (cb_restart)
+		cb_restart();
+
 	writel(0xfdb9, reg_base + reg_restart);
 	return NOTIFY_DONE;
 }
@@ -353,11 +466,12 @@ static struct notifier_block rockchip_restart_handler = {
 	.priority = 128,
 };
 
-void __init rockchip_register_restart_notifier(unsigned int reg)
+void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void))
 {
 	int ret;
 
 	reg_restart = reg;
+	cb_restart = cb;
 	ret = register_restart_handler(&rockchip_restart_handler);
 	if (ret)
 		pr_err("%s: cannot register restart handler, %d\n",
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index dc8ecb2673b7..ff8bd23a93ec 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -2,6 +2,9 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
  * based on
  *
  * samsung/clk.h
@@ -30,7 +33,7 @@ struct clk;
 #define HIWORD_UPDATE(val, mask, shift) \
 		((val) << (shift) | (mask) << ((shift) + 16))
 
-/* register positions shared by RK2928, RK3066 and RK3188 */
+/* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */
 #define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
 #define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
@@ -40,6 +43,22 @@ struct clk;
 #define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON		0x134
 
+#define RK3036_SDMMC_CON0		0x144
+#define RK3036_SDMMC_CON1		0x148
+#define RK3036_SDIO_CON0		0x14c
+#define RK3036_SDIO_CON1		0x150
+#define RK3036_EMMC_CON0		0x154
+#define RK3036_EMMC_CON1		0x158
+
+#define RK3228_GLB_SRST_FST		0x1f0
+#define RK3228_GLB_SRST_SND		0x1f4
+#define RK3228_SDMMC_CON0		0x1c0
+#define RK3228_SDMMC_CON1		0x1c4
+#define RK3228_SDIO_CON0		0x1c8
+#define RK3228_SDIO_CON1		0x1cc
+#define RK3228_EMMC_CON0		0x1d8
+#define RK3228_EMMC_CON1		0x1dc
+
 #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
 #define RK3288_MODE_CON			0x50
 #define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
@@ -74,9 +93,22 @@ struct clk;
 #define RK3368_EMMC_CON1		0x41c
 
 enum rockchip_pll_type {
+	pll_rk3036,
 	pll_rk3066,
 };
 
+#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
+			_postdiv2, _dsmpd, _frac)		\
+{								\
+	.rate	= _rate##U,					\
+	.fbdiv = _fbdiv,					\
+	.postdiv1 = _postdiv1,					\
+	.refdiv = _refdiv,					\
+	.postdiv2 = _postdiv2,					\
+	.dsmpd = _dsmpd,					\
+	.frac = _frac,						\
+}
+
 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
 {						\
 	.rate	= _rate##U,			\
@@ -101,6 +133,13 @@ struct rockchip_pll_rate_table {
 	unsigned int nf;
 	unsigned int no;
 	unsigned int nb;
+	/* for RK3036 */
+	unsigned int fbdiv;
+	unsigned int postdiv1;
+	unsigned int refdiv;
+	unsigned int postdiv2;
+	unsigned int dsmpd;
+	unsigned int frac;
 };
 
 /**
@@ -235,6 +274,7 @@ struct rockchip_clk_branch {
 	int				gate_offset;
 	u8				gate_shift;
 	u8				gate_flags;
+	struct rockchip_clk_branch	*child;
 };
 
 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
@@ -369,6 +409,24 @@ struct rockchip_clk_branch {
 		.gate_flags	= gf,				\
 	}
 
+#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_fraction_divider,	\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.div_shift	= 16,				\
+		.div_width	= 16,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+		.child		= ch,				\
+	}
+
 #define MUX(_id, cname, pnames, f, o, s, w, mf)			\
 	{							\
 		.id		= _id,				\
@@ -464,7 +522,7 @@ void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates);
 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
-void rockchip_register_restart_notifier(unsigned int reg);
+void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void));
 
 #define ROCKCHIP_SOFTRST_HIWORD_MASK	BIT(0)
 
diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
index 2fe37f708dc7..813003d6ce09 100644
--- a/drivers/clk/samsung/clk-cpu.c
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -148,6 +148,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
 	unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
 	unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
 	unsigned long div0, div1 = 0, mux_reg;
+	unsigned long flags;
 
 	/* find out the divider values to use for clock data */
 	while ((cfg_data->prate * 1000) != ndata->new_rate) {
@@ -156,7 +157,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
 		cfg_data++;
 	}
 
-	spin_lock(cpuclk->lock);
+	spin_lock_irqsave(cpuclk->lock, flags);
 
 	/*
 	 * For the selected PLL clock frequency, get the pre-defined divider
@@ -212,7 +213,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
 				DIV_MASK_ALL);
 	}
 
-	spin_unlock(cpuclk->lock);
+	spin_unlock_irqrestore(cpuclk->lock, flags);
 	return 0;
 }
 
@@ -223,6 +224,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
 	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
 	unsigned long div = 0, div_mask = DIV_MASK;
 	unsigned long mux_reg;
+	unsigned long flags;
 
 	/* find out the divider values to use for clock data */
 	if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) {
@@ -233,7 +235,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
 		}
 	}
 
-	spin_lock(cpuclk->lock);
+	spin_lock_irqsave(cpuclk->lock, flags);
 
 	/* select mout_apll as the alternate parent */
 	mux_reg = readl(base + E4210_SRC_CPU);
@@ -246,7 +248,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
 	}
 
 	exynos_set_safe_div(base, div, div_mask);
-	spin_unlock(cpuclk->lock);
+	spin_unlock_irqrestore(cpuclk->lock, flags);
 	return 0;
 }
 
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 389af3c15ec4..d048dedd8b72 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -18,6 +18,7 @@
 #include <linux/syscore_ops.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 
 #define APLL_LOCK		0x0
 #define APLL_CON0		0x100
@@ -616,9 +617,11 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
 	MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
 	MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2),
 
-	MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
+	MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+	      CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
 	MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
-	MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1),
+	MUX_F(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1,
+	      CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
 	MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
 
 	MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2),
@@ -677,8 +680,8 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
 			SRC_TOP5, 20, 1),
 	MUX(CLK_MOUT_USER_ACLK300_DISP1, "mout_user_aclk300_disp1",
 			mout_user_aclk300_disp1_p, SRC_TOP5, 24, 1),
-	MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p,
-			SRC_TOP5, 28, 1),
+	MUX(CLK_MOUT_USER_ACLK300_GSCL, "mout_user_aclk300_gscl",
+			mout_user_aclk300_gscl_p, SRC_TOP5, 28, 1),
 
 	MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1),
 	MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1),
@@ -729,8 +732,8 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
 			SRC_TOP12, 20, 1),
 	MUX(CLK_MOUT_SW_ACLK300, "mout_sw_aclk300_disp1",
 			mout_sw_aclk300_disp1_p, SRC_TOP12, 24, 1),
-	MUX(0, "mout_sw_aclk300_gscl", mout_sw_aclk300_gscl_p,
-			SRC_TOP12, 28, 1),
+	MUX(CLK_MOUT_SW_ACLK300_GSCL, "mout_sw_aclk300_gscl",
+			mout_sw_aclk300_gscl_p, SRC_TOP12, 28, 1),
 
 	/* DISP1 Block */
 	MUX(0, "mout_mipi1", mout_group2_p, SRC_DISP10, 16, 3),
@@ -926,7 +929,7 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
 			GATE_BUS_TOP, 13, 0, 0),
 	GATE(0, "aclk166", "mout_user_aclk166",
 			GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
-	GATE(0, "aclk333", "mout_aclk333",
+	GATE(0, "aclk333", "mout_user_aclk333",
 			GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
 			GATE_BUS_TOP, 16, 0, 0),
@@ -1246,6 +1249,74 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
 		KPLL_CON0, NULL),
 };
 
+#define E5420_EGL_DIV0(apll, pclk_dbg, atb, cpud)			\
+		((((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) |	\
+		 ((cpud) << 4)))
+
+static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
+	{ 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
+	{ 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
+	{ 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
+	{ 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
+	{ 1000000, E5420_EGL_DIV0(3, 6, 6, 2), },
+	{  900000, E5420_EGL_DIV0(3, 6, 6, 2), },
+	{  800000, E5420_EGL_DIV0(3, 5, 5, 2), },
+	{  700000, E5420_EGL_DIV0(3, 5, 5, 2), },
+	{  600000, E5420_EGL_DIV0(3, 4, 4, 2), },
+	{  500000, E5420_EGL_DIV0(3, 3, 3, 2), },
+	{  400000, E5420_EGL_DIV0(3, 3, 3, 2), },
+	{  300000, E5420_EGL_DIV0(3, 3, 3, 2), },
+	{  200000, E5420_EGL_DIV0(3, 3, 3, 2), },
+	{  0 },
+};
+
+static const struct exynos_cpuclk_cfg_data exynos5800_eglclk_d[] __initconst = {
+	{ 2000000, E5420_EGL_DIV0(3, 7, 7, 4), },
+	{ 1900000, E5420_EGL_DIV0(3, 7, 7, 4), },
+	{ 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
+	{ 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
+	{ 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
+	{ 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
+	{ 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
+	{ 1000000, E5420_EGL_DIV0(3, 7, 6, 2), },
+	{  900000, E5420_EGL_DIV0(3, 7, 6, 2), },
+	{  800000, E5420_EGL_DIV0(3, 7, 5, 2), },
+	{  700000, E5420_EGL_DIV0(3, 7, 5, 2), },
+	{  600000, E5420_EGL_DIV0(3, 7, 4, 2), },
+	{  500000, E5420_EGL_DIV0(3, 7, 3, 2), },
+	{  400000, E5420_EGL_DIV0(3, 7, 3, 2), },
+	{  300000, E5420_EGL_DIV0(3, 7, 3, 2), },
+	{  200000, E5420_EGL_DIV0(3, 7, 3, 2), },
+	{  0 },
+};
+
+#define E5420_KFC_DIV(kpll, pclk, aclk)					\
+		((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
+
+static const struct exynos_cpuclk_cfg_data exynos5420_kfcclk_d[] __initconst = {
+	{ 1400000, E5420_KFC_DIV(3, 5, 3), }, /* for Exynos5800 */
+	{ 1300000, E5420_KFC_DIV(3, 5, 2), },
+	{ 1200000, E5420_KFC_DIV(3, 5, 2), },
+	{ 1100000, E5420_KFC_DIV(3, 5, 2), },
+	{ 1000000, E5420_KFC_DIV(3, 5, 2), },
+	{  900000, E5420_KFC_DIV(3, 5, 2), },
+	{  800000, E5420_KFC_DIV(3, 5, 2), },
+	{  700000, E5420_KFC_DIV(3, 4, 2), },
+	{  600000, E5420_KFC_DIV(3, 4, 2), },
+	{  500000, E5420_KFC_DIV(3, 4, 2), },
+	{  400000, E5420_KFC_DIV(3, 3, 2), },
+	{  300000, E5420_KFC_DIV(3, 3, 2), },
+	{  200000, E5420_KFC_DIV(3, 3, 2), },
+	{  0 },
+};
+
 static const struct of_device_id ext_clk_match[] __initconst = {
 	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
 	{ },
@@ -1310,6 +1381,19 @@ static void __init exynos5x_clk_init(struct device_node *np,
 				ARRAY_SIZE(exynos5800_gate_clks));
 	}
 
+	if (soc == EXYNOS5420) {
+		exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+			mout_cpu_p[0], mout_cpu_p[1], 0x200,
+			exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
+	} else {
+		exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+			mout_cpu_p[0], mout_cpu_p[1], 0x200,
+			exynos5800_eglclk_d, ARRAY_SIZE(exynos5800_eglclk_d), 0);
+	}
+	exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
+		mout_kfc_p[0], mout_kfc_p[1], 0x28200,
+		exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
+
 	exynos5420_clk_sleep_init();
 
 	samsung_clk_of_add_provider(np, ctx);
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index e9eb935d7616..ec6fb14d951c 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -77,12 +77,11 @@ static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
 static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
 {
 	struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
-	int ret = 0;
 
 	s3c2410_modify_misccr((clkout->mask << clkout->shift),
 			      (index << clkout->shift));
 
-	return ret;
+	return 0;
 }
 
 static const struct clk_ops s3c24xx_clkout_ops = {
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile
index 97c71c885e4f..7e2579b30326 100644
--- a/drivers/clk/shmobile/Makefile
+++ b/drivers/clk/shmobile/Makefile
@@ -1,13 +1,13 @@
 obj-$(CONFIG_ARCH_EMEV2)		+= clk-emev2.o
-obj-$(CONFIG_ARCH_R7S72100)		+= clk-rz.o
-obj-$(CONFIG_ARCH_R8A73A4)		+= clk-r8a73a4.o
-obj-$(CONFIG_ARCH_R8A7740)		+= clk-r8a7740.o
-obj-$(CONFIG_ARCH_R8A7778)		+= clk-r8a7778.o
-obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o
-obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o
-obj-$(CONFIG_ARCH_R8A7791)		+= clk-rcar-gen2.o
-obj-$(CONFIG_ARCH_R8A7793)		+= clk-rcar-gen2.o
-obj-$(CONFIG_ARCH_R8A7794)		+= clk-rcar-gen2.o
-obj-$(CONFIG_ARCH_SH73A0)		+= clk-sh73a0.o
-obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= clk-div6.o
-obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= clk-mstp.o
+obj-$(CONFIG_ARCH_R7S72100)		+= clk-rz.o clk-mstp.o
+obj-$(CONFIG_ARCH_R8A73A4)		+= clk-r8a73a4.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7740)		+= clk-r8a7740.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7778)		+= clk-r8a7778.o clk-mstp.o
+obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o clk-mstp.o
+obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7791)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7793)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7794)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7795)		+= renesas-cpg-mssr.o \
+					   r8a7795-cpg-mssr.o clk-div6.o
+obj-$(CONFIG_ARCH_SH73A0)		+= clk-sh73a0.o clk-mstp.o clk-div6.o
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c
index b4c8d6746f68..999994769450 100644
--- a/drivers/clk/shmobile/clk-div6.c
+++ b/drivers/clk/shmobile/clk-div6.c
@@ -18,6 +18,8 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 
+#include "clk-div6.h"
+
 #define CPG_DIV6_CKSTP		BIT(8)
 #define CPG_DIV6_DIV(d)		((d) & 0x3f)
 #define CPG_DIV6_DIV_MASK	0x3f
@@ -172,67 +174,44 @@ static const struct clk_ops cpg_div6_clock_ops = {
 	.set_rate = cpg_div6_clock_set_rate,
 };
 
-static void __init cpg_div6_clock_init(struct device_node *np)
+
+/**
+ * cpg_div6_register - Register a DIV6 clock
+ * @name: Name of the DIV6 clock
+ * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8)
+ * @parent_names: Array containing the names of the parent clocks
+ * @reg: Mapped register used to control the DIV6 clock
+ */
+struct clk * __init cpg_div6_register(const char *name,
+				      unsigned int num_parents,
+				      const char **parent_names,
+				      void __iomem *reg)
 {
-	unsigned int num_parents, valid_parents;
-	const char **parent_names;
+	unsigned int valid_parents;
 	struct clk_init_data init;
 	struct div6_clock *clock;
-	const char *name;
 	struct clk *clk;
 	unsigned int i;
-	int ret;
 
 	clock = kzalloc(sizeof(*clock), GFP_KERNEL);
 	if (!clock)
-		return;
+		return ERR_PTR(-ENOMEM);
 
-	num_parents = of_clk_get_parent_count(np);
-	if (num_parents < 1) {
-		pr_err("%s: no parent found for %s DIV6 clock\n",
-		       __func__, np->name);
-		return;
+	clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents),
+				       GFP_KERNEL);
+	if (!clock->parents) {
+		clk = ERR_PTR(-ENOMEM);
+		goto free_clock;
 	}
 
-	clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents),
-		GFP_KERNEL);
-	parent_names = kmalloc_array(num_parents, sizeof(*parent_names),
-				GFP_KERNEL);
-	if (!parent_names)
-		return;
+	clock->reg = reg;
 
-	/* Remap the clock register and read the divisor. Disabling the
-	 * clock overwrites the divisor, so we need to cache its value for the
-	 * enable operation.
+	/*
+	 * Read the divisor. Disabling the clock overwrites the divisor, so we
+	 * need to cache its value for the enable operation.
 	 */
-	clock->reg = of_iomap(np, 0);
-	if (clock->reg == NULL) {
-		pr_err("%s: failed to map %s DIV6 clock register\n",
-		       __func__, np->name);
-		goto error;
-	}
-
 	clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;
 
-	/* Parse the DT properties. */
-	ret = of_property_read_string(np, "clock-output-names", &name);
-	if (ret < 0) {
-		pr_err("%s: failed to get %s DIV6 clock output name\n",
-		       __func__, np->name);
-		goto error;
-	}
-
-
-	for (i = 0, valid_parents = 0; i < num_parents; i++) {
-		const char *name = of_clk_get_parent_name(np, i);
-
-		if (name) {
-			parent_names[valid_parents] = name;
-			clock->parents[valid_parents] = i;
-			valid_parents++;
-		}
-	}
-
 	switch (num_parents) {
 	case 1:
 		/* fixed parent clock */
@@ -250,8 +229,18 @@ static void __init cpg_div6_clock_init(struct device_node *np)
 		break;
 	default:
 		pr_err("%s: invalid number of parents for DIV6 clock %s\n",
-		       __func__, np->name);
-		goto error;
+		       __func__, name);
+		clk = ERR_PTR(-EINVAL);
+		goto free_parents;
+	}
+
+	/* Filter out invalid parents */
+	for (i = 0, valid_parents = 0; i < num_parents; i++) {
+		if (parent_names[i]) {
+			parent_names[valid_parents] = parent_names[i];
+			clock->parents[valid_parents] = i;
+			valid_parents++;
+		}
 	}
 
 	/* Register the clock. */
@@ -264,6 +253,53 @@ static void __init cpg_div6_clock_init(struct device_node *np)
 	clock->hw.init = &init;
 
 	clk = clk_register(NULL, &clock->hw);
+	if (IS_ERR(clk))
+		goto free_parents;
+
+	return clk;
+
+free_parents:
+	kfree(clock->parents);
+free_clock:
+	kfree(clock);
+	return clk;
+}
+
+static void __init cpg_div6_clock_init(struct device_node *np)
+{
+	unsigned int num_parents;
+	const char **parent_names;
+	const char *clk_name = np->name;
+	void __iomem *reg;
+	struct clk *clk;
+	unsigned int i;
+
+	num_parents = of_clk_get_parent_count(np);
+	if (num_parents < 1) {
+		pr_err("%s: no parent found for %s DIV6 clock\n",
+		       __func__, np->name);
+		return;
+	}
+
+	parent_names = kmalloc_array(num_parents, sizeof(*parent_names),
+				GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	reg = of_iomap(np, 0);
+	if (reg == NULL) {
+		pr_err("%s: failed to map %s DIV6 clock register\n",
+		       __func__, np->name);
+		goto error;
+	}
+
+	/* Parse the DT properties. */
+	of_property_read_string(np, "clock-output-names", &clk_name);
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(np, i);
+
+	clk = cpg_div6_register(clk_name, num_parents, parent_names, reg);
 	if (IS_ERR(clk)) {
 		pr_err("%s: failed to register %s DIV6 clock (%ld)\n",
 		       __func__, np->name, PTR_ERR(clk));
@@ -276,9 +312,8 @@ static void __init cpg_div6_clock_init(struct device_node *np)
 	return;
 
 error:
-	if (clock->reg)
-		iounmap(clock->reg);
+	if (reg)
+		iounmap(reg);
 	kfree(parent_names);
-	kfree(clock);
 }
 CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init);
diff --git a/drivers/clk/shmobile/clk-div6.h b/drivers/clk/shmobile/clk-div6.h
new file mode 100644
index 000000000000..9a85a95188da
--- /dev/null
+++ b/drivers/clk/shmobile/clk-div6.h
@@ -0,0 +1,7 @@
+#ifndef __SHMOBILE_CLK_DIV6_H__
+#define __SHMOBILE_CLK_DIV6_H__
+
+struct clk *cpg_div6_register(const char *name, unsigned int num_parents,
+			      const char **parent_names, void __iomem *reg);
+
+#endif
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c
index 745496f7ee9c..841977240305 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -115,7 +115,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 	 *
 	 * Using experimental measurements, it seems that no more than
 	 * ~10 iterations are needed, independently of the CPU rate.
-	 * Since this value might be dependant of external xtal rate, pll1
+	 * Since this value might be dependent on external xtal rate, pll1
 	 * rate or even the other emulation clocks rate, use 1000 as a
 	 * "super" safe value.
 	 */
@@ -262,7 +262,7 @@ static struct clk * __init cpg_adsp_clk_register(struct rcar_gen2_cpg *cpg)
  * 1  1  0	30 / 2		x172/2	x208/2	x106
  * 1  1  1	30 / 2		x172/2	x208/2	x88
  *
- * *1 :	Table 7.6 indicates VCO ouput (PLLx = VCO/2)
+ * *1 :	Table 7.6 indicates VCO output (PLLx = VCO/2)
  */
 #define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
 					 (((md) & BIT(13)) >> 12) | \
diff --git a/drivers/clk/shmobile/r8a7795-cpg-mssr.c b/drivers/clk/shmobile/r8a7795-cpg-mssr.c
new file mode 100644
index 000000000000..13e994772dfd
--- /dev/null
+++ b/drivers/clk/shmobile/r8a7795-cpg-mssr.c
@@ -0,0 +1,383 @@
+/*
+ * r8a7795 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015 Glider bvba
+ *
+ * Based on clk-rcar-gen3.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bug.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+
+#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7795_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_EXTALR,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL2,
+	CLK_PLL3,
+	CLK_PLL4,
+	CLK_PLL1_DIV2,
+	CLK_PLL1_DIV4,
+	CLK_S0,
+	CLK_S1,
+	CLK_S2,
+	CLK_S3,
+	CLK_SDSRC,
+	CLK_SSPSRC,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+enum r8a7795_clk_types {
+	CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM,
+	CLK_TYPE_GEN3_PLL0,
+	CLK_TYPE_GEN3_PLL1,
+	CLK_TYPE_GEN3_PLL2,
+	CLK_TYPE_GEN3_PLL3,
+	CLK_TYPE_GEN3_PLL4,
+};
+
+static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",  CLK_EXTAL),
+	DEF_INPUT("extalr", CLK_EXTALR),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+	DEF_BASE(".pll2",       CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+	DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+	DEF_BASE(".pll4",       CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2,     CLK_PLL1,       2, 1),
+	DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4,     CLK_PLL1_DIV2,  2, 1),
+	DEF_FIXED(".s0",        CLK_S0,            CLK_PLL1_DIV2,  2, 1),
+	DEF_FIXED(".s1",        CLK_S1,            CLK_PLL1_DIV2,  3, 1),
+	DEF_FIXED(".s2",        CLK_S2,            CLK_PLL1_DIV2,  4, 1),
+	DEF_FIXED(".s3",        CLK_S3,            CLK_PLL1_DIV2,  6, 1),
+
+	/* Core Clock Outputs */
+	DEF_FIXED("ztr",        R8A7795_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
+	DEF_FIXED("ztrd2",      R8A7795_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+	DEF_FIXED("zt",         R8A7795_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
+	DEF_FIXED("zx",         R8A7795_CLK_ZX,    CLK_PLL1_DIV2,  2, 1),
+	DEF_FIXED("s0d1",       R8A7795_CLK_S0D1,  CLK_S0,         1, 1),
+	DEF_FIXED("s0d4",       R8A7795_CLK_S0D4,  CLK_S0,         4, 1),
+	DEF_FIXED("s1d1",       R8A7795_CLK_S1D1,  CLK_S1,         1, 1),
+	DEF_FIXED("s1d2",       R8A7795_CLK_S1D2,  CLK_S1,         2, 1),
+	DEF_FIXED("s1d4",       R8A7795_CLK_S1D4,  CLK_S1,         4, 1),
+	DEF_FIXED("s2d1",       R8A7795_CLK_S2D1,  CLK_S2,         1, 1),
+	DEF_FIXED("s2d2",       R8A7795_CLK_S2D2,  CLK_S2,         2, 1),
+	DEF_FIXED("s2d4",       R8A7795_CLK_S2D4,  CLK_S2,         4, 1),
+	DEF_FIXED("s3d1",       R8A7795_CLK_S3D1,  CLK_S3,         1, 1),
+	DEF_FIXED("s3d2",       R8A7795_CLK_S3D2,  CLK_S3,         2, 1),
+	DEF_FIXED("s3d4",       R8A7795_CLK_S3D4,  CLK_S3,         4, 1),
+	DEF_FIXED("cl",         R8A7795_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
+	DEF_FIXED("cp",         R8A7795_CLK_CP,    CLK_EXTAL,      2, 1),
+
+	DEF_DIV6P1("mso",       R8A7795_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
+	DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV2, 0x250),
+};
+
+static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
+	DEF_MOD("scif5",		 202,	R8A7795_CLK_S3D4),
+	DEF_MOD("scif4",		 203,	R8A7795_CLK_S3D4),
+	DEF_MOD("scif3",		 204,	R8A7795_CLK_S3D4),
+	DEF_MOD("scif1",		 206,	R8A7795_CLK_S3D4),
+	DEF_MOD("scif0",		 207,	R8A7795_CLK_S3D4),
+	DEF_MOD("msiof3",		 208,	R8A7795_CLK_MSO),
+	DEF_MOD("msiof2",		 209,	R8A7795_CLK_MSO),
+	DEF_MOD("msiof1",		 210,	R8A7795_CLK_MSO),
+	DEF_MOD("msiof0",		 211,	R8A7795_CLK_MSO),
+	DEF_MOD("sys-dmac2",		 217,	R8A7795_CLK_S3D1),
+	DEF_MOD("sys-dmac1",		 218,	R8A7795_CLK_S3D1),
+	DEF_MOD("sys-dmac0",		 219,	R8A7795_CLK_S3D1),
+	DEF_MOD("scif2",		 310,	R8A7795_CLK_S3D4),
+	DEF_MOD("pcie1",		 318,	R8A7795_CLK_S3D1),
+	DEF_MOD("pcie0",		 319,	R8A7795_CLK_S3D1),
+	DEF_MOD("intc-ap",		 408,	R8A7795_CLK_S3D1),
+	DEF_MOD("audmac0",		 502,	R8A7795_CLK_S3D4),
+	DEF_MOD("audmac1",		 501,	R8A7795_CLK_S3D4),
+	DEF_MOD("hscif4",		 516,	R8A7795_CLK_S3D1),
+	DEF_MOD("hscif3",		 517,	R8A7795_CLK_S3D1),
+	DEF_MOD("hscif2",		 518,	R8A7795_CLK_S3D1),
+	DEF_MOD("hscif1",		 519,	R8A7795_CLK_S3D1),
+	DEF_MOD("hscif0",		 520,	R8A7795_CLK_S3D1),
+	DEF_MOD("vspd3",		 620,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspd2",		 621,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspd1",		 622,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspd0",		 623,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspbc",		 624,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspbd",		 626,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspi2",		 629,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspi1",		 630,	R8A7795_CLK_S2D1),
+	DEF_MOD("vspi0",		 631,	R8A7795_CLK_S2D1),
+	DEF_MOD("ehci2",		 701,	R8A7795_CLK_S3D4),
+	DEF_MOD("ehci1",		 702,	R8A7795_CLK_S3D4),
+	DEF_MOD("ehci0",		 703,	R8A7795_CLK_S3D4),
+	DEF_MOD("hsusb",		 704,	R8A7795_CLK_S3D4),
+	DEF_MOD("du3",			 721,	R8A7795_CLK_S2D1),
+	DEF_MOD("du2",			 722,	R8A7795_CLK_S2D1),
+	DEF_MOD("du1",			 723,	R8A7795_CLK_S2D1),
+	DEF_MOD("du0",			 724,	R8A7795_CLK_S2D1),
+	DEF_MOD("hdmi1",		 728,	R8A7795_CLK_HDMI),
+	DEF_MOD("hdmi0",		 729,	R8A7795_CLK_HDMI),
+	DEF_MOD("etheravb",		 812,	R8A7795_CLK_S3D2),
+	DEF_MOD("sata0",		 815,	R8A7795_CLK_S3D2),
+	DEF_MOD("gpio7",		 905,	R8A7795_CLK_CP),
+	DEF_MOD("gpio6",		 906,	R8A7795_CLK_CP),
+	DEF_MOD("gpio5",		 907,	R8A7795_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7795_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7795_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7795_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7795_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7795_CLK_CP),
+	DEF_MOD("i2c6",			 918,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c5",			 919,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c4",			 927,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c3",			 928,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c2",			 929,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c1",			 930,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c0",			 931,	R8A7795_CLK_S3D2),
+	DEF_MOD("ssi-all",		1005,	R8A7795_CLK_S3D4),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7795_CLK_S3D4),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-AP (GIC) */
+};
+
+
+#define CPG_PLL0CR	0x00d8
+#define CPG_PLL2CR	0x002c
+#define CPG_PLL4CR	0x01f4
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL2	PLL3	PLL4
+ * 14 13 19 17	(MHz)
+ *-------------------------------------------------------------------
+ * 0  0  0  0	16.66 x 1	x180	x192	x144	x192	x144
+ * 0  0  0  1	16.66 x 1	x180	x192	x144	x128	x144
+ * 0  0  1  0	Prohibited setting
+ * 0  0  1  1	16.66 x 1	x180	x192	x144	x192	x144
+ * 0  1  0  0	20    x 1	x150	x160	x120	x160	x120
+ * 0  1  0  1	20    x 1	x150	x160	x120	x106	x120
+ * 0  1  1  0	Prohibited setting
+ * 0  1  1  1	20    x 1	x150	x160	x120	x160	x120
+ * 1  0  0  0	25    x 1	x120	x128	x96	x128	x96
+ * 1  0  0  1	25    x 1	x120	x128	x96	x84	x96
+ * 1  0  1  0	Prohibited setting
+ * 1  0  1  1	25    x 1	x120	x128	x96	x128	x96
+ * 1  1  0  0	33.33 / 2	x180	x192	x144	x192	x144
+ * 1  1  0  1	33.33 / 2	x180	x192	x144	x128	x144
+ * 1  1  1  0	Prohibited setting
+ * 1  1  1  1	33.33 / 2	x180	x192	x144	x192	x144
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 11) | \
+					 (((md) & BIT(13)) >> 11) | \
+					 (((md) & BIT(19)) >> 18) | \
+					 (((md) & BIT(17)) >> 17))
+
+struct cpg_pll_config {
+	unsigned int extal_div;
+	unsigned int pll1_mult;
+	unsigned int pll3_mult;
+};
+
+static const struct cpg_pll_config cpg_pll_configs[16] __initconst = {
+	/* EXTAL div	PLL1 mult	PLL3 mult */
+	{ 1,		192,		192,	},
+	{ 1,		192,		128,	},
+	{ 0, /* Prohibited setting */		},
+	{ 1,		192,		192,	},
+	{ 1,		160,		160,	},
+	{ 1,		160,		106,	},
+	{ 0, /* Prohibited setting */		},
+	{ 1,		160,		160,	},
+	{ 1,		128,		128,	},
+	{ 1,		128,		84,	},
+	{ 0, /* Prohibited setting */		},
+	{ 1,		128,		128,	},
+	{ 2,		192,		192,	},
+	{ 2,		192,		128,	},
+	{ 0, /* Prohibited setting */		},
+	{ 2,		192,		192,	},
+};
+
+static const struct cpg_pll_config *cpg_pll_config __initdata;
+
+static
+struct clk * __init r8a7795_cpg_clk_register(struct device *dev,
+					     const struct cpg_core_clk *core,
+					     const struct cpg_mssr_info *info,
+					     struct clk **clks,
+					     void __iomem *base)
+{
+	const struct clk *parent;
+	unsigned int mult = 1;
+	unsigned int div = 1;
+	u32 value;
+
+	parent = clks[core->parent];
+	if (IS_ERR(parent))
+		return ERR_CAST(parent);
+
+	switch (core->type) {
+	case CLK_TYPE_GEN3_MAIN:
+		div = cpg_pll_config->extal_div;
+		break;
+
+	case CLK_TYPE_GEN3_PLL0:
+		/*
+		 * PLL0 is a configurable multiplier clock. Register it as a
+		 * fixed factor clock for now as there's no generic multiplier
+		 * clock implementation and we currently have no need to change
+		 * the multiplier value.
+		 */
+		value = readl(base + CPG_PLL0CR);
+		mult = (((value >> 24) & 0x7f) + 1) * 2;
+		break;
+
+	case CLK_TYPE_GEN3_PLL1:
+		mult = cpg_pll_config->pll1_mult;
+		break;
+
+	case CLK_TYPE_GEN3_PLL2:
+		/*
+		 * PLL2 is a configurable multiplier clock. Register it as a
+		 * fixed factor clock for now as there's no generic multiplier
+		 * clock implementation and we currently have no need to change
+		 * the multiplier value.
+		 */
+		value = readl(base + CPG_PLL2CR);
+		mult = (((value >> 24) & 0x7f) + 1) * 2;
+		break;
+
+	case CLK_TYPE_GEN3_PLL3:
+		mult = cpg_pll_config->pll3_mult;
+		break;
+
+	case CLK_TYPE_GEN3_PLL4:
+		/*
+		 * PLL4 is a configurable multiplier clock. Register it as a
+		 * fixed factor clock for now as there's no generic multiplier
+		 * clock implementation and we currently have no need to change
+		 * the multiplier value.
+		 */
+		value = readl(base + CPG_PLL4CR);
+		mult = (((value >> 24) & 0x7f) + 1) * 2;
+		break;
+
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	return clk_register_fixed_factor(NULL, core->name,
+					 __clk_get_name(parent), 0, mult, div);
+}
+
+/*
+ * Reset register definitions.
+ */
+#define MODEMR	0xe6160060
+
+static u32 rcar_gen3_read_mode_pins(void)
+{
+	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+	u32 mode;
+
+	BUG_ON(!modemr);
+	mode = ioread32(modemr);
+	iounmap(modemr);
+
+	return mode;
+}
+
+static int __init r8a7795_cpg_mssr_init(struct device *dev)
+{
+	u32 cpg_mode = rcar_gen3_read_mode_pins();
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+	if (!cpg_pll_config->extal_div) {
+		dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7795_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7795_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7795_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7795_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7795_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7795_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7795_cpg_mssr_init,
+	.cpg_clk_register = r8a7795_cpg_clk_register,
+};
diff --git a/drivers/clk/shmobile/renesas-cpg-mssr.c b/drivers/clk/shmobile/renesas-cpg-mssr.c
new file mode 100644
index 000000000000..9a4d888164bb
--- /dev/null
+++ b/drivers/clk/shmobile/renesas-cpg-mssr.c
@@ -0,0 +1,596 @@
+/*
+ * Renesas Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015 Glider bvba
+ *
+ * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "clk-div6.h"
+
+#ifdef DEBUG
+#define WARN_DEBUG(x)	do { } while (0)
+#else
+#define WARN_DEBUG(x)	WARN_ON(x)
+#endif
+
+
+/*
+ * Module Standby and Software Reset register offets.
+ *
+ * If the registers exist, these are valid for SH-Mobile, R-Mobile,
+ * R-Car Gen 2, and R-Car Gen 3.
+ * These are NOT valid for R-Car Gen1 and RZ/A1!
+ */
+
+/*
+ * Module Stop Status Register offsets
+ */
+
+static const u16 mstpsr[] = {
+	0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4,
+	0x9A0, 0x9A4, 0x9A8, 0x9AC,
+};
+
+#define	MSTPSR(i)	mstpsr[i]
+
+
+/*
+ * System Module Stop Control Register offsets
+ */
+
+static const u16 smstpcr[] = {
+	0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C,
+	0x990, 0x994, 0x998, 0x99C,
+};
+
+#define	SMSTPCR(i)	smstpcr[i]
+
+
+/*
+ * Software Reset Register offsets
+ */
+
+static const u16 srcr[] = {
+	0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC,
+	0x920, 0x924, 0x928, 0x92C,
+};
+
+#define	SRCR(i)		srcr[i]
+
+
+/* Realtime Module Stop Control Register offsets */
+#define RMSTPCR(i)	(smstpcr[i] - 0x20)
+
+/* Modem Module Stop Control Register offsets (r8a73a4) */
+#define MMSTPCR(i)	(smstpcr[i] + 0x20)
+
+/* Software Reset Clearing Register offsets */
+#define	SRSTCLR(i)	(0x940 + (i) * 4)
+
+
+/**
+ * Clock Pulse Generator / Module Standby and Software Reset Private Data
+ *
+ * @dev: CPG/MSSR device
+ * @base: CPG/MSSR register block base address
+ * @mstp_lock: protects writes to SMSTPCR
+ * @clks: Array containing all Core and Module Clocks
+ * @num_core_clks: Number of Core Clocks in clks[]
+ * @num_mod_clks: Number of Module Clocks in clks[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ */
+struct cpg_mssr_priv {
+	struct device *dev;
+	void __iomem *base;
+	spinlock_t mstp_lock;
+
+	struct clk **clks;
+	unsigned int num_core_clks;
+	unsigned int num_mod_clks;
+	unsigned int last_dt_core_clk;
+};
+
+
+/**
+ * struct mstp_clock - MSTP gating clock
+ * @hw: handle between common and hardware-specific interfaces
+ * @index: MSTP clock number
+ * @priv: CPG/MSSR private data
+ */
+struct mstp_clock {
+	struct clk_hw hw;
+	u32 index;
+	struct cpg_mssr_priv *priv;
+};
+
+#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
+
+static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
+{
+	struct mstp_clock *clock = to_mstp_clock(hw);
+	struct cpg_mssr_priv *priv = clock->priv;
+	unsigned int reg = clock->index / 32;
+	unsigned int bit = clock->index % 32;
+	struct device *dev = priv->dev;
+	u32 bitmask = BIT(bit);
+	unsigned long flags;
+	unsigned int i;
+	u32 value;
+
+	dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
+		enable ? "ON" : "OFF");
+	spin_lock_irqsave(&priv->mstp_lock, flags);
+
+	value = clk_readl(priv->base + SMSTPCR(reg));
+	if (enable)
+		value &= ~bitmask;
+	else
+		value |= bitmask;
+	clk_writel(value, priv->base + SMSTPCR(reg));
+
+	spin_unlock_irqrestore(&priv->mstp_lock, flags);
+
+	if (!enable)
+		return 0;
+
+	for (i = 1000; i > 0; --i) {
+		if (!(clk_readl(priv->base + MSTPSR(reg)) &
+		      bitmask))
+			break;
+		cpu_relax();
+	}
+
+	if (!i) {
+		dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
+			priv->base + SMSTPCR(reg), bit);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int cpg_mstp_clock_enable(struct clk_hw *hw)
+{
+	return cpg_mstp_clock_endisable(hw, true);
+}
+
+static void cpg_mstp_clock_disable(struct clk_hw *hw)
+{
+	cpg_mstp_clock_endisable(hw, false);
+}
+
+static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
+{
+	struct mstp_clock *clock = to_mstp_clock(hw);
+	struct cpg_mssr_priv *priv = clock->priv;
+	u32 value;
+
+	value = clk_readl(priv->base + MSTPSR(clock->index / 32));
+
+	return !(value & BIT(clock->index % 32));
+}
+
+static const struct clk_ops cpg_mstp_clock_ops = {
+	.enable = cpg_mstp_clock_enable,
+	.disable = cpg_mstp_clock_disable,
+	.is_enabled = cpg_mstp_clock_is_enabled,
+};
+
+static
+struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
+					 void *data)
+{
+	unsigned int clkidx = clkspec->args[1];
+	struct cpg_mssr_priv *priv = data;
+	struct device *dev = priv->dev;
+	unsigned int idx;
+	const char *type;
+	struct clk *clk;
+
+	switch (clkspec->args[0]) {
+	case CPG_CORE:
+		type = "core";
+		if (clkidx > priv->last_dt_core_clk) {
+			dev_err(dev, "Invalid %s clock index %u\n", type,
+			       clkidx);
+			return ERR_PTR(-EINVAL);
+		}
+		clk = priv->clks[clkidx];
+		break;
+
+	case CPG_MOD:
+		type = "module";
+		idx = MOD_CLK_PACK(clkidx);
+		if (clkidx % 100 > 31 || idx >= priv->num_mod_clks) {
+			dev_err(dev, "Invalid %s clock index %u\n", type,
+				clkidx);
+			return ERR_PTR(-EINVAL);
+		}
+		clk = priv->clks[priv->num_core_clks + idx];
+		break;
+
+	default:
+		dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (IS_ERR(clk))
+		dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
+		       PTR_ERR(clk));
+	else
+		dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n",
+			clkspec->args[0], clkspec->args[1], clk, clk);
+	return clk;
+}
+
+static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
+					      const struct cpg_mssr_info *info,
+					      struct cpg_mssr_priv *priv)
+{
+	struct clk *clk = NULL, *parent;
+	struct device *dev = priv->dev;
+	unsigned int id = core->id;
+	const char *parent_name;
+
+	WARN_DEBUG(id >= priv->num_core_clks);
+	WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+	switch (core->type) {
+	case CLK_TYPE_IN:
+		clk = of_clk_get_by_name(priv->dev->of_node, core->name);
+		break;
+
+	case CLK_TYPE_FF:
+	case CLK_TYPE_DIV6P1:
+		WARN_DEBUG(core->parent >= priv->num_core_clks);
+		parent = priv->clks[core->parent];
+		if (IS_ERR(parent)) {
+			clk = parent;
+			goto fail;
+		}
+
+		parent_name = __clk_get_name(parent);
+		if (core->type == CLK_TYPE_FF) {
+			clk = clk_register_fixed_factor(NULL, core->name,
+							parent_name, 0,
+							core->mult, core->div);
+		} else {
+			clk = cpg_div6_register(core->name, 1, &parent_name,
+						priv->base + core->offset);
+		}
+		break;
+
+	default:
+		if (info->cpg_clk_register)
+			clk = info->cpg_clk_register(dev, core, info,
+						     priv->clks, priv->base);
+		else
+			dev_err(dev, "%s has unsupported core clock type %u\n",
+				core->name, core->type);
+		break;
+	}
+
+	if (IS_ERR_OR_NULL(clk))
+		goto fail;
+
+	dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk);
+	priv->clks[id] = clk;
+	return;
+
+fail:
+	dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,",
+		core->name, PTR_ERR(clk));
+}
+
+static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
+					     const struct cpg_mssr_info *info,
+					     struct cpg_mssr_priv *priv)
+{
+	struct mstp_clock *clock = NULL;
+	struct device *dev = priv->dev;
+	unsigned int id = mod->id;
+	struct clk_init_data init;
+	struct clk *parent, *clk;
+	const char *parent_name;
+	unsigned int i;
+
+	WARN_DEBUG(id < priv->num_core_clks);
+	WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
+	WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
+	WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+	parent = priv->clks[mod->parent];
+	if (IS_ERR(parent)) {
+		clk = parent;
+		goto fail;
+	}
+
+	clock = kzalloc(sizeof(*clock), GFP_KERNEL);
+	if (!clock) {
+		clk = ERR_PTR(-ENOMEM);
+		goto fail;
+	}
+
+	init.name = mod->name;
+	init.ops = &cpg_mstp_clock_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	for (i = 0; i < info->num_crit_mod_clks; i++)
+		if (id == info->crit_mod_clks[i]) {
+#ifdef CLK_ENABLE_HAND_OFF
+			dev_dbg(dev, "MSTP %s setting CLK_ENABLE_HAND_OFF\n",
+				mod->name);
+			init.flags |= CLK_ENABLE_HAND_OFF;
+			break;
+#else
+			dev_dbg(dev, "Ignoring MSTP %s to prevent disabling\n",
+				mod->name);
+			return;
+#endif
+		}
+
+	parent_name = __clk_get_name(parent);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clock->index = id - priv->num_core_clks;
+	clock->priv = priv;
+	clock->hw.init = &init;
+
+	clk = clk_register(NULL, &clock->hw);
+	if (IS_ERR(clk))
+		goto fail;
+
+	dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk);
+	priv->clks[id] = clk;
+	return;
+
+fail:
+	dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,",
+		mod->name, PTR_ERR(clk));
+	kfree(clock);
+}
+
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+struct cpg_mssr_clk_domain {
+	struct generic_pm_domain genpd;
+	struct device_node *np;
+	unsigned int num_core_pm_clks;
+	unsigned int core_pm_clks[0];
+};
+
+static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
+			       struct cpg_mssr_clk_domain *pd)
+{
+	unsigned int i;
+
+	if (clkspec->np != pd->np || clkspec->args_count != 2)
+		return false;
+
+	switch (clkspec->args[0]) {
+	case CPG_CORE:
+		for (i = 0; i < pd->num_core_pm_clks; i++)
+			if (clkspec->args[1] == pd->core_pm_clks[i])
+				return true;
+		return false;
+
+	case CPG_MOD:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd,
+			       struct device *dev)
+{
+	struct cpg_mssr_clk_domain *pd =
+		container_of(genpd, struct cpg_mssr_clk_domain, genpd);
+	struct device_node *np = dev->of_node;
+	struct of_phandle_args clkspec;
+	struct clk *clk;
+	int i = 0;
+	int error;
+
+	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+					   &clkspec)) {
+		if (cpg_mssr_is_pm_clk(&clkspec, pd))
+			goto found;
+
+		of_node_put(clkspec.np);
+		i++;
+	}
+
+	return 0;
+
+found:
+	clk = of_clk_get_from_provider(&clkspec);
+	of_node_put(clkspec.np);
+
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	error = pm_clk_create(dev);
+	if (error) {
+		dev_err(dev, "pm_clk_create failed %d\n", error);
+		goto fail_put;
+	}
+
+	error = pm_clk_add_clk(dev, clk);
+	if (error) {
+		dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error);
+		goto fail_destroy;
+	}
+
+	return 0;
+
+fail_destroy:
+	pm_clk_destroy(dev);
+fail_put:
+	clk_put(clk);
+	return error;
+}
+
+static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd,
+				struct device *dev)
+{
+	if (!list_empty(&dev->power.subsys_data->clock_list))
+		pm_clk_destroy(dev);
+}
+
+static int __init cpg_mssr_add_clk_domain(struct device *dev,
+					  const unsigned int *core_pm_clks,
+					  unsigned int num_core_pm_clks)
+{
+	struct device_node *np = dev->of_node;
+	struct generic_pm_domain *genpd;
+	struct cpg_mssr_clk_domain *pd;
+	size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
+
+	pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
+	if (!pd)
+		return -ENOMEM;
+
+	pd->np = np;
+	pd->num_core_pm_clks = num_core_pm_clks;
+	memcpy(pd->core_pm_clks, core_pm_clks, pm_size);
+
+	genpd = &pd->genpd;
+	genpd->name = np->name;
+	genpd->flags = GENPD_FLAG_PM_CLK;
+	pm_genpd_init(genpd, &simple_qos_governor, false);
+	genpd->attach_dev = cpg_mssr_attach_dev;
+	genpd->detach_dev = cpg_mssr_detach_dev;
+
+	of_genpd_add_provider_simple(np, genpd);
+	return 0;
+}
+#else
+static inline int cpg_mssr_add_clk_domain(struct device *dev,
+					  const unsigned int *core_pm_clks,
+					  unsigned int num_core_pm_clks)
+{
+	return 0;
+}
+#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
+
+
+static const struct of_device_id cpg_mssr_match[] = {
+#ifdef CONFIG_ARCH_R8A7795
+	{
+		.compatible = "renesas,r8a7795-cpg-mssr",
+		.data = &r8a7795_cpg_mssr_info,
+	},
+#endif
+	{ /* sentinel */ }
+};
+
+static void cpg_mssr_del_clk_provider(void *data)
+{
+	of_clk_del_provider(data);
+}
+
+static int __init cpg_mssr_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct cpg_mssr_info *info;
+	struct cpg_mssr_priv *priv;
+	unsigned int nclks, i;
+	struct resource *res;
+	struct clk **clks;
+	int error;
+
+	info = of_match_node(cpg_mssr_match, np)->data;
+	if (info->init) {
+		error = info->init(dev);
+		if (error)
+			return error;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	spin_lock_init(&priv->mstp_lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	nclks = info->num_total_core_clks + info->num_hw_mod_clks;
+	clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL);
+	if (!clks)
+		return -ENOMEM;
+
+	priv->clks = clks;
+	priv->num_core_clks = info->num_total_core_clks;
+	priv->num_mod_clks = info->num_hw_mod_clks;
+	priv->last_dt_core_clk = info->last_dt_core_clk;
+
+	for (i = 0; i < nclks; i++)
+		clks[i] = ERR_PTR(-ENOENT);
+
+	for (i = 0; i < info->num_core_clks; i++)
+		cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
+
+	for (i = 0; i < info->num_mod_clks; i++)
+		cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv);
+
+	error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
+	if (error)
+		return error;
+
+	devm_add_action(dev, cpg_mssr_del_clk_provider, np);
+
+	error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
+					info->num_core_pm_clks);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static struct platform_driver cpg_mssr_driver = {
+	.driver		= {
+		.name	= "renesas-cpg-mssr",
+		.of_match_table = cpg_mssr_match,
+	},
+};
+
+static int __init cpg_mssr_init(void)
+{
+	return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe);
+}
+
+subsys_initcall(cpg_mssr_init);
+
+MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/shmobile/renesas-cpg-mssr.h b/drivers/clk/shmobile/renesas-cpg-mssr.h
new file mode 100644
index 000000000000..e09f03cbf086
--- /dev/null
+++ b/drivers/clk/shmobile/renesas-cpg-mssr.h
@@ -0,0 +1,132 @@
+/*
+ * Renesas Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015 Glider bvba
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_CPG_MSSR_H__
+#define __CLK_RENESAS_CPG_MSSR_H__
+
+    /*
+     * Definitions of CPG Core Clocks
+     *
+     * These include:
+     *   - Clock outputs exported to DT
+     *   - External input clocks
+     *   - Internal CPG clocks
+     */
+
+struct cpg_core_clk {
+	/* Common */
+	const char *name;
+	unsigned int id;
+	unsigned int type;
+	/* Depending on type */
+	unsigned int parent;	/* Core Clocks only */
+	unsigned int div;
+	unsigned int mult;
+	unsigned int offset;
+};
+
+enum clk_types {
+	/* Generic */
+	CLK_TYPE_IN,		/* External Clock Input */
+	CLK_TYPE_FF,		/* Fixed Factor Clock */
+	CLK_TYPE_DIV6P1,	/* DIV6 Clock with 1 parent clock */
+
+	/* Custom definitions start here */
+	CLK_TYPE_CUSTOM,
+};
+
+#define DEF_TYPE(_name, _id, _type...)	\
+	{ .name = _name, .id = _id, .type = _type }
+#define DEF_BASE(_name, _id, _type, _parent...)	\
+	DEF_TYPE(_name, _id, _type, .parent = _parent)
+
+#define DEF_INPUT(_name, _id) \
+	DEF_TYPE(_name, _id, CLK_TYPE_IN)
+#define DEF_FIXED(_name, _id, _parent, _div, _mult)	\
+	DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
+#define DEF_DIV6P1(_name, _id, _parent, _offset)	\
+	DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
+
+
+    /*
+     * Definitions of Module Clocks
+     */
+
+struct mssr_mod_clk {
+	const char *name;
+	unsigned int id;
+	unsigned int parent;	/* Add MOD_CLK_BASE for Module Clocks */
+};
+
+/* Convert from sparse base-100 to packed index space */
+#define MOD_CLK_PACK(x)	((x) - ((x) / 100) * (100 - 32))
+
+#define MOD_CLK_ID(x)	(MOD_CLK_BASE + MOD_CLK_PACK(x))
+
+#define DEF_MOD(_name, _mod, _parent...)	\
+	{ .name = _name, .id = MOD_CLK_ID(_mod), .parent = _parent }
+
+
+struct device_node;
+
+    /**
+     * SoC-specific CPG/MSSR Description
+     *
+     * @core_clks: Array of Core Clock definitions
+     * @num_core_clks: Number of entries in core_clks[]
+     * @last_dt_core_clk: ID of the last Core Clock exported to DT
+     * @num_total_core_clks: Total number of Core Clocks (exported + internal)
+     *
+     * @mod_clks: Array of Module Clock definitions
+     * @num_mod_clks: Number of entries in mod_clks[]
+     * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
+     *
+     * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
+     *                 should not be disabled without a knowledgeable driver
+     * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
+     *
+     * @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power
+     *                Management, in addition to Module Clocks
+     * @num_core_pm_clks: Number of entries in core_pm_clks[]
+     *
+     * @init: Optional callback to perform SoC-specific initialization
+     * @cpg_clk_register: Optional callback to handle special Core Clock types
+     */
+
+struct cpg_mssr_info {
+	/* Core Clocks */
+	const struct cpg_core_clk *core_clks;
+	unsigned int num_core_clks;
+	unsigned int last_dt_core_clk;
+	unsigned int num_total_core_clks;
+
+	/* Module Clocks */
+	const struct mssr_mod_clk *mod_clks;
+	unsigned int num_mod_clks;
+	unsigned int num_hw_mod_clks;
+
+	/* Critical Module Clocks that should not be disabled */
+	const unsigned int *crit_mod_clks;
+	unsigned int num_crit_mod_clks;
+
+	/* Core Clocks suitable for PM, in addition to the Module Clocks */
+	const unsigned int *core_pm_clks;
+	unsigned int num_core_pm_clks;
+
+	/* Callbacks */
+	int (*init)(struct device *dev);
+	struct clk *(*cpg_clk_register)(struct device *dev,
+					const struct cpg_core_clk *core,
+					const struct cpg_mssr_info *info,
+					struct clk **clks, void __iomem *base);
+};
+
+extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
+#endif
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index 576cd0354d48..ccb324d97160 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -549,19 +549,20 @@ static int clk_fs660c32_vco_get_params(unsigned long input,
 	return 0;
 }
 
-static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate
-		, unsigned long *prate)
+static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw,
+					   unsigned long rate,
+					   unsigned long *prate)
 {
 	struct stm_fs params;
 
-	if (!clk_fs660c32_vco_get_params(*prate, rate, &params))
-		clk_fs660c32_vco_get_rate(*prate, &params, &rate);
+	if (clk_fs660c32_vco_get_params(*prate, rate, &params))
+		return rate;
 
-	pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
+	clk_fs660c32_vco_get_rate(*prate, &params, &rate);
+
+	pr_debug("%s: %s new rate %ld [ndiv=%u]\n",
 		 __func__, clk_hw_get_name(hw),
-		 rate, (unsigned int)params.sdiv,
-		 (unsigned int)params.mdiv,
-		 (unsigned int)params.pe, (unsigned int)params.nsdiv);
+		 rate, (unsigned int)params.ndiv);
 
 	return rate;
 }
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index cb4c299214ce..3fd7901d48e4 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -7,14 +7,19 @@ obj-y += clk-a10-codec.o
 obj-y += clk-a10-hosc.o
 obj-y += clk-a10-mod1.o
 obj-y += clk-a10-pll2.o
+obj-y += clk-a10-ve.o
 obj-y += clk-a20-gmac.o
 obj-y += clk-mod0.o
 obj-y += clk-simple-gates.o
+obj-y += clk-sun8i-bus-gates.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
 obj-y += clk-sun9i-mmc.o
 obj-y += clk-usb.o
 
+obj-$(CONFIG_MACH_SUN9I) += clk-sun8i-apb0.o
+obj-$(CONFIG_MACH_SUN9I) += clk-sun9i-cpus.o
+
 obj-$(CONFIG_MFD_SUN6I_PRCM) += \
 	clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
 	clk-sun8i-apb0.o
diff --git a/drivers/clk/sunxi/clk-a10-ve.c b/drivers/clk/sunxi/clk-a10-ve.c
new file mode 100644
index 000000000000..044c1717b762
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-ve.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2015 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(ve_lock);
+
+#define SUN4I_VE_ENABLE		31
+#define SUN4I_VE_DIVIDER_SHIFT	16
+#define SUN4I_VE_DIVIDER_WIDTH	3
+#define SUN4I_VE_RESET		0
+
+/**
+ * sunxi_ve_reset... - reset bit in ve clk registers handling
+ */
+
+struct ve_reset_data {
+	void __iomem			*reg;
+	spinlock_t			*lock;
+	struct reset_controller_dev	rcdev;
+};
+
+static int sunxi_ve_reset_assert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	struct ve_reset_data *data = container_of(rcdev,
+						  struct ve_reset_data,
+						  rcdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(data->lock, flags);
+
+	reg = readl(data->reg);
+	writel(reg & ~BIT(SUN4I_VE_RESET), data->reg);
+
+	spin_unlock_irqrestore(data->lock, flags);
+
+	return 0;
+}
+
+static int sunxi_ve_reset_deassert(struct reset_controller_dev *rcdev,
+				   unsigned long id)
+{
+	struct ve_reset_data *data = container_of(rcdev,
+						  struct ve_reset_data,
+						  rcdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(data->lock, flags);
+
+	reg = readl(data->reg);
+	writel(reg | BIT(SUN4I_VE_RESET), data->reg);
+
+	spin_unlock_irqrestore(data->lock, flags);
+
+	return 0;
+}
+
+static int sunxi_ve_of_xlate(struct reset_controller_dev *rcdev,
+			     const struct of_phandle_args *reset_spec)
+{
+	if (WARN_ON(reset_spec->args_count != 0))
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct reset_control_ops sunxi_ve_reset_ops = {
+	.assert		= sunxi_ve_reset_assert,
+	.deassert	= sunxi_ve_reset_deassert,
+};
+
+static void __init sun4i_ve_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	struct clk_divider *div;
+	struct clk_gate *gate;
+	struct ve_reset_data *reset_data;
+	const char *parent;
+	const char *clk_name = node->name;
+	void __iomem *reg;
+	int err;
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg))
+		return;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		goto err_unmap;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		goto err_free_div;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+	parent = of_clk_get_parent_name(node, 0);
+
+	gate->reg = reg;
+	gate->bit_idx = SUN4I_VE_ENABLE;
+	gate->lock = &ve_lock;
+
+	div->reg = reg;
+	div->shift = SUN4I_VE_DIVIDER_SHIFT;
+	div->width = SUN4I_VE_DIVIDER_WIDTH;
+	div->lock = &ve_lock;
+
+	clk = clk_register_composite(NULL, clk_name, &parent, 1,
+				     NULL, NULL,
+				     &div->hw, &clk_divider_ops,
+				     &gate->hw, &clk_gate_ops,
+				     CLK_SET_RATE_PARENT);
+	if (IS_ERR(clk))
+		goto err_free_gate;
+
+	err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (err)
+		goto err_unregister_clk;
+
+	reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
+	if (!reset_data)
+		goto err_del_provider;
+
+	reset_data->reg = reg;
+	reset_data->lock = &ve_lock;
+	reset_data->rcdev.nr_resets = 1;
+	reset_data->rcdev.ops = &sunxi_ve_reset_ops;
+	reset_data->rcdev.of_node = node;
+	reset_data->rcdev.of_xlate = sunxi_ve_of_xlate;
+	reset_data->rcdev.of_reset_n_cells = 0;
+	err = reset_controller_register(&reset_data->rcdev);
+	if (err)
+		goto err_free_reset;
+
+	return;
+
+err_free_reset:
+	kfree(reset_data);
+err_del_provider:
+	of_clk_del_provider(node);
+err_unregister_clk:
+	clk_unregister(clk);
+err_free_gate:
+	kfree(gate);
+err_free_div:
+	kfree(div);
+err_unmap:
+	iounmap(reg);
+}
+CLK_OF_DECLARE(sun4i_ve, "allwinner,sun4i-a10-ve-clk",
+	       sun4i_ve_clk_setup);
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
index 0214c6548afd..f4da52b5ca0e 100644
--- a/drivers/clk/sunxi/clk-simple-gates.c
+++ b/drivers/clk/sunxi/clk-simple-gates.c
@@ -140,6 +140,8 @@ CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-gates-clk",
 	       sunxi_simple_gates_init);
 CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-gates-clk",
 	       sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_apbs, "allwinner,sun9i-a80-apbs-gates-clk",
+	       sunxi_simple_gates_init);
 
 static const int sun4i_a10_ahb_critical_clocks[] __initconst = {
 	14,	/* ahb_sdram */
@@ -158,3 +160,15 @@ CLK_OF_DECLARE(sun5i_a13_ahb, "allwinner,sun5i-a13-ahb-gates-clk",
 	       sun4i_a10_ahb_init);
 CLK_OF_DECLARE(sun7i_a20_ahb, "allwinner,sun7i-a20-ahb-gates-clk",
 	       sun4i_a10_ahb_init);
+
+static const int sun4i_a10_dram_critical_clocks[] __initconst = {
+	15,	/* dram_output */
+};
+
+static void __init sun4i_a10_dram_init(struct device_node *node)
+{
+	sunxi_simple_gates_setup(node, sun4i_a10_dram_critical_clocks,
+				 ARRAY_SIZE(sun4i_a10_dram_critical_clocks));
+}
+CLK_OF_DECLARE(sun4i_a10_dram, "allwinner,sun4i-a10-dram-gates-clk",
+	       sun4i_a10_dram_init);
diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c
index 7ae5d2c2cde1..7ba61103a6f5 100644
--- a/drivers/clk/sunxi/clk-sun8i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun8i-apb0.c
@@ -17,13 +17,77 @@
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 
+static struct clk *sun8i_a23_apb0_register(struct device_node *node,
+					   void __iomem *reg)
+{
+	const char *clk_name = node->name;
+	const char *clk_parent;
+	struct clk *clk;
+	int ret;
+
+	clk_parent = of_clk_get_parent_name(node, 0);
+	if (!clk_parent)
+		return ERR_PTR(-EINVAL);
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	/* The A23 APB0 clock is a standard 2 bit wide divider clock */
+	clk = clk_register_divider(NULL, clk_name, clk_parent, 0, reg,
+				   0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
+	if (IS_ERR(clk))
+		return clk;
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (ret)
+		goto err_unregister;
+
+	return clk;
+
+err_unregister:
+	clk_unregister_divider(clk);
+
+	return ERR_PTR(ret);
+}
+
+static void sun8i_a23_apb0_setup(struct device_node *node)
+{
+	void __iomem *reg;
+	struct resource res;
+	struct clk *clk;
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		/*
+		 * This happens with clk nodes instantiated through mfd,
+		 * as those do not have their resources assigned in the
+		 * device tree. Do not print an error in this case.
+		 */
+		if (PTR_ERR(reg) != -EINVAL)
+			pr_err("Could not get registers for a23-apb0-clk\n");
+
+		return;
+	}
+
+	clk = sun8i_a23_apb0_register(node, reg);
+	if (IS_ERR(clk))
+		goto err_unmap;
+
+	return;
+
+err_unmap:
+	iounmap(reg);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+}
+CLK_OF_DECLARE(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk",
+	       sun8i_a23_apb0_setup);
+
 static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	const char *clk_name = np->name;
-	const char *clk_parent;
 	struct resource *r;
 	void __iomem *reg;
 	struct clk *clk;
@@ -33,19 +97,11 @@ static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
 	if (IS_ERR(reg))
 		return PTR_ERR(reg);
 
-	clk_parent = of_clk_get_parent_name(np, 0);
-	if (!clk_parent)
-		return -EINVAL;
-
-	of_property_read_string(np, "clock-output-names", &clk_name);
-
-	/* The A23 APB0 clock is a standard 2 bit wide divider clock */
-	clk = clk_register_divider(&pdev->dev, clk_name, clk_parent, 0, reg,
-				   0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
+	clk = sun8i_a23_apb0_register(np, reg);
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
-	return of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	return 0;
 }
 
 static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c
new file mode 100644
index 000000000000..e32d18ba252b
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 Jens Kuske <jenskuske@gmail.com>
+ *
+ * Based on clk-simple-gates.c, which is:
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(gates_lock);
+
+static void __init sun8i_h3_bus_gates_init(struct device_node *node)
+{
+	static const char * const names[] = { "ahb1", "ahb2", "apb1", "apb2" };
+	enum { AHB1, AHB2, APB1, APB2, PARENT_MAX } clk_parent;
+	const char *parents[PARENT_MAX];
+	struct clk_onecell_data *clk_data;
+	const char *clk_name;
+	struct property *prop;
+	struct resource res;
+	void __iomem *clk_reg;
+	void __iomem *reg;
+	const __be32 *p;
+	int number, i;
+	u8 clk_bit;
+	int index;
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(names); i++) {
+		int idx = of_property_match_string(node, "clock-names",
+						   names[i]);
+		if (idx < 0)
+			return;
+
+		parents[i] = of_clk_get_parent_name(node, idx);
+	}
+
+	clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err_unmap;
+
+	number = of_property_count_u32_elems(node, "clock-indices");
+	of_property_read_u32_index(node, "clock-indices", number - 1, &number);
+
+	clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err_free_data;
+
+	i = 0;
+	of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+		of_property_read_string_index(node, "clock-output-names",
+					      i, &clk_name);
+
+		if (index == 17 || (index >= 29 && index <= 31))
+			clk_parent = AHB2;
+		else if (index <= 63 || index >= 128)
+			clk_parent = AHB1;
+		else if (index >= 64 && index <= 95)
+			clk_parent = APB1;
+		else if (index >= 96 && index <= 127)
+			clk_parent = APB2;
+
+		clk_reg = reg + 4 * (index / 32);
+		clk_bit = index % 32;
+
+		clk_data->clks[index] = clk_register_gate(NULL, clk_name,
+							  parents[clk_parent],
+							  0, clk_reg, clk_bit,
+							  0, &gates_lock);
+		i++;
+
+		if (IS_ERR(clk_data->clks[index])) {
+			WARN_ON(true);
+			continue;
+		}
+	}
+
+	clk_data->clk_num = number + 1;
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return;
+
+err_free_data:
+	kfree(clk_data);
+err_unmap:
+	iounmap(reg);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+}
+
+CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk",
+	       sun8i_h3_bus_gates_init);
diff --git a/drivers/clk/sunxi/clk-sun9i-cpus.c b/drivers/clk/sunxi/clk-sun9i-cpus.c
new file mode 100644
index 000000000000..7626d2194b96
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun9i-cpus.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2015 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * Allwinner A80 CPUS clock driver
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+static DEFINE_SPINLOCK(sun9i_a80_cpus_lock);
+
+/**
+ * sun9i_a80_cpus_clk_setup() - Setup function for a80 cpus composite clk
+ */
+
+#define SUN9I_CPUS_MAX_PARENTS		4
+#define SUN9I_CPUS_MUX_PARENT_PLL4	3
+#define SUN9I_CPUS_MUX_SHIFT		16
+#define SUN9I_CPUS_MUX_MASK		GENMASK(17, 16)
+#define SUN9I_CPUS_MUX_GET_PARENT(reg)	((reg & SUN9I_CPUS_MUX_MASK) >> \
+						SUN9I_CPUS_MUX_SHIFT)
+
+#define SUN9I_CPUS_DIV_SHIFT		4
+#define SUN9I_CPUS_DIV_MASK		GENMASK(5, 4)
+#define SUN9I_CPUS_DIV_GET(reg)		((reg & SUN9I_CPUS_DIV_MASK) >> \
+						SUN9I_CPUS_DIV_SHIFT)
+#define SUN9I_CPUS_DIV_SET(reg, div)	((reg & ~SUN9I_CPUS_DIV_MASK) | \
+						(div << SUN9I_CPUS_DIV_SHIFT))
+#define SUN9I_CPUS_PLL4_DIV_SHIFT	8
+#define SUN9I_CPUS_PLL4_DIV_MASK	GENMASK(12, 8)
+#define SUN9I_CPUS_PLL4_DIV_GET(reg)	((reg & SUN9I_CPUS_PLL4_DIV_MASK) >> \
+						SUN9I_CPUS_PLL4_DIV_SHIFT)
+#define SUN9I_CPUS_PLL4_DIV_SET(reg, div) ((reg & ~SUN9I_CPUS_PLL4_DIV_MASK) | \
+						(div << SUN9I_CPUS_PLL4_DIV_SHIFT))
+
+struct sun9i_a80_cpus_clk {
+	struct clk_hw hw;
+	void __iomem *reg;
+};
+
+#define to_sun9i_a80_cpus_clk(_hw) container_of(_hw, struct sun9i_a80_cpus_clk, hw)
+
+static unsigned long sun9i_a80_cpus_clk_recalc_rate(struct clk_hw *hw,
+						    unsigned long parent_rate)
+{
+	struct sun9i_a80_cpus_clk *cpus = to_sun9i_a80_cpus_clk(hw);
+	unsigned long rate;
+	u32 reg;
+
+	/* Fetch the register value */
+	reg = readl(cpus->reg);
+
+	/* apply pre-divider first if parent is pll4 */
+	if (SUN9I_CPUS_MUX_GET_PARENT(reg) == SUN9I_CPUS_MUX_PARENT_PLL4)
+		parent_rate /= SUN9I_CPUS_PLL4_DIV_GET(reg) + 1;
+
+	/* clk divider */
+	rate = parent_rate / (SUN9I_CPUS_DIV_GET(reg) + 1);
+
+	return rate;
+}
+
+static long sun9i_a80_cpus_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
+				     u8 parent, unsigned long parent_rate)
+{
+	u8 div, pre_div = 1;
+
+	/*
+	 * clock can only divide, so we will never be able to achieve
+	 * frequencies higher than the parent frequency
+	 */
+	if (parent_rate && rate > parent_rate)
+		rate = parent_rate;
+
+	div = DIV_ROUND_UP(parent_rate, rate);
+
+	/* calculate pre-divider if parent is pll4 */
+	if (parent == SUN9I_CPUS_MUX_PARENT_PLL4 && div > 4) {
+		/* pre-divider is 1 ~ 32 */
+		if (div < 32) {
+			pre_div = div;
+			div = 1;
+		} else if (div < 64) {
+			pre_div = DIV_ROUND_UP(div, 2);
+			div = 2;
+		} else if (div < 96) {
+			pre_div = DIV_ROUND_UP(div, 3);
+			div = 3;
+		} else {
+			pre_div = DIV_ROUND_UP(div, 4);
+			div = 4;
+		}
+	}
+
+	/* we were asked to pass back divider values */
+	if (divp) {
+		*divp = div - 1;
+		*pre_divp = pre_div - 1;
+	}
+
+	return parent_rate / pre_div / div;
+}
+
+static int sun9i_a80_cpus_clk_determine_rate(struct clk_hw *clk,
+					     struct clk_rate_request *req)
+{
+	struct clk_hw *parent, *best_parent = NULL;
+	int i, num_parents;
+	unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
+	unsigned long rate = req->rate;
+
+	/* find the parent that can help provide the fastest rate <= rate */
+	num_parents = clk_hw_get_num_parents(clk);
+	for (i = 0; i < num_parents; i++) {
+		parent = clk_hw_get_parent_by_index(clk, i);
+		if (!parent)
+			continue;
+		if (clk_hw_get_flags(clk) & CLK_SET_RATE_PARENT)
+			parent_rate = clk_hw_round_rate(parent, rate);
+		else
+			parent_rate = clk_hw_get_rate(parent);
+
+		child_rate = sun9i_a80_cpus_clk_round(rate, NULL, NULL, i,
+						      parent_rate);
+
+		if (child_rate <= rate && child_rate > best_child_rate) {
+			best_parent = parent;
+			best = parent_rate;
+			best_child_rate = child_rate;
+		}
+	}
+
+	if (!best_parent)
+		return -EINVAL;
+
+	req->best_parent_hw = best_parent;
+	req->best_parent_rate = best;
+	req->rate = best_child_rate;
+
+	return 0;
+}
+
+static int sun9i_a80_cpus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long parent_rate)
+{
+	struct sun9i_a80_cpus_clk *cpus = to_sun9i_a80_cpus_clk(hw);
+	unsigned long flags;
+	u8 div, pre_div, parent;
+	u32 reg;
+
+	spin_lock_irqsave(&sun9i_a80_cpus_lock, flags);
+
+	reg = readl(cpus->reg);
+
+	/* need to know which parent is used to apply pre-divider */
+	parent = SUN9I_CPUS_MUX_GET_PARENT(reg);
+	sun9i_a80_cpus_clk_round(rate, &div, &pre_div, parent, parent_rate);
+
+	reg = SUN9I_CPUS_DIV_SET(reg, div);
+	reg = SUN9I_CPUS_PLL4_DIV_SET(reg, pre_div);
+	writel(reg, cpus->reg);
+
+	spin_unlock_irqrestore(&sun9i_a80_cpus_lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops sun9i_a80_cpus_clk_ops = {
+	.determine_rate	= sun9i_a80_cpus_clk_determine_rate,
+	.recalc_rate	= sun9i_a80_cpus_clk_recalc_rate,
+	.set_rate	= sun9i_a80_cpus_clk_set_rate,
+};
+
+static void sun9i_a80_cpus_setup(struct device_node *node)
+{
+	const char *clk_name = node->name;
+	const char *parents[SUN9I_CPUS_MAX_PARENTS];
+	struct resource res;
+	struct sun9i_a80_cpus_clk *cpus;
+	struct clk_mux *mux;
+	struct clk *clk;
+	int ret;
+
+	cpus = kzalloc(sizeof(*cpus), GFP_KERNEL);
+	if (!cpus)
+		return;
+
+	cpus->reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(cpus->reg))
+		goto err_free_cpus;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	/* we have a mux, we will have >1 parents */
+	ret = of_clk_parent_fill(node, parents, SUN9I_CPUS_MAX_PARENTS);
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		goto err_unmap;
+
+	/* set up clock properties */
+	mux->reg = cpus->reg;
+	mux->shift = SUN9I_CPUS_MUX_SHIFT;
+	/* un-shifted mask is what mux_clk expects */
+	mux->mask = SUN9I_CPUS_MUX_MASK >> SUN9I_CPUS_MUX_SHIFT;
+	mux->lock = &sun9i_a80_cpus_lock;
+
+	clk = clk_register_composite(NULL, clk_name, parents, ret,
+				     &mux->hw, &clk_mux_ops,
+				     &cpus->hw, &sun9i_a80_cpus_clk_ops,
+				     NULL, NULL, 0);
+	if (IS_ERR(clk))
+		goto err_free_mux;
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (ret)
+		goto err_unregister;
+
+	return;
+
+err_unregister:
+	clk_unregister(clk);
+err_free_mux:
+	kfree(mux);
+err_unmap:
+	iounmap(cpus->reg);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+err_free_cpus:
+	kfree(cpus);
+}
+CLK_OF_DECLARE(sun9i_a80_cpus, "allwinner,sun9i-a80-cpus-clk",
+	       sun9i_a80_cpus_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 9c79af0c03b2..5ba2188ee99c 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -778,6 +778,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
 	.shift = 12,
 };
 
+static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
+	.shift = 0,
+};
+
 static void __init sunxi_mux_clk_setup(struct device_node *node,
 				       struct mux_data *data)
 {
@@ -1130,6 +1134,7 @@ static const struct of_device_id clk_divs_match[] __initconst = {
 static const struct of_device_id clk_mux_match[] __initconst = {
 	{.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
 	{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
+	{.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,},
 	{}
 };
 
@@ -1212,6 +1217,7 @@ CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
 CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks);
 CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
 CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks);
+CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks);
 
 static void __init sun9i_init_clocks(struct device_node *node)
 {
diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c
index 1a72cd672839..67b8e38f4ee9 100644
--- a/drivers/clk/sunxi/clk-usb.c
+++ b/drivers/clk/sunxi/clk-usb.c
@@ -243,3 +243,15 @@ static void __init sun9i_a80_usb_phy_setup(struct device_node *node)
 	sunxi_usb_clk_setup(node, &sun9i_a80_usb_phy_data, &a80_usb_phy_lock);
 }
 CLK_OF_DECLARE(sun9i_a80_usb_phy, "allwinner,sun9i-a80-usb-phy-clk", sun9i_a80_usb_phy_setup);
+
+static const struct usb_clk_data sun8i_h3_usb_clk_data __initconst = {
+	.clk_mask =  BIT(19) | BIT(18) | BIT(17) | BIT(16) |
+		     BIT(11) | BIT(10) | BIT(9) | BIT(8),
+	.reset_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
+};
+
+static void __init sun8i_h3_usb_setup(struct device_node *node)
+{
+	sunxi_usb_clk_setup(node, &sun8i_h3_usb_clk_data, &sun4i_a10_usb_lock);
+}
+CLK_OF_DECLARE(sun8i_h3_usb, "allwinner,sun8i-h3-usb-clk", sun8i_h3_usb_setup);
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 826c325dc2e8..97984c503bbb 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= clk-tegra124.o
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= clk-tegra124-dfll-fcpu.o
 obj-$(CONFIG_ARCH_TEGRA_132_SOC)	+= clk-tegra124.o
 obj-y					+= cvb.o
+obj-$(CONFIG_ARCH_TEGRA_210_SOC)	+= clk-tegra210.o
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index 60738cc954cb..19ce0738ee76 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -13,6 +13,7 @@ enum clk_id {
 	tegra_clk_amx1,
 	tegra_clk_apbdma,
 	tegra_clk_apbif,
+	tegra_clk_ape,
 	tegra_clk_audio0,
 	tegra_clk_audio0_2x,
 	tegra_clk_audio0_mux,
@@ -38,6 +39,7 @@ enum clk_id {
 	tegra_clk_cile,
 	tegra_clk_clk_32k,
 	tegra_clk_clk72Mhz,
+	tegra_clk_clk72Mhz_8,
 	tegra_clk_clk_m,
 	tegra_clk_clk_m_div2,
 	tegra_clk_clk_m_div4,
@@ -51,17 +53,21 @@ enum clk_id {
 	tegra_clk_cml1,
 	tegra_clk_csi,
 	tegra_clk_csite,
+	tegra_clk_csite_8,
 	tegra_clk_csus,
 	tegra_clk_cve,
 	tegra_clk_dam0,
 	tegra_clk_dam1,
 	tegra_clk_dam2,
 	tegra_clk_d_audio,
+	tegra_clk_dbgapb,
 	tegra_clk_dds,
 	tegra_clk_dfll_ref,
 	tegra_clk_dfll_soc,
 	tegra_clk_disp1,
+	tegra_clk_disp1_8,
 	tegra_clk_disp2,
+	tegra_clk_disp2_8,
 	tegra_clk_dp2,
 	tegra_clk_dpaux,
 	tegra_clk_dsialp,
@@ -71,6 +77,7 @@ enum clk_id {
 	tegra_clk_dtv,
 	tegra_clk_emc,
 	tegra_clk_entropy,
+	tegra_clk_entropy_8,
 	tegra_clk_epp,
 	tegra_clk_epp_8,
 	tegra_clk_extern1,
@@ -85,12 +92,16 @@ enum clk_id {
 	tegra_clk_gr3d_8,
 	tegra_clk_hclk,
 	tegra_clk_hda,
+	tegra_clk_hda_8,
 	tegra_clk_hda2codec_2x,
+	tegra_clk_hda2codec_2x_8,
 	tegra_clk_hda2hdmi,
 	tegra_clk_hdmi,
 	tegra_clk_hdmi_audio,
 	tegra_clk_host1x,
 	tegra_clk_host1x_8,
+	tegra_clk_host1x_9,
+	tegra_clk_hsic_trk,
 	tegra_clk_i2c1,
 	tegra_clk_i2c2,
 	tegra_clk_i2c3,
@@ -110,11 +121,14 @@ enum clk_id {
 	tegra_clk_i2s4_sync,
 	tegra_clk_isp,
 	tegra_clk_isp_8,
+	tegra_clk_isp_9,
 	tegra_clk_ispb,
 	tegra_clk_kbc,
 	tegra_clk_kfuse,
 	tegra_clk_la,
+	tegra_clk_maud,
 	tegra_clk_mipi,
+	tegra_clk_mipibif,
 	tegra_clk_mipi_cal,
 	tegra_clk_mpe,
 	tegra_clk_mselect,
@@ -124,15 +138,24 @@ enum clk_id {
 	tegra_clk_ndspeed,
 	tegra_clk_ndspeed_8,
 	tegra_clk_nor,
+	tegra_clk_nvdec,
+	tegra_clk_nvenc,
+	tegra_clk_nvjpg,
 	tegra_clk_owr,
+	tegra_clk_owr_8,
 	tegra_clk_pcie,
 	tegra_clk_pclk,
 	tegra_clk_pll_a,
 	tegra_clk_pll_a_out0,
+	tegra_clk_pll_a1,
 	tegra_clk_pll_c,
 	tegra_clk_pll_c2,
 	tegra_clk_pll_c3,
 	tegra_clk_pll_c4,
+	tegra_clk_pll_c4_out0,
+	tegra_clk_pll_c4_out1,
+	tegra_clk_pll_c4_out2,
+	tegra_clk_pll_c4_out3,
 	tegra_clk_pll_c_out1,
 	tegra_clk_pll_d,
 	tegra_clk_pll_d2,
@@ -140,19 +163,29 @@ enum clk_id {
 	tegra_clk_pll_d_out0,
 	tegra_clk_pll_dp,
 	tegra_clk_pll_e_out0,
+	tegra_clk_pll_g_ref,
 	tegra_clk_pll_m,
 	tegra_clk_pll_m_out1,
+	tegra_clk_pll_mb,
 	tegra_clk_pll_p,
 	tegra_clk_pll_p_out1,
 	tegra_clk_pll_p_out2,
 	tegra_clk_pll_p_out2_int,
 	tegra_clk_pll_p_out3,
 	tegra_clk_pll_p_out4,
+	tegra_clk_pll_p_out4_cpu,
 	tegra_clk_pll_p_out5,
+	tegra_clk_pll_p_out_hsio,
+	tegra_clk_pll_p_out_xusb,
+	tegra_clk_pll_p_out_cpu,
+	tegra_clk_pll_p_out_adsp,
 	tegra_clk_pll_ref,
 	tegra_clk_pll_re_out,
 	tegra_clk_pll_re_vco,
 	tegra_clk_pll_u,
+	tegra_clk_pll_u_out,
+	tegra_clk_pll_u_out1,
+	tegra_clk_pll_u_out2,
 	tegra_clk_pll_u_12m,
 	tegra_clk_pll_u_480m,
 	tegra_clk_pll_u_48m,
@@ -160,53 +193,80 @@ enum clk_id {
 	tegra_clk_pll_x,
 	tegra_clk_pll_x_out0,
 	tegra_clk_pwm,
+	tegra_clk_qspi,
 	tegra_clk_rtc,
 	tegra_clk_sata,
+	tegra_clk_sata_8,
 	tegra_clk_sata_cold,
 	tegra_clk_sata_oob,
+	tegra_clk_sata_oob_8,
 	tegra_clk_sbc1,
 	tegra_clk_sbc1_8,
+	tegra_clk_sbc1_9,
 	tegra_clk_sbc2,
 	tegra_clk_sbc2_8,
+	tegra_clk_sbc2_9,
 	tegra_clk_sbc3,
 	tegra_clk_sbc3_8,
+	tegra_clk_sbc3_9,
 	tegra_clk_sbc4,
 	tegra_clk_sbc4_8,
+	tegra_clk_sbc4_9,
 	tegra_clk_sbc5,
 	tegra_clk_sbc5_8,
 	tegra_clk_sbc6,
 	tegra_clk_sbc6_8,
 	tegra_clk_sclk,
+	tegra_clk_sdmmc_legacy,
 	tegra_clk_sdmmc1,
 	tegra_clk_sdmmc1_8,
+	tegra_clk_sdmmc1_9,
 	tegra_clk_sdmmc2,
 	tegra_clk_sdmmc2_8,
+	tegra_clk_sdmmc2_9,
 	tegra_clk_sdmmc3,
 	tegra_clk_sdmmc3_8,
+	tegra_clk_sdmmc3_9,
 	tegra_clk_sdmmc4,
 	tegra_clk_sdmmc4_8,
+	tegra_clk_sdmmc4_9,
 	tegra_clk_se,
 	tegra_clk_soc_therm,
+	tegra_clk_soc_therm_8,
 	tegra_clk_sor0,
 	tegra_clk_sor0_lvds,
+	tegra_clk_sor1,
+	tegra_clk_sor1_brick,
+	tegra_clk_sor1_src,
 	tegra_clk_spdif,
 	tegra_clk_spdif_2x,
 	tegra_clk_spdif_in,
+	tegra_clk_spdif_in_8,
 	tegra_clk_spdif_in_sync,
 	tegra_clk_spdif_mux,
 	tegra_clk_spdif_out,
 	tegra_clk_timer,
 	tegra_clk_trace,
 	tegra_clk_tsec,
+	tegra_clk_tsec_8,
+	tegra_clk_tsecb,
 	tegra_clk_tsensor,
 	tegra_clk_tvdac,
 	tegra_clk_tvo,
 	tegra_clk_uarta,
+	tegra_clk_uarta_8,
 	tegra_clk_uartb,
+	tegra_clk_uartb_8,
 	tegra_clk_uartc,
+	tegra_clk_uartc_8,
 	tegra_clk_uartd,
+	tegra_clk_uartd_8,
 	tegra_clk_uarte,
+	tegra_clk_uarte_8,
+	tegra_clk_uartape,
 	tegra_clk_usb2,
+	tegra_clk_usb2_hsic_trk,
+	tegra_clk_usb2_trk,
 	tegra_clk_usb3,
 	tegra_clk_usbd,
 	tegra_clk_vcp,
@@ -216,22 +276,35 @@ enum clk_id {
 	tegra_clk_vi,
 	tegra_clk_vi_8,
 	tegra_clk_vi_9,
+	tegra_clk_vi_10,
+	tegra_clk_vi_i2c,
 	tegra_clk_vic03,
+	tegra_clk_vic03_8,
 	tegra_clk_vim2_clk,
 	tegra_clk_vimclk_sync,
 	tegra_clk_vi_sensor,
-	tegra_clk_vi_sensor2,
 	tegra_clk_vi_sensor_8,
+	tegra_clk_vi_sensor_9,
+	tegra_clk_vi_sensor2,
+	tegra_clk_vi_sensor2_8,
 	tegra_clk_xusb_dev,
 	tegra_clk_xusb_dev_src,
+	tegra_clk_xusb_dev_src_8,
 	tegra_clk_xusb_falcon_src,
+	tegra_clk_xusb_falcon_src_8,
 	tegra_clk_xusb_fs_src,
+	tegra_clk_xusb_gate,
 	tegra_clk_xusb_host,
 	tegra_clk_xusb_host_src,
+	tegra_clk_xusb_host_src_8,
 	tegra_clk_xusb_hs_src,
+	tegra_clk_xusb_hs_src_4,
 	tegra_clk_xusb_ss,
 	tegra_clk_xusb_ss_src,
+	tegra_clk_xusb_ss_src_8,
 	tegra_clk_xusb_ss_div2,
+	tegra_clk_xusb_ssp_src,
+	tegra_clk_sclk_mux,
 	tegra_clk_max,
 };
 
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index d6d4ecb88e94..a534bfab30b3 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -65,6 +65,7 @@
 #define PLLE_BASE_DIVN_WIDTH 8
 #define PLLE_BASE_DIVM_SHIFT 0
 #define PLLE_BASE_DIVM_WIDTH 8
+#define PLLE_BASE_ENABLE BIT(31)
 
 #define PLLE_MISC_SETUP_BASE_SHIFT 16
 #define PLLE_MISC_SETUP_BASE_MASK (0xffff << PLLE_MISC_SETUP_BASE_SHIFT)
@@ -102,6 +103,7 @@
 #define PLLE_AUX_SEQ_ENABLE	BIT(24)
 #define PLLE_AUX_SEQ_START_STATE BIT(25)
 #define PLLE_AUX_PLLRE_SEL	BIT(28)
+#define PLLE_AUX_SS_SEQ_INCLUDE	BIT(31)
 
 #define XUSBIO_PLL_CFG0		0x51c
 #define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL	BIT(0)
@@ -187,17 +189,23 @@
 #define pll_readl_base(p) pll_readl(p->params->base_reg, p)
 #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
 #define pll_override_readl(offset, p) readl_relaxed(p->pmc + offset)
+#define pll_readl_sdm_din(p) pll_readl(p->params->sdm_din_reg, p)
+#define pll_readl_sdm_ctrl(p) pll_readl(p->params->sdm_ctrl_reg, p)
 
 #define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset)
 #define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p)
 #define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
 #define pll_override_writel(val, offset, p) writel(val, p->pmc + offset)
+#define pll_writel_sdm_din(val, p) pll_writel(val, p->params->sdm_din_reg, p)
+#define pll_writel_sdm_ctrl(val, p) pll_writel(val, p->params->sdm_ctrl_reg, p)
 
 #define mask(w) ((1 << (w)) - 1)
 #define divm_mask(p) mask(p->params->div_nmp->divm_width)
 #define divn_mask(p) mask(p->params->div_nmp->divn_width)
 #define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
 		      mask(p->params->div_nmp->divp_width))
+#define sdm_din_mask(p) p->params->sdm_din_mask
+#define sdm_en_mask(p) p->params->sdm_ctrl_en_mask
 
 #define divm_shift(p) (p)->params->div_nmp->divm_shift
 #define divn_shift(p) (p)->params->div_nmp->divn_shift
@@ -211,6 +219,9 @@
 #define divn_max(p) (divn_mask(p))
 #define divp_max(p) (1 << (divp_mask(p)))
 
+#define sdin_din_to_data(din)	((u16)((din) ? : 0xFFFFU))
+#define sdin_data_to_din(dat)	(((dat) == 0xFFFFU) ? 0 : (s16)dat)
+
 static struct div_nmp default_nmp = {
 	.divn_shift = PLL_BASE_DIVN_SHIFT,
 	.divn_width = PLL_BASE_DIVN_WIDTH,
@@ -269,6 +280,11 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
 	return -1;
 }
 
+int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll)
+{
+	return clk_pll_wait_for_lock(pll);
+}
+
 static int clk_pll_is_enabled(struct clk_hw *hw)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -290,6 +306,19 @@ static void _clk_pll_enable(struct clk_hw *hw)
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
 	u32 val;
 
+	if (pll->params->iddq_reg) {
+		val = pll_readl(pll->params->iddq_reg, pll);
+		val &= ~BIT(pll->params->iddq_bit_idx);
+		pll_writel(val, pll->params->iddq_reg, pll);
+		udelay(2);
+	}
+
+	if (pll->params->reset_reg) {
+		val = pll_readl(pll->params->reset_reg, pll);
+		val &= ~BIT(pll->params->reset_bit_idx);
+		pll_writel(val, pll->params->reset_reg, pll);
+	}
+
 	clk_pll_enable_lock(pll);
 
 	val = pll_readl_base(pll);
@@ -321,6 +350,19 @@ static void _clk_pll_disable(struct clk_hw *hw)
 		val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
 		writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
 	}
+
+	if (pll->params->reset_reg) {
+		val = pll_readl(pll->params->reset_reg, pll);
+		val |= BIT(pll->params->reset_bit_idx);
+		pll_writel(val, pll->params->reset_reg, pll);
+	}
+
+	if (pll->params->iddq_reg) {
+		val = pll_readl(pll->params->iddq_reg, pll);
+		val |= BIT(pll->params->iddq_bit_idx);
+		pll_writel(val, pll->params->iddq_reg, pll);
+		udelay(2);
+	}
 }
 
 static int clk_pll_enable(struct clk_hw *hw)
@@ -359,7 +401,7 @@ static void clk_pll_disable(struct clk_hw *hw)
 static int _p_div_to_hw(struct clk_hw *hw, u8 p_div)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
+	const struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
 
 	if (p_tohw) {
 		while (p_tohw->pdiv) {
@@ -372,10 +414,15 @@ static int _p_div_to_hw(struct clk_hw *hw, u8 p_div)
 	return -EINVAL;
 }
 
+int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div)
+{
+	return _p_div_to_hw(&pll->hw, p_div);
+}
+
 static int _hw_to_p_div(struct clk_hw *hw, u8 p_div_hw)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
+	const struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
 
 	if (p_tohw) {
 		while (p_tohw->pdiv) {
@@ -395,6 +442,7 @@ static int _get_table_rate(struct clk_hw *hw,
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
 	struct tegra_clk_pll_freq_table *sel;
+	int p;
 
 	for (sel = pll->params->freq_table; sel->input_rate != 0; sel++)
 		if (sel->input_rate == parent_rate &&
@@ -404,12 +452,21 @@ static int _get_table_rate(struct clk_hw *hw,
 	if (sel->input_rate == 0)
 		return -EINVAL;
 
+	if (pll->params->pdiv_tohw) {
+		p = _p_div_to_hw(hw, sel->p);
+		if (p < 0)
+			return p;
+	} else {
+		p = ilog2(sel->p);
+	}
+
 	cfg->input_rate = sel->input_rate;
 	cfg->output_rate = sel->output_rate;
 	cfg->m = sel->m;
 	cfg->n = sel->n;
-	cfg->p = sel->p;
+	cfg->p = p;
 	cfg->cpcon = sel->cpcon;
+	cfg->sdm_data = sel->sdm_data;
 
 	return 0;
 }
@@ -439,7 +496,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 		/*
 		 * PLL_P_OUT1 rate is not listed in PLLA table
 		 */
-		cfreq = parent_rate/(parent_rate/1000000);
+		cfreq = parent_rate / (parent_rate / 1000000);
 		break;
 	default:
 		pr_err("%s Unexpected reference rate %lu\n",
@@ -476,6 +533,42 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 	return 0;
 }
 
+/*
+ * SDM (Sigma Delta Modulator) divisor is 16-bit 2's complement signed number
+ * within (-2^12 ... 2^12-1) range. Represented in PLL data structure as
+ * unsigned 16-bit value, with "0" divisor mapped to 0xFFFF. Data "0" is used
+ * to indicate that SDM is disabled.
+ *
+ * Effective ndiv value when SDM is enabled: ndiv + 1/2 + sdm_din/2^13
+ */
+static void clk_pll_set_sdm_data(struct clk_hw *hw,
+				 struct tegra_clk_pll_freq_table *cfg)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+	bool enabled;
+
+	if (!pll->params->sdm_din_reg)
+		return;
+
+	if (cfg->sdm_data) {
+		val = pll_readl_sdm_din(pll) & (~sdm_din_mask(pll));
+		val |= sdin_data_to_din(cfg->sdm_data) & sdm_din_mask(pll);
+		pll_writel_sdm_din(val, pll);
+	}
+
+	val = pll_readl_sdm_ctrl(pll);
+	enabled = (val & sdm_en_mask(pll));
+
+	if (cfg->sdm_data == 0 && enabled)
+		val &= ~pll->params->sdm_ctrl_en_mask;
+
+	if (cfg->sdm_data != 0 && !enabled)
+		val |= pll->params->sdm_ctrl_en_mask;
+
+	pll_writel_sdm_ctrl(val, pll);
+}
+
 static void _update_pll_mnp(struct tegra_clk_pll *pll,
 			    struct tegra_clk_pll_freq_table *cfg)
 {
@@ -483,7 +576,7 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
 	struct tegra_clk_pll_params *params = pll->params;
 	struct div_nmp *div_nmp = params->div_nmp;
 
-	if ((params->flags & TEGRA_PLLM) &&
+	if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) &&
 		(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
 			PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
 		val = pll_override_readl(params->pmc_divp_reg, pll);
@@ -508,6 +601,8 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
 		       (cfg->p << divp_shift(pll));
 
 		pll_writel_base(val, pll);
+
+		clk_pll_set_sdm_data(&pll->hw, cfg);
 	}
 }
 
@@ -518,7 +613,7 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
 	struct tegra_clk_pll_params *params = pll->params;
 	struct div_nmp *div_nmp = params->div_nmp;
 
-	if ((params->flags & TEGRA_PLLM) &&
+	if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) &&
 		(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
 			PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
 		val = pll_override_readl(params->pmc_divp_reg, pll);
@@ -533,6 +628,14 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
 		cfg->m = (val >> div_nmp->divm_shift) & divm_mask(pll);
 		cfg->n = (val >> div_nmp->divn_shift) & divn_mask(pll);
 		cfg->p = (val >> div_nmp->divp_shift) & divp_mask(pll);
+
+		if (pll->params->sdm_din_reg) {
+			if (sdm_en_mask(pll) & pll_readl_sdm_ctrl(pll)) {
+				val = pll_readl_sdm_din(pll);
+				val &= sdm_din_mask(pll);
+				cfg->sdm_data = sdin_din_to_data(val);
+			}
+		}
 	}
 }
 
@@ -560,16 +663,51 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll,
 	pll_writel_misc(val, pll);
 }
 
+static void pll_clk_start_ss(struct tegra_clk_pll *pll)
+{
+	if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) {
+		u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll);
+
+		val |= pll->params->ssc_ctrl_en_mask;
+		pll_writel(val, pll->params->ssc_ctrl_reg, pll);
+	}
+}
+
+static void pll_clk_stop_ss(struct tegra_clk_pll *pll)
+{
+	if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) {
+		u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll);
+
+		val &= ~pll->params->ssc_ctrl_en_mask;
+		pll_writel(val, pll->params->ssc_ctrl_reg, pll);
+	}
+}
+
 static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 			unsigned long rate)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table old_cfg;
 	int state, ret = 0;
 
 	state = clk_pll_is_enabled(hw);
 
-	if (state)
+	_get_pll_mnp(pll, &old_cfg);
+
+	if (state && pll->params->defaults_set && pll->params->dyn_ramp &&
+			(cfg->m == old_cfg.m) && (cfg->p == old_cfg.p)) {
+		ret = pll->params->dyn_ramp(pll, cfg);
+		if (!ret)
+			return 0;
+	}
+
+	if (state) {
+		pll_clk_stop_ss(pll);
 		_clk_pll_disable(hw);
+	}
+
+	if (!pll->params->defaults_set && pll->params->set_defaults)
+		pll->params->set_defaults(pll);
 
 	_update_pll_mnp(pll, cfg);
 
@@ -579,6 +717,7 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 	if (state) {
 		_clk_pll_enable(hw);
 		ret = clk_pll_wait_for_lock(pll);
+		pll_clk_start_ss(pll);
 	}
 
 	return ret;
@@ -603,7 +742,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 	}
 
 	if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
-	    _calc_rate(hw, &cfg, rate, parent_rate)) {
+	    pll->params->calc_rate(hw, &cfg, rate, parent_rate)) {
 		pr_err("%s: Failed to set %s rate %lu\n", __func__,
 		       clk_hw_get_name(hw), rate);
 		WARN_ON(1);
@@ -613,8 +752,11 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 		spin_lock_irqsave(pll->lock, flags);
 
 	_get_pll_mnp(pll, &old_cfg);
+	if (pll->params->flags & TEGRA_PLL_VCO_OUT)
+		cfg.p = old_cfg.p;
 
-	if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
+	if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p ||
+		old_cfg.sdm_data != cfg.sdm_data)
 		ret = _program_pll(hw, &cfg, rate);
 
 	if (pll->lock)
@@ -629,15 +771,15 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
 	struct tegra_clk_pll_freq_table cfg;
 
-	if (pll->params->flags & TEGRA_PLL_FIXED)
+	if (pll->params->flags & TEGRA_PLL_FIXED) {
+		/* PLLM/MB are used for memory; we do not change rate */
+		if (pll->params->flags & (TEGRA_PLLM | TEGRA_PLLMB))
+			return clk_hw_get_rate(hw);
 		return pll->params->fixed_rate;
-
-	/* PLLM is used for memory; we do not change rate */
-	if (pll->params->flags & TEGRA_PLLM)
-		return clk_hw_get_rate(hw);
+	}
 
 	if (_get_table_rate(hw, &cfg, rate, *prate) &&
-	    _calc_rate(hw, &cfg, rate, *prate))
+	    pll->params->calc_rate(hw, &cfg, rate, *prate))
 		return -EINVAL;
 
 	return cfg.output_rate;
@@ -658,6 +800,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 		return parent_rate;
 
 	if ((pll->params->flags & TEGRA_PLL_FIXED) &&
+	    !(pll->params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) &&
 			!(val & PLL_BASE_OVERRIDE)) {
 		struct tegra_clk_pll_freq_table sel;
 		if (_get_table_rate(hw, &sel, pll->params->fixed_rate,
@@ -671,12 +814,20 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 
 	_get_pll_mnp(pll, &cfg);
 
-	pdiv = _hw_to_p_div(hw, cfg.p);
-	if (pdiv < 0) {
-		WARN_ON(1);
+	if (pll->params->flags & TEGRA_PLL_VCO_OUT) {
 		pdiv = 1;
+	} else {
+		pdiv = _hw_to_p_div(hw, cfg.p);
+		if (pdiv < 0) {
+			WARN(1, "Clock %s has invalid pdiv value : 0x%x\n",
+			     clk_hw_get_name(hw), cfg.p);
+			pdiv = 1;
+		}
 	}
 
+	if (pll->params->set_gain)
+		pll->params->set_gain(&cfg);
+
 	cfg.m *= pdiv;
 
 	rate *= cfg.n;
@@ -816,19 +967,65 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
-#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
-	defined(CONFIG_ARCH_TEGRA_124_SOC) || \
-	defined(CONFIG_ARCH_TEGRA_132_SOC)
-
 static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
 			   unsigned long parent_rate)
 {
+	u16 mdiv = parent_rate / pll_params->cf_min;
+
+	if (pll_params->flags & TEGRA_MDIV_NEW)
+		return (!pll_params->mdiv_default ? mdiv :
+			min(mdiv, pll_params->mdiv_default));
+
+	if (pll_params->mdiv_default)
+		return pll_params->mdiv_default;
+
 	if (parent_rate > pll_params->cf_max)
 		return 2;
 	else
 		return 1;
 }
 
+static int _calc_dynamic_ramp_rate(struct clk_hw *hw,
+				struct tegra_clk_pll_freq_table *cfg,
+				unsigned long rate, unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned int p;
+	int p_div;
+
+	if (!rate)
+		return -EINVAL;
+
+	p = DIV_ROUND_UP(pll->params->vco_min, rate);
+	cfg->m = _pll_fixed_mdiv(pll->params, parent_rate);
+	cfg->output_rate = rate * p;
+	cfg->n = cfg->output_rate * cfg->m / parent_rate;
+	cfg->input_rate = parent_rate;
+
+	p_div = _p_div_to_hw(hw, p);
+	if (p_div < 0)
+		return p_div;
+
+	cfg->p = p_div;
+
+	if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
+		return -EINVAL;
+
+	return 0;
+}
+
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
+	defined(CONFIG_ARCH_TEGRA_124_SOC) || \
+	defined(CONFIG_ARCH_TEGRA_132_SOC) || \
+	defined(CONFIG_ARCH_TEGRA_210_SOC)
+
+u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+
+	return (u16)_pll_fixed_mdiv(pll->params, input_rate);
+}
+
 static unsigned long _clip_vco_min(unsigned long vco_min,
 				   unsigned long parent_rate)
 {
@@ -871,86 +1068,12 @@ static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
 	return 0;
 }
 
-static int clk_pll_iddq_enable(struct clk_hw *hw)
-{
-	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	unsigned long flags = 0;
-
-	u32 val;
-	int ret;
-
-	if (pll->lock)
-		spin_lock_irqsave(pll->lock, flags);
-
-	val = pll_readl(pll->params->iddq_reg, pll);
-	val &= ~BIT(pll->params->iddq_bit_idx);
-	pll_writel(val, pll->params->iddq_reg, pll);
-	udelay(2);
-
-	_clk_pll_enable(hw);
-
-	ret = clk_pll_wait_for_lock(pll);
-
-	if (pll->lock)
-		spin_unlock_irqrestore(pll->lock, flags);
-
-	return 0;
-}
-
-static void clk_pll_iddq_disable(struct clk_hw *hw)
-{
-	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	unsigned long flags = 0;
-	u32 val;
-
-	if (pll->lock)
-		spin_lock_irqsave(pll->lock, flags);
-
-	_clk_pll_disable(hw);
-
-	val = pll_readl(pll->params->iddq_reg, pll);
-	val |= BIT(pll->params->iddq_bit_idx);
-	pll_writel(val, pll->params->iddq_reg, pll);
-	udelay(2);
-
-	if (pll->lock)
-		spin_unlock_irqrestore(pll->lock, flags);
-}
-
-static int _calc_dynamic_ramp_rate(struct clk_hw *hw,
-				struct tegra_clk_pll_freq_table *cfg,
-				unsigned long rate, unsigned long parent_rate)
-{
-	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	unsigned int p;
-	int p_div;
-
-	if (!rate)
-		return -EINVAL;
-
-	p = DIV_ROUND_UP(pll->params->vco_min, rate);
-	cfg->m = _pll_fixed_mdiv(pll->params, parent_rate);
-	cfg->output_rate = rate * p;
-	cfg->n = cfg->output_rate * cfg->m / parent_rate;
-
-	p_div = _p_div_to_hw(hw, p);
-	if (p_div < 0)
-		return p_div;
-	else
-		cfg->p = p_div;
-
-	if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
-		return -EINVAL;
-
-	return 0;
-}
-
 static int _pll_ramp_calc_pll(struct clk_hw *hw,
 			      struct tegra_clk_pll_freq_table *cfg,
 			      unsigned long rate, unsigned long parent_rate)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	int err = 0, p_div;
+	int err = 0;
 
 	err = _get_table_rate(hw, cfg, rate, parent_rate);
 	if (err < 0)
@@ -961,11 +1084,6 @@ static int _pll_ramp_calc_pll(struct clk_hw *hw,
 			err = -EINVAL;
 			goto out;
 		}
-		p_div = _p_div_to_hw(hw, cfg->p);
-		if (p_div < 0)
-			return p_div;
-		else
-			cfg->p = p_div;
 	}
 
 	if (cfg->p >  pll->params->max_p)
@@ -991,6 +1109,8 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
 		spin_lock_irqsave(pll->lock, flags);
 
 	_get_pll_mnp(pll, &old_cfg);
+	if (pll->params->flags & TEGRA_PLL_VCO_OUT)
+		cfg.p = old_cfg.p;
 
 	if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
 		ret = _program_pll(hw, &cfg, rate);
@@ -1004,6 +1124,7 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
 static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
 				unsigned long *prate)
 {
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
 	struct tegra_clk_pll_freq_table cfg;
 	int ret, p_div;
 	u64 output_rate = *prate;
@@ -1016,46 +1137,15 @@ static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
 	if (p_div < 0)
 		return p_div;
 
+	if (pll->params->set_gain)
+		pll->params->set_gain(&cfg);
+
 	output_rate *= cfg.n;
 	do_div(output_rate, cfg.m * p_div);
 
 	return output_rate;
 }
 
-static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long parent_rate)
-{
-	struct tegra_clk_pll_freq_table cfg;
-	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	unsigned long flags = 0;
-	int state, ret = 0;
-
-	if (pll->lock)
-		spin_lock_irqsave(pll->lock, flags);
-
-	state = clk_pll_is_enabled(hw);
-	if (state) {
-		if (rate != clk_get_rate(hw->clk)) {
-			pr_err("%s: Cannot change active PLLM\n", __func__);
-			ret = -EINVAL;
-			goto out;
-		}
-		goto out;
-	}
-
-	ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
-	if (ret < 0)
-		goto out;
-
-	_update_pll_mnp(pll, &cfg);
-
-out:
-	if (pll->lock)
-		spin_unlock_irqrestore(pll->lock, flags);
-
-	return ret;
-}
-
 static void _pllcx_strobe(struct tegra_clk_pll *pll)
 {
 	u32 val;
@@ -1445,6 +1535,17 @@ static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
 	init.parent_names = (parent_name ? &parent_name : NULL);
 	init.num_parents = (parent_name ? 1 : 0);
 
+	/* Default to _calc_rate if unspecified */
+	if (!pll->params->calc_rate) {
+		if (pll->params->flags & TEGRA_PLLM)
+			pll->params->calc_rate = _calc_dynamic_ramp_rate;
+		else
+			pll->params->calc_rate = _calc_rate;
+	}
+
+	if (pll->params->set_defaults)
+		pll->params->set_defaults(pll);
+
 	/* Data in .init is copied by clk_register(), so stack variable OK */
 	pll->hw.init = &init;
 
@@ -1460,7 +1561,7 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 	struct clk *clk;
 
 	pll_params->flags |= TEGRA_PLL_BYPASS;
-	pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+
 	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
@@ -1490,8 +1591,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
 
-	pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
-	pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+	pll_params->flags |= TEGRA_PLL_BYPASS;
 
 	if (!pll_params->div_nmp)
 		pll_params->div_nmp = &pll_e_nmp;
@@ -1510,25 +1610,17 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 
 #if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
 	defined(CONFIG_ARCH_TEGRA_124_SOC) || \
-	defined(CONFIG_ARCH_TEGRA_132_SOC)
+	defined(CONFIG_ARCH_TEGRA_132_SOC) || \
+	defined(CONFIG_ARCH_TEGRA_210_SOC)
 static const struct clk_ops tegra_clk_pllxc_ops = {
 	.is_enabled = clk_pll_is_enabled,
-	.enable = clk_pll_iddq_enable,
-	.disable = clk_pll_iddq_disable,
+	.enable = clk_pll_enable,
+	.disable = clk_pll_disable,
 	.recalc_rate = clk_pll_recalc_rate,
 	.round_rate = clk_pll_ramp_round_rate,
 	.set_rate = clk_pllxc_set_rate,
 };
 
-static const struct clk_ops tegra_clk_pllm_ops = {
-	.is_enabled = clk_pll_is_enabled,
-	.enable = clk_pll_iddq_enable,
-	.disable = clk_pll_iddq_disable,
-	.recalc_rate = clk_pll_recalc_rate,
-	.round_rate = clk_pll_ramp_round_rate,
-	.set_rate = clk_pllm_set_rate,
-};
-
 static const struct clk_ops tegra_clk_pllc_ops = {
 	.is_enabled = clk_pll_is_enabled,
 	.enable = clk_pllc_enable,
@@ -1540,8 +1632,8 @@ static const struct clk_ops tegra_clk_pllc_ops = {
 
 static const struct clk_ops tegra_clk_pllre_ops = {
 	.is_enabled = clk_pll_is_enabled,
-	.enable = clk_pll_iddq_enable,
-	.disable = clk_pll_iddq_disable,
+	.enable = clk_pll_enable,
+	.disable = clk_pll_disable,
 	.recalc_rate = clk_pllre_recalc_rate,
 	.round_rate = clk_pllre_round_rate,
 	.set_rate = clk_pllre_set_rate,
@@ -1564,7 +1656,6 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
 	struct tegra_clk_pll *pll;
 	struct clk *clk, *parent;
 	unsigned long parent_rate;
-	int err;
 	u32 val, val_iddq;
 
 	parent = __clk_lookup(parent_name);
@@ -1581,21 +1672,33 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
 
 	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
-	err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);
-	if (err)
-		return ERR_PTR(err);
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
 
-	val = readl_relaxed(clk_base + pll_params->base_reg);
-	val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+	/*
+	 * If the pll has a set_defaults callback, it will take care of
+	 * configuring dynamic ramping and setting IDDQ in that path.
+	 */
+	if (!pll_params->set_defaults) {
+		int err;
 
-	if (val & PLL_BASE_ENABLE)
-		WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
-	else {
-		val_iddq |= BIT(pll_params->iddq_bit_idx);
-		writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
+		err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);
+		if (err)
+			return ERR_PTR(err);
+
+		val = readl_relaxed(clk_base + pll_params->base_reg);
+		val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+
+		if (val & PLL_BASE_ENABLE)
+			WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
+		else {
+			val_iddq |= BIT(pll_params->iddq_bit_idx);
+			writel_relaxed(val_iddq,
+				       clk_base + pll_params->iddq_reg);
+		}
 	}
 
-	pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
 	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
@@ -1618,10 +1721,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
 
-	pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
-
 	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
 	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
@@ -1630,7 +1735,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
 
 	val = pll_readl_base(pll);
 	if (val & PLL_BASE_ENABLE)
-		WARN_ON(val & pll_params->iddq_bit_idx);
+		WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) &
+				BIT(pll_params->iddq_bit_idx));
 	else {
 		int m;
 
@@ -1678,15 +1784,18 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
 
 	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
 	pll_params->flags |= TEGRA_PLL_BYPASS;
-	pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
 	pll_params->flags |= TEGRA_PLLM;
 	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
 
 	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
-				      &tegra_clk_pllm_ops);
+				      &tegra_clk_pll_ops);
 	if (IS_ERR(clk))
 		kfree(pll);
 
@@ -1700,7 +1809,7 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
 			  spinlock_t *lock)
 {
 	struct clk *parent, *clk;
-	struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
+	const struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
 	struct tegra_clk_pll *pll;
 	struct tegra_clk_pll_freq_table cfg;
 	unsigned long parent_rate;
@@ -1777,7 +1886,6 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
 	struct clk *clk;
 	u32 val, val_aux;
 
-	pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
 	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
@@ -1810,8 +1918,8 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
 static const struct clk_ops tegra_clk_pllss_ops = {
 	.is_enabled = clk_pll_is_enabled,
-	.enable = clk_pll_iddq_enable,
-	.disable = clk_pll_iddq_disable,
+	.enable = clk_pll_enable,
+	.disable = clk_pll_disable,
 	.recalc_rate = clk_pll_recalc_rate,
 	.round_rate = clk_pll_ramp_round_rate,
 	.set_rate = clk_pllxc_set_rate,
@@ -1826,7 +1934,7 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
 	struct clk *clk, *parent;
 	struct tegra_clk_pll_freq_table cfg;
 	unsigned long parent_rate;
-	u32 val;
+	u32 val, val_iddq;
 	int i;
 
 	if (!pll_params->div_nmp)
@@ -1839,7 +1947,6 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
 		return ERR_PTR(-EINVAL);
 	}
 
-	pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK;
 	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
@@ -1874,6 +1981,337 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
 	pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll);
 
 	val = pll_readl_base(pll);
+	val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+	if (val & PLL_BASE_ENABLE) {
+		if (val_iddq & BIT(pll_params->iddq_bit_idx)) {
+			WARN(1, "%s is on but IDDQ set\n", name);
+			kfree(pll);
+			return ERR_PTR(-EINVAL);
+		}
+	} else {
+		val_iddq |= BIT(pll_params->iddq_bit_idx);
+		writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
+	}
+
+	val &= ~PLLSS_LOCK_OVERRIDE;
+	pll_writel_base(val, pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+					&tegra_clk_pllss_ops);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+#endif
+
+#if defined(CONFIG_ARCH_TEGRA_210_SOC)
+static int clk_plle_tegra210_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table sel;
+	u32 val;
+	int ret;
+	unsigned long flags = 0;
+	unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+
+	if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
+		return -EINVAL;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	val = pll_readl_base(pll);
+	val &= ~BIT(30); /* Disable lock override */
+	pll_writel_base(val, pll);
+
+	val = pll_readl(pll->params->aux_reg, pll);
+	val |= PLLE_AUX_ENABLE_SWCTL;
+	val &= ~PLLE_AUX_SEQ_ENABLE;
+	pll_writel(val, pll->params->aux_reg, pll);
+	udelay(1);
+
+	val = pll_readl_misc(pll);
+	val |= PLLE_MISC_LOCK_ENABLE;
+	val |= PLLE_MISC_IDDQ_SW_CTRL;
+	val &= ~PLLE_MISC_IDDQ_SW_VALUE;
+	val |= PLLE_MISC_PLLE_PTS;
+	val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
+	pll_writel_misc(val, pll);
+	udelay(5);
+
+	val = pll_readl(PLLE_SS_CTRL, pll);
+	val |= PLLE_SS_DISABLE;
+	pll_writel(val, PLLE_SS_CTRL, pll);
+
+	val = pll_readl_base(pll);
+	val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
+		 divm_mask_shifted(pll));
+	val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
+	val |= sel.m << divm_shift(pll);
+	val |= sel.n << divn_shift(pll);
+	val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
+	pll_writel_base(val, pll);
+	udelay(1);
+
+	val = pll_readl_base(pll);
+	val |= PLLE_BASE_ENABLE;
+	pll_writel_base(val, pll);
+
+	ret = clk_pll_wait_for_lock(pll);
+
+	if (ret < 0)
+		goto out;
+
+	val = pll_readl(PLLE_SS_CTRL, pll);
+	val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);
+	val &= ~PLLE_SS_COEFFICIENTS_MASK;
+	val |= PLLE_SS_COEFFICIENTS_VAL;
+	pll_writel(val, PLLE_SS_CTRL, pll);
+	val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);
+	pll_writel(val, PLLE_SS_CTRL, pll);
+	udelay(1);
+	val &= ~PLLE_SS_CNTL_INTERP_RESET;
+	pll_writel(val, PLLE_SS_CTRL, pll);
+	udelay(1);
+
+	val = pll_readl_misc(pll);
+	val &= ~PLLE_MISC_IDDQ_SW_CTRL;
+	pll_writel_misc(val, pll);
+
+	val = pll_readl(pll->params->aux_reg, pll);
+	val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE);
+	val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
+	pll_writel(val, pll->params->aux_reg, pll);
+	udelay(1);
+	val |= PLLE_AUX_SEQ_ENABLE;
+	pll_writel(val, pll->params->aux_reg, pll);
+
+out:
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static void clk_plle_tegra210_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	val = pll_readl_base(pll);
+	val &= ~PLLE_BASE_ENABLE;
+	pll_writel_base(val, pll);
+
+	val = pll_readl_misc(pll);
+	val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
+	pll_writel_misc(val, pll);
+	udelay(1);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+
+	val = pll_readl_base(pll);
+
+	return val & PLLE_BASE_ENABLE ? 1 : 0;
+}
+
+static const struct clk_ops tegra_clk_plle_tegra210_ops = {
+	.is_enabled =  clk_plle_tegra210_is_enabled,
+	.enable = clk_plle_tegra210_enable,
+	.disable = clk_plle_tegra210_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+};
+
+struct clk *tegra_clk_register_plle_tegra210(const char *name,
+				const char *parent_name,
+				void __iomem *clk_base, unsigned long flags,
+				struct tegra_clk_pll_params *pll_params,
+				spinlock_t *lock)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+	u32 val, val_aux;
+
+	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* ensure parent is set to pll_re_vco */
+
+	val = pll_readl_base(pll);
+	val_aux = pll_readl(pll_params->aux_reg, pll);
+
+	if (val & PLLE_BASE_ENABLE) {
+		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
+			(val_aux & PLLE_AUX_PLLP_SEL))
+			WARN(1, "pll_e enabled with unsupported parent %s\n",
+			  (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
+					"pll_re_vco");
+	} else {
+		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
+		pll_writel(val_aux, pll_params->aux_reg, pll);
+	}
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_plle_tegra210_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+struct clk *tegra_clk_register_pllc_tegra210(const char *name,
+			const char *parent_name, void __iomem *clk_base,
+			void __iomem *pmc, unsigned long flags,
+			struct tegra_clk_pll_params *pll_params,
+			spinlock_t *lock)
+{
+	struct clk *parent, *clk;
+	const struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
+	struct tegra_clk_pll *pll;
+	unsigned long parent_rate;
+
+	if (!p_tohw)
+		return ERR_PTR(-EINVAL);
+
+	parent = __clk_lookup(parent_name);
+	if (!parent) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			name, parent_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	parent_rate = clk_get_rate(parent);
+
+	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
+	pll_params->flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pll_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+struct clk *tegra_clk_register_pllxc_tegra210(const char *name,
+			const char *parent_name, void __iomem *clk_base,
+			void __iomem *pmc, unsigned long flags,
+			struct tegra_clk_pll_params *pll_params,
+			spinlock_t *lock)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk, *parent;
+	unsigned long parent_rate;
+
+	parent = __clk_lookup(parent_name);
+	if (!parent) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			name, parent_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	parent_rate = clk_get_rate(parent);
+
+	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
+	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pll_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+struct clk *tegra_clk_register_pllss_tegra210(const char *name,
+				const char *parent_name, void __iomem *clk_base,
+				unsigned long flags,
+				struct tegra_clk_pll_params *pll_params,
+				spinlock_t *lock)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk, *parent;
+	struct tegra_clk_pll_freq_table cfg;
+	unsigned long parent_rate;
+	u32 val;
+	int i;
+
+	if (!pll_params->div_nmp)
+		return ERR_PTR(-EINVAL);
+
+	parent = __clk_lookup(parent_name);
+	if (!parent) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			name, parent_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	val = pll_readl_base(pll);
+	val &= ~PLLSS_REF_SRC_SEL_MASK;
+	pll_writel_base(val, pll);
+
+	parent_rate = clk_get_rate(parent);
+
+	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
+	/* initialize PLL to minimum rate */
+
+	cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
+	cfg.n = cfg.m * pll_params->vco_min / parent_rate;
+
+	for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++)
+		;
+	if (!i) {
+		kfree(pll);
+		return ERR_PTR(-EINVAL);
+	}
+
+	cfg.p = pll_params->pdiv_tohw[i-1].hw_val;
+
+	_update_pll_mnp(pll, &cfg);
+
+	pll_writel_misc(PLLSS_MISC_DEFAULT, pll);
+
+	val = pll_readl_base(pll);
 	if (val & PLL_BASE_ENABLE) {
 		if (val & BIT(pll_params->iddq_bit_idx)) {
 			WARN(1, "%s is on but IDDQ set\n", name);
@@ -1887,8 +2325,50 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
 	pll_writel_base(val, pll);
 
 	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
-					&tegra_clk_pllss_ops);
+					&tegra_clk_pll_ops);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
+			  void __iomem *clk_base, void __iomem *pmc,
+			  unsigned long flags,
+			  struct tegra_clk_pll_params *pll_params,
+			  spinlock_t *lock)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk, *parent;
+	unsigned long parent_rate;
 
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	parent = __clk_lookup(parent_name);
+	if (!parent) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			parent_name, name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	parent_rate = clk_get_rate(parent);
+
+	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
+	pll_params->flags |= TEGRA_PLL_BYPASS;
+	pll_params->flags |= TEGRA_PLLMB;
+	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pll_ops);
 	if (IS_ERR(clk))
 		kfree(pll);
 
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index cb6ab830941d..6ad381a888a6 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -124,6 +124,20 @@
 #define CLK_SOURCE_HDMI_AUDIO 0x668
 #define CLK_SOURCE_VIC03 0x678
 #define CLK_SOURCE_CLK72MHZ 0x66c
+#define CLK_SOURCE_DBGAPB 0x718
+#define CLK_SOURCE_NVENC 0x6a0
+#define CLK_SOURCE_NVDEC 0x698
+#define CLK_SOURCE_NVJPG 0x69c
+#define CLK_SOURCE_APE 0x6c0
+#define CLK_SOURCE_SOR1 0x410
+#define CLK_SOURCE_SDMMC_LEGACY 0x694
+#define CLK_SOURCE_QSPI 0x6c4
+#define CLK_SOURCE_VI_I2C 0x6c8
+#define CLK_SOURCE_MIPIBIF 0x660
+#define CLK_SOURCE_UARTAPE 0x710
+#define CLK_SOURCE_TSECB 0x6d8
+#define CLK_SOURCE_MAUD 0x6d4
+#define CLK_SOURCE_USB2_HSIC_TRK 0x6cc
 
 #define MASK(x) (BIT(x) - 1)
 
@@ -182,6 +196,13 @@
 			TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
 			_parents##_idx, 0, NULL)
 
+#define UART8(_name, _parents, _offset,\
+			     _clk_num, _clk_id)			\
+	TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+			29, MASK(3), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \
+			TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
+			_parents##_idx, 0, NULL)
+
 #define I2C(_name, _parents, _offset,\
 			     _clk_num, _clk_id)			\
 	TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
@@ -221,8 +242,21 @@
 		.flags = _flags						\
 	}
 
+#define DIV8(_name, _parent_name, _offset, _clk_id, _flags)		\
+	{								\
+		.name = _name,						\
+		.clk_id = _clk_id,					\
+		.p.parent_name = _parent_name,				\
+		.periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 8, 1,		\
+				TEGRA_DIVIDER_ROUND_UP, 0, 0,		\
+				NULL, NULL),				\
+		.offset = _offset,					\
+		.flags = _flags,					\
+	}
+
 #define PLLP_BASE 0xa0
 #define PLLP_MISC 0xac
+#define PLLP_MISC1 0x680
 #define PLLP_OUTA 0xa4
 #define PLLP_OUTB 0xa8
 #define PLLP_OUTC 0x67c
@@ -234,6 +268,7 @@ static DEFINE_SPINLOCK(PLLP_OUTA_lock);
 static DEFINE_SPINLOCK(PLLP_OUTB_lock);
 static DEFINE_SPINLOCK(PLLP_OUTC_lock);
 static DEFINE_SPINLOCK(sor0_lock);
+static DEFINE_SPINLOCK(sor1_lock);
 
 #define MUX_I2S_SPDIF(_id)						\
 static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
@@ -285,6 +320,68 @@ static u32 mux_pllp_clkm_idx[] = {
 	[0] = 0, [1] = 3,
 };
 
+static const char *mux_pllp_clkm_2[] = {
+	"pll_p", "clk_m"
+};
+static u32 mux_pllp_clkm_2_idx[] = {
+	[0] = 2, [1] = 6,
+};
+
+static const char *mux_pllc2_c_c3_pllp_plla1_clkm[] = {
+	"pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a1", "clk_m"
+};
+static u32 mux_pllc2_c_c3_pllp_plla1_clkm_idx[] = {
+	[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 6, [5] = 7,
+};
+
+static const char *
+mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0[] = {
+	"pll_c4_out1", "pll_c", "pll_c4_out2", "pll_p", "clk_m",
+	"pll_a_out0", "pll_c4_out0"
+};
+static u32 mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0_idx[] = {
+	[0] = 0, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7,
+};
+
+static const char *mux_pllc_pllp_plla[] = {
+	"pll_c", "pll_p", "pll_a_out0"
+};
+static u32 mux_pllc_pllp_plla_idx[] = {
+	[0] = 1, [1] = 2, [2] = 3,
+};
+
+static const char *mux_clkm_pllc_pllp_plla[] = {
+	"clk_m", "pll_c", "pll_p", "pll_a_out0"
+};
+#define mux_clkm_pllc_pllp_plla_idx NULL
+
+static const char *mux_pllc_pllp_plla1_pllc2_c3_clkm[] = {
+	"pll_c", "pll_p", "pll_a1", "pll_c2", "pll_c3", "clk_m"
+};
+static u32 mux_pllc_pllp_plla1_pllc2_c3_clkm_idx[] = {
+	[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6,
+};
+
+static const char *mux_pllc2_c_c3_pllp_clkm_plla1_pllc4[] = {
+	"pll_c2", "pll_c", "pll_c3", "pll_p", "clk_m", "pll_a1", "pll_c4_out0",
+};
+static u32 mux_pllc2_c_c3_pllp_clkm_plla1_pllc4_idx[] = {
+	[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7,
+};
+
+static const char *mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4[] = {
+	"pll_c", "pll_p", "pll_a1", "pll_c2", "pll_c3", "clk_m", "pll_c4_out0",
+};
+#define mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4_idx \
+	mux_pllc2_c_c3_pllp_clkm_plla1_pllc4_idx
+
+static const char *
+mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm[] = {
+	"pll_a_out0", "pll_c4_out0", "pll_c", "pll_c4_out1", "pll_p",
+	"pll_c4_out2", "clk_m"
+};
+#define mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm_idx NULL
+
 static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
 	"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
 };
@@ -302,12 +399,93 @@ static const char *mux_pllm_pllc_pllp_plla[] = {
 #define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
 
 static const char *mux_pllp_pllc_clkm[] = {
-	"pll_p", "pll_c", "pll_m"
+	"pll_p", "pll_c", "clk_m"
 };
 static u32 mux_pllp_pllc_clkm_idx[] = {
 	[0] = 0, [1] = 1, [2] = 3,
 };
 
+static const char *mux_pllp_pllc_clkm_1[] = {
+	"pll_p", "pll_c", "clk_m"
+};
+static u32 mux_pllp_pllc_clkm_1_idx[] = {
+	[0] = 0, [1] = 2, [2] = 5,
+};
+
+static const char *mux_pllp_pllc_plla_clkm[] = {
+	"pll_p", "pll_c", "pll_a_out0", "clk_m"
+};
+static u32 mux_pllp_pllc_plla_clkm_idx[] = {
+	[0] = 0, [1] = 2, [2] = 4, [3] = 6,
+};
+
+static const char *mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2[] = {
+	"pll_p", "pll_c", "pll_c4_out0", "pll_c4_out1", "clk_m", "pll_c4_out2"
+};
+static u32 mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2_idx[] = {
+	[0] = 0, [1] = 2, [2] = 3, [3] = 5, [4] = 6, [5] = 7,
+};
+
+static const char *
+mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
+	"pll_p", "pll_c_out1", "pll_c", "pll_c4_out2", "pll_c4_out1",
+	"clk_m", "pll_c4_out0"
+};
+static u32
+mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0_idx[] = {
+	[0] = 0, [1] = 1, [2] = 2, [3] = 4, [4] = 5, [5] = 6, [6] = 7,
+};
+
+static const char *mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
+	"pll_p", "pll_c4_out2", "pll_c4_out1", "clk_m", "pll_c4_out0"
+};
+static u32 mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0_idx[] = {
+	[0] = 0, [1] = 3, [2] = 4, [3] = 6, [4] = 7,
+};
+
+static const char *mux_pllp_clkm_pllc4_out2_out1_out0_lj[] = {
+	"pll_p",
+	"pll_c4_out2", "pll_c4_out0",	/* LJ input */
+	"pll_c4_out2", "pll_c4_out1",
+	"pll_c4_out1",			/* LJ input */
+	"clk_m", "pll_c4_out0"
+};
+#define mux_pllp_clkm_pllc4_out2_out1_out0_lj_idx NULL
+
+static const char *mux_pllp_pllc2_c_c3_clkm[] = {
+	"pll_p", "pll_c2", "pll_c", "pll_c3", "clk_m"
+};
+static u32 mux_pllp_pllc2_c_c3_clkm_idx[] = {
+	[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 6,
+};
+
+static const char *mux_pllp_clkm_clk32_plle[] = {
+	"pll_p", "clk_m", "clk_32k", "pll_e"
+};
+static u32 mux_pllp_clkm_clk32_plle_idx[] = {
+	[0] = 0, [1] = 2, [2] = 4, [3] = 6,
+};
+
+static const char *mux_pllp_pllp_out3_clkm_clk32k_plla[] = {
+	"pll_p", "pll_p_out3", "clk_m", "clk_32k", "pll_a_out0"
+};
+#define mux_pllp_pllp_out3_clkm_clk32k_plla_idx NULL
+
+static const char *mux_pllp_out3_clkm_pllp_pllc4[] = {
+	"pll_p_out3", "clk_m", "pll_p", "pll_c4_out0", "pll_c4_out1",
+	"pll_c4_out2"
+};
+static u32 mux_pllp_out3_clkm_pllp_pllc4_idx[] = {
+	[0] = 0, [1] = 3, [2] = 4, [3] = 5, [4] = 6, [5] = 7,
+};
+
+static const char *mux_clkm_pllp_pllre[] = {
+	"clk_m", "pll_p_out_xusb", "pll_re_out"
+};
+static u32 mux_clkm_pllp_pllre_idx[] = {
+	[0] = 0, [1] = 1, [2] = 5,
+};
+
 static const char *mux_pllp_pllc_clkm_clk32[] = {
 	"pll_p", "pll_c", "clk_m", "clk_32k"
 };
@@ -332,6 +510,11 @@ static u32 mux_clkm_48M_pllp_480M_idx[] = {
 	[0] = 0, [1] = 2, [2] = 4, [3] = 6,
 };
 
+static const char *mux_clkm_pllre_clk32_480M[] = {
+	"clk_m", "pll_re_out", "clk_32k", "pll_u_480M"
+};
+#define mux_clkm_pllre_clk32_480M_idx NULL
+
 static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
 	"clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
 };
@@ -339,10 +522,27 @@ static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
 	[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
 };
 
-static const char *mux_ss_60M[] = {
+static const char *mux_pllp_out3_pllp_pllc_clkm[] = {
+	"pll_p_out3", "pll_p", "pll_c", "clk_m"
+};
+static u32 mux_pllp_out3_pllp_pllc_clkm_idx[] = {
+	[0] = 0, [1] = 1, [2] = 2, [3] = 6,
+};
+
+static const char *mux_ss_div2_60M[] = {
 	"xusb_ss_div2", "pll_u_60M"
 };
-#define mux_ss_60M_idx NULL
+#define mux_ss_div2_60M_idx NULL
+
+static const char *mux_ss_div2_60M_ss[] = {
+	"xusb_ss_div2", "pll_u_60M", "xusb_ss_src"
+};
+#define mux_ss_div2_60M_ss_idx NULL
+
+static const char *mux_ss_clkm[] = {
+	"xusb_ss_src", "clk_m"
+};
+#define mux_ss_clkm_idx NULL
 
 static const char *mux_d_audio_clk[] = {
 	"pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
@@ -386,6 +586,32 @@ static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = {
 	[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7,
 };
 
+/* SOR1 mux'es */
+static const char *mux_pllp_plld_plld2_clkm[] = {
+	"pll_p", "pll_d_out0", "pll_d2_out0", "clk_m"
+};
+static u32 mux_pllp_plld_plld2_clkm_idx[] = {
+	[0] = 0, [1] = 2, [2] = 5, [3] = 6
+};
+
+static const char *mux_plldp_sor1_src[] = {
+	"pll_dp", "clk_sor1_src"
+};
+#define mux_plldp_sor1_src_idx NULL
+
+static const char *mux_clkm_sor1_brick_sor1_src[] = {
+	"clk_m", "sor1_brick", "sor1_src", "sor1_brick"
+};
+#define mux_clkm_sor1_brick_sor1_src_idx NULL
+
+static const char *mux_pllp_pllre_clkm[] = {
+	"pll_p", "pll_re_out1", "clk_m"
+};
+
+static u32 mux_pllp_pllre_clkm_idx[] = {
+	[0] = 0, [1] = 2, [2] = 3,
+};
+
 static const char *mux_clkm_plldp_sor0lvds[] = {
 	"clk_m", "pll_dp", "sor0_lvds",
 };
@@ -401,6 +627,7 @@ static struct tegra_periph_init_data periph_clks[] = {
 	I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3),
 	I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4),
 	I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5),
+	I2C("i2c6", mux_pllp_clkm, CLK_SOURCE_I2C6, 166, tegra_clk_i2c6),
 	INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde),
 	INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi),
 	INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp),
@@ -411,14 +638,19 @@ static struct tegra_periph_init_data periph_clks[] = {
 	INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8),
 	INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8),
 	INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9),
+	INT8("vi", mux_pllc2_c_c3_pllp_clkm_plla1_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_10),
 	INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8),
 	INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc),
 	INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec),
+	INT("tsec", mux_pllp_pllc_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec_8),
 	INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
+	INT8("host1x", mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_9),
 	INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
+	INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
 	INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
 	INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
 	INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
+	INT8("vic03", mux_pllc_pllp_plla1_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03_8),
 	INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED),
 	MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0),
 	MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1),
@@ -427,22 +659,31 @@ static struct tegra_periph_init_data periph_clks[] = {
 	MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4),
 	MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out),
 	MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in),
+	MUX8("spdif_in", mux_pllp_pllc_clkm_1, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in_8),
 	MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm),
 	MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx),
 	MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx),
 	MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda),
+	MUX("hda", mux_pllp_pllc_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda_8),
 	MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
+	MUX8("hda2codec_2x", mux_pllp_pllc_plla_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x_8),
 	MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
 	MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1),
 	MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2),
 	MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3),
 	MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4),
+	MUX8("sdmmc1", mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_9),
+	MUX8("sdmmc2", mux_pllp_clkm_pllc4_out2_out1_out0_lj, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_9),
+	MUX8("sdmmc3", mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_9),
+	MUX8("sdmmc4", mux_pllp_clkm_pllc4_out2_out1_out0_lj, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4_9),
 	MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la),
 	MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace),
 	MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr),
+	MUX("owr", mux_pllp_pllc_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr_8),
 	MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor),
 	MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi),
 	MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor),
+	MUX("vi_sensor", mux_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_9),
 	MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab),
 	MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd),
 	MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile),
@@ -465,10 +706,13 @@ static struct tegra_periph_init_data periph_clks[] = {
 	MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash),
 	MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed),
 	MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob),
+	MUX("sata_oob", mux_pllp_pllc_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob_8),
 	MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
+	MUX("sata", mux_pllp_pllc_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata_8),
 	MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
 	MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
 	MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
+	MUX("vi_sensor2", mux_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2_8),
 	MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_8),
 	MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_8),
 	MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_8),
@@ -479,6 +723,10 @@ static struct tegra_periph_init_data periph_clks[] = {
 	MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8),
 	MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8),
 	MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8),
+	MUX("sbc1", mux_pllp_pllc_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_9),
+	MUX("sbc2", mux_pllp_pllc_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_9),
+	MUX("sbc3", mux_pllp_pllc_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_9),
+	MUX("sbc4", mux_pllp_pllc_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_9),
 	MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
 	MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
 	MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
@@ -486,27 +734,59 @@ static struct tegra_periph_init_data periph_clks[] = {
 	MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
 	MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
 	MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
+	MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
 	MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
 	MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
+	MUX8("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_9),
 	MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149,  0, tegra_clk_entropy),
+	MUX8("entropy", mux_pllp_clkm_clk32_plle, CLK_SOURCE_ENTROPY, 149,  0, tegra_clk_entropy_8),
 	MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
 	MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz),
+	MUX8("clk72mhz", mux_pllp_out3_pllp_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz_8),
 	MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock),
 	MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED),
+	MUX_FLAGS("csite", mux_pllp_pllre_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite_8, CLK_IGNORE_UNUSED),
 	NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL),
+	NODIV("disp1", mux_pllp_plld_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1_8, NULL),
 	NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL),
+	NODIV("disp2", mux_pllp_plld_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2_8, NULL),
 	NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock),
 	UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta),
 	UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
 	UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
 	UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
 	UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte),
+	UART8("uarta", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTA, 6, tegra_clk_uarta_8),
+	UART8("uartb", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTB, 7, tegra_clk_uartb_8),
+	UART8("uartc", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTC, 55, tegra_clk_uartc_8),
+	UART8("uartd", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTD, 65, tegra_clk_uartd_8),
 	XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
+	XUSB("xusb_host_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src_8),
 	XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
+	XUSB("xusb_falcon_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src_8),
 	XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
 	XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src),
-	NODIV("xusb_hs_src", mux_ss_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL),
+	XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src_8),
+	NODIV("xusb_hs_src", mux_ss_div2_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL),
+	NODIV("xusb_hs_src", mux_ss_div2_60M_ss, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(2), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src_4, NULL),
+	NODIV("xusb_ssp_src", mux_ss_clkm, CLK_SOURCE_XUSB_SS_SRC, 24, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ssp_src, NULL),
 	XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
+	XUSB("xusb_dev_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src_8),
+	MUX8("dbgapb", mux_pllp_clkm_2, CLK_SOURCE_DBGAPB, 185, TEGRA_PERIPH_NO_RESET, tegra_clk_dbgapb),
+	MUX8("msenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc),
+	MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec),
+	MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg),
+	MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape),
+	MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock),
+	NODIV("sor1_brick", mux_plldp_sor1_src, CLK_SOURCE_SOR1, 14, MASK(1), 183, 0, tegra_clk_sor1_brick, &sor1_lock),
+	NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock),
+	MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy),
+	MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi),
+	MUX("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, TEGRA_PERIPH_ON_APB, tegra_clk_vi_i2c),
+	MUX("mipibif", mux_pllp_clkm, CLK_SOURCE_MIPIBIF, 173, TEGRA_PERIPH_ON_APB, tegra_clk_mipibif),
+	MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape),
+	MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb),
+	MUX8("maud", mux_pllp_pllp_out3_clkm_clk32k_plla, CLK_SOURCE_MAUD, 202, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_maud),
 };
 
 static struct tegra_periph_init_data gate_clks[] = {
@@ -543,6 +823,16 @@ static struct tegra_periph_init_data gate_clks[] = {
 	GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
 	GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
 	GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
+	GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0),
+	GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0),
+	GATE("usb2_trk", "usb2_hsic_trk", 210, TEGRA_PERIPH_NO_RESET, tegra_clk_usb2_trk, 0),
+	GATE("xusb_gate", "osc", 143, 0, tegra_clk_xusb_gate, 0),
+	GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0),
+	GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0),
+};
+
+static struct tegra_periph_init_data div_clks[] = {
+	DIV8("usb2_hsic_trk", "osc", CLK_SOURCE_USB2_HSIC_TRK, tegra_clk_usb2_hsic_trk, 0),
 };
 
 struct pll_out_data {
@@ -633,6 +923,33 @@ static void __init gate_clk_init(void __iomem *clk_base,
 	}
 }
 
+static void __init div_clk_init(void __iomem *clk_base,
+				struct tegra_clk *tegra_clks)
+{
+	int i;
+	struct clk *clk;
+	struct clk **dt_clk;
+
+	for (i = 0; i < ARRAY_SIZE(div_clks); i++) {
+		struct tegra_periph_init_data *data;
+
+		data = div_clks + i;
+
+		dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
+		if (!dt_clk)
+			continue;
+
+		clk = tegra_clk_register_divider(data->name,
+				data->p.parent_name, clk_base + data->offset,
+				data->flags, data->periph.divider.flags,
+				data->periph.divider.shift,
+				data->periph.divider.width,
+				data->periph.divider.frac_width,
+				data->periph.divider.lock);
+		*dt_clk = clk;
+	}
+}
+
 static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
 				struct tegra_clk *tegra_clks,
 				struct tegra_clk_pll_params *pll_params)
@@ -669,6 +986,51 @@ static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
 				data->lock);
 		*dt_clk = clk;
 	}
+
+	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_cpu,
+			tegra_clks);
+	if (dt_clk) {
+		/*
+		 * Tegra210 has control on enabling/disabling PLLP branches to
+		 * CPU, register a gate clock "pll_p_out_cpu" for this gating
+		 * function and parent "pll_p_out4" to it, so when we are
+		 * re-parenting CPU off from "pll_p_out4" the PLLP branching to
+		 * CPU can be disabled automatically.
+		 */
+		clk = tegra_clk_register_divider("pll_p_out4_div",
+				"pll_p_out_cpu", clk_base + PLLP_OUTB, 0, 0, 24,
+				8, 1, &PLLP_OUTB_lock);
+
+		dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out4_cpu, tegra_clks);
+		if (dt_clk) {
+			clk = tegra_clk_register_pll_out("pll_p_out4",
+					"pll_p_out4_div", clk_base + PLLP_OUTB,
+					17, 16, CLK_IGNORE_UNUSED |
+					CLK_SET_RATE_PARENT, 0,
+					&PLLP_OUTB_lock);
+			*dt_clk = clk;
+		}
+	}
+
+	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_hsio, tegra_clks);
+	if (dt_clk) {
+		/* PLLP_OUT_HSIO */
+		clk = clk_register_gate(NULL, "pll_p_out_hsio", "pll_p",
+				CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+				clk_base + PLLP_MISC1, 29, 0, NULL);
+		*dt_clk = clk;
+	}
+
+	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_xusb, tegra_clks);
+	if (dt_clk) {
+		/* PLLP_OUT_XUSB */
+		clk = clk_register_gate(NULL, "pll_p_out_xusb",
+				"pll_p_out_hsio", CLK_SET_RATE_PARENT |
+				CLK_IGNORE_UNUSED, clk_base + PLLP_MISC1, 28, 0,
+				NULL);
+		clk_register_clkdev(clk, "pll_p_out_xusb", NULL);
+		*dt_clk = clk;
+	}
 }
 
 void __init tegra_periph_clk_init(void __iomem *clk_base,
@@ -678,4 +1040,5 @@ void __init tegra_periph_clk_init(void __iomem *clk_base,
 	init_pllp(clk_base, pmc_base, tegra_clks, pll_params);
 	periph_clk_init(clk_base, tegra_clks);
 	gate_clk_init(clk_base, tegra_clks);
+	div_clk_init(clk_base, tegra_clks);
 }
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c
index 5b1d723932c5..4559a20e3af6 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -34,9 +34,25 @@
 #define CCLKLP_BURST_POLICY 0x370
 #define SCLK_BURST_POLICY 0x028
 #define SYSTEM_CLK_RATE 0x030
+#define SCLK_DIVIDER 0x2c
 
 static DEFINE_SPINLOCK(sysrate_lock);
 
+enum tegra_super_gen {
+	gen4 = 4,
+	gen5,
+};
+
+struct tegra_super_gen_info {
+	enum tegra_super_gen gen;
+	const char **sclk_parents;
+	const char **cclk_g_parents;
+	const char **cclk_lp_parents;
+	int num_sclk_parents;
+	int num_cclk_g_parents;
+	int num_cclk_lp_parents;
+};
+
 static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
 			       "pll_p", "pll_p_out2", "unused",
 			       "clk_32k", "pll_m_out1" };
@@ -51,21 +67,81 @@ static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
 					 "pll_p", "pll_p_out4", "unused",
 					 "unused", "pll_x", "pll_x_out0" };
 
+const struct tegra_super_gen_info tegra_super_gen_info_gen4 = {
+	.gen = gen4,
+	.sclk_parents = sclk_parents,
+	.cclk_g_parents = cclk_g_parents,
+	.cclk_lp_parents = cclk_lp_parents,
+	.num_sclk_parents = ARRAY_SIZE(sclk_parents),
+	.num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents),
+	.num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents),
+};
+
+static const char *sclk_parents_gen5[] = { "clk_m", "pll_c_out1", "pll_c4_out3",
+			       "pll_p", "pll_p_out2", "pll_c4_out1",
+			       "clk_32k", "pll_c4_out2" };
+
+static const char *cclk_g_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused",
+					"pll_p", "pll_p_out4", "unused",
+					"unused", "pll_x", "unused", "unused",
+					"unused", "unused", "unused", "unused",
+					"dfllCPU_out" };
+
+static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused",
+					"pll_p", "pll_p_out4", "unused",
+					"unused", "pll_x", "unused", "unused",
+					"unused", "unused", "unused", "unused",
+					"dfllCPU_out" };
+
+const struct tegra_super_gen_info tegra_super_gen_info_gen5 = {
+	.gen = gen5,
+	.sclk_parents = sclk_parents_gen5,
+	.cclk_g_parents = cclk_g_parents_gen5,
+	.cclk_lp_parents = cclk_lp_parents_gen5,
+	.num_sclk_parents = ARRAY_SIZE(sclk_parents_gen5),
+	.num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents_gen5),
+	.num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents_gen5),
+};
+
 static void __init tegra_sclk_init(void __iomem *clk_base,
-				struct tegra_clk *tegra_clks)
+				struct tegra_clk *tegra_clks,
+				const struct tegra_super_gen_info *gen_info)
 {
 	struct clk *clk;
 	struct clk **dt_clk;
 
-	/* SCLK */
-	dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
+	/* SCLK_MUX */
+	dt_clk = tegra_lookup_dt_id(tegra_clk_sclk_mux, tegra_clks);
 	if (dt_clk) {
-		clk = tegra_clk_register_super_mux("sclk", sclk_parents,
-						ARRAY_SIZE(sclk_parents),
+		clk = tegra_clk_register_super_mux("sclk_mux",
+						gen_info->sclk_parents,
+						gen_info->num_sclk_parents,
 						CLK_SET_RATE_PARENT,
 						clk_base + SCLK_BURST_POLICY,
 						0, 4, 0, 0, NULL);
 		*dt_clk = clk;
+
+
+		/* SCLK */
+		dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
+		if (dt_clk) {
+			clk = clk_register_divider(NULL, "sclk", "sclk_mux", 0,
+						clk_base + SCLK_DIVIDER, 0, 8,
+						0, &sysrate_lock);
+			*dt_clk = clk;
+		}
+	} else {
+		/* SCLK */
+		dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
+		if (dt_clk) {
+			clk = tegra_clk_register_super_mux("sclk",
+						gen_info->sclk_parents,
+						gen_info->num_sclk_parents,
+						CLK_SET_RATE_PARENT,
+						clk_base + SCLK_BURST_POLICY,
+						0, 4, 0, 0, NULL);
+			*dt_clk = clk;
+		}
 	}
 
 	/* HCLK */
@@ -95,10 +171,11 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
 	*dt_clk = clk;
 }
 
-void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
+void __init tegra_super_clk_init(void __iomem *clk_base,
 				void __iomem *pmc_base,
 				struct tegra_clk *tegra_clks,
-				struct tegra_clk_pll_params *params)
+				struct tegra_clk_pll_params *params,
+				const struct tegra_super_gen_info *gen_info)
 {
 	struct clk *clk;
 	struct clk **dt_clk;
@@ -106,28 +183,50 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
 	/* CCLKG */
 	dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
 	if (dt_clk) {
-		clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
-					ARRAY_SIZE(cclk_g_parents),
+		if (gen_info->gen == gen5) {
+			clk = tegra_clk_register_super_mux("cclk_g",
+					gen_info->cclk_g_parents,
+					gen_info->num_cclk_g_parents,
+					CLK_SET_RATE_PARENT,
+					clk_base + CCLKG_BURST_POLICY,
+					0, 4, 8, 0, NULL);
+		} else {
+			clk = tegra_clk_register_super_mux("cclk_g",
+					gen_info->cclk_g_parents,
+					gen_info->num_cclk_g_parents,
 					CLK_SET_RATE_PARENT,
 					clk_base + CCLKG_BURST_POLICY,
 					0, 4, 0, 0, NULL);
+		}
 		*dt_clk = clk;
 	}
 
 	/* CCLKLP */
 	dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
 	if (dt_clk) {
-		clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
-					ARRAY_SIZE(cclk_lp_parents),
+		if (gen_info->gen == gen5) {
+			clk = tegra_clk_register_super_mux("cclk_lp",
+					gen_info->cclk_lp_parents,
+					gen_info->num_cclk_lp_parents,
+					CLK_SET_RATE_PARENT,
+					clk_base + CCLKLP_BURST_POLICY,
+					0, 4, 8, 0, NULL);
+		} else {
+			clk = tegra_clk_register_super_mux("cclk_lp",
+					gen_info->cclk_lp_parents,
+					gen_info->num_cclk_lp_parents,
 					CLK_SET_RATE_PARENT,
 					clk_base + CCLKLP_BURST_POLICY,
 					TEGRA_DIVIDER_2, 4, 8, 9, NULL);
+		}
 		*dt_clk = clk;
 	}
 
-	tegra_sclk_init(clk_base, tegra_clks);
+	tegra_sclk_init(clk_base, tegra_clks, gen_info);
 
-#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
+    defined(CONFIG_ARCH_TEGRA_124_SOC) || \
+    defined(CONFIG_ARCH_TEGRA_210_SOC)
 	/* PLLX */
 	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
 	if (!dt_clk)
@@ -148,3 +247,20 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
 #endif
 }
 
+void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
+				void __iomem *pmc_base,
+				struct tegra_clk *tegra_clks,
+				struct tegra_clk_pll_params *params)
+{
+	tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params,
+			     &tegra_super_gen_info_gen4);
+}
+
+void __init tegra_super_clk_gen5_init(void __iomem *clk_base,
+				void __iomem *pmc_base,
+				struct tegra_clk *tegra_clks,
+				struct tegra_clk_pll_params *params)
+{
+	tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params,
+			     &tegra_super_gen_info_gen5);
+}
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index b7d03e9add97..4a24aa4bbdea 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -182,40 +182,40 @@ static struct div_nmp pllxc_nmp = {
 	.divp_width = 4,
 };
 
-static struct pdiv_map pllxc_p[] = {
-	{ .pdiv = 1, .hw_val = 0 },
-	{ .pdiv = 2, .hw_val = 1 },
-	{ .pdiv = 3, .hw_val = 2 },
-	{ .pdiv = 4, .hw_val = 3 },
-	{ .pdiv = 5, .hw_val = 4 },
-	{ .pdiv = 6, .hw_val = 5 },
-	{ .pdiv = 8, .hw_val = 6 },
-	{ .pdiv = 10, .hw_val = 7 },
-	{ .pdiv = 12, .hw_val = 8 },
-	{ .pdiv = 16, .hw_val = 9 },
+static const struct pdiv_map pllxc_p[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv = 10, .hw_val =  7 },
+	{ .pdiv = 12, .hw_val =  8 },
+	{ .pdiv = 16, .hw_val =  9 },
 	{ .pdiv = 12, .hw_val = 10 },
 	{ .pdiv = 16, .hw_val = 11 },
 	{ .pdiv = 20, .hw_val = 12 },
 	{ .pdiv = 24, .hw_val = 13 },
 	{ .pdiv = 32, .hw_val = 14 },
-	{ .pdiv = 0, .hw_val = 0 },
+	{ .pdiv =  0, .hw_val =  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-	{ 12000000, 624000000, 104, 0, 2},
-	{ 12000000, 600000000, 100, 0, 2},
-	{ 13000000, 600000000,  92, 0, 2},	/* actual: 598.0 MHz */
-	{ 16800000, 600000000,  71, 0, 2},	/* actual: 596.4 MHz */
-	{ 19200000, 600000000,  62, 0, 2},	/* actual: 595.2 MHz */
-	{ 26000000, 600000000,  92, 1, 2},	/* actual: 598.0 MHz */
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 624000000, 104, 1, 2, 0 },
+	{ 12000000, 600000000, 100, 1, 2, 0 },
+	{ 13000000, 600000000,  92, 1, 2, 0 }, /* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 2, 2, 0 }, /* actual: 598.0 MHz */
+	{        0,         0,   0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_c_params = {
 	.input_min = 12000000,
 	.input_max = 800000000,
 	.cf_min = 12000000,
-	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
 	.vco_min = 600000000,
 	.vco_max = 1400000000,
 	.base_reg = PLLC_BASE,
@@ -232,7 +232,7 @@ static struct tegra_clk_pll_params pll_c_params = {
 	.pdiv_tohw = pllxc_p,
 	.div_nmp = &pllxc_nmp,
 	.freq_table = pll_c_freq_table,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct div_nmp pllcx_nmp = {
@@ -244,22 +244,22 @@ static struct div_nmp pllcx_nmp = {
 	.divp_width = 3,
 };
 
-static struct pdiv_map pllc_p[] = {
-	{ .pdiv = 1, .hw_val = 0 },
-	{ .pdiv = 2, .hw_val = 1 },
-	{ .pdiv = 4, .hw_val = 3 },
-	{ .pdiv = 8, .hw_val = 5 },
+static const struct pdiv_map pllc_p[] = {
+	{ .pdiv =  1, .hw_val = 0 },
+	{ .pdiv =  2, .hw_val = 1 },
+	{ .pdiv =  4, .hw_val = 3 },
+	{ .pdiv =  8, .hw_val = 5 },
 	{ .pdiv = 16, .hw_val = 7 },
-	{ .pdiv = 0, .hw_val = 0 },
+	{ .pdiv =  0, .hw_val = 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
-	{12000000, 600000000, 100, 0, 2},
-	{13000000, 600000000, 92, 0, 2},	/* actual: 598.0 MHz */
-	{16800000, 600000000, 71, 0, 2},	/* actual: 596.4 MHz */
-	{19200000, 600000000, 62, 0, 2},	/* actual: 595.2 MHz */
-	{26000000, 600000000, 92, 1, 2},	/* actual: 598.0 MHz */
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 600000000, 100, 1, 2, 0 },
+	{ 13000000, 600000000,  92, 1, 2, 0 }, /* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 2, 2, 0 }, /* actual: 598.0 MHz */
+	{        0,         0,   0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_c2_params = {
@@ -318,26 +318,26 @@ static struct div_nmp pllm_nmp = {
 	.override_divp_shift = 27,
 };
 
-static struct pdiv_map pllm_p[] = {
+static const struct pdiv_map pllm_p[] = {
 	{ .pdiv = 1, .hw_val = 0 },
 	{ .pdiv = 2, .hw_val = 1 },
 	{ .pdiv = 0, .hw_val = 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-	{12000000, 800000000, 66, 0, 1},	/* actual: 792.0 MHz */
-	{13000000, 800000000, 61, 0, 1},	/* actual: 793.0 MHz */
-	{16800000, 800000000, 47, 0, 1},	/* actual: 789.6 MHz */
-	{19200000, 800000000, 41, 0, 1},	/* actual: 787.2 MHz */
-	{26000000, 800000000, 61, 1, 1},	/* actual: 793.0 MHz */
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */
+	{ 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */
+	{ 16800000, 800000000, 47, 1, 1, 0 }, /* actual: 789.6 MHz */
+	{ 19200000, 800000000, 41, 1, 1, 0 }, /* actual: 787.2 MHz */
+	{ 26000000, 800000000, 61, 2, 1, 0 }, /* actual: 793.0 MHz */
+	{        0,         0,  0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_m_params = {
 	.input_min = 12000000,
 	.input_max = 500000000,
 	.cf_min = 12000000,
-	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
 	.vco_min = 400000000,
 	.vco_max = 1066000000,
 	.base_reg = PLLM_BASE,
@@ -351,7 +351,8 @@ static struct tegra_clk_pll_params pll_m_params = {
 	.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
 	.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
 	.freq_table = pll_m_freq_table,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
+		 TEGRA_PLL_FIXED,
 };
 
 static struct div_nmp pllp_nmp = {
@@ -364,12 +365,12 @@ static struct div_nmp pllp_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{12000000, 216000000, 432, 12, 1, 8},
-	{13000000, 216000000, 432, 13, 1, 8},
-	{16800000, 216000000, 360, 14, 1, 8},
-	{19200000, 216000000, 360, 16, 1, 8},
-	{26000000, 216000000, 432, 26, 1, 8},
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 216000000, 432, 12, 2, 8 },
+	{ 13000000, 216000000, 432, 13, 2, 8 },
+	{ 16800000, 216000000, 360, 14, 2, 8 },
+	{ 19200000, 216000000, 360, 16, 2, 8 },
+	{ 26000000, 216000000, 432, 26, 2, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_p_params = {
@@ -386,19 +387,19 @@ static struct tegra_clk_pll_params pll_p_params = {
 	.lock_delay = 300,
 	.div_nmp = &pllp_nmp,
 	.freq_table = pll_p_freq_table,
-	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 	.fixed_rate = 408000000,
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-	{9600000, 282240000, 147, 5, 0, 4},
-	{9600000, 368640000, 192, 5, 0, 4},
-	{9600000, 240000000, 200, 8, 0, 8},
-
-	{28800000, 282240000, 245, 25, 0, 8},
-	{28800000, 368640000, 320, 25, 0, 8},
-	{28800000, 240000000, 200, 24, 0, 8},
-	{0, 0, 0, 0, 0, 0},
+	{  9600000, 282240000, 147,  5, 1, 4 },
+	{  9600000, 368640000, 192,  5, 1, 4 },
+	{  9600000, 240000000, 200,  8, 1, 8 },
+	{ 28800000, 282240000, 245, 25, 1, 8 },
+	{ 28800000, 368640000, 320, 25, 1, 8 },
+	{ 28800000, 240000000, 200, 24, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 
@@ -416,28 +417,26 @@ static struct tegra_clk_pll_params pll_a_params = {
 	.lock_delay = 300,
 	.div_nmp = &pllp_nmp,
 	.freq_table = pll_a_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-	{12000000, 216000000, 864, 12, 2, 12},
-	{13000000, 216000000, 864, 13, 2, 12},
-	{16800000, 216000000, 720, 14, 2, 12},
-	{19200000, 216000000, 720, 16, 2, 12},
-	{26000000, 216000000, 864, 26, 2, 12},
-
-	{12000000, 594000000, 594, 12, 0, 12},
-	{13000000, 594000000, 594, 13, 0, 12},
-	{16800000, 594000000, 495, 14, 0, 12},
-	{19200000, 594000000, 495, 16, 0, 12},
-	{26000000, 594000000, 594, 26, 0, 12},
-
-	{12000000, 1000000000, 1000, 12, 0, 12},
-	{13000000, 1000000000, 1000, 13, 0, 12},
-	{19200000, 1000000000, 625, 12, 0, 12},
-	{26000000, 1000000000, 1000, 26, 0, 12},
-
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000,  216000000,  864, 12, 4, 12 },
+	{ 13000000,  216000000,  864, 13, 4, 12 },
+	{ 16800000,  216000000,  720, 14, 4, 12 },
+	{ 19200000,  216000000,  720, 16, 4, 12 },
+	{ 26000000,  216000000,  864, 26, 4, 12 },
+	{ 12000000,  594000000,  594, 12, 1, 12 },
+	{ 13000000,  594000000,  594, 13, 1, 12 },
+	{ 16800000,  594000000,  495, 14, 1, 12 },
+	{ 19200000,  594000000,  495, 16, 1, 12 },
+	{ 26000000,  594000000,  594, 26, 1, 12 },
+	{ 12000000, 1000000000, 1000, 12, 1, 12 },
+	{ 13000000, 1000000000, 1000, 13, 1, 12 },
+	{ 19200000, 1000000000,  625, 12, 1, 12 },
+	{ 26000000, 1000000000, 1000, 26, 1, 12 },
+	{        0,          0,    0,  0, 0,  0 },
 };
 
 static struct tegra_clk_pll_params pll_d_params = {
@@ -455,7 +454,7 @@ static struct tegra_clk_pll_params pll_d_params = {
 	.div_nmp = &pllp_nmp,
 	.freq_table = pll_d_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_d2_params = {
@@ -473,10 +472,10 @@ static struct tegra_clk_pll_params pll_d2_params = {
 	.div_nmp = &pllp_nmp,
 	.freq_table = pll_d_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
-static struct pdiv_map pllu_p[] = {
+static const struct pdiv_map pllu_p[] = {
 	{ .pdiv = 1, .hw_val = 1 },
 	{ .pdiv = 2, .hw_val = 0 },
 	{ .pdiv = 0, .hw_val = 0 },
@@ -492,12 +491,12 @@ static struct div_nmp pllu_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{12000000, 480000000, 960, 12, 0, 12},
-	{13000000, 480000000, 960, 13, 0, 12},
-	{16800000, 480000000, 400, 7, 0, 5},
-	{19200000, 480000000, 200, 4, 0, 3},
-	{26000000, 480000000, 960, 26, 0, 12},
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 480000000, 960, 12, 2, 12 },
+	{ 13000000, 480000000, 960, 13, 2, 12 },
+	{ 16800000, 480000000, 400,  7, 2,  5 },
+	{ 19200000, 480000000, 200,  4, 2,  3 },
+	{ 26000000, 480000000, 960, 26, 2, 12 },
+	{        0,         0,   0,  0, 0,  0 },
 };
 
 static struct tegra_clk_pll_params pll_u_params = {
@@ -516,25 +515,24 @@ static struct tegra_clk_pll_params pll_u_params = {
 	.div_nmp = &pllu_nmp,
 	.freq_table = pll_u_freq_table,
 	.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
 	/* 1 GHz */
-	{12000000, 1000000000, 83, 0, 1},	/* actual: 996.0 MHz */
-	{13000000, 1000000000, 76, 0, 1},	/* actual: 988.0 MHz */
-	{16800000, 1000000000, 59, 0, 1},	/* actual: 991.2 MHz */
-	{19200000, 1000000000, 52, 0, 1},	/* actual: 998.4 MHz */
-	{26000000, 1000000000, 76, 1, 1},	/* actual: 988.0 MHz */
-
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */
+	{ 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */
+	{ 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */
+	{ 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */
+	{ 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */
+	{        0,          0,  0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
 	.input_min = 12000000,
 	.input_max = 800000000,
 	.cf_min = 12000000,
-	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
 	.vco_min = 700000000,
 	.vco_max = 2400000000U,
 	.base_reg = PLLX_BASE,
@@ -551,15 +549,34 @@ static struct tegra_clk_pll_params pll_x_params = {
 	.pdiv_tohw = pllxc_p,
 	.div_nmp = &pllxc_nmp,
 	.freq_table = pll_x_freq_table,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
 	/* PLLE special case: use cpcon field to store cml divider value */
-	{336000000, 100000000, 100, 21, 16, 11},
-	{312000000, 100000000, 200, 26, 24, 13},
-	{12000000, 100000000, 200,  1,  24, 13},
-	{0, 0, 0, 0, 0, 0},
+	{ 336000000, 100000000, 100, 21, 16, 11 },
+	{ 312000000, 100000000, 200, 26, 24, 13 },
+	{  12000000, 100000000, 200,  1, 24, 13 },
+	{         0,         0,   0,  0,  0,  0 },
+};
+
+static const struct pdiv_map plle_p[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv = 10, .hw_val =  7 },
+	{ .pdiv = 12, .hw_val =  8 },
+	{ .pdiv = 16, .hw_val =  9 },
+	{ .pdiv = 12, .hw_val = 10 },
+	{ .pdiv = 16, .hw_val = 11 },
+	{ .pdiv = 20, .hw_val = 12 },
+	{ .pdiv = 24, .hw_val = 13 },
+	{ .pdiv = 32, .hw_val = 14 },
+	{ .pdiv =  0, .hw_val =  0 }
 };
 
 static struct div_nmp plle_nmp = {
@@ -584,9 +601,10 @@ static struct tegra_clk_pll_params pll_e_params = {
 	.lock_mask = PLLE_MISC_LOCK,
 	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
+	.pdiv_tohw = plle_p,
 	.div_nmp = &plle_nmp,
 	.freq_table = pll_e_freq_table,
-	.flags = TEGRA_PLL_FIXED,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_LOCK_ENABLE,
 	.fixed_rate = 100000000,
 };
 
@@ -614,18 +632,19 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
 	.iddq_reg = PLLRE_MISC,
 	.iddq_bit_idx = PLLRE_IDDQ_BIT,
 	.div_nmp = &pllre_nmp,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
+		 TEGRA_PLL_LOCK_MISC,
 };
 
 /* possible OSC frequencies in Hz */
 static unsigned long tegra114_input_freq[] = {
-	[0] = 13000000,
-	[1] = 16800000,
-	[4] = 19200000,
-	[5] = 38400000,
-	[8] = 12000000,
-	[9] = 48000000,
-	[12] = 260000000,
+	[ 0] = 13000000,
+	[ 1] = 16800000,
+	[ 4] = 19200000,
+	[ 5] = 38400000,
+	[ 8] = 12000000,
+	[ 9] = 48000000,
+	[12] = 26000000,
 };
 
 #define MASK(x) (BIT(x) - 1)
@@ -644,21 +663,27 @@ struct utmi_clk_param {
 };
 
 static const struct utmi_clk_param utmi_parameters[] = {
-	{.osc_frequency = 13000000, .enable_delay_count = 0x02,
-	 .stable_count = 0x33, .active_delay_count = 0x05,
-	 .xtal_freq_count = 0x7F},
-	{.osc_frequency = 19200000, .enable_delay_count = 0x03,
-	 .stable_count = 0x4B, .active_delay_count = 0x06,
-	 .xtal_freq_count = 0xBB},
-	{.osc_frequency = 12000000, .enable_delay_count = 0x02,
-	 .stable_count = 0x2F, .active_delay_count = 0x04,
-	 .xtal_freq_count = 0x76},
-	{.osc_frequency = 26000000, .enable_delay_count = 0x04,
-	 .stable_count = 0x66, .active_delay_count = 0x09,
-	 .xtal_freq_count = 0xFE},
-	{.osc_frequency = 16800000, .enable_delay_count = 0x03,
-	 .stable_count = 0x41, .active_delay_count = 0x0A,
-	 .xtal_freq_count = 0xA4},
+	{
+		.osc_frequency = 13000000, .enable_delay_count = 0x02,
+		.stable_count = 0x33, .active_delay_count = 0x05,
+		.xtal_freq_count = 0x7f
+	}, {
+		.osc_frequency = 19200000, .enable_delay_count = 0x03,
+		.stable_count = 0x4b, .active_delay_count = 0x06,
+		.xtal_freq_count = 0xbb
+	}, {
+		.osc_frequency = 12000000, .enable_delay_count = 0x02,
+		.stable_count = 0x2f, .active_delay_count = 0x04,
+		.xtal_freq_count = 0x76
+	}, {
+		.osc_frequency = 26000000, .enable_delay_count = 0x04,
+		.stable_count = 0x66, .active_delay_count = 0x09,
+		.xtal_freq_count = 0xfe
+	}, {
+		.osc_frequency = 16800000, .enable_delay_count = 0x03,
+		.stable_count = 0x41, .active_delay_count = 0x0a,
+		.xtal_freq_count = 0xa4
+	},
 };
 
 /* peripheral mux definitions */
@@ -965,8 +990,8 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
 
 static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
 {
+	unsigned int i;
 	u32 reg;
-	int i;
 
 	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
 		if (osc_freq == utmi_parameters[i].osc_frequency)
@@ -1173,7 +1198,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
 {
 	struct clk *clk;
 	struct tegra_periph_init_data *data;
-	int i;
+	unsigned int i;
 
 	/* xusb_ss_div2 */
 	clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
@@ -1278,7 +1303,7 @@ static struct tegra_cpu_car_ops tegra114_cpu_car_ops = {
 
 static const struct of_device_id pmc_match[] __initconst = {
 	{ .compatible = "nvidia,tegra114-pmc" },
-	{},
+	{ },
 };
 
 /*
@@ -1286,37 +1311,37 @@ static const struct of_device_id pmc_match[] __initconst = {
  * breaks
  */
 static struct tegra_clk_init_table init_table[] __initdata = {
-	{TEGRA114_CLK_UARTA, TEGRA114_CLK_PLL_P, 408000000, 0},
-	{TEGRA114_CLK_UARTB, TEGRA114_CLK_PLL_P, 408000000, 0},
-	{TEGRA114_CLK_UARTC, TEGRA114_CLK_PLL_P, 408000000, 0},
-	{TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0},
-	{TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1},
-	{TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1},
-	{TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1},
-	{TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1},
-	{TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1},
-	{TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0},
-	{TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1},
-	{TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1},
-	{TEGRA114_CLK_DISP1, TEGRA114_CLK_PLL_P, 0, 0},
-	{TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0},
-	{TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0},
-	{TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0},
-	{TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0},
-	{TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0},
-	{TEGRA114_CLK_PLL_RE_VCO, TEGRA114_CLK_CLK_MAX, 612000000, 0},
-	{TEGRA114_CLK_XUSB_SS_SRC, TEGRA114_CLK_PLL_RE_OUT, 122400000, 0},
-	{TEGRA114_CLK_XUSB_FS_SRC, TEGRA114_CLK_PLL_U_48M, 48000000, 0},
-	{TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0},
-	{TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0},
-	{TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0},
-	/* This MUST be the last entry. */
-	{TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0},
+	{ TEGRA114_CLK_UARTA, TEGRA114_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA114_CLK_UARTB, TEGRA114_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA114_CLK_UARTC, TEGRA114_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1 },
+	{ TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1 },
+	{ TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1 },
+	{ TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1 },
+	{ TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0 },
+	{ TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1 },
+	{ TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1 },
+	{ TEGRA114_CLK_DISP1, TEGRA114_CLK_PLL_P, 0, 0 },
+	{ TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0 },
+	{ TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0 },
+	{ TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0 },
+	{ TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0 },
+	{ TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0 },
+	{ TEGRA114_CLK_PLL_RE_VCO, TEGRA114_CLK_CLK_MAX, 612000000, 0 },
+	{ TEGRA114_CLK_XUSB_SS_SRC, TEGRA114_CLK_PLL_RE_OUT, 122400000, 0 },
+	{ TEGRA114_CLK_XUSB_FS_SRC, TEGRA114_CLK_PLL_U_48M, 48000000, 0 },
+	{ TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0 },
+	{ TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0 },
+	{ TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0 },
+	/* must be the last entry */
+	{ TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 },
 };
 
 static void __init tegra114_clock_apply_init_table(void)
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 87975f7adddc..1627258292d2 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -150,13 +150,13 @@ static DEFINE_SPINLOCK(emc_lock);
 
 /* possible OSC frequencies in Hz */
 static unsigned long tegra124_input_freq[] = {
-	[0] = 13000000,
-	[1] = 16800000,
-	[4] = 19200000,
-	[5] = 38400000,
-	[8] = 12000000,
-	[9] = 48000000,
-	[12] = 260000000,
+	[ 0] = 13000000,
+	[ 1] = 16800000,
+	[ 4] = 19200000,
+	[ 5] = 38400000,
+	[ 8] = 12000000,
+	[ 9] = 48000000,
+	[12] = 26000000,
 };
 
 static struct div_nmp pllxc_nmp = {
@@ -168,33 +168,33 @@ static struct div_nmp pllxc_nmp = {
 	.divp_width = 4,
 };
 
-static struct pdiv_map pllxc_p[] = {
-	{ .pdiv = 1, .hw_val = 0 },
-	{ .pdiv = 2, .hw_val = 1 },
-	{ .pdiv = 3, .hw_val = 2 },
-	{ .pdiv = 4, .hw_val = 3 },
-	{ .pdiv = 5, .hw_val = 4 },
-	{ .pdiv = 6, .hw_val = 5 },
-	{ .pdiv = 8, .hw_val = 6 },
-	{ .pdiv = 10, .hw_val = 7 },
-	{ .pdiv = 12, .hw_val = 8 },
-	{ .pdiv = 16, .hw_val = 9 },
+static const struct pdiv_map pllxc_p[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv = 10, .hw_val =  7 },
+	{ .pdiv = 12, .hw_val =  8 },
+	{ .pdiv = 16, .hw_val =  9 },
 	{ .pdiv = 12, .hw_val = 10 },
 	{ .pdiv = 16, .hw_val = 11 },
 	{ .pdiv = 20, .hw_val = 12 },
 	{ .pdiv = 24, .hw_val = 13 },
 	{ .pdiv = 32, .hw_val = 14 },
-	{ .pdiv = 0, .hw_val = 0 },
+	{ .pdiv =  0, .hw_val =  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
 	/* 1 GHz */
-	{12000000, 1000000000, 83, 0, 1},	/* actual: 996.0 MHz */
-	{13000000, 1000000000, 76, 0, 1},	/* actual: 988.0 MHz */
-	{16800000, 1000000000, 59, 0, 1},	/* actual: 991.2 MHz */
-	{19200000, 1000000000, 52, 0, 1},	/* actual: 998.4 MHz */
-	{26000000, 1000000000, 76, 1, 1},	/* actual: 988.0 MHz */
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */
+	{ 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */
+	{ 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */
+	{ 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */
+	{ 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */
+	{        0,          0,  0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -218,24 +218,24 @@ static struct tegra_clk_pll_params pll_x_params = {
 	.pdiv_tohw = pllxc_p,
 	.div_nmp = &pllxc_nmp,
 	.freq_table = pll_x_freq_table,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-	{ 12000000, 624000000, 104, 1, 2},
-	{ 12000000, 600000000, 100, 1, 2},
-	{ 13000000, 600000000,  92, 1, 2},	/* actual: 598.0 MHz */
-	{ 16800000, 600000000,  71, 1, 2},	/* actual: 596.4 MHz */
-	{ 19200000, 600000000,  62, 1, 2},	/* actual: 595.2 MHz */
-	{ 26000000, 600000000,  92, 2, 2},	/* actual: 598.0 MHz */
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 624000000, 104, 1, 2, 0 },
+	{ 12000000, 600000000, 100, 1, 2, 0 },
+	{ 13000000, 600000000,  92, 1, 2, 0 }, /* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 2, 2, 0 }, /* actual: 598.0 MHz */
+	{        0,         0,   0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_c_params = {
 	.input_min = 12000000,
 	.input_max = 800000000,
 	.cf_min = 12000000,
-	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
 	.vco_min = 600000000,
 	.vco_max = 1400000000,
 	.base_reg = PLLC_BASE,
@@ -252,7 +252,7 @@ static struct tegra_clk_pll_params pll_c_params = {
 	.pdiv_tohw = pllxc_p,
 	.div_nmp = &pllxc_nmp,
 	.freq_table = pll_c_freq_table,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct div_nmp pllcx_nmp = {
@@ -264,25 +264,25 @@ static struct div_nmp pllcx_nmp = {
 	.divp_width = 3,
 };
 
-static struct pdiv_map pllc_p[] = {
-	{ .pdiv = 1, .hw_val = 0 },
-	{ .pdiv = 2, .hw_val = 1 },
-	{ .pdiv = 3, .hw_val = 2 },
-	{ .pdiv = 4, .hw_val = 3 },
-	{ .pdiv = 6, .hw_val = 4 },
-	{ .pdiv = 8, .hw_val = 5 },
+static const struct pdiv_map pllc_p[] = {
+	{ .pdiv =  1, .hw_val = 0 },
+	{ .pdiv =  2, .hw_val = 1 },
+	{ .pdiv =  3, .hw_val = 2 },
+	{ .pdiv =  4, .hw_val = 3 },
+	{ .pdiv =  6, .hw_val = 4 },
+	{ .pdiv =  8, .hw_val = 5 },
 	{ .pdiv = 12, .hw_val = 6 },
 	{ .pdiv = 16, .hw_val = 7 },
-	{ .pdiv = 0, .hw_val = 0 },
+	{ .pdiv =  0, .hw_val = 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
-	{12000000, 600000000, 100, 1, 2},
-	{13000000, 600000000, 92, 1, 2},	/* actual: 598.0 MHz */
-	{16800000, 600000000, 71, 1, 2},	/* actual: 596.4 MHz */
-	{19200000, 600000000, 62, 1, 2},	/* actual: 595.2 MHz */
-	{26000000, 600000000, 92, 2, 2},	/* actual: 598.0 MHz */
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 600000000, 100, 1, 2, 0 },
+	{ 13000000, 600000000,  92, 1, 2, 0 }, /* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 2, 2, 0 }, /* actual: 598.0 MHz */
+	{        0,         0,   0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_c2_params = {
@@ -338,32 +338,32 @@ static struct div_nmp pllss_nmp = {
 	.divp_width = 4,
 };
 
-static struct pdiv_map pll12g_ssd_esd_p[] = {
-	{ .pdiv = 1, .hw_val = 0 },
-	{ .pdiv = 2, .hw_val = 1 },
-	{ .pdiv = 3, .hw_val = 2 },
-	{ .pdiv = 4, .hw_val = 3 },
-	{ .pdiv = 5, .hw_val = 4 },
-	{ .pdiv = 6, .hw_val = 5 },
-	{ .pdiv = 8, .hw_val = 6 },
-	{ .pdiv = 10, .hw_val = 7 },
-	{ .pdiv = 12, .hw_val = 8 },
-	{ .pdiv = 16, .hw_val = 9 },
+static const struct pdiv_map pll12g_ssd_esd_p[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv = 10, .hw_val =  7 },
+	{ .pdiv = 12, .hw_val =  8 },
+	{ .pdiv = 16, .hw_val =  9 },
 	{ .pdiv = 12, .hw_val = 10 },
 	{ .pdiv = 16, .hw_val = 11 },
 	{ .pdiv = 20, .hw_val = 12 },
 	{ .pdiv = 24, .hw_val = 13 },
 	{ .pdiv = 32, .hw_val = 14 },
-	{ .pdiv = 0, .hw_val = 0 },
+	{ .pdiv =  0, .hw_val =  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_c4_freq_table[] = {
-	{ 12000000, 600000000, 100, 1, 1},
-	{ 13000000, 600000000,  92, 1, 1},      /* actual: 598.0 MHz */
-	{ 16800000, 600000000,  71, 1, 1},      /* actual: 596.4 MHz */
-	{ 19200000, 600000000,  62, 1, 1},      /* actual: 595.2 MHz */
-	{ 26000000, 600000000,  92, 2, 1},      /* actual: 598.0 MHz */
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 600000000, 100, 1, 2, 0 },
+	{ 13000000, 600000000,  92, 1, 2, 0 }, /* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 2, 2, 0 }, /* actual: 598.0 MHz */
+	{        0,         0,   0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_c4_params = {
@@ -386,21 +386,35 @@ static struct tegra_clk_pll_params pll_c4_params = {
 	.ext_misc_reg[1] = 0x5b0,
 	.ext_misc_reg[2] = 0x5b4,
 	.freq_table = pll_c4_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
-static struct pdiv_map pllm_p[] = {
-	{ .pdiv = 1, .hw_val = 0 },
-	{ .pdiv = 2, .hw_val = 1 },
-	{ .pdiv = 0, .hw_val = 0 },
+static const struct pdiv_map pllm_p[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv = 10, .hw_val =  7 },
+	{ .pdiv = 12, .hw_val =  8 },
+	{ .pdiv = 16, .hw_val =  9 },
+	{ .pdiv = 12, .hw_val = 10 },
+	{ .pdiv = 16, .hw_val = 11 },
+	{ .pdiv = 20, .hw_val = 12 },
+	{ .pdiv = 24, .hw_val = 13 },
+	{ .pdiv = 32, .hw_val = 14 },
+	{ .pdiv =  0, .hw_val =  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-	{12000000, 800000000, 66, 1, 1},	/* actual: 792.0 MHz */
-	{13000000, 800000000, 61, 1, 1},	/* actual: 793.0 MHz */
-	{16800000, 800000000, 47, 1, 1},	/* actual: 789.6 MHz */
-	{19200000, 800000000, 41, 1, 1},	/* actual: 787.2 MHz */
-	{26000000, 800000000, 61, 2, 1},	/* actual: 793.0 MHz */
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */
+	{ 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */
+	{ 16800000, 800000000, 47, 1, 1, 0 }, /* actual: 789.6 MHz */
+	{ 19200000, 800000000, 41, 1, 1, 0 }, /* actual: 787.2 MHz */
+	{ 26000000, 800000000, 61, 2, 1, 0 }, /* actual: 793.0 MHz */
+	{        0,         0,  0, 0, 0, 0},
 };
 
 static struct div_nmp pllm_nmp = {
@@ -427,22 +441,41 @@ static struct tegra_clk_pll_params pll_m_params = {
 	.lock_mask = PLL_BASE_LOCK,
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
-	.max_p = 2,
+	.max_p = 5,
 	.pdiv_tohw = pllm_p,
 	.div_nmp = &pllm_nmp,
 	.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
 	.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
 	.freq_table = pll_m_freq_table,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
 	/* PLLE special case: use cpcon field to store cml divider value */
-	{336000000, 100000000, 100, 21, 16, 11},
-	{312000000, 100000000, 200, 26, 24, 13},
-	{13000000,  100000000, 200, 1,  26, 13},
-	{12000000,  100000000, 200, 1,  24, 13},
-	{0, 0, 0, 0, 0, 0},
+	{ 336000000, 100000000, 100, 21, 16, 11 },
+	{ 312000000, 100000000, 200, 26, 24, 13 },
+	{  13000000, 100000000, 200,  1, 26, 13 },
+	{  12000000, 100000000, 200,  1, 24, 13 },
+	{         0,         0,   0,  0,  0,  0 },
+};
+
+static const struct pdiv_map plle_p[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv = 10, .hw_val =  7 },
+	{ .pdiv = 12, .hw_val =  8 },
+	{ .pdiv = 16, .hw_val =  9 },
+	{ .pdiv = 12, .hw_val = 10 },
+	{ .pdiv = 16, .hw_val = 11 },
+	{ .pdiv = 20, .hw_val = 12 },
+	{ .pdiv = 24, .hw_val = 13 },
+	{ .pdiv = 32, .hw_val = 14 },
+	{ .pdiv =  1, .hw_val =  0 },
 };
 
 static struct div_nmp plle_nmp = {
@@ -467,9 +500,10 @@ static struct tegra_clk_pll_params pll_e_params = {
 	.lock_mask = PLLE_MISC_LOCK,
 	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
+	.pdiv_tohw = plle_p,
 	.div_nmp = &plle_nmp,
 	.freq_table = pll_e_freq_table,
-	.flags = TEGRA_PLL_FIXED,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_LOCK_ENABLE,
 	.fixed_rate = 100000000,
 };
 
@@ -507,7 +541,8 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
 	.iddq_reg = PLLRE_MISC,
 	.iddq_bit_idx = PLLRE_IDDQ_BIT,
 	.div_nmp = &pllre_nmp,
-	.flags = TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
+		 TEGRA_PLL_LOCK_MISC,
 };
 
 static struct div_nmp pllp_nmp = {
@@ -520,12 +555,12 @@ static struct div_nmp pllp_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{12000000, 408000000, 408, 12, 0, 8},
-	{13000000, 408000000, 408, 13, 0, 8},
-	{16800000, 408000000, 340, 14, 0, 8},
-	{19200000, 408000000, 340, 16, 0, 8},
-	{26000000, 408000000, 408, 26, 0, 8},
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 408000000, 408, 12, 1, 8 },
+	{ 13000000, 408000000, 408, 13, 1, 8 },
+	{ 16800000, 408000000, 340, 14, 1, 8 },
+	{ 19200000, 408000000, 340, 16, 1, 8 },
+	{ 26000000, 408000000, 408, 26, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_p_params = {
@@ -543,18 +578,18 @@ static struct tegra_clk_pll_params pll_p_params = {
 	.div_nmp = &pllp_nmp,
 	.freq_table = pll_p_freq_table,
 	.fixed_rate = 408000000,
-	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-	{9600000, 282240000, 147, 5, 0, 4},
-	{9600000, 368640000, 192, 5, 0, 4},
-	{9600000, 240000000, 200, 8, 0, 8},
-
-	{28800000, 282240000, 245, 25, 0, 8},
-	{28800000, 368640000, 320, 25, 0, 8},
-	{28800000, 240000000, 200, 24, 0, 8},
-	{0, 0, 0, 0, 0, 0},
+	{  9600000, 282240000, 147,  5, 1, 4 },
+	{  9600000, 368640000, 192,  5, 1, 4 },
+	{  9600000, 240000000, 200,  8, 1, 8 },
+	{ 28800000, 282240000, 245, 25, 1, 8 },
+	{ 28800000, 368640000, 320, 25, 1, 8 },
+	{ 28800000, 240000000, 200, 24, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_a_params = {
@@ -571,7 +606,8 @@ static struct tegra_clk_pll_params pll_a_params = {
 	.lock_delay = 300,
 	.div_nmp = &pllp_nmp,
 	.freq_table = pll_a_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct div_nmp plld_nmp = {
@@ -584,24 +620,21 @@ static struct div_nmp plld_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-	{12000000, 216000000, 864, 12, 4, 12},
-	{13000000, 216000000, 864, 13, 4, 12},
-	{16800000, 216000000, 720, 14, 4, 12},
-	{19200000, 216000000, 720, 16, 4, 12},
-	{26000000, 216000000, 864, 26, 4, 12},
-
-	{12000000, 594000000, 594, 12, 1, 12},
-	{13000000, 594000000, 594, 13, 1, 12},
-	{16800000, 594000000, 495, 14, 1, 12},
-	{19200000, 594000000, 495, 16, 1, 12},
-	{26000000, 594000000, 594, 26, 1, 12},
-
-	{12000000, 1000000000, 1000, 12, 1, 12},
-	{13000000, 1000000000, 1000, 13, 1, 12},
-	{19200000, 1000000000, 625, 12, 1, 12},
-	{26000000, 1000000000, 1000, 26, 1, 12},
-
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000,  216000000,  864, 12, 4, 12 },
+	{ 13000000,  216000000,  864, 13, 4, 12 },
+	{ 16800000,  216000000,  720, 14, 4, 12 },
+	{ 19200000,  216000000,  720, 16, 4, 12 },
+	{ 26000000,  216000000,  864, 26, 4, 12 },
+	{ 12000000,  594000000,  594, 12, 1, 12 },
+	{ 13000000,  594000000,  594, 13, 1, 12 },
+	{ 16800000,  594000000,  495, 14, 1, 12 },
+	{ 19200000,  594000000,  495, 16, 1, 12 },
+	{ 26000000,  594000000,  594, 26, 1, 12 },
+	{ 12000000, 1000000000, 1000, 12, 1, 12 },
+	{ 13000000, 1000000000, 1000, 13, 1, 12 },
+	{ 19200000, 1000000000,  625, 12, 1, 12 },
+	{ 26000000, 1000000000, 1000, 26, 1, 12 },
+	{        0,          0,    0,  0, 0,  0 },
 };
 
 static struct tegra_clk_pll_params pll_d_params = {
@@ -619,16 +652,16 @@ static struct tegra_clk_pll_params pll_d_params = {
 	.div_nmp = &plld_nmp,
 	.freq_table = pll_d_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = {
-	{ 12000000, 594000000,  99, 1, 2},
-	{ 13000000, 594000000,  91, 1, 2},      /* actual: 591.5 MHz */
-	{ 16800000, 594000000,  71, 1, 2},      /* actual: 596.4 MHz */
-	{ 19200000, 594000000,  62, 1, 2},      /* actual: 595.2 MHz */
-	{ 26000000, 594000000,  91, 2, 2},      /* actual: 591.5 MHz */
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 594000000, 99, 1, 2, 0 },
+	{ 13000000, 594000000, 91, 1, 2, 0 }, /* actual: 591.5 MHz */
+	{ 16800000, 594000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 594000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 594000000, 91, 2, 2, 0 }, /* actual: 591.5 MHz */
+	{        0,         0,  0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params tegra124_pll_d2_params = {
@@ -652,15 +685,16 @@ static struct tegra_clk_pll_params tegra124_pll_d2_params = {
 	.ext_misc_reg[2] = 0x578,
 	.max_p = 15,
 	.freq_table = tegra124_pll_d2_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = {
-	{ 12000000, 600000000, 100, 1, 1},
-	{ 13000000, 600000000,  92, 1, 1},      /* actual: 598.0 MHz */
-	{ 16800000, 600000000,  71, 1, 1},      /* actual: 596.4 MHz */
-	{ 19200000, 600000000,  62, 1, 1},      /* actual: 595.2 MHz */
-	{ 26000000, 600000000,  92, 2, 1},      /* actual: 598.0 MHz */
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 600000000, 100, 1, 2, 0 },
+	{ 13000000, 600000000,  92, 1, 2, 0 }, /* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 1, 2, 0 }, /* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 1, 2, 0 }, /* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 2, 2, 0 }, /* actual: 598.0 MHz */
+	{        0,         0,   0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_params pll_dp_params = {
@@ -684,9 +718,10 @@ static struct tegra_clk_pll_params pll_dp_params = {
 	.ext_misc_reg[2] = 0x5a0,
 	.max_p = 5,
 	.freq_table = pll_dp_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
-static struct pdiv_map pllu_p[] = {
+static const struct pdiv_map pllu_p[] = {
 	{ .pdiv = 1, .hw_val = 1 },
 	{ .pdiv = 2, .hw_val = 0 },
 	{ .pdiv = 0, .hw_val = 0 },
@@ -702,12 +737,12 @@ static struct div_nmp pllu_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{12000000, 480000000, 960, 12, 2, 12},
-	{13000000, 480000000, 960, 13, 2, 12},
-	{16800000, 480000000, 400, 7, 2, 5},
-	{19200000, 480000000, 200, 4, 2, 3},
-	{26000000, 480000000, 960, 26, 2, 12},
-	{0, 0, 0, 0, 0, 0},
+	{ 12000000, 480000000, 960, 12, 2, 12 },
+	{ 13000000, 480000000, 960, 13, 2, 12 },
+	{ 16800000, 480000000, 400,  7, 2,  5 },
+	{ 19200000, 480000000, 200,  4, 2,  3 },
+	{ 26000000, 480000000, 960, 26, 2, 12 },
+	{        0,         0,   0,  0, 0,  0 },
 };
 
 static struct tegra_clk_pll_params pll_u_params = {
@@ -726,7 +761,7 @@ static struct tegra_clk_pll_params pll_u_params = {
 	.div_nmp = &pllu_nmp,
 	.freq_table = pll_u_freq_table,
 	.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 struct utmi_clk_param {
@@ -743,21 +778,27 @@ struct utmi_clk_param {
 };
 
 static const struct utmi_clk_param utmi_parameters[] = {
-	{.osc_frequency = 13000000, .enable_delay_count = 0x02,
-	 .stable_count = 0x33, .active_delay_count = 0x05,
-	 .xtal_freq_count = 0x7F},
-	{.osc_frequency = 19200000, .enable_delay_count = 0x03,
-	 .stable_count = 0x4B, .active_delay_count = 0x06,
-	 .xtal_freq_count = 0xBB},
-	{.osc_frequency = 12000000, .enable_delay_count = 0x02,
-	 .stable_count = 0x2F, .active_delay_count = 0x04,
-	 .xtal_freq_count = 0x76},
-	{.osc_frequency = 26000000, .enable_delay_count = 0x04,
-	 .stable_count = 0x66, .active_delay_count = 0x09,
-	 .xtal_freq_count = 0xFE},
-	{.osc_frequency = 16800000, .enable_delay_count = 0x03,
-	 .stable_count = 0x41, .active_delay_count = 0x0A,
-	 .xtal_freq_count = 0xA4},
+	{
+		.osc_frequency = 13000000, .enable_delay_count = 0x02,
+		.stable_count = 0x33, .active_delay_count = 0x05,
+		.xtal_freq_count = 0x7f
+	}, {
+		.osc_frequency = 19200000, .enable_delay_count = 0x03,
+		.stable_count = 0x4b, .active_delay_count = 0x06,
+		.xtal_freq_count = 0xbb
+	}, {
+		.osc_frequency = 12000000, .enable_delay_count = 0x02,
+		.stable_count = 0x2f, .active_delay_count = 0x04,
+		.xtal_freq_count = 0x76
+	}, {
+		.osc_frequency = 26000000, .enable_delay_count = 0x04,
+		.stable_count = 0x66, .active_delay_count = 0x09,
+		.xtal_freq_count = 0xfe
+	}, {
+		.osc_frequency = 16800000, .enable_delay_count = 0x03,
+		.stable_count = 0x41, .active_delay_count = 0x0a,
+		.xtal_freq_count = 0xa4
+	},
 };
 
 static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
@@ -1024,8 +1065,8 @@ static struct clk **clks;
 
 static void tegra124_utmi_param_configure(void __iomem *clk_base)
 {
+	unsigned int i;
 	u32 reg;
-	int i;
 
 	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
 		if (osc_freq == utmi_parameters[i].osc_frequency)
@@ -1356,65 +1397,65 @@ static struct tegra_cpu_car_ops tegra124_cpu_car_ops = {
 
 static const struct of_device_id pmc_match[] __initconst = {
 	{ .compatible = "nvidia,tegra124-pmc" },
-	{},
+	{ },
 };
 
 static struct tegra_clk_init_table common_init_table[] __initdata = {
-	{TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0},
-	{TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0},
-	{TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0},
-	{TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0},
-	{TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1},
-	{TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1},
-	{TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1},
-	{TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1},
-	{TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1},
-	{TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0},
-	{TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1},
-	{TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0},
-	{TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0},
-	{TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1},
-	{TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1},
-	{TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1},
-	{TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0},
-	{TEGRA124_CLK_PLL_C_OUT1, TEGRA124_CLK_CLK_MAX, 100000000, 0},
-	{TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1},
-	{TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0},
-	{TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0},
-	{TEGRA124_CLK_PLL_RE_VCO, TEGRA124_CLK_CLK_MAX, 672000000, 0},
-	{TEGRA124_CLK_XUSB_SS_SRC, TEGRA124_CLK_PLL_U_480M, 120000000, 0},
-	{TEGRA124_CLK_XUSB_FS_SRC, TEGRA124_CLK_PLL_U_48M, 48000000, 0},
-	{TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0},
-	{TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0},
-	{TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
-	{TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
-	{TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
-	{TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
-	{TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
-	{TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
-	/* This MUST be the last entry. */
-	{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
+	{ TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1 },
+	{ TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1 },
+	{ TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1 },
+	{ TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1 },
+	{ TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0 },
+	{ TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1 },
+	{ TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0 },
+	{ TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0 },
+	{ TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1 },
+	{ TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1 },
+	{ TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1 },
+	{ TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0 },
+	{ TEGRA124_CLK_PLL_C_OUT1, TEGRA124_CLK_CLK_MAX, 100000000, 0 },
+	{ TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1 },
+	{ TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0 },
+	{ TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0 },
+	{ TEGRA124_CLK_PLL_RE_VCO, TEGRA124_CLK_CLK_MAX, 672000000, 0 },
+	{ TEGRA124_CLK_XUSB_SS_SRC, TEGRA124_CLK_PLL_U_480M, 120000000, 0 },
+	{ TEGRA124_CLK_XUSB_FS_SRC, TEGRA124_CLK_PLL_U_48M, 48000000, 0 },
+	{ TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0 },
+	{ TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0 },
+	{ TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0 },
+	{ TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0 },
+	{ TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0 },
+	{ TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0 },
+	/* must be the last entry */
+	{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
 };
 
 static struct tegra_clk_init_table tegra124_init_table[] __initdata = {
-	{TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0},
-	{TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1},
-	{TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0},
-	{TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0},
-	/* This MUST be the last entry. */
-	{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
+	{ TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0 },
+	{ TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0 },
+	{ TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0 },
+	/* must be the last entry */
+	{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
 };
 
 /* Tegra132 requires the SOC_THERM clock to remain active */
 static struct tegra_clk_init_table tegra132_init_table[] __initdata = {
-	{TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 1},
-	/* This MUST be the last entry. */
-	{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
+	{ TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 1 },
+	/* must be the last entry */
+	{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
 };
 
 static struct tegra_audio_clk_info tegra124_audio_plls[] = {
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index bf004f0e4f65..7a48e986c4c9 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -166,126 +166,120 @@ static DEFINE_SPINLOCK(emc_lock);
 static struct clk **clks;
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-	{ 12000000, 600000000, 600, 12, 0, 8 },
-	{ 13000000, 600000000, 600, 13, 0, 8 },
-	{ 19200000, 600000000, 500, 16, 0, 6 },
-	{ 26000000, 600000000, 600, 26, 0, 8 },
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 600000000, 600, 12, 1, 8 },
+	{ 13000000, 600000000, 600, 13, 1, 8 },
+	{ 19200000, 600000000, 500, 16, 1, 6 },
+	{ 26000000, 600000000, 600, 26, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 0, 8},
-	{ 13000000, 666000000, 666, 13, 0, 8},
-	{ 19200000, 666000000, 555, 16, 0, 8},
-	{ 26000000, 666000000, 666, 26, 0, 8},
-	{ 12000000, 600000000, 600, 12, 0, 8},
-	{ 13000000, 600000000, 600, 13, 0, 8},
-	{ 19200000, 600000000, 375, 12, 0, 6},
-	{ 26000000, 600000000, 600, 26, 0, 8},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 666000000, 666, 12, 1, 8 },
+	{ 13000000, 666000000, 666, 13, 1, 8 },
+	{ 19200000, 666000000, 555, 16, 1, 8 },
+	{ 26000000, 666000000, 666, 26, 1, 8 },
+	{ 12000000, 600000000, 600, 12, 1, 8 },
+	{ 13000000, 600000000, 600, 13, 1, 8 },
+	{ 19200000, 600000000, 375, 12, 1, 6 },
+	{ 26000000, 600000000, 600, 26, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 1, 8},
-	{ 13000000, 216000000, 432, 13, 1, 8},
-	{ 19200000, 216000000, 90,   4, 1, 1},
-	{ 26000000, 216000000, 432, 26, 1, 8},
-	{ 12000000, 432000000, 432, 12, 0, 8},
-	{ 13000000, 432000000, 432, 13, 0, 8},
-	{ 19200000, 432000000, 90,   4, 0, 1},
-	{ 26000000, 432000000, 432, 26, 0, 8},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 216000000, 432, 12, 2, 8 },
+	{ 13000000, 216000000, 432, 13, 2, 8 },
+	{ 19200000, 216000000,  90,  4, 2, 1 },
+	{ 26000000, 216000000, 432, 26, 2, 8 },
+	{ 12000000, 432000000, 432, 12, 1, 8 },
+	{ 13000000, 432000000, 432, 13, 1, 8 },
+	{ 19200000, 432000000,  90,  4, 1, 1 },
+	{ 26000000, 432000000, 432, 26, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-	{ 28800000, 56448000, 49, 25, 0, 1},
-	{ 28800000, 73728000, 64, 25, 0, 1},
-	{ 28800000, 24000000,  5,  6, 0, 1},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 28800000, 56448000, 49, 25, 1, 1 },
+	{ 28800000, 73728000, 64, 25, 1, 1 },
+	{ 28800000, 24000000,  5,  6, 1, 1 },
+	{        0,        0,  0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 0, 4},
-	{ 13000000, 216000000, 216, 13, 0, 4},
-	{ 19200000, 216000000, 135, 12, 0, 3},
-	{ 26000000, 216000000, 216, 26, 0, 4},
-
-	{ 12000000, 594000000, 594, 12, 0, 8},
-	{ 13000000, 594000000, 594, 13, 0, 8},
-	{ 19200000, 594000000, 495, 16, 0, 8},
-	{ 26000000, 594000000, 594, 26, 0, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 0, 12},
-	{ 13000000, 1000000000, 1000, 13, 0, 12},
-	{ 19200000, 1000000000, 625,  12, 0, 8},
-	{ 26000000, 1000000000, 1000, 26, 0, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000,  216000000,  216, 12, 1,  4 },
+	{ 13000000,  216000000,  216, 13, 1,  4 },
+	{ 19200000,  216000000,  135, 12, 1,  3 },
+	{ 26000000,  216000000,  216, 26, 1,  4 },
+	{ 12000000,  594000000,  594, 12, 1,  8 },
+	{ 13000000,  594000000,  594, 13, 1,  8 },
+	{ 19200000,  594000000,  495, 16, 1,  8 },
+	{ 26000000,  594000000,  594, 26, 1,  8 },
+	{ 12000000, 1000000000, 1000, 12, 1, 12 },
+	{ 13000000, 1000000000, 1000, 13, 1, 12 },
+	{ 19200000, 1000000000,  625, 12, 1,  8 },
+	{ 26000000, 1000000000, 1000, 26, 1, 12 },
+	{        0,          0,    0,  0, 0,  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 0, 0},
-	{ 13000000, 480000000, 960, 13, 0, 0},
-	{ 19200000, 480000000, 200, 4,  0, 0},
-	{ 26000000, 480000000, 960, 26, 0, 0},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 480000000, 960, 12, 1, 0 },
+	{ 13000000, 480000000, 960, 13, 1, 0 },
+	{ 19200000, 480000000, 200,  4, 1, 0 },
+	{ 26000000, 480000000, 960, 26, 1, 0 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
 	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 0, 12},
-	{ 13000000, 1000000000, 1000, 13, 0, 12},
-	{ 19200000, 1000000000, 625,  12, 0, 8},
-	{ 26000000, 1000000000, 1000, 26, 0, 12},
-
+	{ 12000000, 1000000000, 1000, 12, 1, 12 },
+	{ 13000000, 1000000000, 1000, 13, 1, 12 },
+	{ 19200000, 1000000000,  625, 12, 1,  8 },
+	{ 26000000, 1000000000, 1000, 26, 1, 12 },
 	/* 912 MHz */
-	{ 12000000, 912000000,  912,  12, 0, 12},
-	{ 13000000, 912000000,  912,  13, 0, 12},
-	{ 19200000, 912000000,  760,  16, 0, 8},
-	{ 26000000, 912000000,  912,  26, 0, 12},
-
+	{ 12000000,  912000000,  912, 12, 1, 12 },
+	{ 13000000,  912000000,  912, 13, 1, 12 },
+	{ 19200000,  912000000,  760, 16, 1,  8 },
+	{ 26000000,  912000000,  912, 26, 1, 12 },
 	/* 816 MHz */
-	{ 12000000, 816000000,  816,  12, 0, 12},
-	{ 13000000, 816000000,  816,  13, 0, 12},
-	{ 19200000, 816000000,  680,  16, 0, 8},
-	{ 26000000, 816000000,  816,  26, 0, 12},
-
+	{ 12000000,  816000000,  816, 12, 1, 12 },
+	{ 13000000,  816000000,  816, 13, 1, 12 },
+	{ 19200000,  816000000,  680, 16, 1,  8 },
+	{ 26000000,  816000000,  816, 26, 1, 12 },
 	/* 760 MHz */
-	{ 12000000, 760000000,  760,  12, 0, 12},
-	{ 13000000, 760000000,  760,  13, 0, 12},
-	{ 19200000, 760000000,  950,  24, 0, 8},
-	{ 26000000, 760000000,  760,  26, 0, 12},
-
+	{ 12000000,  760000000,  760, 12, 1, 12 },
+	{ 13000000,  760000000,  760, 13, 1, 12 },
+	{ 19200000,  760000000,  950, 24, 1,  8 },
+	{ 26000000,  760000000,  760, 26, 1, 12 },
 	/* 750 MHz */
-	{ 12000000, 750000000,  750,  12, 0, 12},
-	{ 13000000, 750000000,  750,  13, 0, 12},
-	{ 19200000, 750000000,  625,  16, 0, 8},
-	{ 26000000, 750000000,  750,  26, 0, 12},
-
+	{ 12000000,  750000000,  750, 12, 1, 12 },
+	{ 13000000,  750000000,  750, 13, 1, 12 },
+	{ 19200000,  750000000,  625, 16, 1,  8 },
+	{ 26000000,  750000000,  750, 26, 1, 12 },
 	/* 608 MHz */
-	{ 12000000, 608000000,  608,  12, 0, 12},
-	{ 13000000, 608000000,  608,  13, 0, 12},
-	{ 19200000, 608000000,  380,  12, 0, 8},
-	{ 26000000, 608000000,  608,  26, 0, 12},
-
+	{ 12000000,  608000000,  608, 12, 1, 12 },
+	{ 13000000,  608000000,  608, 13, 1, 12 },
+	{ 19200000,  608000000,  380, 12, 1,  8 },
+	{ 26000000,  608000000,  608, 26, 1, 12 },
 	/* 456 MHz */
-	{ 12000000, 456000000,  456,  12, 0, 12},
-	{ 13000000, 456000000,  456,  13, 0, 12},
-	{ 19200000, 456000000,  380,  16, 0, 8},
-	{ 26000000, 456000000,  456,  26, 0, 12},
-
+	{ 12000000,  456000000,  456, 12, 1, 12 },
+	{ 13000000,  456000000,  456, 13, 1, 12 },
+	{ 19200000,  456000000,  380, 16, 1,  8 },
+	{ 26000000,  456000000,  456, 26, 1, 12 },
 	/* 312 MHz */
-	{ 12000000, 312000000,  312,  12, 0, 12},
-	{ 13000000, 312000000,  312,  13, 0, 12},
-	{ 19200000, 312000000,  260,  16, 0, 8},
-	{ 26000000, 312000000,  312,  26, 0, 12},
+	{ 12000000,  312000000,  312, 12, 1, 12 },
+	{ 13000000,  312000000,  312, 13, 1, 12 },
+	{ 19200000,  312000000,  260, 16, 1,  8 },
+	{ 26000000,  312000000,  312, 26, 1, 12 },
+	{        0,          0,    0,  0, 0,  0 },
+};
 
-	{ 0, 0, 0, 0, 0, 0 },
+static const struct pdiv_map plle_p[] = {
+	{ .pdiv = 1, .hw_val = 1 },
+	{ .pdiv = 0, .hw_val = 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
-	{ 12000000, 100000000,  200,  24, 0, 0 },
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 100000000, 200, 24, 1, 0 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 /* PLL parameters */
@@ -302,7 +296,7 @@ static struct tegra_clk_pll_params pll_c_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_c_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_m_params = {
@@ -318,7 +312,7 @@ static struct tegra_clk_pll_params pll_m_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_m_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_p_params = {
@@ -334,7 +328,8 @@ static struct tegra_clk_pll_params pll_p_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_p_freq_table,
-	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 	.fixed_rate =  216000000,
 };
 
@@ -351,7 +346,7 @@ static struct tegra_clk_pll_params pll_a_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_a_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_d_params = {
@@ -367,10 +362,10 @@ static struct tegra_clk_pll_params pll_d_params = {
 	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
 	.lock_delay = 1000,
 	.freq_table = pll_d_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
-static struct pdiv_map pllu_p[] = {
+static const struct pdiv_map pllu_p[] = {
 	{ .pdiv = 1, .hw_val = 1 },
 	{ .pdiv = 2, .hw_val = 0 },
 	{ .pdiv = 0, .hw_val = 0 },
@@ -390,7 +385,7 @@ static struct tegra_clk_pll_params pll_u_params = {
 	.lock_delay = 1000,
 	.pdiv_tohw = pllu_p,
 	.freq_table = pll_u_freq_table,
-	.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -406,7 +401,7 @@ static struct tegra_clk_pll_params pll_x_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_x_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_e_params = {
@@ -421,8 +416,10 @@ static struct tegra_clk_pll_params pll_e_params = {
 	.lock_mask = PLLE_MISC_LOCK,
 	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
 	.lock_delay = 0,
+	.pdiv_tohw = plle_p,
 	.freq_table = pll_e_freq_table,
-	.flags = TEGRA_PLL_FIXED,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_LOCK_MISC |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 	.fixed_rate = 100000000,
 };
 
@@ -733,9 +730,9 @@ static void tegra20_super_clk_init(void)
 	clks[TEGRA20_CLK_TWD] = clk;
 }
 
-static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused",
-				      "pll_a_out0", "unused", "unused",
-				      "unused"};
+static const char *audio_parents[] = { "spdif_in", "i2s1", "i2s2", "unused",
+				       "pll_a_out0", "unused", "unused",
+				       "unused" };
 
 static void __init tegra20_audio_clk_init(void)
 {
@@ -759,19 +756,18 @@ static void __init tegra20_audio_clk_init(void)
 				    CLK_SET_RATE_PARENT, 89,
 				    periph_clk_enb_refcnt);
 	clks[TEGRA20_CLK_AUDIO_2X] = clk;
-
 }
 
-static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
-				     "clk_m"};
-static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
-				     "clk_m"};
-static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m",
-				    "clk_32k"};
-static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"};
-static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c",
-					"clk_m"};
-static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"};
+static const char *i2s1_parents[] = { "pll_a_out0", "audio_2x", "pll_p",
+				      "clk_m" };
+static const char *i2s2_parents[] = { "pll_a_out0", "audio_2x", "pll_p",
+				      "clk_m" };
+static const char *pwm_parents[] = { "pll_p", "pll_c", "audio", "clk_m",
+				     "clk_32k" };
+static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" };
+static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c",
+					 "clk_m" };
+static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" };
 
 static struct tegra_periph_init_data tegra_periph_clk_list[] = {
 	TEGRA_INIT_DATA_MUX("i2s1", i2s1_parents,     CLK_SOURCE_I2S1,   11, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S1),
@@ -802,7 +798,7 @@ static void __init tegra20_periph_clk_init(void)
 {
 	struct tegra_periph_init_data *data;
 	struct clk *clk;
-	int i;
+	unsigned int i;
 
 	/* ac97 */
 	clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0",
@@ -1025,44 +1021,45 @@ static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
 };
 
 static struct tegra_clk_init_table init_table[] __initdata = {
-	{TEGRA20_CLK_PLL_P, TEGRA20_CLK_CLK_MAX, 216000000, 1},
-	{TEGRA20_CLK_PLL_P_OUT1, TEGRA20_CLK_CLK_MAX, 28800000, 1},
-	{TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1},
-	{TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1},
-	{TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1},
-	{TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1},
-	{TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1},
-	{TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1},
-	{TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1},
-	{TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1},
-	{TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1},
-	{TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1},
-	{TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1},
-	{TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0},
-	{TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0},
-	{TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0},
-	{TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0},
-	{TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0},
-	{TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1},
-	{TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1},
-	{TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1},
-	{TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1},
-	{TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0},
-	{TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0},
-	{TEGRA20_CLK_SDMMC4, TEGRA20_CLK_PLL_P, 48000000, 0},
-	{TEGRA20_CLK_SPI, TEGRA20_CLK_PLL_P, 20000000, 0},
-	{TEGRA20_CLK_SBC1, TEGRA20_CLK_PLL_P, 100000000, 0},
-	{TEGRA20_CLK_SBC2, TEGRA20_CLK_PLL_P, 100000000, 0},
-	{TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0},
-	{TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0},
-	{TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0},
-	{TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0},
-	{TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0},
-	{TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0},
-	{TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0},
-	{TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry */
+	{ TEGRA20_CLK_PLL_P, TEGRA20_CLK_CLK_MAX, 216000000, 1 },
+	{ TEGRA20_CLK_PLL_P_OUT1, TEGRA20_CLK_CLK_MAX, 28800000, 1 },
+	{ TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1 },
+	{ TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 },
+	{ TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 },
+	{ TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 },
+	{ TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1 },
+	{ TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 },
+	{ TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 },
+	{ TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0 },
+	{ TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0 },
+	{ TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0 },
+	{ TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0 },
+	{ TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0 },
+	{ TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1 },
+	{ TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1 },
+	{ TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1 },
+	{ TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0 },
+	{ TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0 },
+	{ TEGRA20_CLK_SDMMC4, TEGRA20_CLK_PLL_P, 48000000, 0 },
+	{ TEGRA20_CLK_SPI, TEGRA20_CLK_PLL_P, 20000000, 0 },
+	{ TEGRA20_CLK_SBC1, TEGRA20_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA20_CLK_SBC2, TEGRA20_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0 },
+	{ TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0 },
+	{ TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 },
+	{ TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 },
+	{ TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 },
+	/* must be the last entry */
+	{ TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 },
 };
 
 static void __init tegra20_clock_apply_init_table(void)
@@ -1076,16 +1073,17 @@ static void __init tegra20_clock_apply_init_table(void)
  * table under two names.
  */
 static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
-	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,   "utmip-pad",    NULL),
-	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,   "tegra-ehci.0", NULL),
-	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,   "tegra-otg",    NULL),
-	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK,   NULL,           "cpu"),
-	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL), /* Must be the last entry */
+	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,    "utmip-pad",     NULL),
+	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,    "tegra-ehci.0",  NULL),
+	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,    "tegra-otg",     NULL),
+	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK,    NULL,           "cpu"),
+	/* must be the last entry */
+	TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL,            NULL),
 };
 
 static const struct of_device_id pmc_match[] __initconst = {
 	{ .compatible = "nvidia,tegra20-pmc" },
-	{},
+	{ },
 };
 
 static void __init tegra20_clock_init(struct device_node *np)
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
new file mode 100644
index 000000000000..58514c44ea83
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -0,0 +1,2852 @@
+/*
+ * Copyright (c) 2012-2014 NVIDIA 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/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+#include <dt-bindings/clock/tegra210-car.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+/*
+ * TEGRA210_CAR_BANK_COUNT: the number of peripheral clock register
+ * banks present in the Tegra210 CAR IP block.  The banks are
+ * identified by single letters, e.g.: L, H, U, V, W, X, Y.  See
+ * periph_regs[] in drivers/clk/tegra/clk.c
+ */
+#define TEGRA210_CAR_BANK_COUNT			7
+
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_EMC 0x19c
+
+#define PLLC_BASE 0x80
+#define PLLC_OUT 0x84
+#define PLLC_MISC0 0x88
+#define PLLC_MISC1 0x8c
+#define PLLC_MISC2 0x5d0
+#define PLLC_MISC3 0x5d4
+
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC0 0x4ec
+#define PLLC2_MISC1 0x4f0
+#define PLLC2_MISC2 0x4f4
+#define PLLC2_MISC3 0x4f8
+
+#define PLLC3_BASE 0x4fc
+#define PLLC3_MISC0 0x500
+#define PLLC3_MISC1 0x504
+#define PLLC3_MISC2 0x508
+#define PLLC3_MISC3 0x50c
+
+#define PLLM_BASE 0x90
+#define PLLM_MISC0 0x9c
+#define PLLM_MISC1 0x98
+#define PLLP_BASE 0xa0
+#define PLLP_MISC0 0xac
+#define PLLP_MISC1 0x680
+#define PLLA_BASE 0xb0
+#define PLLA_MISC0 0xbc
+#define PLLA_MISC1 0xb8
+#define PLLA_MISC2 0x5d8
+#define PLLD_BASE 0xd0
+#define PLLD_MISC0 0xdc
+#define PLLD_MISC1 0xd8
+#define PLLU_BASE 0xc0
+#define PLLU_OUTA 0xc4
+#define PLLU_MISC0 0xcc
+#define PLLU_MISC1 0xc8
+#define PLLX_BASE 0xe0
+#define PLLX_MISC0 0xe4
+#define PLLX_MISC1 0x510
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLX_MISC4 0x5f0
+#define PLLX_MISC5 0x5f4
+#define PLLE_BASE 0xe8
+#define PLLE_MISC0 0xec
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC0 0x4bc
+#define PLLD2_MISC1 0x570
+#define PLLD2_MISC2 0x574
+#define PLLD2_MISC3 0x578
+#define PLLE_AUX 0x48c
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC0 0x4c8
+#define PLLDP_BASE 0x590
+#define PLLDP_MISC 0x594
+
+#define PLLC4_BASE 0x5a4
+#define PLLC4_MISC0 0x5a8
+#define PLLC4_OUT 0x5e4
+#define PLLMB_BASE 0x5e8
+#define PLLMB_MISC0 0x5ec
+#define PLLA1_BASE 0x6a4
+#define PLLA1_MISC0 0x6a8
+#define PLLA1_MISC1 0x6ac
+#define PLLA1_MISC2 0x6b0
+#define PLLA1_MISC3 0x6b4
+
+#define PLLU_IDDQ_BIT 31
+#define PLLCX_IDDQ_BIT 27
+#define PLLRE_IDDQ_BIT 24
+#define PLLA_IDDQ_BIT 25
+#define PLLD_IDDQ_BIT 20
+#define PLLSS_IDDQ_BIT 18
+#define PLLM_IDDQ_BIT 5
+#define PLLMB_IDDQ_BIT 17
+#define PLLXP_IDDQ_BIT 3
+
+#define PLLCX_RESET_BIT 30
+
+#define PLL_BASE_LOCK BIT(27)
+#define PLLCX_BASE_LOCK BIT(26)
+#define PLLE_MISC_LOCK BIT(11)
+#define PLLRE_MISC_LOCK BIT(27)
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLC_MISC_LOCK_ENABLE 24
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLU_MISC_LOCK_ENABLE 29
+#define PLLE_MISC_LOCK_ENABLE 9
+#define PLLRE_MISC_LOCK_ENABLE 30
+#define PLLSS_MISC_LOCK_ENABLE 30
+#define PLLP_MISC_LOCK_ENABLE 18
+#define PLLM_MISC_LOCK_ENABLE 4
+#define PLLMB_MISC_LOCK_ENABLE 16
+#define PLLA_MISC_LOCK_ENABLE 28
+#define PLLU_MISC_LOCK_ENABLE 29
+#define PLLD_MISC_LOCK_ENABLE 18
+
+#define PLLA_SDM_DIN_MASK 0xffff
+#define PLLA_SDM_EN_MASK BIT(26)
+
+#define PLLD_SDM_EN_MASK BIT(16)
+
+#define PLLD2_SDM_EN_MASK BIT(31)
+#define PLLD2_SSC_EN_MASK BIT(30)
+
+#define PLLDP_SS_CFG	0x598
+#define PLLDP_SDM_EN_MASK BIT(31)
+#define PLLDP_SSC_EN_MASK BIT(30)
+#define PLLDP_SS_CTRL1	0x59c
+#define PLLDP_SS_CTRL2	0x5a0
+
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
+#define UTMIPLL_HW_PWRDN_CFG0			0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK	BIT(31)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE	BIT(25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE	BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE	BIT(7)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET	BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE	BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL	BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL	BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE	BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL	BIT(0)
+
+#define PLLU_HW_PWRDN_CFG0			0x530
+#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE	BIT(28)
+#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE		BIT(24)
+#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT	BIT(7)
+#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET		BIT(6)
+#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL	BIT(2)
+#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL	BIT(0)
+
+#define XUSB_PLL_CFG0				0x534
+#define XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY		0x3ff
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK	(0x3ff << 14)
+
+#define SPARE_REG0 0x55c
+#define CLK_M_DIVISOR_SHIFT 2
+#define CLK_M_DIVISOR_MASK 0x3
+
+/*
+ * SDM fractional divisor is 16-bit 2's complement signed number within
+ * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
+ * 16-bit value, with "0" divisor mapped to 0xFFFF. Data "0" is used to
+ * indicate that SDM is disabled.
+ *
+ * Effective ndiv value when SDM is enabled: ndiv + 1/2 + sdm_din/2^13
+ */
+#define PLL_SDM_COEFF BIT(13)
+#define sdin_din_to_data(din)	((u16)((din) ? : 0xFFFFU))
+#define sdin_data_to_din(dat)	(((dat) == 0xFFFFU) ? 0 : (s16)dat)
+
+/* Tegra CPU clock and reset control regs */
+#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
+
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+	u32 clk_csite_src;
+} tegra210_cpu_clk_sctx;
+#endif
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static unsigned long osc_freq;
+static unsigned long pll_ref_freq;
+
+static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_e_lock);
+static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(pll_u_lock);
+static DEFINE_SPINLOCK(emc_lock);
+
+/* possible OSC frequencies in Hz */
+static unsigned long tegra210_input_freq[] = {
+	[5] = 38400000,
+	[8] = 12000000,
+};
+
+static const char *mux_pllmcp_clkm[] = {
+	"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
+};
+#define mux_pllmcp_clkm_idx NULL
+
+#define PLL_ENABLE			(1 << 30)
+
+#define PLLCX_MISC1_IDDQ		(1 << 27)
+#define PLLCX_MISC0_RESET		(1 << 30)
+
+#define PLLCX_MISC0_DEFAULT_VALUE	0x40080000
+#define PLLCX_MISC0_WRITE_MASK		0x400ffffb
+#define PLLCX_MISC1_DEFAULT_VALUE	0x08000000
+#define PLLCX_MISC1_WRITE_MASK		0x08003cff
+#define PLLCX_MISC2_DEFAULT_VALUE	0x1f720f05
+#define PLLCX_MISC2_WRITE_MASK		0xffffff17
+#define PLLCX_MISC3_DEFAULT_VALUE	0x000000c4
+#define PLLCX_MISC3_WRITE_MASK		0x00ffffff
+
+/* PLLA */
+#define PLLA_BASE_IDDQ			(1 << 25)
+#define PLLA_BASE_LOCK			(1 << 27)
+
+#define PLLA_MISC0_LOCK_ENABLE		(1 << 28)
+#define PLLA_MISC0_LOCK_OVERRIDE	(1 << 27)
+
+#define PLLA_MISC2_EN_SDM		(1 << 26)
+#define PLLA_MISC2_EN_DYNRAMP		(1 << 25)
+
+#define PLLA_MISC0_DEFAULT_VALUE	0x12000020
+#define PLLA_MISC0_WRITE_MASK		0x7fffffff
+#define PLLA_MISC2_DEFAULT_VALUE	0x0
+#define PLLA_MISC2_WRITE_MASK		0x06ffffff
+
+/* PLLD */
+#define PLLD_MISC0_EN_SDM		(1 << 16)
+#define PLLD_MISC0_LOCK_OVERRIDE	(1 << 17)
+#define PLLD_MISC0_LOCK_ENABLE		(1 << 18)
+#define PLLD_MISC0_IDDQ			(1 << 20)
+#define PLLD_MISC0_DSI_CLKENABLE	(1 << 21)
+
+#define PLLD_MISC0_DEFAULT_VALUE	0x00140000
+#define PLLD_MISC0_WRITE_MASK		0x3ff7ffff
+#define PLLD_MISC1_DEFAULT_VALUE	0x20
+#define PLLD_MISC1_WRITE_MASK		0x00ffffff
+
+/* PLLD2 and PLLDP  and PLLC4 */
+#define PLLDSS_BASE_LOCK		(1 << 27)
+#define PLLDSS_BASE_LOCK_OVERRIDE	(1 << 24)
+#define PLLDSS_BASE_IDDQ		(1 << 18)
+#define PLLDSS_BASE_REF_SEL_SHIFT	25
+#define PLLDSS_BASE_REF_SEL_MASK	(0x3 << PLLDSS_BASE_REF_SEL_SHIFT)
+
+#define PLLDSS_MISC0_LOCK_ENABLE	(1 << 30)
+
+#define PLLDSS_MISC1_CFG_EN_SDM		(1 << 31)
+#define PLLDSS_MISC1_CFG_EN_SSC		(1 << 30)
+
+#define PLLD2_MISC0_DEFAULT_VALUE	0x40000020
+#define PLLD2_MISC1_CFG_DEFAULT_VALUE	0x10000000
+#define PLLD2_MISC2_CTRL1_DEFAULT_VALUE	0x0
+#define PLLD2_MISC3_CTRL2_DEFAULT_VALUE	0x0
+
+#define PLLDP_MISC0_DEFAULT_VALUE	0x40000020
+#define PLLDP_MISC1_CFG_DEFAULT_VALUE	0xc0000000
+#define PLLDP_MISC2_CTRL1_DEFAULT_VALUE	0xf400f0da
+#define PLLDP_MISC3_CTRL2_DEFAULT_VALUE	0x2004f400
+
+#define PLLDSS_MISC0_WRITE_MASK		0x47ffffff
+#define PLLDSS_MISC1_CFG_WRITE_MASK	0xf8000000
+#define PLLDSS_MISC2_CTRL1_WRITE_MASK	0xffffffff
+#define PLLDSS_MISC3_CTRL2_WRITE_MASK	0xffffffff
+
+#define PLLC4_MISC0_DEFAULT_VALUE	0x40000000
+
+/* PLLRE */
+#define PLLRE_MISC0_LOCK_ENABLE		(1 << 30)
+#define PLLRE_MISC0_LOCK_OVERRIDE	(1 << 29)
+#define PLLRE_MISC0_LOCK		(1 << 27)
+#define PLLRE_MISC0_IDDQ		(1 << 24)
+
+#define PLLRE_BASE_DEFAULT_VALUE	0x0
+#define PLLRE_MISC0_DEFAULT_VALUE	0x41000000
+
+#define PLLRE_BASE_DEFAULT_MASK		0x1c000000
+#define PLLRE_MISC0_WRITE_MASK		0x67ffffff
+
+/* PLLX */
+#define PLLX_USE_DYN_RAMP		1
+#define PLLX_BASE_LOCK			(1 << 27)
+
+#define PLLX_MISC0_FO_G_DISABLE		(0x1 << 28)
+#define PLLX_MISC0_LOCK_ENABLE		(0x1 << 18)
+
+#define PLLX_MISC2_DYNRAMP_STEPB_SHIFT	24
+#define PLLX_MISC2_DYNRAMP_STEPB_MASK	(0xFF << PLLX_MISC2_DYNRAMP_STEPB_SHIFT)
+#define PLLX_MISC2_DYNRAMP_STEPA_SHIFT	16
+#define PLLX_MISC2_DYNRAMP_STEPA_MASK	(0xFF << PLLX_MISC2_DYNRAMP_STEPA_SHIFT)
+#define PLLX_MISC2_NDIV_NEW_SHIFT	8
+#define PLLX_MISC2_NDIV_NEW_MASK	(0xFF << PLLX_MISC2_NDIV_NEW_SHIFT)
+#define PLLX_MISC2_LOCK_OVERRIDE	(0x1 << 4)
+#define PLLX_MISC2_DYNRAMP_DONE		(0x1 << 2)
+#define PLLX_MISC2_EN_DYNRAMP		(0x1 << 0)
+
+#define PLLX_MISC3_IDDQ			(0x1 << 3)
+
+#define PLLX_MISC0_DEFAULT_VALUE	PLLX_MISC0_LOCK_ENABLE
+#define PLLX_MISC0_WRITE_MASK		0x10c40000
+#define PLLX_MISC1_DEFAULT_VALUE	0x20
+#define PLLX_MISC1_WRITE_MASK		0x00ffffff
+#define PLLX_MISC2_DEFAULT_VALUE	0x0
+#define PLLX_MISC2_WRITE_MASK		0xffffff11
+#define PLLX_MISC3_DEFAULT_VALUE	PLLX_MISC3_IDDQ
+#define PLLX_MISC3_WRITE_MASK		0x01ff0f0f
+#define PLLX_MISC4_DEFAULT_VALUE	0x0
+#define PLLX_MISC4_WRITE_MASK		0x8000ffff
+#define PLLX_MISC5_DEFAULT_VALUE	0x0
+#define PLLX_MISC5_WRITE_MASK		0x0000ffff
+
+#define PLLX_HW_CTRL_CFG		0x548
+#define PLLX_HW_CTRL_CFG_SWCTRL		(0x1 << 0)
+
+/* PLLMB */
+#define PLLMB_BASE_LOCK			(1 << 27)
+
+#define PLLMB_MISC0_LOCK_OVERRIDE	(1 << 18)
+#define PLLMB_MISC0_IDDQ		(1 << 17)
+#define PLLMB_MISC0_LOCK_ENABLE		(1 << 16)
+
+#define PLLMB_MISC0_DEFAULT_VALUE	0x00030000
+#define PLLMB_MISC0_WRITE_MASK		0x0007ffff
+
+/* PLLP */
+#define PLLP_BASE_OVERRIDE		(1 << 28)
+#define PLLP_BASE_LOCK			(1 << 27)
+
+#define PLLP_MISC0_LOCK_ENABLE		(1 << 18)
+#define PLLP_MISC0_LOCK_OVERRIDE	(1 << 17)
+#define PLLP_MISC0_IDDQ			(1 << 3)
+
+#define PLLP_MISC1_HSIO_EN_SHIFT	29
+#define PLLP_MISC1_HSIO_EN		(1 << PLLP_MISC1_HSIO_EN_SHIFT)
+#define PLLP_MISC1_XUSB_EN_SHIFT	28
+#define PLLP_MISC1_XUSB_EN		(1 << PLLP_MISC1_XUSB_EN_SHIFT)
+
+#define PLLP_MISC0_DEFAULT_VALUE	0x00040008
+#define PLLP_MISC1_DEFAULT_VALUE	0x0
+
+#define PLLP_MISC0_WRITE_MASK		0xdc6000f
+#define PLLP_MISC1_WRITE_MASK		0x70ffffff
+
+/* PLLU */
+#define PLLU_BASE_LOCK			(1 << 27)
+#define PLLU_BASE_OVERRIDE		(1 << 24)
+#define PLLU_BASE_CLKENABLE_USB		(1 << 21)
+#define PLLU_BASE_CLKENABLE_HSIC	(1 << 22)
+#define PLLU_BASE_CLKENABLE_ICUSB	(1 << 23)
+#define PLLU_BASE_CLKENABLE_48M		(1 << 25)
+#define PLLU_BASE_CLKENABLE_ALL		(PLLU_BASE_CLKENABLE_USB |\
+					 PLLU_BASE_CLKENABLE_HSIC |\
+					 PLLU_BASE_CLKENABLE_ICUSB |\
+					 PLLU_BASE_CLKENABLE_48M)
+
+#define PLLU_MISC0_IDDQ			(1 << 31)
+#define PLLU_MISC0_LOCK_ENABLE		(1 << 29)
+#define PLLU_MISC1_LOCK_OVERRIDE	(1 << 0)
+
+#define PLLU_MISC0_DEFAULT_VALUE	0xa0000000
+#define PLLU_MISC1_DEFAULT_VALUE	0x0
+
+#define PLLU_MISC0_WRITE_MASK		0xbfffffff
+#define PLLU_MISC1_WRITE_MASK		0x00000007
+
+static inline void _pll_misc_chk_default(void __iomem *base,
+					struct tegra_clk_pll_params *params,
+					u8 misc_num, u32 default_val, u32 mask)
+{
+	u32 boot_val = readl_relaxed(base + params->ext_misc_reg[misc_num]);
+
+	boot_val &= mask;
+	default_val &= mask;
+	if (boot_val != default_val) {
+		pr_warn("boot misc%d 0x%x: expected 0x%x\n",
+			misc_num, boot_val, default_val);
+		pr_warn(" (comparison mask = 0x%x)\n", mask);
+		params->defaults_set = false;
+	}
+}
+
+/*
+ * PLLCX: PLLC, PLLC2, PLLC3, PLLA1
+ * Hybrid PLLs with dynamic ramp. Dynamic ramp is allowed for any transition
+ * that changes NDIV only, while PLL is already locked.
+ */
+static void pllcx_check_defaults(struct tegra_clk_pll_params *params)
+{
+	u32 default_val;
+
+	default_val = PLLCX_MISC0_DEFAULT_VALUE & (~PLLCX_MISC0_RESET);
+	_pll_misc_chk_default(clk_base, params, 0, default_val,
+			PLLCX_MISC0_WRITE_MASK);
+
+	default_val = PLLCX_MISC1_DEFAULT_VALUE & (~PLLCX_MISC1_IDDQ);
+	_pll_misc_chk_default(clk_base, params, 1, default_val,
+			PLLCX_MISC1_WRITE_MASK);
+
+	default_val = PLLCX_MISC2_DEFAULT_VALUE;
+	_pll_misc_chk_default(clk_base, params, 2, default_val,
+			PLLCX_MISC2_WRITE_MASK);
+
+	default_val = PLLCX_MISC3_DEFAULT_VALUE;
+	_pll_misc_chk_default(clk_base, params, 3, default_val,
+			PLLCX_MISC3_WRITE_MASK);
+}
+
+void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx)
+{
+	pllcx->params->defaults_set = true;
+
+	if (readl_relaxed(clk_base + pllcx->params->base_reg) &
+			PLL_ENABLE) {
+		/* PLL is ON: only check if defaults already set */
+		pllcx_check_defaults(pllcx->params);
+		pr_warn("%s already enabled. Postponing set full defaults\n",
+			name);
+		return;
+	}
+
+	/* Defaults assert PLL reset, and set IDDQ */
+	writel_relaxed(PLLCX_MISC0_DEFAULT_VALUE,
+			clk_base + pllcx->params->ext_misc_reg[0]);
+	writel_relaxed(PLLCX_MISC1_DEFAULT_VALUE,
+			clk_base + pllcx->params->ext_misc_reg[1]);
+	writel_relaxed(PLLCX_MISC2_DEFAULT_VALUE,
+			clk_base + pllcx->params->ext_misc_reg[2]);
+	writel_relaxed(PLLCX_MISC3_DEFAULT_VALUE,
+			clk_base + pllcx->params->ext_misc_reg[3]);
+	udelay(1);
+}
+
+void _pllc_set_defaults(struct tegra_clk_pll *pllcx)
+{
+	tegra210_pllcx_set_defaults("PLL_C", pllcx);
+}
+
+void _pllc2_set_defaults(struct tegra_clk_pll *pllcx)
+{
+	tegra210_pllcx_set_defaults("PLL_C2", pllcx);
+}
+
+void _pllc3_set_defaults(struct tegra_clk_pll *pllcx)
+{
+	tegra210_pllcx_set_defaults("PLL_C3", pllcx);
+}
+
+void _plla1_set_defaults(struct tegra_clk_pll *pllcx)
+{
+	tegra210_pllcx_set_defaults("PLL_A1", pllcx);
+}
+
+/*
+ * PLLA
+ * PLL with dynamic ramp and fractional SDM. Dynamic ramp is not used.
+ * Fractional SDM is allowed to provide exact audio rates.
+ */
+void tegra210_plla_set_defaults(struct tegra_clk_pll *plla)
+{
+	u32 mask;
+	u32 val = readl_relaxed(clk_base + plla->params->base_reg);
+
+	plla->params->defaults_set = true;
+
+	if (val & PLL_ENABLE) {
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		if (val & PLLA_BASE_IDDQ) {
+			pr_warn("PLL_A boot enabled with IDDQ set\n");
+			plla->params->defaults_set = false;
+		}
+
+		pr_warn("PLL_A already enabled. Postponing set full defaults\n");
+
+		val = PLLA_MISC0_DEFAULT_VALUE;	/* ignore lock enable */
+		mask = PLLA_MISC0_LOCK_ENABLE | PLLA_MISC0_LOCK_OVERRIDE;
+		_pll_misc_chk_default(clk_base, plla->params, 0, val,
+				~mask & PLLA_MISC0_WRITE_MASK);
+
+		val = PLLA_MISC2_DEFAULT_VALUE; /* ignore all but control bit */
+		_pll_misc_chk_default(clk_base, plla->params, 2, val,
+				PLLA_MISC2_EN_DYNRAMP);
+
+		/* Enable lock detect */
+		val = readl_relaxed(clk_base + plla->params->ext_misc_reg[0]);
+		val &= ~mask;
+		val |= PLLA_MISC0_DEFAULT_VALUE & mask;
+		writel_relaxed(val, clk_base + plla->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	/* set IDDQ, enable lock detect, disable dynamic ramp and SDM */
+	val |= PLLA_BASE_IDDQ;
+	writel_relaxed(val, clk_base + plla->params->base_reg);
+	writel_relaxed(PLLA_MISC0_DEFAULT_VALUE,
+			clk_base + plla->params->ext_misc_reg[0]);
+	writel_relaxed(PLLA_MISC2_DEFAULT_VALUE,
+			clk_base + plla->params->ext_misc_reg[2]);
+	udelay(1);
+}
+
+/*
+ * PLLD
+ * PLL with fractional SDM.
+ */
+void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
+{
+	u32 val;
+	u32 mask = 0xffff;
+
+	plld->params->defaults_set = true;
+
+	if (readl_relaxed(clk_base + plld->params->base_reg) &
+			PLL_ENABLE) {
+		pr_warn("PLL_D already enabled. Postponing set full defaults\n");
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		val = PLLD_MISC1_DEFAULT_VALUE;
+		_pll_misc_chk_default(clk_base, plld->params, 1,
+				val, PLLD_MISC1_WRITE_MASK);
+
+		/* ignore lock, DSI and SDM controls, make sure IDDQ not set */
+		val = PLLD_MISC0_DEFAULT_VALUE & (~PLLD_MISC0_IDDQ);
+		mask |= PLLD_MISC0_DSI_CLKENABLE | PLLD_MISC0_LOCK_ENABLE |
+			PLLD_MISC0_LOCK_OVERRIDE | PLLD_MISC0_EN_SDM;
+		_pll_misc_chk_default(clk_base, plld->params, 0, val,
+				~mask & PLLD_MISC0_WRITE_MASK);
+
+		/* Enable lock detect */
+		mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE;
+		val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
+		val &= ~mask;
+		val |= PLLD_MISC0_DEFAULT_VALUE & mask;
+		writel_relaxed(val, clk_base + plld->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
+	val &= PLLD_MISC0_DSI_CLKENABLE;
+	val |= PLLD_MISC0_DEFAULT_VALUE;
+	/* set IDDQ, enable lock detect, disable SDM */
+	writel_relaxed(val, clk_base + plld->params->ext_misc_reg[0]);
+	writel_relaxed(PLLD_MISC1_DEFAULT_VALUE, clk_base +
+			plld->params->ext_misc_reg[1]);
+	udelay(1);
+}
+
+/*
+ * PLLD2, PLLDP
+ * PLL with fractional SDM and Spread Spectrum (SDM is a must if SSC is used).
+ */
+static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss,
+		u32 misc0_val, u32 misc1_val, u32 misc2_val, u32 misc3_val)
+{
+	u32 default_val;
+	u32 val = readl_relaxed(clk_base + plldss->params->base_reg);
+
+	plldss->params->defaults_set = true;
+
+	if (val & PLL_ENABLE) {
+		pr_warn("%s already enabled. Postponing set full defaults\n",
+			 pll_name);
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		if (val & PLLDSS_BASE_IDDQ) {
+			pr_warn("plldss boot enabled with IDDQ set\n");
+			plldss->params->defaults_set = false;
+		}
+
+		/* ignore lock enable */
+		default_val = misc0_val;
+		_pll_misc_chk_default(clk_base, plldss->params, 0, default_val,
+				     PLLDSS_MISC0_WRITE_MASK &
+				     (~PLLDSS_MISC0_LOCK_ENABLE));
+
+		/*
+		 * If SSC is used, check all settings, otherwise just confirm
+		 * that SSC is not used on boot as well. Do nothing when using
+		 * this function for PLLC4 that has only MISC0.
+		 */
+		if (plldss->params->ssc_ctrl_en_mask) {
+			default_val = misc1_val;
+			_pll_misc_chk_default(clk_base, plldss->params, 1,
+				default_val, PLLDSS_MISC1_CFG_WRITE_MASK);
+			default_val = misc2_val;
+			_pll_misc_chk_default(clk_base, plldss->params, 2,
+				default_val, PLLDSS_MISC2_CTRL1_WRITE_MASK);
+			default_val = misc3_val;
+			_pll_misc_chk_default(clk_base, plldss->params, 3,
+				default_val, PLLDSS_MISC3_CTRL2_WRITE_MASK);
+		} else if (plldss->params->ext_misc_reg[1]) {
+			default_val = misc1_val;
+			_pll_misc_chk_default(clk_base, plldss->params, 1,
+				default_val, PLLDSS_MISC1_CFG_WRITE_MASK &
+				(~PLLDSS_MISC1_CFG_EN_SDM));
+		}
+
+		/* Enable lock detect */
+		if (val & PLLDSS_BASE_LOCK_OVERRIDE) {
+			val &= ~PLLDSS_BASE_LOCK_OVERRIDE;
+			writel_relaxed(val, clk_base +
+					plldss->params->base_reg);
+		}
+
+		val = readl_relaxed(clk_base + plldss->params->ext_misc_reg[0]);
+		val &= ~PLLDSS_MISC0_LOCK_ENABLE;
+		val |= misc0_val & PLLDSS_MISC0_LOCK_ENABLE;
+		writel_relaxed(val, clk_base + plldss->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	/* set IDDQ, enable lock detect, configure SDM/SSC  */
+	val |= PLLDSS_BASE_IDDQ;
+	val &= ~PLLDSS_BASE_LOCK_OVERRIDE;
+	writel_relaxed(val, clk_base + plldss->params->base_reg);
+
+	/* When using this function for PLLC4 exit here */
+	if (!plldss->params->ext_misc_reg[1]) {
+		writel_relaxed(misc0_val, clk_base +
+				plldss->params->ext_misc_reg[0]);
+		udelay(1);
+		return;
+	}
+
+	writel_relaxed(misc0_val, clk_base +
+			plldss->params->ext_misc_reg[0]);
+	/* if SSC used set by 1st enable */
+	writel_relaxed(misc1_val & (~PLLDSS_MISC1_CFG_EN_SSC),
+			clk_base + plldss->params->ext_misc_reg[1]);
+	writel_relaxed(misc2_val, clk_base + plldss->params->ext_misc_reg[2]);
+	writel_relaxed(misc3_val, clk_base + plldss->params->ext_misc_reg[3]);
+	udelay(1);
+}
+
+void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2)
+{
+	plldss_defaults("PLL_D2", plld2, PLLD2_MISC0_DEFAULT_VALUE,
+			PLLD2_MISC1_CFG_DEFAULT_VALUE,
+			PLLD2_MISC2_CTRL1_DEFAULT_VALUE,
+			PLLD2_MISC3_CTRL2_DEFAULT_VALUE);
+}
+
+void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp)
+{
+	plldss_defaults("PLL_DP", plldp, PLLDP_MISC0_DEFAULT_VALUE,
+			PLLDP_MISC1_CFG_DEFAULT_VALUE,
+			PLLDP_MISC2_CTRL1_DEFAULT_VALUE,
+			PLLDP_MISC3_CTRL2_DEFAULT_VALUE);
+}
+
+/*
+ * PLLC4
+ * Base and misc0 layout is the same as PLLD2/PLLDP, but no SDM/SSC support.
+ * VCO is exposed to the clock tree via fixed 1/3 and 1/5 dividers.
+ */
+void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4)
+{
+	plldss_defaults("PLL_C4", pllc4, PLLC4_MISC0_DEFAULT_VALUE, 0, 0, 0);
+}
+
+/*
+ * PLLRE
+ * VCO is exposed to the clock tree directly along with post-divider output
+ */
+void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre)
+{
+	u32 mask;
+	u32 val = readl_relaxed(clk_base + pllre->params->base_reg);
+
+	pllre->params->defaults_set = true;
+
+	if (val & PLL_ENABLE) {
+		pr_warn("PLL_RE already enabled. Postponing set full defaults\n");
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		val &= PLLRE_BASE_DEFAULT_MASK;
+		if (val != PLLRE_BASE_DEFAULT_VALUE) {
+			pr_warn("pllre boot base 0x%x : expected 0x%x\n",
+				val, PLLRE_BASE_DEFAULT_VALUE);
+			pr_warn("(comparison mask = 0x%x)\n",
+				PLLRE_BASE_DEFAULT_MASK);
+			pllre->params->defaults_set = false;
+		}
+
+		/* Ignore lock enable */
+		val = PLLRE_MISC0_DEFAULT_VALUE & (~PLLRE_MISC0_IDDQ);
+		mask = PLLRE_MISC0_LOCK_ENABLE | PLLRE_MISC0_LOCK_OVERRIDE;
+		_pll_misc_chk_default(clk_base, pllre->params, 0, val,
+				~mask & PLLRE_MISC0_WRITE_MASK);
+
+		/* Enable lock detect */
+		val = readl_relaxed(clk_base + pllre->params->ext_misc_reg[0]);
+		val &= ~mask;
+		val |= PLLRE_MISC0_DEFAULT_VALUE & mask;
+		writel_relaxed(val, clk_base + pllre->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	/* set IDDQ, enable lock detect */
+	val &= ~PLLRE_BASE_DEFAULT_MASK;
+	val |= PLLRE_BASE_DEFAULT_VALUE & PLLRE_BASE_DEFAULT_MASK;
+	writel_relaxed(val, clk_base + pllre->params->base_reg);
+	writel_relaxed(PLLRE_MISC0_DEFAULT_VALUE,
+			clk_base + pllre->params->ext_misc_reg[0]);
+	udelay(1);
+}
+
+static void pllx_get_dyn_steps(struct clk_hw *hw, u32 *step_a, u32 *step_b)
+{
+	unsigned long input_rate;
+
+	if (!IS_ERR_OR_NULL(hw->clk)) {
+		input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
+		/* cf rate */
+		input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate);
+	} else {
+		input_rate = 38400000;
+	}
+
+	switch (input_rate) {
+	case 12000000:
+	case 12800000:
+	case 13000000:
+		*step_a = 0x2B;
+		*step_b = 0x0B;
+		return;
+	case 19200000:
+		*step_a = 0x12;
+		*step_b = 0x08;
+		return;
+	case 38400000:
+		*step_a = 0x04;
+		*step_b = 0x05;
+		return;
+	default:
+		pr_err("%s: Unexpected reference rate %lu\n",
+			__func__, input_rate);
+		BUG();
+	}
+}
+
+static void pllx_check_defaults(struct tegra_clk_pll *pll)
+{
+	u32 default_val;
+
+	default_val = PLLX_MISC0_DEFAULT_VALUE;
+	/* ignore lock enable */
+	_pll_misc_chk_default(clk_base, pll->params, 0, default_val,
+			PLLX_MISC0_WRITE_MASK & (~PLLX_MISC0_LOCK_ENABLE));
+
+	default_val = PLLX_MISC1_DEFAULT_VALUE;
+	_pll_misc_chk_default(clk_base, pll->params, 1, default_val,
+			PLLX_MISC1_WRITE_MASK);
+
+	/* ignore all but control bit */
+	default_val = PLLX_MISC2_DEFAULT_VALUE;
+	_pll_misc_chk_default(clk_base, pll->params, 2,
+			default_val, PLLX_MISC2_EN_DYNRAMP);
+
+	default_val = PLLX_MISC3_DEFAULT_VALUE & (~PLLX_MISC3_IDDQ);
+	_pll_misc_chk_default(clk_base, pll->params, 3, default_val,
+			PLLX_MISC3_WRITE_MASK);
+
+	default_val = PLLX_MISC4_DEFAULT_VALUE;
+	_pll_misc_chk_default(clk_base, pll->params, 4, default_val,
+			PLLX_MISC4_WRITE_MASK);
+
+	default_val = PLLX_MISC5_DEFAULT_VALUE;
+	_pll_misc_chk_default(clk_base, pll->params, 5, default_val,
+			PLLX_MISC5_WRITE_MASK);
+}
+
+void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
+{
+	u32 val;
+	u32 step_a, step_b;
+
+	pllx->params->defaults_set = true;
+
+	/* Get ready dyn ramp state machine settings */
+	pllx_get_dyn_steps(&pllx->hw, &step_a, &step_b);
+	val = PLLX_MISC2_DEFAULT_VALUE & (~PLLX_MISC2_DYNRAMP_STEPA_MASK) &
+		(~PLLX_MISC2_DYNRAMP_STEPB_MASK);
+	val |= step_a << PLLX_MISC2_DYNRAMP_STEPA_SHIFT;
+	val |= step_b << PLLX_MISC2_DYNRAMP_STEPB_SHIFT;
+
+	if (readl_relaxed(clk_base + pllx->params->base_reg) & PLL_ENABLE) {
+		pr_warn("PLL_X already enabled. Postponing set full defaults\n");
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		pllx_check_defaults(pllx);
+
+		/* Configure dyn ramp, disable lock override */
+		writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+
+		/* Enable lock detect */
+		val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[0]);
+		val &= ~PLLX_MISC0_LOCK_ENABLE;
+		val |= PLLX_MISC0_DEFAULT_VALUE & PLLX_MISC0_LOCK_ENABLE;
+		writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	/* Enable lock detect and CPU output */
+	writel_relaxed(PLLX_MISC0_DEFAULT_VALUE, clk_base +
+			pllx->params->ext_misc_reg[0]);
+
+	/* Setup */
+	writel_relaxed(PLLX_MISC1_DEFAULT_VALUE, clk_base +
+			pllx->params->ext_misc_reg[1]);
+
+	/* Configure dyn ramp state machine, disable lock override */
+	writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+
+	/* Set IDDQ */
+	writel_relaxed(PLLX_MISC3_DEFAULT_VALUE, clk_base +
+			pllx->params->ext_misc_reg[3]);
+
+	/* Disable SDM */
+	writel_relaxed(PLLX_MISC4_DEFAULT_VALUE, clk_base +
+			pllx->params->ext_misc_reg[4]);
+	writel_relaxed(PLLX_MISC5_DEFAULT_VALUE, clk_base +
+			pllx->params->ext_misc_reg[5]);
+	udelay(1);
+}
+
+/* PLLMB */
+void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
+{
+	u32 mask, val = readl_relaxed(clk_base + pllmb->params->base_reg);
+
+	pllmb->params->defaults_set = true;
+
+	if (val & PLL_ENABLE) {
+		pr_warn("PLL_MB already enabled. Postponing set full defaults\n");
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		val = PLLMB_MISC0_DEFAULT_VALUE & (~PLLMB_MISC0_IDDQ);
+		mask = PLLMB_MISC0_LOCK_ENABLE | PLLMB_MISC0_LOCK_OVERRIDE;
+		_pll_misc_chk_default(clk_base, pllmb->params, 0, val,
+				~mask & PLLMB_MISC0_WRITE_MASK);
+
+		/* Enable lock detect */
+		val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]);
+		val &= ~mask;
+		val |= PLLMB_MISC0_DEFAULT_VALUE & mask;
+		writel_relaxed(val, clk_base + pllmb->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	/* set IDDQ, enable lock detect */
+	writel_relaxed(PLLMB_MISC0_DEFAULT_VALUE,
+			clk_base + pllmb->params->ext_misc_reg[0]);
+	udelay(1);
+}
+
+/*
+ * PLLP
+ * VCO is exposed to the clock tree directly along with post-divider output.
+ * Both VCO and post-divider output rates are fixed at 408MHz and 204MHz,
+ * respectively.
+ */
+static void pllp_check_defaults(struct tegra_clk_pll *pll, bool enabled)
+{
+	u32 val, mask;
+
+	/* Ignore lock enable (will be set), make sure not in IDDQ if enabled */
+	val = PLLP_MISC0_DEFAULT_VALUE & (~PLLP_MISC0_IDDQ);
+	mask = PLLP_MISC0_LOCK_ENABLE | PLLP_MISC0_LOCK_OVERRIDE;
+	if (!enabled)
+		mask |= PLLP_MISC0_IDDQ;
+	_pll_misc_chk_default(clk_base, pll->params, 0, val,
+			~mask & PLLP_MISC0_WRITE_MASK);
+
+	/* Ignore branch controls */
+	val = PLLP_MISC1_DEFAULT_VALUE;
+	mask = PLLP_MISC1_HSIO_EN | PLLP_MISC1_XUSB_EN;
+	_pll_misc_chk_default(clk_base, pll->params, 1, val,
+			~mask & PLLP_MISC1_WRITE_MASK);
+}
+
+void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
+{
+	u32 mask;
+	u32 val = readl_relaxed(clk_base + pllp->params->base_reg);
+
+	pllp->params->defaults_set = true;
+
+	if (val & PLL_ENABLE) {
+		pr_warn("PLL_P already enabled. Postponing set full defaults\n");
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		pllp_check_defaults(pllp, true);
+
+		/* Enable lock detect */
+		val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]);
+		mask = PLLP_MISC0_LOCK_ENABLE | PLLP_MISC0_LOCK_OVERRIDE;
+		val &= ~mask;
+		val |= PLLP_MISC0_DEFAULT_VALUE & mask;
+		writel_relaxed(val, clk_base + pllp->params->ext_misc_reg[0]);
+		udelay(1);
+
+		return;
+	}
+
+	/* set IDDQ, enable lock detect */
+	writel_relaxed(PLLP_MISC0_DEFAULT_VALUE,
+			clk_base + pllp->params->ext_misc_reg[0]);
+
+	/* Preserve branch control */
+	val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[1]);
+	mask = PLLP_MISC1_HSIO_EN | PLLP_MISC1_XUSB_EN;
+	val &= mask;
+	val |= ~mask & PLLP_MISC1_DEFAULT_VALUE;
+	writel_relaxed(val, clk_base + pllp->params->ext_misc_reg[1]);
+	udelay(1);
+}
+
+/*
+ * PLLU
+ * VCO is exposed to the clock tree directly along with post-divider output.
+ * Both VCO and post-divider output rates are fixed at 480MHz and 240MHz,
+ * respectively.
+ */
+static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control)
+{
+	u32 val, mask;
+
+	/* Ignore lock enable (will be set) and IDDQ if under h/w control */
+	val = PLLU_MISC0_DEFAULT_VALUE & (~PLLU_MISC0_IDDQ);
+	mask = PLLU_MISC0_LOCK_ENABLE | (hw_control ? PLLU_MISC0_IDDQ : 0);
+	_pll_misc_chk_default(clk_base, pll->params, 0, val,
+			~mask & PLLU_MISC0_WRITE_MASK);
+
+	val = PLLU_MISC1_DEFAULT_VALUE;
+	mask = PLLU_MISC1_LOCK_OVERRIDE;
+	_pll_misc_chk_default(clk_base, pll->params, 1, val,
+			~mask & PLLU_MISC1_WRITE_MASK);
+}
+
+void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
+{
+	u32 val = readl_relaxed(clk_base + pllu->params->base_reg);
+
+	pllu->params->defaults_set = true;
+
+	if (val & PLL_ENABLE) {
+		pr_warn("PLL_U already enabled. Postponing set full defaults\n");
+
+		/*
+		 * PLL is ON: check if defaults already set, then set those
+		 * that can be updated in flight.
+		 */
+		pllu_check_defaults(pllu, false);
+
+		/* Enable lock detect */
+		val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[0]);
+		val &= ~PLLU_MISC0_LOCK_ENABLE;
+		val |= PLLU_MISC0_DEFAULT_VALUE & PLLU_MISC0_LOCK_ENABLE;
+		writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[0]);
+
+		val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[1]);
+		val &= ~PLLU_MISC1_LOCK_OVERRIDE;
+		val |= PLLU_MISC1_DEFAULT_VALUE & PLLU_MISC1_LOCK_OVERRIDE;
+		writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[1]);
+		udelay(1);
+
+		return;
+	}
+
+	/* set IDDQ, enable lock detect */
+	writel_relaxed(PLLU_MISC0_DEFAULT_VALUE,
+			clk_base + pllu->params->ext_misc_reg[0]);
+	writel_relaxed(PLLU_MISC1_DEFAULT_VALUE,
+			clk_base + pllu->params->ext_misc_reg[1]);
+	udelay(1);
+}
+
+#define mask(w) ((1 << (w)) - 1)
+#define divm_mask(p) mask(p->params->div_nmp->divm_width)
+#define divn_mask(p) mask(p->params->div_nmp->divn_width)
+#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
+		      mask(p->params->div_nmp->divp_width))
+
+#define divm_shift(p) ((p)->params->div_nmp->divm_shift)
+#define divn_shift(p) ((p)->params->div_nmp->divn_shift)
+#define divp_shift(p) ((p)->params->div_nmp->divp_shift)
+
+#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p))
+#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p))
+#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p))
+
+#define PLL_LOCKDET_DELAY 2	/* Lock detection safety delays */
+static int tegra210_wait_for_mask(struct tegra_clk_pll *pll,
+				  u32 reg, u32 mask)
+{
+	int i;
+	u32 val = 0;
+
+	for (i = 0; i < pll->params->lock_delay / PLL_LOCKDET_DELAY + 1; i++) {
+		udelay(PLL_LOCKDET_DELAY);
+		val = readl_relaxed(clk_base + reg);
+		if ((val & mask) == mask) {
+			udelay(PLL_LOCKDET_DELAY);
+			return 0;
+		}
+	}
+	return -ETIMEDOUT;
+}
+
+static int tegra210_pllx_dyn_ramp(struct tegra_clk_pll *pllx,
+		struct tegra_clk_pll_freq_table *cfg)
+{
+	u32 val, base, ndiv_new_mask;
+
+	ndiv_new_mask = (divn_mask(pllx) >> pllx->params->div_nmp->divn_shift)
+			 << PLLX_MISC2_NDIV_NEW_SHIFT;
+
+	val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[2]);
+	val &= (~ndiv_new_mask);
+	val |= cfg->n << PLLX_MISC2_NDIV_NEW_SHIFT;
+	writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+	udelay(1);
+
+	val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[2]);
+	val |= PLLX_MISC2_EN_DYNRAMP;
+	writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+	udelay(1);
+
+	tegra210_wait_for_mask(pllx, pllx->params->ext_misc_reg[2],
+			       PLLX_MISC2_DYNRAMP_DONE);
+
+	base = readl_relaxed(clk_base + pllx->params->base_reg) &
+		(~divn_mask_shifted(pllx));
+	base |= cfg->n << pllx->params->div_nmp->divn_shift;
+	writel_relaxed(base, clk_base + pllx->params->base_reg);
+	udelay(1);
+
+	val &= ~PLLX_MISC2_EN_DYNRAMP;
+	writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+	udelay(1);
+
+	pr_debug("%s: dynamic ramp to m = %u n = %u p = %u, Fout = %lu kHz\n",
+		 __clk_get_name(pllx->hw.clk), cfg->m, cfg->n, cfg->p,
+		 cfg->input_rate / cfg->m * cfg->n /
+		 pllx->params->pdiv_tohw[cfg->p].pdiv / 1000);
+
+	return 0;
+}
+
+/*
+ * Common configuration for PLLs with fixed input divider policy:
+ * - always set fixed M-value based on the reference rate
+ * - always set P-value value 1:1 for output rates above VCO minimum, and
+ *   choose minimum necessary P-value for output rates below VCO maximum
+ * - calculate N-value based on selected M and P
+ * - calculate SDM_DIN fractional part
+ */
+static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
+			       struct tegra_clk_pll_freq_table *cfg,
+			       unsigned long rate, unsigned long input_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_params *params = pll->params;
+	int p;
+	unsigned long cf, p_rate;
+	u32 pdiv;
+
+	if (!rate)
+		return -EINVAL;
+
+	if (!(params->flags & TEGRA_PLL_VCO_OUT)) {
+		p = DIV_ROUND_UP(params->vco_min, rate);
+		p = params->round_p_to_pdiv(p, &pdiv);
+	} else {
+		p = rate >= params->vco_min ? 1 : -EINVAL;
+	}
+
+	if (IS_ERR_VALUE(p))
+		return -EINVAL;
+
+	cfg->m = tegra_pll_get_fixed_mdiv(hw, input_rate);
+	cfg->p = p;
+
+	/* Store P as HW value, as that is what is expected */
+	cfg->p = tegra_pll_p_div_to_hw(pll, cfg->p);
+
+	p_rate = rate * p;
+	if (p_rate > params->vco_max)
+		p_rate = params->vco_max;
+	cf = input_rate / cfg->m;
+	cfg->n = p_rate / cf;
+
+	cfg->sdm_data = 0;
+	if (params->sdm_ctrl_reg) {
+		unsigned long rem = p_rate - cf * cfg->n;
+		/* If ssc is enabled SDM enabled as well, even for integer n */
+		if (rem || params->ssc_ctrl_reg) {
+			u64 s = rem * PLL_SDM_COEFF;
+
+			do_div(s, cf);
+			s -= PLL_SDM_COEFF / 2;
+			cfg->sdm_data = sdin_din_to_data(s);
+		}
+	}
+
+	cfg->input_rate = input_rate;
+	cfg->output_rate = rate;
+
+	return 0;
+}
+
+/*
+ * clk_pll_set_gain - set gain to m, n to calculate correct VCO rate
+ *
+ * @cfg: struct tegra_clk_pll_freq_table * cfg
+ *
+ * For Normal mode:
+ *     Fvco = Fref * NDIV / MDIV
+ *
+ * For fractional mode:
+ *     Fvco = Fref * (NDIV + 0.5 + SDM_DIN / PLL_SDM_COEFF) / MDIV
+ */
+static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg)
+{
+	cfg->n = cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 +
+			sdin_data_to_din(cfg->sdm_data);
+	cfg->m *= PLL_SDM_COEFF;
+}
+
+unsigned long tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params,
+					  unsigned long parent_rate)
+{
+	unsigned long vco_min = params->vco_min;
+
+	params->vco_min += DIV_ROUND_UP(parent_rate, PLL_SDM_COEFF);
+	vco_min = min(vco_min, params->vco_min);
+
+	return vco_min;
+}
+
+static struct div_nmp pllx_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.divp_shift = 20,
+	.divp_width = 5,
+};
+/*
+ * PLL post divider maps - two types: quasi-linear and exponential
+ * post divider.
+ */
+#define PLL_QLIN_PDIV_MAX	16
+static const struct pdiv_map pll_qlin_pdiv_to_hw[] = {
+	{ .pdiv =  1, .hw_val =  0 },
+	{ .pdiv =  2, .hw_val =  1 },
+	{ .pdiv =  3, .hw_val =  2 },
+	{ .pdiv =  4, .hw_val =  3 },
+	{ .pdiv =  5, .hw_val =  4 },
+	{ .pdiv =  6, .hw_val =  5 },
+	{ .pdiv =  8, .hw_val =  6 },
+	{ .pdiv =  9, .hw_val =  7 },
+	{ .pdiv = 10, .hw_val =  8 },
+	{ .pdiv = 12, .hw_val =  9 },
+	{ .pdiv = 15, .hw_val = 10 },
+	{ .pdiv = 16, .hw_val = 11 },
+	{ .pdiv = 18, .hw_val = 12 },
+	{ .pdiv = 20, .hw_val = 13 },
+	{ .pdiv = 24, .hw_val = 14 },
+	{ .pdiv = 30, .hw_val = 15 },
+	{ .pdiv = 32, .hw_val = 16 },
+};
+
+static u32 pll_qlin_p_to_pdiv(u32 p, u32 *pdiv)
+{
+	int i;
+
+	if (p) {
+		for (i = 0; i <= PLL_QLIN_PDIV_MAX; i++) {
+			if (p <= pll_qlin_pdiv_to_hw[i].pdiv) {
+				if (pdiv)
+					*pdiv = i;
+				return pll_qlin_pdiv_to_hw[i].pdiv;
+			}
+		}
+	}
+
+	return -EINVAL;
+}
+
+#define PLL_EXPO_PDIV_MAX	7
+static const struct pdiv_map pll_expo_pdiv_to_hw[] = {
+	{ .pdiv =   1, .hw_val = 0 },
+	{ .pdiv =   2, .hw_val = 1 },
+	{ .pdiv =   4, .hw_val = 2 },
+	{ .pdiv =   8, .hw_val = 3 },
+	{ .pdiv =  16, .hw_val = 4 },
+	{ .pdiv =  32, .hw_val = 5 },
+	{ .pdiv =  64, .hw_val = 6 },
+	{ .pdiv = 128, .hw_val = 7 },
+};
+
+static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
+{
+	if (p) {
+		u32 i = fls(p);
+
+		if (i == ffs(p))
+			i--;
+
+		if (i <= PLL_EXPO_PDIV_MAX) {
+			if (pdiv)
+				*pdiv = i;
+			return 1 << i;
+		}
+	}
+	return -EINVAL;
+}
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+	/* 1 GHz */
+	{ 12000000, 1000000000, 166, 1, 1, 0 }, /* actual: 996.0 MHz */
+	{ 13000000, 1000000000, 153, 1, 1, 0 }, /* actual: 994.0 MHz */
+	{ 38400000, 1000000000, 156, 3, 1, 0 }, /* actual: 998.4 MHz */
+	{        0,          0,   0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 38400000,
+	.vco_min = 1350000000,
+	.vco_max = 3000000000UL,
+	.base_reg = PLLX_BASE,
+	.misc_reg = PLLX_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.ext_misc_reg[0] = PLLX_MISC0,
+	.ext_misc_reg[1] = PLLX_MISC1,
+	.ext_misc_reg[2] = PLLX_MISC2,
+	.ext_misc_reg[3] = PLLX_MISC3,
+	.ext_misc_reg[4] = PLLX_MISC4,
+	.ext_misc_reg[5] = PLLX_MISC5,
+	.iddq_reg = PLLX_MISC3,
+	.iddq_bit_idx = PLLXP_IDDQ_BIT,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.mdiv_default = 2,
+	.dyn_ramp_reg = PLLX_MISC2,
+	.stepa_shift = 16,
+	.stepb_shift = 24,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllx_nmp,
+	.freq_table = pll_x_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.dyn_ramp = tegra210_pllx_dyn_ramp,
+	.set_defaults = tegra210_pllx_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct div_nmp pllc_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 10,
+	.divn_width = 8,
+	.divp_shift = 20,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
+	{ 12000000, 510000000, 85, 1, 1, 0 },
+	{ 13000000, 510000000, 78, 1, 1, 0 }, /* actual: 507.0 MHz */
+	{ 38400000, 510000000, 79, 3, 1, 0 }, /* actual: 505.6 MHz */
+	{        0,         0,  0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_c_params = {
+	.input_min = 12000000,
+	.input_max = 700000000,
+	.cf_min = 12000000,
+	.cf_max = 50000000,
+	.vco_min = 600000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLC_BASE,
+	.misc_reg = PLLC_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_delay = 300,
+	.iddq_reg = PLLC_MISC1,
+	.iddq_bit_idx = PLLCX_IDDQ_BIT,
+	.reset_reg = PLLC_MISC0,
+	.reset_bit_idx = PLLCX_RESET_BIT,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLC_MISC0,
+	.ext_misc_reg[1] = PLLC_MISC1,
+	.ext_misc_reg[2] = PLLC_MISC2,
+	.ext_misc_reg[3] = PLLC_MISC3,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.mdiv_default = 3,
+	.div_nmp = &pllc_nmp,
+	.freq_table = pll_cx_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.set_defaults = _pllc_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct div_nmp pllcx_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 10,
+	.divn_width = 8,
+	.divp_shift = 20,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_params pll_c2_params = {
+	.input_min = 12000000,
+	.input_max = 700000000,
+	.cf_min = 12000000,
+	.cf_max = 50000000,
+	.vco_min = 600000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLC2_BASE,
+	.misc_reg = PLLC2_MISC0,
+	.iddq_reg = PLLC2_MISC1,
+	.iddq_bit_idx = PLLCX_IDDQ_BIT,
+	.reset_reg = PLLC2_MISC0,
+	.reset_bit_idx = PLLCX_RESET_BIT,
+	.lock_mask = PLLCX_BASE_LOCK,
+	.lock_delay = 300,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.mdiv_default = 3,
+	.div_nmp = &pllcx_nmp,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLC2_MISC0,
+	.ext_misc_reg[1] = PLLC2_MISC1,
+	.ext_misc_reg[2] = PLLC2_MISC2,
+	.ext_misc_reg[3] = PLLC2_MISC3,
+	.freq_table = pll_cx_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.set_defaults = _pllc2_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct tegra_clk_pll_params pll_c3_params = {
+	.input_min = 12000000,
+	.input_max = 700000000,
+	.cf_min = 12000000,
+	.cf_max = 50000000,
+	.vco_min = 600000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLC3_BASE,
+	.misc_reg = PLLC3_MISC0,
+	.lock_mask = PLLCX_BASE_LOCK,
+	.lock_delay = 300,
+	.iddq_reg = PLLC3_MISC1,
+	.iddq_bit_idx = PLLCX_IDDQ_BIT,
+	.reset_reg = PLLC3_MISC0,
+	.reset_bit_idx = PLLCX_RESET_BIT,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.mdiv_default = 3,
+	.div_nmp = &pllcx_nmp,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLC3_MISC0,
+	.ext_misc_reg[1] = PLLC3_MISC1,
+	.ext_misc_reg[2] = PLLC3_MISC2,
+	.ext_misc_reg[3] = PLLC3_MISC3,
+	.freq_table = pll_cx_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.set_defaults = _pllc3_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct div_nmp pllss_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.divp_shift = 19,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = {
+	{ 12000000, 600000000, 50, 1, 0, 0 },
+	{ 13000000, 600000000, 46, 1, 0, 0 }, /* actual: 598.0 MHz */
+	{ 38400000, 600000000, 62, 4, 0, 0 }, /* actual: 595.2 MHz */
+	{        0,         0,  0, 0, 0, 0 },
+};
+
+static const struct clk_div_table pll_vco_post_div_table[] = {
+	{ .val =  0, .div =  1 },
+	{ .val =  1, .div =  2 },
+	{ .val =  2, .div =  3 },
+	{ .val =  3, .div =  4 },
+	{ .val =  4, .div =  5 },
+	{ .val =  5, .div =  6 },
+	{ .val =  6, .div =  8 },
+	{ .val =  7, .div = 10 },
+	{ .val =  8, .div = 12 },
+	{ .val =  9, .div = 16 },
+	{ .val = 10, .div = 12 },
+	{ .val = 11, .div = 16 },
+	{ .val = 12, .div = 20 },
+	{ .val = 13, .div = 24 },
+	{ .val = 14, .div = 32 },
+	{ .val =  0, .div =  0 },
+};
+
+static struct tegra_clk_pll_params pll_c4_vco_params = {
+	.input_min = 9600000,
+	.input_max = 800000000,
+	.cf_min = 9600000,
+	.cf_max = 19200000,
+	.vco_min = 500000000,
+	.vco_max = 1080000000,
+	.base_reg = PLLC4_BASE,
+	.misc_reg = PLLC4_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLC4_MISC0,
+	.iddq_reg = PLLC4_BASE,
+	.iddq_bit_idx = PLLSS_IDDQ_BIT,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.mdiv_default = 3,
+	.div_nmp = &pllss_nmp,
+	.freq_table = pll_c4_vco_freq_table,
+	.set_defaults = tegra210_pllc4_set_defaults,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
+		 TEGRA_PLL_VCO_OUT,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+	{ 12000000,  800000000,  66, 1, 0, 0 }, /* actual: 792.0 MHz */
+	{ 13000000,  800000000,  61, 1, 0, 0 }, /* actual: 793.0 MHz */
+	{ 38400000,  297600000,  93, 4, 2, 0 },
+	{ 38400000,  400000000, 125, 4, 2, 0 },
+	{ 38400000,  532800000, 111, 4, 1, 0 },
+	{ 38400000,  665600000, 104, 3, 1, 0 },
+	{ 38400000,  800000000, 125, 3, 1, 0 },
+	{ 38400000,  931200000,  97, 4, 0, 0 },
+	{ 38400000, 1065600000, 111, 4, 0, 0 },
+	{ 38400000, 1200000000, 125, 4, 0, 0 },
+	{ 38400000, 1331200000, 104, 3, 0, 0 },
+	{ 38400000, 1459200000,  76, 2, 0, 0 },
+	{ 38400000, 1600000000, 125, 3, 0, 0 },
+	{        0,          0,   0, 0, 0, 0 },
+};
+
+static struct div_nmp pllm_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.override_divm_shift = 0,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.override_divn_shift = 8,
+	.divp_shift = 20,
+	.divp_width = 5,
+	.override_divp_shift = 27,
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+	.input_min = 9600000,
+	.input_max = 500000000,
+	.cf_min = 9600000,
+	.cf_max = 19200000,
+	.vco_min = 800000000,
+	.vco_max = 1866000000,
+	.base_reg = PLLM_BASE,
+	.misc_reg = PLLM_MISC1,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLM_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLM_MISC0,
+	.iddq_bit_idx = PLLM_IDDQ_BIT,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLM_MISC0,
+	.ext_misc_reg[0] = PLLM_MISC1,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllm_nmp,
+	.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
+	.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
+	.freq_table = pll_m_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct tegra_clk_pll_params pll_mb_params = {
+	.input_min = 9600000,
+	.input_max = 500000000,
+	.cf_min = 9600000,
+	.cf_max = 19200000,
+	.vco_min = 800000000,
+	.vco_max = 1866000000,
+	.base_reg = PLLMB_BASE,
+	.misc_reg = PLLMB_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLMB_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLMB_MISC0,
+	.iddq_bit_idx = PLLMB_IDDQ_BIT,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLMB_MISC0,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllm_nmp,
+	.freq_table = pll_m_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.set_defaults = tegra210_pllmb_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+	/* PLLE special case: use cpcon field to store cml divider value */
+	{ 672000000, 100000000, 125, 42, 0, 13 },
+	{ 624000000, 100000000, 125, 39, 0, 13 },
+	{ 336000000, 100000000, 125, 21, 0, 13 },
+	{ 312000000, 100000000, 200, 26, 0, 14 },
+	{  38400000, 100000000, 125,  2, 0, 14 },
+	{  12000000, 100000000, 200,  1, 0, 14 },
+	{         0,         0,   0,  0, 0,  0 },
+};
+
+static struct div_nmp plle_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.divp_shift = 24,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 38400000,
+	.vco_min = 1600000000,
+	.vco_max = 2500000000U,
+	.base_reg = PLLE_BASE,
+	.misc_reg = PLLE_MISC0,
+	.aux_reg = PLLE_AUX,
+	.lock_mask = PLLE_MISC_LOCK,
+	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.div_nmp = &plle_nmp,
+	.freq_table = pll_e_freq_table,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_LOCK_MISC | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
+	.fixed_rate = 100000000,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct tegra_clk_pll_freq_table pll_re_vco_freq_table[] = {
+	{ 12000000, 672000000, 56, 1, 0, 0 },
+	{ 13000000, 672000000, 51, 1, 0, 0 }, /* actual: 663.0 MHz */
+	{ 38400000, 672000000, 70, 4, 0, 0 },
+	{        0,         0,  0, 0, 0, 0 },
+};
+
+static struct div_nmp pllre_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.divp_shift = 16,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_params pll_re_vco_params = {
+	.input_min = 9600000,
+	.input_max = 800000000,
+	.cf_min = 9600000,
+	.cf_max = 19200000,
+	.vco_min = 350000000,
+	.vco_max = 700000000,
+	.base_reg = PLLRE_BASE,
+	.misc_reg = PLLRE_MISC0,
+	.lock_mask = PLLRE_MISC_LOCK,
+	.lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.ext_misc_reg[0] = PLLRE_MISC0,
+	.iddq_reg = PLLRE_MISC0,
+	.iddq_bit_idx = PLLRE_IDDQ_BIT,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllre_nmp,
+	.freq_table = pll_re_vco_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC |
+		 TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT,
+	.set_defaults = tegra210_pllre_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct div_nmp pllp_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 10,
+	.divn_width = 8,
+	.divp_shift = 20,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+	{ 12000000, 408000000, 34, 1, 0, 0 },
+	{ 38400000, 408000000, 85, 8, 0, 0 }, /* cf = 4.8MHz, allowed exception */
+	{        0,         0,  0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+	.input_min = 9600000,
+	.input_max = 800000000,
+	.cf_min = 9600000,
+	.cf_max = 19200000,
+	.vco_min = 350000000,
+	.vco_max = 700000000,
+	.base_reg = PLLP_BASE,
+	.misc_reg = PLLP_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLP_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLP_MISC0,
+	.iddq_bit_idx = PLLXP_IDDQ_BIT,
+	.ext_misc_reg[0] = PLLP_MISC0,
+	.ext_misc_reg[1] = PLLP_MISC1,
+	.div_nmp = &pllp_nmp,
+	.freq_table = pll_p_freq_table,
+	.fixed_rate = 408000000,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT,
+	.set_defaults = tegra210_pllp_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct tegra_clk_pll_params pll_a1_params = {
+	.input_min = 12000000,
+	.input_max = 700000000,
+	.cf_min = 12000000,
+	.cf_max = 50000000,
+	.vco_min = 600000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLA1_BASE,
+	.misc_reg = PLLA1_MISC0,
+	.lock_mask = PLLCX_BASE_LOCK,
+	.lock_delay = 300,
+	.iddq_reg = PLLA1_MISC0,
+	.iddq_bit_idx = PLLCX_IDDQ_BIT,
+	.reset_reg = PLLA1_MISC0,
+	.reset_bit_idx = PLLCX_RESET_BIT,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllc_nmp,
+	.ext_misc_reg[0] = PLLA1_MISC0,
+	.ext_misc_reg[1] = PLLA1_MISC1,
+	.ext_misc_reg[2] = PLLA1_MISC2,
+	.ext_misc_reg[3] = PLLA1_MISC3,
+	.freq_table = pll_cx_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.set_defaults = _plla1_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+static struct div_nmp plla_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.divp_shift = 20,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+	{ 12000000, 282240000, 47, 1, 1, 1, 0xf148 }, /* actual: 282240234 */
+	{ 12000000, 368640000, 61, 1, 1, 1, 0xfe15 }, /* actual: 368640381 */
+	{ 12000000, 240000000, 60, 1, 2, 1,      0 },
+	{ 13000000, 282240000, 43, 1, 1, 1, 0xfd7d }, /* actual: 282239807 */
+	{ 13000000, 368640000, 56, 1, 1, 1, 0x06d8 }, /* actual: 368640137 */
+	{ 13000000, 240000000, 55, 1, 2, 1,      0 }, /* actual: 238.3 MHz */
+	{ 38400000, 282240000, 44, 3, 1, 1, 0xf333 }, /* actual: 282239844 */
+	{ 38400000, 368640000, 57, 3, 1, 1, 0x0333 }, /* actual: 368639844 */
+	{ 38400000, 240000000, 75, 3, 3, 1,      0 },
+	{        0,         0,  0, 0, 0, 0,      0 },
+};
+
+static struct tegra_clk_pll_params pll_a_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000,
+	.vco_min = 500000000,
+	.vco_max = 1000000000,
+	.base_reg = PLLA_BASE,
+	.misc_reg = PLLA_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLA_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.iddq_reg = PLLA_BASE,
+	.iddq_bit_idx = PLLA_IDDQ_BIT,
+	.div_nmp = &plla_nmp,
+	.sdm_din_reg = PLLA_MISC1,
+	.sdm_din_mask = PLLA_SDM_DIN_MASK,
+	.sdm_ctrl_reg = PLLA_MISC2,
+	.sdm_ctrl_en_mask = PLLA_SDM_EN_MASK,
+	.ext_misc_reg[0] = PLLA_MISC0,
+	.ext_misc_reg[1] = PLLA_MISC1,
+	.ext_misc_reg[2] = PLLA_MISC2,
+	.freq_table = pll_a_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
+	.set_defaults = tegra210_plla_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+	.set_gain = tegra210_clk_pll_set_gain,
+	.adjust_vco = tegra210_clk_adjust_vco_min,
+};
+
+static struct div_nmp plld_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 11,
+	.divn_width = 8,
+	.divp_shift = 20,
+	.divp_width = 3,
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+	{ 12000000, 594000000, 99, 1, 1, 0,      0 },
+	{ 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */
+	{ 38400000, 594000000, 30, 1, 1, 0, 0x0e00 },
+	{        0,         0,  0, 0, 0, 0,      0 },
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 38400000,
+	.vco_min = 750000000,
+	.vco_max = 1500000000,
+	.base_reg = PLLD_BASE,
+	.misc_reg = PLLD_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLD_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+	.iddq_reg = PLLD_MISC0,
+	.iddq_bit_idx = PLLD_IDDQ_BIT,
+	.round_p_to_pdiv = pll_expo_p_to_pdiv,
+	.pdiv_tohw = pll_expo_pdiv_to_hw,
+	.div_nmp = &plld_nmp,
+	.sdm_din_reg = PLLD_MISC0,
+	.sdm_din_mask = PLLA_SDM_DIN_MASK,
+	.sdm_ctrl_reg = PLLD_MISC0,
+	.sdm_ctrl_en_mask = PLLD_SDM_EN_MASK,
+	.ext_misc_reg[0] = PLLD_MISC0,
+	.ext_misc_reg[1] = PLLD_MISC1,
+	.freq_table = pll_d_freq_table,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.mdiv_default = 1,
+	.set_defaults = tegra210_plld_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+	.set_gain = tegra210_clk_pll_set_gain,
+	.adjust_vco = tegra210_clk_adjust_vco_min,
+};
+
+static struct tegra_clk_pll_freq_table tegra210_pll_d2_freq_table[] = {
+	{ 12000000, 594000000, 99, 1, 1, 0, 0xf000 },
+	{ 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */
+	{ 38400000, 594000000, 30, 1, 1, 0, 0x0e00 },
+	{        0,         0,  0, 0, 0, 0,      0 },
+};
+
+/* s/w policy, always tegra_pll_ref */
+static struct tegra_clk_pll_params pll_d2_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 38400000,
+	.vco_min = 750000000,
+	.vco_max = 1500000000,
+	.base_reg = PLLD2_BASE,
+	.misc_reg = PLLD2_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLD2_BASE,
+	.iddq_bit_idx = PLLSS_IDDQ_BIT,
+	.sdm_din_reg = PLLD2_MISC3,
+	.sdm_din_mask = PLLA_SDM_DIN_MASK,
+	.sdm_ctrl_reg = PLLD2_MISC1,
+	.sdm_ctrl_en_mask = PLLD2_SDM_EN_MASK,
+	.ssc_ctrl_reg = PLLD2_MISC1,
+	.ssc_ctrl_en_mask = PLLD2_SSC_EN_MASK,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllss_nmp,
+	.ext_misc_reg[0] = PLLD2_MISC0,
+	.ext_misc_reg[1] = PLLD2_MISC1,
+	.ext_misc_reg[2] = PLLD2_MISC2,
+	.ext_misc_reg[3] = PLLD2_MISC3,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.mdiv_default = 1,
+	.freq_table = tegra210_pll_d2_freq_table,
+	.set_defaults = tegra210_plld2_set_defaults,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+	.set_gain = tegra210_clk_pll_set_gain,
+	.adjust_vco = tegra210_clk_adjust_vco_min,
+};
+
+static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = {
+	{ 12000000, 270000000, 90, 1, 3, 0, 0xf000 },
+	{ 13000000, 270000000, 83, 1, 3, 0, 0xf000 }, /* actual: 269.8 MHz */
+	{ 38400000, 270000000, 28, 1, 3, 0, 0xf400 },
+	{        0,         0,  0, 0, 0, 0,      0 },
+};
+
+static struct tegra_clk_pll_params pll_dp_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 38400000,
+	.vco_min = 750000000,
+	.vco_max = 1500000000,
+	.base_reg = PLLDP_BASE,
+	.misc_reg = PLLDP_MISC,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLDP_BASE,
+	.iddq_bit_idx = PLLSS_IDDQ_BIT,
+	.sdm_din_reg = PLLDP_SS_CTRL2,
+	.sdm_din_mask = PLLA_SDM_DIN_MASK,
+	.sdm_ctrl_reg = PLLDP_SS_CFG,
+	.sdm_ctrl_en_mask = PLLDP_SDM_EN_MASK,
+	.ssc_ctrl_reg = PLLDP_SS_CFG,
+	.ssc_ctrl_en_mask = PLLDP_SSC_EN_MASK,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllss_nmp,
+	.ext_misc_reg[0] = PLLDP_MISC,
+	.ext_misc_reg[1] = PLLDP_SS_CFG,
+	.ext_misc_reg[2] = PLLDP_SS_CTRL1,
+	.ext_misc_reg[3] = PLLDP_SS_CTRL2,
+	.max_p = PLL_QLIN_PDIV_MAX,
+	.mdiv_default = 1,
+	.freq_table = pll_dp_freq_table,
+	.set_defaults = tegra210_plldp_set_defaults,
+	.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+	.set_gain = tegra210_clk_pll_set_gain,
+	.adjust_vco = tegra210_clk_adjust_vco_min,
+};
+
+static struct div_nmp pllu_nmp = {
+	.divm_shift = 0,
+	.divm_width = 8,
+	.divn_shift = 8,
+	.divn_width = 8,
+	.divp_shift = 16,
+	.divp_width = 5,
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+	{ 12000000, 480000000, 40, 1, 0, 0 },
+	{ 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */
+	{ 38400000, 480000000, 25, 2, 0, 0 },
+	{        0,         0,  0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_u_vco_params = {
+	.input_min = 9600000,
+	.input_max = 800000000,
+	.cf_min = 9600000,
+	.cf_max = 19200000,
+	.vco_min = 350000000,
+	.vco_max = 700000000,
+	.base_reg = PLLU_BASE,
+	.misc_reg = PLLU_MISC0,
+	.lock_mask = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+	.iddq_reg = PLLU_MISC0,
+	.iddq_bit_idx = PLLU_IDDQ_BIT,
+	.ext_misc_reg[0] = PLLU_MISC0,
+	.ext_misc_reg[1] = PLLU_MISC1,
+	.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+	.pdiv_tohw = pll_qlin_pdiv_to_hw,
+	.div_nmp = &pllu_nmp,
+	.freq_table = pll_u_freq_table,
+	.flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
+		 TEGRA_PLL_VCO_OUT,
+	.set_defaults = tegra210_pllu_set_defaults,
+	.calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+struct utmi_clk_param {
+	/* Oscillator Frequency in KHz */
+	u32 osc_frequency;
+	/* UTMIP PLL Enable Delay Count  */
+	u8 enable_delay_count;
+	/* UTMIP PLL Stable count */
+	u16 stable_count;
+	/*  UTMIP PLL Active delay count */
+	u8 active_delay_count;
+	/* UTMIP PLL Xtal frequency count */
+	u16 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+	{
+		.osc_frequency = 38400000, .enable_delay_count = 0x0,
+		.stable_count = 0x0, .active_delay_count = 0x6,
+		.xtal_freq_count = 0x80
+	}, {
+		.osc_frequency = 13000000, .enable_delay_count = 0x02,
+		.stable_count = 0x33, .active_delay_count = 0x05,
+		.xtal_freq_count = 0x7f
+	}, {
+		.osc_frequency = 19200000, .enable_delay_count = 0x03,
+		.stable_count = 0x4b, .active_delay_count = 0x06,
+		.xtal_freq_count = 0xbb
+	}, {
+		.osc_frequency = 12000000, .enable_delay_count = 0x02,
+		.stable_count = 0x2f, .active_delay_count = 0x08,
+		.xtal_freq_count = 0x76
+	}, {
+		.osc_frequency = 26000000, .enable_delay_count = 0x04,
+		.stable_count = 0x66, .active_delay_count = 0x09,
+		.xtal_freq_count = 0xfe
+	}, {
+		.osc_frequency = 16800000, .enable_delay_count = 0x03,
+		.stable_count = 0x41, .active_delay_count = 0x0a,
+		.xtal_freq_count = 0xa4
+	},
+};
+
+static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
+	[tegra_clk_ispb] = { .dt_id = TEGRA210_CLK_ISPB, .present = true },
+	[tegra_clk_rtc] = { .dt_id = TEGRA210_CLK_RTC, .present = true },
+	[tegra_clk_timer] = { .dt_id = TEGRA210_CLK_TIMER, .present = true },
+	[tegra_clk_uarta_8] = { .dt_id = TEGRA210_CLK_UARTA, .present = true },
+	[tegra_clk_sdmmc2_9] = { .dt_id = TEGRA210_CLK_SDMMC2, .present = true },
+	[tegra_clk_i2s1] = { .dt_id = TEGRA210_CLK_I2S1, .present = true },
+	[tegra_clk_i2c1] = { .dt_id = TEGRA210_CLK_I2C1, .present = true },
+	[tegra_clk_sdmmc1_9] = { .dt_id = TEGRA210_CLK_SDMMC1, .present = true },
+	[tegra_clk_sdmmc4_9] = { .dt_id = TEGRA210_CLK_SDMMC4, .present = true },
+	[tegra_clk_pwm] = { .dt_id = TEGRA210_CLK_PWM, .present = true },
+	[tegra_clk_i2s2] = { .dt_id = TEGRA210_CLK_I2S2, .present = true },
+	[tegra_clk_usbd] = { .dt_id = TEGRA210_CLK_USBD, .present = true },
+	[tegra_clk_isp_9] = { .dt_id = TEGRA210_CLK_ISP, .present = true },
+	[tegra_clk_disp2_8] = { .dt_id = TEGRA210_CLK_DISP2, .present = true },
+	[tegra_clk_disp1_8] = { .dt_id = TEGRA210_CLK_DISP1, .present = true },
+	[tegra_clk_host1x_9] = { .dt_id = TEGRA210_CLK_HOST1X, .present = true },
+	[tegra_clk_i2s0] = { .dt_id = TEGRA210_CLK_I2S0, .present = true },
+	[tegra_clk_apbdma] = { .dt_id = TEGRA210_CLK_APBDMA, .present = true },
+	[tegra_clk_kfuse] = { .dt_id = TEGRA210_CLK_KFUSE, .present = true },
+	[tegra_clk_sbc1_9] = { .dt_id = TEGRA210_CLK_SBC1, .present = true },
+	[tegra_clk_sbc2_9] = { .dt_id = TEGRA210_CLK_SBC2, .present = true },
+	[tegra_clk_sbc3_9] = { .dt_id = TEGRA210_CLK_SBC3, .present = true },
+	[tegra_clk_i2c5] = { .dt_id = TEGRA210_CLK_I2C5, .present = true },
+	[tegra_clk_csi] = { .dt_id = TEGRA210_CLK_CSI, .present = true },
+	[tegra_clk_i2c2] = { .dt_id = TEGRA210_CLK_I2C2, .present = true },
+	[tegra_clk_uartc_8] = { .dt_id = TEGRA210_CLK_UARTC, .present = true },
+	[tegra_clk_mipi_cal] = { .dt_id = TEGRA210_CLK_MIPI_CAL, .present = true },
+	[tegra_clk_emc] = { .dt_id = TEGRA210_CLK_EMC, .present = true },
+	[tegra_clk_usb2] = { .dt_id = TEGRA210_CLK_USB2, .present = true },
+	[tegra_clk_bsev] = { .dt_id = TEGRA210_CLK_BSEV, .present = true },
+	[tegra_clk_uartd_8] = { .dt_id = TEGRA210_CLK_UARTD, .present = true },
+	[tegra_clk_i2c3] = { .dt_id = TEGRA210_CLK_I2C3, .present = true },
+	[tegra_clk_sbc4_9] = { .dt_id = TEGRA210_CLK_SBC4, .present = true },
+	[tegra_clk_sdmmc3_9] = { .dt_id = TEGRA210_CLK_SDMMC3, .present = true },
+	[tegra_clk_pcie] = { .dt_id = TEGRA210_CLK_PCIE, .present = true },
+	[tegra_clk_owr_8] = { .dt_id = TEGRA210_CLK_OWR, .present = true },
+	[tegra_clk_afi] = { .dt_id = TEGRA210_CLK_AFI, .present = true },
+	[tegra_clk_csite_8] = { .dt_id = TEGRA210_CLK_CSITE, .present = true },
+	[tegra_clk_soc_therm_8] = { .dt_id = TEGRA210_CLK_SOC_THERM, .present = true },
+	[tegra_clk_dtv] = { .dt_id = TEGRA210_CLK_DTV, .present = true },
+	[tegra_clk_i2cslow] = { .dt_id = TEGRA210_CLK_I2CSLOW, .present = true },
+	[tegra_clk_tsec_8] = { .dt_id = TEGRA210_CLK_TSEC, .present = true },
+	[tegra_clk_xusb_host] = { .dt_id = TEGRA210_CLK_XUSB_HOST, .present = true },
+	[tegra_clk_csus] = { .dt_id = TEGRA210_CLK_CSUS, .present = true },
+	[tegra_clk_mselect] = { .dt_id = TEGRA210_CLK_MSELECT, .present = true },
+	[tegra_clk_tsensor] = { .dt_id = TEGRA210_CLK_TSENSOR, .present = true },
+	[tegra_clk_i2s3] = { .dt_id = TEGRA210_CLK_I2S3, .present = true },
+	[tegra_clk_i2s4] = { .dt_id = TEGRA210_CLK_I2S4, .present = true },
+	[tegra_clk_i2c4] = { .dt_id = TEGRA210_CLK_I2C4, .present = true },
+	[tegra_clk_d_audio] = { .dt_id = TEGRA210_CLK_D_AUDIO, .present = true },
+	[tegra_clk_hda2codec_2x_8] = { .dt_id = TEGRA210_CLK_HDA2CODEC_2X, .present = true },
+	[tegra_clk_spdif_2x] = { .dt_id = TEGRA210_CLK_SPDIF_2X, .present = true },
+	[tegra_clk_actmon] = { .dt_id = TEGRA210_CLK_ACTMON, .present = true },
+	[tegra_clk_extern1] = { .dt_id = TEGRA210_CLK_EXTERN1, .present = true },
+	[tegra_clk_extern2] = { .dt_id = TEGRA210_CLK_EXTERN2, .present = true },
+	[tegra_clk_extern3] = { .dt_id = TEGRA210_CLK_EXTERN3, .present = true },
+	[tegra_clk_sata_oob_8] = { .dt_id = TEGRA210_CLK_SATA_OOB, .present = true },
+	[tegra_clk_sata_8] = { .dt_id = TEGRA210_CLK_SATA, .present = true },
+	[tegra_clk_hda_8] = { .dt_id = TEGRA210_CLK_HDA, .present = true },
+	[tegra_clk_hda2hdmi] = { .dt_id = TEGRA210_CLK_HDA2HDMI, .present = true },
+	[tegra_clk_cilab] = { .dt_id = TEGRA210_CLK_CILAB, .present = true },
+	[tegra_clk_cilcd] = { .dt_id = TEGRA210_CLK_CILCD, .present = true },
+	[tegra_clk_cile] = { .dt_id = TEGRA210_CLK_CILE, .present = true },
+	[tegra_clk_dsialp] = { .dt_id = TEGRA210_CLK_DSIALP, .present = true },
+	[tegra_clk_dsiblp] = { .dt_id = TEGRA210_CLK_DSIBLP, .present = true },
+	[tegra_clk_entropy_8] = { .dt_id = TEGRA210_CLK_ENTROPY, .present = true },
+	[tegra_clk_xusb_ss] = { .dt_id = TEGRA210_CLK_XUSB_SS, .present = true },
+	[tegra_clk_i2c6] = { .dt_id = TEGRA210_CLK_I2C6, .present = true },
+	[tegra_clk_vim2_clk] = { .dt_id = TEGRA210_CLK_VIM2_CLK, .present = true },
+	[tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true },
+	[tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true },
+	[tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true },
+	[tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true },
+	[tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true },
+	[tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true },
+	[tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, },
+	[tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true },
+	[tegra_clk_vfir] = { .dt_id = TEGRA210_CLK_VFIR, .present = true },
+	[tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true },
+	[tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true },
+	[tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true },
+	[tegra_clk_vi_sensor_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR, .present = true },
+	[tegra_clk_fuse] = { .dt_id = TEGRA210_CLK_FUSE, .present = true },
+	[tegra_clk_fuse_burn] = { .dt_id = TEGRA210_CLK_FUSE_BURN, .present = true },
+	[tegra_clk_clk_32k] = { .dt_id = TEGRA210_CLK_CLK_32K, .present = true },
+	[tegra_clk_clk_m] = { .dt_id = TEGRA210_CLK_CLK_M, .present = true },
+	[tegra_clk_clk_m_div2] = { .dt_id = TEGRA210_CLK_CLK_M_DIV2, .present = true },
+	[tegra_clk_clk_m_div4] = { .dt_id = TEGRA210_CLK_CLK_M_DIV4, .present = true },
+	[tegra_clk_pll_ref] = { .dt_id = TEGRA210_CLK_PLL_REF, .present = true },
+	[tegra_clk_pll_c] = { .dt_id = TEGRA210_CLK_PLL_C, .present = true },
+	[tegra_clk_pll_c_out1] = { .dt_id = TEGRA210_CLK_PLL_C_OUT1, .present = true },
+	[tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present = true },
+	[tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present = true },
+	[tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present = true },
+	[tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1, .present = true },
+	[tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present = true },
+	[tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1, .present = true },
+	[tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3, .present = true },
+	[tegra_clk_pll_p_out4_cpu] = { .dt_id = TEGRA210_CLK_PLL_P_OUT4, .present = true },
+	[tegra_clk_pll_p_out_hsio] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_HSIO, .present = true },
+	[tegra_clk_pll_p_out_xusb] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_XUSB, .present = true },
+	[tegra_clk_pll_p_out_cpu] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_CPU, .present = true },
+	[tegra_clk_pll_p_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_ADSP, .present = true },
+	[tegra_clk_pll_a] = { .dt_id = TEGRA210_CLK_PLL_A, .present = true },
+	[tegra_clk_pll_a_out0] = { .dt_id = TEGRA210_CLK_PLL_A_OUT0, .present = true },
+	[tegra_clk_pll_d] = { .dt_id = TEGRA210_CLK_PLL_D, .present = true },
+	[tegra_clk_pll_d_out0] = { .dt_id = TEGRA210_CLK_PLL_D_OUT0, .present = true },
+	[tegra_clk_pll_d2] = { .dt_id = TEGRA210_CLK_PLL_D2, .present = true },
+	[tegra_clk_pll_d2_out0] = { .dt_id = TEGRA210_CLK_PLL_D2_OUT0, .present = true },
+	[tegra_clk_pll_u] = { .dt_id = TEGRA210_CLK_PLL_U, .present = true },
+	[tegra_clk_pll_u_out] = { .dt_id = TEGRA210_CLK_PLL_U_OUT, .present = true },
+	[tegra_clk_pll_u_out1] = { .dt_id = TEGRA210_CLK_PLL_U_OUT1, .present = true },
+	[tegra_clk_pll_u_out2] = { .dt_id = TEGRA210_CLK_PLL_U_OUT2, .present = true },
+	[tegra_clk_pll_u_480m] = { .dt_id = TEGRA210_CLK_PLL_U_480M, .present = true },
+	[tegra_clk_pll_u_60m] = { .dt_id = TEGRA210_CLK_PLL_U_60M, .present = true },
+	[tegra_clk_pll_u_48m] = { .dt_id = TEGRA210_CLK_PLL_U_48M, .present = true },
+	[tegra_clk_pll_x] = { .dt_id = TEGRA210_CLK_PLL_X, .present = true },
+	[tegra_clk_pll_x_out0] = { .dt_id = TEGRA210_CLK_PLL_X_OUT0, .present = true },
+	[tegra_clk_pll_re_vco] = { .dt_id = TEGRA210_CLK_PLL_RE_VCO, .present = true },
+	[tegra_clk_pll_re_out] = { .dt_id = TEGRA210_CLK_PLL_RE_OUT, .present = true },
+	[tegra_clk_spdif_in_sync] = { .dt_id = TEGRA210_CLK_SPDIF_IN_SYNC, .present = true },
+	[tegra_clk_i2s0_sync] = { .dt_id = TEGRA210_CLK_I2S0_SYNC, .present = true },
+	[tegra_clk_i2s1_sync] = { .dt_id = TEGRA210_CLK_I2S1_SYNC, .present = true },
+	[tegra_clk_i2s2_sync] = { .dt_id = TEGRA210_CLK_I2S2_SYNC, .present = true },
+	[tegra_clk_i2s3_sync] = { .dt_id = TEGRA210_CLK_I2S3_SYNC, .present = true },
+	[tegra_clk_i2s4_sync] = { .dt_id = TEGRA210_CLK_I2S4_SYNC, .present = true },
+	[tegra_clk_vimclk_sync] = { .dt_id = TEGRA210_CLK_VIMCLK_SYNC, .present = true },
+	[tegra_clk_audio0] = { .dt_id = TEGRA210_CLK_AUDIO0, .present = true },
+	[tegra_clk_audio1] = { .dt_id = TEGRA210_CLK_AUDIO1, .present = true },
+	[tegra_clk_audio2] = { .dt_id = TEGRA210_CLK_AUDIO2, .present = true },
+	[tegra_clk_audio3] = { .dt_id = TEGRA210_CLK_AUDIO3, .present = true },
+	[tegra_clk_audio4] = { .dt_id = TEGRA210_CLK_AUDIO4, .present = true },
+	[tegra_clk_spdif] = { .dt_id = TEGRA210_CLK_SPDIF, .present = true },
+	[tegra_clk_clk_out_1] = { .dt_id = TEGRA210_CLK_CLK_OUT_1, .present = true },
+	[tegra_clk_clk_out_2] = { .dt_id = TEGRA210_CLK_CLK_OUT_2, .present = true },
+	[tegra_clk_clk_out_3] = { .dt_id = TEGRA210_CLK_CLK_OUT_3, .present = true },
+	[tegra_clk_blink] = { .dt_id = TEGRA210_CLK_BLINK, .present = true },
+	[tegra_clk_xusb_gate] = { .dt_id = TEGRA210_CLK_XUSB_GATE, .present = true },
+	[tegra_clk_xusb_host_src_8] = { .dt_id = TEGRA210_CLK_XUSB_HOST_SRC, .present = true },
+	[tegra_clk_xusb_falcon_src_8] = { .dt_id = TEGRA210_CLK_XUSB_FALCON_SRC, .present = true },
+	[tegra_clk_xusb_fs_src] = { .dt_id = TEGRA210_CLK_XUSB_FS_SRC, .present = true },
+	[tegra_clk_xusb_ss_src_8] = { .dt_id = TEGRA210_CLK_XUSB_SS_SRC, .present = true },
+	[tegra_clk_xusb_ss_div2] = { .dt_id = TEGRA210_CLK_XUSB_SS_DIV2, .present = true },
+	[tegra_clk_xusb_dev_src_8] = { .dt_id = TEGRA210_CLK_XUSB_DEV_SRC, .present = true },
+	[tegra_clk_xusb_dev] = { .dt_id = TEGRA210_CLK_XUSB_DEV, .present = true },
+	[tegra_clk_xusb_hs_src_4] = { .dt_id = TEGRA210_CLK_XUSB_HS_SRC, .present = true },
+	[tegra_clk_xusb_ssp_src] = { .dt_id = TEGRA210_CLK_XUSB_SSP_SRC, .present = true },
+	[tegra_clk_usb2_hsic_trk] = { .dt_id = TEGRA210_CLK_USB2_HSIC_TRK, .present = true },
+	[tegra_clk_hsic_trk] = { .dt_id = TEGRA210_CLK_HSIC_TRK, .present = true },
+	[tegra_clk_usb2_trk] = { .dt_id = TEGRA210_CLK_USB2_TRK, .present = true },
+	[tegra_clk_sclk] = { .dt_id = TEGRA210_CLK_SCLK, .present = true },
+	[tegra_clk_sclk_mux] = { .dt_id = TEGRA210_CLK_SCLK_MUX, .present = true },
+	[tegra_clk_hclk] = { .dt_id = TEGRA210_CLK_HCLK, .present = true },
+	[tegra_clk_pclk] = { .dt_id = TEGRA210_CLK_PCLK, .present = true },
+	[tegra_clk_cclk_g] = { .dt_id = TEGRA210_CLK_CCLK_G, .present = true },
+	[tegra_clk_cclk_lp] = { .dt_id = TEGRA210_CLK_CCLK_LP, .present = true },
+	[tegra_clk_dfll_ref] = { .dt_id = TEGRA210_CLK_DFLL_REF, .present = true },
+	[tegra_clk_dfll_soc] = { .dt_id = TEGRA210_CLK_DFLL_SOC, .present = true },
+	[tegra_clk_vi_sensor2_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR2, .present = true },
+	[tegra_clk_pll_p_out5] = { .dt_id = TEGRA210_CLK_PLL_P_OUT5, .present = true },
+	[tegra_clk_pll_c4] = { .dt_id = TEGRA210_CLK_PLL_C4, .present = true },
+	[tegra_clk_pll_dp] = { .dt_id = TEGRA210_CLK_PLL_DP, .present = true },
+	[tegra_clk_audio0_mux] = { .dt_id = TEGRA210_CLK_AUDIO0_MUX, .present = true },
+	[tegra_clk_audio1_mux] = { .dt_id = TEGRA210_CLK_AUDIO1_MUX, .present = true },
+	[tegra_clk_audio2_mux] = { .dt_id = TEGRA210_CLK_AUDIO2_MUX, .present = true },
+	[tegra_clk_audio3_mux] = { .dt_id = TEGRA210_CLK_AUDIO3_MUX, .present = true },
+	[tegra_clk_audio4_mux] = { .dt_id = TEGRA210_CLK_AUDIO4_MUX, .present = true },
+	[tegra_clk_spdif_mux] = { .dt_id = TEGRA210_CLK_SPDIF_MUX, .present = true },
+	[tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_1_MUX, .present = true },
+	[tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_2_MUX, .present = true },
+	[tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_3_MUX, .present = true },
+	[tegra_clk_maud] = { .dt_id = TEGRA210_CLK_MAUD, .present = true },
+	[tegra_clk_mipibif] = { .dt_id = TEGRA210_CLK_MIPIBIF, .present = true },
+	[tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .present = true },
+	[tegra_clk_sdmmc_legacy] = { .dt_id = TEGRA210_CLK_SDMMC_LEGACY, .present = true },
+	[tegra_clk_tsecb] = { .dt_id = TEGRA210_CLK_TSECB, .present = true },
+	[tegra_clk_uartape] = { .dt_id = TEGRA210_CLK_UARTAPE, .present = true },
+	[tegra_clk_vi_i2c] = { .dt_id = TEGRA210_CLK_VI_I2C, .present = true },
+	[tegra_clk_ape] = { .dt_id = TEGRA210_CLK_APE, .present = true },
+	[tegra_clk_dbgapb] = { .dt_id = TEGRA210_CLK_DBGAPB, .present = true },
+	[tegra_clk_nvdec] = { .dt_id = TEGRA210_CLK_NVDEC, .present = true },
+	[tegra_clk_nvenc] = { .dt_id = TEGRA210_CLK_NVENC, .present = true },
+	[tegra_clk_nvjpg] = { .dt_id = TEGRA210_CLK_NVJPG, .present = true },
+	[tegra_clk_pll_c4_out0] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT0, .present = true },
+	[tegra_clk_pll_c4_out1] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT1, .present = true },
+	[tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true },
+	[tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true },
+};
+
+static struct tegra_devclk devclks[] __initdata = {
+	{ .con_id = "clk_m", .dt_id = TEGRA210_CLK_CLK_M },
+	{ .con_id = "pll_ref", .dt_id = TEGRA210_CLK_PLL_REF },
+	{ .con_id = "clk_32k", .dt_id = TEGRA210_CLK_CLK_32K },
+	{ .con_id = "clk_m_div2", .dt_id = TEGRA210_CLK_CLK_M_DIV2 },
+	{ .con_id = "clk_m_div4", .dt_id = TEGRA210_CLK_CLK_M_DIV4 },
+	{ .con_id = "pll_c", .dt_id = TEGRA210_CLK_PLL_C },
+	{ .con_id = "pll_c_out1", .dt_id = TEGRA210_CLK_PLL_C_OUT1 },
+	{ .con_id = "pll_c2", .dt_id = TEGRA210_CLK_PLL_C2 },
+	{ .con_id = "pll_c3", .dt_id = TEGRA210_CLK_PLL_C3 },
+	{ .con_id = "pll_p", .dt_id = TEGRA210_CLK_PLL_P },
+	{ .con_id = "pll_p_out1", .dt_id = TEGRA210_CLK_PLL_P_OUT1 },
+	{ .con_id = "pll_p_out2", .dt_id = TEGRA210_CLK_PLL_P_OUT2 },
+	{ .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 },
+	{ .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 },
+	{ .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M },
+	{ .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 },
+	{ .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X },
+	{ .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 },
+	{ .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U },
+	{ .con_id = "pll_u_out", .dt_id = TEGRA210_CLK_PLL_U_OUT },
+	{ .con_id = "pll_u_out1", .dt_id = TEGRA210_CLK_PLL_U_OUT1 },
+	{ .con_id = "pll_u_out2", .dt_id = TEGRA210_CLK_PLL_U_OUT2 },
+	{ .con_id = "pll_u_480M", .dt_id = TEGRA210_CLK_PLL_U_480M },
+	{ .con_id = "pll_u_60M", .dt_id = TEGRA210_CLK_PLL_U_60M },
+	{ .con_id = "pll_u_48M", .dt_id = TEGRA210_CLK_PLL_U_48M },
+	{ .con_id = "pll_d", .dt_id = TEGRA210_CLK_PLL_D },
+	{ .con_id = "pll_d_out0", .dt_id = TEGRA210_CLK_PLL_D_OUT0 },
+	{ .con_id = "pll_d2", .dt_id = TEGRA210_CLK_PLL_D2 },
+	{ .con_id = "pll_d2_out0", .dt_id = TEGRA210_CLK_PLL_D2_OUT0 },
+	{ .con_id = "pll_a", .dt_id = TEGRA210_CLK_PLL_A },
+	{ .con_id = "pll_a_out0", .dt_id = TEGRA210_CLK_PLL_A_OUT0 },
+	{ .con_id = "pll_re_vco", .dt_id = TEGRA210_CLK_PLL_RE_VCO },
+	{ .con_id = "pll_re_out", .dt_id = TEGRA210_CLK_PLL_RE_OUT },
+	{ .con_id = "spdif_in_sync", .dt_id = TEGRA210_CLK_SPDIF_IN_SYNC },
+	{ .con_id = "i2s0_sync", .dt_id = TEGRA210_CLK_I2S0_SYNC },
+	{ .con_id = "i2s1_sync", .dt_id = TEGRA210_CLK_I2S1_SYNC },
+	{ .con_id = "i2s2_sync", .dt_id = TEGRA210_CLK_I2S2_SYNC },
+	{ .con_id = "i2s3_sync", .dt_id = TEGRA210_CLK_I2S3_SYNC },
+	{ .con_id = "i2s4_sync", .dt_id = TEGRA210_CLK_I2S4_SYNC },
+	{ .con_id = "vimclk_sync", .dt_id = TEGRA210_CLK_VIMCLK_SYNC },
+	{ .con_id = "audio0", .dt_id = TEGRA210_CLK_AUDIO0 },
+	{ .con_id = "audio1", .dt_id = TEGRA210_CLK_AUDIO1 },
+	{ .con_id = "audio2", .dt_id = TEGRA210_CLK_AUDIO2 },
+	{ .con_id = "audio3", .dt_id = TEGRA210_CLK_AUDIO3 },
+	{ .con_id = "audio4", .dt_id = TEGRA210_CLK_AUDIO4 },
+	{ .con_id = "spdif", .dt_id = TEGRA210_CLK_SPDIF },
+	{ .con_id = "spdif_2x", .dt_id = TEGRA210_CLK_SPDIF_2X },
+	{ .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA210_CLK_EXTERN1 },
+	{ .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA210_CLK_EXTERN2 },
+	{ .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA210_CLK_EXTERN3 },
+	{ .con_id = "blink", .dt_id = TEGRA210_CLK_BLINK },
+	{ .con_id = "cclk_g", .dt_id = TEGRA210_CLK_CCLK_G },
+	{ .con_id = "cclk_lp", .dt_id = TEGRA210_CLK_CCLK_LP },
+	{ .con_id = "sclk", .dt_id = TEGRA210_CLK_SCLK },
+	{ .con_id = "hclk", .dt_id = TEGRA210_CLK_HCLK },
+	{ .con_id = "pclk", .dt_id = TEGRA210_CLK_PCLK },
+	{ .con_id = "fuse", .dt_id = TEGRA210_CLK_FUSE },
+	{ .dev_id = "rtc-tegra", .dt_id = TEGRA210_CLK_RTC },
+	{ .dev_id = "timer", .dt_id = TEGRA210_CLK_TIMER },
+	{ .con_id = "pll_c4_out0", .dt_id = TEGRA210_CLK_PLL_C4_OUT0 },
+	{ .con_id = "pll_c4_out1", .dt_id = TEGRA210_CLK_PLL_C4_OUT1 },
+	{ .con_id = "pll_c4_out2", .dt_id = TEGRA210_CLK_PLL_C4_OUT2 },
+	{ .con_id = "pll_c4_out3", .dt_id = TEGRA210_CLK_PLL_C4_OUT3 },
+	{ .con_id = "dpaux", .dt_id = TEGRA210_CLK_DPAUX },
+	{ .con_id = "sor0", .dt_id = TEGRA210_CLK_SOR0 },
+};
+
+static struct tegra_audio_clk_info tegra210_audio_plls[] = {
+	{ "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_ref" },
+	{ "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" },
+};
+
+static struct clk **clks;
+
+static void tegra210_utmi_param_configure(void __iomem *clk_base)
+{
+	u32 reg;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+		if (osc_freq == utmi_parameters[i].osc_frequency)
+			break;
+	}
+
+	if (i >= ARRAY_SIZE(utmi_parameters)) {
+		pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
+		       osc_freq);
+		return;
+	}
+
+	reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
+	reg |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
+	       PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
+	       PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
+	reg &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
+		  PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
+	writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
+
+	reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
+	reg |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
+	writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
+	udelay(1);
+
+	reg = readl_relaxed(clk_base + PLLU_BASE);
+	reg &= ~PLLU_BASE_CLKENABLE_USB;
+	writel_relaxed(reg, clk_base + PLLU_BASE);
+
+	reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+	reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+	writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+	udelay(10);
+
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+	/* Program UTMIP PLL stable and active counts */
+	/* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+	reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+	reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
+
+	reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+	reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].
+					    active_delay_count);
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+	/* Program UTMIP PLL delay and oscillator frequency counts */
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+	reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+	reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].
+					    enable_delay_count);
+
+	reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+	reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].
+					   xtal_freq_count);
+
+	reg |= UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+	/* Remove power downs from UTMIP PLL control bits */
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+	reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+	udelay(1);
+
+	/* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+	reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
+	reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
+	reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+	/* Setup HW control of UTMIPLL */
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+	reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+	reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+	reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+	writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+	udelay(1);
+
+	reg = readl_relaxed(clk_base + XUSB_PLL_CFG0);
+	reg &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
+	writel_relaxed(reg, clk_base + XUSB_PLL_CFG0);
+
+	udelay(1);
+
+	/* Enable HW control UTMIPLL */
+	reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+	reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+	writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+
+static __init void tegra210_periph_clk_init(void __iomem *clk_base,
+					    void __iomem *pmc_base)
+{
+	struct clk *clk;
+
+	/* xusb_ss_div2 */
+	clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
+					1, 2);
+	clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk;
+
+	/* pll_d_dsi_out */
+	clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
+				clk_base + PLLD_MISC0, 21, 0, &pll_d_lock);
+	clks[TEGRA210_CLK_PLL_D_DSI_OUT] = clk;
+
+	/* dsia */
+	clk = tegra_clk_register_periph_gate("dsia", "pll_d_dsi_out", 0,
+					     clk_base, 0, 48,
+					     periph_clk_enb_refcnt);
+	clks[TEGRA210_CLK_DSIA] = clk;
+
+	/* dsib */
+	clk = tegra_clk_register_periph_gate("dsib", "pll_d_dsi_out", 0,
+					     clk_base, 0, 82,
+					     periph_clk_enb_refcnt);
+	clks[TEGRA210_CLK_DSIB] = clk;
+
+	/* emc mux */
+	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+			       ARRAY_SIZE(mux_pllmcp_clkm), 0,
+			       clk_base + CLK_SOURCE_EMC,
+			       29, 3, 0, &emc_lock);
+
+	clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+				    &emc_lock);
+	clks[TEGRA210_CLK_MC] = clk;
+
+	/* cml0 */
+	clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
+				0, 0, &pll_e_lock);
+	clk_register_clkdev(clk, "cml0", NULL);
+	clks[TEGRA210_CLK_CML0] = clk;
+
+	/* cml1 */
+	clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX,
+				1, 0, &pll_e_lock);
+	clk_register_clkdev(clk, "cml1", NULL);
+	clks[TEGRA210_CLK_CML1] = clk;
+
+	tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params);
+}
+
+static void __init tegra210_pll_init(void __iomem *clk_base,
+				     void __iomem *pmc)
+{
+	u32 val;
+	struct clk *clk;
+
+	/* PLLC */
+	clk = tegra_clk_register_pllxc_tegra210("pll_c", "pll_ref", clk_base,
+			pmc, 0, &pll_c_params, NULL);
+	if (!WARN_ON(IS_ERR(clk)))
+		clk_register_clkdev(clk, "pll_c", NULL);
+	clks[TEGRA210_CLK_PLL_C] = clk;
+
+	/* PLLC_OUT1 */
+	clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+			clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+			8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+				clk_base + PLLC_OUT, 1, 0,
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_c_out1", NULL);
+	clks[TEGRA210_CLK_PLL_C_OUT1] = clk;
+
+	/* PLLC_UD */
+	clk = clk_register_fixed_factor(NULL, "pll_c_ud", "pll_c",
+					CLK_SET_RATE_PARENT, 1, 1);
+	clk_register_clkdev(clk, "pll_c_ud", NULL);
+	clks[TEGRA210_CLK_PLL_C_UD] = clk;
+
+	/* PLLC2 */
+	clk = tegra_clk_register_pllc_tegra210("pll_c2", "pll_ref", clk_base,
+			     pmc, 0, &pll_c2_params, NULL);
+	clk_register_clkdev(clk, "pll_c2", NULL);
+	clks[TEGRA210_CLK_PLL_C2] = clk;
+
+	/* PLLC3 */
+	clk = tegra_clk_register_pllc_tegra210("pll_c3", "pll_ref", clk_base,
+			     pmc, 0, &pll_c3_params, NULL);
+	clk_register_clkdev(clk, "pll_c3", NULL);
+	clks[TEGRA210_CLK_PLL_C3] = clk;
+
+	/* PLLM */
+	clk = tegra_clk_register_pllm("pll_m", "osc", clk_base, pmc,
+			     CLK_SET_RATE_GATE, &pll_m_params, NULL);
+	clk_register_clkdev(clk, "pll_m", NULL);
+	clks[TEGRA210_CLK_PLL_M] = clk;
+
+	/* PLLMB */
+	clk = tegra_clk_register_pllmb("pll_mb", "osc", clk_base, pmc,
+			     CLK_SET_RATE_GATE, &pll_mb_params, NULL);
+	clk_register_clkdev(clk, "pll_mb", NULL);
+	clks[TEGRA210_CLK_PLL_MB] = clk;
+
+	clk_register_clkdev(clk, "pll_m_out1", NULL);
+	clks[TEGRA210_CLK_PLL_M_OUT1] = clk;
+
+	/* PLLM_UD */
+	clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
+					CLK_SET_RATE_PARENT, 1, 1);
+	clk_register_clkdev(clk, "pll_m_ud", NULL);
+	clks[TEGRA210_CLK_PLL_M_UD] = clk;
+
+	/* PLLU_VCO */
+	val = readl(clk_base + pll_u_vco_params.base_reg);
+	val &= ~BIT(24); /* disable PLLU_OVERRIDE */
+	writel(val, clk_base + pll_u_vco_params.base_reg);
+
+	clk = tegra_clk_register_pllre("pll_u_vco", "pll_ref", clk_base, pmc,
+			    0, &pll_u_vco_params, &pll_u_lock, pll_ref_freq);
+	clk_register_clkdev(clk, "pll_u_vco", NULL);
+	clks[TEGRA210_CLK_PLL_U] = clk;
+
+	/* PLLU_OUT */
+	clk = clk_register_divider_table(NULL, "pll_u_out", "pll_u_vco", 0,
+					 clk_base + PLLU_BASE, 16, 4, 0,
+					 pll_vco_post_div_table, NULL);
+	clk_register_clkdev(clk, "pll_u_out", NULL);
+	clks[TEGRA210_CLK_PLL_U_OUT] = clk;
+
+	/* PLLU_OUT1 */
+	clk = tegra_clk_register_divider("pll_u_out1_div", "pll_u_out",
+				clk_base + PLLU_OUTA, 0,
+				TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, &pll_u_lock);
+	clk = tegra_clk_register_pll_out("pll_u_out1", "pll_u_out1_div",
+				clk_base + PLLU_OUTA, 1, 0,
+				CLK_SET_RATE_PARENT, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_out1", NULL);
+	clks[TEGRA210_CLK_PLL_U_OUT1] = clk;
+
+	/* PLLU_OUT2 */
+	clk = tegra_clk_register_divider("pll_u_out2_div", "pll_u_out",
+				clk_base + PLLU_OUTA, 0,
+				TEGRA_DIVIDER_ROUND_UP,
+				24, 8, 1, &pll_u_lock);
+	clk = tegra_clk_register_pll_out("pll_u_out2", "pll_u_out2_div",
+				clk_base + PLLU_OUTA, 17, 16,
+				CLK_SET_RATE_PARENT, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_out2", NULL);
+	clks[TEGRA210_CLK_PLL_U_OUT2] = clk;
+
+	tegra210_utmi_param_configure(clk_base);
+
+	/* PLLU_480M */
+	clk = clk_register_gate(NULL, "pll_u_480M", "pll_u_vco",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				22, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_480M", NULL);
+	clks[TEGRA210_CLK_PLL_U_480M] = clk;
+
+	/* PLLU_60M */
+	clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_out2",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				23, 0, NULL);
+	clk_register_clkdev(clk, "pll_u_60M", NULL);
+	clks[TEGRA210_CLK_PLL_U_60M] = clk;
+
+	/* PLLU_48M */
+	clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_out1",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				25, 0, NULL);
+	clk_register_clkdev(clk, "pll_u_48M", NULL);
+	clks[TEGRA210_CLK_PLL_U_48M] = clk;
+
+	/* PLLD */
+	clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0,
+			    &pll_d_params, &pll_d_lock);
+	clk_register_clkdev(clk, "pll_d", NULL);
+	clks[TEGRA210_CLK_PLL_D] = clk;
+
+	/* PLLD_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_d_out0", NULL);
+	clks[TEGRA210_CLK_PLL_D_OUT0] = clk;
+
+	/* PLLRE */
+	clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
+			     0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq);
+	clk_register_clkdev(clk, "pll_re_vco", NULL);
+	clks[TEGRA210_CLK_PLL_RE_VCO] = clk;
+
+	clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0,
+					 clk_base + PLLRE_BASE, 16, 5, 0,
+					 pll_vco_post_div_table, &pll_re_lock);
+	clk_register_clkdev(clk, "pll_re_out", NULL);
+	clks[TEGRA210_CLK_PLL_RE_OUT] = clk;
+
+	/* PLLE */
+	clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref",
+				      clk_base, 0, &pll_e_params, NULL);
+	clk_register_clkdev(clk, "pll_e", NULL);
+	clks[TEGRA210_CLK_PLL_E] = clk;
+
+	/* PLLC4 */
+	clk = tegra_clk_register_pllre("pll_c4_vco", "pll_ref", clk_base, pmc,
+			     0, &pll_c4_vco_params, NULL, pll_ref_freq);
+	clk_register_clkdev(clk, "pll_c4_vco", NULL);
+	clks[TEGRA210_CLK_PLL_C4] = clk;
+
+	/* PLLC4_OUT0 */
+	clk = clk_register_divider_table(NULL, "pll_c4_out0", "pll_c4_vco", 0,
+					 clk_base + PLLC4_BASE, 19, 4, 0,
+					 pll_vco_post_div_table, NULL);
+	clk_register_clkdev(clk, "pll_c4_out0", NULL);
+	clks[TEGRA210_CLK_PLL_C4_OUT0] = clk;
+
+	/* PLLC4_OUT1 */
+	clk = clk_register_fixed_factor(NULL, "pll_c4_out1", "pll_c4_vco",
+					CLK_SET_RATE_PARENT, 1, 3);
+	clk_register_clkdev(clk, "pll_c4_out1", NULL);
+	clks[TEGRA210_CLK_PLL_C4_OUT1] = clk;
+
+	/* PLLC4_OUT2 */
+	clk = clk_register_fixed_factor(NULL, "pll_c4_out2", "pll_c4_vco",
+					CLK_SET_RATE_PARENT, 1, 5);
+	clk_register_clkdev(clk, "pll_c4_out2", NULL);
+	clks[TEGRA210_CLK_PLL_C4_OUT2] = clk;
+
+	/* PLLC4_OUT3 */
+	clk = tegra_clk_register_divider("pll_c4_out3_div", "pll_c4_out0",
+			clk_base + PLLC4_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+			8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_c4_out3", "pll_c4_out3_div",
+				clk_base + PLLC4_OUT, 1, 0,
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_c4_out3", NULL);
+	clks[TEGRA210_CLK_PLL_C4_OUT3] = clk;
+
+	/* PLLDP */
+	clk = tegra_clk_register_pllss_tegra210("pll_dp", "pll_ref", clk_base,
+					0, &pll_dp_params, NULL);
+	clk_register_clkdev(clk, "pll_dp", NULL);
+	clks[TEGRA210_CLK_PLL_DP] = clk;
+
+	/* PLLD2 */
+	clk = tegra_clk_register_pllss_tegra210("pll_d2", "pll_ref", clk_base,
+					0, &pll_d2_params, NULL);
+	clk_register_clkdev(clk, "pll_d2", NULL);
+	clks[TEGRA210_CLK_PLL_D2] = clk;
+
+	/* PLLD2_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
+					CLK_SET_RATE_PARENT, 1, 1);
+	clk_register_clkdev(clk, "pll_d2_out0", NULL);
+	clks[TEGRA210_CLK_PLL_D2_OUT0] = clk;
+
+	/* PLLP_OUT2 */
+	clk = clk_register_fixed_factor(NULL, "pll_p_out2", "pll_p",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_p_out2", NULL);
+	clks[TEGRA210_CLK_PLL_P_OUT2] = clk;
+
+}
+
+/* Tegra210 CPU clock and reset control functions */
+static void tegra210_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(clk_base + CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));  /* check CPU been reset or not */
+}
+
+static void tegra210_disable_cpu_clock(u32 cpu)
+{
+	/* flow controller would take care in the power sequence. */
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void tegra210_cpu_clock_suspend(void)
+{
+	/* switch coresite to clk_m, save off original source */
+	tegra210_cpu_clk_sctx.clk_csite_src =
+				readl(clk_base + CLK_SOURCE_CSITE);
+	writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+}
+
+static void tegra210_cpu_clock_resume(void)
+{
+	writel(tegra210_cpu_clk_sctx.clk_csite_src,
+				clk_base + CLK_SOURCE_CSITE);
+}
+#endif
+
+static struct tegra_cpu_car_ops tegra210_cpu_car_ops = {
+	.wait_for_reset	= tegra210_wait_cpu_in_reset,
+	.disable_clock	= tegra210_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+	.suspend	= tegra210_cpu_clock_suspend,
+	.resume		= tegra210_cpu_clock_resume,
+#endif
+};
+
+static const struct of_device_id pmc_match[] __initconst = {
+	{ .compatible = "nvidia,tegra210-pmc" },
+	{ },
+};
+
+static struct tegra_clk_init_table init_table[] __initdata = {
+	{ TEGRA210_CLK_UARTA, TEGRA210_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA210_CLK_UARTB, TEGRA210_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA210_CLK_UARTC, TEGRA210_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA210_CLK_UARTD, TEGRA210_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1 },
+	{ TEGRA210_CLK_PLL_A_OUT0, TEGRA210_CLK_CLK_MAX, 11289600, 1 },
+	{ TEGRA210_CLK_EXTERN1, TEGRA210_CLK_PLL_A_OUT0, 0, 1 },
+	{ TEGRA210_CLK_CLK_OUT_1_MUX, TEGRA210_CLK_EXTERN1, 0, 1 },
+	{ TEGRA210_CLK_CLK_OUT_1, TEGRA210_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA210_CLK_I2S0, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA210_CLK_I2S1, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA210_CLK_I2S2, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA210_CLK_I2S3, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 },
+	{ TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 },
+	{ TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 1 },
+	{ TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 },
+	{ TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 },
+	{ TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 },
+	{ TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 },
+	{ TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
+	{ TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
+	{ TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 },
+	{ TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 },
+	{ TEGRA210_CLK_XUSB_HS_SRC, TEGRA210_CLK_XUSB_SS_SRC, 120000000, 0 },
+	{ TEGRA210_CLK_XUSB_SSP_SRC, TEGRA210_CLK_XUSB_SS_SRC, 120000000, 0 },
+	{ TEGRA210_CLK_XUSB_FALCON_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 204000000, 0 },
+	{ TEGRA210_CLK_XUSB_HOST_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 },
+	{ TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 },
+	{ TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 },
+	{ TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 },
+	{ TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA210_CLK_TSENSOR, TEGRA210_CLK_CLK_M, 400000, 0 },
+	{ TEGRA210_CLK_I2C1, TEGRA210_CLK_PLL_P, 0, 0 },
+	{ TEGRA210_CLK_I2C2, TEGRA210_CLK_PLL_P, 0, 0 },
+	{ TEGRA210_CLK_I2C3, TEGRA210_CLK_PLL_P, 0, 0 },
+	{ TEGRA210_CLK_I2C4, TEGRA210_CLK_PLL_P, 0, 0 },
+	{ TEGRA210_CLK_I2C5, TEGRA210_CLK_PLL_P, 0, 0 },
+	{ TEGRA210_CLK_I2C6, TEGRA210_CLK_PLL_P, 0, 0 },
+	{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 },
+	{ TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 },
+	{ TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 },
+	/* This MUST be the last entry. */
+	{ TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 },
+};
+
+/**
+ * tegra210_clock_apply_init_table - initialize clocks on Tegra210 SoCs
+ *
+ * Program an initial clock rate and enable or disable clocks needed
+ * by the rest of the kernel, for Tegra210 SoCs.  It is intended to be
+ * called by assigning a pointer to it to tegra_clk_apply_init_table -
+ * this will be called as an arch_initcall.  No return value.
+ */
+static void __init tegra210_clock_apply_init_table(void)
+{
+	tegra_init_from_table(init_table, clks, TEGRA210_CLK_CLK_MAX);
+}
+
+/**
+ * tegra210_clock_init - Tegra210-specific clock initialization
+ * @np: struct device_node * of the DT node for the SoC CAR IP block
+ *
+ * Register most SoC clocks for the Tegra210 system-on-chip.  Intended
+ * to be called by the OF init code when a DT node with the
+ * "nvidia,tegra210-car" string is encountered, and declared with
+ * CLK_OF_DECLARE.  No return value.
+ */
+static void __init tegra210_clock_init(struct device_node *np)
+{
+	struct device_node *node;
+	u32 value, clk_m_div;
+
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("ioremap tegra210 CAR failed\n");
+		return;
+	}
+
+	node = of_find_matching_node(NULL, pmc_match);
+	if (!node) {
+		pr_err("Failed to find pmc node\n");
+		WARN_ON(1);
+		return;
+	}
+
+	pmc_base = of_iomap(node, 0);
+	if (!pmc_base) {
+		pr_err("Can't map pmc registers\n");
+		WARN_ON(1);
+		return;
+	}
+
+	clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX,
+			      TEGRA210_CAR_BANK_COUNT);
+	if (!clks)
+		return;
+
+	value = clk_readl(clk_base + SPARE_REG0) >> CLK_M_DIVISOR_SHIFT;
+	clk_m_div = (value & CLK_M_DIVISOR_MASK) + 1;
+
+	if (tegra_osc_clk_init(clk_base, tegra210_clks, tegra210_input_freq,
+			       ARRAY_SIZE(tegra210_input_freq), clk_m_div,
+			       &osc_freq, &pll_ref_freq) < 0)
+		return;
+
+	tegra_fixed_clk_init(tegra210_clks);
+	tegra210_pll_init(clk_base, pmc_base);
+	tegra210_periph_clk_init(clk_base, pmc_base);
+	tegra_audio_clk_init(clk_base, pmc_base, tegra210_clks,
+			     tegra210_audio_plls,
+			     ARRAY_SIZE(tegra210_audio_plls));
+	tegra_pmc_clk_init(pmc_base, tegra210_clks);
+
+	/* For Tegra210, PLLD is the only source for DSIA & DSIB */
+	value = clk_readl(clk_base + PLLD_BASE);
+	value &= ~BIT(25);
+	clk_writel(value, clk_base + PLLD_BASE);
+
+	tegra_clk_apply_init_table = tegra210_clock_apply_init_table;
+
+	tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks,
+				  &pll_x_params);
+	tegra_add_of_provider(np);
+	tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
+
+	tegra_cpu_car_ops = &tegra210_cpu_car_ops;
+}
+CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index b90db615c29e..0478565cf292 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -224,188 +224,192 @@ struct utmi_clk_param {
 };
 
 static const struct utmi_clk_param utmi_parameters[] = {
-/*	OSC_FREQUENCY, ENABLE_DLY, STABLE_CNT, ACTIVE_DLY, XTAL_FREQ_CNT */
-	{13000000,     0x02,       0x33,       0x05,       0x7F},
-	{19200000,     0x03,       0x4B,       0x06,       0xBB},
-	{12000000,     0x02,       0x2F,       0x04,       0x76},
-	{26000000,     0x04,       0x66,       0x09,       0xFE},
-	{16800000,     0x03,       0x41,       0x0A,       0xA4},
+	{
+		.osc_frequency = 13000000, .enable_delay_count = 0x02,
+		.stable_count = 0x33, .active_delay_count = 0x05,
+		.xtal_freq_count = 0x7f
+	}, {
+		.osc_frequency = 19200000, .enable_delay_count = 0x03,
+		.stable_count = 0x4b, .active_delay_count = 0x06,
+		.xtal_freq_count = 0xbb
+	}, {
+		.osc_frequency = 12000000, .enable_delay_count = 0x02,
+		.stable_count = 0x2f, .active_delay_count = 0x04,
+		.xtal_freq_count = 0x76
+	}, {
+		.osc_frequency = 26000000, .enable_delay_count = 0x04,
+		.stable_count = 0x66, .active_delay_count = 0x09,
+		.xtal_freq_count = 0xfe
+	}, {
+		.osc_frequency = 16800000, .enable_delay_count = 0x03,
+		.stable_count = 0x41, .active_delay_count = 0x0a,
+		.xtal_freq_count = 0xa4
+	},
 };
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-	{ 12000000, 1040000000, 520,  6, 0, 8},
-	{ 13000000, 1040000000, 480,  6, 0, 8},
-	{ 16800000, 1040000000, 495,  8, 0, 8},	/* actual: 1039.5 MHz */
-	{ 19200000, 1040000000, 325,  6, 0, 6},
-	{ 26000000, 1040000000, 520, 13, 0, 8},
-
-	{ 12000000, 832000000, 416,  6, 0, 8},
-	{ 13000000, 832000000, 832, 13, 0, 8},
-	{ 16800000, 832000000, 396,  8, 0, 8},	/* actual: 831.6 MHz */
-	{ 19200000, 832000000, 260,  6, 0, 8},
-	{ 26000000, 832000000, 416, 13, 0, 8},
-
-	{ 12000000, 624000000, 624, 12, 0, 8},
-	{ 13000000, 624000000, 624, 13, 0, 8},
-	{ 16800000, 600000000, 520, 14, 0, 8},
-	{ 19200000, 624000000, 520, 16, 0, 8},
-	{ 26000000, 624000000, 624, 26, 0, 8},
-
-	{ 12000000, 600000000, 600, 12, 0, 8},
-	{ 13000000, 600000000, 600, 13, 0, 8},
-	{ 16800000, 600000000, 500, 14, 0, 8},
-	{ 19200000, 600000000, 375, 12, 0, 6},
-	{ 26000000, 600000000, 600, 26, 0, 8},
-
-	{ 12000000, 520000000, 520, 12, 0, 8},
-	{ 13000000, 520000000, 520, 13, 0, 8},
-	{ 16800000, 520000000, 495, 16, 0, 8},	/* actual: 519.75 MHz */
-	{ 19200000, 520000000, 325, 12, 0, 6},
-	{ 26000000, 520000000, 520, 26, 0, 8},
-
-	{ 12000000, 416000000, 416, 12, 0, 8},
-	{ 13000000, 416000000, 416, 13, 0, 8},
-	{ 16800000, 416000000, 396, 16, 0, 8},	/* actual: 415.8 MHz */
-	{ 19200000, 416000000, 260, 12, 0, 6},
-	{ 26000000, 416000000, 416, 26, 0, 8},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 1040000000, 520,  6, 1, 8 },
+	{ 13000000, 1040000000, 480,  6, 1, 8 },
+	{ 16800000, 1040000000, 495,  8, 1, 8 }, /* actual: 1039.5 MHz */
+	{ 19200000, 1040000000, 325,  6, 1, 6 },
+	{ 26000000, 1040000000, 520, 13, 1, 8 },
+	{ 12000000,  832000000, 416,  6, 1, 8 },
+	{ 13000000,  832000000, 832, 13, 1, 8 },
+	{ 16800000,  832000000, 396,  8, 1, 8 }, /* actual: 831.6 MHz */
+	{ 19200000,  832000000, 260,  6, 1, 8 },
+	{ 26000000,  832000000, 416, 13, 1, 8 },
+	{ 12000000,  624000000, 624, 12, 1, 8 },
+	{ 13000000,  624000000, 624, 13, 1, 8 },
+	{ 16800000,  600000000, 520, 14, 1, 8 },
+	{ 19200000,  624000000, 520, 16, 1, 8 },
+	{ 26000000,  624000000, 624, 26, 1, 8 },
+	{ 12000000,  600000000, 600, 12, 1, 8 },
+	{ 13000000,  600000000, 600, 13, 1, 8 },
+	{ 16800000,  600000000, 500, 14, 1, 8 },
+	{ 19200000,  600000000, 375, 12, 1, 6 },
+	{ 26000000,  600000000, 600, 26, 1, 8 },
+	{ 12000000,  520000000, 520, 12, 1, 8 },
+	{ 13000000,  520000000, 520, 13, 1, 8 },
+	{ 16800000,  520000000, 495, 16, 1, 8 }, /* actual: 519.75 MHz */
+	{ 19200000,  520000000, 325, 12, 1, 6 },
+	{ 26000000,  520000000, 520, 26, 1, 8 },
+	{ 12000000,  416000000, 416, 12, 1, 8 },
+	{ 13000000,  416000000, 416, 13, 1, 8 },
+	{ 16800000,  416000000, 396, 16, 1, 8 }, /* actual: 415.8 MHz */
+	{ 19200000,  416000000, 260, 12, 1, 6 },
+	{ 26000000,  416000000, 416, 26, 1, 8 },
+	{        0,          0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 0, 8},
-	{ 13000000, 666000000, 666, 13, 0, 8},
-	{ 16800000, 666000000, 555, 14, 0, 8},
-	{ 19200000, 666000000, 555, 16, 0, 8},
-	{ 26000000, 666000000, 666, 26, 0, 8},
-	{ 12000000, 600000000, 600, 12, 0, 8},
-	{ 13000000, 600000000, 600, 13, 0, 8},
-	{ 16800000, 600000000, 500, 14, 0, 8},
-	{ 19200000, 600000000, 375, 12, 0, 6},
-	{ 26000000, 600000000, 600, 26, 0, 8},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 666000000, 666, 12, 1, 8 },
+	{ 13000000, 666000000, 666, 13, 1, 8 },
+	{ 16800000, 666000000, 555, 14, 1, 8 },
+	{ 19200000, 666000000, 555, 16, 1, 8 },
+	{ 26000000, 666000000, 666, 26, 1, 8 },
+	{ 12000000, 600000000, 600, 12, 1, 8 },
+	{ 13000000, 600000000, 600, 13, 1, 8 },
+	{ 16800000, 600000000, 500, 14, 1, 8 },
+	{ 19200000, 600000000, 375, 12, 1, 6 },
+	{ 26000000, 600000000, 600, 26, 1, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 1, 8},
-	{ 13000000, 216000000, 432, 13, 1, 8},
-	{ 16800000, 216000000, 360, 14, 1, 8},
-	{ 19200000, 216000000, 360, 16, 1, 8},
-	{ 26000000, 216000000, 432, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 216000000, 432, 12, 2, 8 },
+	{ 13000000, 216000000, 432, 13, 2, 8 },
+	{ 16800000, 216000000, 360, 14, 2, 8 },
+	{ 19200000, 216000000, 360, 16, 2, 8 },
+	{ 26000000, 216000000, 432, 26, 2, 8 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-	{ 9600000, 564480000, 294, 5, 0, 4},
-	{ 9600000, 552960000, 288, 5, 0, 4},
-	{ 9600000, 24000000,  5,   2, 0, 1},
-
-	{ 28800000, 56448000, 49, 25, 0, 1},
-	{ 28800000, 73728000, 64, 25, 0, 1},
-	{ 28800000, 24000000,  5,  6, 0, 1},
-	{ 0, 0, 0, 0, 0, 0 },
+	{  9600000, 564480000, 294,  5, 1, 4 },
+	{  9600000, 552960000, 288,  5, 1, 4 },
+	{  9600000,  24000000,   5,  2, 1, 1 },
+	{ 28800000,  56448000,  49, 25, 1, 1 },
+	{ 28800000,  73728000,  64, 25, 1, 1 },
+	{ 28800000,  24000000,   5,  6, 1, 1 },
+	{        0,         0,   0,  0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 0, 4},
-	{ 13000000, 216000000, 216, 13, 0, 4},
-	{ 16800000, 216000000, 180, 14, 0, 4},
-	{ 19200000, 216000000, 180, 16, 0, 4},
-	{ 26000000, 216000000, 216, 26, 0, 4},
-
-	{ 12000000, 594000000, 594, 12, 0, 8},
-	{ 13000000, 594000000, 594, 13, 0, 8},
-	{ 16800000, 594000000, 495, 14, 0, 8},
-	{ 19200000, 594000000, 495, 16, 0, 8},
-	{ 26000000, 594000000, 594, 26, 0, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 0, 12},
-	{ 13000000, 1000000000, 1000, 13, 0, 12},
-	{ 19200000, 1000000000, 625,  12, 0, 8},
-	{ 26000000, 1000000000, 1000, 26, 0, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000,  216000000,  216, 12, 1,  4 },
+	{ 13000000,  216000000,  216, 13, 1,  4 },
+	{ 16800000,  216000000,  180, 14, 1,  4 },
+	{ 19200000,  216000000,  180, 16, 1,  4 },
+	{ 26000000,  216000000,  216, 26, 1,  4 },
+	{ 12000000,  594000000,  594, 12, 1,  8 },
+	{ 13000000,  594000000,  594, 13, 1,  8 },
+	{ 16800000,  594000000,  495, 14, 1,  8 },
+	{ 19200000,  594000000,  495, 16, 1,  8 },
+	{ 26000000,  594000000,  594, 26, 1,  8 },
+	{ 12000000, 1000000000, 1000, 12, 1, 12 },
+	{ 13000000, 1000000000, 1000, 13, 1, 12 },
+	{ 19200000, 1000000000,  625, 12, 1,  8 },
+	{ 26000000, 1000000000, 1000, 26, 1, 12 },
+	{        0,          0,    0,  0, 0,  0 },
 };
 
-static struct pdiv_map pllu_p[] = {
+static const struct pdiv_map pllu_p[] = {
 	{ .pdiv = 1, .hw_val = 1 },
 	{ .pdiv = 2, .hw_val = 0 },
 	{ .pdiv = 0, .hw_val = 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 0, 12},
-	{ 13000000, 480000000, 960, 13, 0, 12},
-	{ 16800000, 480000000, 400, 7,  0, 5},
-	{ 19200000, 480000000, 200, 4,  0, 3},
-	{ 26000000, 480000000, 960, 26, 0, 12},
-	{ 0, 0, 0, 0, 0, 0 },
+	{ 12000000, 480000000, 960, 12, 1, 12 },
+	{ 13000000, 480000000, 960, 13, 1, 12 },
+	{ 16800000, 480000000, 400,  7, 1,  5 },
+	{ 19200000, 480000000, 200,  4, 1,  3 },
+	{ 26000000, 480000000, 960, 26, 1, 12 },
+	{        0,         0,   0,  0, 0,  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
 	/* 1.7 GHz */
-	{ 12000000, 1700000000, 850,  6,  0, 8},
-	{ 13000000, 1700000000, 915,  7,  0, 8},	/* actual: 1699.2 MHz */
-	{ 16800000, 1700000000, 708,  7,  0, 8},	/* actual: 1699.2 MHz */
-	{ 19200000, 1700000000, 885,  10, 0, 8},	/* actual: 1699.2 MHz */
-	{ 26000000, 1700000000, 850,  13, 0, 8},
-
+	{ 12000000, 1700000000, 850,   6, 1, 8 },
+	{ 13000000, 1700000000, 915,   7, 1, 8 }, /* actual: 1699.2 MHz */
+	{ 16800000, 1700000000, 708,   7, 1, 8 }, /* actual: 1699.2 MHz */
+	{ 19200000, 1700000000, 885,  10, 1, 8 }, /* actual: 1699.2 MHz */
+	{ 26000000, 1700000000, 850,  13, 1, 8 },
 	/* 1.6 GHz */
-	{ 12000000, 1600000000, 800,  6,  0, 8},
-	{ 13000000, 1600000000, 738,  6,  0, 8},	/* actual: 1599.0 MHz */
-	{ 16800000, 1600000000, 857,  9,  0, 8},	/* actual: 1599.7 MHz */
-	{ 19200000, 1600000000, 500,  6,  0, 8},
-	{ 26000000, 1600000000, 800,  13, 0, 8},
-
+	{ 12000000, 1600000000, 800,   6, 1, 8 },
+	{ 13000000, 1600000000, 738,   6, 1, 8 }, /* actual: 1599.0 MHz */
+	{ 16800000, 1600000000, 857,   9, 1, 8 }, /* actual: 1599.7 MHz */
+	{ 19200000, 1600000000, 500,   6, 1, 8 },
+	{ 26000000, 1600000000, 800,  13, 1, 8 },
 	/* 1.5 GHz */
-	{ 12000000, 1500000000, 750,  6,  0, 8},
-	{ 13000000, 1500000000, 923,  8,  0, 8},	/* actual: 1499.8 MHz */
-	{ 16800000, 1500000000, 625,  7,  0, 8},
-	{ 19200000, 1500000000, 625,  8,  0, 8},
-	{ 26000000, 1500000000, 750,  13, 0, 8},
-
+	{ 12000000, 1500000000, 750,   6, 1, 8 },
+	{ 13000000, 1500000000, 923,   8, 1, 8 }, /* actual: 1499.8 MHz */
+	{ 16800000, 1500000000, 625,   7, 1, 8 },
+	{ 19200000, 1500000000, 625,   8, 1, 8 },
+	{ 26000000, 1500000000, 750,  13, 1, 8 },
 	/* 1.4 GHz */
-	{ 12000000, 1400000000, 700,  6,  0, 8},
-	{ 13000000, 1400000000, 969,  9,  0, 8},	/* actual: 1399.7 MHz */
-	{ 16800000, 1400000000, 1000, 12, 0, 8},
-	{ 19200000, 1400000000, 875,  12, 0, 8},
-	{ 26000000, 1400000000, 700,  13, 0, 8},
-
+	{ 12000000, 1400000000,  700,  6, 1, 8 },
+	{ 13000000, 1400000000,  969,  9, 1, 8 }, /* actual: 1399.7 MHz */
+	{ 16800000, 1400000000, 1000, 12, 1, 8 },
+	{ 19200000, 1400000000,  875, 12, 1, 8 },
+	{ 26000000, 1400000000,  700, 13, 1, 8 },
 	/* 1.3 GHz */
-	{ 12000000, 1300000000, 975,  9,  0, 8},
-	{ 13000000, 1300000000, 1000, 10, 0, 8},
-	{ 16800000, 1300000000, 928,  12, 0, 8},	/* actual: 1299.2 MHz */
-	{ 19200000, 1300000000, 812,  12, 0, 8},	/* actual: 1299.2 MHz */
-	{ 26000000, 1300000000, 650,  13, 0, 8},
-
+	{ 12000000, 1300000000,  975,  9, 1, 8 },
+	{ 13000000, 1300000000, 1000, 10, 1, 8 },
+	{ 16800000, 1300000000,  928, 12, 1, 8 }, /* actual: 1299.2 MHz */
+	{ 19200000, 1300000000,  812, 12, 1, 8 }, /* actual: 1299.2 MHz */
+	{ 26000000, 1300000000,  650, 13, 1, 8 },
 	/* 1.2 GHz */
-	{ 12000000, 1200000000, 1000, 10, 0, 8},
-	{ 13000000, 1200000000, 923,  10, 0, 8},	/* actual: 1199.9 MHz */
-	{ 16800000, 1200000000, 1000, 14, 0, 8},
-	{ 19200000, 1200000000, 1000, 16, 0, 8},
-	{ 26000000, 1200000000, 600,  13, 0, 8},
-
+	{ 12000000, 1200000000, 1000, 10, 1, 8 },
+	{ 13000000, 1200000000,  923, 10, 1, 8 }, /* actual: 1199.9 MHz */
+	{ 16800000, 1200000000, 1000, 14, 1, 8 },
+	{ 19200000, 1200000000, 1000, 16, 1, 8 },
+	{ 26000000, 1200000000,  600, 13, 1, 8 },
 	/* 1.1 GHz */
-	{ 12000000, 1100000000, 825,  9,  0, 8},
-	{ 13000000, 1100000000, 846,  10, 0, 8},	/* actual: 1099.8 MHz */
-	{ 16800000, 1100000000, 982,  15, 0, 8},	/* actual: 1099.8 MHz */
-	{ 19200000, 1100000000, 859,  15, 0, 8},	/* actual: 1099.5 MHz */
-	{ 26000000, 1100000000, 550,  13, 0, 8},
-
+	{ 12000000, 1100000000, 825,   9, 1, 8 },
+	{ 13000000, 1100000000, 846,  10, 1, 8 }, /* actual: 1099.8 MHz */
+	{ 16800000, 1100000000, 982,  15, 1, 8 }, /* actual: 1099.8 MHz */
+	{ 19200000, 1100000000, 859,  15, 1, 8 }, /* actual: 1099.5 MHz */
+	{ 26000000, 1100000000, 550,  13, 1, 8 },
 	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 0, 8},
-	{ 13000000, 1000000000, 1000, 13, 0, 8},
-	{ 16800000, 1000000000, 833,  14, 0, 8},	/* actual: 999.6 MHz */
-	{ 19200000, 1000000000, 625,  12, 0, 8},
-	{ 26000000, 1000000000, 1000, 26, 0, 8},
+	{ 12000000, 1000000000, 1000, 12, 1, 8 },
+	{ 13000000, 1000000000, 1000, 13, 1, 8 },
+	{ 16800000, 1000000000,  833, 14, 1, 8 }, /* actual: 999.6 MHz */
+	{ 19200000, 1000000000,  625, 12, 1, 8 },
+	{ 26000000, 1000000000, 1000, 26, 1, 8 },
+	{        0,          0,    0,  0, 0, 0 },
+};
 
-	{ 0, 0, 0, 0, 0, 0 },
+static const struct pdiv_map plle_p[] = {
+	{ .pdiv = 18, .hw_val = 18 },
+	{ .pdiv = 24, .hw_val = 24 },
+	{ .pdiv =  0, .hw_val =  0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
 	/* PLLE special case: use cpcon field to store cml divider value */
-	{ 12000000,  100000000, 150, 1,  18, 11},
-	{ 216000000, 100000000, 200, 18, 24, 13},
-	{ 0, 0, 0, 0, 0, 0 },
+	{  12000000, 100000000, 150,  1, 18, 11 },
+	{ 216000000, 100000000, 200, 18, 24, 13 },
+	{         0,         0,   0,  0,  0,  0 },
 };
 
 /* PLL parameters */
@@ -422,7 +426,8 @@ static struct tegra_clk_pll_params pll_c_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_c_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct div_nmp pllm_nmp = {
@@ -454,7 +459,8 @@ static struct tegra_clk_pll_params pll_m_params = {
 	.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE,
 	.freq_table = pll_m_freq_table,
 	.flags = TEGRA_PLLM | TEGRA_PLL_HAS_CPCON |
-		 TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_FIXED,
 };
 
 static struct tegra_clk_pll_params pll_p_params = {
@@ -470,7 +476,8 @@ static struct tegra_clk_pll_params pll_p_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_p_freq_table,
-	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 	.fixed_rate = 408000000,
 };
 
@@ -487,7 +494,8 @@ static struct tegra_clk_pll_params pll_a_params = {
 	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
 	.freq_table = pll_a_freq_table,
-	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_d_params = {
@@ -504,8 +512,7 @@ static struct tegra_clk_pll_params pll_d_params = {
 	.lock_delay = 1000,
 	.freq_table = pll_d_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
-
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_d2_params = {
@@ -522,7 +529,7 @@ static struct tegra_clk_pll_params pll_d2_params = {
 	.lock_delay = 1000,
 	.freq_table = pll_d_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_u_params = {
@@ -539,7 +546,8 @@ static struct tegra_clk_pll_params pll_u_params = {
 	.lock_delay = 1000,
 	.pdiv_tohw = pllu_p,
 	.freq_table = pll_u_freq_table,
-	.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON,
+	.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+		 TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -556,7 +564,7 @@ static struct tegra_clk_pll_params pll_x_params = {
 	.lock_delay = 300,
 	.freq_table = pll_x_freq_table,
 	.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_DCCON |
-		 TEGRA_PLL_USE_LOCK,
+		 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
 static struct tegra_clk_pll_params pll_e_params = {
@@ -571,19 +579,21 @@ static struct tegra_clk_pll_params pll_e_params = {
 	.lock_mask = PLLE_MISC_LOCK,
 	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
 	.lock_delay = 300,
+	.pdiv_tohw = plle_p,
 	.freq_table = pll_e_freq_table,
-	.flags = TEGRA_PLLE_CONFIGURE | TEGRA_PLL_FIXED,
+	.flags = TEGRA_PLLE_CONFIGURE | TEGRA_PLL_FIXED |
+		 TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC,
 	.fixed_rate = 100000000,
 };
 
 static unsigned long tegra30_input_freq[] = {
-	[0] = 13000000,
-	[1] = 16800000,
-	[4] = 19200000,
-	[5] = 38400000,
-	[8] = 12000000,
-	[9] = 48000000,
-	[12] = 260000000,
+	[ 0] = 13000000,
+	[ 1] = 16800000,
+	[ 4] = 19200000,
+	[ 5] = 38400000,
+	[ 8] = 12000000,
+	[ 9] = 48000000,
+	[12] = 26000000,
 };
 
 static struct tegra_devclk devclks[] __initdata = {
@@ -861,13 +871,12 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_pll_p_out4] = { .dt_id = TEGRA30_CLK_PLL_P_OUT4, .present = true },
 	[tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
 	[tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
-
 };
 
 static void tegra30_utmi_param_configure(void)
 {
+	unsigned int i;
 	u32 reg;
-	int i;
 
 	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
 		if (input_freq == utmi_parameters[i].osc_frequency)
@@ -917,7 +926,7 @@ static void tegra30_utmi_param_configure(void)
 	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
 }
 
-static const char *pll_e_parents[] = {"pll_ref", "pll_p"};
+static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
 
 static void __init tegra30_pll_init(void)
 {
@@ -925,7 +934,7 @@ static void __init tegra30_pll_init(void)
 
 	/* PLLC */
 	clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0,
-				&pll_c_params, NULL);
+				     &pll_c_params, NULL);
 	clks[TEGRA30_CLK_PLL_C] = clk;
 
 	/* PLLC_OUT1 */
@@ -1135,7 +1144,7 @@ static void __init tegra30_periph_clk_init(void)
 {
 	struct tegra_periph_init_data *data;
 	struct clk *clk;
-	int i;
+	unsigned int i;
 
 	/* dsia */
 	clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base,
@@ -1224,7 +1233,6 @@ static void tegra30_cpu_out_of_reset(u32 cpu)
 	wmb();
 }
 
-
 static void tegra30_enable_cpu_clock(u32 cpu)
 {
 	unsigned int reg;
@@ -1237,7 +1245,6 @@ static void tegra30_enable_cpu_clock(u32 cpu)
 
 static void tegra30_disable_cpu_clock(u32 cpu)
 {
-
 	unsigned int reg;
 
 	reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
@@ -1268,7 +1275,7 @@ static void tegra30_cpu_clock_suspend(void)
 	/* switch coresite to clk_m, save off original source */
 	tegra30_cpu_clk_sctx.clk_csite_src =
 				readl(clk_base + CLK_RESET_SOURCE_CSITE);
-	writel(3<<30, clk_base + CLK_RESET_SOURCE_CSITE);
+	writel(3 << 30, clk_base + CLK_RESET_SOURCE_CSITE);
 
 	tegra30_cpu_clk_sctx.cpu_burst =
 				readl(clk_base + CLK_RESET_CCLK_BURST);
@@ -1335,44 +1342,45 @@ static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
 };
 
 static struct tegra_clk_init_table init_table[] __initdata = {
-	{TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 408000000, 0},
-	{TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 408000000, 0},
-	{TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0},
-	{TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0},
-	{TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0},
-	{TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1},
-	{TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1},
-	{TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1},
-	{TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0},
-	{TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA30_CLK_I2S3, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA30_CLK_I2S4, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
-	{TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0},
-	{TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0},
-	{TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0},
-	{TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0},
-	{TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0},
-	{TEGRA30_CLK_SBC3, TEGRA30_CLK_PLL_P, 100000000, 0},
-	{TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0},
-	{TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0},
-	{TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0},
-	{TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0},
-	{TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0},
-	{TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0},
-	{TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1},
-	{TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0},
-	{TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0},
-	{TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0},
-	{TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry. */
+	{ TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0 },
+	{ TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
+	{ TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
+	{ TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
+	{ TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0 },
+	{ TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA30_CLK_I2S3, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA30_CLK_I2S4, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
+	{ TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0 },
+	{ TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0 },
+	{ TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0 },
+	{ TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_SBC3, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 },
+	{ TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 },
+	{ TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 },
+	{ TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1 },
+	{ TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 },
+	{ TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
+	{ TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
+	/* must be the last entry */
+	{ TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
 };
 
 static void __init tegra30_clock_apply_init_table(void)
@@ -1397,12 +1405,13 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
 	TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML1, "tegra_sata_cml", NULL),
 	TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML0, "tegra_pcie", "cml"),
 	TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VCP, "nvavp", "vcp"),
-	TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL), /* MUST be the last entry */
+	/* must be the last entry */
+	TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL),
 };
 
 static const struct of_device_id pmc_match[] __initconst = {
 	{ .compatible = "nvidia,tegra30-pmc" },
-	{},
+	{ },
 };
 
 static struct tegra_audio_clk_info tegra30_audio_plls[] = {
@@ -1441,7 +1450,6 @@ static void __init tegra30_clock_init(struct device_node *np)
 			       NULL) < 0)
 		return;
 
-
 	tegra_fixed_clk_init(tegra30_clks);
 	tegra30_pll_init();
 	tegra30_super_clk_init();
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 5d2678914160..4dbcfaec576a 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -110,14 +110,16 @@ struct clk *tegra_clk_register_mc(const char *name, const char *parent_name,
  * @m:			input divider
  * @p:			post divider
  * @cpcon:		charge pump current
+ * @sdm_data:		fraction divider setting (0 = disabled)
  */
 struct tegra_clk_pll_freq_table {
 	unsigned long	input_rate;
 	unsigned long	output_rate;
-	u16		n;
+	u32		n;
 	u16		m;
 	u8		p;
 	u8		cpcon;
+	u16		sdm_data;
 };
 
 /**
@@ -156,6 +158,10 @@ struct div_nmp {
 	u8		override_divp_shift;
 };
 
+#define MAX_PLL_MISC_REG_COUNT	6
+
+struct tegra_clk_pll;
+
 /**
  * struct tegra_clk_pll_params - PLL parameters
  *
@@ -172,6 +178,14 @@ struct div_nmp {
  * @lock_enable_bit_idx:	Bit index to enable PLL lock
  * @iddq_reg:			PLL IDDQ register offset
  * @iddq_bit_idx:		Bit index to enable PLL IDDQ
+ * @reset_reg:			Register offset of where RESET bit is
+ * @reset_bit_idx:		Shift of reset bit in reset_reg
+ * @sdm_din_reg:		Register offset where SDM settings are
+ * @sdm_din_mask:		Mask of SDM divider bits
+ * @sdm_ctrl_reg:		Register offset where SDM enable is
+ * @sdm_ctrl_en_mask:		Mask of SDM enable bit
+ * @ssc_ctrl_reg:		Register offset where SSC settings are
+ * @ssc_ctrl_en_mask:		Mask of SSC enable bit
  * @aux_reg:			AUX register offset
  * @dyn_ramp_reg:		Dynamic ramp control register offset
  * @ext_misc_reg:		Miscellaneous control register offsets
@@ -182,10 +196,27 @@ struct div_nmp {
  * @stepb_shift:		Dynamic ramp step B field shift
  * @lock_delay:			Delay in us if PLL lock is not used
  * @max_p:			maximum value for the p divider
+ * @defaults_set:		Boolean signaling all reg defaults for PLL set.
  * @pdiv_tohw:			mapping of p divider to register values
  * @div_nmp:			offsets and widths on n, m and p fields
  * @freq_table:			array of frequencies supported by PLL
  * @fixed_rate:			PLL rate if it is fixed
+ * @mdiv_default:		Default value for fixed mdiv for this PLL
+ * @round_p_to_pdiv:		Callback used to round p to the closed pdiv
+ * @set_gain:			Callback to adjust N div for SDM enabled
+ *				PLL's based on fractional divider value.
+ * @calc_rate:			Callback used to change how out of table
+ *				rates (dividers and multipler) are calculated.
+ * @adjust_vco:			Callback to adjust the programming range of the
+ *				divider range (if SDM is present)
+ * @set_defaults:		Callback which will try to initialize PLL
+ *				registers to sane default values. This is first
+ *				tried during PLL registration, but if the PLL
+ *				is already enabled, it will be done the first
+ *				time the rate is changed while the PLL is
+ *				disabled.
+ * @dyn_ramp:			Callback which can be used to define a custom
+ *				dynamic ramp function for a given PLL.
  *
  * Flags:
  * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
@@ -207,6 +238,11 @@ struct div_nmp {
  *     base register.
  * TEGRA_PLL_BYPASS - PLL has bypass bit
  * TEGRA_PLL_HAS_LOCK_ENABLE - PLL has bit to enable lock monitoring
+ * TEGRA_MDIV_NEW - Switch to new method for calculating fixed mdiv
+ *     it may be more accurate (especially if SDM present)
+ * TEGRA_PLLMB - PLLMB has should be treated similar to PLLM. This
+ *     flag indicated that it is PLLMB.
+ * TEGRA_PLL_VCO_OUT - Used to indicate that the PLL has a VCO output
  */
 struct tegra_clk_pll_params {
 	unsigned long	input_min;
@@ -223,9 +259,17 @@ struct tegra_clk_pll_params {
 	u32		lock_enable_bit_idx;
 	u32		iddq_reg;
 	u32		iddq_bit_idx;
+	u32		reset_reg;
+	u32		reset_bit_idx;
+	u32		sdm_din_reg;
+	u32		sdm_din_mask;
+	u32		sdm_ctrl_reg;
+	u32		sdm_ctrl_en_mask;
+	u32		ssc_ctrl_reg;
+	u32		ssc_ctrl_en_mask;
 	u32		aux_reg;
 	u32		dyn_ramp_reg;
-	u32		ext_misc_reg[3];
+	u32		ext_misc_reg[MAX_PLL_MISC_REG_COUNT];
 	u32		pmc_divnm_reg;
 	u32		pmc_divp_reg;
 	u32		flags;
@@ -233,10 +277,22 @@ struct tegra_clk_pll_params {
 	int		stepb_shift;
 	int		lock_delay;
 	int		max_p;
-	struct pdiv_map *pdiv_tohw;
+	bool		defaults_set;
+	const struct pdiv_map *pdiv_tohw;
 	struct div_nmp	*div_nmp;
 	struct tegra_clk_pll_freq_table	*freq_table;
 	unsigned long	fixed_rate;
+	u16		mdiv_default;
+	u32	(*round_p_to_pdiv)(u32 p, u32 *pdiv);
+	void	(*set_gain)(struct tegra_clk_pll_freq_table *cfg);
+	int	(*calc_rate)(struct clk_hw *hw,
+			struct tegra_clk_pll_freq_table *cfg,
+			unsigned long rate, unsigned long parent_rate);
+	unsigned long	(*adjust_vco)(struct tegra_clk_pll_params *pll_params,
+				unsigned long parent_rate);
+	void	(*set_defaults)(struct tegra_clk_pll *pll);
+	int	(*dyn_ramp)(struct tegra_clk_pll *pll,
+			struct tegra_clk_pll_freq_table *cfg);
 };
 
 #define TEGRA_PLL_USE_LOCK BIT(0)
@@ -250,6 +306,9 @@ struct tegra_clk_pll_params {
 #define TEGRA_PLL_LOCK_MISC BIT(8)
 #define TEGRA_PLL_BYPASS BIT(9)
 #define TEGRA_PLL_HAS_LOCK_ENABLE BIT(10)
+#define TEGRA_MDIV_NEW BIT(11)
+#define TEGRA_PLLMB BIT(12)
+#define TEGRA_PLL_VCO_OUT BIT(13)
 
 /**
  * struct tegra_clk_pll - Tegra PLL clock
@@ -303,6 +362,12 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
 			    struct tegra_clk_pll_params *pll_params,
 			    spinlock_t *lock);
 
+struct clk *tegra_clk_register_pllxc_tegra210(const char *name,
+			const char *parent_name, void __iomem *clk_base,
+			void __iomem *pmc, unsigned long flags,
+			struct tegra_clk_pll_params *pll_params,
+			spinlock_t *lock);
+
 struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
 			   void __iomem *clk_base, void __iomem *pmc,
 			   unsigned long flags,
@@ -327,11 +392,35 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
 				struct tegra_clk_pll_params *pll_params,
 				spinlock_t *lock);
 
+struct clk *tegra_clk_register_plle_tegra210(const char *name,
+				const char *parent_name,
+				void __iomem *clk_base, unsigned long flags,
+				struct tegra_clk_pll_params *pll_params,
+				spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllc_tegra210(const char *name,
+				const char *parent_name, void __iomem *clk_base,
+				void __iomem *pmc, unsigned long flags,
+				struct tegra_clk_pll_params *pll_params,
+				spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllss_tegra210(const char *name,
+				const char *parent_name, void __iomem *clk_base,
+				unsigned long flags,
+				struct tegra_clk_pll_params *pll_params,
+				spinlock_t *lock);
+
 struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
 			   void __iomem *clk_base, unsigned long flags,
 			   struct tegra_clk_pll_params *pll_params,
 			   spinlock_t *lock);
 
+struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
+			   void __iomem *clk_base, void __iomem *pmc,
+			   unsigned long flags,
+			   struct tegra_clk_pll_params *pll_params,
+			   spinlock_t *lock);
+
 /**
  * struct tegra_clk_pll_out - PLL divider down clock
  *
@@ -653,6 +742,9 @@ int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
 void tegra_super_clk_gen4_init(void __iomem *clk_base,
 			void __iomem *pmc_base, struct tegra_clk *tegra_clks,
 			struct tegra_clk_pll_params *pll_params);
+void tegra_super_clk_gen5_init(void __iomem *clk_base,
+			void __iomem *pmc_base, struct tegra_clk *tegra_clks,
+			struct tegra_clk_pll_params *pll_params);
 
 #ifdef CONFIG_TEGRA_CLK_EMC
 struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
@@ -674,5 +766,8 @@ void tegra114_clock_deassert_dfll_dvco_reset(void);
 
 typedef void (*tegra_clk_apply_init_table_func)(void);
 extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
+int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll);
+u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate);
+int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
 
 #endif /* TEGRA_CLK_H */
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index f3eab6e79027..b336a8c11e2a 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -323,7 +323,7 @@ static void omap2_apll_deny_idle(struct clk_hw_omap *clk)
 	omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE);
 }
 
-static struct clk_hw_omap_ops omap2_apll_hwops = {
+static const struct clk_hw_omap_ops omap2_apll_hwops = {
 	.allow_idle	= &omap2_apll_allow_idle,
 	.deny_idle	= &omap2_apll_deny_idle,
 };
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
index f4dec00fb684..1c300388782b 100644
--- a/drivers/clk/ti/dpll3xxx.c
+++ b/drivers/clk/ti/dpll3xxx.c
@@ -305,8 +305,9 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
 static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 {
 	struct dpll_data *dd = clk->dpll_data;
-	u8 dco, sd_div;
+	u8 dco, sd_div, ai = 0;
 	u32 v;
+	bool errata_i810;
 
 	/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
 	_omap3_noncore_dpll_bypass(clk);
@@ -350,6 +351,25 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 		v |= sd_div << __ffs(dd->sddiv_mask);
 	}
 
+	/*
+	 * Errata i810 - DPLL controller can get stuck while transitioning
+	 * to a power saving state. Software must ensure the DPLL can not
+	 * transition to a low power state while changing M/N values.
+	 * Easiest way to accomplish this is to prevent DPLL autoidle
+	 * before doing the M/N re-program.
+	 */
+	errata_i810 = ti_clk_get_features()->flags & TI_CLK_ERRATA_I810;
+
+	if (errata_i810) {
+		ai = omap3_dpll_autoidle_read(clk);
+		if (ai) {
+			omap3_dpll_deny_idle(clk);
+
+			/* OCP barrier */
+			omap3_dpll_autoidle_read(clk);
+		}
+	}
+
 	ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg);
 
 	/* Set 4X multiplier and low-power mode */
@@ -379,6 +399,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 
 	_omap3_noncore_dpll_lock(clk);
 
+	if (errata_i810 && ai)
+		omap3_dpll_allow_idle(clk);
+
 	return 0;
 }
 
diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c
index a1cdef6b0f90..e78755e0ef78 100644
--- a/drivers/clk/versatile/clk-sp810.c
+++ b/drivers/clk/versatile/clk-sp810.c
@@ -95,13 +95,12 @@ static void __init clk_sp810_of_setup(struct device_node *node)
 	int i;
 	bool deprecated;
 
-	if (!sp810) {
-		pr_err("Failed to allocate memory for SP810!\n");
+	if (!sp810)
 		return;
-	}
 
 	if (of_clk_parent_fill(node, parent_names, num) != num) {
 		pr_warn("Failed to obtain parent clocks for SP810!\n");
+		kfree(sp810);
 		return;
 	}
 
diff --git a/include/dt-bindings/clock/bcm2835-aux.h b/include/dt-bindings/clock/bcm2835-aux.h
new file mode 100644
index 000000000000..d91156e2658d
--- /dev/null
+++ b/include/dt-bindings/clock/bcm2835-aux.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define BCM2835_AUX_CLOCK_UART		0
+#define BCM2835_AUX_CLOCK_SPI1		1
+#define BCM2835_AUX_CLOCK_SPI2		2
+#define BCM2835_AUX_CLOCK_COUNT		3
diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h
index d323efac7edf..61f1d20c2a67 100644
--- a/include/dt-bindings/clock/bcm2835.h
+++ b/include/dt-bindings/clock/bcm2835.h
@@ -43,5 +43,6 @@
 #define BCM2835_CLOCK_TSENS		27
 #define BCM2835_CLOCK_EMMC		28
 #define BCM2835_CLOCK_PERI_IMAGE	29
+#define BCM2835_CLOCK_PWM		30
 
-#define BCM2835_CLOCK_COUNT		30
+#define BCM2835_CLOCK_COUNT		31
diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h
index 99da0d117a7d..7699ee9c16c0 100644
--- a/include/dt-bindings/clock/exynos5420.h
+++ b/include/dt-bindings/clock/exynos5420.h
@@ -25,6 +25,8 @@
 #define CLK_FOUT_MPLL		10
 #define CLK_FOUT_BPLL		11
 #define CLK_FOUT_KPLL		12
+#define CLK_ARM_CLK		13
+#define CLK_KFC_CLK		14
 
 /* gate for special clocks (sclk) */
 #define CLK_SCLK_UART0		128
@@ -210,6 +212,8 @@
 #define CLK_MOUT_SW_ACLK300     649
 #define CLK_MOUT_USER_ACLK400_DISP1     650
 #define CLK_MOUT_SW_ACLK400     651
+#define CLK_MOUT_USER_ACLK300_GSCL	652
+#define CLK_MOUT_SW_ACLK300_GSCL	653
 
 /* divider clocks */
 #define CLK_DOUT_PIXEL		768
diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h
index a4a7a9ce3457..edca8985c50e 100644
--- a/include/dt-bindings/clock/imx7d-clock.h
+++ b/include/dt-bindings/clock/imx7d-clock.h
@@ -447,5 +447,6 @@
 #define IMX7D_SEMA4_HS_ROOT_CLK		434
 #define IMX7D_PLL_DRAM_TEST_DIV		435
 #define IMX7D_ADC_ROOT_CLK		436
-#define IMX7D_CLK_END			437
+#define IMX7D_CLK_ARM			437
+#define IMX7D_CLK_END			438
 #endif /* __DT_BINDINGS_CLOCK_IMX7D_H */
diff --git a/include/dt-bindings/clock/lpc32xx-clock.h b/include/dt-bindings/clock/lpc32xx-clock.h
new file mode 100644
index 000000000000..bcb1c9a73519
--- /dev/null
+++ b/include/dt-bindings/clock/lpc32xx-clock.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Vladimir Zapolskiy <vz@mleia.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+#ifndef __DT_BINDINGS_LPC32XX_CLOCK_H
+#define __DT_BINDINGS_LPC32XX_CLOCK_H
+
+/* LPC32XX System Control Block clocks */
+#define LPC32XX_CLK_RTC		1
+#define LPC32XX_CLK_DMA		2
+#define LPC32XX_CLK_MLC		3
+#define LPC32XX_CLK_SLC		4
+#define LPC32XX_CLK_LCD		5
+#define LPC32XX_CLK_MAC		6
+#define LPC32XX_CLK_SD		7
+#define LPC32XX_CLK_DDRAM	8
+#define LPC32XX_CLK_SSP0	9
+#define LPC32XX_CLK_SSP1	10
+#define LPC32XX_CLK_UART3	11
+#define LPC32XX_CLK_UART4	12
+#define LPC32XX_CLK_UART5	13
+#define LPC32XX_CLK_UART6	14
+#define LPC32XX_CLK_IRDA	15
+#define LPC32XX_CLK_I2C1	16
+#define LPC32XX_CLK_I2C2	17
+#define LPC32XX_CLK_TIMER0	18
+#define LPC32XX_CLK_TIMER1	19
+#define LPC32XX_CLK_TIMER2	20
+#define LPC32XX_CLK_TIMER3	21
+#define LPC32XX_CLK_TIMER4	22
+#define LPC32XX_CLK_TIMER5	23
+#define LPC32XX_CLK_WDOG	24
+#define LPC32XX_CLK_I2S0	25
+#define LPC32XX_CLK_I2S1	26
+#define LPC32XX_CLK_SPI1	27
+#define LPC32XX_CLK_SPI2	28
+#define LPC32XX_CLK_MCPWM	29
+#define LPC32XX_CLK_HSTIMER	30
+#define LPC32XX_CLK_KEY		31
+#define LPC32XX_CLK_PWM1	32
+#define LPC32XX_CLK_PWM2	33
+#define LPC32XX_CLK_ADC		34
+
+/* LPC32XX USB clocks */
+#define LPC32XX_USB_CLK_I2C	1
+#define LPC32XX_USB_CLK_DEVICE	2
+#define LPC32XX_USB_CLK_HOST	3
+
+#endif /* __DT_BINDINGS_LPC32XX_CLOCK_H */
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8996.h b/include/dt-bindings/clock/qcom,gcc-msm8996.h
new file mode 100644
index 000000000000..888e75ce8fec
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-msm8996.h
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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_MSM_GCC_8996_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8996_H
+
+#define GPLL0_EARLY						0
+#define GPLL0							1
+#define GPLL1_EARLY						2
+#define GPLL1							3
+#define GPLL2_EARLY						4
+#define GPLL2							5
+#define GPLL3_EARLY						6
+#define GPLL3							7
+#define GPLL4_EARLY						8
+#define GPLL4							9
+#define SYSTEM_NOC_CLK_SRC					10
+#define CONFIG_NOC_CLK_SRC					11
+#define PERIPH_NOC_CLK_SRC					12
+#define MMSS_BIMC_GFX_CLK_SRC					13
+#define USB30_MASTER_CLK_SRC					14
+#define USB30_MOCK_UTMI_CLK_SRC					15
+#define USB3_PHY_AUX_CLK_SRC					16
+#define USB20_MASTER_CLK_SRC					17
+#define USB20_MOCK_UTMI_CLK_SRC					18
+#define SDCC1_APPS_CLK_SRC					19
+#define SDCC1_ICE_CORE_CLK_SRC					20
+#define SDCC2_APPS_CLK_SRC					21
+#define SDCC3_APPS_CLK_SRC					22
+#define SDCC4_APPS_CLK_SRC					23
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC				24
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC				25
+#define BLSP1_UART1_APPS_CLK_SRC				26
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC				27
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC				28
+#define BLSP1_UART2_APPS_CLK_SRC				29
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC				30
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC				31
+#define BLSP1_UART3_APPS_CLK_SRC				32
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC				33
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC				34
+#define BLSP1_UART4_APPS_CLK_SRC				35
+#define BLSP1_QUP5_SPI_APPS_CLK_SRC				36
+#define BLSP1_QUP5_I2C_APPS_CLK_SRC				37
+#define BLSP1_UART5_APPS_CLK_SRC				38
+#define BLSP1_QUP6_SPI_APPS_CLK_SRC				39
+#define BLSP1_QUP6_I2C_APPS_CLK_SRC				40
+#define BLSP1_UART6_APPS_CLK_SRC				41
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC				42
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC				43
+#define BLSP2_UART1_APPS_CLK_SRC				44
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC				45
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC				46
+#define BLSP2_UART2_APPS_CLK_SRC				47
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC				48
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC				49
+#define BLSP2_UART3_APPS_CLK_SRC				50
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC				51
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC				52
+#define BLSP2_UART4_APPS_CLK_SRC				53
+#define BLSP2_QUP5_SPI_APPS_CLK_SRC				54
+#define BLSP2_QUP5_I2C_APPS_CLK_SRC				55
+#define BLSP2_UART5_APPS_CLK_SRC				56
+#define BLSP2_QUP6_SPI_APPS_CLK_SRC				57
+#define BLSP2_QUP6_I2C_APPS_CLK_SRC				58
+#define BLSP2_UART6_APPS_CLK_SRC				59
+#define PDM2_CLK_SRC						60
+#define TSIF_REF_CLK_SRC					61
+#define CE1_CLK_SRC						62
+#define GCC_SLEEP_CLK_SRC					63
+#define BIMC_CLK_SRC						64
+#define HMSS_AHB_CLK_SRC					65
+#define BIMC_HMSS_AXI_CLK_SRC					66
+#define HMSS_RBCPR_CLK_SRC					67
+#define HMSS_GPLL0_CLK_SRC					68
+#define GP1_CLK_SRC						69
+#define GP2_CLK_SRC						70
+#define GP3_CLK_SRC						71
+#define PCIE_AUX_CLK_SRC					72
+#define UFS_AXI_CLK_SRC						73
+#define UFS_ICE_CORE_CLK_SRC					74
+#define QSPI_SER_CLK_SRC					75
+#define GCC_SYS_NOC_AXI_CLK					76
+#define GCC_SYS_NOC_HMSS_AHB_CLK				77
+#define GCC_SNOC_CNOC_AHB_CLK					78
+#define GCC_SNOC_PNOC_AHB_CLK					79
+#define GCC_SYS_NOC_AT_CLK					80
+#define GCC_SYS_NOC_USB3_AXI_CLK				81
+#define GCC_SYS_NOC_UFS_AXI_CLK					82
+#define GCC_CFG_NOC_AHB_CLK					83
+#define GCC_PERIPH_NOC_AHB_CLK					84
+#define GCC_PERIPH_NOC_USB20_AHB_CLK				85
+#define GCC_TIC_CLK						86
+#define GCC_IMEM_AXI_CLK					87
+#define GCC_MMSS_SYS_NOC_AXI_CLK				88
+#define GCC_MMSS_NOC_CFG_AHB_CLK				89
+#define GCC_MMSS_BIMC_GFX_CLK					90
+#define GCC_USB30_MASTER_CLK					91
+#define GCC_USB30_SLEEP_CLK					92
+#define GCC_USB30_MOCK_UTMI_CLK					93
+#define GCC_USB3_PHY_AUX_CLK					94
+#define GCC_USB3_PHY_PIPE_CLK					95
+#define GCC_USB20_MASTER_CLK					96
+#define GCC_USB20_SLEEP_CLK					97
+#define GCC_USB20_MOCK_UTMI_CLK					98
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK				99
+#define GCC_SDCC1_APPS_CLK					100
+#define GCC_SDCC1_AHB_CLK					101
+#define GCC_SDCC1_ICE_CORE_CLK					102
+#define GCC_SDCC2_APPS_CLK					103
+#define GCC_SDCC2_AHB_CLK					104
+#define GCC_SDCC3_APPS_CLK					105
+#define GCC_SDCC3_AHB_CLK					106
+#define GCC_SDCC4_APPS_CLK					107
+#define GCC_SDCC4_AHB_CLK					108
+#define GCC_BLSP1_AHB_CLK					109
+#define GCC_BLSP1_SLEEP_CLK					110
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK				111
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK				112
+#define GCC_BLSP1_UART1_APPS_CLK				113
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK				114
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK				115
+#define GCC_BLSP1_UART2_APPS_CLK				116
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK				117
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK				118
+#define GCC_BLSP1_UART3_APPS_CLK				119
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK				120
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK				121
+#define GCC_BLSP1_UART4_APPS_CLK				122
+#define GCC_BLSP1_QUP5_SPI_APPS_CLK				123
+#define GCC_BLSP1_QUP5_I2C_APPS_CLK				124
+#define GCC_BLSP1_UART5_APPS_CLK				125
+#define GCC_BLSP1_QUP6_SPI_APPS_CLK				126
+#define GCC_BLSP1_QUP6_I2C_APPS_CLK				127
+#define GCC_BLSP1_UART6_APPS_CLK				128
+#define GCC_BLSP2_AHB_CLK					129
+#define GCC_BLSP2_SLEEP_CLK					130
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK				131
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK				132
+#define GCC_BLSP2_UART1_APPS_CLK				133
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK				134
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK				135
+#define GCC_BLSP2_UART2_APPS_CLK				136
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK				137
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK				138
+#define GCC_BLSP2_UART3_APPS_CLK				139
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK				140
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK				141
+#define GCC_BLSP2_UART4_APPS_CLK				142
+#define GCC_BLSP2_QUP5_SPI_APPS_CLK				143
+#define GCC_BLSP2_QUP5_I2C_APPS_CLK				144
+#define GCC_BLSP2_UART5_APPS_CLK				145
+#define GCC_BLSP2_QUP6_SPI_APPS_CLK				146
+#define GCC_BLSP2_QUP6_I2C_APPS_CLK				147
+#define GCC_BLSP2_UART6_APPS_CLK				148
+#define GCC_PDM_AHB_CLK						149
+#define GCC_PDM_XO4_CLK						150
+#define GCC_PDM2_CLK						151
+#define GCC_PRNG_AHB_CLK					152
+#define GCC_TSIF_AHB_CLK					153
+#define GCC_TSIF_REF_CLK					154
+#define GCC_TSIF_INACTIVITY_TIMERS_CLK				155
+#define GCC_TCSR_AHB_CLK					156
+#define GCC_BOOT_ROM_AHB_CLK					157
+#define GCC_MSG_RAM_AHB_CLK					158
+#define GCC_TLMM_AHB_CLK					159
+#define GCC_TLMM_CLK						160
+#define GCC_MPM_AHB_CLK						161
+#define GCC_SPMI_SER_CLK					162
+#define GCC_SPMI_CNOC_AHB_CLK					163
+#define GCC_CE1_CLK						164
+#define GCC_CE1_AXI_CLK						165
+#define GCC_CE1_AHB_CLK						166
+#define GCC_BIMC_HMSS_AXI_CLK					167
+#define GCC_BIMC_GFX_CLK					168
+#define GCC_HMSS_AHB_CLK					169
+#define GCC_HMSS_SLV_AXI_CLK					170
+#define GCC_HMSS_MSTR_AXI_CLK					171
+#define GCC_HMSS_RBCPR_CLK					172
+#define GCC_GP1_CLK						173
+#define GCC_GP2_CLK						174
+#define GCC_GP3_CLK						175
+#define GCC_PCIE_0_SLV_AXI_CLK					176
+#define GCC_PCIE_0_MSTR_AXI_CLK					177
+#define GCC_PCIE_0_CFG_AHB_CLK					178
+#define GCC_PCIE_0_AUX_CLK					179
+#define GCC_PCIE_0_PIPE_CLK					180
+#define GCC_PCIE_1_SLV_AXI_CLK					181
+#define GCC_PCIE_1_MSTR_AXI_CLK					182
+#define GCC_PCIE_1_CFG_AHB_CLK					183
+#define GCC_PCIE_1_AUX_CLK					184
+#define GCC_PCIE_1_PIPE_CLK					185
+#define GCC_PCIE_2_SLV_AXI_CLK					186
+#define GCC_PCIE_2_MSTR_AXI_CLK					187
+#define GCC_PCIE_2_CFG_AHB_CLK					188
+#define GCC_PCIE_2_AUX_CLK					189
+#define GCC_PCIE_2_PIPE_CLK					190
+#define GCC_PCIE_PHY_CFG_AHB_CLK				191
+#define GCC_PCIE_PHY_AUX_CLK					192
+#define GCC_UFS_AXI_CLK						193
+#define GCC_UFS_AHB_CLK						194
+#define GCC_UFS_TX_CFG_CLK					195
+#define GCC_UFS_RX_CFG_CLK					196
+#define GCC_UFS_TX_SYMBOL_0_CLK					197
+#define GCC_UFS_RX_SYMBOL_0_CLK					198
+#define GCC_UFS_RX_SYMBOL_1_CLK					199
+#define GCC_UFS_UNIPRO_CORE_CLK					200
+#define GCC_UFS_ICE_CORE_CLK					201
+#define GCC_UFS_SYS_CLK_CORE_CLK				202
+#define GCC_UFS_TX_SYMBOL_CLK_CORE_CLK				203
+#define GCC_AGGRE0_SNOC_AXI_CLK					204
+#define GCC_AGGRE0_CNOC_AHB_CLK					205
+#define GCC_SMMU_AGGRE0_AXI_CLK					206
+#define GCC_SMMU_AGGRE0_AHB_CLK					207
+#define GCC_AGGRE1_PNOC_AHB_CLK					208
+#define GCC_AGGRE2_UFS_AXI_CLK					209
+#define GCC_AGGRE2_USB3_AXI_CLK					210
+#define GCC_QSPI_AHB_CLK					211
+#define GCC_QSPI_SER_CLK					212
+#define GCC_USB3_CLKREF_CLK					213
+#define GCC_HDMI_CLKREF_CLK					214
+#define GCC_UFS_CLKREF_CLK					215
+#define GCC_PCIE_CLKREF_CLK					216
+#define GCC_RX2_USB2_CLKREF_CLK					217
+#define GCC_RX1_USB2_CLKREF_CLK					218
+
+#define GCC_SYSTEM_NOC_BCR					0
+#define GCC_CONFIG_NOC_BCR					1
+#define GCC_PERIPH_NOC_BCR					2
+#define GCC_IMEM_BCR						3
+#define GCC_MMSS_BCR						4
+#define GCC_PIMEM_BCR						5
+#define GCC_QDSS_BCR						6
+#define GCC_USB_30_BCR						7
+#define GCC_USB_20_BCR						8
+#define GCC_QUSB2PHY_PRIM_BCR					9
+#define GCC_QUSB2PHY_SEC_BCR					10
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR				11
+#define GCC_SDCC1_BCR						12
+#define GCC_SDCC2_BCR						13
+#define GCC_SDCC3_BCR						14
+#define GCC_SDCC4_BCR						15
+#define GCC_BLSP1_BCR						16
+#define GCC_BLSP1_QUP1_BCR					17
+#define GCC_BLSP1_UART1_BCR					18
+#define GCC_BLSP1_QUP2_BCR					19
+#define GCC_BLSP1_UART2_BCR					20
+#define GCC_BLSP1_QUP3_BCR					21
+#define GCC_BLSP1_UART3_BCR					22
+#define GCC_BLSP1_QUP4_BCR					23
+#define GCC_BLSP1_UART4_BCR					24
+#define GCC_BLSP1_QUP5_BCR					25
+#define GCC_BLSP1_UART5_BCR					26
+#define GCC_BLSP1_QUP6_BCR					27
+#define GCC_BLSP1_UART6_BCR					28
+#define GCC_BLSP2_BCR						29
+#define GCC_BLSP2_QUP1_BCR					30
+#define GCC_BLSP2_UART1_BCR					31
+#define GCC_BLSP2_QUP2_BCR					32
+#define GCC_BLSP2_UART2_BCR					33
+#define GCC_BLSP2_QUP3_BCR					34
+#define GCC_BLSP2_UART3_BCR					35
+#define GCC_BLSP2_QUP4_BCR					36
+#define GCC_BLSP2_UART4_BCR					37
+#define GCC_BLSP2_QUP5_BCR					38
+#define GCC_BLSP2_UART5_BCR					39
+#define GCC_BLSP2_QUP6_BCR					40
+#define GCC_BLSP2_UART6_BCR					41
+#define GCC_PDM_BCR						42
+#define GCC_PRNG_BCR						43
+#define GCC_TSIF_BCR						44
+#define GCC_TCSR_BCR						45
+#define GCC_BOOT_ROM_BCR					46
+#define GCC_MSG_RAM_BCR						47
+#define GCC_TLMM_BCR						48
+#define GCC_MPM_BCR						49
+#define GCC_SEC_CTRL_BCR					50
+#define GCC_SPMI_BCR						51
+#define GCC_SPDM_BCR						52
+#define GCC_CE1_BCR						53
+#define GCC_BIMC_BCR						54
+#define GCC_SNOC_BUS_TIMEOUT0_BCR				55
+#define GCC_SNOC_BUS_TIMEOUT2_BCR				56
+#define GCC_SNOC_BUS_TIMEOUT1_BCR				57
+#define GCC_SNOC_BUS_TIMEOUT3_BCR				58
+#define GCC_SNOC_BUS_TIMEOUT_EXTREF_BCR				59
+#define GCC_PNOC_BUS_TIMEOUT0_BCR				60
+#define GCC_PNOC_BUS_TIMEOUT1_BCR				61
+#define GCC_PNOC_BUS_TIMEOUT2_BCR				62
+#define GCC_PNOC_BUS_TIMEOUT3_BCR				63
+#define GCC_PNOC_BUS_TIMEOUT4_BCR				64
+#define GCC_CNOC_BUS_TIMEOUT0_BCR				65
+#define GCC_CNOC_BUS_TIMEOUT1_BCR				66
+#define GCC_CNOC_BUS_TIMEOUT2_BCR				67
+#define GCC_CNOC_BUS_TIMEOUT3_BCR				68
+#define GCC_CNOC_BUS_TIMEOUT4_BCR				69
+#define GCC_CNOC_BUS_TIMEOUT5_BCR				70
+#define GCC_CNOC_BUS_TIMEOUT6_BCR				71
+#define GCC_CNOC_BUS_TIMEOUT7_BCR				72
+#define GCC_CNOC_BUS_TIMEOUT8_BCR				73
+#define GCC_CNOC_BUS_TIMEOUT9_BCR				74
+#define GCC_CNOC_BUS_TIMEOUT_EXTREF_BCR				75
+#define GCC_APB2JTAG_BCR					76
+#define GCC_RBCPR_CX_BCR					77
+#define GCC_RBCPR_MX_BCR					78
+#define GCC_PCIE_0_BCR						79
+#define GCC_PCIE_0_PHY_BCR					80
+#define GCC_PCIE_1_BCR						81
+#define GCC_PCIE_1_PHY_BCR					82
+#define GCC_PCIE_2_BCR						83
+#define GCC_PCIE_2_PHY_BCR					84
+#define GCC_PCIE_PHY_BCR					85
+#define GCC_DCD_BCR						86
+#define GCC_OBT_ODT_BCR						87
+#define GCC_UFS_BCR						88
+#define GCC_SSC_BCR						89
+#define GCC_VS_BCR						90
+#define GCC_AGGRE0_NOC_BCR					91
+#define GCC_AGGRE1_NOC_BCR					92
+#define GCC_AGGRE2_NOC_BCR					93
+#define GCC_DCC_BCR						94
+#define GCC_IPA_BCR						95
+#define GCC_QSPI_BCR						96
+#define GCC_SKL_BCR						97
+#define GCC_MSMPU_BCR						98
+#define GCC_MSS_Q6_BCR						99
+#define GCC_QREFS_VBG_CAL_BCR					100
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8996.h b/include/dt-bindings/clock/qcom,mmcc-msm8996.h
new file mode 100644
index 000000000000..9b81ca65fcec
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,mmcc-msm8996.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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_MSM_MMCC_8996_H
+#define _DT_BINDINGS_CLK_MSM_MMCC_8996_H
+
+#define MMPLL0_EARLY					0
+#define MMPLL0_PLL					1
+#define MMPLL1_EARLY					2
+#define MMPLL1_PLL					3
+#define MMPLL2_EARLY					4
+#define MMPLL2_PLL					5
+#define MMPLL3_EARLY					6
+#define MMPLL3_PLL					7
+#define MMPLL4_EARLY					8
+#define MMPLL4_PLL					9
+#define MMPLL5_EARLY					10
+#define MMPLL5_PLL					11
+#define MMPLL8_EARLY					12
+#define MMPLL8_PLL					13
+#define MMPLL9_EARLY					14
+#define MMPLL9_PLL					15
+#define AHB_CLK_SRC					16
+#define AXI_CLK_SRC					17
+#define MAXI_CLK_SRC					18
+#define DSA_CORE_CLK_SRC				19
+#define GFX3D_CLK_SRC					20
+#define RBBMTIMER_CLK_SRC				21
+#define ISENSE_CLK_SRC					22
+#define RBCPR_CLK_SRC					23
+#define VIDEO_CORE_CLK_SRC				24
+#define VIDEO_SUBCORE0_CLK_SRC				25
+#define VIDEO_SUBCORE1_CLK_SRC				26
+#define PCLK0_CLK_SRC					27
+#define PCLK1_CLK_SRC					28
+#define MDP_CLK_SRC					29
+#define EXTPCLK_CLK_SRC					30
+#define VSYNC_CLK_SRC					31
+#define HDMI_CLK_SRC					32
+#define BYTE0_CLK_SRC					33
+#define BYTE1_CLK_SRC					34
+#define ESC0_CLK_SRC					35
+#define ESC1_CLK_SRC					36
+#define CAMSS_GP0_CLK_SRC				37
+#define CAMSS_GP1_CLK_SRC				38
+#define MCLK0_CLK_SRC					39
+#define MCLK1_CLK_SRC					40
+#define MCLK2_CLK_SRC					41
+#define MCLK3_CLK_SRC					42
+#define CCI_CLK_SRC					43
+#define CSI0PHYTIMER_CLK_SRC				44
+#define CSI1PHYTIMER_CLK_SRC				45
+#define CSI2PHYTIMER_CLK_SRC				46
+#define CSIPHY0_3P_CLK_SRC				47
+#define CSIPHY1_3P_CLK_SRC				48
+#define CSIPHY2_3P_CLK_SRC				49
+#define JPEG0_CLK_SRC					50
+#define JPEG2_CLK_SRC					51
+#define JPEG_DMA_CLK_SRC				52
+#define VFE0_CLK_SRC					53
+#define VFE1_CLK_SRC					54
+#define CPP_CLK_SRC					55
+#define CSI0_CLK_SRC					56
+#define CSI1_CLK_SRC					57
+#define CSI2_CLK_SRC					58
+#define CSI3_CLK_SRC					59
+#define FD_CORE_CLK_SRC					60
+#define MMSS_CXO_CLK					61
+#define MMSS_SLEEPCLK_CLK				62
+#define MMSS_MMAGIC_AHB_CLK				63
+#define MMSS_MMAGIC_CFG_AHB_CLK				64
+#define MMSS_MISC_AHB_CLK				65
+#define MMSS_MISC_CXO_CLK				66
+#define MMSS_BTO_AHB_CLK				67
+#define MMSS_MMAGIC_AXI_CLK				68
+#define MMSS_S0_AXI_CLK					69
+#define MMSS_MMAGIC_MAXI_CLK				70
+#define DSA_CORE_CLK					71
+#define DSA_NOC_CFG_AHB_CLK				72
+#define MMAGIC_CAMSS_AXI_CLK				73
+#define MMAGIC_CAMSS_NOC_CFG_AHB_CLK			74
+#define THROTTLE_CAMSS_CXO_CLK				75
+#define THROTTLE_CAMSS_AHB_CLK				76
+#define THROTTLE_CAMSS_AXI_CLK				77
+#define SMMU_VFE_AHB_CLK				78
+#define SMMU_VFE_AXI_CLK				79
+#define SMMU_CPP_AHB_CLK				80
+#define SMMU_CPP_AXI_CLK				81
+#define SMMU_JPEG_AHB_CLK				82
+#define SMMU_JPEG_AXI_CLK				83
+#define MMAGIC_MDSS_AXI_CLK				84
+#define MMAGIC_MDSS_NOC_CFG_AHB_CLK			85
+#define THROTTLE_MDSS_CXO_CLK				86
+#define THROTTLE_MDSS_AHB_CLK				87
+#define THROTTLE_MDSS_AXI_CLK				88
+#define SMMU_ROT_AHB_CLK				89
+#define SMMU_ROT_AXI_CLK				90
+#define SMMU_MDP_AHB_CLK				91
+#define SMMU_MDP_AXI_CLK				92
+#define MMAGIC_VIDEO_AXI_CLK				93
+#define MMAGIC_VIDEO_NOC_CFG_AHB_CLK			94
+#define THROTTLE_VIDEO_CXO_CLK				95
+#define THROTTLE_VIDEO_AHB_CLK				96
+#define THROTTLE_VIDEO_AXI_CLK				97
+#define SMMU_VIDEO_AHB_CLK				98
+#define SMMU_VIDEO_AXI_CLK				99
+#define MMAGIC_BIMC_AXI_CLK				100
+#define MMAGIC_BIMC_NOC_CFG_AHB_CLK			101
+#define GPU_GX_GFX3D_CLK				102
+#define GPU_GX_RBBMTIMER_CLK				103
+#define GPU_AHB_CLK					104
+#define GPU_AON_ISENSE_CLK				105
+#define VMEM_MAXI_CLK					106
+#define VMEM_AHB_CLK					107
+#define MMSS_RBCPR_CLK					108
+#define MMSS_RBCPR_AHB_CLK				109
+#define VIDEO_CORE_CLK					110
+#define VIDEO_AXI_CLK					111
+#define VIDEO_MAXI_CLK					112
+#define VIDEO_AHB_CLK					113
+#define VIDEO_SUBCORE0_CLK				114
+#define VIDEO_SUBCORE1_CLK				115
+#define MDSS_AHB_CLK					116
+#define MDSS_HDMI_AHB_CLK				117
+#define MDSS_AXI_CLK					118
+#define MDSS_PCLK0_CLK					119
+#define MDSS_PCLK1_CLK					120
+#define MDSS_MDP_CLK					121
+#define MDSS_EXTPCLK_CLK				122
+#define MDSS_VSYNC_CLK					123
+#define MDSS_HDMI_CLK					124
+#define MDSS_BYTE0_CLK					125
+#define MDSS_BYTE1_CLK					126
+#define MDSS_ESC0_CLK					127
+#define MDSS_ESC1_CLK					128
+#define CAMSS_TOP_AHB_CLK				129
+#define CAMSS_AHB_CLK					130
+#define CAMSS_MICRO_AHB_CLK				131
+#define CAMSS_GP0_CLK					132
+#define CAMSS_GP1_CLK					133
+#define CAMSS_MCLK0_CLK					134
+#define CAMSS_MCLK1_CLK					135
+#define CAMSS_MCLK2_CLK					136
+#define CAMSS_MCLK3_CLK					137
+#define CAMSS_CCI_CLK					138
+#define CAMSS_CCI_AHB_CLK				139
+#define CAMSS_CSI0PHYTIMER_CLK				140
+#define CAMSS_CSI1PHYTIMER_CLK				141
+#define CAMSS_CSI2PHYTIMER_CLK				142
+#define CAMSS_CSIPHY0_3P_CLK				143
+#define CAMSS_CSIPHY1_3P_CLK				144
+#define CAMSS_CSIPHY2_3P_CLK				145
+#define CAMSS_JPEG0_CLK					146
+#define CAMSS_JPEG2_CLK					147
+#define CAMSS_JPEG_DMA_CLK				148
+#define CAMSS_JPEG_AHB_CLK				149
+#define CAMSS_JPEG_AXI_CLK				150
+#define CAMSS_VFE_AHB_CLK				151
+#define CAMSS_VFE_AXI_CLK				152
+#define CAMSS_VFE0_CLK					153
+#define CAMSS_VFE0_STREAM_CLK				154
+#define CAMSS_VFE0_AHB_CLK				155
+#define CAMSS_VFE1_CLK					156
+#define CAMSS_VFE1_STREAM_CLK				157
+#define CAMSS_VFE1_AHB_CLK				158
+#define CAMSS_CSI_VFE0_CLK				159
+#define CAMSS_CSI_VFE1_CLK				160
+#define CAMSS_CPP_VBIF_AHB_CLK				161
+#define CAMSS_CPP_AXI_CLK				162
+#define CAMSS_CPP_CLK					163
+#define CAMSS_CPP_AHB_CLK				164
+#define CAMSS_CSI0_CLK					165
+#define CAMSS_CSI0_AHB_CLK				166
+#define CAMSS_CSI0PHY_CLK				167
+#define CAMSS_CSI0RDI_CLK				168
+#define CAMSS_CSI0PIX_CLK				169
+#define CAMSS_CSI1_CLK					170
+#define CAMSS_CSI1_AHB_CLK				171
+#define CAMSS_CSI1PHY_CLK				172
+#define CAMSS_CSI1RDI_CLK				173
+#define CAMSS_CSI1PIX_CLK				174
+#define CAMSS_CSI2_CLK					175
+#define CAMSS_CSI2_AHB_CLK				176
+#define CAMSS_CSI2PHY_CLK				177
+#define CAMSS_CSI2RDI_CLK				178
+#define CAMSS_CSI2PIX_CLK				179
+#define CAMSS_CSI3_CLK					180
+#define CAMSS_CSI3_AHB_CLK				181
+#define CAMSS_CSI3PHY_CLK				182
+#define CAMSS_CSI3RDI_CLK				183
+#define CAMSS_CSI3PIX_CLK				184
+#define CAMSS_ISPIF_AHB_CLK				185
+#define FD_CORE_CLK					186
+#define FD_CORE_UAR_CLK					187
+#define FD_AHB_CLK					188
+#define MMSS_SPDM_CSI0_CLK				189
+#define MMSS_SPDM_JPEG_DMA_CLK				190
+#define MMSS_SPDM_CPP_CLK				191
+#define MMSS_SPDM_PCLK0_CLK				192
+#define MMSS_SPDM_AHB_CLK				193
+#define MMSS_SPDM_GFX3D_CLK				194
+#define MMSS_SPDM_PCLK1_CLK				195
+#define MMSS_SPDM_JPEG2_CLK				196
+#define MMSS_SPDM_DEBUG_CLK				197
+#define MMSS_SPDM_VFE1_CLK				198
+#define MMSS_SPDM_VFE0_CLK				199
+#define MMSS_SPDM_VIDEO_CORE_CLK			200
+#define MMSS_SPDM_AXI_CLK				201
+#define MMSS_SPDM_MDP_CLK				202
+#define MMSS_SPDM_JPEG0_CLK				203
+#define MMSS_SPDM_RM_AXI_CLK				204
+#define MMSS_SPDM_RM_MAXI_CLK				205
+
+#define MMAGICAHB_BCR					0
+#define MMAGIC_CFG_BCR					1
+#define MISC_BCR					2
+#define BTO_BCR						3
+#define MMAGICAXI_BCR					4
+#define MMAGICMAXI_BCR					5
+#define DSA_BCR						6
+#define MMAGIC_CAMSS_BCR				7
+#define THROTTLE_CAMSS_BCR				8
+#define SMMU_VFE_BCR					9
+#define SMMU_CPP_BCR					10
+#define SMMU_JPEG_BCR					11
+#define MMAGIC_MDSS_BCR					12
+#define THROTTLE_MDSS_BCR				13
+#define SMMU_ROT_BCR					14
+#define SMMU_MDP_BCR					15
+#define MMAGIC_VIDEO_BCR				16
+#define THROTTLE_VIDEO_BCR				17
+#define SMMU_VIDEO_BCR					18
+#define MMAGIC_BIMC_BCR					19
+#define GPU_GX_BCR					20
+#define GPU_BCR						21
+#define GPU_AON_BCR					22
+#define VMEM_BCR					23
+#define MMSS_RBCPR_BCR					24
+#define VIDEO_BCR					25
+#define MDSS_BCR					26
+#define CAMSS_TOP_BCR					27
+#define CAMSS_AHB_BCR					28
+#define CAMSS_MICRO_BCR					29
+#define CAMSS_CCI_BCR					30
+#define CAMSS_PHY0_BCR					31
+#define CAMSS_PHY1_BCR					32
+#define CAMSS_PHY2_BCR					33
+#define CAMSS_CSIPHY0_3P_BCR				34
+#define CAMSS_CSIPHY1_3P_BCR				35
+#define CAMSS_CSIPHY2_3P_BCR				36
+#define CAMSS_JPEG_BCR					37
+#define CAMSS_VFE_BCR					38
+#define CAMSS_VFE0_BCR					39
+#define CAMSS_VFE1_BCR					40
+#define CAMSS_CSI_VFE0_BCR				41
+#define CAMSS_CSI_VFE1_BCR				42
+#define CAMSS_CPP_TOP_BCR				43
+#define CAMSS_CPP_BCR					44
+#define CAMSS_CSI0_BCR					45
+#define CAMSS_CSI0RDI_BCR				46
+#define CAMSS_CSI0PIX_BCR				47
+#define CAMSS_CSI1_BCR					48
+#define CAMSS_CSI1RDI_BCR				49
+#define CAMSS_CSI1PIX_BCR				50
+#define CAMSS_CSI2_BCR					51
+#define CAMSS_CSI2RDI_BCR				52
+#define CAMSS_CSI2PIX_BCR				53
+#define CAMSS_CSI3_BCR					54
+#define CAMSS_CSI3RDI_BCR				55
+#define CAMSS_CSI3PIX_BCR				56
+#define CAMSS_ISPIF_BCR					57
+#define FD_BCR						58
+#define MMSS_SPDM_RM_BCR				59
+
+#endif
diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h
new file mode 100644
index 000000000000..ebc7a7b43f52
--- /dev/null
+++ b/include/dt-bindings/clock/rk3036-cru.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_ROCKCHIP_RK3036_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
+
+/* core clocks */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_GPLL		3
+#define ARMCLK			4
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU		64
+#define SCLK_SPI		65
+#define SCLK_SDMMC		68
+#define SCLK_SDIO		69
+#define SCLK_EMMC		71
+#define SCLK_NANDC		76
+#define SCLK_UART0		77
+#define SCLK_UART1		78
+#define SCLK_UART2		79
+#define SCLK_I2S		82
+#define SCLK_SPDIF		83
+#define SCLK_TIMER0		85
+#define SCLK_TIMER1		86
+#define SCLK_TIMER2		87
+#define SCLK_TIMER3		88
+#define SCLK_OTGPHY0		93
+#define SCLK_LCDC		100
+#define SCLK_HDMI		109
+#define SCLK_HEVC		111
+#define SCLK_I2S_OUT		113
+#define SCLK_SDMMC_DRV		114
+#define SCLK_SDIO_DRV		115
+#define SCLK_EMMC_DRV		117
+#define SCLK_SDMMC_SAMPLE	118
+#define SCLK_SDIO_SAMPLE	119
+#define SCLK_EMMC_SAMPLE	121
+#define SCLK_PVTM_CORE		123
+#define SCLK_PVTM_GPU		124
+#define SCLK_PVTM_VIDEO		125
+#define SCLK_MAC		151
+#define SCLK_MACREF		152
+#define SCLK_SFC		160
+
+/* aclk gates */
+#define ACLK_DMAC2		194
+#define ACLK_LCDC		197
+#define ACLK_VIO		203
+#define ACLK_VCODEC		208
+#define ACLK_CPU		209
+#define ACLK_PERI		210
+
+/* pclk gates */
+#define PCLK_GPIO0		320
+#define PCLK_GPIO1		321
+#define PCLK_GPIO2		322
+#define PCLK_GRF		329
+#define PCLK_I2C0		332
+#define PCLK_I2C1		333
+#define PCLK_I2C2		334
+#define PCLK_SPI		338
+#define PCLK_UART0		341
+#define PCLK_UART1		342
+#define PCLK_UART2		343
+#define PCLK_PWM		350
+#define PCLK_TIMER		353
+#define PCLK_HDMI		360
+#define PCLK_CPU		362
+#define PCLK_PERI		363
+#define PCLK_DDRUPCTL		364
+#define PCLK_WDT		368
+#define PCLK_ACODEC		369
+
+/* hclk gates */
+#define HCLK_OTG0		449
+#define HCLK_OTG1		450
+#define HCLK_NANDC		453
+#define HCLK_SDMMC		456
+#define HCLK_SDIO		457
+#define HCLK_EMMC		459
+#define HCLK_I2S		462
+#define HCLK_LCDC		465
+#define HCLK_ROM		467
+#define HCLK_VIO_BUS		472
+#define HCLK_VCODEC		476
+#define HCLK_CPU		477
+#define HCLK_PERI		478
+
+#define CLK_NR_CLKS		(HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0		0
+#define SRST_CORE1		1
+#define SRST_CORE0_DBG		4
+#define SRST_CORE1_DBG		5
+#define SRST_CORE0_POR		8
+#define SRST_CORE1_POR		9
+#define SRST_L2C		12
+#define SRST_TOPDBG		13
+#define SRST_STRC_SYS_A		14
+#define SRST_PD_CORE_NIU	15
+
+#define SRST_TIMER2		16
+#define SRST_CPUSYS_H		17
+#define SRST_AHB2APB_H		19
+#define SRST_TIMER3		20
+#define SRST_INTMEM		21
+#define SRST_ROM		22
+#define SRST_PERI_NIU		23
+#define SRST_I2S		24
+#define SRST_DDR_PLL		25
+#define SRST_GPU_DLL		26
+#define SRST_TIMER0		27
+#define SRST_TIMER1		28
+#define SRST_CORE_DLL		29
+#define SRST_EFUSE_P		30
+#define SRST_ACODEC_P		31
+
+#define SRST_GPIO0		32
+#define SRST_GPIO1		33
+#define SRST_GPIO2		34
+#define SRST_UART0		39
+#define SRST_UART1		40
+#define SRST_UART2		41
+#define SRST_I2C0		43
+#define SRST_I2C1		44
+#define SRST_I2C2		45
+#define SRST_SFC		47
+
+#define SRST_PWM0		48
+#define SRST_DAP		51
+#define SRST_DAP_SYS		52
+#define SRST_GRF		55
+#define SRST_PERIPHSYS_A	57
+#define SRST_PERIPHSYS_H	58
+#define SRST_PERIPHSYS_P	59
+#define SRST_CPU_PERI		61
+#define SRST_EMEM_PERI		62
+#define SRST_USB_PERI		63
+
+#define SRST_DMA2		64
+#define SRST_MAC		66
+#define SRST_NANDC		68
+#define SRST_USBOTG0		69
+#define SRST_OTGC0		71
+#define SRST_USBOTG1		72
+#define SRST_OTGC1		74
+#define SRST_DDRMSCH		79
+
+#define SRST_MMC0		81
+#define SRST_SDIO		82
+#define SRST_EMMC		83
+#define SRST_SPI0		84
+#define SRST_WDT		86
+#define SRST_DDRPHY		88
+#define SRST_DDRPHY_P		89
+#define SRST_DDRCTRL		90
+#define SRST_DDRCTRL_P		91
+
+#define SRST_HDMI_P		96
+#define SRST_VIO_BUS_H		99
+#define SRST_UTMI0		103
+#define SRST_UTMI1		104
+#define SRST_USBPOR		105
+
+#define SRST_VCODEC_A		112
+#define SRST_VCODEC_H		113
+#define SRST_VIO1_A		114
+#define SRST_HEVC		115
+#define SRST_VCODEC_NIU_A	116
+#define SRST_LCDC1_A		117
+#define SRST_LCDC1_H		118
+#define SRST_LCDC1_D		119
+#define SRST_GPU		120
+#define SRST_GPU_NIU_A		122
+
+#define SRST_DBG_P		131
+
+#endif
diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h
new file mode 100644
index 000000000000..a78dd891e24a
--- /dev/null
+++ b/include/dt-bindings/clock/rk3228-cru.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Jeffy Chen <jeffy.chen@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_ROCKCHIP_RK3228_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3228_H
+
+/* core clocks */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_CPLL		3
+#define PLL_GPLL		4
+#define ARMCLK			5
+
+/* sclk gates (special clocks) */
+#define SCLK_SPI0		65
+#define SCLK_NANDC		67
+#define SCLK_SDMMC		68
+#define SCLK_SDIO		69
+#define SCLK_EMMC		71
+#define SCLK_UART0		77
+#define SCLK_UART1		78
+#define SCLK_UART2		79
+#define SCLK_I2S0		80
+#define SCLK_I2S1		81
+#define SCLK_I2S2		82
+#define SCLK_SPDIF		83
+#define SCLK_TIMER0		85
+#define SCLK_TIMER1		86
+#define SCLK_TIMER2		87
+#define SCLK_TIMER3		88
+#define SCLK_TIMER4		89
+#define SCLK_TIMER5		90
+#define SCLK_I2S_OUT		113
+#define SCLK_SDMMC_DRV		114
+#define SCLK_SDIO_DRV		115
+#define SCLK_EMMC_DRV		117
+#define SCLK_SDMMC_SAMPLE	118
+#define SCLK_SDIO_SAMPLE	119
+#define SCLK_EMMC_SAMPLE	121
+
+/* aclk gates */
+#define ACLK_DMAC		194
+#define ACLK_PERI		210
+
+/* pclk gates */
+#define PCLK_GPIO0		320
+#define PCLK_GPIO1		321
+#define PCLK_GPIO2		322
+#define PCLK_GPIO3		323
+#define PCLK_GRF		329
+#define PCLK_I2C0		332
+#define PCLK_I2C1		333
+#define PCLK_I2C2		334
+#define PCLK_I2C3		335
+#define PCLK_SPI0		338
+#define PCLK_UART0		341
+#define PCLK_UART1		342
+#define PCLK_UART2		343
+#define PCLK_PWM		350
+#define PCLK_TIMER		353
+#define PCLK_PERI		363
+
+/* hclk gates */
+#define HCLK_NANDC		453
+#define HCLK_SDMMC		456
+#define HCLK_SDIO		457
+#define HCLK_EMMC		459
+#define HCLK_PERI		478
+
+#define CLK_NR_CLKS		(HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0_PO		0
+#define SRST_CORE1_PO		1
+#define SRST_CORE2_PO		2
+#define SRST_CORE3_PO		3
+#define SRST_CORE0		4
+#define SRST_CORE1		5
+#define SRST_CORE2		6
+#define SRST_CORE3		7
+#define SRST_CORE0_DBG		8
+#define SRST_CORE1_DBG		9
+#define SRST_CORE2_DBG		10
+#define SRST_CORE3_DBG		11
+#define SRST_TOPDBG		12
+#define SRST_ACLK_CORE		13
+#define SRST_NOC		14
+#define SRST_L2C		15
+
+#define SRST_CPUSYS_H		18
+#define SRST_BUSSYS_H		19
+#define SRST_SPDIF		20
+#define SRST_INTMEM		21
+#define SRST_ROM		22
+#define SRST_OTG_ADP		23
+#define SRST_I2S0		24
+#define SRST_I2S1		25
+#define SRST_I2S2		26
+#define SRST_ACODEC_P		27
+#define SRST_DFIMON		28
+#define SRST_MSCH		29
+#define SRST_EFUSE1024		30
+#define SRST_EFUSE256		31
+
+#define SRST_GPIO0		32
+#define SRST_GPIO1		33
+#define SRST_GPIO2		34
+#define SRST_GPIO3		35
+#define SRST_PERIPH_NOC_A	36
+#define SRST_PERIPH_NOC_BUS_H	37
+#define SRST_PERIPH_NOC_P	38
+#define SRST_UART0		39
+#define SRST_UART1		40
+#define SRST_UART2		41
+#define SRST_PHYNOC		42
+#define SRST_I2C0		43
+#define SRST_I2C1		44
+#define SRST_I2C2		45
+#define SRST_I2C3		46
+
+#define SRST_PWM		48
+#define SRST_A53_GIC		49
+#define SRST_DAP		51
+#define SRST_DAP_NOC		52
+#define SRST_CRYPTO		53
+#define SRST_SGRF		54
+#define SRST_GRF		55
+#define SRST_GMAC		56
+#define SRST_PERIPH_NOC_H	58
+#define SRST_MACPHY		63
+
+#define SRST_DMA		64
+#define SRST_NANDC		68
+#define SRST_USBOTG		69
+#define SRST_OTGC		70
+#define SRST_USBHOST0		71
+#define SRST_HOST_CTRL0		72
+#define SRST_USBHOST1		73
+#define SRST_HOST_CTRL1		74
+#define SRST_USBHOST2		75
+#define SRST_HOST_CTRL2		76
+#define SRST_USBPOR0		77
+#define SRST_USBPOR1		78
+#define SRST_DDRMSCH		79
+
+#define SRST_SMART_CARD		80
+#define SRST_SDMMC		81
+#define SRST_SDIO		82
+#define SRST_EMMC		83
+#define SRST_SPI		84
+#define SRST_TSP_H		85
+#define SRST_TSP		86
+#define SRST_TSADC		87
+#define SRST_DDRPHY		88
+#define SRST_DDRPHY_P		89
+#define SRST_DDRCTRL		90
+#define SRST_DDRCTRL_P		91
+#define SRST_HOST0_ECHI		92
+#define SRST_HOST1_ECHI		93
+#define SRST_HOST2_ECHI		94
+#define SRST_VOP_NOC_A		95
+
+#define SRST_HDMI_P		96
+#define SRST_VIO_ARBI_H		97
+#define SRST_IEP_NOC_A		98
+#define SRST_VIO_NOC_H		99
+#define SRST_VOP_A		100
+#define SRST_VOP_H		101
+#define SRST_VOP_D		102
+#define SRST_UTMI0		103
+#define SRST_UTMI1		104
+#define SRST_UTMI2		105
+#define SRST_UTMI3		106
+#define SRST_RGA		107
+#define SRST_RGA_NOC_A		108
+#define SRST_RGA_A		109
+#define SRST_RGA_H		110
+#define SRST_HDCP_A		111
+
+#define SRST_VPU_A		112
+#define SRST_VPU_H		113
+#define SRST_VPU_NOC_A		116
+#define SRST_VPU_NOC_H		117
+#define SRST_RKVDEC_A		118
+#define SRST_RKVDEC_NOC_A	119
+#define SRST_RKVDEC_H		120
+#define SRST_RKVDEC_NOC_H	121
+#define SRST_RKVDEC_CORE	122
+#define SRST_RKVDEC_CABAC	123
+#define SRST_IEP_A		124
+#define SRST_IEP_H		125
+#define SRST_GPU_A		126
+#define SRST_GPU_NOC_A		127
+
+#define SRST_CORE_DBG		128
+#define SRST_DBG_P		129
+#define SRST_TIMER0		130
+#define SRST_TIMER1		131
+#define SRST_TIMER2		132
+#define SRST_TIMER3		133
+#define SRST_TIMER4		134
+#define SRST_TIMER5		135
+#define SRST_VIO_H2P		136
+#define SRST_HDMIPHY		139
+#define SRST_VDAC		140
+#define SRST_TIMER_6CH_P	141
+
+#endif
diff --git a/include/dt-bindings/clock/rk3288-cru.h b/include/dt-bindings/clock/rk3288-cru.h
index c719aacef14f..9a586e2d9c91 100644
--- a/include/dt-bindings/clock/rk3288-cru.h
+++ b/include/dt-bindings/clock/rk3288-cru.h
@@ -86,6 +86,8 @@
 #define SCLK_USBPHY480M_SRC	122
 #define SCLK_PVTM_CORE		123
 #define SCLK_PVTM_GPU		124
+#define SCLK_CRYPTO		125
+#define SCLK_MIPIDSI_24M	126
 
 #define SCLK_MAC		151
 #define SCLK_MACREF_OUT		152
@@ -164,6 +166,8 @@
 #define PCLK_DDRUPCTL1		366
 #define PCLK_PUBL1		367
 #define PCLK_WDT		368
+#define PCLK_EFUSE256		369
+#define PCLK_EFUSE1024		370
 
 /* hclk gates */
 #define HCLK_GPS		448
diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h
new file mode 100644
index 000000000000..6f45aea49e4f
--- /dev/null
+++ b/include/dt-bindings/clock/tegra210-car.h
@@ -0,0 +1,401 @@
+/*
+ * This header provides constants for binding nvidia,tegra210-car.
+ *
+ * The first 224 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 224 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 224 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA210_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA210_CAR_H
+
+/* 0 */
+/* 1 */
+/* 2 */
+#define TEGRA210_CLK_ISPB 3
+#define TEGRA210_CLK_RTC 4
+#define TEGRA210_CLK_TIMER 5
+#define TEGRA210_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+#define TEGRA210_CLK_GPIO 8
+#define TEGRA210_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA210_CLK_I2S1 11
+#define TEGRA210_CLK_I2C1 12
+/* 13 */
+#define TEGRA210_CLK_SDMMC1 14
+#define TEGRA210_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA210_CLK_PWM 17
+#define TEGRA210_CLK_I2S2 18
+/* 19 */
+/* 20 (register bit affects vi and vi_sensor) */
+/* 21 */
+#define TEGRA210_CLK_USBD 22
+#define TEGRA210_CLK_ISP 23
+/* 24 */
+/* 25 */
+#define TEGRA210_CLK_DISP2 26
+#define TEGRA210_CLK_DISP1 27
+#define TEGRA210_CLK_HOST1X 28
+/* 29 */
+#define TEGRA210_CLK_I2S0 30
+/* 31 */
+
+#define TEGRA210_CLK_MC 32
+#define TEGRA210_CLK_AHBDMA 33
+#define TEGRA210_CLK_APBDMA 34
+/* 35 */
+/* 36 */
+/* 37 */
+#define TEGRA210_CLK_PMC 38
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA210_CLK_KFUSE 40
+#define TEGRA210_CLK_SBC1 41
+/* 42 */
+/* 43 */
+#define TEGRA210_CLK_SBC2 44
+/* 45 */
+#define TEGRA210_CLK_SBC3 46
+#define TEGRA210_CLK_I2C5 47
+#define TEGRA210_CLK_DSIA 48
+/* 49 */
+/* 50 */
+/* 51 */
+#define TEGRA210_CLK_CSI 52
+/* 53 */
+#define TEGRA210_CLK_I2C2 54
+#define TEGRA210_CLK_UARTC 55
+#define TEGRA210_CLK_MIPI_CAL 56
+#define TEGRA210_CLK_EMC 57
+#define TEGRA210_CLK_USB2 58
+/* 59 */
+/* 60 */
+/* 61 */
+/* 62 */
+#define TEGRA210_CLK_BSEV 63
+
+/* 64 */
+#define TEGRA210_CLK_UARTD 65
+/* 66 */
+#define TEGRA210_CLK_I2C3 67
+#define TEGRA210_CLK_SBC4 68
+#define TEGRA210_CLK_SDMMC3 69
+#define TEGRA210_CLK_PCIE 70
+#define TEGRA210_CLK_OWR 71
+#define TEGRA210_CLK_AFI 72
+#define TEGRA210_CLK_CSITE 73
+/* 74 */
+/* 75 */
+/* 76 */
+/* 77 */
+#define TEGRA210_CLK_SOC_THERM 78
+#define TEGRA210_CLK_DTV 79
+/* 80 */
+#define TEGRA210_CLK_I2CSLOW 81
+#define TEGRA210_CLK_DSIB 82
+#define TEGRA210_CLK_TSEC 83
+/* 84 */
+/* 85 */
+/* 86 */
+/* 87 */
+/* 88 */
+#define TEGRA210_CLK_XUSB_HOST 89
+/* 90 */
+/* 91 */
+#define TEGRA210_CLK_CSUS 92
+/* 93 */
+/* 94 */
+/* 95 (bit affects xusb_dev and xusb_dev_src) */
+
+/* 96 */
+/* 97 */
+/* 98 */
+#define TEGRA210_CLK_MSELECT 99
+#define TEGRA210_CLK_TSENSOR 100
+#define TEGRA210_CLK_I2S3 101
+#define TEGRA210_CLK_I2S4 102
+#define TEGRA210_CLK_I2C4 103
+/* 104 */
+/* 105 */
+#define TEGRA210_CLK_D_AUDIO 106
+/* 107 ( affects abp -> ape) */
+/* 108 */
+/* 109 */
+/* 110 */
+#define TEGRA210_CLK_HDA2CODEC_2X 111
+/* 112 */
+/* 113 */
+/* 114 */
+/* 115 */
+/* 116 */
+/* 117 */
+#define TEGRA210_CLK_SPDIF_2X 118
+#define TEGRA210_CLK_ACTMON 119
+#define TEGRA210_CLK_EXTERN1 120
+#define TEGRA210_CLK_EXTERN2 121
+#define TEGRA210_CLK_EXTERN3 122
+#define TEGRA210_CLK_SATA_OOB 123
+#define TEGRA210_CLK_SATA 124
+#define TEGRA210_CLK_HDA 125
+/* 126 */
+/* 127 */
+
+#define TEGRA210_CLK_HDA2HDMI 128
+/* 129 */
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* (bit affects xusb_falcon_src, xusb_fs_src, xusb_host_src and xusb_ss_src) */
+#define TEGRA210_CLK_XUSB_GATE 143
+#define TEGRA210_CLK_CILAB 144
+#define TEGRA210_CLK_CILCD 145
+#define TEGRA210_CLK_CILE 146
+#define TEGRA210_CLK_DSIALP 147
+#define TEGRA210_CLK_DSIBLP 148
+#define TEGRA210_CLK_ENTROPY 149
+/* 150 */
+/* 151 */
+/* 152 */
+/* 153 */
+/* 154 */
+/* 155 (bit affects dfll_ref and dfll_soc) */
+#define TEGRA210_CLK_XUSB_SS 156
+/* 157 */
+/* 158 */
+/* 159 */
+
+/* 160 */
+#define TEGRA210_CLK_DMIC1 161
+#define TEGRA210_CLK_DMIC2 162
+/* 163 */
+/* 164 */
+/* 165 */
+#define TEGRA210_CLK_I2C6 166
+/* 167 */
+/* 168 */
+/* 169 */
+/* 170 */
+#define TEGRA210_CLK_VIM2_CLK 171
+/* 172 */
+#define TEGRA210_CLK_MIPIBIF 173
+/* 174 */
+/* 175 */
+/* 176 */
+#define TEGRA210_CLK_CLK72MHZ 177
+#define TEGRA210_CLK_VIC03 178
+/* 179 */
+/* 180 */
+#define TEGRA210_CLK_DPAUX 181
+#define TEGRA210_CLK_SOR0 182
+#define TEGRA210_CLK_SOR1 183
+#define TEGRA210_CLK_GPU 184
+#define TEGRA210_CLK_DBGAPB 185
+/* 186 */
+#define TEGRA210_CLK_PLL_P_OUT_ADSP 187
+/* 188 */
+#define TEGRA210_CLK_PLL_G_REF 189
+/* 190 */
+/* 191 */
+
+/* 192 */
+#define TEGRA210_CLK_SDMMC_LEGACY 193
+#define TEGRA210_CLK_NVDEC 194
+#define TEGRA210_CLK_NVJPG 195
+/* 196 */
+#define TEGRA210_CLK_DMIC3 197
+#define TEGRA210_CLK_APE 198
+/* 199 */
+/* 200 */
+/* 201 */
+#define TEGRA210_CLK_MAUD 202
+/* 203 */
+/* 204 */
+/* 205 */
+#define TEGRA210_CLK_TSECB 206
+#define TEGRA210_CLK_DPAUX1 207
+#define TEGRA210_CLK_VI_I2C 208
+#define TEGRA210_CLK_HSIC_TRK 209
+#define TEGRA210_CLK_USB2_TRK 210
+#define TEGRA210_CLK_QSPI 211
+#define TEGRA210_CLK_UARTAPE 212
+/* 213 */
+/* 214 */
+/* 215 */
+/* 216 */
+/* 217 */
+/* 218 */
+#define TEGRA210_CLK_NVENC 219
+/* 220 */
+/* 221 */
+#define TEGRA210_CLK_SOR_SAFE 222
+#define TEGRA210_CLK_PLL_P_OUT_CPU 223
+
+
+#define TEGRA210_CLK_UARTB 224
+#define TEGRA210_CLK_VFIR 225
+#define TEGRA210_CLK_SPDIF_IN 226
+#define TEGRA210_CLK_SPDIF_OUT 227
+#define TEGRA210_CLK_VI 228
+#define TEGRA210_CLK_VI_SENSOR 229
+#define TEGRA210_CLK_FUSE 230
+#define TEGRA210_CLK_FUSE_BURN 231
+#define TEGRA210_CLK_CLK_32K 232
+#define TEGRA210_CLK_CLK_M 233
+#define TEGRA210_CLK_CLK_M_DIV2 234
+#define TEGRA210_CLK_CLK_M_DIV4 235
+#define TEGRA210_CLK_PLL_REF 236
+#define TEGRA210_CLK_PLL_C 237
+#define TEGRA210_CLK_PLL_C_OUT1 238
+#define TEGRA210_CLK_PLL_C2 239
+#define TEGRA210_CLK_PLL_C3 240
+#define TEGRA210_CLK_PLL_M 241
+#define TEGRA210_CLK_PLL_M_OUT1 242
+#define TEGRA210_CLK_PLL_P 243
+#define TEGRA210_CLK_PLL_P_OUT1 244
+#define TEGRA210_CLK_PLL_P_OUT2 245
+#define TEGRA210_CLK_PLL_P_OUT3 246
+#define TEGRA210_CLK_PLL_P_OUT4 247
+#define TEGRA210_CLK_PLL_A 248
+#define TEGRA210_CLK_PLL_A_OUT0 249
+#define TEGRA210_CLK_PLL_D 250
+#define TEGRA210_CLK_PLL_D_OUT0 251
+#define TEGRA210_CLK_PLL_D2 252
+#define TEGRA210_CLK_PLL_D2_OUT0 253
+#define TEGRA210_CLK_PLL_U 254
+#define TEGRA210_CLK_PLL_U_480M 255
+
+#define TEGRA210_CLK_PLL_U_60M 256
+#define TEGRA210_CLK_PLL_U_48M 257
+/* 258 */
+#define TEGRA210_CLK_PLL_X 259
+#define TEGRA210_CLK_PLL_X_OUT0 260
+#define TEGRA210_CLK_PLL_RE_VCO 261
+#define TEGRA210_CLK_PLL_RE_OUT 262
+#define TEGRA210_CLK_PLL_E 263
+#define TEGRA210_CLK_SPDIF_IN_SYNC 264
+#define TEGRA210_CLK_I2S0_SYNC 265
+#define TEGRA210_CLK_I2S1_SYNC 266
+#define TEGRA210_CLK_I2S2_SYNC 267
+#define TEGRA210_CLK_I2S3_SYNC 268
+#define TEGRA210_CLK_I2S4_SYNC 269
+#define TEGRA210_CLK_VIMCLK_SYNC 270
+#define TEGRA210_CLK_AUDIO0 271
+#define TEGRA210_CLK_AUDIO1 272
+#define TEGRA210_CLK_AUDIO2 273
+#define TEGRA210_CLK_AUDIO3 274
+#define TEGRA210_CLK_AUDIO4 275
+#define TEGRA210_CLK_SPDIF 276
+#define TEGRA210_CLK_CLK_OUT_1 277
+#define TEGRA210_CLK_CLK_OUT_2 278
+#define TEGRA210_CLK_CLK_OUT_3 279
+#define TEGRA210_CLK_BLINK 280
+/* 281 */
+/* 282 */
+/* 283 */
+#define TEGRA210_CLK_XUSB_HOST_SRC 284
+#define TEGRA210_CLK_XUSB_FALCON_SRC 285
+#define TEGRA210_CLK_XUSB_FS_SRC 286
+#define TEGRA210_CLK_XUSB_SS_SRC 287
+
+#define TEGRA210_CLK_XUSB_DEV_SRC 288
+#define TEGRA210_CLK_XUSB_DEV 289
+#define TEGRA210_CLK_XUSB_HS_SRC 290
+#define TEGRA210_CLK_SCLK 291
+#define TEGRA210_CLK_HCLK 292
+#define TEGRA210_CLK_PCLK 293
+#define TEGRA210_CLK_CCLK_G 294
+#define TEGRA210_CLK_CCLK_LP 295
+#define TEGRA210_CLK_DFLL_REF 296
+#define TEGRA210_CLK_DFLL_SOC 297
+#define TEGRA210_CLK_VI_SENSOR2 298
+#define TEGRA210_CLK_PLL_P_OUT5 299
+#define TEGRA210_CLK_CML0 300
+#define TEGRA210_CLK_CML1 301
+#define TEGRA210_CLK_PLL_C4 302
+#define TEGRA210_CLK_PLL_DP 303
+#define TEGRA210_CLK_PLL_E_MUX 304
+#define TEGRA210_CLK_PLL_MB 305
+#define TEGRA210_CLK_PLL_A1 306
+#define TEGRA210_CLK_PLL_D_DSI_OUT 307
+#define TEGRA210_CLK_PLL_C4_OUT0 308
+#define TEGRA210_CLK_PLL_C4_OUT1 309
+#define TEGRA210_CLK_PLL_C4_OUT2 310
+#define TEGRA210_CLK_PLL_C4_OUT3 311
+#define TEGRA210_CLK_PLL_U_OUT 312
+#define TEGRA210_CLK_PLL_U_OUT1 313
+#define TEGRA210_CLK_PLL_U_OUT2 314
+#define TEGRA210_CLK_USB2_HSIC_TRK 315
+#define TEGRA210_CLK_PLL_P_OUT_HSIO 316
+#define TEGRA210_CLK_PLL_P_OUT_XUSB 317
+#define TEGRA210_CLK_XUSB_SSP_SRC 318
+/* 319 */
+/* 320 */
+/* 321 */
+/* 322 */
+/* 323 */
+/* 324 */
+/* 325 */
+/* 326 */
+/* 327 */
+/* 328 */
+/* 329 */
+/* 330 */
+/* 331 */
+/* 332 */
+/* 333 */
+/* 334 */
+/* 335 */
+/* 336 */
+/* 337 */
+/* 338 */
+/* 339 */
+/* 340 */
+/* 341 */
+/* 342 */
+/* 343 */
+/* 344 */
+/* 345 */
+/* 346 */
+/* 347 */
+/* 348 */
+/* 349 */
+
+#define TEGRA210_CLK_AUDIO0_MUX 350
+#define TEGRA210_CLK_AUDIO1_MUX 351
+#define TEGRA210_CLK_AUDIO2_MUX 352
+#define TEGRA210_CLK_AUDIO3_MUX 353
+#define TEGRA210_CLK_AUDIO4_MUX 354
+#define TEGRA210_CLK_SPDIF_MUX 355
+#define TEGRA210_CLK_CLK_OUT_1_MUX 356
+#define TEGRA210_CLK_CLK_OUT_2_MUX 357
+#define TEGRA210_CLK_CLK_OUT_3_MUX 358
+#define TEGRA210_CLK_DSIA_MUX 359
+#define TEGRA210_CLK_DSIB_MUX 360
+#define TEGRA210_CLK_SOR0_LVDS 361
+#define TEGRA210_CLK_XUSB_SS_DIV2 362
+
+#define TEGRA210_CLK_PLL_M_UD 363
+#define TEGRA210_CLK_PLL_C_UD 364
+#define TEGRA210_CLK_SCLK_MUX 365
+
+#define TEGRA210_CLK_CLK_MAX 366
+
+#endif	/* _DT_BINDINGS_CLOCK_TEGRA210_CAR_H */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c56988ac63f7..1143e38555a4 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -31,6 +31,7 @@
 #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 #define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after notifications */
+#define CLK_SET_RATE_UNGATE	BIT(10) /* clock needs to run to set rate */
 
 struct clk;
 struct clk_hw;
@@ -44,7 +45,7 @@ struct dentry;
  * @rate:		Requested clock rate. This field will be adjusted by
  *			clock drivers according to hardware capabilities.
  * @min_rate:		Minimum rate imposed by clk users.
- * @max_rate:		Maximum rate a imposed by clk users.
+ * @max_rate:		Maximum rate imposed by clk users.
  * @best_parent_rate:	The best parent rate a parent can provide to fulfill the
  *			requested constraints.
  * @best_parent_hw:	The most appropriate parent clock that fulfills the
@@ -715,8 +716,7 @@ static inline int of_clk_add_provider(struct device_node *np,
 {
 	return 0;
 }
-#define of_clk_del_provider(np) \
-	{ while (0); }
+static inline void of_clk_del_provider(struct device_node *np) {}
 static inline struct clk *of_clk_src_simple_get(
 	struct of_phandle_args *clkspec, void *data)
 {
@@ -741,8 +741,7 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 {
 	return NULL;
 }
-#define of_clk_init(matches) \
-	{ while (0); }
+static inline void of_clk_init(const struct of_device_id *matches) {}
 #endif /* CONFIG_OF */
 
 /*
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 223be696df27..75205df29b9c 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -286,6 +286,7 @@ struct ti_clk_features {
 #define TI_CLK_DPLL_HAS_FREQSEL			BIT(0)
 #define TI_CLK_DPLL4_DENY_REPROGRAM		BIT(1)
 #define TI_CLK_DISABLE_CLKDM_CONTROL		BIT(2)
+#define TI_CLK_ERRATA_I810			BIT(3)
 
 void ti_clk_setup_features(struct ti_clk_features *features);
 const struct ti_clk_features *ti_clk_get_features(void);