]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'clk-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/clk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Jul 2016 18:20:02 +0000 (11:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Jul 2016 18:20:02 +0000 (11:20 -0700)
Pull clk updates from Michael Turquette:
 "The bulk of the changes are updates and fixes to existing clk provider
  drivers, along with a pretty standard number of new drivers.  The core
  recieved a small number of updates as well.

  Core changes of note:
   - removed CLK_IS_ROOT flag

  New clk provider drivers:
   - Renesas r8a7796 clock pulse generator / module standby and
     software reset
   - Allwinner sun8i H3 clock controller unit
   - AmLogic meson8b clock controller (rewritten)
   - AmLogic gxbb clock controller
   - support for some new ICs was added by simple changes to static
     data tables for chips sharing the same family

  Driver updates of note:
   - the Allwinner sunxi clock driver infrastucture was rewritten to
     comform to the state of the art at drivers/clk/sunxi-ng.  The old
     implementation is still supported for backwards compatibility with
     the DT ABI"

* tag 'clk-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (162 commits)
  clk: Makefile: re-sort and clean up
  Revert "clk: gxbb: expose CLKID_MMC_PCLK"
  clk: samsung: Allow modular build of the Audio Subsystem CLKCON driver
  clk: samsung: make clk-s5pv210-audss explicitly non-modular
  clk: exynos5433: remove CLK_IGNORE_UNUSED flag from SPI clocks
  clk: oxnas: Add hardware dependencies
  clk: imx7d: do not set parent of ethernet time/ref clocks
  ARM: dt: sun8i: switch the H3 to the new CCU driver
  clk: sunxi-ng: h3: Fix Kconfig symbol typo
  clk: sunxi-ng: h3: Fix audio clock divider offset
  clk: sunxi-ng: Add H3 clocks
  clk: sunxi-ng: Add N-K-M-P factor clock
  clk: sunxi-ng: Add N-K-M Factor clock
  clk: sunxi-ng: Add N-M-factor clock support
  clk: sunxi-ng: Add N-K-factor clock support
  clk: sunxi-ng: Add M-P factor clock support
  clk: sunxi-ng: Add divider
  clk: sunxi-ng: Add phase clock support
  clk: sunxi-ng: Add mux clock support
  clk: sunxi-ng: Add gate clock support
  ...

148 files changed:
Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/fixed-factor-clock.txt
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
Documentation/devicetree/bindings/clock/sunxi-ccu.txt [new file with mode: 0644]
arch/arm/boot/dts/sun8i-h3.dtsi
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/at91/clk-generated.c
drivers/clk/bcm/clk-iproc-armpll.c
drivers/clk/bcm/clk-iproc-asiu.c
drivers/clk/bcm/clk-iproc-pll.c
drivers/clk/clk-conf.c
drivers/clk/clk-fixed-factor.c
drivers/clk/clk-fixed-rate.c
drivers/clk/clk-highbank.c
drivers/clk/clk-multiplier.c
drivers/clk/clk-nomadik.c
drivers/clk/clk-oxnas.c
drivers/clk/clk-s2mps11.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-u300.c
drivers/clk/clk-vt8500.c
drivers/clk/clk.c
drivers/clk/hisilicon/clk-hi3519.c
drivers/clk/hisilicon/clk-hi6220.c
drivers/clk/hisilicon/clk.c
drivers/clk/hisilicon/clk.h
drivers/clk/hisilicon/clkdivider-hi6220.c
drivers/clk/hisilicon/reset.c
drivers/clk/hisilicon/reset.h
drivers/clk/imx/clk-imx6q.c
drivers/clk/imx/clk-imx6sl.c
drivers/clk/imx/clk-imx6sx.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/imx/clk-imx7d.c
drivers/clk/imx/clk-pllv3.c
drivers/clk/imx/clk-vf610.c
drivers/clk/imx/clk.h
drivers/clk/meson/Kconfig [new file with mode: 0644]
drivers/clk/meson/Makefile
drivers/clk/meson/clk-cpu.c
drivers/clk/meson/clk-mpll.c [new file with mode: 0644]
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clkc.c [deleted file]
drivers/clk/meson/clkc.h
drivers/clk/meson/gxbb.c [new file with mode: 0644]
drivers/clk/meson/gxbb.h [new file with mode: 0644]
drivers/clk/meson/meson8b-clkc.c
drivers/clk/nxp/clk-lpc32xx.c
drivers/clk/qcom/gcc-msm8660.c
drivers/clk/qcom/gcc-msm8996.c
drivers/clk/renesas/Kconfig
drivers/clk/renesas/Makefile
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/rcar-gen3-cpg.c [new file with mode: 0644]
drivers/clk/renesas/rcar-gen3-cpg.h [new file with mode: 0644]
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/rockchip/clk-rk3228.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/samsung/Kconfig
drivers/clk/samsung/Makefile
drivers/clk/samsung/clk-cpu.c
drivers/clk/samsung/clk-cpu.h
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos4415.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5260.c
drivers/clk/samsung/clk-exynos5410.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/samsung/clk-exynos5440.c
drivers/clk/samsung/clk-exynos7.c
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-s3c2410-dclk.c
drivers/clk/samsung/clk-s3c2410.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clk/samsung/clk-s5pv210-audss.c
drivers/clk/samsung/clk-s5pv210.c
drivers/clk/samsung/clk.c
drivers/clk/samsung/clk.h
drivers/clk/st/clk-flexgen.c
drivers/clk/st/clkgen-fsyn.c
drivers/clk/st/clkgen-pll.c
drivers/clk/sunxi-ng/Kconfig [new file with mode: 0644]
drivers/clk/sunxi-ng/Makefile [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun8i-h3.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun8i-h3.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_common.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_common.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_div.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_div.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_frac.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_frac.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_gate.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_gate.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_mp.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_mp.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_mult.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_mux.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_mux.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nk.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nk.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nkm.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nkm.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nkmp.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nkmp.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nm.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_nm.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_phase.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_phase.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_reset.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu_reset.h [new file with mode: 0644]
drivers/clk/sunxi/clk-factors.c
drivers/clk/sunxi/clk-sun6i-apb0-gates.c
drivers/clk/sunxi/clk-sun6i-apb0.c
drivers/clk/sunxi/clk-sun6i-ar100.c
drivers/clk/sunxi/clk-sun8i-apb0.c
drivers/clk/sunxi/clk-sun9i-mmc.c
drivers/clk/tegra/clk-id.h
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.h
include/dt-bindings/clock/exynos5410.h
include/dt-bindings/clock/exynos5433.h
include/dt-bindings/clock/gxbb-clkc.h [new file with mode: 0644]
include/dt-bindings/clock/hi6220-clock.h
include/dt-bindings/clock/lpc32xx-clock.h
include/dt-bindings/clock/meson8b-clkc.h
include/dt-bindings/clock/r8a7796-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/rk3228-cru.h
include/dt-bindings/clock/sun8i-h3-ccu.h [new file with mode: 0644]
include/dt-bindings/clock/tegra210-car.h
include/dt-bindings/reset/sun8i-h3-ccu.h [new file with mode: 0644]
include/linux/clk-provider.h
include/linux/clk.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
new file mode 100644 (file)
index 0000000..ce06435
--- /dev/null
@@ -0,0 +1,36 @@
+* Amlogic GXBB Clock and Reset Unit
+
+The Amlogic GXBB clock controller generates and supplies clock to various
+controllers within the SoC.
+
+Required Properties:
+
+- compatible: should be "amlogic,gxbb-clkc"
+- reg: physical base address of the clock controller and length of memory
+       mapped region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/gxbb-clkc.h header and can be
+used in device tree sources.
+
+Example: Clock controller node:
+
+       clkc: clock-controller@c883c000 {
+               #clock-cells = <1>;
+               compatible = "amlogic,gxbb-clkc";
+               reg = <0x0 0xc883c000 0x0 0x3db>;
+       };
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+       uart_AO: serial@c81004c0 {
+               compatible = "amlogic,meson-uart";
+               reg = <0xc81004c0 0x14>;
+               interrupts = <0 90 1>;
+               clocks = <&clkc CLKID_CLK81>;
+               status = "disabled";
+       };
index 1bae8527eb9bc15cdb148daa861ee79272098094..189467a7188af15fe16978839643b02cd217fd77 100644 (file)
@@ -14,6 +14,10 @@ Required properties:
 Optional properties:
 - clock-output-names : From common clock binding.
 
+Some clocks that require special treatments are also handled by that
+driver, with the compatibles:
+  - allwinner,sun4i-a10-pll3-2x-clk
+
 Example:
        clock {
                compatible = "fixed-factor-clock";
index fefb8023020f1a543b61fb230c9de2985c3cfb03..394d725ac7e0baa3bf8ba8429409ba5d0c017d4c 100644 (file)
@@ -13,7 +13,8 @@ They provide the following functionalities:
 
 Required Properties:
   - compatible: Must be one of:
-      - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC
+      - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
+      - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
 
   - reg: Base address and length of the memory resource used by the CPG/MSSR
     block
@@ -21,8 +22,8 @@ Required Properties:
   - clocks: References to external parent clocks, one entry for each entry in
     clock-names
   - clock-names: List of external parent clock names. Valid names are:
-      - "extal" (r8a7795)
-      - "extalr" (r8a7795)
+      - "extal" (r8a7795, r8a7796)
+      - "extalr" (r8a7795, r8a7796)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
index 16ed18155160f58c9ce17dce42f50f1527261f72..da578ebdda2889fc1dad50c671bc274af7d38169 100644 (file)
@@ -17,6 +17,7 @@ Required Properties:
     - "renesas,r8a7779-mstp-clocks" for R8A7779 (R-Car H1) MSTP gate clocks
     - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks
     - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2-W) MSTP gate clocks
+    - "renesas,r8a7792-mstp-clocks" for R8A7792 (R-Car V2H) MSTP gate clocks
     - "renesas,r8a7793-mstp-clocks" for R8A7793 (R-Car M2-N) MSTP gate clocks
     - "renesas,r8a7794-mstp-clocks" for R8A7794 (R-Car E2) MSTP gate clocks
     - "renesas,sh73a0-mstp-clocks" for SH73A0 (SH-MobileAG5) MSTP gate clocks
index 2a9a8edc8f3547b051a35b341abce912c41c427f..f8c05bb4116eae54b663c821476f2eeaa6bb9415 100644 (file)
@@ -10,6 +10,7 @@ Required Properties:
   - compatible: Must be one of
     - "renesas,r8a7790-cpg-clocks" for the r8a7790 CPG
     - "renesas,r8a7791-cpg-clocks" for the r8a7791 CPG
+    - "renesas,r8a7792-cpg-clocks" for the r8a7792 CPG
     - "renesas,r8a7793-cpg-clocks" for the r8a7793 CPG
     - "renesas,r8a7794-cpg-clocks" for the r8a7794 CPG
     and "renesas,rcar-gen2-cpg-clocks" as a fallback.
diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt
new file mode 100644 (file)
index 0000000..cb91507
--- /dev/null
@@ -0,0 +1,24 @@
+Allwinner Clock Control Unit Binding
+------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatible:
+               - "allwinner,sun8i-h3-ccu"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the oscillators feeding the CCU. Two are needed:
+  - "hosc": the high frequency oscillator (usually at 24MHz)
+  - "losc": the low frequency oscillator (usually at 32kHz)
+- clock-names: Must contain the clock names described just above
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+ccu: clock@01c20000 {
+       compatible = "allwinner,sun8i-h3-ccu";
+       reg = <0x01c20000 0x400>;
+       clocks = <&osc24M>, <&osc32k>;
+       clock-names = "hosc", "losc";
+       #clock-cells = <1>;
+       #reset-cells = <1>;
+};
index 4a4926b0b0ed70774533eb81aaff0243a1f07dd6..9871bad34742faa756251f02e084938e483203a6 100644 (file)
 
 #include "skeleton.dtsi"
 
+#include <dt-bindings/clock/sun8i-h3-ccu.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/reset/sun8i-h3-ccu.h>
 
 / {
        interrupt-parent = <&gic>;
                        clock-output-names = "osc32k";
                };
 
-               pll1: clk@01c20000 {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun8i-a23-pll1-clk";
-                       reg = <0x01c20000 0x4>;
-                       clocks = <&osc24M>;
-                       clock-output-names = "pll1";
-               };
-
-               /* dummy clock until actually implemented */
-               pll5: pll5_clk {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <0>;
-                       clock-output-names = "pll5";
-               };
-
-               pll6: clk@01c20028 {
-                       #clock-cells = <1>;
-                       compatible = "allwinner,sun6i-a31-pll6-clk";
-                       reg = <0x01c20028 0x4>;
-                       clocks = <&osc24M>;
-                       clock-output-names = "pll6", "pll6x2";
-               };
-
-               pll6d2: pll6d2_clk {
-                       #clock-cells = <0>;
-                       compatible = "fixed-factor-clock";
-                       clock-div = <2>;
-                       clock-mult = <1>;
-                       clocks = <&pll6 0>;
-                       clock-output-names = "pll6d2";
-               };
-
-               /* dummy clock until pll6 can be reused */
-               pll8: pll8_clk {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <1>;
-                       clock-output-names = "pll8";
-               };
-
-               cpu: cpu_clk@01c20050 {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun4i-a10-cpu-clk";
-                       reg = <0x01c20050 0x4>;
-                       clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
-                       clock-output-names = "cpu";
-               };
-
-               axi: axi_clk@01c20050 {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun4i-a10-axi-clk";
-                       reg = <0x01c20050 0x4>;
-                       clocks = <&cpu>;
-                       clock-output-names = "axi";
-               };
-
-               ahb1: ahb1_clk@01c20054 {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun6i-a31-ahb1-clk";
-                       reg = <0x01c20054 0x4>;
-                       clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
-                       clock-output-names = "ahb1";
-               };
-
-               ahb2: ahb2_clk@01c2005c {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun8i-h3-ahb2-clk";
-                       reg = <0x01c2005c 0x4>;
-                       clocks = <&ahb1>, <&pll6d2>;
-                       clock-output-names = "ahb2";
-               };
-
-               apb1: apb1_clk@01c20054 {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun4i-a10-apb0-clk";
-                       reg = <0x01c20054 0x4>;
-                       clocks = <&ahb1>;
-                       clock-output-names = "apb1";
-               };
-
-               apb2: apb2_clk@01c20058 {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun4i-a10-apb1-clk";
-                       reg = <0x01c20058 0x4>;
-                       clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
-                       clock-output-names = "apb2";
-               };
-
-               bus_gates: clk@01c20060 {
-                       #clock-cells = <1>;
-                       compatible = "allwinner,sun8i-h3-bus-gates-clk";
-                       reg = <0x01c20060 0x14>;
-                       clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>;
-                       clock-names = "ahb1", "ahb2", "apb1", "apb2";
-                       clock-indices = <5>, <6>, <8>,
-                                       <9>, <10>, <13>,
-                                       <14>, <17>, <18>,
-                                       <19>, <20>,
-                                       <21>, <23>,
-                                       <24>, <25>,
-                                       <26>, <27>,
-                                       <28>, <29>,
-                                       <30>, <31>, <32>,
-                                       <35>, <36>, <37>,
-                                       <40>, <41>, <43>,
-                                       <44>, <52>, <53>,
-                                       <54>, <64>,
-                                       <65>, <69>, <72>,
-                                       <76>, <77>, <78>,
-                                       <96>, <97>, <98>,
-                                       <112>, <113>,
-                                       <114>, <115>,
-                                       <116>, <128>, <135>;
-                       clock-output-names = "bus_ce", "bus_dma", "bus_mmc0",
-                                            "bus_mmc1", "bus_mmc2", "bus_nand",
-                                            "bus_sdram", "bus_gmac", "bus_ts",
-                                            "bus_hstimer", "bus_spi0",
-                                            "bus_spi1", "bus_otg",
-                                            "bus_otg_ehci0", "bus_ehci1",
-                                            "bus_ehci2", "bus_ehci3",
-                                            "bus_otg_ohci0", "bus_ohci1",
-                                            "bus_ohci2", "bus_ohci3", "bus_ve",
-                                            "bus_lcd0", "bus_lcd1", "bus_deint",
-                                            "bus_csi", "bus_tve", "bus_hdmi",
-                                            "bus_de", "bus_gpu", "bus_msgbox",
-                                            "bus_spinlock", "bus_codec",
-                                            "bus_spdif", "bus_pio", "bus_ths",
-                                            "bus_i2s0", "bus_i2s1", "bus_i2s2",
-                                            "bus_i2c0", "bus_i2c1", "bus_i2c2",
-                                            "bus_uart0", "bus_uart1",
-                                            "bus_uart2", "bus_uart3",
-                                            "bus_scr", "bus_ephy", "bus_dbg";
-               };
-
-               mmc0_clk: clk@01c20088 {
-                       #clock-cells = <1>;
-                       compatible = "allwinner,sun4i-a10-mmc-clk";
-                       reg = <0x01c20088 0x4>;
-                       clocks = <&osc24M>, <&pll6 0>, <&pll8>;
-                       clock-output-names = "mmc0",
-                                            "mmc0_output",
-                                            "mmc0_sample";
-               };
-
-               mmc1_clk: clk@01c2008c {
-                       #clock-cells = <1>;
-                       compatible = "allwinner,sun4i-a10-mmc-clk";
-                       reg = <0x01c2008c 0x4>;
-                       clocks = <&osc24M>, <&pll6 0>, <&pll8>;
-                       clock-output-names = "mmc1",
-                                            "mmc1_output",
-                                            "mmc1_sample";
-               };
-
-               mmc2_clk: clk@01c20090 {
-                       #clock-cells = <1>;
-                       compatible = "allwinner,sun4i-a10-mmc-clk";
-                       reg = <0x01c20090 0x4>;
-                       clocks = <&osc24M>, <&pll6 0>, <&pll8>;
-                       clock-output-names = "mmc2",
-                                            "mmc2_output",
-                                            "mmc2_sample";
-               };
-
-               usb_clk: clk@01c200cc {
-                       #clock-cells = <1>;
-                       #reset-cells = <1>;
-                       compatible = "allwinner,sun8i-h3-usb-clk";
-                       reg = <0x01c200cc 0x4>;
-                       clocks = <&osc24M>;
-                       clock-output-names = "usb_phy0", "usb_phy1",
-                                            "usb_phy2", "usb_phy3",
-                                            "usb_ohci0", "usb_ohci1",
-                                            "usb_ohci2", "usb_ohci3";
-               };
-
-               mbus_clk: clk@01c2015c {
-                       #clock-cells = <0>;
-                       compatible = "allwinner,sun8i-a23-mbus-clk";
-                       reg = <0x01c2015c 0x4>;
-                       clocks = <&osc24M>, <&pll6 1>, <&pll5>;
-                       clock-output-names = "mbus";
-               };
-
                apb0: apb0_clk {
                        compatible = "fixed-factor-clock";
                        #clock-cells = <0>;
                        compatible = "allwinner,sun8i-h3-dma";
                        reg = <0x01c02000 0x1000>;
                        interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 6>;
-                       resets = <&ahb_rst 6>;
+                       clocks = <&ccu CLK_BUS_DMA>;
+                       resets = <&ccu RST_BUS_DMA>;
                        #dma-cells = <1>;
                };
 
                mmc0: mmc@01c0f000 {
                        compatible = "allwinner,sun5i-a13-mmc";
                        reg = <0x01c0f000 0x1000>;
-                       clocks = <&bus_gates 8>,
-                                <&mmc0_clk 0>,
-                                <&mmc0_clk 1>,
-                                <&mmc0_clk 2>;
+                       clocks = <&ccu CLK_BUS_MMC0>,
+                                <&ccu CLK_MMC0>,
+                                <&ccu CLK_MMC0_OUTPUT>,
+                                <&ccu CLK_MMC0_SAMPLE>;
                        clock-names = "ahb",
                                      "mmc",
                                      "output",
                                      "sample";
-                       resets = <&ahb_rst 8>;
+                       resets = <&ccu RST_BUS_MMC0>;
                        reset-names = "ahb";
                        interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                mmc1: mmc@01c10000 {
                        compatible = "allwinner,sun5i-a13-mmc";
                        reg = <0x01c10000 0x1000>;
-                       clocks = <&bus_gates 9>,
-                                <&mmc1_clk 0>,
-                                <&mmc1_clk 1>,
-                                <&mmc1_clk 2>;
+                       clocks = <&ccu CLK_BUS_MMC1>,
+                                <&ccu CLK_MMC1>,
+                                <&ccu CLK_MMC1_OUTPUT>,
+                                <&ccu CLK_MMC1_SAMPLE>;
                        clock-names = "ahb",
                                      "mmc",
                                      "output",
                                      "sample";
-                       resets = <&ahb_rst 9>;
+                       resets = <&ccu RST_BUS_MMC1>;
                        reset-names = "ahb";
                        interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                mmc2: mmc@01c11000 {
                        compatible = "allwinner,sun5i-a13-mmc";
                        reg = <0x01c11000 0x1000>;
-                       clocks = <&bus_gates 10>,
-                                <&mmc2_clk 0>,
-                                <&mmc2_clk 1>,
-                                <&mmc2_clk 2>;
+                       clocks = <&ccu CLK_BUS_MMC2>,
+                                <&ccu CLK_MMC2>,
+                                <&ccu CLK_MMC2_OUTPUT>,
+                                <&ccu CLK_MMC2_SAMPLE>;
                        clock-names = "ahb",
                                      "mmc",
                                      "output",
                                      "sample";
-                       resets = <&ahb_rst 10>;
+                       resets = <&ccu RST_BUS_MMC2>;
                        reset-names = "ahb";
                        interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                                    "pmu1",
                                    "pmu2",
                                    "pmu3";
-                       clocks = <&usb_clk 8>,
-                                <&usb_clk 9>,
-                                <&usb_clk 10>,
-                                <&usb_clk 11>;
+                       clocks = <&ccu CLK_USB_PHY0>,
+                                <&ccu CLK_USB_PHY1>,
+                                <&ccu CLK_USB_PHY2>,
+                                <&ccu CLK_USB_PHY3>;
                        clock-names = "usb0_phy",
                                      "usb1_phy",
                                      "usb2_phy",
                                      "usb3_phy";
-                       resets = <&usb_clk 0>,
-                                <&usb_clk 1>,
-                                <&usb_clk 2>,
-                                <&usb_clk 3>;
+                       resets = <&ccu RST_USB_PHY0>,
+                                <&ccu RST_USB_PHY1>,
+                                <&ccu RST_USB_PHY2>,
+                                <&ccu RST_USB_PHY3>;
                        reset-names = "usb0_reset",
                                      "usb1_reset",
                                      "usb2_reset",
                        compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
                        reg = <0x01c1b000 0x100>;
                        interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 25>, <&bus_gates 29>;
-                       resets = <&ahb_rst 25>, <&ahb_rst 29>;
+                       clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>;
+                       resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
                        phys = <&usbphy 1>;
                        phy-names = "usb";
                        status = "disabled";
                        compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
                        reg = <0x01c1b400 0x100>;
                        interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 29>, <&bus_gates 25>,
-                                <&usb_clk 17>;
-                       resets = <&ahb_rst 29>, <&ahb_rst 25>;
+                       clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>,
+                                <&ccu CLK_USB_OHCI1>;
+                       resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
                        phys = <&usbphy 1>;
                        phy-names = "usb";
                        status = "disabled";
                        compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
                        reg = <0x01c1c000 0x100>;
                        interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 26>, <&bus_gates 30>;
-                       resets = <&ahb_rst 26>, <&ahb_rst 30>;
+                       clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>;
+                       resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
                        phys = <&usbphy 2>;
                        phy-names = "usb";
                        status = "disabled";
                        compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
                        reg = <0x01c1c400 0x100>;
                        interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 30>, <&bus_gates 26>,
-                                <&usb_clk 18>;
-                       resets = <&ahb_rst 30>, <&ahb_rst 26>;
+                       clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>,
+                                <&ccu CLK_USB_OHCI2>;
+                       resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
                        phys = <&usbphy 2>;
                        phy-names = "usb";
                        status = "disabled";
                        compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
                        reg = <0x01c1d000 0x100>;
                        interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 27>, <&bus_gates 31>;
-                       resets = <&ahb_rst 27>, <&ahb_rst 31>;
+                       clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>;
+                       resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
                        phys = <&usbphy 3>;
                        phy-names = "usb";
                        status = "disabled";
                        compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
                        reg = <0x01c1d400 0x100>;
                        interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 31>, <&bus_gates 27>,
-                                <&usb_clk 19>;
-                       resets = <&ahb_rst 31>, <&ahb_rst 27>;
+                       clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>,
+                                <&ccu CLK_USB_OHCI3>;
+                       resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
                        phys = <&usbphy 3>;
                        phy-names = "usb";
                        status = "disabled";
                };
 
+               ccu: clock@01c20000 {
+                       compatible = "allwinner,sun8i-h3-ccu";
+                       reg = <0x01c20000 0x400>;
+                       clocks = <&osc24M>, <&osc32k>;
+                       clock-names = "hosc", "losc";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
                pio: pinctrl@01c20800 {
                        compatible = "allwinner,sun8i-h3-pinctrl";
                        reg = <0x01c20800 0x400>;
                        interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&bus_gates 69>;
+                       clocks = <&ccu CLK_BUS_PIO>;
                        gpio-controller;
                        #gpio-cells = <3>;
                        interrupt-controller;
                        };
                };
 
-               ahb_rst: reset@01c202c0 {
-                       #reset-cells = <1>;
-                       compatible = "allwinner,sun6i-a31-ahb1-reset";
-                       reg = <0x01c202c0 0xc>;
-               };
-
-               apb1_rst: reset@01c202d0 {
-                       #reset-cells = <1>;
-                       compatible = "allwinner,sun6i-a31-clock-reset";
-                       reg = <0x01c202d0 0x4>;
-               };
-
-               apb2_rst: reset@01c202d8 {
-                       #reset-cells = <1>;
-                       compatible = "allwinner,sun6i-a31-clock-reset";
-                       reg = <0x01c202d8 0x4>;
-               };
-
                timer@01c20c00 {
                        compatible = "allwinner,sun4i-a10-timer";
                        reg = <0x01c20c00 0xa0>;
                        interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
-                       clocks = <&bus_gates 112>;
-                       resets = <&apb2_rst 16>;
+                       clocks = <&ccu CLK_BUS_UART0>;
+                       resets = <&ccu RST_BUS_UART0>;
                        dmas = <&dma 6>, <&dma 6>;
                        dma-names = "rx", "tx";
                        status = "disabled";
                        interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
-                       clocks = <&bus_gates 113>;
-                       resets = <&apb2_rst 17>;
+                       clocks = <&ccu CLK_BUS_UART1>;
+                       resets = <&ccu RST_BUS_UART1>;
                        dmas = <&dma 7>, <&dma 7>;
                        dma-names = "rx", "tx";
                        status = "disabled";
                        interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
-                       clocks = <&bus_gates 114>;
-                       resets = <&apb2_rst 18>;
+                       clocks = <&ccu CLK_BUS_UART2>;
+                       resets = <&ccu RST_BUS_UART2>;
                        dmas = <&dma 8>, <&dma 8>;
                        dma-names = "rx", "tx";
                        status = "disabled";
                        interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
-                       clocks = <&bus_gates 115>;
-                       resets = <&apb2_rst 19>;
+                       clocks = <&ccu CLK_BUS_UART3>;
+                       resets = <&ccu RST_BUS_UART3>;
                        dmas = <&dma 9>, <&dma 9>;
                        dma-names = "rx", "tx";
                        status = "disabled";
index 98efbfcdb503e181d32f44a0dd0b44f286e6080a..e2d9bd760c84a04e94290c3f4d523f8c0f1266df 100644 (file)
@@ -49,10 +49,10 @@ config COMMON_CLK_MAX77802
          This driver supports Maxim 77802 crystal oscillator clock.
 
 config COMMON_CLK_RK808
-       tristate "Clock driver for RK808"
+       tristate "Clock driver for RK808/RK818"
        depends on MFD_RK808
        ---help---
-         This driver supports RK808 crystal oscillator clock. These
+         This driver supports RK808 and RK818 crystal oscillator clock. These
          multi-function devices have two fixed-rate oscillators,
          clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
          by control register.
@@ -203,16 +203,19 @@ config COMMON_CLK_PIC32
 
 config COMMON_CLK_OXNAS
        bool "Clock driver for the OXNAS SoC Family"
+       depends on ARCH_OXNAS || COMPILE_TEST
        select MFD_SYSCON
        ---help---
          Support for the OXNAS SoC Family clocks.
 
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
+source "drivers/clk/meson/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 source "drivers/clk/renesas/Kconfig"
 source "drivers/clk/samsung/Kconfig"
+source "drivers/clk/sunxi-ng/Kconfig"
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/ti/Kconfig"
 
index dcc5e698ff6dd4d61255dd274dafadb1af239161..3b6f9cf3464aaddca0a54886aa575a108c21b7ca 100644 (file)
@@ -16,13 +16,14 @@ obj-$(CONFIG_COMMON_CLK)    += clk-conf.o
 endif
 
 # hardware specific clock types
-# please keep this section sorted lexicographically by file/directory path name
+# please keep this section sorted lexicographically by file path name
 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_COMMON_CLK_CDCE925)       += clk-cdce925.o
 obj-$(CONFIG_ARCH_CLPS711X)            += clk-clps711x.o
+obj-$(CONFIG_COMMON_CLK_CS2000_CP)     += clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_EFM32)               += clk-efm32gg.o
 obj-$(CONFIG_ARCH_HIGHBANK)            += clk-highbank.o
 obj-$(CONFIG_MACH_LOONGSON32)          += clk-ls1x.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_ARCH_NOMADIK)            += clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)              += clk-nspire.o
 obj-$(CONFIG_COMMON_CLK_OXNAS)         += clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)                += clk-palmas.o
+obj-$(CONFIG_COMMON_CLK_PWM)           += clk-pwm.o
 obj-$(CONFIG_CLK_QORIQ)                        += clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)         += clk-rk808.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)       += clk-s2mps11.o
@@ -42,7 +44,6 @@ obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
 obj-$(CONFIG_COMMON_CLK_SI5351)                += clk-si5351.o
 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_TANGO)               += clk-tango4.o
 obj-$(CONFIG_CLK_TWL6040)              += clk-twl6040.o
@@ -50,35 +51,39 @@ obj-$(CONFIG_ARCH_U300)                     += clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)              += clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_WM831X)                += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_XGENE)         += clk-xgene.o
-obj-$(CONFIG_COMMON_CLK_PWM)           += clk-pwm.o
+
+# please keep this section sorted lexicographically by directory path name
 obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
 obj-$(CONFIG_ARCH_ARTPEC)              += axis/
+obj-$(CONFIG_ARC_PLAT_AXS10X)          += axs10x/
 obj-y                                  += bcm/
 obj-$(CONFIG_ARCH_BERLIN)              += berlin/
+obj-$(CONFIG_H8300)                    += h8300/
 obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
 obj-$(CONFIG_ARCH_MXC)                 += imx/
 obj-$(CONFIG_MACH_INGENIC)             += ingenic/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
 obj-$(CONFIG_ARCH_MEDIATEK)            += mediatek/
+obj-$(CONFIG_COMMON_CLK_AMLOGIC)       += meson/
 obj-$(CONFIG_MACH_PIC32)               += microchip/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)                 += mmp/
 endif
 obj-y                                  += mvebu/
-obj-$(CONFIG_ARCH_MESON)               += meson/
 obj-$(CONFIG_ARCH_MXS)                 += mxs/
-obj-$(CONFIG_MACH_PISTACHIO)           += pistachio/
 obj-$(CONFIG_COMMON_CLK_NXP)           += nxp/
+obj-$(CONFIG_MACH_PISTACHIO)           += pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)           += pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)          += qcom/
+obj-$(CONFIG_ARCH_RENESAS)             += renesas/
 obj-$(CONFIG_ARCH_ROCKCHIP)            += rockchip/
 obj-$(CONFIG_COMMON_CLK_SAMSUNG)       += samsung/
-obj-$(CONFIG_ARCH_RENESAS)             += renesas/
 obj-$(CONFIG_ARCH_SIRF)                        += sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)             += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)               += spear/
 obj-$(CONFIG_ARCH_STI)                 += st/
 obj-$(CONFIG_ARCH_SUNXI)               += sunxi/
+obj-$(CONFIG_ARCH_SUNXI)               += sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)               += tegra/
 obj-y                                  += ti/
 obj-$(CONFIG_ARCH_U8500)               += ux500/
@@ -86,5 +91,3 @@ obj-$(CONFIG_COMMON_CLK_VERSATILE)    += versatile/
 obj-$(CONFIG_X86)                      += x86/
 obj-$(CONFIG_ARCH_ZX)                  += zte/
 obj-$(CONFIG_ARCH_ZYNQ)                        += zynq/
-obj-$(CONFIG_H8300)            += h8300/
-obj-$(CONFIG_ARC_PLAT_AXS10X)          += axs10x/
index e1aa210dd7aa6a6bf3ca40bb76f31f36407eb116..7f6bec8837eaa755934f3a4f5c2bc503813b16b6 100644 (file)
@@ -267,7 +267,7 @@ at91_clk_register_generated(struct regmap *regmap,  spinlock_t *lock, const char
        return clk;
 }
 
-void __init of_sama5d2_clk_generated_setup(struct device_node *np)
+static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
 {
        int num;
        u32 id;
index a196ee28a17ae63f42e03a1f10714405254b52e2..d7d628214b85f40481c6a9b28c49dd858448f5f5 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/clkdev.h>
 #include <linux/of_address.h>
 
+#include "clk-iproc.h"
+
 #define IPROC_CLK_MAX_FREQ_POLICY                    0x3
 #define IPROC_CLK_POLICY_FREQ_OFFSET                 0x008
 #define IPROC_CLK_POLICY_FREQ_POLICY_FREQ_SHIFT      8
@@ -242,7 +244,6 @@ static const struct clk_ops iproc_arm_pll_ops = {
 void __init iproc_armpll_setup(struct device_node *node)
 {
        int ret;
-       struct clk *clk;
        struct iproc_arm_pll *pll;
        struct clk_init_data init;
        const char *parent_name;
@@ -263,18 +264,18 @@ void __init iproc_armpll_setup(struct device_node *node)
        init.num_parents = (parent_name ? 1 : 0);
        pll->hw.init = &init;
 
-       clk = clk_register(NULL, &pll->hw);
-       if (WARN_ON(IS_ERR(clk)))
+       ret = clk_hw_register(NULL, &pll->hw);
+       if (WARN_ON(ret))
                goto err_iounmap;
 
-       ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll->hw);
        if (WARN_ON(ret))
                goto err_clk_unregister;
 
        return;
 
 err_clk_unregister:
-       clk_unregister(clk);
+       clk_hw_unregister(&pll->hw);
 err_iounmap:
        iounmap(pll->base);
 err_free_pll:
index f630e1bbdcfee9ba2016c856ee7f3b9f449a0205..4360e481368b5708866a7fdb4814a8b6bc482b86 100644 (file)
@@ -37,7 +37,7 @@ struct iproc_asiu {
        void __iomem *div_base;
        void __iomem *gate_base;
 
-       struct clk_onecell_data clk_data;
+       struct clk_hw_onecell_data *clk_data;
        struct iproc_asiu_clk *clks;
 };
 
@@ -197,11 +197,11 @@ void __init iproc_asiu_setup(struct device_node *node,
        if (WARN_ON(!asiu))
                return;
 
-       asiu->clk_data.clk_num = num_clks;
-       asiu->clk_data.clks = kcalloc(num_clks, sizeof(*asiu->clk_data.clks),
-                                     GFP_KERNEL);
-       if (WARN_ON(!asiu->clk_data.clks))
+       asiu->clk_data = kzalloc(sizeof(*asiu->clk_data->hws) * num_clks +
+                                sizeof(*asiu->clk_data), GFP_KERNEL);
+       if (WARN_ON(!asiu->clk_data))
                goto err_clks;
+       asiu->clk_data->num = num_clks;
 
        asiu->clks = kcalloc(num_clks, sizeof(*asiu->clks), GFP_KERNEL);
        if (WARN_ON(!asiu->clks))
@@ -217,7 +217,6 @@ void __init iproc_asiu_setup(struct device_node *node,
 
        for (i = 0; i < num_clks; i++) {
                struct clk_init_data init;
-               struct clk *clk;
                const char *parent_name;
                struct iproc_asiu_clk *asiu_clk;
                const char *clk_name;
@@ -240,22 +239,22 @@ void __init iproc_asiu_setup(struct device_node *node,
                init.num_parents = (parent_name ? 1 : 0);
                asiu_clk->hw.init = &init;
 
-               clk = clk_register(NULL, &asiu_clk->hw);
-               if (WARN_ON(IS_ERR(clk)))
+               ret = clk_hw_register(NULL, &asiu_clk->hw);
+               if (WARN_ON(ret))
                        goto err_clk_register;
-               asiu->clk_data.clks[i] = clk;
+               asiu->clk_data->hws[i] = &asiu_clk->hw;
        }
 
-       ret = of_clk_add_provider(node, of_clk_src_onecell_get,
-                                 &asiu->clk_data);
+       ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+                                    asiu->clk_data);
        if (WARN_ON(ret))
                goto err_clk_register;
 
        return;
 
 err_clk_register:
-       for (i = 0; i < num_clks; i++)
-               clk_unregister(asiu->clk_data.clks[i]);
+       while (--i >= 0)
+               clk_hw_unregister(asiu->clk_data->hws[i]);
        iounmap(asiu->gate_base);
 
 err_iomap_gate:
@@ -265,7 +264,7 @@ err_iomap_div:
        kfree(asiu->clks);
 
 err_asiu_clks:
-       kfree(asiu->clk_data.clks);
+       kfree(asiu->clk_data);
 
 err_clks:
        kfree(asiu);
index fd492a5dad12bf48b96fbaa2484100093f581d96..e04634c46395b43f9a1d7e452d59dacecff4bce7 100644 (file)
@@ -89,7 +89,7 @@ struct iproc_pll {
        const struct iproc_pll_vco_param *vco_param;
        unsigned int num_vco_entries;
 
-       struct clk_onecell_data clk_data;
+       struct clk_hw_onecell_data *clk_data;
        struct iproc_clk *clks;
 };
 
@@ -625,7 +625,6 @@ void __init iproc_pll_clk_setup(struct device_node *node,
                                unsigned int num_clks)
 {
        int i, ret;
-       struct clk *clk;
        struct iproc_pll *pll;
        struct iproc_clk *iclk;
        struct clk_init_data init;
@@ -638,11 +637,11 @@ void __init iproc_pll_clk_setup(struct device_node *node,
        if (WARN_ON(!pll))
                return;
 
-       pll->clk_data.clk_num = num_clks;
-       pll->clk_data.clks = kcalloc(num_clks, sizeof(*pll->clk_data.clks),
-                                    GFP_KERNEL);
-       if (WARN_ON(!pll->clk_data.clks))
+       pll->clk_data = kzalloc(sizeof(*pll->clk_data->hws) * num_clks +
+                               sizeof(*pll->clk_data), GFP_KERNEL);
+       if (WARN_ON(!pll->clk_data))
                goto err_clk_data;
+       pll->clk_data->num = num_clks;
 
        pll->clks = kcalloc(num_clks, sizeof(*pll->clks), GFP_KERNEL);
        if (WARN_ON(!pll->clks))
@@ -694,11 +693,11 @@ void __init iproc_pll_clk_setup(struct device_node *node,
 
        iproc_pll_sw_cfg(pll);
 
-       clk = clk_register(NULL, &iclk->hw);
-       if (WARN_ON(IS_ERR(clk)))
+       ret = clk_hw_register(NULL, &iclk->hw);
+       if (WARN_ON(ret))
                goto err_pll_register;
 
-       pll->clk_data.clks[0] = clk;
+       pll->clk_data->hws[0] = &iclk->hw;
 
        /* now initialize and register all leaf clocks */
        for (i = 1; i < num_clks; i++) {
@@ -724,22 +723,23 @@ void __init iproc_pll_clk_setup(struct device_node *node,
                init.num_parents = (parent_name ? 1 : 0);
                iclk->hw.init = &init;
 
-               clk = clk_register(NULL, &iclk->hw);
-               if (WARN_ON(IS_ERR(clk)))
+               ret = clk_hw_register(NULL, &iclk->hw);
+               if (WARN_ON(ret))
                        goto err_clk_register;
 
-               pll->clk_data.clks[i] = clk;
+               pll->clk_data->hws[i] = &iclk->hw;
        }
 
-       ret = of_clk_add_provider(node, of_clk_src_onecell_get, &pll->clk_data);
+       ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+                                    pll->clk_data);
        if (WARN_ON(ret))
                goto err_clk_register;
 
        return;
 
 err_clk_register:
-       for (i = 0; i < num_clks; i++)
-               clk_unregister(pll->clk_data.clks[i]);
+       while (--i >= 0)
+               clk_hw_unregister(pll->clk_data->hws[i]);
 
 err_pll_register:
        if (pll->status_base != pll->control_base)
@@ -759,7 +759,7 @@ err_pll_iomap:
        kfree(pll->clks);
 
 err_clks:
-       kfree(pll->clk_data.clks);
+       kfree(pll->clk_data);
 
 err_clk_data:
        kfree(pll);
index 43a218f35b190a21e62bc520cdac38f275f5da82..674785d968a3e1c507637ebbeb3865e17fcb5def 100644 (file)
@@ -55,7 +55,7 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
                }
                clk = of_clk_get_from_provider(&clkspec);
                if (IS_ERR(clk)) {
-                       pr_warn("clk: couldn't get parent clock %d for %s\n",
+                       pr_warn("clk: couldn't get assigned clock %d for %s\n",
                                index, node->full_name);
                        rc = PTR_ERR(clk);
                        goto err;
index 75cd6c792cb8cd10b57c55f29e4eadbaec4138b6..4db3be2140776a27e6e6207c9fb446702d338000 100644 (file)
@@ -142,6 +142,11 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
 EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
 
 #ifdef CONFIG_OF
+static const struct of_device_id set_rate_parent_matches[] = {
+       { .compatible = "allwinner,sun4i-a10-pll3-2x-clk" },
+       { /* Sentinel */ },
+};
+
 /**
  * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
  */
@@ -150,6 +155,7 @@ void __init of_fixed_factor_clk_setup(struct device_node *node)
        struct clk *clk;
        const char *clk_name = node->name;
        const char *parent_name;
+       unsigned long flags = 0;
        u32 div, mult;
 
        if (of_property_read_u32(node, "clock-div", &div)) {
@@ -167,7 +173,10 @@ void __init of_fixed_factor_clk_setup(struct device_node *node)
        of_property_read_string(node, "clock-output-names", &clk_name);
        parent_name = of_clk_get_parent_name(node, 0);
 
-       clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0,
+       if (of_match_node(set_rate_parent_matches, node))
+               flags |= CLK_SET_RATE_PARENT;
+
+       clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags,
                                        mult, div);
        if (!IS_ERR(clk))
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
index 8e4453eb54e8266479d6f6256e02a9b505a90e8a..2edb39342a02a8d6397c9f9cef9ccdcd95f6e656 100644 (file)
@@ -145,6 +145,17 @@ void clk_unregister_fixed_rate(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_unregister_fixed_rate);
 
+void clk_hw_unregister_fixed_rate(struct clk_hw *hw)
+{
+       struct clk_fixed_rate *fixed;
+
+       fixed = to_clk_fixed_rate(hw);
+
+       clk_hw_unregister(hw);
+       kfree(fixed);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate);
+
 #ifdef CONFIG_OF
 /**
  * of_fixed_clk_setup() - Setup function for simple fixed rate clock
index be3a21abb185a188e207d8dd35cb8146293779a0..727ed8e1bb726fd424f97427507abe6f46fe84a9 100644 (file)
@@ -275,7 +275,6 @@ static const struct clk_ops periclk_ops = {
 static __init struct clk *hb_clk_init(struct device_node *node, const struct clk_ops *ops)
 {
        u32 reg;
-       struct clk *clk;
        struct hb_clk *hb_clk;
        const char *clk_name = node->name;
        const char *parent_name;
@@ -308,13 +307,13 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk
 
        hb_clk->hw.init = &init;
 
-       clk = clk_register(NULL, &hb_clk->hw);
-       if (WARN_ON(IS_ERR(clk))) {
+       rc = clk_hw_register(NULL, &hb_clk->hw);
+       if (WARN_ON(rc)) {
                kfree(hb_clk);
                return NULL;
        }
-       rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
-       return clk;
+       rc = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &hb_clk->hw);
+       return hb_clk->hw.clk;
 }
 
 static void __init hb_pll_init(struct device_node *node)
index 9e449c7b751c328e23b074186e1bebf426172087..dc037c957acd8a1dc1f74f3c0407567a09fa66cd 100644 (file)
@@ -52,14 +52,28 @@ static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
                                unsigned long *best_parent_rate,
                                u8 width, unsigned long flags)
 {
+       struct clk_multiplier *mult = to_clk_multiplier(hw);
        unsigned long orig_parent_rate = *best_parent_rate;
        unsigned long parent_rate, current_rate, best_rate = ~0;
        unsigned int i, bestmult = 0;
+       unsigned int maxmult = (1 << width) - 1;
+
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+               bestmult = rate / orig_parent_rate;
+
+               /* Make sure we don't end up with a 0 multiplier */
+               if ((bestmult == 0) &&
+                   !(mult->flags & CLK_MULTIPLIER_ZERO_BYPASS))
+                       bestmult = 1;
 
-       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT))
-               return rate / *best_parent_rate;
+               /* Make sure we don't overflow the multiplier */
+               if (bestmult > maxmult)
+                       bestmult = maxmult;
+
+               return bestmult;
+       }
 
-       for (i = 1; i < ((1 << width) - 1); i++) {
+       for (i = 1; i < maxmult; i++) {
                if (rate == orig_parent_rate * i) {
                        /*
                         * This is the best case for us if we have a
index e4d8a991c58fa3972d414810e634ec5c72fb0c9a..71677eb125656420482f9b6405fa3765d0c5bb80 100644 (file)
@@ -253,11 +253,11 @@ static const struct clk_ops pll_clk_ops = {
        .recalc_rate = pll_clk_recalc_rate,
 };
 
-static struct clk * __init
+static struct clk_hw * __init
 pll_clk_register(struct device *dev, const char *name,
                 const char *parent_name, u32 id)
 {
-       struct clk *clk;
+       int ret;
        struct clk_pll *pll;
        struct clk_init_data init;
 
@@ -281,11 +281,13 @@ pll_clk_register(struct device *dev, const char *name,
 
        pr_debug("register PLL1 clock \"%s\"\n", name);
 
-       clk = clk_register(dev, &pll->hw);
-       if (IS_ERR(clk))
+       ret = clk_hw_register(dev, &pll->hw);
+       if (ret) {
                kfree(pll);
+               return ERR_PTR(ret);
+       }
 
-       return clk;
+       return &pll->hw;
 }
 
 /*
@@ -345,11 +347,11 @@ static const struct clk_ops src_clk_ops = {
        .recalc_rate = src_clk_recalc_rate,
 };
 
-static struct clk * __init
+static struct clk_hw * __init
 src_clk_register(struct device *dev, const char *name,
                 const char *parent_name, u8 id)
 {
-       struct clk *clk;
+       int ret;
        struct clk_src *sclk;
        struct clk_init_data init;
 
@@ -376,11 +378,13 @@ src_clk_register(struct device *dev, const char *name,
        pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
                 name, id, sclk->group1, sclk->clkbit);
 
-       clk = clk_register(dev, &sclk->hw);
-       if (IS_ERR(clk))
+       ret = clk_hw_register(dev, &sclk->hw);
+       if (ret) {
                kfree(sclk);
+               return ERR_PTR(ret);
+       }
 
-       return clk;
+       return &sclk->hw;
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -508,7 +512,7 @@ device_initcall(nomadik_src_clk_init_debugfs);
 
 static void __init of_nomadik_pll_setup(struct device_node *np)
 {
-       struct clk *clk = ERR_PTR(-EINVAL);
+       struct clk_hw *hw;
        const char *clk_name = np->name;
        const char *parent_name;
        u32 pll_id;
@@ -522,16 +526,16 @@ static void __init of_nomadik_pll_setup(struct device_node *np)
                return;
        }
        parent_name = of_clk_get_parent_name(np, 0);
-       clk = pll_clk_register(NULL, clk_name, parent_name, pll_id);
-       if (!IS_ERR(clk))
-               of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       hw = pll_clk_register(NULL, clk_name, parent_name, pll_id);
+       if (!IS_ERR(hw))
+               of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 }
 CLK_OF_DECLARE(nomadik_pll_clk,
        "st,nomadik-pll-clock", of_nomadik_pll_setup);
 
 static void __init of_nomadik_hclk_setup(struct device_node *np)
 {
-       struct clk *clk = ERR_PTR(-EINVAL);
+       struct clk_hw *hw;
        const char *clk_name = np->name;
        const char *parent_name;
 
@@ -542,20 +546,20 @@ static void __init of_nomadik_hclk_setup(struct device_node *np)
        /*
         * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
         */
-       clk = clk_register_divider(NULL, clk_name, parent_name,
+       hw = clk_hw_register_divider(NULL, clk_name, parent_name,
                           0, src_base + SRC_CR,
                           13, 2,
                           CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
                           &src_lock);
-       if (!IS_ERR(clk))
-               of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       if (!IS_ERR(hw))
+               of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 }
 CLK_OF_DECLARE(nomadik_hclk_clk,
        "st,nomadik-hclk-clock", of_nomadik_hclk_setup);
 
 static void __init of_nomadik_src_clk_setup(struct device_node *np)
 {
-       struct clk *clk = ERR_PTR(-EINVAL);
+       struct clk_hw *hw;
        const char *clk_name = np->name;
        const char *parent_name;
        u32 clk_id;
@@ -569,9 +573,9 @@ static void __init of_nomadik_src_clk_setup(struct device_node *np)
                return;
        }
        parent_name = of_clk_get_parent_name(np, 0);
-       clk = src_clk_register(NULL, clk_name, parent_name, clk_id);
-       if (!IS_ERR(clk))
-               of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       hw = src_clk_register(NULL, clk_name, parent_name, clk_id);
+       if (!IS_ERR(hw))
+               of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 }
 CLK_OF_DECLARE(nomadik_src_clk,
        "st,nomadik-src-clock", of_nomadik_src_clk_setup);
index 79bcb2e4206048c74add49b88f9efe97d11622ff..47649ac5d3993d08c2eae6a7db719cef96790949 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/stringify.h>
@@ -170,26 +170,17 @@ static int oxnas_stdclk_probe(struct platform_device *pdev)
                                   clk_oxnas->onecell_data);
 }
 
-static int oxnas_stdclk_remove(struct platform_device *pdev)
-{
-       of_clk_del_provider(pdev->dev.of_node);
-
-       return 0;
-}
-
 static const struct of_device_id oxnas_stdclk_dt_ids[] = {
        { .compatible = "oxsemi,ox810se-stdclk" },
        { }
 };
-MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids);
 
 static struct platform_driver oxnas_stdclk_driver = {
        .probe = oxnas_stdclk_probe,
-       .remove = oxnas_stdclk_remove,
        .driver = {
                .name = "oxnas-stdclk",
+               .suppress_bind_attrs = true,
                .of_match_table = oxnas_stdclk_dt_ids,
        },
 };
-
-module_platform_driver(oxnas_stdclk_driver);
+builtin_platform_driver(oxnas_stdclk_driver);
index f8c83977c7fa8ded548f9d6af43a954e41599c81..fbaa84a33c46c4e5b0160c154c1b3fd9a30b1788 100644 (file)
@@ -137,7 +137,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct s2mps11_clk *s2mps11_clks;
-       struct clk_onecell_data *clk_data;
+       struct clk_hw_onecell_data *clk_data;
        unsigned int s2mps11_reg;
        int i, ret = 0;
        enum sec_device_type hwid = platform_get_device_id(pdev)->driver_data;
@@ -147,15 +147,12 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
        if (!s2mps11_clks)
                return -ENOMEM;
 
-       clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
+       clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+                               sizeof(*clk_data->hws) * S2MPS11_CLKS_NUM,
+                               GFP_KERNEL);
        if (!clk_data)
                return -ENOMEM;
 
-       clk_data->clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
-                               sizeof(struct clk *), GFP_KERNEL);
-       if (!clk_data->clks)
-               return -ENOMEM;
-
        switch (hwid) {
        case S2MPS11X:
                s2mps11_reg = S2MPS11_REG_RTC_CTRL;
@@ -196,18 +193,18 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                        goto err_reg;
                }
 
-               s2mps11_clks[i].lookup = clkdev_create(s2mps11_clks[i].clk,
+               s2mps11_clks[i].lookup = clkdev_hw_create(&s2mps11_clks[i].hw,
                                        s2mps11_clks_init[i].name, NULL);
                if (!s2mps11_clks[i].lookup) {
                        ret = -ENOMEM;
                        goto err_reg;
                }
-               clk_data->clks[i] = s2mps11_clks[i].clk;
+               clk_data->hws[i] = &s2mps11_clks[i].hw;
        }
 
-       clk_data->clk_num = S2MPS11_CLKS_NUM;
-       of_clk_add_provider(s2mps11_clks->clk_np, of_clk_src_onecell_get,
-                       clk_data);
+       clk_data->num = S2MPS11_CLKS_NUM;
+       of_clk_add_hw_provider(s2mps11_clks->clk_np, of_clk_hw_onecell_get,
+                              clk_data);
 
        platform_set_drvdata(pdev, s2mps11_clks);
 
index fd89e771107eadfcb3b319f67f65eb16773bb654..02d6810084017212c04cf83ae7b27b586fd74ca7 100644 (file)
@@ -136,7 +136,7 @@ static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
                                           0x0000000000000001ull,
                                           0x04777f33f6fec9ffull };
 
-static struct clk *clks[MAX_CLKS];
+static struct clk_hw *clks[MAX_CLKS];
 static DEFINE_SPINLOCK(stm32f4_clk_lock);
 static void __iomem *base;
 
@@ -281,7 +281,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
               (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
 }
 
-static struct clk *
+static struct clk_hw *
 stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
 {
        int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]);
@@ -346,9 +346,9 @@ static void __init stm32f4_rcc_init(struct device_node *np)
        clk_register_apb_mul(NULL, "apb2_mul", "apb2_div",
                             CLK_SET_RATE_PARENT, 15);
 
-       clks[SYSTICK] = clk_register_fixed_factor(NULL, "systick", "ahb_div",
+       clks[SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", "ahb_div",
                                                  0, 1, 8);
-       clks[FCLK] = clk_register_fixed_factor(NULL, "fclk", "ahb_div",
+       clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
                                               0, 1, 1);
 
        for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
@@ -360,18 +360,18 @@ static void __init stm32f4_rcc_init(struct device_node *np)
                if (idx < 0)
                        goto fail;
 
-               clks[idx] = clk_register_gate(
+               clks[idx] = clk_hw_register_gate(
                    NULL, gd->name, gd->parent_name, gd->flags,
                    base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock);
 
-               if (IS_ERR(clks[n])) {
+               if (IS_ERR(clks[idx])) {
                        pr_err("%s: Unable to register leaf clock %s\n",
                               np->full_name, gd->name);
                        goto fail;
                }
        }
 
-       of_clk_add_provider(np, stm32f4_rcc_lookup_clk, NULL);
+       of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
        return;
 fail:
        iounmap(base);
index 95d1742dac309fe43036b0d926e3b516a23a7822..ec8aafda6e243216b523f6630cf1a148f254c49a 100644 (file)
@@ -689,7 +689,7 @@ static const struct clk_ops syscon_clk_ops = {
        .set_rate = syscon_clk_set_rate,
 };
 
-static struct clk * __init
+static struct clk_hw * __init
 syscon_clk_register(struct device *dev, const char *name,
                    const char *parent_name, unsigned long flags,
                    bool hw_ctrld,
@@ -697,9 +697,10 @@ syscon_clk_register(struct device *dev, const char *name,
                    void __iomem *en_reg, u8 en_bit,
                    u16 clk_val)
 {
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_syscon *sclk;
        struct clk_init_data init;
+       int ret;
 
        sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL);
        if (!sclk) {
@@ -722,11 +723,14 @@ syscon_clk_register(struct device *dev, const char *name,
        sclk->en_bit = en_bit;
        sclk->clk_val = clk_val;
 
-       clk = clk_register(dev, &sclk->hw);
-       if (IS_ERR(clk))
+       hw = &sclk->hw;
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
                kfree(sclk);
+               hw = ERR_PTR(ret);
+       }
 
-       return clk;
+       return hw;
 }
 
 #define U300_CLK_TYPE_SLOW 0
@@ -868,7 +872,7 @@ static struct u300_clock const u300_clk_lookup[] __initconst = {
 
 static void __init of_u300_syscon_clk_init(struct device_node *np)
 {
-       struct clk *clk = ERR_PTR(-EINVAL);
+       struct clk_hw *hw = ERR_PTR(-EINVAL);
        const char *clk_name = np->name;
        const char *parent_name;
        void __iomem *res_reg;
@@ -911,16 +915,15 @@ static void __init of_u300_syscon_clk_init(struct device_node *np)
                const struct u300_clock *u3clk = &u300_clk_lookup[i];
 
                if (u3clk->type == clk_type && u3clk->id == clk_id)
-                       clk = syscon_clk_register(NULL,
-                                                 clk_name, parent_name,
-                                                 0, u3clk->hw_ctrld,
-                                                 res_reg, u3clk->id,
-                                                 en_reg, u3clk->id,
-                                                 u3clk->clk_val);
+                       hw = syscon_clk_register(NULL, clk_name, parent_name,
+                                                0, u3clk->hw_ctrld,
+                                                res_reg, u3clk->id,
+                                                en_reg, u3clk->id,
+                                                u3clk->clk_val);
        }
 
-       if (!IS_ERR(clk)) {
-               of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       if (!IS_ERR(hw)) {
+               of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 
                /*
                 * Some few system clocks - device tree does not
@@ -928,11 +931,11 @@ static void __init of_u300_syscon_clk_init(struct device_node *np)
                 * for now we add these three clocks here.
                 */
                if (clk_type == U300_CLK_TYPE_REST && clk_id == 5)
-                       clk_register_clkdev(clk, NULL, "pl172");
+                       clk_hw_register_clkdev(hw, NULL, "pl172");
                if (clk_type == U300_CLK_TYPE_REST && clk_id == 9)
-                       clk_register_clkdev(clk, NULL, "semi");
+                       clk_hw_register_clkdev(hw, NULL, "semi");
                if (clk_type == U300_CLK_TYPE_REST && clk_id == 12)
-                       clk_register_clkdev(clk, NULL, "intcon");
+                       clk_hw_register_clkdev(hw, NULL, "intcon");
        }
 }
 
@@ -1111,13 +1114,14 @@ static const struct clk_ops mclk_ops = {
        .set_rate = mclk_clk_set_rate,
 };
 
-static struct clk * __init
+static struct clk_hw * __init
 mclk_clk_register(struct device *dev, const char *name,
                  const char *parent_name, bool is_mspro)
 {
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_mclk *mclk;
        struct clk_init_data init;
+       int ret;
 
        mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL);
        if (!mclk) {
@@ -1133,23 +1137,26 @@ mclk_clk_register(struct device *dev, const char *name,
        mclk->hw.init = &init;
        mclk->is_mspro = is_mspro;
 
-       clk = clk_register(dev, &mclk->hw);
-       if (IS_ERR(clk))
+       hw = &mclk->hw;
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
                kfree(mclk);
+               hw = ERR_PTR(ret);
+       }
 
-       return clk;
+       return hw;
 }
 
 static void __init of_u300_syscon_mclk_init(struct device_node *np)
 {
-       struct clk *clk = ERR_PTR(-EINVAL);
+       struct clk_hw *hw;
        const char *clk_name = np->name;
        const char *parent_name;
 
        parent_name = of_clk_get_parent_name(np, 0);
-       clk = mclk_clk_register(NULL, clk_name, parent_name, false);
-       if (!IS_ERR(clk))
-               of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       hw = mclk_clk_register(NULL, clk_name, parent_name, false);
+       if (!IS_ERR(hw))
+               of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 }
 
 static const struct of_device_id u300_clk_match[] __initconst = {
index b0f76a84f1e9fec9d3f2bcc7ec0f41eec37fbf93..37368a399ff9d8faa370ba727bb06b472b338354 100644 (file)
@@ -383,51 +383,49 @@ static int vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
        return 0;
 }
 
-static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
-                               u32 *multiplier, u32 *divisor1, u32 *divisor2)
+/*
+ * M * parent [O1] => / P [O2] => / D [O3]
+ * Where O1 is 900MHz...3GHz;
+ * O2 is 600MHz >= (M * parent) / P >= 300MHz;
+ * M is 36...120 [25MHz parent]; D is 1 or 2 or 4 or 8.
+ * Possible ranges (O3):
+ * D = 8: 37,5MHz...75MHz
+ * D = 4: 75MHz...150MHz
+ * D = 2: 150MHz...300MHz
+ * D = 1: 300MHz...600MHz
+ */
+static int wm8650_find_pll_bits(unsigned long rate,
+       unsigned long parent_rate, u32 *multiplier, u32 *divisor1,
+       u32 *divisor2)
 {
-       u32 mul, div1;
-       int div2;
-       u32 best_mul, best_div1, best_div2;
-       unsigned long tclk, rate_err, best_err;
-
-       best_err = (unsigned long)-1;
+       unsigned long O1, min_err, rate_err;
 
-       /* Find the closest match (lower or equal to requested) */
-       for (div1 = 5; div1 >= 3; div1--)
-               for (div2 = 3; div2 >= 0; div2--)
-                       for (mul = 3; mul <= 1023; mul++) {
-                               tclk = parent_rate * mul / (div1 * (1 << div2));
-                               if (tclk > rate)
-                                       continue;
-                               /* error will always be +ve */
-                               rate_err = rate - tclk;
-                               if (rate_err == 0) {
-                                       *multiplier = mul;
-                                       *divisor1 = div1;
-                                       *divisor2 = div2;
-                                       return 0;
-                               }
+       if (!parent_rate || (rate < 37500000) || (rate > 600000000))
+               return -EINVAL;
 
-                               if (rate_err < best_err) {
-                                       best_err = rate_err;
-                                       best_mul = mul;
-                                       best_div1 = div1;
-                                       best_div2 = div2;
-                               }
-                       }
+       *divisor2 = rate <= 75000000 ? 3 : rate <= 150000000 ? 2 :
+                                          rate <= 300000000 ? 1 : 0;
+       /*
+        * Divisor P cannot be calculated. Test all divisors and find where M
+        * will be as close as possible to the requested rate.
+        */
+       min_err = ULONG_MAX;
+       for (*divisor1 = 5; *divisor1 >= 3; (*divisor1)--) {
+               O1 = rate * *divisor1 * (1 << (*divisor2));
+               rate_err = O1 % parent_rate;
+               if (rate_err < min_err) {
+                       *multiplier = O1 / parent_rate;
+                       if (rate_err == 0)
+                               return 0;
+
+                       min_err = rate_err;
+               }
+       }
 
-       if (best_err == (unsigned long)-1) {
-               pr_warn("%s: impossible rate %lu\n", __func__, rate);
+       if ((*multiplier < 3) || (*multiplier > 1023))
                return -EINVAL;
-       }
 
-       /* if we got here, it wasn't an exact match */
-       pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
-                                                       rate - best_err);
-       *multiplier = best_mul;
-       *divisor1 = best_div1;
-       *divisor2 = best_div2;
+       pr_warn("%s: rate error is %lu\n", __func__, min_err);
 
        return 0;
 }
@@ -464,7 +462,6 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
 {
        u32 mul;
        int div1, div2;
-       u32 best_mul, best_div1, best_div2;
        unsigned long tclk, rate_err, best_err;
 
        best_err = (unsigned long)-1;
@@ -488,9 +485,9 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
 
                                if (rate_err < best_err) {
                                        best_err = rate_err;
-                                       best_mul = mul;
-                                       best_div1 = div1;
-                                       best_div2 = div2;
+                                       *multiplier = mul;
+                                       *divisor1 = div1;
+                                       *divisor2 = div2;
                                }
                        }
 
@@ -503,10 +500,7 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
        pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
                                                        rate - best_err);
 
-       *filter = wm8750_get_filter(parent_rate, best_div1);
-       *multiplier = best_mul;
-       *divisor1 = best_div1;
-       *divisor2 = best_div2;
+       *filter = wm8750_get_filter(parent_rate, *divisor1);
 
        return 0;
 }
@@ -516,7 +510,6 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
 {
        u32 mul;
        int div1, div2;
-       u32 best_mul, best_div1, best_div2;
        unsigned long tclk, rate_err, best_err;
 
        best_err = (unsigned long)-1;
@@ -540,9 +533,9 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
 
                                if (rate_err < best_err) {
                                        best_err = rate_err;
-                                       best_mul = mul;
-                                       best_div1 = div1;
-                                       best_div2 = div2;
+                                       *multiplier = mul;
+                                       *divisor1 = div1;
+                                       *divisor2 = div2;
                                }
                        }
 
@@ -555,10 +548,6 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
        pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
                                                        rate - best_err);
 
-       *multiplier = best_mul;
-       *divisor1 = best_div1;
-       *divisor2 = best_div2;
-
        return 0;
 }
 
index d584004f7af7d193d5f2646b482f26ce442deeef..820a939fb6bbf40dfada897360e83ecd43c285a6 100644 (file)
@@ -172,104 +172,6 @@ static bool clk_core_is_enabled(struct clk_core *core)
        return core->ops->is_enabled(core->hw);
 }
 
-static void clk_unprepare_unused_subtree(struct clk_core *core)
-{
-       struct clk_core *child;
-
-       lockdep_assert_held(&prepare_lock);
-
-       hlist_for_each_entry(child, &core->children, child_node)
-               clk_unprepare_unused_subtree(child);
-
-       if (core->prepare_count)
-               return;
-
-       if (core->flags & CLK_IGNORE_UNUSED)
-               return;
-
-       if (clk_core_is_prepared(core)) {
-               trace_clk_unprepare(core);
-               if (core->ops->unprepare_unused)
-                       core->ops->unprepare_unused(core->hw);
-               else if (core->ops->unprepare)
-                       core->ops->unprepare(core->hw);
-               trace_clk_unprepare_complete(core);
-       }
-}
-
-static void clk_disable_unused_subtree(struct clk_core *core)
-{
-       struct clk_core *child;
-       unsigned long flags;
-
-       lockdep_assert_held(&prepare_lock);
-
-       hlist_for_each_entry(child, &core->children, child_node)
-               clk_disable_unused_subtree(child);
-
-       flags = clk_enable_lock();
-
-       if (core->enable_count)
-               goto unlock_out;
-
-       if (core->flags & CLK_IGNORE_UNUSED)
-               goto unlock_out;
-
-       /*
-        * some gate clocks have special needs during the disable-unused
-        * sequence.  call .disable_unused if available, otherwise fall
-        * back to .disable
-        */
-       if (clk_core_is_enabled(core)) {
-               trace_clk_disable(core);
-               if (core->ops->disable_unused)
-                       core->ops->disable_unused(core->hw);
-               else if (core->ops->disable)
-                       core->ops->disable(core->hw);
-               trace_clk_disable_complete(core);
-       }
-
-unlock_out:
-       clk_enable_unlock(flags);
-}
-
-static bool clk_ignore_unused;
-static int __init clk_ignore_unused_setup(char *__unused)
-{
-       clk_ignore_unused = true;
-       return 1;
-}
-__setup("clk_ignore_unused", clk_ignore_unused_setup);
-
-static int clk_disable_unused(void)
-{
-       struct clk_core *core;
-
-       if (clk_ignore_unused) {
-               pr_warn("clk: Not disabling unused clocks\n");
-               return 0;
-       }
-
-       clk_prepare_lock();
-
-       hlist_for_each_entry(core, &clk_root_list, child_node)
-               clk_disable_unused_subtree(core);
-
-       hlist_for_each_entry(core, &clk_orphan_list, child_node)
-               clk_disable_unused_subtree(core);
-
-       hlist_for_each_entry(core, &clk_root_list, child_node)
-               clk_unprepare_unused_subtree(core);
-
-       hlist_for_each_entry(core, &clk_orphan_list, child_node)
-               clk_unprepare_unused_subtree(core);
-
-       clk_prepare_unlock();
-
-       return 0;
-}
-late_initcall_sync(clk_disable_unused);
-
 /***    helper functions   ***/
 
 const char *__clk_get_name(const struct clk *clk)
@@ -591,6 +493,13 @@ static void clk_core_unprepare(struct clk_core *core)
        clk_core_unprepare(core->parent);
 }
 
+static void clk_core_unprepare_lock(struct clk_core *core)
+{
+       clk_prepare_lock();
+       clk_core_unprepare(core);
+       clk_prepare_unlock();
+}
+
 /**
  * clk_unprepare - undo preparation of a clock source
  * @clk: the clk being unprepared
@@ -607,9 +516,7 @@ void clk_unprepare(struct clk *clk)
        if (IS_ERR_OR_NULL(clk))
                return;
 
-       clk_prepare_lock();
-       clk_core_unprepare(clk->core);
-       clk_prepare_unlock();
+       clk_core_unprepare_lock(clk->core);
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
@@ -645,6 +552,17 @@ static int clk_core_prepare(struct clk_core *core)
        return 0;
 }
 
+static int clk_core_prepare_lock(struct clk_core *core)
+{
+       int ret;
+
+       clk_prepare_lock();
+       ret = clk_core_prepare(core);
+       clk_prepare_unlock();
+
+       return ret;
+}
+
 /**
  * clk_prepare - prepare a clock source
  * @clk: the clk being prepared
@@ -659,16 +577,10 @@ static int clk_core_prepare(struct clk_core *core)
  */
 int clk_prepare(struct clk *clk)
 {
-       int ret;
-
        if (!clk)
                return 0;
 
-       clk_prepare_lock();
-       ret = clk_core_prepare(clk->core);
-       clk_prepare_unlock();
-
-       return ret;
+       return clk_core_prepare_lock(clk->core);
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
 
@@ -688,16 +600,25 @@ static void clk_core_disable(struct clk_core *core)
        if (--core->enable_count > 0)
                return;
 
-       trace_clk_disable(core);
+       trace_clk_disable_rcuidle(core);
 
        if (core->ops->disable)
                core->ops->disable(core->hw);
 
-       trace_clk_disable_complete(core);
+       trace_clk_disable_complete_rcuidle(core);
 
        clk_core_disable(core->parent);
 }
 
+static void clk_core_disable_lock(struct clk_core *core)
+{
+       unsigned long flags;
+
+       flags = clk_enable_lock();
+       clk_core_disable(core);
+       clk_enable_unlock(flags);
+}
+
 /**
  * clk_disable - gate a clock
  * @clk: the clk being gated
@@ -712,14 +633,10 @@ static void clk_core_disable(struct clk_core *core)
  */
 void clk_disable(struct clk *clk)
 {
-       unsigned long flags;
-
        if (IS_ERR_OR_NULL(clk))
                return;
 
-       flags = clk_enable_lock();
-       clk_core_disable(clk->core);
-       clk_enable_unlock(flags);
+       clk_core_disable_lock(clk->core);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
@@ -741,12 +658,12 @@ static int clk_core_enable(struct clk_core *core)
                if (ret)
                        return ret;
 
-               trace_clk_enable(core);
+               trace_clk_enable_rcuidle(core);
 
                if (core->ops->enable)
                        ret = core->ops->enable(core->hw);
 
-               trace_clk_enable_complete(core);
+               trace_clk_enable_complete_rcuidle(core);
 
                if (ret) {
                        clk_core_disable(core->parent);
@@ -758,6 +675,18 @@ static int clk_core_enable(struct clk_core *core)
        return 0;
 }
 
+static int clk_core_enable_lock(struct clk_core *core)
+{
+       unsigned long flags;
+       int ret;
+
+       flags = clk_enable_lock();
+       ret = clk_core_enable(core);
+       clk_enable_unlock(flags);
+
+       return ret;
+}
+
 /**
  * clk_enable - ungate a clock
  * @clk: the clk being ungated
@@ -773,19 +702,136 @@ static int clk_core_enable(struct clk_core *core)
  */
 int clk_enable(struct clk *clk)
 {
-       unsigned long flags;
-       int ret;
-
        if (!clk)
                return 0;
 
+       return clk_core_enable_lock(clk->core);
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+static int clk_core_prepare_enable(struct clk_core *core)
+{
+       int ret;
+
+       ret = clk_core_prepare_lock(core);
+       if (ret)
+               return ret;
+
+       ret = clk_core_enable_lock(core);
+       if (ret)
+               clk_core_unprepare_lock(core);
+
+       return ret;
+}
+
+static void clk_core_disable_unprepare(struct clk_core *core)
+{
+       clk_core_disable_lock(core);
+       clk_core_unprepare_lock(core);
+}
+
+static void clk_unprepare_unused_subtree(struct clk_core *core)
+{
+       struct clk_core *child;
+
+       lockdep_assert_held(&prepare_lock);
+
+       hlist_for_each_entry(child, &core->children, child_node)
+               clk_unprepare_unused_subtree(child);
+
+       if (core->prepare_count)
+               return;
+
+       if (core->flags & CLK_IGNORE_UNUSED)
+               return;
+
+       if (clk_core_is_prepared(core)) {
+               trace_clk_unprepare(core);
+               if (core->ops->unprepare_unused)
+                       core->ops->unprepare_unused(core->hw);
+               else if (core->ops->unprepare)
+                       core->ops->unprepare(core->hw);
+               trace_clk_unprepare_complete(core);
+       }
+}
+
+static void clk_disable_unused_subtree(struct clk_core *core)
+{
+       struct clk_core *child;
+       unsigned long flags;
+
+       lockdep_assert_held(&prepare_lock);
+
+       hlist_for_each_entry(child, &core->children, child_node)
+               clk_disable_unused_subtree(child);
+
+       if (core->flags & CLK_OPS_PARENT_ENABLE)
+               clk_core_prepare_enable(core->parent);
+
        flags = clk_enable_lock();
-       ret = clk_core_enable(clk->core);
+
+       if (core->enable_count)
+               goto unlock_out;
+
+       if (core->flags & CLK_IGNORE_UNUSED)
+               goto unlock_out;
+
+       /*
+        * some gate clocks have special needs during the disable-unused
+        * sequence.  call .disable_unused if available, otherwise fall
+        * back to .disable
+        */
+       if (clk_core_is_enabled(core)) {
+               trace_clk_disable(core);
+               if (core->ops->disable_unused)
+                       core->ops->disable_unused(core->hw);
+               else if (core->ops->disable)
+                       core->ops->disable(core->hw);
+               trace_clk_disable_complete(core);
+       }
+
+unlock_out:
        clk_enable_unlock(flags);
+       if (core->flags & CLK_OPS_PARENT_ENABLE)
+               clk_core_disable_unprepare(core->parent);
+}
 
-       return ret;
+static bool clk_ignore_unused;
+static int __init clk_ignore_unused_setup(char *__unused)
+{
+       clk_ignore_unused = true;
+       return 1;
 }
-EXPORT_SYMBOL_GPL(clk_enable);
+__setup("clk_ignore_unused", clk_ignore_unused_setup);
+
+static int clk_disable_unused(void)
+{
+       struct clk_core *core;
+
+       if (clk_ignore_unused) {
+               pr_warn("clk: Not disabling unused clocks\n");
+               return 0;
+       }
+
+       clk_prepare_lock();
+
+       hlist_for_each_entry(core, &clk_root_list, child_node)
+               clk_disable_unused_subtree(core);
+
+       hlist_for_each_entry(core, &clk_orphan_list, child_node)
+               clk_disable_unused_subtree(core);
+
+       hlist_for_each_entry(core, &clk_root_list, child_node)
+               clk_unprepare_unused_subtree(core);
+
+       hlist_for_each_entry(core, &clk_orphan_list, child_node)
+               clk_unprepare_unused_subtree(core);
+
+       clk_prepare_unlock();
+
+       return 0;
+}
+late_initcall_sync(clk_disable_unused);
 
 static int clk_core_round_rate_nolock(struct clk_core *core,
                                      struct clk_rate_request *req)
@@ -828,9 +874,7 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
 /**
  * __clk_determine_rate - get the closest rate actually supported by a clock
  * @hw: determine the rate of this clock
- * @rate: target rate
- * @min_rate: returned rate must be greater than this rate
- * @max_rate: returned rate must be less than this rate
+ * @req: target rate request
  *
  * Useful for clk_ops such as .set_rate and .determine_rate.
  */
@@ -1128,7 +1172,9 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core,
        struct clk_core *old_parent = core->parent;
 
        /*
-        * Migrate prepare state between parents and prevent race with
+        * 1. enable parents for CLK_OPS_PARENT_ENABLE clock
+        *
+        * 2. Migrate prepare state between parents and prevent race with
         * clk_enable().
         *
         * If the clock is not prepared, then a race with
@@ -1144,12 +1190,17 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core,
         *
         * See also: Comment for clk_set_parent() below.
         */
+
+       /* enable old_parent & parent if CLK_OPS_PARENT_ENABLE is set */
+       if (core->flags & CLK_OPS_PARENT_ENABLE) {
+               clk_core_prepare_enable(old_parent);
+               clk_core_prepare_enable(parent);
+       }
+
+       /* migrate prepare count if > 0 */
        if (core->prepare_count) {
-               clk_core_prepare(parent);
-               flags = clk_enable_lock();
-               clk_core_enable(parent);
-               clk_core_enable(core);
-               clk_enable_unlock(flags);
+               clk_core_prepare_enable(parent);
+               clk_core_enable_lock(core);
        }
 
        /* update the clk tree topology */
@@ -1164,18 +1215,19 @@ static void __clk_set_parent_after(struct clk_core *core,
                                   struct clk_core *parent,
                                   struct clk_core *old_parent)
 {
-       unsigned long flags;
-
        /*
         * Finish the migration of prepare state and undo the changes done
         * for preventing a race with clk_enable().
         */
        if (core->prepare_count) {
-               flags = clk_enable_lock();
-               clk_core_disable(core);
-               clk_core_disable(old_parent);
-               clk_enable_unlock(flags);
-               clk_core_unprepare(old_parent);
+               clk_core_disable_lock(core);
+               clk_core_disable_unprepare(old_parent);
+       }
+
+       /* re-balance ref counting if CLK_OPS_PARENT_ENABLE is set */
+       if (core->flags & CLK_OPS_PARENT_ENABLE) {
+               clk_core_disable_unprepare(parent);
+               clk_core_disable_unprepare(old_parent);
        }
 }
 
@@ -1422,13 +1474,17 @@ static void clk_change_rate(struct clk_core *core)
        unsigned long best_parent_rate = 0;
        bool skip_set_rate = false;
        struct clk_core *old_parent;
+       struct clk_core *parent = NULL;
 
        old_rate = core->rate;
 
-       if (core->new_parent)
+       if (core->new_parent) {
+               parent = core->new_parent;
                best_parent_rate = core->new_parent->rate;
-       else if (core->parent)
+       } else if (core->parent) {
+               parent = core->parent;
                best_parent_rate = core->parent->rate;
+       }
 
        if (core->flags & CLK_SET_RATE_UNGATE) {
                unsigned long flags;
@@ -1456,6 +1512,9 @@ static void clk_change_rate(struct clk_core *core)
                __clk_set_parent_after(core, core->new_parent, old_parent);
        }
 
+       if (core->flags & CLK_OPS_PARENT_ENABLE)
+               clk_core_prepare_enable(parent);
+
        trace_clk_set_rate(core, core->new_rate);
 
        if (!skip_set_rate && core->ops->set_rate)
@@ -1474,6 +1533,9 @@ static void clk_change_rate(struct clk_core *core)
                clk_core_unprepare(core);
        }
 
+       if (core->flags & CLK_OPS_PARENT_ENABLE)
+               clk_core_disable_unprepare(parent);
+
        if (core->notifier_count && old_rate != core->rate)
                __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
 
@@ -1501,7 +1563,6 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 {
        struct clk_core *top, *fail_clk;
        unsigned long rate = req_rate;
-       int ret = 0;
 
        if (!core)
                return 0;
@@ -1532,7 +1593,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 
        core->req_rate = req_rate;
 
-       return ret;
+       return 0;
 }
 
 /**
index 715c7301a66ab33cae34c3ee7260550b20de7f57..51b173ef1ddad864b34ba04ba37b608c74f6c609 100644 (file)
 
 #define HI3519_NR_CLKS         128
 
+struct hi3519_crg_data {
+       struct hisi_clock_data *clk_data;
+       struct hisi_reset_controller *rstc;
+};
+
 static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = {
        { HI3519_FIXED_24M, "24m", NULL, 0, 24000000, },
        { HI3519_FIXED_50M, "50m", NULL, 0, 50000000, },
@@ -80,33 +85,105 @@ static const struct hisi_gate_clock hi3519_gate_clks[] = {
                CLK_SET_RATE_PARENT, 0xe4, 18, 0, },
 };
 
-static int hi3519_clk_probe(struct platform_device *pdev)
+static struct hisi_clock_data *hi3519_clk_register(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
        struct hisi_clock_data *clk_data;
-       struct hisi_reset_controller *rstc;
+       int ret;
 
-       rstc = hisi_reset_init(np);
-       if (!rstc)
+       clk_data = hisi_clk_alloc(pdev, HI3519_NR_CLKS);
+       if (!clk_data)
+               return ERR_PTR(-ENOMEM);
+
+       ret = hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks,
+                                    ARRAY_SIZE(hi3519_fixed_rate_clks),
+                                    clk_data);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = hisi_clk_register_mux(hi3519_mux_clks,
+                               ARRAY_SIZE(hi3519_mux_clks),
+                               clk_data);
+       if (ret)
+               goto unregister_fixed_rate;
+
+       ret = hisi_clk_register_gate(hi3519_gate_clks,
+                               ARRAY_SIZE(hi3519_gate_clks),
+                               clk_data);
+       if (ret)
+               goto unregister_mux;
+
+       ret = of_clk_add_provider(pdev->dev.of_node,
+                       of_clk_src_onecell_get, &clk_data->clk_data);
+       if (ret)
+               goto unregister_gate;
+
+       return clk_data;
+
+unregister_fixed_rate:
+       hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks,
+                               ARRAY_SIZE(hi3519_fixed_rate_clks),
+                               clk_data);
+
+unregister_mux:
+       hisi_clk_unregister_mux(hi3519_mux_clks,
+                               ARRAY_SIZE(hi3519_mux_clks),
+                               clk_data);
+unregister_gate:
+       hisi_clk_unregister_gate(hi3519_gate_clks,
+                               ARRAY_SIZE(hi3519_gate_clks),
+                               clk_data);
+       return ERR_PTR(ret);
+}
+
+static void hi3519_clk_unregister(struct platform_device *pdev)
+{
+       struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
+
+       of_clk_del_provider(pdev->dev.of_node);
+
+       hisi_clk_unregister_gate(hi3519_gate_clks,
+                               ARRAY_SIZE(hi3519_mux_clks),
+                               crg->clk_data);
+       hisi_clk_unregister_mux(hi3519_mux_clks,
+                               ARRAY_SIZE(hi3519_mux_clks),
+                               crg->clk_data);
+       hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks,
+                               ARRAY_SIZE(hi3519_fixed_rate_clks),
+                               crg->clk_data);
+}
+
+static int hi3519_clk_probe(struct platform_device *pdev)
+{
+       struct hi3519_crg_data *crg;
+
+       crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+       if (!crg)
+               return -ENOMEM;
+
+       crg->rstc = hisi_reset_init(pdev);
+       if (!crg->rstc)
                return -ENOMEM;
 
-       clk_data = hisi_clk_init(np, HI3519_NR_CLKS);
-       if (!clk_data) {
-               hisi_reset_exit(rstc);
-               return -ENODEV;
+       crg->clk_data = hi3519_clk_register(pdev);
+       if (IS_ERR(crg->clk_data)) {
+               hisi_reset_exit(crg->rstc);
+               return PTR_ERR(crg->clk_data);
        }
 
-       hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks,
-                                    ARRAY_SIZE(hi3519_fixed_rate_clks),
-                                    clk_data);
-       hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks),
-                                       clk_data);
-       hisi_clk_register_gate(hi3519_gate_clks,
-                       ARRAY_SIZE(hi3519_gate_clks), clk_data);
+       platform_set_drvdata(pdev, crg);
+       return 0;
+}
+
+static int hi3519_clk_remove(struct platform_device *pdev)
+{
+       struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
 
+       hisi_reset_exit(crg->rstc);
+       hi3519_clk_unregister(pdev);
        return 0;
 }
 
+
 static const struct of_device_id hi3519_clk_match_table[] = {
        { .compatible = "hisilicon,hi3519-crg" },
        { }
@@ -115,6 +192,7 @@ MODULE_DEVICE_TABLE(of, hi3519_clk_match_table);
 
 static struct platform_driver hi3519_clk_driver = {
        .probe          = hi3519_clk_probe,
+       .remove         = hi3519_clk_remove,
        .driver         = {
                .name   = "hi3519-clk",
                .of_match_table = hi3519_clk_match_table,
@@ -127,5 +205,11 @@ static int __init hi3519_clk_init(void)
 }
 core_initcall(hi3519_clk_init);
 
+static void __exit hi3519_clk_exit(void)
+{
+       platform_driver_unregister(&hi3519_clk_driver);
+}
+module_exit(hi3519_clk_exit);
+
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver");
index f02cb41d40a44fb2a04eedc67cabd6e4b5a87b98..fe364e63f8de899867d2c6e8bb47394b8e871426 100644 (file)
@@ -34,8 +34,8 @@ static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
        { HI6220_PLL_BBP,       "bbppll0",      NULL, 0, 245760000, },
        { HI6220_PLL_GPU,       "gpupll",       NULL, 0, 1000000000,},
        { HI6220_PLL1_DDR,      "ddrpll1",      NULL, 0, 1066000000,},
-       { HI6220_PLL_SYS,       "syspll",       NULL, 0, 1200000000,},
-       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, 0, 1200000000,},
+       { HI6220_PLL_SYS,       "syspll",       NULL, 0, 1190400000,},
+       { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, 0, 1190400000,},
        { HI6220_DDR_SRC,       "ddr_sel_src",  NULL, 0, 1200000000,},
        { HI6220_PLL_MEDIA,     "media_pll",    NULL, 0, 1440000000,},
        { HI6220_PLL_DDR,       "ddrpll0",      NULL, 0, 1600000000,},
@@ -68,6 +68,8 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
        { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
        { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
        { HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
+       { HI6220_RTC0_PCLK,   "rtc0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 25, 0, },
+       { HI6220_RTC1_PCLK,   "rtc1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 26, 0, },
 };
 
 static void __init hi6220_clk_ao_init(struct device_node *np)
index 9b15adbfc30c3daa93f31785dffebf600b3f4659..9ba2d91f4d3a0d7e37660c866f49c753be0c3e7f 100644 (file)
 
 static DEFINE_SPINLOCK(hisi_clk_lock);
 
+struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
+                                               int nr_clks)
+{
+       struct hisi_clock_data *clk_data;
+       struct resource *res;
+       struct clk **clk_table;
+
+       clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
+       if (!clk_data)
+               return NULL;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       clk_data->base = devm_ioremap(&pdev->dev,
+                               res->start, resource_size(res));
+       if (!clk_data->base)
+               return NULL;
+
+       clk_table = devm_kmalloc(&pdev->dev, sizeof(struct clk *) * nr_clks,
+                               GFP_KERNEL);
+       if (!clk_table)
+               return NULL;
+
+       clk_data->clk_data.clks = clk_table;
+       clk_data->clk_data.clk_num = nr_clks;
+
+       return clk_data;
+}
+EXPORT_SYMBOL_GPL(hisi_clk_alloc);
+
 struct hisi_clock_data *hisi_clk_init(struct device_node *np,
                                             int nr_clks)
 {
@@ -73,7 +102,7 @@ err:
 }
 EXPORT_SYMBOL_GPL(hisi_clk_init);
 
-void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
+int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
                                         int nums, struct hisi_clock_data *data)
 {
        struct clk *clk;
@@ -87,14 +116,22 @@ void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
                if (IS_ERR(clk)) {
                        pr_err("%s: failed to register clock %s\n",
                               __func__, clks[i].name);
-                       continue;
+                       goto err;
                }
                data->clk_data.clks[clks[i].id] = clk;
        }
+
+       return 0;
+
+err:
+       while (i--)
+               clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
+
+       return PTR_ERR(clk);
 }
 EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
 
-void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
+int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
                                           int nums,
                                           struct hisi_clock_data *data)
 {
@@ -109,14 +146,22 @@ void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
                if (IS_ERR(clk)) {
                        pr_err("%s: failed to register clock %s\n",
                               __func__, clks[i].name);
-                       continue;
+                       goto err;
                }
                data->clk_data.clks[clks[i].id] = clk;
        }
+
+       return 0;
+
+err:
+       while (i--)
+               clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
+
+       return PTR_ERR(clk);
 }
 EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
 
-void hisi_clk_register_mux(const struct hisi_mux_clock *clks,
+int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
                                  int nums, struct hisi_clock_data *data)
 {
        struct clk *clk;
@@ -135,7 +180,7 @@ void hisi_clk_register_mux(const struct hisi_mux_clock *clks,
                if (IS_ERR(clk)) {
                        pr_err("%s: failed to register clock %s\n",
                               __func__, clks[i].name);
-                       continue;
+                       goto err;
                }
 
                if (clks[i].alias)
@@ -143,10 +188,18 @@ void hisi_clk_register_mux(const struct hisi_mux_clock *clks,
 
                data->clk_data.clks[clks[i].id] = clk;
        }
+
+       return 0;
+
+err:
+       while (i--)
+               clk_unregister_mux(data->clk_data.clks[clks[i].id]);
+
+       return PTR_ERR(clk);
 }
 EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
 
-void hisi_clk_register_divider(const struct hisi_divider_clock *clks,
+int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
                                      int nums, struct hisi_clock_data *data)
 {
        struct clk *clk;
@@ -165,7 +218,7 @@ void hisi_clk_register_divider(const struct hisi_divider_clock *clks,
                if (IS_ERR(clk)) {
                        pr_err("%s: failed to register clock %s\n",
                               __func__, clks[i].name);
-                       continue;
+                       goto err;
                }
 
                if (clks[i].alias)
@@ -173,10 +226,18 @@ void hisi_clk_register_divider(const struct hisi_divider_clock *clks,
 
                data->clk_data.clks[clks[i].id] = clk;
        }
+
+       return 0;
+
+err:
+       while (i--)
+               clk_unregister_divider(data->clk_data.clks[clks[i].id]);
+
+       return PTR_ERR(clk);
 }
 EXPORT_SYMBOL_GPL(hisi_clk_register_divider);
 
-void hisi_clk_register_gate(const struct hisi_gate_clock *clks,
+int hisi_clk_register_gate(const struct hisi_gate_clock *clks,
                                       int nums, struct hisi_clock_data *data)
 {
        struct clk *clk;
@@ -194,7 +255,7 @@ void hisi_clk_register_gate(const struct hisi_gate_clock *clks,
                if (IS_ERR(clk)) {
                        pr_err("%s: failed to register clock %s\n",
                               __func__, clks[i].name);
-                       continue;
+                       goto err;
                }
 
                if (clks[i].alias)
@@ -202,6 +263,14 @@ void hisi_clk_register_gate(const struct hisi_gate_clock *clks,
 
                data->clk_data.clks[clks[i].id] = clk;
        }
+
+       return 0;
+
+err:
+       while (i--)
+               clk_unregister_gate(data->clk_data.clks[clks[i].id]);
+
+       return PTR_ERR(clk);
 }
 EXPORT_SYMBOL_GPL(hisi_clk_register_gate);
 
index 20d64afe4ad8413b30c52383f24e82bafe3e9529..4e1d1affc6f548ea11d9d6d9ae610659310479b3 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/io.h>
 #include <linux/spinlock.h>
 
+struct platform_device;
+
 struct hisi_clock_data {
        struct clk_onecell_data clk_data;
        void __iomem            *base;
@@ -110,19 +112,41 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
        const char *parent_name, unsigned long flags, void __iomem *reg,
        u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
 
+struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int);
 struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
-void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *,
+int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *,
                                int, struct hisi_clock_data *);
-void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
+int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
                                int, struct hisi_clock_data *);
-void hisi_clk_register_mux(const struct hisi_mux_clock *, int,
+int hisi_clk_register_mux(const struct hisi_mux_clock *, int,
                                struct hisi_clock_data *);
-void hisi_clk_register_divider(const struct hisi_divider_clock *,
+int hisi_clk_register_divider(const struct hisi_divider_clock *,
                                int, struct hisi_clock_data *);
-void hisi_clk_register_gate(const struct hisi_gate_clock *,
+int hisi_clk_register_gate(const struct hisi_gate_clock *,
                                int, struct hisi_clock_data *);
 void hisi_clk_register_gate_sep(const struct hisi_gate_clock *,
                                int, struct hisi_clock_data *);
 void hi6220_clk_register_divider(const struct hi6220_divider_clock *,
                                int, struct hisi_clock_data *);
+
+#define hisi_clk_unregister(type) \
+static inline \
+void hisi_clk_unregister_##type(const struct hisi_##type##_clock *clks, \
+                               int nums, struct hisi_clock_data *data) \
+{ \
+       struct clk **clocks = data->clk_data.clks; \
+       int i; \
+       for (i = 0; i < nums; i++) { \
+               int id = clks[i].id; \
+               if (clocks[id])  \
+                       clk_unregister_##type(clocks[id]); \
+       } \
+}
+
+hisi_clk_unregister(fixed_rate)
+hisi_clk_unregister(fixed_factor)
+hisi_clk_unregister(mux)
+hisi_clk_unregister(divider)
+hisi_clk_unregister(gate)
+
 #endif /* __HISI_CLK_H */
index 113eee8ed23a04f90d00518c6436259f1bc58649..a1c1f684ad585bbc5d64f3b7954473d442197398 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/err.h>
 #include <linux/spinlock.h>
 
+#include "clk.h"
+
 #define div_mask(width)        ((1 << (width)) - 1)
 
 /**
index 6aa49c2204d0836da2faf86f17277f9581b88378..2a5015c736ce6d604d371c0bcd2a894d1ae4015f 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/io.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -98,25 +99,25 @@ static const struct reset_control_ops hisi_reset_ops = {
        .deassert       = hisi_reset_deassert,
 };
 
-struct hisi_reset_controller *hisi_reset_init(struct device_node *np)
+struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev)
 {
        struct hisi_reset_controller *rstc;
+       struct resource *res;
 
-       rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
+       rstc = devm_kmalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL);
        if (!rstc)
                return NULL;
 
-       rstc->membase = of_iomap(np, 0);
-       if (!rstc->membase) {
-               kfree(rstc);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rstc->membase = devm_ioremap(&pdev->dev,
+                               res->start, resource_size(res));
+       if (!rstc->membase)
                return NULL;
-       }
 
        spin_lock_init(&rstc->lock);
-
        rstc->rcdev.owner = THIS_MODULE;
        rstc->rcdev.ops = &hisi_reset_ops;
-       rstc->rcdev.of_node = np;
+       rstc->rcdev.of_node = pdev->dev.of_node;
        rstc->rcdev.of_reset_n_cells = 2;
        rstc->rcdev.of_xlate = hisi_reset_of_xlate;
        reset_controller_register(&rstc->rcdev);
@@ -128,7 +129,5 @@ EXPORT_SYMBOL_GPL(hisi_reset_init);
 void hisi_reset_exit(struct hisi_reset_controller *rstc)
 {
        reset_controller_unregister(&rstc->rcdev);
-       iounmap(rstc->membase);
-       kfree(rstc);
 }
 EXPORT_SYMBOL_GPL(hisi_reset_exit);
index 677d773ed27c09dc9a72b820bce47b5c743de7dc..9a69374a0b3287acee17457678366228caa24e98 100644 (file)
@@ -22,10 +22,11 @@ struct device_node;
 struct hisi_reset_controller;
 
 #ifdef CONFIG_RESET_CONTROLLER
-struct hisi_reset_controller *hisi_reset_init(struct device_node *np);
+struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev);
 void hisi_reset_exit(struct hisi_reset_controller *rstc);
 #else
-static inline hisi_reset_controller *hisi_reset_init(struct device_node *np)
+static inline
+struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev)
 {
        return 0;
 }
index 2beb396fe6523cb332ec369d6a65a1c7bf9d3e25..ba1c1ae72ac2af632953df98c5bcc9ef5c44799b 100644 (file)
@@ -192,13 +192,13 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
 
        /*                                    type               name    parent_name        base         div_mask */
-       clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
-       clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
-       clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", base + 0x10, 0x3);
-       clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
-       clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
-       clk[IMX6QDL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
-       clk[IMX6QDL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+       clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       clk[IMX6QDL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       clk[IMX6QDL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
 
        clk[IMX6QDL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
        clk[IMX6QDL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
index 1be6230a07af0fc2482250c9a48ba216cdcf1c3a..5fd4ddac1bf19cba71f16d95911e1a2e54218f0f 100644 (file)
@@ -218,13 +218,13 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
        clks[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
 
        /*                                    type               name    parent_name        base         div_mask */
-       clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
-       clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
-       clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", base + 0x10, 0x3);
-       clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
-       clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
-       clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
-       clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+       clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
 
        clks[IMX6SL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
        clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
index 97e742a8be174597b81ae1916cbf0ca3526b220f..b5c96de41ccf957b5f556794756545714d0a3528 100644 (file)
@@ -174,13 +174,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
        clks[IMX6SX_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
 
        /*                                    type               name    parent_name        base         div_mask */
-       clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
-       clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
-       clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", base + 0x10, 0x3);
-       clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
-       clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
-       clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
-       clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+       clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
 
        clks[IMX6SX_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
        clks[IMX6SX_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
index 0f1f17a8f3ed3e43cbb2d8b7834c1f2f6af8251c..d1d7787ce2113f8854619e69217edda89598a55f 100644 (file)
@@ -130,13 +130,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
        clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
 
-       clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
-       clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
-       clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", base + 0x10, 0x3);
-       clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
-       clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
-       clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
-       clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+       clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
 
        clks[IMX6UL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
        clks[IMX6UL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
@@ -305,8 +305,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_CAN1_SERIAL]    = imx_clk_gate2("can1_serial",  "can_podf",     base + 0x68,    16);
        clks[IMX6UL_CLK_CAN2_IPG]       = imx_clk_gate2("can2_ipg",     "ipg",          base + 0x68,    18);
        clks[IMX6UL_CLK_CAN2_SERIAL]    = imx_clk_gate2("can2_serial",  "can_podf",     base + 0x68,    20);
-       clks[IMX6UL_CLK_GPT2_BUS]       = imx_clk_gate2("gpt_bus",      "perclk",       base + 0x68,    24);
-       clks[IMX6UL_CLK_GPT2_SERIAL]    = imx_clk_gate2("gpt_serial",   "perclk",       base + 0x68,    26);
+       clks[IMX6UL_CLK_GPT2_BUS]       = imx_clk_gate2("gpt2_bus",     "perclk",       base + 0x68,    24);
+       clks[IMX6UL_CLK_GPT2_SERIAL]    = imx_clk_gate2("gpt2_serial",  "perclk",       base + 0x68,    26);
        clks[IMX6UL_CLK_UART2_IPG]      = imx_clk_gate2("uart2_ipg",    "ipg",          base + 0x68,    28);
        clks[IMX6UL_CLK_UART2_SERIAL]   = imx_clk_gate2("uart2_serial", "uart_podf",    base + 0x68,    28);
        clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",          base + 0x68,    30);
index 522996800d5bc55db0b84898a671d059a1fb7940..6ed4f8fa0667caf09e02f7e0a50b1e158c02577a 100644 (file)
@@ -65,7 +65,7 @@ static const char *dram_phym_sel[] = { "pll_dram_main_clk",
        "dram_phym_alt_clk", };
 
 static const char *dram_sel[] = { "pll_dram_main_clk",
-       "dram_alt_clk", };
+       "dram_alt_root_clk", };
 
 static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk",
        "pll_sys_main_clk", "pll_enet_500m_clk",
@@ -361,6 +361,14 @@ static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src
 static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", };
 static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", };
 
+static int const clks_init_on[] __initconst = {
+       IMX7D_ARM_A7_ROOT_CLK, IMX7D_MAIN_AXI_ROOT_CLK,
+       IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
+       IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
+       IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
+       IMX7D_AHB_CHANNEL_ROOT_CLK,
+};
+
 static struct clk_onecell_data clk_data;
 
 static struct clk ** const uart_clks[] __initconst = {
@@ -395,12 +403,12 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_PLL_AUDIO_MAIN_SRC] = imx_clk_mux("pll_audio_main_src", base + 0xf0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
        clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
 
-       clks[IMX7D_PLL_ARM_MAIN]  = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "pll_arm_main_src", base + 0x60, 0x7f);
-       clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_dram_main", "pll_dram_main_src", base + 0x70, 0x7f);
-       clks[IMX7D_PLL_SYS_MAIN]  = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "pll_sys_main_src", base + 0xb0, 0x1);
-       clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "pll_enet_main_src", base + 0xe0, 0x0);
-       clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "pll_audio_main_src", base + 0xf0, 0x7f);
-       clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "pll_video_main_src", base + 0x130, 0x7f);
+       clks[IMX7D_PLL_ARM_MAIN]  = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f);
+       clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "osc", base + 0x70, 0x7f);
+       clks[IMX7D_PLL_SYS_MAIN]  = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1);
+       clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0);
+       clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f);
+       clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "osc", base + 0x130, 0x7f);
 
        clks[IMX7D_PLL_ARM_MAIN_BYPASS]  = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT);
        clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT);
@@ -474,363 +482,363 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        base = of_iomap(np, 0);
        WARN_ON(!base);
 
-       clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel));
-       clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
-       clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel));
-       clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
-       clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
-       clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel));
-       clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel));
-       clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel));
-       clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel));
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel));
-       clks[IMX7D_DRAM_ALT_ROOT_SRC]  = imx_clk_mux("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel));
-       clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel));
-       clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
-       clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
-       clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
-       clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
-       clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux("mipi_dsi_src", base + 0xa380, 24, 3,  mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
-       clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
-       clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
-       clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel));
-       clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel));
-       clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel));
-       clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel));
-       clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel));
-       clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel));
-       clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel));
-       clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel));
-       clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel));
-       clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel));
-       clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel));
-       clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel));
-       clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel));
-       clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel));
-       clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel));
-       clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel));
-       clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel));
-       clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel));
-       clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel));
-       clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel));
-       clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel));
-       clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel));
-       clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel));
-       clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel));
-       clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel));
-       clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel));
-       clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel));
-       clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel));
-       clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel));
-       clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel));
-       clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel));
-       clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel));
-       clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel));
-       clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel));
-       clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel));
-       clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel));
-       clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel));
-       clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel));
-       clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel));
-       clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel));
-       clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel));
-       clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel));
-       clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel));
-       clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel));
-       clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel));
-       clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel));
-       clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel));
-       clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel));
-       clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel));
-       clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel));
-       clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel));
-
-       clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
-       clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
-       clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate("arm_m0_cg", "arm_m0_src", base + 0x8100, 28);
-       clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate("axi_cg", "axi_src", base + 0x8800, 28);
-       clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate("disp_axi_cg", "disp_axi_src", base + 0x8880, 28);
-       clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate("enet_axi_cg", "enet_axi_src", base + 0x8900, 28);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28);
-       clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate("ahb_cg", "ahb_src", base + 0x9000, 28);
-       clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate("dram_phym_cg", "dram_phym_src", base + 0x9800, 28);
-       clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate("dram_cg", "dram_src", base + 0x9880, 28);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28);
-       clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate("dram_alt_cg", "dram_alt_src", base + 0xa080, 28);
-       clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28);
-       clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28);
-       clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28);
-       clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28);
-       clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28);
-       clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28);
-       clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28);
-       clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate("sai1_cg", "sai1_src", base + 0xa500, 28);
-       clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate("sai2_cg", "sai2_src", base + 0xa580, 28);
-       clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate("sai3_cg", "sai3_src", base + 0xa600, 28);
-       clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate("spdif_cg", "spdif_src", base + 0xa680, 28);
-       clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28);
-       clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate("enet1_time_cg", "enet1_time_src", base + 0xa780, 28);
-       clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28);
-       clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate("enet2_time_cg", "enet2_time_src", base + 0xa880, 28);
-       clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28);
-       clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate("eim_cg", "eim_src", base + 0xa980, 28);
-       clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate("nand_cg", "nand_src", base + 0xaa00, 28);
-       clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate("qspi_cg", "qspi_src", base + 0xaa80, 28);
-       clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate("usdhc1_cg", "usdhc1_src", base + 0xab00, 28);
-       clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate("usdhc2_cg", "usdhc2_src", base + 0xab80, 28);
-       clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate("usdhc3_cg", "usdhc3_src", base + 0xac00, 28);
-       clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate("can1_cg", "can1_src", base + 0xac80, 28);
-       clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate("can2_cg", "can2_src", base + 0xad00, 28);
-       clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate("i2c1_cg", "i2c1_src", base + 0xad80, 28);
-       clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate("i2c2_cg", "i2c2_src", base + 0xae00, 28);
-       clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate("i2c3_cg", "i2c3_src", base + 0xae80, 28);
-       clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate("i2c4_cg", "i2c4_src", base + 0xaf00, 28);
-       clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate("uart1_cg", "uart1_src", base + 0xaf80, 28);
-       clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate("uart2_cg", "uart2_src", base + 0xb000, 28);
-       clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate("uart3_cg", "uart3_src", base + 0xb080, 28);
-       clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate("uart4_cg", "uart4_src", base + 0xb100, 28);
-       clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate("uart5_cg", "uart5_src", base + 0xb180, 28);
-       clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate("uart6_cg", "uart6_src", base + 0xb200, 28);
-       clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate("uart7_cg", "uart7_src", base + 0xb280, 28);
-       clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate("ecspi1_cg", "ecspi1_src", base + 0xb300, 28);
-       clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate("ecspi2_cg", "ecspi2_src", base + 0xb380, 28);
-       clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate("ecspi3_cg", "ecspi3_src", base + 0xb400, 28);
-       clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate("ecspi4_cg", "ecspi4_src", base + 0xb480, 28);
-       clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate("pwm1_cg", "pwm1_src", base + 0xb500, 28);
-       clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate("pwm2_cg", "pwm2_src", base + 0xb580, 28);
-       clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate("pwm3_cg", "pwm3_src", base + 0xb600, 28);
-       clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate("pwm4_cg", "pwm4_src", base + 0xb680, 28);
-       clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate("flextimer1_cg", "flextimer1_src", base + 0xb700, 28);
-       clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate("flextimer2_cg", "flextimer2_src", base + 0xb780, 28);
-       clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate("sim1_cg", "sim1_src", base + 0xb800, 28);
-       clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate("sim2_cg", "sim2_src", base + 0xb880, 28);
-       clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate("gpt1_cg", "gpt1_src", base + 0xb900, 28);
-       clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate("gpt2_cg", "gpt2_src", base + 0xb980, 28);
-       clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate("gpt3_cg", "gpt3_src", base + 0xbA00, 28);
-       clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate("gpt4_cg", "gpt4_src", base + 0xbA80, 28);
-       clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate("trace_cg", "trace_src", base + 0xbb00, 28);
-       clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate("wdog_cg", "wdog_src", base + 0xbb80, 28);
-       clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28);
-       clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28);
-       clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate("wrclk_cg", "wrclk_src", base + 0xbd00, 28);
-       clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate("clko1_cg", "clko1_src", base + 0xbd80, 28);
-       clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate("clko2_cg", "clko2_src", base + 0xbe00, 28);
-
-       clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider("axi_pre_div", "axi_cg", base + 0x8800, 16, 3);
-       clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3);
-       clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3);
-       clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3);
-       clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3);
-       clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3);
-       clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3);
-       clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3);
-       clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3);
-       clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3);
-       clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3);
-       clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3);
-       clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3);
-       clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3);
-       clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3);
-       clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3);
-       clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3);
-       clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3);
-       clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3);
-       clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3);
-       clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3);
-       clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider("eim_pre_div", "eim_cg", base + 0xa980, 16, 3);
-       clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3);
-       clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3);
-       clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3);
-       clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3);
-       clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3);
-       clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider("can1_pre_div", "can1_cg", base + 0xac80, 16, 3);
-       clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider("can2_pre_div", "can2_cg", base + 0xad00, 16, 3);
-       clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3);
-       clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3);
-       clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3);
-       clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3);
-       clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3);
-       clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3);
-       clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3);
-       clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3);
-       clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3);
-       clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3);
-       clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3);
-       clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3);
-       clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3);
-       clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3);
-       clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3);
-       clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3);
-       clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3);
-       clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3);
-       clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3);
-       clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3);
-       clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3);
-       clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3);
-       clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3);
-       clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3);
-       clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3);
-       clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3);
-       clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3);
-       clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3);
-       clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3);
-       clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3);
-       clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3);
-       clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3);
-       clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3);
-       clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3);
-
-       clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
-       clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
-       clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3);
-       clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
-       clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
-       clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
-       clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6);
-       clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
-       clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
-       clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6);
-       clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6);
-       clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6);
-       clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6);
-       clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6);
-       clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6);
-       clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6);
-       clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6);
-       clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6);
-       clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6);
-       clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6);
-       clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6);
-       clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6);
-       clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6);
-       clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6);
-       clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6);
-       clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6);
-       clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6);
-       clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6);
-       clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6);
-       clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6);
-       clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6);
-       clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6);
-       clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6);
-       clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6);
-       clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6);
-       clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6);
-       clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6);
-       clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6);
-       clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6);
-       clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6);
-       clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6);
-       clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6);
-       clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6);
-       clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6);
-       clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6);
-       clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6);
-       clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6);
-       clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6);
-       clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6);
-       clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6);
-       clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6);
-       clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6);
-       clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6);
-       clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6);
-       clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6);
-       clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6);
-       clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6);
-       clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6);
-       clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6);
-       clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6);
-       clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6);
-       clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6);
-       clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6);
-       clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6);
-       clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6);
-       clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
-       clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
-
-       clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
-       clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate2("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
-       clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate2("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0);
-       clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
-       clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate2("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
-       clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate2("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
-       clks[IMX7D_OCRAM_CLK] = imx_clk_gate2("ocram_clk", "axi_post_div", base + 0x4110, 0);
-       clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate2("ocram_s_clk", "ahb_post_div", base + 0x4120, 0);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate2("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
-       clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate2("ahb_root_clk", "ahb_post_div", base + 0x4200, 0);
-       clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2("dram_root_clk", "dram_post_div", base + 0x4130, 0);
-       clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
-       clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
-       clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate2("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0);
-       clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate2("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
-       clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate2("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0);
-       clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate2("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate2("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0);
-       clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate2("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0);
-       clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate2("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0);
-       clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate2("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0);
-       clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0);
-       clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0);
-       clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0);
-       clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate2("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0);
-       clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate2("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0);
-       clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate2("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0);
-       clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate2("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0);
-       clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0);
-       clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate2("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0);
-       clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate2("eim_root_clk", "eim_post_div", base + 0x4160, 0);
-       clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate2("nand_root_clk", "nand_post_div", base + 0x4140, 0);
-       clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate2("qspi_root_clk", "qspi_post_div", base + 0x4150, 0);
-       clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate2("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0);
-       clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate2("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);
-       clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate2("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0);
-       clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate2("can1_root_clk", "can1_post_div", base + 0x4740, 0);
-       clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate2("can2_root_clk", "can2_post_div", base + 0x4750, 0);
-       clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate2("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0);
-       clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate2("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0);
-       clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate2("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0);
-       clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate2("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0);
-       clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate2("uart1_root_clk", "uart1_post_div", base + 0x4940, 0);
-       clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate2("uart2_root_clk", "uart2_post_div", base + 0x4950, 0);
-       clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate2("uart3_root_clk", "uart3_post_div", base + 0x4960, 0);
-       clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate2("uart4_root_clk", "uart4_post_div", base + 0x4970, 0);
-       clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate2("uart5_root_clk", "uart5_post_div", base + 0x4980, 0);
-       clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate2("uart6_root_clk", "uart6_post_div", base + 0x4990, 0);
-       clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate2("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0);
-       clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate2("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0);
-       clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate2("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0);
-       clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate2("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0);
-       clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate2("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0);
-       clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate2("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0);
-       clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate2("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0);
-       clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate2("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0);
-       clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate2("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0);
-       clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate2("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0);
-       clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate2("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0);
-       clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate2("sim1_root_clk", "sim1_post_div", base + 0x4900, 0);
-       clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate2("sim2_root_clk", "sim2_post_div", base + 0x4910, 0);
-       clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate2("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0);
-       clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate2("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0);
-       clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate2("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0);
-       clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate2("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0);
-       clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate2("trace_root_clk", "trace_post_div", base + 0x4300, 0);
-       clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate2("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0);
-       clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate2("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0);
-       clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate2("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0);
-       clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate2("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0);
-       clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
-       clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
-       clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
-       clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate2("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
+       clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel));
+       clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
+       clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel));
+       clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
+       clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
+       clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
+       clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux2("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel));
+       clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux2("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel));
+       clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux2("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel));
+       clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel));
+       clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux2("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel));
+       clks[IMX7D_DRAM_ALT_ROOT_SRC]  = imx_clk_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel));
+       clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux2("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel));
+       clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
+       clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
+       clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
+       clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
+       clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux2("mipi_dsi_src", base + 0xa380, 24, 3,  mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
+       clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
+       clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
+       clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux2("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel));
+       clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux2("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel));
+       clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux2("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel));
+       clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux2("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel));
+       clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux2("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel));
+       clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux2("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel));
+       clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux2("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel));
+       clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux2("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel));
+       clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux2("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel));
+       clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux2("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel));
+       clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux2("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel));
+       clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux2("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel));
+       clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux2("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel));
+       clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux2("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel));
+       clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux2("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel));
+       clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux2("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel));
+       clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux2("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel));
+       clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux2("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel));
+       clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux2("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel));
+       clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux2("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel));
+       clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux2("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel));
+       clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux2("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel));
+       clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux2("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel));
+       clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux2("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel));
+       clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux2("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel));
+       clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux2("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel));
+       clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux2("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel));
+       clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux2("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel));
+       clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux2("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel));
+       clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux2("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel));
+       clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux2("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel));
+       clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux2("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel));
+       clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux2("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel));
+       clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux2("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel));
+       clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux2("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel));
+       clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux2("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel));
+       clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux2("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel));
+       clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux2("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel));
+       clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux2("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel));
+       clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux2("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel));
+       clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux2("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel));
+       clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux2("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel));
+       clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux2("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel));
+       clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux2("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel));
+       clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux2("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel));
+       clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux2("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel));
+       clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux2("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel));
+       clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux2("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel));
+       clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux2("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel));
+       clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux2("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel));
+       clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux2("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel));
+
+       clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
+       clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
+       clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28);
+       clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28);
+       clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28);
+       clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28);
+       clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate3("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28);
+       clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate3("ahb_cg", "ahb_src", base + 0x9000, 28);
+       clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate3("dram_phym_cg", "dram_phym_src", base + 0x9800, 28);
+       clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate3("dram_cg", "dram_src", base + 0x9880, 28);
+       clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate3("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28);
+       clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate3("dram_alt_cg", "dram_alt_src", base + 0xa080, 28);
+       clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate3("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28);
+       clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate3("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28);
+       clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate3("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28);
+       clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate3("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28);
+       clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate3("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28);
+       clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate3("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28);
+       clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate3("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28);
+       clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate3("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28);
+       clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate3("sai1_cg", "sai1_src", base + 0xa500, 28);
+       clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate3("sai2_cg", "sai2_src", base + 0xa580, 28);
+       clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate3("sai3_cg", "sai3_src", base + 0xa600, 28);
+       clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate3("spdif_cg", "spdif_src", base + 0xa680, 28);
+       clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate3("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28);
+       clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate3("enet1_time_cg", "enet1_time_src", base + 0xa780, 28);
+       clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate3("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28);
+       clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate3("enet2_time_cg", "enet2_time_src", base + 0xa880, 28);
+       clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate3("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28);
+       clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate3("eim_cg", "eim_src", base + 0xa980, 28);
+       clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate3("nand_cg", "nand_src", base + 0xaa00, 28);
+       clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate3("qspi_cg", "qspi_src", base + 0xaa80, 28);
+       clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate3("usdhc1_cg", "usdhc1_src", base + 0xab00, 28);
+       clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate3("usdhc2_cg", "usdhc2_src", base + 0xab80, 28);
+       clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate3("usdhc3_cg", "usdhc3_src", base + 0xac00, 28);
+       clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate3("can1_cg", "can1_src", base + 0xac80, 28);
+       clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate3("can2_cg", "can2_src", base + 0xad00, 28);
+       clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate3("i2c1_cg", "i2c1_src", base + 0xad80, 28);
+       clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate3("i2c2_cg", "i2c2_src", base + 0xae00, 28);
+       clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate3("i2c3_cg", "i2c3_src", base + 0xae80, 28);
+       clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate3("i2c4_cg", "i2c4_src", base + 0xaf00, 28);
+       clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate3("uart1_cg", "uart1_src", base + 0xaf80, 28);
+       clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate3("uart2_cg", "uart2_src", base + 0xb000, 28);
+       clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate3("uart3_cg", "uart3_src", base + 0xb080, 28);
+       clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate3("uart4_cg", "uart4_src", base + 0xb100, 28);
+       clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate3("uart5_cg", "uart5_src", base + 0xb180, 28);
+       clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate3("uart6_cg", "uart6_src", base + 0xb200, 28);
+       clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate3("uart7_cg", "uart7_src", base + 0xb280, 28);
+       clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate3("ecspi1_cg", "ecspi1_src", base + 0xb300, 28);
+       clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate3("ecspi2_cg", "ecspi2_src", base + 0xb380, 28);
+       clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate3("ecspi3_cg", "ecspi3_src", base + 0xb400, 28);
+       clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate3("ecspi4_cg", "ecspi4_src", base + 0xb480, 28);
+       clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate3("pwm1_cg", "pwm1_src", base + 0xb500, 28);
+       clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate3("pwm2_cg", "pwm2_src", base + 0xb580, 28);
+       clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate3("pwm3_cg", "pwm3_src", base + 0xb600, 28);
+       clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate3("pwm4_cg", "pwm4_src", base + 0xb680, 28);
+       clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate3("flextimer1_cg", "flextimer1_src", base + 0xb700, 28);
+       clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate3("flextimer2_cg", "flextimer2_src", base + 0xb780, 28);
+       clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate3("sim1_cg", "sim1_src", base + 0xb800, 28);
+       clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate3("sim2_cg", "sim2_src", base + 0xb880, 28);
+       clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate3("gpt1_cg", "gpt1_src", base + 0xb900, 28);
+       clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate3("gpt2_cg", "gpt2_src", base + 0xb980, 28);
+       clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate3("gpt3_cg", "gpt3_src", base + 0xbA00, 28);
+       clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate3("gpt4_cg", "gpt4_src", base + 0xbA80, 28);
+       clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate3("trace_cg", "trace_src", base + 0xbb00, 28);
+       clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate3("wdog_cg", "wdog_src", base + 0xbb80, 28);
+       clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate3("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28);
+       clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate3("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28);
+       clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate3("wrclk_cg", "wrclk_src", base + 0xbd00, 28);
+       clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate3("clko1_cg", "clko1_src", base + 0xbd80, 28);
+       clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate3("clko2_cg", "clko2_src", base + 0xbe00, 28);
+
+       clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider2("axi_pre_div", "axi_cg", base + 0x8800, 16, 3);
+       clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider2("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3);
+       clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider2("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3);
+       clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider2("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3);
+       clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider2("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3);
+       clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3);
+       clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3);
+       clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider2("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3);
+       clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider2("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3);
+       clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider2("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3);
+       clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3);
+       clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3);
+       clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3);
+       clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3);
+       clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3);
+       clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider2("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3);
+       clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider2("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3);
+       clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider2("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3);
+       clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider2("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3);
+       clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3);
+       clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3);
+       clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3);
+       clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3);
+       clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3);
+       clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider2("eim_pre_div", "eim_cg", base + 0xa980, 16, 3);
+       clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider2("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3);
+       clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider2("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3);
+       clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider2("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3);
+       clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider2("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3);
+       clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider2("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3);
+       clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider2("can1_pre_div", "can1_cg", base + 0xac80, 16, 3);
+       clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider2("can2_pre_div", "can2_cg", base + 0xad00, 16, 3);
+       clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider2("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3);
+       clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider2("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3);
+       clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider2("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3);
+       clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider2("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3);
+       clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider2("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3);
+       clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider2("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3);
+       clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider2("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3);
+       clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider2("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3);
+       clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider2("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3);
+       clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider2("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3);
+       clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider2("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3);
+       clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider2("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3);
+       clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider2("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3);
+       clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider2("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3);
+       clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider2("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3);
+       clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider2("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3);
+       clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider2("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3);
+       clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider2("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3);
+       clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider2("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3);
+       clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider2("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3);
+       clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider2("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3);
+       clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider2("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3);
+       clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider2("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3);
+       clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider2("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3);
+       clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider2("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3);
+       clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider2("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3);
+       clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider2("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3);
+       clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider2("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3);
+       clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider2("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3);
+       clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3);
+       clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3);
+       clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider2("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3);
+       clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider2("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3);
+       clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider2("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3);
+
+       clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
+       clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
+       clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3);
+       clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
+       clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
+       clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
+       clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
+       clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6);
+       clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
+       clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
+       clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
+       clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider2("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6);
+       clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider2("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6);
+       clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider2("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6);
+       clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider2("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6);
+       clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider2("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6);
+       clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider2("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6);
+       clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider2("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6);
+       clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider2("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6);
+       clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider2("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6);
+       clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider2("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6);
+       clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider2("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6);
+       clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider2("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6);
+       clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider2("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6);
+       clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider2("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6);
+       clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider2("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6);
+       clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider2("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6);
+       clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider2("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6);
+       clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider2("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6);
+       clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider2("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6);
+       clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider2("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6);
+       clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider2("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6);
+       clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider2("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6);
+       clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider2("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6);
+       clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider2("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6);
+       clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider2("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6);
+       clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider2("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6);
+       clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider2("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6);
+       clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider2("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6);
+       clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider2("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6);
+       clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider2("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6);
+       clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider2("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6);
+       clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider2("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6);
+       clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider2("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6);
+       clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider2("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6);
+       clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider2("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6);
+       clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider2("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6);
+       clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider2("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6);
+       clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider2("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6);
+       clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider2("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6);
+       clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider2("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6);
+       clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider2("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6);
+       clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider2("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6);
+       clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider2("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6);
+       clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider2("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6);
+       clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider2("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6);
+       clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider2("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6);
+       clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider2("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6);
+       clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider2("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6);
+       clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider2("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6);
+       clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider2("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6);
+       clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider2("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6);
+       clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider2("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6);
+       clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider2("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6);
+       clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider2("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6);
+       clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider2("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6);
+       clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider2("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6);
+       clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider2("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6);
+       clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
+       clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
+
+       clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
+       clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
+       clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0);
+       clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
+       clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
+       clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
+       clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0);
+       clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0);
+       clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
+       clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0);
+       clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
+       clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
+       clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
+       clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
+       clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0);
+       clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
+       clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0);
+       clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate4("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0);
+       clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate4("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0);
+       clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate4("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0);
+       clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate4("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0);
+       clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate4("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0);
+       clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate4("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0);
+       clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate4("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0);
+       clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate4("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0);
+       clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate4("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0);
+       clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate4("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0);
+       clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate4("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0);
+       clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate4("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0);
+       clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate4("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0);
+       clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate4("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0);
+       clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0);
+       clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate4("nand_root_clk", "nand_post_div", base + 0x4140, 0);
+       clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0);
+       clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0);
+       clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);
+       clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate4("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0);
+       clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate4("can1_root_clk", "can1_post_div", base + 0x4740, 0);
+       clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate4("can2_root_clk", "can2_post_div", base + 0x4750, 0);
+       clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate4("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0);
+       clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate4("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0);
+       clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate4("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0);
+       clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate4("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0);
+       clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate4("uart1_root_clk", "uart1_post_div", base + 0x4940, 0);
+       clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate4("uart2_root_clk", "uart2_post_div", base + 0x4950, 0);
+       clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate4("uart3_root_clk", "uart3_post_div", base + 0x4960, 0);
+       clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate4("uart4_root_clk", "uart4_post_div", base + 0x4970, 0);
+       clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate4("uart5_root_clk", "uart5_post_div", base + 0x4980, 0);
+       clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate4("uart6_root_clk", "uart6_post_div", base + 0x4990, 0);
+       clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate4("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0);
+       clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate4("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0);
+       clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate4("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0);
+       clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate4("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0);
+       clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate4("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0);
+       clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate4("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0);
+       clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate4("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0);
+       clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate4("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0);
+       clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate4("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0);
+       clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate4("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0);
+       clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate4("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0);
+       clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate4("sim1_root_clk", "sim1_post_div", base + 0x4900, 0);
+       clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate4("sim2_root_clk", "sim2_post_div", base + 0x4910, 0);
+       clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate4("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0);
+       clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate4("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0);
+       clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate4("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0);
+       clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate4("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0);
+       clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate4("trace_root_clk", "trace_post_div", base + 0x4300, 0);
+       clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate4("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0);
+       clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate4("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0);
+       clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate4("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0);
+       clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0);
+       clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
+       clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
+       clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
+       clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
 
        clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
 
@@ -846,28 +854,13 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clk_data.clk_num = ARRAY_SIZE(clks);
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-       /* TO BE FIXED LATER
-        * Enable all clock to bring up imx7, otherwise system will be halt and block
-        * the other part upstream Because imx7d clock design changed, clock framework
-        * need do a little modify.
-        * Dong Aisheng is working on this. After that, this part need be changed.
-        */
-       for (i = 0; i < IMX7D_CLK_END; i++)
-               clk_prepare_enable(clks[i]);
+       for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+               clk_prepare_enable(clks[clks_init_on[i]]);
 
        /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */
        clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
 
-       /*
-        * init enet clock source:
-        *      AXI clock source is 250MHz
-        *      Phy refrence clock is 25MHz
-        *      1588 time clock source is 100MHz
-        */
        clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]);
-       clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_25M_CLK]);
-       clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
-       clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
 
        /* set uart module clock's parent clock source that must be great then 80MHz */
        clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
index 4826b3c9e19ed7f24b248cedc7da5050b1bfebf0..19f9b622981a5281bc375a756d437cc117c63640 100644 (file)
@@ -29,8 +29,8 @@
  * struct clk_pllv3 - IMX PLL clock version 3
  * @clk_hw:     clock source
  * @base:       base address of PLL registers
- * @powerup_set: set POWER bit to power up the PLL
- * @powerdown:   pll powerdown offset bit
+ * @power_bit:  pll power bit mask
+ * @powerup_set: set power_bit to power up the PLL
  * @div_mask:   mask of divider bits
  * @div_shift:  shift of divider bits
  *
@@ -40,8 +40,8 @@
 struct clk_pllv3 {
        struct clk_hw   hw;
        void __iomem    *base;
+       u32             power_bit;
        bool            powerup_set;
-       u32             powerdown;
        u32             div_mask;
        u32             div_shift;
        unsigned long   ref_clock;
@@ -52,7 +52,7 @@ struct clk_pllv3 {
 static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
 {
        unsigned long timeout = jiffies + msecs_to_jiffies(10);
-       u32 val = readl_relaxed(pll->base) & pll->powerdown;
+       u32 val = readl_relaxed(pll->base) & pll->power_bit;
 
        /* No need to wait for lock when pll is not powered up */
        if ((pll->powerup_set && !val) || (!pll->powerup_set && val))
@@ -77,9 +77,9 @@ static int clk_pllv3_prepare(struct clk_hw *hw)
 
        val = readl_relaxed(pll->base);
        if (pll->powerup_set)
-               val |= BM_PLL_POWER;
+               val |= pll->power_bit;
        else
-               val &= ~BM_PLL_POWER;
+               val &= ~pll->power_bit;
        writel_relaxed(val, pll->base);
 
        return clk_pllv3_wait_lock(pll);
@@ -92,9 +92,9 @@ static void clk_pllv3_unprepare(struct clk_hw *hw)
 
        val = readl_relaxed(pll->base);
        if (pll->powerup_set)
-               val &= ~BM_PLL_POWER;
+               val &= ~pll->power_bit;
        else
-               val |= BM_PLL_POWER;
+               val |= pll->power_bit;
        writel_relaxed(val, pll->base);
 }
 
@@ -218,8 +218,12 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
        u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
        u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
        u32 div = readl_relaxed(pll->base) & pll->div_mask;
+       u64 temp64 = (u64)parent_rate;
 
-       return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+       temp64 *= mfn;
+       do_div(temp64, mfd);
+
+       return (parent_rate * div) + (u32)temp64;
 }
 
 static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -243,7 +247,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
        do_div(temp64, parent_rate);
        mfn = temp64;
 
-       return parent_rate * div + parent_rate / mfd * mfn;
+       return parent_rate * div + parent_rate * mfn / mfd;
 }
 
 static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -312,7 +316,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
        if (!pll)
                return ERR_PTR(-ENOMEM);
 
-       pll->powerdown = BM_PLL_POWER;
+       pll->power_bit = BM_PLL_POWER;
 
        switch (type) {
        case IMX_PLLV3_SYS:
@@ -328,7 +332,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
                ops = &clk_pllv3_av_ops;
                break;
        case IMX_PLLV3_ENET_IMX7:
-               pll->powerdown = IMX7_ENET_PLL_POWER;
+               pll->power_bit = IMX7_ENET_PLL_POWER;
                pll->ref_clock = 1000000000;
                ops = &clk_pllv3_enet_ops;
                break;
index 3a1f24475ee4af56b2329eadb0e9ce38b85b4d8a..0476353ab423f38155a4ed1c83e6b29af479c011 100644 (file)
@@ -315,12 +315,12 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 
        clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7));
 
-       clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7));
-       clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8));
-       clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9));
-       clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10));
-       clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9));
-       clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10));
+       clk[VF610_CLK_UART0] = imx_clk_gate2_cgr("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7), 0x2);
+       clk[VF610_CLK_UART1] = imx_clk_gate2_cgr("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8), 0x2);
+       clk[VF610_CLK_UART2] = imx_clk_gate2_cgr("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9), 0x2);
+       clk[VF610_CLK_UART3] = imx_clk_gate2_cgr("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10), 0x2);
+       clk[VF610_CLK_UART4] = imx_clk_gate2_cgr("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9), 0x2);
+       clk[VF610_CLK_UART5] = imx_clk_gate2_cgr("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10), 0x2);
 
        clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
        clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7));
index 508d0fad84cf0744d7a7d4c73d8ba748be03a09f..a81c0385ed646c1eb81535c7620d9646ff8132fd 100644 (file)
@@ -51,28 +51,6 @@ struct clk * imx_obtain_fixed_clock(
 struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
         void __iomem *reg, u8 shift, u32 exclusive_mask);
 
-static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
-               void __iomem *reg, u8 shift)
-{
-       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, 0x3, 0, &imx_ccm_lock, NULL);
-}
-
-static inline struct clk *imx_clk_gate2_shared(const char *name,
-               const char *parent, void __iomem *reg, u8 shift,
-               unsigned int *share_count)
-{
-       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, 0x3, 0, &imx_ccm_lock, share_count);
-}
-
-static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent,
-               void __iomem *reg, u8 shift, u8 cgr_val)
-{
-       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, cgr_val, 0, &imx_ccm_lock, NULL);
-}
-
 struct clk *imx_clk_pfd(const char *name, const char *parent_name,
                void __iomem *reg, u8 idx);
 
@@ -97,6 +75,13 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate)
        return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
+static inline struct clk *imx_clk_fixed_factor(const char *name,
+               const char *parent, unsigned int mult, unsigned int div)
+{
+       return clk_register_fixed_factor(NULL, name, parent,
+                       CLK_SET_RATE_PARENT, mult, div);
+}
+
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
                void __iomem *reg, u8 shift, u8 width)
 {
@@ -112,6 +97,14 @@ static inline struct clk *imx_clk_divider_flags(const char *name,
                        reg, shift, width, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_divider2(const char *name, const char *parent,
+               void __iomem *reg, u8 shift, u8 width)
+{
+       return clk_register_divider(NULL, name, parent,
+                       CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+                       reg, shift, width, 0, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
                void __iomem *reg, u8 shift)
 {
@@ -126,6 +119,44 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
                        shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
+               void __iomem *reg, u8 shift)
+{
+       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+                       shift, 0x3, 0, &imx_ccm_lock, NULL);
+}
+
+static inline struct clk *imx_clk_gate2_shared(const char *name,
+               const char *parent, void __iomem *reg, u8 shift,
+               unsigned int *share_count)
+{
+       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+                       shift, 0x3, 0, &imx_ccm_lock, share_count);
+}
+
+static inline struct clk *imx_clk_gate2_cgr(const char *name,
+               const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
+{
+       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+                       shift, cgr_val, 0, &imx_ccm_lock, NULL);
+}
+
+static inline struct clk *imx_clk_gate3(const char *name, const char *parent,
+               void __iomem *reg, u8 shift)
+{
+       return clk_register_gate(NULL, name, parent,
+                       CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+                       reg, shift, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
+               void __iomem *reg, u8 shift)
+{
+       return clk_register_gate2(NULL, name, parent,
+                       CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+                       reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
+}
+
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
                u8 shift, u8 width, const char **parents, int num_parents)
 {
@@ -134,6 +165,14 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
                        width, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
+               u8 shift, u8 width, const char **parents, int num_parents)
+{
+       return clk_register_mux(NULL, name, parents, num_parents,
+                       CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE,
+                       reg, shift, width, 0, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_mux_flags(const char *name,
                void __iomem *reg, u8 shift, u8 width, const char **parents,
                int num_parents, unsigned long flags)
@@ -143,13 +182,6 @@ static inline struct clk *imx_clk_mux_flags(const char *name,
                        &imx_ccm_lock);
 }
 
-static inline struct clk *imx_clk_fixed_factor(const char *name,
-               const char *parent, unsigned int mult, unsigned int div)
-{
-       return clk_register_fixed_factor(NULL, name, parent,
-                       CLK_SET_RATE_PARENT, mult, div);
-}
-
 struct clk *imx_clk_cpu(const char *name, const char *parent_name,
                struct clk *div, struct clk *mux, struct clk *pll,
                struct clk *step);
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
new file mode 100644 (file)
index 0000000..19480bc
--- /dev/null
@@ -0,0 +1,19 @@
+config COMMON_CLK_AMLOGIC
+       bool
+       depends on OF
+       depends on ARCH_MESON || COMPILE_TEST
+
+config COMMON_CLK_MESON8B
+       bool
+       depends on COMMON_CLK_AMLOGIC
+       help
+         Support for the clock controller on AmLogic S805 devices, aka
+         meson8b. Say Y if you want peripherals and CPU frequency scaling to
+         work.
+
+config COMMON_CLK_GXBB
+       bool
+       depends on COMMON_CLK_AMLOGIC
+       help
+         Support for the clock controller on AmLogic S905 devices, aka gxbb.
+         Say Y if you want peripherals and CPU frequency scaling to work.
index 6d45531df9abf1355ca437511f9d580aff5d7f7f..197e40175166831a97a4a9f55f38fb571b306d99 100644 (file)
@@ -2,5 +2,6 @@
 # Makefile for Meson specific clk
 #
 
-obj-y += clkc.o clk-pll.o clk-cpu.o
-obj-y += meson8b-clkc.o
+obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
+obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o
+obj-$(CONFIG_COMMON_CLK_GXBB)   += gxbb.o
index f7c30ea54ca8d85625b8bc33c5c772dd2700e0dd..f8b2b7efd0161ee2cea918ee395fdd9c7e49522c 100644 (file)
 
 #include "clkc.h"
 
-struct meson_clk_cpu {
-       struct notifier_block           clk_nb;
-       const struct clk_div_table      *div_table;
-       struct clk_hw                   hw;
-       void __iomem                    *base;
-       u16                             reg_off;
-};
 #define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
 #define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
 
@@ -119,6 +112,7 @@ static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
        return parent_rate / div;
 }
 
+/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
 static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
                                         struct clk_notifier_data *ndata)
 {
@@ -140,6 +134,7 @@ static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
        return 0;
 }
 
+/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
 static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
                                          struct clk_notifier_data *ndata)
 {
@@ -161,7 +156,7 @@ static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
  * PLL clock is to be changed. We use the xtal input as temporary parent
  * while the PLL frequency is stabilized.
  */
-static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
+int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
                                     unsigned long event, void *data)
 {
        struct clk_notifier_data *ndata = data;
@@ -176,68 +171,8 @@ static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
        return notifier_from_errno(ret);
 }
 
-static const struct clk_ops meson_clk_cpu_ops = {
+const struct clk_ops meson_clk_cpu_ops = {
        .recalc_rate    = meson_clk_cpu_recalc_rate,
        .round_rate     = meson_clk_cpu_round_rate,
        .set_rate       = meson_clk_cpu_set_rate,
 };
-
-struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
-                                  void __iomem *reg_base,
-                                  spinlock_t *lock)
-{
-       struct clk *clk;
-       struct clk *pclk;
-       struct meson_clk_cpu *clk_cpu;
-       struct clk_init_data init;
-       int ret;
-
-       clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
-       if (!clk_cpu)
-               return ERR_PTR(-ENOMEM);
-
-       clk_cpu->base = reg_base;
-       clk_cpu->reg_off = clk_conf->reg_off;
-       clk_cpu->div_table = clk_conf->conf.div_table;
-       clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;
-
-       init.name = clk_conf->clk_name;
-       init.ops = &meson_clk_cpu_ops;
-       init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
-       init.flags |= CLK_SET_RATE_PARENT;
-       init.parent_names = clk_conf->clks_parent;
-       init.num_parents = 1;
-
-       clk_cpu->hw.init = &init;
-
-       pclk = __clk_lookup(clk_conf->clks_parent[0]);
-       if (!pclk) {
-               pr_err("%s: could not lookup parent clock %s\n",
-                               __func__, clk_conf->clks_parent[0]);
-               ret = -EINVAL;
-               goto free_clk;
-       }
-
-       ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
-       if (ret) {
-               pr_err("%s: failed to register clock notifier for %s\n",
-                               __func__, clk_conf->clk_name);
-               goto free_clk;
-       }
-
-       clk = clk_register(NULL, &clk_cpu->hw);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               goto unregister_clk_nb;
-       }
-
-       return clk;
-
-unregister_clk_nb:
-       clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
-free_clk:
-       kfree(clk_cpu);
-
-       return ERR_PTR(ret);
-}
-
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
new file mode 100644 (file)
index 0000000..03af790
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 AmLogic, Inc.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 AmLogic, Inc.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * MultiPhase Locked Loops are outputs from a PLL with additional frequency
+ * scaling capabilities. MPLL rates are calculated as:
+ *
+ * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
+ */
+
+#include <linux/clk-provider.h>
+#include "clkc.h"
+
+#define SDM_MAX 16384
+
+#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
+
+static unsigned long mpll_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p;
+       unsigned long rate = 0;
+       unsigned long reg, sdm, n2;
+
+       p = &mpll->sdm;
+       reg = readl(mpll->base + p->reg_off);
+       sdm = PARM_GET(p->width, p->shift, reg);
+
+       p = &mpll->n2;
+       reg = readl(mpll->base + p->reg_off);
+       n2 = PARM_GET(p->width, p->shift, reg);
+
+       rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
+
+       return rate;
+}
+
+const struct clk_ops meson_clk_mpll_ro_ops = {
+       .recalc_rate = mpll_recalc_rate,
+};
index 664edf0708ea712ad677415904e3361ae5026e6e..4adc1e89212c9a944587117ee8d1a8b9eae63d4d 100644 (file)
 #define MESON_PLL_RESET                                BIT(29)
 #define MESON_PLL_LOCK                         BIT(31)
 
-struct meson_clk_pll {
-       struct clk_hw   hw;
-       void __iomem    *base;
-       struct pll_conf *conf;
-       unsigned int    rate_count;
-       spinlock_t      *lock;
-};
 #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
 
 static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@@ -60,22 +53,36 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
        struct parm *p;
        unsigned long parent_rate_mhz = parent_rate / 1000000;
        unsigned long rate_mhz;
-       u16 n, m, od;
+       u16 n, m, frac = 0, od, od2 = 0;
        u32 reg;
 
-       p = &pll->conf->n;
+       p = &pll->n;
        reg = readl(pll->base + p->reg_off);
        n = PARM_GET(p->width, p->shift, reg);
 
-       p = &pll->conf->m;
+       p = &pll->m;
        reg = readl(pll->base + p->reg_off);
        m = PARM_GET(p->width, p->shift, reg);
 
-       p = &pll->conf->od;
+       p = &pll->od;
        reg = readl(pll->base + p->reg_off);
        od = PARM_GET(p->width, p->shift, reg);
 
-       rate_mhz = (parent_rate_mhz * m / n) >> od;
+       p = &pll->od2;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               od2 = PARM_GET(p->width, p->shift, reg);
+       }
+
+       p = &pll->frac;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               frac = PARM_GET(p->width, p->shift, reg);
+               rate_mhz = (parent_rate_mhz * m + \
+                               (parent_rate_mhz * frac >> 12)) * 2 / n;
+               rate_mhz = rate_mhz >> od >> od2;
+       } else
+               rate_mhz = (parent_rate_mhz * m / n) >> od >> od2;
 
        return rate_mhz * 1000000;
 }
@@ -84,7 +91,7 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                                     unsigned long *parent_rate)
 {
        struct meson_clk_pll *pll = to_meson_clk_pll(hw);
-       const struct pll_rate_table *rate_table = pll->conf->rate_table;
+       const struct pll_rate_table *rate_table = pll->rate_table;
        int i;
 
        for (i = 0; i < pll->rate_count; i++) {
@@ -99,7 +106,7 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
                                                               unsigned long rate)
 {
-       const struct pll_rate_table *rate_table = pll->conf->rate_table;
+       const struct pll_rate_table *rate_table = pll->rate_table;
        int i;
 
        for (i = 0; i < pll->rate_count; i++) {
@@ -145,24 +152,38 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                return -EINVAL;
 
        /* PLL reset */
-       p = &pll->conf->n;
+       p = &pll->n;
        reg = readl(pll->base + p->reg_off);
        writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
 
        reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
        writel(reg, pll->base + p->reg_off);
 
-       p = &pll->conf->m;
+       p = &pll->m;
        reg = readl(pll->base + p->reg_off);
        reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
        writel(reg, pll->base + p->reg_off);
 
-       p = &pll->conf->od;
+       p = &pll->od;
        reg = readl(pll->base + p->reg_off);
        reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
        writel(reg, pll->base + p->reg_off);
 
-       p = &pll->conf->n;
+       p = &pll->od2;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               reg = PARM_SET(p->width, p->shift, reg, rate_set->od2);
+               writel(reg, pll->base + p->reg_off);
+       }
+
+       p = &pll->frac;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               reg = PARM_SET(p->width, p->shift, reg, rate_set->frac);
+               writel(reg, pll->base + p->reg_off);
+       }
+
+       p = &pll->n;
        ret = meson_clk_pll_wait_lock(pll, p);
        if (ret) {
                pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
@@ -173,55 +194,12 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        return ret;
 }
 
-static const struct clk_ops meson_clk_pll_ops = {
+const struct clk_ops meson_clk_pll_ops = {
        .recalc_rate    = meson_clk_pll_recalc_rate,
        .round_rate     = meson_clk_pll_round_rate,
        .set_rate       = meson_clk_pll_set_rate,
 };
 
-static const struct clk_ops meson_clk_pll_ro_ops = {
+const struct clk_ops meson_clk_pll_ro_ops = {
        .recalc_rate    = meson_clk_pll_recalc_rate,
 };
-
-struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
-                                  void __iomem *reg_base,
-                                  spinlock_t *lock)
-{
-       struct clk *clk;
-       struct meson_clk_pll *clk_pll;
-       struct clk_init_data init;
-
-       clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
-       if (!clk_pll)
-               return ERR_PTR(-ENOMEM);
-
-       clk_pll->base = reg_base + clk_conf->reg_off;
-       clk_pll->lock = lock;
-       clk_pll->conf = clk_conf->conf.pll;
-
-       init.name = clk_conf->clk_name;
-       init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
-
-       init.parent_names = &clk_conf->clks_parent[0];
-       init.num_parents = 1;
-       init.ops = &meson_clk_pll_ro_ops;
-
-       /* If no rate_table is specified we assume the PLL is read-only */
-       if (clk_pll->conf->rate_table) {
-               int len;
-
-               for (len = 0; clk_pll->conf->rate_table[len].rate != 0; )
-                       len++;
-
-                clk_pll->rate_count = len;
-                init.ops = &meson_clk_pll_ops;
-       }
-
-       clk_pll->hw.init = &init;
-
-       clk = clk_register(NULL, &clk_pll->hw);
-       if (IS_ERR(clk))
-               kfree(clk_pll);
-
-       return clk;
-}
diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
deleted file mode 100644 (file)
index d920d41..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2015 Endless Mobile, Inc.
- * Author: Carlo Caione <carlo@endlessm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/clk-provider.h>
-#include <linux/mfd/syscon.h>
-#include <linux/slab.h>
-
-#include "clkc.h"
-
-static DEFINE_SPINLOCK(clk_lock);
-
-static struct clk **clks;
-static struct clk_onecell_data clk_data;
-
-struct clk ** __init meson_clk_init(struct device_node *np,
-                                  unsigned long nr_clks)
-{
-       clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
-       if (!clks)
-               return ERR_PTR(-ENOMEM);
-
-       clk_data.clks = clks;
-       clk_data.clk_num = nr_clks;
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-
-       return clks;
-}
-
-static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
-{
-       if (clks && id)
-               clks[id] = clk;
-}
-
-static struct clk * __init
-meson_clk_register_composite(const struct clk_conf *clk_conf,
-                            void __iomem *clk_base)
-{
-       struct clk *clk;
-       struct clk_mux *mux = NULL;
-       struct clk_divider *div = NULL;
-       struct clk_gate *gate = NULL;
-       const struct clk_ops *mux_ops = NULL;
-       const struct composite_conf *composite_conf;
-
-       composite_conf = clk_conf->conf.composite;
-
-       if (clk_conf->num_parents > 1) {
-               mux = kzalloc(sizeof(*mux), GFP_KERNEL);
-               if (!mux)
-                       return ERR_PTR(-ENOMEM);
-
-               mux->reg = clk_base + clk_conf->reg_off
-                               + composite_conf->mux_parm.reg_off;
-               mux->shift = composite_conf->mux_parm.shift;
-               mux->mask = BIT(composite_conf->mux_parm.width) - 1;
-               mux->flags = composite_conf->mux_flags;
-               mux->lock = &clk_lock;
-               mux->table = composite_conf->mux_table;
-               mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
-                         &clk_mux_ro_ops : &clk_mux_ops;
-       }
-
-       if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
-               div = kzalloc(sizeof(*div), GFP_KERNEL);
-               if (!div) {
-                       clk = ERR_PTR(-ENOMEM);
-                       goto error;
-               }
-
-               div->reg = clk_base + clk_conf->reg_off
-                               + composite_conf->div_parm.reg_off;
-               div->shift = composite_conf->div_parm.shift;
-               div->width = composite_conf->div_parm.width;
-               div->lock = &clk_lock;
-               div->flags = composite_conf->div_flags;
-               div->table = composite_conf->div_table;
-       }
-
-       if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
-               gate = kzalloc(sizeof(*gate), GFP_KERNEL);
-               if (!gate) {
-                       clk = ERR_PTR(-ENOMEM);
-                       goto error;
-               }
-
-               gate->reg = clk_base + clk_conf->reg_off
-                               + composite_conf->div_parm.reg_off;
-               gate->bit_idx = composite_conf->gate_parm.shift;
-               gate->flags = composite_conf->gate_flags;
-               gate->lock = &clk_lock;
-       }
-
-       clk = clk_register_composite(NULL, clk_conf->clk_name,
-                                   clk_conf->clks_parent,
-                                   clk_conf->num_parents,
-                                   mux ? &mux->hw : NULL, mux_ops,
-                                   div ? &div->hw : NULL, &clk_divider_ops,
-                                   gate ? &gate->hw : NULL, &clk_gate_ops,
-                                   clk_conf->flags);
-       if (IS_ERR(clk))
-               goto error;
-
-       return clk;
-
-error:
-       kfree(gate);
-       kfree(div);
-       kfree(mux);
-
-       return clk;
-}
-
-static struct clk * __init
-meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
-                               void __iomem *clk_base)
-{
-       struct clk *clk;
-       const struct fixed_fact_conf *fixed_fact_conf;
-       const struct parm *p;
-       unsigned int mult, div;
-       u32 reg;
-
-       fixed_fact_conf = &clk_conf->conf.fixed_fact;
-
-       mult = clk_conf->conf.fixed_fact.mult;
-       div = clk_conf->conf.fixed_fact.div;
-
-       if (!mult) {
-               mult = 1;
-               p = &fixed_fact_conf->mult_parm;
-               if (MESON_PARM_APPLICABLE(p)) {
-                       reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
-                       mult = PARM_GET(p->width, p->shift, reg);
-               }
-       }
-
-       if (!div) {
-               div = 1;
-               p = &fixed_fact_conf->div_parm;
-               if (MESON_PARM_APPLICABLE(p)) {
-                       reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
-                       mult = PARM_GET(p->width, p->shift, reg);
-               }
-       }
-
-       clk = clk_register_fixed_factor(NULL,
-                       clk_conf->clk_name,
-                       clk_conf->clks_parent[0],
-                       clk_conf->flags,
-                       mult, div);
-
-       return clk;
-}
-
-static struct clk * __init
-meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
-                             void __iomem *clk_base)
-{
-       struct clk *clk;
-       const struct fixed_rate_conf *fixed_rate_conf;
-       const struct parm *r;
-       unsigned long rate;
-       u32 reg;
-
-       fixed_rate_conf = &clk_conf->conf.fixed_rate;
-       rate = fixed_rate_conf->rate;
-
-       if (!rate) {
-               r = &fixed_rate_conf->rate_parm;
-               reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
-               rate = PARM_GET(r->width, r->shift, reg);
-       }
-
-       rate *= 1000000;
-
-       clk = clk_register_fixed_rate(NULL,
-                       clk_conf->clk_name,
-                       clk_conf->num_parents
-                               ? clk_conf->clks_parent[0] : NULL,
-                       clk_conf->flags, rate);
-
-       return clk;
-}
-
-void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
-                                   unsigned int nr_confs,
-                                   void __iomem *clk_base)
-{
-       unsigned int i;
-       struct clk *clk = NULL;
-
-       for (i = 0; i < nr_confs; i++) {
-               const struct clk_conf *clk_conf = &clk_confs[i];
-
-               switch (clk_conf->clk_type) {
-               case CLK_FIXED_RATE:
-                       clk = meson_clk_register_fixed_rate(clk_conf,
-                                                           clk_base);
-                       break;
-               case CLK_FIXED_FACTOR:
-                       clk = meson_clk_register_fixed_factor(clk_conf,
-                                                             clk_base);
-                       break;
-               case CLK_COMPOSITE:
-                       clk = meson_clk_register_composite(clk_conf,
-                                                          clk_base);
-                       break;
-               case CLK_CPU:
-                       clk = meson_clk_register_cpu(clk_conf, clk_base,
-                                                    &clk_lock);
-                       break;
-               case CLK_PLL:
-                       clk = meson_clk_register_pll(clk_conf, clk_base,
-                                                    &clk_lock);
-                       break;
-               default:
-                       clk = NULL;
-               }
-
-               if (!clk) {
-                       pr_err("%s: unknown clock type %d\n", __func__,
-                              clk_conf->clk_type);
-                       continue;
-               }
-
-               if (IS_ERR(clk)) {
-                       pr_warn("%s: Unable to create %s clock\n", __func__,
-                               clk_conf->clk_name);
-                       continue;
-               }
-
-               meson_clk_add_lookup(clk, clk_conf->clk_id);
-       }
-}
index 609ae92cc13f16e2cc292a513ff2f5c06ee48fe4..53326c32e8532a1cef69243653281d9a665cf4c3 100644 (file)
@@ -34,19 +34,16 @@ struct parm {
        u8      shift;
        u8      width;
 };
-#define PARM(_r, _s, _w)                                               \
-       {                                                               \
-               .reg_off        = (_r),                                 \
-               .shift          = (_s),                                 \
-               .width          = (_w),                                 \
-       }                                                               \
 
 struct pll_rate_table {
        unsigned long   rate;
        u16             m;
        u16             n;
        u16             od;
+       u16             od2;
+       u16             frac;
 };
+
 #define PLL_RATE(_r, _m, _n, _od)                                      \
        {                                                               \
                .rate           = (_r),                                 \
@@ -55,133 +52,69 @@ struct pll_rate_table {
                .od             = (_od),                                \
        }                                                               \
 
-struct pll_conf {
-       const struct pll_rate_table     *rate_table;
-       struct parm                     m;
-       struct parm                     n;
-       struct parm                     od;
-};
+#define PLL_FRAC_RATE(_r, _m, _n, _od, _od2, _frac)                    \
+       {                                                               \
+               .rate           = (_r),                                 \
+               .m              = (_m),                                 \
+               .n              = (_n),                                 \
+               .od             = (_od),                                \
+               .od2            = (_od2),                               \
+               .frac           = (_frac),                              \
+       }                                                               \
 
-struct fixed_fact_conf {
-       unsigned int    div;
-       unsigned int    mult;
-       struct parm     div_parm;
-       struct parm     mult_parm;
+struct meson_clk_pll {
+       struct clk_hw hw;
+       void __iomem *base;
+       struct parm m;
+       struct parm n;
+       struct parm frac;
+       struct parm od;
+       struct parm od2;
+       const struct pll_rate_table *rate_table;
+       unsigned int rate_count;
+       spinlock_t *lock;
 };
 
-struct fixed_rate_conf {
-       unsigned long   rate;
-       struct parm     rate_parm;
-};
+#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
 
-struct composite_conf {
-       struct parm             mux_parm;
-       struct parm             div_parm;
-       struct parm             gate_parm;
-       struct clk_div_table    *div_table;
-       u32                     *mux_table;
-       u8                      mux_flags;
-       u8                      div_flags;
-       u8                      gate_flags;
+struct meson_clk_cpu {
+       struct clk_hw hw;
+       void __iomem *base;
+       u16 reg_off;
+       struct notifier_block clk_nb;
+       const struct clk_div_table *div_table;
 };
 
-#define PNAME(x) static const char *x[]
+int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event,
+               void *data);
 
-enum clk_type {
-       CLK_FIXED_FACTOR,
-       CLK_FIXED_RATE,
-       CLK_COMPOSITE,
-       CLK_CPU,
-       CLK_PLL,
+struct meson_clk_mpll {
+       struct clk_hw hw;
+       void __iomem *base;
+       struct parm sdm;
+       struct parm n2;
+       /* FIXME ssen gate control? */
+       spinlock_t *lock;
 };
 
-struct clk_conf {
-       u16                             reg_off;
-       enum clk_type                   clk_type;
-       unsigned int                    clk_id;
-       const char                      *clk_name;
-       const char                      **clks_parent;
-       int                             num_parents;
-       unsigned long                   flags;
-       union {
-               struct fixed_fact_conf          fixed_fact;
-               struct fixed_rate_conf          fixed_rate;
-               const struct composite_conf             *composite;
-               struct pll_conf                 *pll;
-               const struct clk_div_table      *div_table;
-       } conf;
+#define MESON_GATE(_name, _reg, _bit)                                  \
+struct clk_gate gxbb_##_name = {                                               \
+       .reg = (void __iomem *) _reg,                                   \
+       .bit_idx = (_bit),                                              \
+       .lock = &clk_lock,                                              \
+       .hw.init = &(struct clk_init_data) {                            \
+               .name = #_name,                                 \
+               .ops = &clk_gate_ops,                                   \
+               .parent_names = (const char *[]){ "clk81" },            \
+               .num_parents = 1,                                       \
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
+       },                                                              \
 };
 
-#define FIXED_RATE_P(_ro, _ci, _cn, _f, _c)                            \
-       {                                                               \
-               .reg_off                        = (_ro),                \
-               .clk_type                       = CLK_FIXED_RATE,       \
-               .clk_id                         = (_ci),                \
-               .clk_name                       = (_cn),                \
-               .flags                          = (_f),                 \
-               .conf.fixed_rate.rate_parm      = _c,                   \
-       }                                                               \
-
-#define FIXED_RATE(_ci, _cn, _f, _r)                                   \
-       {                                                               \
-               .clk_type                       = CLK_FIXED_RATE,       \
-               .clk_id                         = (_ci),                \
-               .clk_name                       = (_cn),                \
-               .flags                          = (_f),                 \
-               .conf.fixed_rate.rate           = (_r),                 \
-       }                                                               \
-
-#define PLL(_ro, _ci, _cn, _cp, _f, _c)                                        \
-       {                                                               \
-               .reg_off                        = (_ro),                \
-               .clk_type                       = CLK_PLL,              \
-               .clk_id                         = (_ci),                \
-               .clk_name                       = (_cn),                \
-               .clks_parent                    = (_cp),                \
-               .num_parents                    = ARRAY_SIZE(_cp),      \
-               .flags                          = (_f),                 \
-               .conf.pll                       = (_c),                 \
-       }                                                               \
-
-#define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d)                                \
-       {                                                               \
-               .clk_type                       = CLK_FIXED_FACTOR,     \
-               .clk_id                         = (_ci),                \
-               .clk_name                       = (_cn),                \
-               .clks_parent                    = (_cp),                \
-               .num_parents                    = ARRAY_SIZE(_cp),      \
-               .conf.fixed_fact.div            = (_d),                 \
-       }                                                               \
-
-#define CPU(_ro, _ci, _cn, _cp, _dt)                                   \
-       {                                                               \
-               .reg_off                        = (_ro),                \
-               .clk_type                       = CLK_CPU,              \
-               .clk_id                         = (_ci),                \
-               .clk_name                       = (_cn),                \
-               .clks_parent                    = (_cp),                \
-               .num_parents                    = ARRAY_SIZE(_cp),      \
-               .conf.div_table                 = (_dt),                \
-       }                                                               \
-
-#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c)                          \
-       {                                                               \
-               .reg_off                        = (_ro),                \
-               .clk_type                       = CLK_COMPOSITE,        \
-               .clk_id                         = (_ci),                \
-               .clk_name                       = (_cn),                \
-               .clks_parent                    = (_cp),                \
-               .num_parents                    = ARRAY_SIZE(_cp),      \
-               .flags                          = (_f),                 \
-               .conf.composite                 = (_c),                 \
-       }                                                               \
-
-struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
-void meson_clk_register_clks(const struct clk_conf *clk_confs,
-                            unsigned int nr_confs, void __iomem *clk_base);
-struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
-                                  void __iomem *reg_base, spinlock_t *lock);
-struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
-                                  void __iomem *reg_base, spinlock_t *lock);
+/* clk_ops */
+extern const struct clk_ops meson_clk_pll_ro_ops;
+extern const struct clk_ops meson_clk_pll_ops;
+extern const struct clk_ops meson_clk_cpu_ops;
+extern const struct clk_ops meson_clk_mpll_ro_ops;
 
 #endif /* __CLKC_H */
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
new file mode 100644 (file)
index 0000000..a4c6684
--- /dev/null
@@ -0,0 +1,944 @@
+/*
+ * AmLogic S905 / GXBB Clock Controller Driver
+ *
+ * Copyright (c) 2016 AmLogic, Inc.
+ * Michael Turquette <mturquette@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+
+#include "clkc.h"
+#include "gxbb.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static const struct pll_rate_table sys_pll_rate_table[] = {
+       PLL_RATE(24000000, 56, 1, 2),
+       PLL_RATE(48000000, 64, 1, 2),
+       PLL_RATE(72000000, 72, 1, 2),
+       PLL_RATE(96000000, 64, 1, 2),
+       PLL_RATE(120000000, 80, 1, 2),
+       PLL_RATE(144000000, 96, 1, 2),
+       PLL_RATE(168000000, 56, 1, 1),
+       PLL_RATE(192000000, 64, 1, 1),
+       PLL_RATE(216000000, 72, 1, 1),
+       PLL_RATE(240000000, 80, 1, 1),
+       PLL_RATE(264000000, 88, 1, 1),
+       PLL_RATE(288000000, 96, 1, 1),
+       PLL_RATE(312000000, 52, 1, 2),
+       PLL_RATE(336000000, 56, 1, 2),
+       PLL_RATE(360000000, 60, 1, 2),
+       PLL_RATE(384000000, 64, 1, 2),
+       PLL_RATE(408000000, 68, 1, 2),
+       PLL_RATE(432000000, 72, 1, 2),
+       PLL_RATE(456000000, 76, 1, 2),
+       PLL_RATE(480000000, 80, 1, 2),
+       PLL_RATE(504000000, 84, 1, 2),
+       PLL_RATE(528000000, 88, 1, 2),
+       PLL_RATE(552000000, 92, 1, 2),
+       PLL_RATE(576000000, 96, 1, 2),
+       PLL_RATE(600000000, 50, 1, 1),
+       PLL_RATE(624000000, 52, 1, 1),
+       PLL_RATE(648000000, 54, 1, 1),
+       PLL_RATE(672000000, 56, 1, 1),
+       PLL_RATE(696000000, 58, 1, 1),
+       PLL_RATE(720000000, 60, 1, 1),
+       PLL_RATE(744000000, 62, 1, 1),
+       PLL_RATE(768000000, 64, 1, 1),
+       PLL_RATE(792000000, 66, 1, 1),
+       PLL_RATE(816000000, 68, 1, 1),
+       PLL_RATE(840000000, 70, 1, 1),
+       PLL_RATE(864000000, 72, 1, 1),
+       PLL_RATE(888000000, 74, 1, 1),
+       PLL_RATE(912000000, 76, 1, 1),
+       PLL_RATE(936000000, 78, 1, 1),
+       PLL_RATE(960000000, 80, 1, 1),
+       PLL_RATE(984000000, 82, 1, 1),
+       PLL_RATE(1008000000, 84, 1, 1),
+       PLL_RATE(1032000000, 86, 1, 1),
+       PLL_RATE(1056000000, 88, 1, 1),
+       PLL_RATE(1080000000, 90, 1, 1),
+       PLL_RATE(1104000000, 92, 1, 1),
+       PLL_RATE(1128000000, 94, 1, 1),
+       PLL_RATE(1152000000, 96, 1, 1),
+       PLL_RATE(1176000000, 98, 1, 1),
+       PLL_RATE(1200000000, 50, 1, 0),
+       PLL_RATE(1224000000, 51, 1, 0),
+       PLL_RATE(1248000000, 52, 1, 0),
+       PLL_RATE(1272000000, 53, 1, 0),
+       PLL_RATE(1296000000, 54, 1, 0),
+       PLL_RATE(1320000000, 55, 1, 0),
+       PLL_RATE(1344000000, 56, 1, 0),
+       PLL_RATE(1368000000, 57, 1, 0),
+       PLL_RATE(1392000000, 58, 1, 0),
+       PLL_RATE(1416000000, 59, 1, 0),
+       PLL_RATE(1440000000, 60, 1, 0),
+       PLL_RATE(1464000000, 61, 1, 0),
+       PLL_RATE(1488000000, 62, 1, 0),
+       PLL_RATE(1512000000, 63, 1, 0),
+       PLL_RATE(1536000000, 64, 1, 0),
+       PLL_RATE(1560000000, 65, 1, 0),
+       PLL_RATE(1584000000, 66, 1, 0),
+       PLL_RATE(1608000000, 67, 1, 0),
+       PLL_RATE(1632000000, 68, 1, 0),
+       PLL_RATE(1656000000, 68, 1, 0),
+       PLL_RATE(1680000000, 68, 1, 0),
+       PLL_RATE(1704000000, 68, 1, 0),
+       PLL_RATE(1728000000, 69, 1, 0),
+       PLL_RATE(1752000000, 69, 1, 0),
+       PLL_RATE(1776000000, 69, 1, 0),
+       PLL_RATE(1800000000, 69, 1, 0),
+       PLL_RATE(1824000000, 70, 1, 0),
+       PLL_RATE(1848000000, 70, 1, 0),
+       PLL_RATE(1872000000, 70, 1, 0),
+       PLL_RATE(1896000000, 70, 1, 0),
+       PLL_RATE(1920000000, 71, 1, 0),
+       PLL_RATE(1944000000, 71, 1, 0),
+       PLL_RATE(1968000000, 71, 1, 0),
+       PLL_RATE(1992000000, 71, 1, 0),
+       PLL_RATE(2016000000, 72, 1, 0),
+       PLL_RATE(2040000000, 72, 1, 0),
+       PLL_RATE(2064000000, 72, 1, 0),
+       PLL_RATE(2088000000, 72, 1, 0),
+       PLL_RATE(2112000000, 73, 1, 0),
+       { /* sentinel */ },
+};
+
+static const struct pll_rate_table gp0_pll_rate_table[] = {
+       PLL_RATE(96000000, 32, 1, 3),
+       PLL_RATE(99000000, 33, 1, 3),
+       PLL_RATE(102000000, 34, 1, 3),
+       PLL_RATE(105000000, 35, 1, 3),
+       PLL_RATE(108000000, 36, 1, 3),
+       PLL_RATE(111000000, 37, 1, 3),
+       PLL_RATE(114000000, 38, 1, 3),
+       PLL_RATE(117000000, 39, 1, 3),
+       PLL_RATE(120000000, 40, 1, 3),
+       PLL_RATE(123000000, 41, 1, 3),
+       PLL_RATE(126000000, 42, 1, 3),
+       PLL_RATE(129000000, 43, 1, 3),
+       PLL_RATE(132000000, 44, 1, 3),
+       PLL_RATE(135000000, 45, 1, 3),
+       PLL_RATE(138000000, 46, 1, 3),
+       PLL_RATE(141000000, 47, 1, 3),
+       PLL_RATE(144000000, 48, 1, 3),
+       PLL_RATE(147000000, 49, 1, 3),
+       PLL_RATE(150000000, 50, 1, 3),
+       PLL_RATE(153000000, 51, 1, 3),
+       PLL_RATE(156000000, 52, 1, 3),
+       PLL_RATE(159000000, 53, 1, 3),
+       PLL_RATE(162000000, 54, 1, 3),
+       PLL_RATE(165000000, 55, 1, 3),
+       PLL_RATE(168000000, 56, 1, 3),
+       PLL_RATE(171000000, 57, 1, 3),
+       PLL_RATE(174000000, 58, 1, 3),
+       PLL_RATE(177000000, 59, 1, 3),
+       PLL_RATE(180000000, 60, 1, 3),
+       PLL_RATE(183000000, 61, 1, 3),
+       PLL_RATE(186000000, 62, 1, 3),
+       PLL_RATE(192000000, 32, 1, 2),
+       PLL_RATE(198000000, 33, 1, 2),
+       PLL_RATE(204000000, 34, 1, 2),
+       PLL_RATE(210000000, 35, 1, 2),
+       PLL_RATE(216000000, 36, 1, 2),
+       PLL_RATE(222000000, 37, 1, 2),
+       PLL_RATE(228000000, 38, 1, 2),
+       PLL_RATE(234000000, 39, 1, 2),
+       PLL_RATE(240000000, 40, 1, 2),
+       PLL_RATE(246000000, 41, 1, 2),
+       PLL_RATE(252000000, 42, 1, 2),
+       PLL_RATE(258000000, 43, 1, 2),
+       PLL_RATE(264000000, 44, 1, 2),
+       PLL_RATE(270000000, 45, 1, 2),
+       PLL_RATE(276000000, 46, 1, 2),
+       PLL_RATE(282000000, 47, 1, 2),
+       PLL_RATE(288000000, 48, 1, 2),
+       PLL_RATE(294000000, 49, 1, 2),
+       PLL_RATE(300000000, 50, 1, 2),
+       PLL_RATE(306000000, 51, 1, 2),
+       PLL_RATE(312000000, 52, 1, 2),
+       PLL_RATE(318000000, 53, 1, 2),
+       PLL_RATE(324000000, 54, 1, 2),
+       PLL_RATE(330000000, 55, 1, 2),
+       PLL_RATE(336000000, 56, 1, 2),
+       PLL_RATE(342000000, 57, 1, 2),
+       PLL_RATE(348000000, 58, 1, 2),
+       PLL_RATE(354000000, 59, 1, 2),
+       PLL_RATE(360000000, 60, 1, 2),
+       PLL_RATE(366000000, 61, 1, 2),
+       PLL_RATE(372000000, 62, 1, 2),
+       PLL_RATE(384000000, 32, 1, 1),
+       PLL_RATE(396000000, 33, 1, 1),
+       PLL_RATE(408000000, 34, 1, 1),
+       PLL_RATE(420000000, 35, 1, 1),
+       PLL_RATE(432000000, 36, 1, 1),
+       PLL_RATE(444000000, 37, 1, 1),
+       PLL_RATE(456000000, 38, 1, 1),
+       PLL_RATE(468000000, 39, 1, 1),
+       PLL_RATE(480000000, 40, 1, 1),
+       PLL_RATE(492000000, 41, 1, 1),
+       PLL_RATE(504000000, 42, 1, 1),
+       PLL_RATE(516000000, 43, 1, 1),
+       PLL_RATE(528000000, 44, 1, 1),
+       PLL_RATE(540000000, 45, 1, 1),
+       PLL_RATE(552000000, 46, 1, 1),
+       PLL_RATE(564000000, 47, 1, 1),
+       PLL_RATE(576000000, 48, 1, 1),
+       PLL_RATE(588000000, 49, 1, 1),
+       PLL_RATE(600000000, 50, 1, 1),
+       PLL_RATE(612000000, 51, 1, 1),
+       PLL_RATE(624000000, 52, 1, 1),
+       PLL_RATE(636000000, 53, 1, 1),
+       PLL_RATE(648000000, 54, 1, 1),
+       PLL_RATE(660000000, 55, 1, 1),
+       PLL_RATE(672000000, 56, 1, 1),
+       PLL_RATE(684000000, 57, 1, 1),
+       PLL_RATE(696000000, 58, 1, 1),
+       PLL_RATE(708000000, 59, 1, 1),
+       PLL_RATE(720000000, 60, 1, 1),
+       PLL_RATE(732000000, 61, 1, 1),
+       PLL_RATE(744000000, 62, 1, 1),
+       PLL_RATE(768000000, 32, 1, 0),
+       PLL_RATE(792000000, 33, 1, 0),
+       PLL_RATE(816000000, 34, 1, 0),
+       PLL_RATE(840000000, 35, 1, 0),
+       PLL_RATE(864000000, 36, 1, 0),
+       PLL_RATE(888000000, 37, 1, 0),
+       PLL_RATE(912000000, 38, 1, 0),
+       PLL_RATE(936000000, 39, 1, 0),
+       PLL_RATE(960000000, 40, 1, 0),
+       PLL_RATE(984000000, 41, 1, 0),
+       PLL_RATE(1008000000, 42, 1, 0),
+       PLL_RATE(1032000000, 43, 1, 0),
+       PLL_RATE(1056000000, 44, 1, 0),
+       PLL_RATE(1080000000, 45, 1, 0),
+       PLL_RATE(1104000000, 46, 1, 0),
+       PLL_RATE(1128000000, 47, 1, 0),
+       PLL_RATE(1152000000, 48, 1, 0),
+       PLL_RATE(1176000000, 49, 1, 0),
+       PLL_RATE(1200000000, 50, 1, 0),
+       PLL_RATE(1224000000, 51, 1, 0),
+       PLL_RATE(1248000000, 52, 1, 0),
+       PLL_RATE(1272000000, 53, 1, 0),
+       PLL_RATE(1296000000, 54, 1, 0),
+       PLL_RATE(1320000000, 55, 1, 0),
+       PLL_RATE(1344000000, 56, 1, 0),
+       PLL_RATE(1368000000, 57, 1, 0),
+       PLL_RATE(1392000000, 58, 1, 0),
+       PLL_RATE(1416000000, 59, 1, 0),
+       PLL_RATE(1440000000, 60, 1, 0),
+       PLL_RATE(1464000000, 61, 1, 0),
+       PLL_RATE(1488000000, 62, 1, 0),
+       { /* sentinel */ },
+};
+
+static const struct clk_div_table cpu_div_table[] = {
+       { .val = 1, .div = 1 },
+       { .val = 2, .div = 2 },
+       { .val = 3, .div = 3 },
+       { .val = 2, .div = 4 },
+       { .val = 3, .div = 6 },
+       { .val = 4, .div = 8 },
+       { .val = 5, .div = 10 },
+       { .val = 6, .div = 12 },
+       { .val = 7, .div = 14 },
+       { .val = 8, .div = 16 },
+       { /* sentinel */ },
+};
+
+static struct meson_clk_pll gxbb_fixed_pll = {
+       .m = {
+               .reg_off = HHI_MPLL_CNTL,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_MPLL_CNTL,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_MPLL_CNTL,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "fixed_pll",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll gxbb_hdmi_pll = {
+       .m = {
+               .reg_off = HHI_HDMI_PLL_CNTL,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_HDMI_PLL_CNTL,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .frac = {
+               .reg_off = HHI_HDMI_PLL_CNTL2,
+               .shift   = 0,
+               .width   = 12,
+       },
+       .od = {
+               .reg_off = HHI_HDMI_PLL_CNTL2,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .od2 = {
+               .reg_off = HHI_HDMI_PLL_CNTL2,
+               .shift   = 22,
+               .width   = 2,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll gxbb_sys_pll = {
+       .m = {
+               .reg_off = HHI_SYS_PLL_CNTL,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_SYS_PLL_CNTL,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_SYS_PLL_CNTL,
+               .shift   = 10,
+               .width   = 2,
+       },
+       .rate_table = sys_pll_rate_table,
+       .rate_count = ARRAY_SIZE(sys_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll gxbb_gp0_pll = {
+       .m = {
+               .reg_off = HHI_GP0_PLL_CNTL,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_GP0_PLL_CNTL,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_GP0_PLL_CNTL,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .rate_table = gp0_pll_rate_table,
+       .rate_count = ARRAY_SIZE(gp0_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "gp0_pll",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div3 = {
+       .mult = 1,
+       .div = 3,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div5 = {
+       .mult = 1,
+       .div = 5,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div7 = {
+       .mult = 1,
+       .div = 7,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll gxbb_mpll0 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 16,
+               .width   = 9,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &meson_clk_mpll_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll gxbb_mpll1 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 16,
+               .width   = 9,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &meson_clk_mpll_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll gxbb_mpll2 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 16,
+               .width   = 9,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2",
+               .ops = &meson_clk_mpll_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+/*
+ * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
+ * post-dividers and should be modeled with their respective PLLs via the
+ * forthcoming coordinated clock rates feature
+ */
+static struct meson_clk_cpu gxbb_cpu_clk = {
+       .reg_off = HHI_SYS_CPU_CLK_CNTL1,
+       .div_table = cpu_div_table,
+       .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk",
+               .ops = &meson_clk_cpu_ops,
+               .parent_names = (const char *[]){ "sys_pll" },
+               .num_parents = 1,
+       },
+};
+
+static u32 mux_table_clk81[]   = { 6, 5, 7 };
+
+static struct clk_mux gxbb_mpeg_clk_sel = {
+       .reg = (void *)HHI_MPEG_CLK_CNTL,
+       .mask = 0x7,
+       .shift = 12,
+       .flags = CLK_MUX_READ_ONLY,
+       .table = mux_table_clk81,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_sel",
+               .ops = &clk_mux_ro_ops,
+               /*
+                * FIXME bits 14:12 selects from 8 possible parents:
+                * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
+                * fclk_div4, fclk_div3, fclk_div5
+                */
+               .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
+                       "fclk_div5" },
+               .num_parents = 3,
+               .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
+       },
+};
+
+static struct clk_divider gxbb_mpeg_clk_div = {
+       .reg = (void *)HHI_MPEG_CLK_CNTL,
+       .shift = 0,
+       .width = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_sel" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
+       },
+};
+
+/* the mother of dragons^W gates */
+static struct clk_gate gxbb_clk81 = {
+       .reg = (void *)HHI_MPEG_CLK_CNTL,
+       .bit_idx = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "clk81",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_div" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL),
+       },
+};
+
+/* Everything Else (EE) domain gates */
+static MESON_GATE(ddr, HHI_GCLK_MPEG0, 0);
+static MESON_GATE(dos, HHI_GCLK_MPEG0, 1);
+static MESON_GATE(isa, HHI_GCLK_MPEG0, 5);
+static MESON_GATE(pl301, HHI_GCLK_MPEG0, 6);
+static MESON_GATE(periphs, HHI_GCLK_MPEG0, 7);
+static MESON_GATE(spicc, HHI_GCLK_MPEG0, 8);
+static MESON_GATE(i2c, HHI_GCLK_MPEG0, 9);
+static MESON_GATE(sar_adc, HHI_GCLK_MPEG0, 10);
+static MESON_GATE(smart_card, HHI_GCLK_MPEG0, 11);
+static MESON_GATE(rng0, HHI_GCLK_MPEG0, 12);
+static MESON_GATE(uart0, HHI_GCLK_MPEG0, 13);
+static MESON_GATE(sdhc, HHI_GCLK_MPEG0, 14);
+static MESON_GATE(stream, HHI_GCLK_MPEG0, 15);
+static MESON_GATE(async_fifo, HHI_GCLK_MPEG0, 16);
+static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17);
+static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18);
+static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19);
+static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23);
+static MESON_GATE(spi, HHI_GCLK_MPEG0, 30);
+
+static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2);
+static MESON_GATE(eth, HHI_GCLK_MPEG1, 3);
+static MESON_GATE(demux, HHI_GCLK_MPEG1, 4);
+static MESON_GATE(aiu_glue, HHI_GCLK_MPEG1, 6);
+static MESON_GATE(iec958, HHI_GCLK_MPEG1, 7);
+static MESON_GATE(i2s_out, HHI_GCLK_MPEG1, 8);
+static MESON_GATE(amclk, HHI_GCLK_MPEG1, 9);
+static MESON_GATE(aififo2, HHI_GCLK_MPEG1, 10);
+static MESON_GATE(mixer, HHI_GCLK_MPEG1, 11);
+static MESON_GATE(mixer_iface, HHI_GCLK_MPEG1, 12);
+static MESON_GATE(adc, HHI_GCLK_MPEG1, 13);
+static MESON_GATE(blkmv, HHI_GCLK_MPEG1, 14);
+static MESON_GATE(aiu, HHI_GCLK_MPEG1, 15);
+static MESON_GATE(uart1, HHI_GCLK_MPEG1, 16);
+static MESON_GATE(g2d, HHI_GCLK_MPEG1, 20);
+static MESON_GATE(usb0, HHI_GCLK_MPEG1, 21);
+static MESON_GATE(usb1, HHI_GCLK_MPEG1, 22);
+static MESON_GATE(reset, HHI_GCLK_MPEG1, 23);
+static MESON_GATE(nand, HHI_GCLK_MPEG1, 24);
+static MESON_GATE(dos_parser, HHI_GCLK_MPEG1, 25);
+static MESON_GATE(usb, HHI_GCLK_MPEG1, 26);
+static MESON_GATE(vdin1, HHI_GCLK_MPEG1, 28);
+static MESON_GATE(ahb_arb0, HHI_GCLK_MPEG1, 29);
+static MESON_GATE(efuse, HHI_GCLK_MPEG1, 30);
+static MESON_GATE(boot_rom, HHI_GCLK_MPEG1, 31);
+
+static MESON_GATE(ahb_data_bus, HHI_GCLK_MPEG2, 1);
+static MESON_GATE(ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
+static MESON_GATE(hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
+static MESON_GATE(hdmi_pclk, HHI_GCLK_MPEG2, 4);
+static MESON_GATE(usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
+static MESON_GATE(usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
+static MESON_GATE(mmc_pclk, HHI_GCLK_MPEG2, 11);
+static MESON_GATE(dvin, HHI_GCLK_MPEG2, 12);
+static MESON_GATE(uart2, HHI_GCLK_MPEG2, 15);
+static MESON_GATE(sana, HHI_GCLK_MPEG2, 22);
+static MESON_GATE(vpu_intr, HHI_GCLK_MPEG2, 25);
+static MESON_GATE(sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
+static MESON_GATE(clk81_a53, HHI_GCLK_MPEG2, 29);
+
+static MESON_GATE(vclk2_venci0, HHI_GCLK_OTHER, 1);
+static MESON_GATE(vclk2_venci1, HHI_GCLK_OTHER, 2);
+static MESON_GATE(vclk2_vencp0, HHI_GCLK_OTHER, 3);
+static MESON_GATE(vclk2_vencp1, HHI_GCLK_OTHER, 4);
+static MESON_GATE(gclk_venci_int0, HHI_GCLK_OTHER, 8);
+static MESON_GATE(gclk_vencp_int, HHI_GCLK_OTHER, 9);
+static MESON_GATE(dac_clk, HHI_GCLK_OTHER, 10);
+static MESON_GATE(aoclk_gate, HHI_GCLK_OTHER, 14);
+static MESON_GATE(iec958_gate, HHI_GCLK_OTHER, 16);
+static MESON_GATE(enc480p, HHI_GCLK_OTHER, 20);
+static MESON_GATE(rng1, HHI_GCLK_OTHER, 21);
+static MESON_GATE(gclk_venci_int1, HHI_GCLK_OTHER, 22);
+static MESON_GATE(vclk2_venclmcc, HHI_GCLK_OTHER, 24);
+static MESON_GATE(vclk2_vencl, HHI_GCLK_OTHER, 25);
+static MESON_GATE(vclk_other, HHI_GCLK_OTHER, 26);
+static MESON_GATE(edp, HHI_GCLK_OTHER, 31);
+
+/* Always On (AO) domain gates */
+
+static MESON_GATE(ao_media_cpu, HHI_GCLK_AO, 0);
+static MESON_GATE(ao_ahb_sram, HHI_GCLK_AO, 1);
+static MESON_GATE(ao_ahb_bus, HHI_GCLK_AO, 2);
+static MESON_GATE(ao_iface, HHI_GCLK_AO, 3);
+static MESON_GATE(ao_i2c, HHI_GCLK_AO, 4);
+
+/* Array of all clocks provided by this provider */
+
+static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
+       .hws = {
+               [CLKID_SYS_PLL]             = &gxbb_sys_pll.hw,
+               [CLKID_CPUCLK]              = &gxbb_cpu_clk.hw,
+               [CLKID_HDMI_PLL]            = &gxbb_hdmi_pll.hw,
+               [CLKID_FIXED_PLL]           = &gxbb_fixed_pll.hw,
+               [CLKID_FCLK_DIV2]           = &gxbb_fclk_div2.hw,
+               [CLKID_FCLK_DIV3]           = &gxbb_fclk_div3.hw,
+               [CLKID_FCLK_DIV4]           = &gxbb_fclk_div4.hw,
+               [CLKID_FCLK_DIV5]           = &gxbb_fclk_div5.hw,
+               [CLKID_FCLK_DIV7]           = &gxbb_fclk_div7.hw,
+               [CLKID_GP0_PLL]             = &gxbb_gp0_pll.hw,
+               [CLKID_MPEG_SEL]            = &gxbb_mpeg_clk_sel.hw,
+               [CLKID_MPEG_DIV]            = &gxbb_mpeg_clk_div.hw,
+               [CLKID_CLK81]               = &gxbb_clk81.hw,
+               [CLKID_MPLL0]               = &gxbb_mpll0.hw,
+               [CLKID_MPLL1]               = &gxbb_mpll1.hw,
+               [CLKID_MPLL2]               = &gxbb_mpll2.hw,
+               [CLKID_DDR]                 = &gxbb_ddr.hw,
+               [CLKID_DOS]                 = &gxbb_dos.hw,
+               [CLKID_ISA]                 = &gxbb_isa.hw,
+               [CLKID_PL301]               = &gxbb_pl301.hw,
+               [CLKID_PERIPHS]             = &gxbb_periphs.hw,
+               [CLKID_SPICC]               = &gxbb_spicc.hw,
+               [CLKID_I2C]                 = &gxbb_i2c.hw,
+               [CLKID_SAR_ADC]             = &gxbb_sar_adc.hw,
+               [CLKID_SMART_CARD]          = &gxbb_smart_card.hw,
+               [CLKID_RNG0]                = &gxbb_rng0.hw,
+               [CLKID_UART0]               = &gxbb_uart0.hw,
+               [CLKID_SDHC]                = &gxbb_sdhc.hw,
+               [CLKID_STREAM]              = &gxbb_stream.hw,
+               [CLKID_ASYNC_FIFO]          = &gxbb_async_fifo.hw,
+               [CLKID_SDIO]                = &gxbb_sdio.hw,
+               [CLKID_ABUF]                = &gxbb_abuf.hw,
+               [CLKID_HIU_IFACE]           = &gxbb_hiu_iface.hw,
+               [CLKID_ASSIST_MISC]         = &gxbb_assist_misc.hw,
+               [CLKID_SPI]                 = &gxbb_spi.hw,
+               [CLKID_I2S_SPDIF]           = &gxbb_i2s_spdif.hw,
+               [CLKID_ETH]                 = &gxbb_eth.hw,
+               [CLKID_DEMUX]               = &gxbb_demux.hw,
+               [CLKID_AIU_GLUE]            = &gxbb_aiu_glue.hw,
+               [CLKID_IEC958]              = &gxbb_iec958.hw,
+               [CLKID_I2S_OUT]             = &gxbb_i2s_out.hw,
+               [CLKID_AMCLK]               = &gxbb_amclk.hw,
+               [CLKID_AIFIFO2]             = &gxbb_aififo2.hw,
+               [CLKID_MIXER]               = &gxbb_mixer.hw,
+               [CLKID_MIXER_IFACE]         = &gxbb_mixer_iface.hw,
+               [CLKID_ADC]                 = &gxbb_adc.hw,
+               [CLKID_BLKMV]               = &gxbb_blkmv.hw,
+               [CLKID_AIU]                 = &gxbb_aiu.hw,
+               [CLKID_UART1]               = &gxbb_uart1.hw,
+               [CLKID_G2D]                 = &gxbb_g2d.hw,
+               [CLKID_USB0]                = &gxbb_usb0.hw,
+               [CLKID_USB1]                = &gxbb_usb1.hw,
+               [CLKID_RESET]               = &gxbb_reset.hw,
+               [CLKID_NAND]                = &gxbb_nand.hw,
+               [CLKID_DOS_PARSER]          = &gxbb_dos_parser.hw,
+               [CLKID_USB]                 = &gxbb_usb.hw,
+               [CLKID_VDIN1]               = &gxbb_vdin1.hw,
+               [CLKID_AHB_ARB0]            = &gxbb_ahb_arb0.hw,
+               [CLKID_EFUSE]               = &gxbb_efuse.hw,
+               [CLKID_BOOT_ROM]            = &gxbb_boot_rom.hw,
+               [CLKID_AHB_DATA_BUS]        = &gxbb_ahb_data_bus.hw,
+               [CLKID_AHB_CTRL_BUS]        = &gxbb_ahb_ctrl_bus.hw,
+               [CLKID_HDMI_INTR_SYNC]      = &gxbb_hdmi_intr_sync.hw,
+               [CLKID_HDMI_PCLK]           = &gxbb_hdmi_pclk.hw,
+               [CLKID_USB1_DDR_BRIDGE]     = &gxbb_usb1_ddr_bridge.hw,
+               [CLKID_USB0_DDR_BRIDGE]     = &gxbb_usb0_ddr_bridge.hw,
+               [CLKID_MMC_PCLK]            = &gxbb_mmc_pclk.hw,
+               [CLKID_DVIN]                = &gxbb_dvin.hw,
+               [CLKID_UART2]               = &gxbb_uart2.hw,
+               [CLKID_SANA]                = &gxbb_sana.hw,
+               [CLKID_VPU_INTR]            = &gxbb_vpu_intr.hw,
+               [CLKID_SEC_AHB_AHB3_BRIDGE] = &gxbb_sec_ahb_ahb3_bridge.hw,
+               [CLKID_CLK81_A53]           = &gxbb_clk81_a53.hw,
+               [CLKID_VCLK2_VENCI0]        = &gxbb_vclk2_venci0.hw,
+               [CLKID_VCLK2_VENCI1]        = &gxbb_vclk2_venci1.hw,
+               [CLKID_VCLK2_VENCP0]        = &gxbb_vclk2_vencp0.hw,
+               [CLKID_VCLK2_VENCP1]        = &gxbb_vclk2_vencp1.hw,
+               [CLKID_GCLK_VENCI_INT0]     = &gxbb_gclk_venci_int0.hw,
+               [CLKID_GCLK_VENCI_INT]      = &gxbb_gclk_vencp_int.hw,
+               [CLKID_DAC_CLK]             = &gxbb_dac_clk.hw,
+               [CLKID_AOCLK_GATE]          = &gxbb_aoclk_gate.hw,
+               [CLKID_IEC958_GATE]         = &gxbb_iec958_gate.hw,
+               [CLKID_ENC480P]             = &gxbb_enc480p.hw,
+               [CLKID_RNG1]                = &gxbb_rng1.hw,
+               [CLKID_GCLK_VENCI_INT1]     = &gxbb_gclk_venci_int1.hw,
+               [CLKID_VCLK2_VENCLMCC]      = &gxbb_vclk2_venclmcc.hw,
+               [CLKID_VCLK2_VENCL]         = &gxbb_vclk2_vencl.hw,
+               [CLKID_VCLK_OTHER]          = &gxbb_vclk_other.hw,
+               [CLKID_EDP]                 = &gxbb_edp.hw,
+               [CLKID_AO_MEDIA_CPU]        = &gxbb_ao_media_cpu.hw,
+               [CLKID_AO_AHB_SRAM]         = &gxbb_ao_ahb_sram.hw,
+               [CLKID_AO_AHB_BUS]          = &gxbb_ao_ahb_bus.hw,
+               [CLKID_AO_IFACE]            = &gxbb_ao_iface.hw,
+               [CLKID_AO_I2C]              = &gxbb_ao_i2c.hw,
+       },
+       .num = NR_CLKS,
+};
+
+/* Convenience tables to populate base addresses in .probe */
+
+static struct meson_clk_pll *const gxbb_clk_plls[] = {
+       &gxbb_fixed_pll,
+       &gxbb_hdmi_pll,
+       &gxbb_sys_pll,
+       &gxbb_gp0_pll,
+};
+
+static struct meson_clk_mpll *const gxbb_clk_mplls[] = {
+       &gxbb_mpll0,
+       &gxbb_mpll1,
+       &gxbb_mpll2,
+};
+
+static struct clk_gate *gxbb_clk_gates[] = {
+       &gxbb_clk81,
+       &gxbb_ddr,
+       &gxbb_dos,
+       &gxbb_isa,
+       &gxbb_pl301,
+       &gxbb_periphs,
+       &gxbb_spicc,
+       &gxbb_i2c,
+       &gxbb_sar_adc,
+       &gxbb_smart_card,
+       &gxbb_rng0,
+       &gxbb_uart0,
+       &gxbb_sdhc,
+       &gxbb_stream,
+       &gxbb_async_fifo,
+       &gxbb_sdio,
+       &gxbb_abuf,
+       &gxbb_hiu_iface,
+       &gxbb_assist_misc,
+       &gxbb_spi,
+       &gxbb_i2s_spdif,
+       &gxbb_eth,
+       &gxbb_demux,
+       &gxbb_aiu_glue,
+       &gxbb_iec958,
+       &gxbb_i2s_out,
+       &gxbb_amclk,
+       &gxbb_aififo2,
+       &gxbb_mixer,
+       &gxbb_mixer_iface,
+       &gxbb_adc,
+       &gxbb_blkmv,
+       &gxbb_aiu,
+       &gxbb_uart1,
+       &gxbb_g2d,
+       &gxbb_usb0,
+       &gxbb_usb1,
+       &gxbb_reset,
+       &gxbb_nand,
+       &gxbb_dos_parser,
+       &gxbb_usb,
+       &gxbb_vdin1,
+       &gxbb_ahb_arb0,
+       &gxbb_efuse,
+       &gxbb_boot_rom,
+       &gxbb_ahb_data_bus,
+       &gxbb_ahb_ctrl_bus,
+       &gxbb_hdmi_intr_sync,
+       &gxbb_hdmi_pclk,
+       &gxbb_usb1_ddr_bridge,
+       &gxbb_usb0_ddr_bridge,
+       &gxbb_mmc_pclk,
+       &gxbb_dvin,
+       &gxbb_uart2,
+       &gxbb_sana,
+       &gxbb_vpu_intr,
+       &gxbb_sec_ahb_ahb3_bridge,
+       &gxbb_clk81_a53,
+       &gxbb_vclk2_venci0,
+       &gxbb_vclk2_venci1,
+       &gxbb_vclk2_vencp0,
+       &gxbb_vclk2_vencp1,
+       &gxbb_gclk_venci_int0,
+       &gxbb_gclk_vencp_int,
+       &gxbb_dac_clk,
+       &gxbb_aoclk_gate,
+       &gxbb_iec958_gate,
+       &gxbb_enc480p,
+       &gxbb_rng1,
+       &gxbb_gclk_venci_int1,
+       &gxbb_vclk2_venclmcc,
+       &gxbb_vclk2_vencl,
+       &gxbb_vclk_other,
+       &gxbb_edp,
+       &gxbb_ao_media_cpu,
+       &gxbb_ao_ahb_sram,
+       &gxbb_ao_ahb_bus,
+       &gxbb_ao_iface,
+       &gxbb_ao_i2c,
+};
+
+static int gxbb_clkc_probe(struct platform_device *pdev)
+{
+       void __iomem *clk_base;
+       int ret, clkid, i;
+       struct clk_hw *parent_hw;
+       struct clk *parent_clk;
+       struct device *dev = &pdev->dev;
+
+       /*  Generic clocks and PLLs */
+       clk_base = of_iomap(dev->of_node, 0);
+       if (!clk_base) {
+               pr_err("%s: Unable to map clk base\n", __func__);
+               return -ENXIO;
+       }
+
+       /* Populate base address for PLLs */
+       for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++)
+               gxbb_clk_plls[i]->base = clk_base;
+
+       /* Populate base address for MPLLs */
+       for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++)
+               gxbb_clk_mplls[i]->base = clk_base;
+
+       /* Populate the base address for CPU clk */
+       gxbb_cpu_clk.base = clk_base;
+
+       /* Populate the base address for the MPEG clks */
+       gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
+       gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
+
+       /* Populate base address for gates */
+       for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
+               gxbb_clk_gates[i]->reg = clk_base +
+                       (u64)gxbb_clk_gates[i]->reg;
+
+       /*
+        * register all clks
+        */
+       for (clkid = 0; clkid < NR_CLKS; clkid++) {
+               ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]);
+               if (ret)
+                       goto iounmap;
+       }
+
+       /*
+        * Register CPU clk notifier
+        *
+        * FIXME this is wrong for a lot of reasons. First, the muxes should be
+        * struct clk_hw objects. Second, we shouldn't program the muxes in
+        * notifier handlers. The tricky programming sequence will be handled
+        * by the forthcoming coordinated clock rates mechanism once that
+        * feature is released.
+        *
+        * Furthermore, looking up the parent this way is terrible. At some
+        * point we will stop allocating a default struct clk when registering
+        * a new clk_hw, and this hack will no longer work. Releasing the ccr
+        * feature before that time solves the problem :-)
+        */
+       parent_hw = clk_hw_get_parent(&gxbb_cpu_clk.hw);
+       parent_clk = parent_hw->clk;
+       ret = clk_notifier_register(parent_clk, &gxbb_cpu_clk.clk_nb);
+       if (ret) {
+               pr_err("%s: failed to register clock notifier for cpu_clk\n",
+                               __func__);
+               goto iounmap;
+       }
+
+       return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+                       &gxbb_hw_onecell_data);
+
+iounmap:
+       iounmap(clk_base);
+       return ret;
+}
+
+static const struct of_device_id gxbb_clkc_match_table[] = {
+       { .compatible = "amlogic,gxbb-clkc" },
+       { }
+};
+
+static struct platform_driver gxbb_driver = {
+       .probe          = gxbb_clkc_probe,
+       .driver         = {
+               .name   = "gxbb-clkc",
+               .of_match_table = gxbb_clkc_match_table,
+       },
+};
+
+static int __init gxbb_clkc_init(void)
+{
+       return platform_driver_register(&gxbb_driver);
+}
+device_initcall(gxbb_clkc_init);
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
new file mode 100644 (file)
index 0000000..a2adf34
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 AmLogic, Inc.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GXBB_H
+#define __GXBB_H
+
+/*
+ * Clock controller register offsets
+ *
+ * Register offsets from the data sheet are listed in comment blocks below.
+ * Those offsets must be multiplied by 4 before adding them to the base address
+ * to get the right value
+ */
+#define SCR                            0x2C /* 0x0b offset in data sheet */
+#define TIMEOUT_VALUE                  0x3c /* 0x0f offset in data sheet */
+
+#define HHI_GP0_PLL_CNTL               0x40 /* 0x10 offset in data sheet */
+#define HHI_GP0_PLL_CNTL2              0x44 /* 0x11 offset in data sheet */
+#define HHI_GP0_PLL_CNTL3              0x48 /* 0x12 offset in data sheet */
+#define HHI_GP0_PLL_CNTL4              0x4c /* 0x13 offset in data sheet */
+
+#define HHI_XTAL_DIVN_CNTL             0xbc /* 0x2f offset in data sheet */
+#define HHI_TIMER90K                   0xec /* 0x3b offset in data sheet */
+
+#define HHI_MEM_PD_REG0                        0x100 /* 0x40 offset in data sheet */
+#define HHI_MEM_PD_REG1                        0x104 /* 0x41 offset in data sheet */
+#define HHI_VPU_MEM_PD_REG1            0x108 /* 0x42 offset in data sheet */
+#define HHI_VIID_CLK_DIV               0x128 /* 0x4a offset in data sheet */
+#define HHI_VIID_CLK_CNTL              0x12c /* 0x4b offset in data sheet */
+
+#define HHI_GCLK_MPEG0                 0x140 /* 0x50 offset in data sheet */
+#define HHI_GCLK_MPEG1                 0x144 /* 0x51 offset in data sheet */
+#define HHI_GCLK_MPEG2                 0x148 /* 0x52 offset in data sheet */
+#define HHI_GCLK_OTHER                 0x150 /* 0x54 offset in data sheet */
+#define HHI_GCLK_AO                    0x154 /* 0x55 offset in data sheet */
+#define HHI_SYS_OSCIN_CNTL             0x158 /* 0x56 offset in data sheet */
+#define HHI_SYS_CPU_CLK_CNTL1          0x15c /* 0x57 offset in data sheet */
+#define HHI_SYS_CPU_RESET_CNTL         0x160 /* 0x58 offset in data sheet */
+#define HHI_VID_CLK_DIV                        0x164 /* 0x59 offset in data sheet */
+
+#define HHI_MPEG_CLK_CNTL              0x174 /* 0x5d offset in data sheet */
+#define HHI_AUD_CLK_CNTL               0x178 /* 0x5e offset in data sheet */
+#define HHI_VID_CLK_CNTL               0x17c /* 0x5f offset in data sheet */
+#define HHI_AUD_CLK_CNTL2              0x190 /* 0x64 offset in data sheet */
+#define HHI_VID_CLK_CNTL2              0x194 /* 0x65 offset in data sheet */
+#define HHI_SYS_CPU_CLK_CNTL0          0x19c /* 0x67 offset in data sheet */
+#define HHI_VID_PLL_CLK_DIV            0x1a0 /* 0x68 offset in data sheet */
+#define HHI_AUD_CLK_CNTL3              0x1a4 /* 0x69 offset in data sheet */
+#define HHI_MALI_CLK_CNTL              0x1b0 /* 0x6c offset in data sheet */
+#define HHI_VPU_CLK_CNTL               0x1bC /* 0x6f offset in data sheet */
+
+#define HHI_HDMI_CLK_CNTL              0x1CC /* 0x73 offset in data sheet */
+#define HHI_VDEC_CLK_CNTL              0x1E0 /* 0x78 offset in data sheet */
+#define HHI_VDEC2_CLK_CNTL             0x1E4 /* 0x79 offset in data sheet */
+#define HHI_VDEC3_CLK_CNTL             0x1E8 /* 0x7a offset in data sheet */
+#define HHI_VDEC4_CLK_CNTL             0x1EC /* 0x7b offset in data sheet */
+#define HHI_HDCP22_CLK_CNTL            0x1F0 /* 0x7c offset in data sheet */
+#define HHI_VAPBCLK_CNTL               0x1F4 /* 0x7d offset in data sheet */
+
+#define HHI_VPU_CLKB_CNTL              0x20C /* 0x83 offset in data sheet */
+#define HHI_USB_CLK_CNTL               0x220 /* 0x88 offset in data sheet */
+#define HHI_32K_CLK_CNTL               0x224 /* 0x89 offset in data sheet */
+#define HHI_GEN_CLK_CNTL               0x228 /* 0x8a offset in data sheet */
+#define HHI_GEN_CLK_CNTL               0x228 /* 0x8a offset in data sheet */
+
+#define HHI_PCM_CLK_CNTL               0x258 /* 0x96 offset in data sheet */
+#define HHI_NAND_CLK_CNTL              0x25C /* 0x97 offset in data sheet */
+#define HHI_SD_EMMC_CLK_CNTL           0x264 /* 0x99 offset in data sheet */
+
+#define HHI_MPLL_CNTL                  0x280 /* 0xa0 offset in data sheet */
+#define HHI_MPLL_CNTL2                 0x284 /* 0xa1 offset in data sheet */
+#define HHI_MPLL_CNTL3                 0x288 /* 0xa2 offset in data sheet */
+#define HHI_MPLL_CNTL4                 0x28C /* 0xa3 offset in data sheet */
+#define HHI_MPLL_CNTL5                 0x290 /* 0xa4 offset in data sheet */
+#define HHI_MPLL_CNTL6                 0x294 /* 0xa5 offset in data sheet */
+#define HHI_MPLL_CNTL7                 0x298 /* MP0, 0xa6 offset in data sheet */
+#define HHI_MPLL_CNTL8                 0x29C /* MP1, 0xa7 offset in data sheet */
+#define HHI_MPLL_CNTL9                 0x2A0 /* MP2, 0xa8 offset in data sheet */
+#define HHI_MPLL_CNTL10                        0x2A4 /* MP2, 0xa9 offset in data sheet */
+
+#define HHI_MPLL3_CNTL0                        0x2E0 /* 0xb8 offset in data sheet */
+#define HHI_MPLL3_CNTL1                        0x2E4 /* 0xb9 offset in data sheet */
+#define HHI_VDAC_CNTL0                 0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1                 0x2F8 /* 0xbe offset in data sheet */
+
+#define HHI_SYS_PLL_CNTL               0x300 /* 0xc0 offset in data sheet */
+#define HHI_SYS_PLL_CNTL2              0x304 /* 0xc1 offset in data sheet */
+#define HHI_SYS_PLL_CNTL3              0x308 /* 0xc2 offset in data sheet */
+#define HHI_SYS_PLL_CNTL4              0x30c /* 0xc3 offset in data sheet */
+#define HHI_SYS_PLL_CNTL5              0x310 /* 0xc4 offset in data sheet */
+#define HHI_DPLL_TOP_I                 0x318 /* 0xc6 offset in data sheet */
+#define HHI_DPLL_TOP2_I                        0x31C /* 0xc7 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL              0x320 /* 0xc8 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL2             0x324 /* 0xc9 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL3             0x328 /* 0xca offset in data sheet */
+#define HHI_HDMI_PLL_CNTL4             0x32C /* 0xcb offset in data sheet */
+#define HHI_HDMI_PLL_CNTL5             0x330 /* 0xcc offset in data sheet */
+#define HHI_HDMI_PLL_CNTL6             0x334 /* 0xcd offset in data sheet */
+#define HHI_HDMI_PLL_CNTL_I            0x338 /* 0xce offset in data sheet */
+#define HHI_HDMI_PLL_CNTL7             0x33C /* 0xcf offset in data sheet */
+
+#define HHI_HDMI_PHY_CNTL0             0x3A0 /* 0xe8 offset in data sheet */
+#define HHI_HDMI_PHY_CNTL1             0x3A4 /* 0xe9 offset in data sheet */
+#define HHI_HDMI_PHY_CNTL2             0x3A8 /* 0xea offset in data sheet */
+#define HHI_HDMI_PHY_CNTL3             0x3AC /* 0xeb offset in data sheet */
+
+#define HHI_VID_LOCK_CLK_CNTL          0x3C8 /* 0xf2 offset in data sheet */
+#define HHI_BT656_CLK_CNTL             0x3D4 /* 0xf5 offset in data sheet */
+#define HHI_SAR_CLK_CNTL               0x3D8 /* 0xf6 offset in data sheet */
+
+/*
+ * CLKID index values
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * Migrate them out of this header and into the DT header file when they need
+ * to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h
+ */
+#define CLKID_SYS_PLL            0
+/* CLKID_CPUCLK */
+#define CLKID_HDMI_PLL           2
+#define CLKID_FIXED_PLL                  3
+#define CLKID_FCLK_DIV2                  4
+#define CLKID_FCLK_DIV3                  5
+#define CLKID_FCLK_DIV4                  6
+#define CLKID_FCLK_DIV5                  7
+#define CLKID_FCLK_DIV7                  8
+#define CLKID_GP0_PLL            9
+#define CLKID_MPEG_SEL           10
+#define CLKID_MPEG_DIV           11
+/* CLKID_CLK81 */
+#define CLKID_MPLL0              13
+#define CLKID_MPLL1              14
+#define CLKID_MPLL2              15
+#define CLKID_DDR                16
+#define CLKID_DOS                17
+#define CLKID_ISA                18
+#define CLKID_PL301              19
+#define CLKID_PERIPHS            20
+#define CLKID_SPICC              21
+#define CLKID_I2C                22
+#define CLKID_SAR_ADC            23
+#define CLKID_SMART_CARD         24
+#define CLKID_RNG0               25
+#define CLKID_UART0              26
+#define CLKID_SDHC               27
+#define CLKID_STREAM             28
+#define CLKID_ASYNC_FIFO         29
+#define CLKID_SDIO               30
+#define CLKID_ABUF               31
+#define CLKID_HIU_IFACE                  32
+#define CLKID_ASSIST_MISC        33
+#define CLKID_SPI                34
+#define CLKID_I2S_SPDIF                  35
+#define CLKID_ETH                36
+#define CLKID_DEMUX              37
+#define CLKID_AIU_GLUE           38
+#define CLKID_IEC958             39
+#define CLKID_I2S_OUT            40
+#define CLKID_AMCLK              41
+#define CLKID_AIFIFO2            42
+#define CLKID_MIXER              43
+#define CLKID_MIXER_IFACE        44
+#define CLKID_ADC                45
+#define CLKID_BLKMV              46
+#define CLKID_AIU                47
+#define CLKID_UART1              48
+#define CLKID_G2D                49
+#define CLKID_USB0               50
+#define CLKID_USB1               51
+#define CLKID_RESET              52
+#define CLKID_NAND               53
+#define CLKID_DOS_PARSER         54
+#define CLKID_USB                55
+#define CLKID_VDIN1              56
+#define CLKID_AHB_ARB0           57
+#define CLKID_EFUSE              58
+#define CLKID_BOOT_ROM           59
+#define CLKID_AHB_DATA_BUS       60
+#define CLKID_AHB_CTRL_BUS       61
+#define CLKID_HDMI_INTR_SYNC     62
+#define CLKID_HDMI_PCLK                  63
+#define CLKID_USB1_DDR_BRIDGE    64
+#define CLKID_USB0_DDR_BRIDGE    65
+#define CLKID_MMC_PCLK           66
+#define CLKID_DVIN               67
+#define CLKID_UART2              68
+#define CLKID_SANA               69
+#define CLKID_VPU_INTR           70
+#define CLKID_SEC_AHB_AHB3_BRIDGE 71
+#define CLKID_CLK81_A53                  72
+#define CLKID_VCLK2_VENCI0       73
+#define CLKID_VCLK2_VENCI1       74
+#define CLKID_VCLK2_VENCP0       75
+#define CLKID_VCLK2_VENCP1       76
+#define CLKID_GCLK_VENCI_INT0    77
+#define CLKID_GCLK_VENCI_INT     78
+#define CLKID_DAC_CLK            79
+#define CLKID_AOCLK_GATE         80
+#define CLKID_IEC958_GATE        81
+#define CLKID_ENC480P            82
+#define CLKID_RNG1               83
+#define CLKID_GCLK_VENCI_INT1    84
+#define CLKID_VCLK2_VENCLMCC     85
+#define CLKID_VCLK2_VENCL        86
+#define CLKID_VCLK_OTHER         87
+#define CLKID_EDP                88
+#define CLKID_AO_MEDIA_CPU       89
+#define CLKID_AO_AHB_SRAM        90
+#define CLKID_AO_AHB_BUS         91
+#define CLKID_AO_IFACE           92
+#define CLKID_AO_I2C             93
+
+#define NR_CLKS                          94
+
+/* include the CLKIDs that have been made part of the stable DT binding */
+#include <dt-bindings/clock/gxbb-clkc.h>
+
+#endif /* __GXBB_H */
index 4d057b3e21b2a50d9bbae66abf745d2d7a4ef277..4c9413cdf373058aee6cd09703dc98bdde5fcb28 100644 (file)
@@ -1,7 +1,12 @@
 /*
+ * AmLogic S805 / Meson8b Clock Controller Driver
+ *
  * Copyright (c) 2015 Endless Mobile, Inc.
  * Author: Carlo Caione <carlo@endlessm.com>
  *
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Michael Turquette <mturquette@baylibre.com>
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  * version 2, as published by the Free Software Foundation.
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/kernel.h>
-#include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/slab.h>
 #include <dt-bindings/clock/meson8b-clkc.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
 
 #include "clkc.h"
 
-#define MESON8B_REG_CTL0_ADDR          0x0000
-#define MESON8B_REG_SYS_CPU_CNTL1      0x015c
-#define MESON8B_REG_HHI_MPEG           0x0174
-#define MESON8B_REG_MALI               0x01b0
+/*
+ * Clock controller register offsets
+ *
+ * Register offsets from the HardKernel[0] data sheet are listed in comment
+ * blocks below. Those offsets must be multiplied by 4 before adding them to
+ * the base address to get the right value
+ *
+ * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
+ */
+#define MESON8B_REG_SYS_CPU_CNTL1      0x015c /* 0x57 offset in data sheet */
+#define MESON8B_REG_HHI_MPEG           0x0174 /* 0x5d offset in data sheet */
+#define MESON8B_REG_MALI               0x01b0 /* 0x6c offset in data sheet */
 #define MESON8B_REG_PLL_FIXED          0x0280
 #define MESON8B_REG_PLL_SYS            0x0300
 #define MESON8B_REG_PLL_VID            0x0320
 
+static DEFINE_SPINLOCK(clk_lock);
+
 static const struct pll_rate_table sys_pll_rate_table[] = {
        PLL_RATE(312000000, 52, 1, 2),
        PLL_RATE(336000000, 56, 1, 2),
@@ -102,95 +117,331 @@ static const struct clk_div_table cpu_div_table[] = {
        { /* sentinel */ },
 };
 
-PNAME(p_xtal)          = { "xtal" };
-PNAME(p_fclk_div)      = { "fixed_pll" };
-PNAME(p_cpu_clk)       = { "sys_pll" };
-PNAME(p_clk81)         = { "fclk_div3", "fclk_div4", "fclk_div5" };
-PNAME(p_mali)          = { "fclk_div3", "fclk_div4", "fclk_div5",
-                           "fclk_div7", "zero" };
+static struct clk_fixed_rate meson8b_xtal = {
+       .fixed_rate = 24000000,
+       .hw.init = &(struct clk_init_data){
+               .name = "xtal",
+               .num_parents = 0,
+               .ops = &clk_fixed_rate_ops,
+       },
+};
+
+static struct meson_clk_pll meson8b_fixed_pll = {
+       .m = {
+               .reg_off = MESON8B_REG_PLL_FIXED,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = MESON8B_REG_PLL_FIXED,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = MESON8B_REG_PLL_FIXED,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "fixed_pll",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll meson8b_vid_pll = {
+       .m = {
+               .reg_off = MESON8B_REG_PLL_VID,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = MESON8B_REG_PLL_VID,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = MESON8B_REG_PLL_VID,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "vid_pll",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll meson8b_sys_pll = {
+       .m = {
+               .reg_off = MESON8B_REG_PLL_SYS,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = MESON8B_REG_PLL_SYS,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = MESON8B_REG_PLL_SYS,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .rate_table = sys_pll_rate_table,
+       .rate_count = ARRAY_SIZE(sys_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div3 = {
+       .mult = 1,
+       .div = 3,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div5 = {
+       .mult = 1,
+       .div = 5,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div7 = {
+       .mult = 1,
+       .div = 7,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+/*
+ * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
+ * post-dividers and should be modeled with their respective PLLs via the
+ * forthcoming coordinated clock rates feature
+ */
+static struct meson_clk_cpu meson8b_cpu_clk = {
+       .reg_off = MESON8B_REG_SYS_CPU_CNTL1,
+       .div_table = cpu_div_table,
+       .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk",
+               .ops = &meson_clk_cpu_ops,
+               .parent_names = (const char *[]){ "sys_pll" },
+               .num_parents = 1,
+       },
+};
 
 static u32 mux_table_clk81[]   = { 6, 5, 7 };
-static u32 mux_table_mali[]    = { 6, 5, 7, 4, 0 };
-
-static struct pll_conf pll_confs = {
-       .m              = PARM(0x00, 0,  9),
-       .n              = PARM(0x00, 9,  5),
-       .od             = PARM(0x00, 16, 2),
-};
-
-static struct pll_conf sys_pll_conf = {
-       .m              = PARM(0x00, 0,  9),
-       .n              = PARM(0x00, 9,  5),
-       .od             = PARM(0x00, 16, 2),
-       .rate_table     = sys_pll_rate_table,
-};
-
-static const struct composite_conf clk81_conf __initconst = {
-       .mux_table              = mux_table_clk81,
-       .mux_flags              = CLK_MUX_READ_ONLY,
-       .mux_parm               = PARM(0x00, 12, 3),
-       .div_parm               = PARM(0x00, 0, 7),
-       .gate_parm              = PARM(0x00, 7, 1),
-};
-
-static const struct composite_conf mali_conf __initconst = {
-       .mux_table              = mux_table_mali,
-       .mux_parm               = PARM(0x00, 9, 3),
-       .div_parm               = PARM(0x00, 0, 7),
-       .gate_parm              = PARM(0x00, 8, 1),
-};
-
-static const struct clk_conf meson8b_xtal_conf __initconst =
-       FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", 0,
-                       PARM(0x00, 4, 7));
-
-static const struct clk_conf meson8b_clk_confs[] __initconst = {
-       FIXED_RATE(CLKID_ZERO, "zero", 0, 0),
-       PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll",
-           p_xtal, 0, &pll_confs),
-       PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll",
-           p_xtal, 0, &pll_confs),
-       PLL(MESON8B_REG_PLL_SYS, CLKID_PLL_SYS, "sys_pll",
-           p_xtal, 0, &sys_pll_conf),
-       FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2),
-       FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3),
-       FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4),
-       FIXED_FACTOR_DIV(CLKID_FCLK_DIV5, "fclk_div5", p_fclk_div, 0, 5),
-       FIXED_FACTOR_DIV(CLKID_FCLK_DIV7, "fclk_div7", p_fclk_div, 0, 7),
-       CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk,
-           cpu_div_table),
-       COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81,
-                 CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
-       COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
-                 CLK_IGNORE_UNUSED, &mali_conf),
-};
-
-static void __init meson8b_clkc_init(struct device_node *np)
-{
-       void __iomem *clk_base;
 
-       if (!meson_clk_init(np, CLK_NR_CLKS))
-               return;
+struct clk_mux meson8b_mpeg_clk_sel = {
+       .reg = (void *)MESON8B_REG_HHI_MPEG,
+       .mask = 0x7,
+       .shift = 12,
+       .flags = CLK_MUX_READ_ONLY,
+       .table = mux_table_clk81,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_sel",
+               .ops = &clk_mux_ro_ops,
+               /*
+                * FIXME bits 14:12 selects from 8 possible parents:
+                * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
+                * fclk_div4, fclk_div3, fclk_div5
+                */
+               .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
+                       "fclk_div5" },
+               .num_parents = 3,
+               .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
+       },
+};
 
-       /* XTAL */
-       clk_base = of_iomap(np, 0);
-       if (!clk_base) {
-               pr_err("%s: Unable to map xtal base\n", __func__);
-               return;
-       }
+struct clk_divider meson8b_mpeg_clk_div = {
+       .reg = (void *)MESON8B_REG_HHI_MPEG,
+       .shift = 0,
+       .width = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_sel" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
+       },
+};
 
-       meson_clk_register_clks(&meson8b_xtal_conf, 1, clk_base);
-       iounmap(clk_base);
+struct clk_gate meson8b_clk81 = {
+       .reg = (void *)MESON8B_REG_HHI_MPEG,
+       .bit_idx = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "clk81",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_div" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
+       },
+};
+
+static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
+       .hws = {
+               [CLKID_XTAL] = &meson8b_xtal.hw,
+               [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
+               [CLKID_PLL_VID] = &meson8b_vid_pll.hw,
+               [CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
+               [CLKID_FCLK_DIV2] = &meson8b_fclk_div2.hw,
+               [CLKID_FCLK_DIV3] = &meson8b_fclk_div3.hw,
+               [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw,
+               [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw,
+               [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw,
+               [CLKID_CPUCLK] = &meson8b_cpu_clk.hw,
+               [CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw,
+               [CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw,
+               [CLKID_CLK81] = &meson8b_clk81.hw,
+       },
+       .num = CLK_NR_CLKS,
+};
+
+static struct meson_clk_pll *const meson8b_clk_plls[] = {
+       &meson8b_fixed_pll,
+       &meson8b_vid_pll,
+       &meson8b_sys_pll,
+};
+
+static int meson8b_clkc_probe(struct platform_device *pdev)
+{
+       void __iomem *clk_base;
+       int ret, clkid, i;
+       struct clk_hw *parent_hw;
+       struct clk *parent_clk;
+       struct device *dev = &pdev->dev;
 
        /*  Generic clocks and PLLs */
-       clk_base = of_iomap(np, 1);
+       clk_base = of_iomap(dev->of_node, 1);
        if (!clk_base) {
                pr_err("%s: Unable to map clk base\n", __func__);
-               return;
+               return -ENXIO;
+       }
+
+       /* Populate base address for PLLs */
+       for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
+               meson8b_clk_plls[i]->base = clk_base;
+
+       /* Populate the base address for CPU clk */
+       meson8b_cpu_clk.base = clk_base;
+
+       /* Populate the base address for the MPEG clks */
+       meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg;
+       meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
+       meson8b_clk81.reg = clk_base + (u32)meson8b_clk81.reg;
+
+       /*
+        * register all clks
+        * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
+        */
+       for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) {
+               /* array might be sparse */
+               if (!meson8b_hw_onecell_data.hws[clkid])
+                       continue;
+
+               /* FIXME convert to devm_clk_register */
+               ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]);
+               if (ret)
+                       goto iounmap;
        }
 
-       meson_clk_register_clks(meson8b_clk_confs,
-                               ARRAY_SIZE(meson8b_clk_confs),
-                               clk_base);
+       /*
+        * Register CPU clk notifier
+        *
+        * FIXME this is wrong for a lot of reasons. First, the muxes should be
+        * struct clk_hw objects. Second, we shouldn't program the muxes in
+        * notifier handlers. The tricky programming sequence will be handled
+        * by the forthcoming coordinated clock rates mechanism once that
+        * feature is released.
+        *
+        * Furthermore, looking up the parent this way is terrible. At some
+        * point we will stop allocating a default struct clk when registering
+        * a new clk_hw, and this hack will no longer work. Releasing the ccr
+        * feature before that time solves the problem :-)
+        */
+       parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw);
+       parent_clk = parent_hw->clk;
+       ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb);
+       if (ret) {
+               pr_err("%s: failed to register clock notifier for cpu_clk\n",
+                               __func__);
+               goto iounmap;
+       }
+
+       return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+                       &meson8b_hw_onecell_data);
+
+iounmap:
+       iounmap(clk_base);
+       return ret;
+}
+
+static const struct of_device_id meson8b_clkc_match_table[] = {
+       { .compatible = "amlogic,meson8b-clkc" },
+       { }
+};
+
+static struct platform_driver meson8b_driver = {
+       .probe          = meson8b_clkc_probe,
+       .driver         = {
+               .name   = "meson8b-clkc",
+               .of_match_table = meson8b_clkc_match_table,
+       },
+};
+
+static int __init meson8b_clkc_init(void)
+{
+       return platform_driver_register(&meson8b_driver);
 }
-CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init);
+device_initcall(meson8b_clkc_init);
index 481b2646b4964ba5974dc7a4f4f0f40742796b3e..90d740a2fc0dd1c1765098d5d25904ef1f4f3c0e 100644 (file)
@@ -87,7 +87,7 @@ enum {
 
 enum {
        /* Start from the last defined clock in dt bindings */
-       LPC32XX_CLK_ADC_DIV = LPC32XX_CLK_HCLK_PLL + 1,
+       LPC32XX_CLK_ADC_DIV = LPC32XX_CLK_PERIPH + 1,
        LPC32XX_CLK_ADC_RTC,
        LPC32XX_CLK_TEST1,
        LPC32XX_CLK_TEST2,
@@ -99,7 +99,6 @@ enum {
        LPC32XX_CLK_HCLK_DIV_PERIPH,
        LPC32XX_CLK_HCLK_DIV,
        LPC32XX_CLK_HCLK,
-       LPC32XX_CLK_PERIPH,
        LPC32XX_CLK_ARM,
        LPC32XX_CLK_ARM_VFP,
 
index 6dc55864979c8843e03cb792b57f1af8e64ecdc6..c347a0d44bc8b0bbd108c92992099f3634b82134 100644 (file)
@@ -2290,6 +2290,32 @@ static struct clk_branch sdc5_h_clk = {
        },
 };
 
+static struct clk_branch ebi2_2x_clk = {
+       .halt_reg = 0x2fcc,
+       .halt_bit = 18,
+       .clkr = {
+               .enable_reg = 0x2660,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "ebi2_2x_clk",
+                       .ops = &clk_branch_ops,
+               },
+       },
+};
+
+static struct clk_branch ebi2_clk = {
+       .halt_reg = 0x2fcc,
+       .halt_bit = 19,
+       .clkr = {
+               .enable_reg = 0x2664,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "ebi2_clk",
+                       .ops = &clk_branch_ops,
+               },
+       },
+};
+
 static struct clk_branch adm0_clk = {
        .halt_reg = 0x2fdc,
        .halt_check = BRANCH_HALT_VOTED,
@@ -2533,6 +2559,8 @@ static struct clk_regmap *gcc_msm8660_clks[] = {
        [SDC3_H_CLK] = &sdc3_h_clk.clkr,
        [SDC4_H_CLK] = &sdc4_h_clk.clkr,
        [SDC5_H_CLK] = &sdc5_h_clk.clkr,
+       [EBI2_2X_CLK] = &ebi2_2x_clk.clkr,
+       [EBI2_CLK] = &ebi2_clk.clkr,
        [ADM0_CLK] = &adm0_clk.clkr,
        [ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr,
        [ADM1_CLK] = &adm1_clk.clkr,
index c9b96f318d9c84159841b0ba40bd6e35cf841d3b..bbf732bbc3fdc37dd79fd6475461356e64b85538 100644 (file)
@@ -2891,21 +2891,6 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
        },
 };
 
-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 = {
@@ -3308,7 +3293,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = {
        [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,
index 2115ce410cfb4bc9607744ac03ff506fb330adf8..41a12d376799ae8c4b358f5f0cc3e5846b98cfcf 100644 (file)
@@ -1,6 +1,7 @@
 config CLK_RENESAS_CPG_MSSR
        bool
        default y if ARCH_R8A7795
+       default y if ARCH_R8A7796
 
 config CLK_RENESAS_CPG_MSTP
        bool
@@ -11,6 +12,7 @@ config CLK_RENESAS_CPG_MSTP
        default y if ARCH_R8A7779
        default y if ARCH_R8A7790
        default y if ARCH_R8A7791
+       default y if ARCH_R8A7792
        default y if ARCH_R8A7793
        default y if ARCH_R8A7794
        default y if ARCH_SH73A0
index ead8bb8435249493958f2320c5c15aca9430fa66..90dd0db7d9c6ef7c328c1ff981872d7e24623d84 100644 (file)
@@ -6,9 +6,11 @@ obj-$(CONFIG_ARCH_R8A7778)             += clk-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)             += clk-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)             += clk-rcar-gen2.o clk-div6.o
 obj-$(CONFIG_ARCH_R8A7791)             += clk-rcar-gen2.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7792)             += clk-rcar-gen2.o clk-div6.o
 obj-$(CONFIG_ARCH_R8A7793)             += clk-rcar-gen2.o clk-div6.o
 obj-$(CONFIG_ARCH_R8A7794)             += clk-rcar-gen2.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7795)             += r8a7795-cpg-mssr.o
+obj-$(CONFIG_ARCH_R8A7795)             += r8a7795-cpg-mssr.o rcar-gen3-cpg.o
+obj-$(CONFIG_ARCH_R8A7796)             += r8a7796-cpg-mssr.o rcar-gen3-cpg.o
 obj-$(CONFIG_ARCH_SH73A0)              += clk-sh73a0.o clk-div6.o
 
 obj-$(CONFIG_CLK_RENESAS_CPG_MSSR)     += renesas-cpg-mssr.o clk-div6.o
index ca5519c583d4bf57d1c948abc4bf76ee4b8e60c7..d359c92e13a65c00725f3a1178a1096babc0e226 100644 (file)
  * the Free Software Foundation; version 2 of the License.
  */
 
-#include <linux/bug.h>
-#include <linux/clk.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 <linux/slab.h>
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 
 #include "renesas-cpg-mssr.h"
-
-#define CPG_RCKCR      0x240
+#include "rcar-gen3-cpg.h"
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
@@ -58,20 +50,6 @@ enum clk_ids {
        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,
-       CLK_TYPE_GEN3_SD,
-       CLK_TYPE_GEN3_R,
-};
-
-#define DEF_GEN3_SD(_name, _id, _parent, _offset)      \
-       DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
-
 static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
        /* External Clock Inputs */
        DEF_INPUT("extal",  CLK_EXTAL),
@@ -129,6 +107,9 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
 };
 
 static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
+       DEF_MOD("fdp1-2",                117,   R8A7795_CLK_S2D1),
+       DEF_MOD("fdp1-1",                118,   R8A7795_CLK_S2D1),
+       DEF_MOD("fdp1-0",                119,   R8A7795_CLK_S2D1),
        DEF_MOD("scif5",                 202,   R8A7795_CLK_S3D4),
        DEF_MOD("scif4",                 203,   R8A7795_CLK_S3D4),
        DEF_MOD("scif3",                 204,   R8A7795_CLK_S3D4),
@@ -157,11 +138,20 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
        DEF_MOD("intc-ap",               408,   R8A7795_CLK_S3D1),
        DEF_MOD("audmac0",               502,   R8A7795_CLK_S3D4),
        DEF_MOD("audmac1",               501,   R8A7795_CLK_S3D4),
+       DEF_MOD("drif7",                 508,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif6",                 509,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif5",                 510,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif4",                 511,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif3",                 512,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif2",                 513,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif1",                 514,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif0",                 515,   R8A7795_CLK_S3D2),
        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("thermal",               522,   R8A7795_CLK_CP),
        DEF_MOD("pwm",                   523,   R8A7795_CLK_S3D4),
        DEF_MOD("fcpvd3",                600,   R8A7795_CLK_S2D1),
        DEF_MOD("fcpvd2",                601,   R8A7795_CLK_S2D1),
@@ -199,7 +189,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
        DEF_MOD("du2",                   722,   R8A7795_CLK_S2D1),
        DEF_MOD("du1",                   723,   R8A7795_CLK_S2D1),
        DEF_MOD("du0",                   724,   R8A7795_CLK_S2D1),
-       DEF_MOD("lvds",                  727,   R8A7795_CLK_S2D1),
+       DEF_MOD("lvds",                  727,   R8A7795_CLK_S0D4),
        DEF_MOD("hdmi1",                 728,   R8A7795_CLK_HDMI),
        DEF_MOD("hdmi0",                 729,   R8A7795_CLK_HDMI),
        DEF_MOD("vin7",                  804,   R8A7795_CLK_S2D1),
@@ -262,225 +252,6 @@ static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
        MOD_CLK_ID(408),        /* INTC-AP (GIC) */
 };
 
-/* -----------------------------------------------------------------------------
- * SDn Clock
- *
- */
-#define CPG_SD_STP_HCK         BIT(9)
-#define CPG_SD_STP_CK          BIT(8)
-
-#define CPG_SD_STP_MASK                (CPG_SD_STP_HCK | CPG_SD_STP_CK)
-#define CPG_SD_FC_MASK         (0x7 << 2 | 0x3 << 0)
-
-#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
-{ \
-       .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
-              ((stp_ck) ? CPG_SD_STP_CK : 0) | \
-              ((sd_srcfc) << 2) | \
-              ((sd_fc) << 0), \
-       .div = (sd_div), \
-}
-
-struct sd_div_table {
-       u32 val;
-       unsigned int div;
-};
-
-struct sd_clock {
-       struct clk_hw hw;
-       void __iomem *reg;
-       const struct sd_div_table *div_table;
-       unsigned int div_num;
-       unsigned int div_min;
-       unsigned int div_max;
-};
-
-/* SDn divider
- *                     sd_srcfc   sd_fc   div
- * stp_hck   stp_ck    (div)      (div)     = sd_srcfc x sd_fc
- *-------------------------------------------------------------------
- *  0         0         0 (1)      1 (4)      4
- *  0         0         1 (2)      1 (4)      8
- *  1         0         2 (4)      1 (4)     16
- *  1         0         3 (8)      1 (4)     32
- *  1         0         4 (16)     1 (4)     64
- *  0         0         0 (1)      0 (2)      2
- *  0         0         1 (2)      0 (2)      4
- *  1         0         2 (4)      0 (2)      8
- *  1         0         3 (8)      0 (2)     16
- *  1         0         4 (16)     0 (2)     32
- */
-static const struct sd_div_table cpg_sd_div_table[] = {
-/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  stp_ck,   sd_srcfc,   sd_fc,  sd_div) */
-       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          1,        4),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          1,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          1,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          1,       32),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          1,       64),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          0,        2),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          0,        4),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          0,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          0,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          0,       32),
-};
-
-#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
-
-static int cpg_sd_clock_enable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       u32 val, sd_fc;
-       unsigned int i;
-
-       val = clk_readl(clock->reg);
-
-       sd_fc = val & CPG_SD_FC_MASK;
-       for (i = 0; i < clock->div_num; i++)
-               if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       val &= ~(CPG_SD_STP_MASK);
-       val |= clock->div_table[i].val & CPG_SD_STP_MASK;
-
-       clk_writel(val, clock->reg);
-
-       return 0;
-}
-
-static void cpg_sd_clock_disable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
-}
-
-static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       return !(clk_readl(clock->reg) & CPG_SD_STP_MASK);
-}
-
-static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
-                                               unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned long rate = parent_rate;
-       u32 val, sd_fc;
-       unsigned int i;
-
-       val = clk_readl(clock->reg);
-
-       sd_fc = val & CPG_SD_FC_MASK;
-       for (i = 0; i < clock->div_num; i++)
-               if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div);
-}
-
-static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
-                                         unsigned long rate,
-                                         unsigned long parent_rate)
-{
-       unsigned int div;
-
-       if (!rate)
-               rate = 1;
-
-       div = DIV_ROUND_CLOSEST(parent_rate, rate);
-
-       return clamp_t(unsigned int, div, clock->div_min, clock->div_max);
-}
-
-static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
-                                     unsigned long *parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate);
-
-       return DIV_ROUND_CLOSEST(*parent_rate, div);
-}
-
-static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
-                                  unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
-       u32 val;
-       unsigned int i;
-
-       for (i = 0; i < clock->div_num; i++)
-               if (div == clock->div_table[i].div)
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       val = clk_readl(clock->reg);
-       val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-       val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-       clk_writel(val, clock->reg);
-
-       return 0;
-}
-
-static const struct clk_ops cpg_sd_clock_ops = {
-       .enable = cpg_sd_clock_enable,
-       .disable = cpg_sd_clock_disable,
-       .is_enabled = cpg_sd_clock_is_enabled,
-       .recalc_rate = cpg_sd_clock_recalc_rate,
-       .round_rate = cpg_sd_clock_round_rate,
-       .set_rate = cpg_sd_clock_set_rate,
-};
-
-static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
-                                              void __iomem *base,
-                                              const char *parent_name)
-{
-       struct clk_init_data init;
-       struct sd_clock *clock;
-       struct clk *clk;
-       unsigned int i;
-
-       clock = kzalloc(sizeof(*clock), GFP_KERNEL);
-       if (!clock)
-               return ERR_PTR(-ENOMEM);
-
-       init.name = core->name;
-       init.ops = &cpg_sd_clock_ops;
-       init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
-
-       clock->reg = base + core->offset;
-       clock->hw.init = &init;
-       clock->div_table = cpg_sd_div_table;
-       clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
-
-       clock->div_max = clock->div_table[0].div;
-       clock->div_min = clock->div_max;
-       for (i = 1; i < clock->div_num; i++) {
-               clock->div_max = max(clock->div_max, clock->div_table[i].div);
-               clock->div_min = min(clock->div_min, clock->div_table[i].div);
-       }
-
-       clk = clk_register(NULL, &clock->hw);
-       if (IS_ERR(clk))
-               kfree(clock);
-
-       return clk;
-}
-
-#define CPG_PLL0CR     0x00d8
-#define CPG_PLL2CR     0x002c
-#define CPG_PLL4CR     0x01f4
 
 /*
  * CPG Clock Data
@@ -512,13 +283,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
                                         (((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 = {
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
        /* EXTAL div    PLL1 mult       PLL3 mult */
        { 1,            192,            192,    },
        { 1,            192,            128,    },
@@ -538,112 +303,9 @@ static const struct cpg_pll_config cpg_pll_configs[16] __initconst = {
        { 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;
-
-       case CLK_TYPE_GEN3_SD:
-               return cpg_sd_clk_register(core, base, __clk_get_name(parent));
-
-       case CLK_TYPE_GEN3_R:
-               /* RINT is default. Only if EXTALR is populated, we switch to it */
-               value = readl(base + CPG_RCKCR) & 0x3f;
-
-               if (clk_get_rate(clks[CLK_EXTALR])) {
-                       parent = clks[CLK_EXTALR];
-                       value |= BIT(15);
-               }
-
-               writel(value, base + CPG_RCKCR);
-               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)
 {
+       const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
        u32 cpg_mode = rcar_gen3_read_mode_pins();
 
        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
@@ -652,7 +314,7 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev)
                return -EINVAL;
        }
 
-       return 0;
+       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
 }
 
 const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
@@ -673,5 +335,5 @@ const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
 
        /* Callbacks */
        .init = r8a7795_cpg_mssr_init,
-       .cpg_clk_register = r8a7795_cpg_clk_register,
+       .cpg_clk_register = rcar_gen3_cpg_clk_register,
 };
diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c
new file mode 100644 (file)
index 0000000..c84b549
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Glider bvba
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * 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/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A7796_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
+};
+
+static const struct cpg_core_clk r8a7796_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",        R8A7796_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
+       DEF_FIXED("ztrd2",      R8A7796_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+       DEF_FIXED("zt",         R8A7796_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
+       DEF_FIXED("zx",         R8A7796_CLK_ZX,    CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED("s0d1",       R8A7796_CLK_S0D1,  CLK_S0,         1, 1),
+       DEF_FIXED("s0d2",       R8A7796_CLK_S0D2,  CLK_S0,         2, 1),
+       DEF_FIXED("s0d3",       R8A7796_CLK_S0D3,  CLK_S0,         3, 1),
+       DEF_FIXED("s0d4",       R8A7796_CLK_S0D4,  CLK_S0,         4, 1),
+       DEF_FIXED("s0d6",       R8A7796_CLK_S0D6,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d8",       R8A7796_CLK_S0D8,  CLK_S0,         8, 1),
+       DEF_FIXED("s0d12",      R8A7796_CLK_S0D12, CLK_S0,        12, 1),
+       DEF_FIXED("s1d1",       R8A7796_CLK_S1D1,  CLK_S1,         1, 1),
+       DEF_FIXED("s1d2",       R8A7796_CLK_S1D2,  CLK_S1,         2, 1),
+       DEF_FIXED("s1d4",       R8A7796_CLK_S1D4,  CLK_S1,         4, 1),
+       DEF_FIXED("s2d1",       R8A7796_CLK_S2D1,  CLK_S2,         1, 1),
+       DEF_FIXED("s2d2",       R8A7796_CLK_S2D2,  CLK_S2,         2, 1),
+       DEF_FIXED("s2d4",       R8A7796_CLK_S2D4,  CLK_S2,         4, 1),
+       DEF_FIXED("s3d1",       R8A7796_CLK_S3D1,  CLK_S3,         1, 1),
+       DEF_FIXED("s3d2",       R8A7796_CLK_S3D2,  CLK_S3,         2, 1),
+       DEF_FIXED("s3d4",       R8A7796_CLK_S3D4,  CLK_S3,         4, 1),
+
+       DEF_FIXED("cl",         R8A7796_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
+       DEF_FIXED("cp",         R8A7796_CLK_CP,    CLK_EXTAL,      2, 1),
+};
+
+static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
+       DEF_MOD("scif2",                 310,   R8A7796_CLK_S3D4),
+       DEF_MOD("intc-ap",               408,   R8A7796_CLK_S3D1),
+};
+
+static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(408),        /* INTC-AP (GIC) */
+};
+
+
+/*
+ * 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))
+
+static const struct rcar_gen3_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 int __init r8a7796_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+       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 rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
+}
+
+const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks = r8a7796_core_clks,
+       .num_core_clks = ARRAY_SIZE(r8a7796_core_clks),
+       .last_dt_core_clk = LAST_DT_CORE_CLK,
+       .num_total_core_clks = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks = r8a7796_mod_clks,
+       .num_mod_clks = ARRAY_SIZE(r8a7796_mod_clks),
+       .num_hw_mod_clks = 12 * 32,
+
+       /* Critical Module Clocks */
+       .crit_mod_clks = r8a7796_crit_mod_clks,
+       .num_crit_mod_clks = ARRAY_SIZE(r8a7796_crit_mod_clks),
+
+       /* Callbacks */
+       .init = r8a7796_cpg_mssr_init,
+       .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
new file mode 100644 (file)
index 0000000..bb4f2f9
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * R-Car Gen3 Clock Pulse Generator
+ *
+ * Copyright (C) 2015-2016 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.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+#define CPG_PLL0CR             0x00d8
+#define CPG_PLL2CR             0x002c
+#define CPG_PLL4CR             0x01f4
+
+
+/*
+ * SDn Clock
+ */
+#define CPG_SD_STP_HCK         BIT(9)
+#define CPG_SD_STP_CK          BIT(8)
+
+#define CPG_SD_STP_MASK                (CPG_SD_STP_HCK | CPG_SD_STP_CK)
+#define CPG_SD_FC_MASK         (0x7 << 2 | 0x3 << 0)
+
+#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
+{ \
+       .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
+              ((stp_ck) ? CPG_SD_STP_CK : 0) | \
+              ((sd_srcfc) << 2) | \
+              ((sd_fc) << 0), \
+       .div = (sd_div), \
+}
+
+struct sd_div_table {
+       u32 val;
+       unsigned int div;
+};
+
+struct sd_clock {
+       struct clk_hw hw;
+       void __iomem *reg;
+       const struct sd_div_table *div_table;
+       unsigned int div_num;
+       unsigned int div_min;
+       unsigned int div_max;
+};
+
+/* SDn divider
+ *                     sd_srcfc   sd_fc   div
+ * stp_hck   stp_ck    (div)      (div)     = sd_srcfc x sd_fc
+ *-------------------------------------------------------------------
+ *  0         0         0 (1)      1 (4)      4
+ *  0         0         1 (2)      1 (4)      8
+ *  1         0         2 (4)      1 (4)     16
+ *  1         0         3 (8)      1 (4)     32
+ *  1         0         4 (16)     1 (4)     64
+ *  0         0         0 (1)      0 (2)      2
+ *  0         0         1 (2)      0 (2)      4
+ *  1         0         2 (4)      0 (2)      8
+ *  1         0         3 (8)      0 (2)     16
+ *  1         0         4 (16)     0 (2)     32
+ */
+static const struct sd_div_table cpg_sd_div_table[] = {
+/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  stp_ck,   sd_srcfc,   sd_fc,  sd_div) */
+       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          1,        4),
+       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          1,        8),
+       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          1,       16),
+       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          1,       32),
+       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          1,       64),
+       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          0,        2),
+       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          0,        4),
+       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          0,        8),
+       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          0,       16),
+       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          0,       32),
+};
+
+#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
+
+static int cpg_sd_clock_enable(struct clk_hw *hw)
+{
+       struct sd_clock *clock = to_sd_clock(hw);
+       u32 val, sd_fc;
+       unsigned int i;
+
+       val = clk_readl(clock->reg);
+
+       sd_fc = val & CPG_SD_FC_MASK;
+       for (i = 0; i < clock->div_num; i++)
+               if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
+                       break;
+
+       if (i >= clock->div_num)
+               return -EINVAL;
+
+       val &= ~(CPG_SD_STP_MASK);
+       val |= clock->div_table[i].val & CPG_SD_STP_MASK;
+
+       clk_writel(val, clock->reg);
+
+       return 0;
+}
+
+static void cpg_sd_clock_disable(struct clk_hw *hw)
+{
+       struct sd_clock *clock = to_sd_clock(hw);
+
+       clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
+}
+
+static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
+{
+       struct sd_clock *clock = to_sd_clock(hw);
+
+       return !(clk_readl(clock->reg) & CPG_SD_STP_MASK);
+}
+
+static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       struct sd_clock *clock = to_sd_clock(hw);
+       unsigned long rate = parent_rate;
+       u32 val, sd_fc;
+       unsigned int i;
+
+       val = clk_readl(clock->reg);
+
+       sd_fc = val & CPG_SD_FC_MASK;
+       for (i = 0; i < clock->div_num; i++)
+               if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
+                       break;
+
+       if (i >= clock->div_num)
+               return -EINVAL;
+
+       return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div);
+}
+
+static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
+                                         unsigned long rate,
+                                         unsigned long parent_rate)
+{
+       unsigned int div;
+
+       if (!rate)
+               rate = 1;
+
+       div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+       return clamp_t(unsigned int, div, clock->div_min, clock->div_max);
+}
+
+static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
+                                     unsigned long *parent_rate)
+{
+       struct sd_clock *clock = to_sd_clock(hw);
+       unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate);
+
+       return DIV_ROUND_CLOSEST(*parent_rate, div);
+}
+
+static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+{
+       struct sd_clock *clock = to_sd_clock(hw);
+       unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
+       u32 val;
+       unsigned int i;
+
+       for (i = 0; i < clock->div_num; i++)
+               if (div == clock->div_table[i].div)
+                       break;
+
+       if (i >= clock->div_num)
+               return -EINVAL;
+
+       val = clk_readl(clock->reg);
+       val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
+       val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
+       clk_writel(val, clock->reg);
+
+       return 0;
+}
+
+static const struct clk_ops cpg_sd_clock_ops = {
+       .enable = cpg_sd_clock_enable,
+       .disable = cpg_sd_clock_disable,
+       .is_enabled = cpg_sd_clock_is_enabled,
+       .recalc_rate = cpg_sd_clock_recalc_rate,
+       .round_rate = cpg_sd_clock_round_rate,
+       .set_rate = cpg_sd_clock_set_rate,
+};
+
+static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
+                                              void __iomem *base,
+                                              const char *parent_name)
+{
+       struct clk_init_data init;
+       struct sd_clock *clock;
+       struct clk *clk;
+       unsigned int i;
+
+       clock = kzalloc(sizeof(*clock), GFP_KERNEL);
+       if (!clock)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = core->name;
+       init.ops = &cpg_sd_clock_ops;
+       init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       clock->reg = base + core->offset;
+       clock->hw.init = &init;
+       clock->div_table = cpg_sd_div_table;
+       clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
+
+       clock->div_max = clock->div_table[0].div;
+       clock->div_min = clock->div_max;
+       for (i = 1; i < clock->div_num; i++) {
+               clock->div_max = max(clock->div_max, clock->div_table[i].div);
+               clock->div_min = min(clock->div_min, clock->div_table[i].div);
+       }
+
+       clk = clk_register(NULL, &clock->hw);
+       if (IS_ERR(clk))
+               kfree(clock);
+
+       return clk;
+}
+
+
+static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_clk_extalr __initdata;
+
+struct clk * __init rcar_gen3_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;
+
+       case CLK_TYPE_GEN3_SD:
+               return cpg_sd_clk_register(core, base, __clk_get_name(parent));
+
+       case CLK_TYPE_GEN3_R:
+               /*
+                * RINT is default.
+                * Only if EXTALR is populated, we switch to it.
+                */
+               value = readl(base + CPG_RCKCR) & 0x3f;
+
+               if (clk_get_rate(clks[cpg_clk_extalr])) {
+                       parent = clks[cpg_clk_extalr];
+                       value |= BIT(15);
+               }
+
+               writel(value, base + CPG_RCKCR);
+               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
+
+u32 __init 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;
+}
+
+int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
+                             unsigned int clk_extalr)
+{
+       cpg_pll_config = config;
+       cpg_clk_extalr = clk_extalr;
+       return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
new file mode 100644 (file)
index 0000000..f699085
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * R-Car Gen3 Clock Pulse Generator
+ *
+ * Copyright (C) 2015-2016 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_RCAR_GEN3_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN3_CPG_H__
+
+enum rcar_gen3_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,
+       CLK_TYPE_GEN3_SD,
+       CLK_TYPE_GEN3_R,
+};
+
+#define DEF_GEN3_SD(_name, _id, _parent, _offset)      \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
+
+struct rcar_gen3_cpg_pll_config {
+       unsigned int extal_div;
+       unsigned int pll1_mult;
+       unsigned int pll3_mult;
+};
+
+#define CPG_RCKCR      0x240
+
+u32 rcar_gen3_read_mode_pins(void);
+struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
+       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+       struct clk **clks, void __iomem *base);
+int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
+                      unsigned int clk_extalr);
+
+#endif
index 210cd744a7a97bbd278ae7f671bf5b2403d4af1e..e1365e7491ae02a0519ec94aaea92baa5f58d55e 100644 (file)
@@ -508,6 +508,12 @@ static const struct of_device_id cpg_mssr_match[] = {
                .compatible = "renesas,r8a7795-cpg-mssr",
                .data = &r8a7795_cpg_mssr_info,
        },
+#endif
+#ifdef CONFIG_ARCH_R8A7796
+       {
+               .compatible = "renesas,r8a7796-cpg-mssr",
+               .data = &r8a7796_cpg_mssr_info,
+       },
 #endif
        { /* sentinel */ }
 };
index 0d1e3e811e79bf431c0640667af9343b92a3cbf0..ee7edfaf14089cefbd5949a484334c8de7d181dc 100644 (file)
@@ -131,4 +131,5 @@ struct cpg_mssr_info {
 };
 
 extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
 #endif
index 016bdb0b793ab94501fa59f1e185cf3c9f44dc87..db6e5a9e6de64a781122695a8e807f937c9e0933 100644 (file)
@@ -151,8 +151,8 @@ 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_mac_extclk_p)   = { "ext_gmac", "phy_50m_out" };
+PNAME(mux_sclk_gmac_pre_p)     = { "sclk_gmac_src", "sclk_mac_extclk" };
 PNAME(mux_sclk_macphy_p)       = { "sclk_gmac_src", "ext_gmac" };
 
 static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = {
@@ -170,6 +170,34 @@ static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = {
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
 
+static struct rockchip_clk_branch rk3228_i2s0_fracmux __initdata =
+       MUX(0, "i2s0_pre", mux_i2s0_p, CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(9), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3228_i2s1_fracmux __initdata =
+       MUX(0, "i2s1_pre", mux_i2s1_pre_p, CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3228_i2s2_fracmux __initdata =
+       MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(16), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3228_spdif_fracmux __initdata =
+       MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(6), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3228_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 rk3228_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 rk3228_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 rk3228_clk_branches[] __initdata = {
        /*
         * Clock-Architecture Diagram 1
@@ -335,7 +363,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(2), 6, GFLAGS),
 
        GATE(0, "sclk_hsadc", "ext_hsadc", 0,
-                       RK3288_CLKGATE_CON(10), 12, GFLAGS),
+                       RK2928_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,
@@ -379,22 +407,21 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
        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,
+       COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(8), 0,
+                       RK2928_CLKGATE_CON(0), 4, GFLAGS,
+                       &rk3228_i2s0_fracmux),
+       GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
                        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,
+       COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(7), 0,
+                       RK2928_CLKGATE_CON(0), 11, GFLAGS,
+                       &rk3228_i2s1_fracmux),
+       GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
                        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,
@@ -403,21 +430,20 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
        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,
+       COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(30), 0,
+                       RK2928_CLKGATE_CON(0), 8, GFLAGS,
+                       &rk3228_i2s2_fracmux),
+       GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
                        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),
+       COMPOSITE_FRACMUX(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(20), 0,
+                       RK2928_CLKGATE_CON(2), 12, GFLAGS,
+                       &rk3228_spdif_fracmux),
 
        GATE(0, "jtag", "ext_jtag", 0,
                        RK2928_CLKGATE_CON(1), 3, GFLAGS),
@@ -456,45 +482,42 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
        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,
+       COMPOSITE_FRACMUX(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_CLKGATE_CON(1), 9, GFLAGS,
+                       &rk3228_uart0_fracmux),
+       COMPOSITE_FRACMUX(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_CLKGATE_CON(1), 11, GFLAGS,
+                       &rk3228_uart1_fracmux),
+       COMPOSITE_FRACMUX(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),
+                       RK2928_CLKGATE_CON(1), 13, GFLAGS,
+                       &rk3228_uart2_fracmux),
 
        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,
+       COMPOSITE(SCLK_MAC_SRC, "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,
+       MUX(SCLK_MAC_EXTCLK, "sclk_mac_extclk", mux_sclk_mac_extclk_p, 0,
                        RK2928_CLKSEL_CON(29), 10, 1, MFLAGS),
-       MUX(0, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0,
+       MUX(SCLK_MAC, "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,
+       GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_gmac_pre", 0,
                        RK2928_CLKGATE_CON(5), 4, GFLAGS),
-       GATE(0, "sclk_mac_ref", "sclk_gmac_pre", 0,
+       GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_gmac_pre", 0,
                        RK2928_CLKGATE_CON(5), 3, GFLAGS),
-       GATE(0, "sclk_mac_rx", "sclk_gmac_pre", 0,
+       GATE(SCLK_MAC_RX, "sclk_mac_rx", "sclk_gmac_pre", 0,
                        RK2928_CLKGATE_CON(5), 5, GFLAGS),
-       GATE(0, "sclk_mac_tx", "sclk_gmac_pre", 0,
+       GATE(SCLK_MAC_TX, "sclk_mac_tx", "sclk_gmac_pre", 0,
                        RK2928_CLKGATE_CON(5), 6, GFLAGS),
-       COMPOSITE(0, "sclk_macphy", mux_sclk_macphy_p, 0,
+       COMPOSITE(SCLK_MAC_PHY, "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,
+       COMPOSITE(SCLK_MAC_OUT, "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),
 
@@ -528,7 +551,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 
        /* 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(ACLK_GMAC, "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),
@@ -544,7 +567,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
        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(PCLK_GMAC, "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 */
@@ -558,10 +581,10 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
        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(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS),
+       GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS),
+       GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+       GATE(HCLK_SPDIF_8CH, "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),
index 8059a8d3ea36430e359e4857b33b58a5f4952aec..c109d80e7a8a96340f187a81b3699ae115928a71 100644 (file)
@@ -586,7 +586,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
                        RK3399_CLKGATE_CON(8), 15, GFLAGS),
 
        COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, 0,
-                       RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS,
                        RK3399_CLKGATE_CON(10), 6, GFLAGS),
        /* i2s */
        COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0,
@@ -1500,6 +1500,7 @@ static void __init rk3399_clk_init(struct device_node *np)
 {
        struct rockchip_clk_provider *ctx;
        void __iomem *reg_base;
+       struct clk *clk;
 
        reg_base = of_iomap(np, 0);
        if (!reg_base) {
@@ -1514,6 +1515,14 @@ static void __init rk3399_clk_init(struct device_node *np)
                return;
        }
 
+       /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
+       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_alive", 0, 1, 1);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock pclk_wdt: %ld\n",
+                       __func__, PTR_ERR(clk));
+       else
+               rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
+
        rockchip_clk_register_plls(ctx, rk3399_pll_clks,
                                   ARRAY_SIZE(rk3399_pll_clks), -1);
 
index 20c5fe92ab4adf9da4e655e264f2ba1d486bd8b5..addc65270e43415c5c5e57fefe3555789db2d3c6 100644 (file)
@@ -9,6 +9,15 @@ config EXYNOS_ARM64_COMMON_CLK
        bool "Samsung Exynos ARMv8-family clock controller support" if COMPILE_TEST
        depends on COMMON_CLK_SAMSUNG
 
+config EXYNOS_AUDSS_CLK_CON
+       tristate "Samsung Exynos AUDSS clock controller support"
+       depends on COMMON_CLK_SAMSUNG
+       default y if ARCH_EXYNOS
+       help
+         Support for the Audio Subsystem CLKCON clock controller present
+         on some Exynos SoC variants. Choose M or Y here if you want to
+         use audio devices such as I2S, PCM, etc.
+
 # For S3C24XX platforms, select following symbols:
 config S3C2410_COMMON_CLK
        bool "Samsung S3C2410 clock controller support" if COMPILE_TEST
index fc367d4b2902b14286ff4075f6d452612dd08f01..57f4dc6dc4474cccc23a934450d07302a5a742bc 100644 (file)
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_EXYNOS5410)  += clk-exynos5410.o
 obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5420.o
 obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK)  += clk-exynos5433.o
 obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
-obj-$(CONFIG_ARCH_EXYNOS)      += clk-exynos-audss.o
+obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
 obj-$(CONFIG_ARCH_EXYNOS)      += clk-exynos-clkout.o
 obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK)  += clk-exynos7.o
 obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
index 813003d6ce097f4bbbda48e7d471b73388b611ac..8bf7e805fd34913ad08622824309753a86850b3a 100644 (file)
 #define E4210_DIV_STAT_CPU0    0x400
 #define E4210_DIV_STAT_CPU1    0x404
 
+#define E5433_MUX_SEL2         0x008
+#define E5433_MUX_STAT2                0x208
+#define E5433_DIV_CPU0         0x400
+#define E5433_DIV_CPU1         0x404
+#define E5433_DIV_STAT_CPU0    0x500
+#define E5433_DIV_STAT_CPU1    0x504
+
 #define E4210_DIV0_RATIO0_MASK 0x7
 #define E4210_DIV1_HPM_MASK    (0x7 << 4)
 #define E4210_DIV1_COPY_MASK   (0x7 << 0)
@@ -252,6 +259,102 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
        return 0;
 }
 
+/*
+ * Helper function to set the 'safe' dividers for the CPU clock. The parameters
+ * div and mask contain the divider value and the register bit mask of the
+ * dividers to be programmed.
+ */
+static void exynos5433_set_safe_div(void __iomem *base, unsigned long div,
+                                       unsigned long mask)
+{
+       unsigned long div0;
+
+       div0 = readl(base + E5433_DIV_CPU0);
+       div0 = (div0 & ~mask) | (div & mask);
+       writel(div0, base + E5433_DIV_CPU0);
+       wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, mask);
+}
+
+/* handler for pre-rate change notification from parent clock */
+static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
+                       struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+       const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+       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) {
+               if (cfg_data->prate == 0)
+                       return -EINVAL;
+               cfg_data++;
+       }
+
+       spin_lock_irqsave(cpuclk->lock, flags);
+
+       /*
+        * For the selected PLL clock frequency, get the pre-defined divider
+        * values.
+        */
+       div0 = cfg_data->div0;
+       div1 = cfg_data->div1;
+
+       /*
+        * If the old parent clock speed is less than the clock speed of
+        * the alternate parent, then it should be ensured that at no point
+        * the armclk speed is more than the old_prate until the dividers are
+        * set.  Also workaround the issue of the dividers being set to lower
+        * values before the parent clock speed is set to new lower speed
+        * (this can result in too high speed of armclk output clocks).
+        */
+       if (alt_prate > ndata->old_rate || ndata->old_rate > ndata->new_rate) {
+               unsigned long tmp_rate = min(ndata->old_rate, ndata->new_rate);
+
+               alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1;
+               WARN_ON(alt_div >= MAX_DIV);
+
+               exynos5433_set_safe_div(base, alt_div, alt_div_mask);
+               div0 |= alt_div;
+       }
+
+       /* select the alternate parent */
+       mux_reg = readl(base + E5433_MUX_SEL2);
+       writel(mux_reg | 1, base + E5433_MUX_SEL2);
+       wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 2);
+
+       /* alternate parent is active now. set the dividers */
+       writel(div0, base + E5433_DIV_CPU0);
+       wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, DIV_MASK_ALL);
+
+       writel(div1, base + E5433_DIV_CPU1);
+       wait_until_divider_stable(base + E5433_DIV_STAT_CPU1, DIV_MASK_ALL);
+
+       spin_unlock_irqrestore(cpuclk->lock, flags);
+       return 0;
+}
+
+/* handler for post-rate change notification from parent clock */
+static int exynos5433_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
+                       struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+       unsigned long div = 0, div_mask = DIV_MASK;
+       unsigned long mux_reg;
+       unsigned long flags;
+
+       spin_lock_irqsave(cpuclk->lock, flags);
+
+       /* select apll as the alternate parent */
+       mux_reg = readl(base + E5433_MUX_SEL2);
+       writel(mux_reg & ~1, base + E5433_MUX_SEL2);
+       wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 1);
+
+       exynos5433_set_safe_div(base, div, div_mask);
+       spin_unlock_irqrestore(cpuclk->lock, flags);
+       return 0;
+}
+
 /*
  * This notifier function is called for the pre-rate and post-rate change
  * notifications of the parent clock of cpuclk.
@@ -275,6 +378,29 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
        return notifier_from_errno(err);
 }
 
+/*
+ * This notifier function is called for the pre-rate and post-rate change
+ * notifications of the parent clock of cpuclk.
+ */
+static int exynos5433_cpuclk_notifier_cb(struct notifier_block *nb,
+                               unsigned long event, void *data)
+{
+       struct clk_notifier_data *ndata = data;
+       struct exynos_cpuclk *cpuclk;
+       void __iomem *base;
+       int err = 0;
+
+       cpuclk = container_of(nb, struct exynos_cpuclk, clk_nb);
+       base = cpuclk->ctrl_base;
+
+       if (event == PRE_RATE_CHANGE)
+               err = exynos5433_cpuclk_pre_rate_change(ndata, cpuclk, base);
+       else if (event == POST_RATE_CHANGE)
+               err = exynos5433_cpuclk_post_rate_change(ndata, cpuclk, base);
+
+       return notifier_from_errno(err);
+}
+
 /* helper function to register a CPU clock */
 int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
                unsigned int lookup_id, const char *name, const char *parent,
@@ -301,7 +427,10 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
        cpuclk->ctrl_base = ctx->reg_base + offset;
        cpuclk->lock = &ctx->lock;
        cpuclk->flags = flags;
-       cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
+       if (flags & CLK_CPU_HAS_E5433_REGS_LAYOUT)
+               cpuclk->clk_nb.notifier_call = exynos5433_cpuclk_notifier_cb;
+       else
+               cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
 
        cpuclk->alt_parent = __clk_lookup(alt_parent);
        if (!cpuclk->alt_parent) {
index 37874d3c3165eb7589a3cc75b08a6af371539a26..d4b6b517fe1b44689df28853cf894baa3799153d 100644 (file)
@@ -57,10 +57,12 @@ struct exynos_cpuclk {
        struct notifier_block                   clk_nb;
        unsigned long                           flags;
 
-/* The CPU clock registers has DIV1 configuration register */
+/* The CPU clock registers have DIV1 configuration register */
 #define CLK_CPU_HAS_DIV1               (1 << 0)
 /* When ALT parent is active, debug clocks need safe divider values */
 #define CLK_CPU_NEEDS_DEBUG_ALT_DIV    (1 << 1)
+/* The CPU clock registers have Exynos5433-compatible layout */
+#define CLK_CPU_HAS_E5433_REGS_LAYOUT  (1 << 2)
 };
 
 extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
index 4e9584d79089d355fcc67b4154724f4d6cc2ed62..bdf8b971f332502bb8c19ffc399b6886bf7d42aa 100644 (file)
@@ -273,17 +273,7 @@ static struct platform_driver exynos_audss_clk_driver = {
        .remove = exynos_audss_clk_remove,
 };
 
-static int __init exynos_audss_clk_init(void)
-{
-       return platform_driver_register(&exynos_audss_clk_driver);
-}
-core_initcall(exynos_audss_clk_init);
-
-static void __exit exynos_audss_clk_exit(void)
-{
-       platform_driver_unregister(&exynos_audss_clk_driver);
-}
-module_exit(exynos_audss_clk_exit);
+module_platform_driver(exynos_audss_clk_driver);
 
 MODULE_AUTHOR("Padmavathi Venna <padma.v@samsung.com>");
 MODULE_DESCRIPTION("Exynos Audio Subsystem Clock Controller");
index 7cd02ff37a1f6919fea89e6c1a6306fd3695dc28..96fab6cfb2027f805e8ed941012a464d58cbb3dd 100644 (file)
@@ -151,6 +151,8 @@ static void __init exynos5_clkout_init(struct device_node *node)
 }
 CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu",
                exynos5_clkout_init);
+CLK_OF_DECLARE(exynos5410_clkout, "samsung,exynos5410-pmu",
+               exynos5_clkout_init);
 CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu",
                exynos5_clkout_init);
 CLK_OF_DECLARE(exynos5433_clkout, "samsung,exynos5433-pmu",
index 16575ee874cbb9e633a575001406e10621602836..1b81e283f60589c900c5bfc6370a125d8c8c845d 100644 (file)
 #define PWR_CTRL1_USE_CORE1_WFI                        (1 << 1)
 #define PWR_CTRL1_USE_CORE0_WFI                        (1 << 0)
 
-static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
+static const unsigned long exynos3250_cmu_clk_regs[] __initconst = {
        SRC_LEFTBUS,
        DIV_LEFTBUS,
        GATE_IP_LEFTBUS,
@@ -226,7 +226,7 @@ PNAME(group_sclk_fimd0_p)   = { "xxti", "xusbxti",
 PNAME(mout_mfc_p)              = { "mout_mfc_0", "mout_mfc_1" };
 PNAME(mout_g3d_p)              = { "mout_g3d_0", "mout_g3d_1" };
 
-static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock fixed_factor_clks[] __initconst = {
        FFACTOR(0, "sclk_mpll_1600", "mout_mpll", 1, 1, 0),
        FFACTOR(0, "sclk_mpll_mif", "mout_mpll", 1, 2, 0),
        FFACTOR(0, "sclk_bpll", "fout_bpll", 1, 2, 0),
@@ -237,7 +237,7 @@ static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = {
        FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0),
 };
 
-static struct samsung_mux_clock mux_clks[] __initdata = {
+static const struct samsung_mux_clock mux_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -326,7 +326,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
                        CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock div_clks[] __initdata = {
+static const struct samsung_div_clock div_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -429,7 +429,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
        DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
 };
 
-static struct samsung_gate_clock gate_clks[] __initdata = {
+static const struct samsung_gate_clock gate_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -669,7 +669,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = {
 };
 
 /* APLL & MPLL & BPLL & UPLL */
-static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_pll_rates[] __initconst = {
        PLL_35XX_RATE(1200000000, 400, 4, 1),
        PLL_35XX_RATE(1100000000, 275, 3, 1),
        PLL_35XX_RATE(1066000000, 533, 6, 1),
@@ -691,7 +691,7 @@ static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
 };
 
 /* EPLL */
-static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = {
        PLL_36XX_RATE(800000000, 200, 3, 1,     0),
        PLL_36XX_RATE(288000000,  96, 2, 2,     0),
        PLL_36XX_RATE(192000000, 128, 2, 3,     0),
@@ -710,7 +710,7 @@ static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
 };
 
 /* VPLL */
-static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = {
        PLL_36XX_RATE(600000000, 100, 2, 1,     0),
        PLL_36XX_RATE(533000000, 266, 3, 2, 32768),
        PLL_36XX_RATE(519230987, 173, 2, 2,  5046),
@@ -740,7 +740,7 @@ static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_clock exynos3250_plls[] __initdata = {
+static const struct samsung_pll_clock exynos3250_plls[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
                APLL_LOCK, APLL_CON0, exynos3250_pll_rates),
        PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
@@ -772,7 +772,7 @@ static void __init exynos3_core_down_clock(void __iomem *reg_base)
        __raw_writel(0x0, reg_base + PWR_CTRL2);
 }
 
-static struct samsung_cmu_info cmu_info __initdata = {
+static const struct samsung_cmu_info cmu_info __initconst = {
        .pll_clks               = exynos3250_plls,
        .nr_pll_clks            = ARRAY_SIZE(exynos3250_plls),
        .mux_clks               = mux_clks,
@@ -848,7 +848,7 @@ CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
 #define EPLL_CON2              0x111c
 #define SRC_EPLL               0x1120
 
-static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
+static const unsigned long exynos3250_cmu_dmc_clk_regs[] __initconst = {
        BPLL_LOCK,
        BPLL_CON0,
        BPLL_CON1,
@@ -874,7 +874,7 @@ PNAME(mout_bpll_p)  = { "fin_pll", "fout_bpll", };
 PNAME(mout_mpll_mif_p) = { "fin_pll", "sclk_mpll_mif", };
 PNAME(mout_dphy_p)     = { "mout_mpll_mif", "mout_bpll", };
 
-static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock dmc_mux_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -893,7 +893,7 @@ static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
        MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_EPLL, 4, 1),
 };
 
-static struct samsung_div_clock dmc_div_clks[] __initdata = {
+static const struct samsung_div_clock dmc_div_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -910,14 +910,14 @@ static struct samsung_div_clock dmc_div_clks[] __initdata = {
        DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3),
 };
 
-static struct samsung_pll_clock exynos3250_dmc_plls[] __initdata = {
+static const struct samsung_pll_clock exynos3250_dmc_plls[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
                BPLL_LOCK, BPLL_CON0, exynos3250_pll_rates),
        PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
                EPLL_LOCK, EPLL_CON0, exynos3250_epll_rates),
 };
 
-static struct samsung_cmu_info dmc_cmu_info __initdata = {
+static const struct samsung_cmu_info dmc_cmu_info __initconst = {
        .pll_clks               = exynos3250_dmc_plls,
        .nr_pll_clks            = ARRAY_SIZE(exynos3250_dmc_plls),
        .mux_clks               = dmc_mux_clks,
@@ -947,7 +947,7 @@ CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
 #define GATE_IP_ISP1           0x804
 #define GATE_SCLK_ISP          0x900
 
-static struct samsung_div_clock isp_div_clks[] __initdata = {
+static const struct samsung_div_clock isp_div_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -967,7 +967,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = {
        DIV(CLK_DIV_MPWM, "div_mpwm", "div_isp1", DIV_ISP1, 0, 3),
 };
 
-static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -1063,7 +1063,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = {
                GATE_SCLK_ISP, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info isp_cmu_info __initdata = {
+static const struct samsung_cmu_info isp_cmu_info __initconst = {
        .div_clks       = isp_div_clks,
        .nr_div_clks    = ARRAY_SIZE(isp_div_clks),
        .gate_clks      = isp_gate_clks,
@@ -1079,14 +1079,15 @@ static int __init exynos3250_cmu_isp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id exynos3250_cmu_isp_of_match[] = {
+static const struct of_device_id exynos3250_cmu_isp_of_match[] __initconst = {
        { .compatible = "samsung,exynos3250-cmu-isp", },
        { /* sentinel */ }
 };
 
-static struct platform_driver exynos3250_cmu_isp_driver = {
+static struct platform_driver exynos3250_cmu_isp_driver __initdata = {
        .driver = {
                .name = "exynos3250-cmu-isp",
+               .suppress_bind_attrs = true,
                .of_match_table = exynos3250_cmu_isp_of_match,
        },
 };
index 7b3d0f97598740240fecec3afa0e08e074933876..faab9b31baf5b4b15ec0fec8623d01031e991fa9 100644 (file)
@@ -169,7 +169,7 @@ static struct samsung_clk_reg_dump *exynos4_save_pll;
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
  */
-static unsigned long exynos4210_clk_save[] __initdata = {
+static const unsigned long exynos4210_clk_save[] __initconst = {
        E4210_SRC_IMAGE,
        E4210_SRC_LCD1,
        E4210_SRC_MASK_LCD1,
@@ -181,7 +181,7 @@ static unsigned long exynos4210_clk_save[] __initdata = {
        PWR_CTRL1,
 };
 
-static unsigned long exynos4x12_clk_save[] __initdata = {
+static const unsigned long exynos4x12_clk_save[] __initconst = {
        E4X12_GATE_IP_IMAGE,
        E4X12_GATE_IP_PERIR,
        E4X12_SRC_CAM1,
@@ -192,7 +192,7 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
        E4X12_PWR_CTRL2,
 };
 
-static unsigned long exynos4_clk_pll_regs[] __initdata = {
+static const unsigned long exynos4_clk_pll_regs[] __initconst = {
        EPLL_LOCK,
        VPLL_LOCK,
        EPLL_CON0,
@@ -203,7 +203,7 @@ static unsigned long exynos4_clk_pll_regs[] __initdata = {
        VPLL_CON2,
 };
 
-static unsigned long exynos4_clk_regs[] __initdata = {
+static const unsigned long exynos4_clk_regs[] __initconst = {
        SRC_LEFTBUS,
        DIV_LEFTBUS,
        GATE_IP_LEFTBUS,
@@ -505,28 +505,28 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initconst = {
        FRATE(0, "sclk_hdmi24m", NULL, 0, 24000000),
        FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", "hdmi", 0, 27000000),
        FRATE(0, "sclk_usbphy0", NULL, 0, 48000000),
 };
 
-static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initconst = {
        FRATE(0, "sclk_usbphy1", NULL, 0, 48000000),
 };
 
-static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
        FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
        FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
        FFACTOR(0, "arm_clk_div_2", "div_core2", 1, 2, 0),
 };
 
-static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0),
 };
 
-static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0),
        FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0),
        FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0),
@@ -534,7 +534,7 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda
 };
 
 /* list of mux clocks supported in all exynos4 soc's */
-static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = {
        MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
                        CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0,
                        "mout_apll"),
@@ -555,11 +555,11 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4210 soc */
-static struct samsung_mux_clock exynos4210_mux_early[] __initdata = {
+static const struct samsung_mux_clock exynos4210_mux_early[] __initconst = {
        MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
 };
 
-static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4210_mux_clks[] __initconst = {
        MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1),
        MUX(0, "mout_clkout_leftbus", clkout_left_p4210,
                        CLKOUT_CMU_LEFTBUS, 0, 5),
@@ -622,7 +622,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4x12 soc */
-static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4x12_mux_clks[] __initconst = {
        MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1),
        MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1),
        MUX(0, "mout_clkout_leftbus", clkout_left_p4x12,
@@ -705,7 +705,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in all exynos4 soc's */
-static struct samsung_div_clock exynos4_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4_div_clks[] __initconst = {
        DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
        DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
        DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus",
@@ -795,7 +795,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4210 soc */
-static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4210_div_clks[] __initconst = {
        DIV(CLK_ACLK200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
        DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4),
        DIV(0, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
@@ -806,7 +806,7 @@ static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4x12 soc */
-static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = {
        DIV(0, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
        DIV(0, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
        DIV(0, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
@@ -837,7 +837,7 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in all exynos4 soc's */
-static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = {
        /*
         * After all Exynos4 based platforms are migrated to use device tree,
         * the device name and clock alias names specified below for some
@@ -1043,7 +1043,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in exynos4210 soc */
-static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4210_gate_clks[] __initconst = {
        GATE(CLK_TVENC, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
        GATE(CLK_G2D, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
        GATE(CLK_ROTATOR, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
@@ -1090,7 +1090,7 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in exynos4x12 soc */
-static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
        GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
        GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
        GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
@@ -1190,17 +1190,17 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
                0),
 };
 
-static struct samsung_clock_alias exynos4_aliases[] __initdata = {
+static const struct samsung_clock_alias exynos4_aliases[] __initconst = {
        ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
        ALIAS(CLK_ARM_CLK, NULL, "armclk"),
        ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
 };
 
-static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
+static const struct samsung_clock_alias exynos4210_aliases[] __initconst = {
        ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
 };
 
-static struct samsung_clock_alias exynos4x12_aliases[] __initdata = {
+static const struct samsung_clock_alias exynos4x12_aliases[] __initconst = {
        ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"),
 };
 
@@ -1211,7 +1211,7 @@ static struct samsung_clock_alias exynos4x12_aliases[] __initdata = {
  * controller is first remapped and the value of XOM[0] bit is read to
  * determine the parent clock.
  */
-static unsigned long exynos4_get_xom(void)
+static unsigned long __init exynos4_get_xom(void)
 {
        unsigned long xom = 0;
        void __iomem *chipid_base;
@@ -1264,7 +1264,7 @@ static const struct of_device_id ext_clk_match[] __initconst = {
 };
 
 /* PLLs PMS values */
-static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4210_apll_rates[] __initconst = {
        PLL_45XX_RATE(1200000000, 150,  3, 1, 28),
        PLL_45XX_RATE(1000000000, 250,  6, 1, 28),
        PLL_45XX_RATE( 800000000, 200,  6, 1, 28),
@@ -1277,7 +1277,7 @@ static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4210_epll_rates[] __initconst = {
        PLL_4600_RATE(192000000, 48, 3, 1,     0, 0),
        PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0),
        PLL_4600_RATE(180000000, 45, 3, 1,     0, 0),
@@ -1288,7 +1288,7 @@ static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4210_vpll_rates[] __initconst = {
        PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0),
        PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1,  1, 1),
        PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1),
@@ -1297,7 +1297,7 @@ static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = {
        PLL_35XX_RATE(1500000000, 250, 4, 0),
        PLL_35XX_RATE(1400000000, 175, 3, 0),
        PLL_35XX_RATE(1300000000, 325, 6, 0),
@@ -1315,7 +1315,7 @@ static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = {
        PLL_36XX_RATE(192000000, 48, 3, 1,     0),
        PLL_36XX_RATE(180633605, 45, 3, 1, 10381),
        PLL_36XX_RATE(180000000, 45, 3, 1,     0),
@@ -1326,7 +1326,7 @@ static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = {
        PLL_36XX_RATE(533000000, 133, 3, 1, 16384),
        PLL_36XX_RATE(440000000, 110, 3, 1,     0),
        PLL_36XX_RATE(350000000, 175, 3, 2,     0),
@@ -1375,12 +1375,12 @@ static void __init exynos4x12_core_down_clock(void)
        if (num_possible_cpus() == 4)
                tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
                       PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
-       __raw_writel(tmp, reg_base + PWR_CTRL1);
+       writel_relaxed(tmp, reg_base + PWR_CTRL1);
 
        /*
         * Disable the clock up feature in case it was enabled by bootloader.
         */
-       __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
+       writel_relaxed(0x0, reg_base + E4X12_PWR_CTRL2);
 }
 
 #define E4210_CPU_DIV0(apll, pclk_dbg, atb, periph, corem1, corem0)    \
@@ -1450,8 +1450,6 @@ static void __init exynos4_clk_init(struct device_node *np,
                panic("%s: failed to map registers\n", __func__);
 
        ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
                        ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
index 86ee06b226bdbaa0f71793d1ea50265faee1c6e4..6c90631597176af72e325d9bc57403ae34720a93 100644 (file)
 #define DIV_CPU0               0x14500
 #define DIV_CPU1               0x14504
 
-static unsigned long exynos4415_cmu_clk_regs[] __initdata = {
+static const unsigned long exynos4415_cmu_clk_regs[] __initconst = {
        SRC_LEFTBUS,
        DIV_LEFTBUS,
        GATE_IP_LEFTBUS,
@@ -268,16 +268,16 @@ PNAME(group_aclk_isp0_300_user_p) = { "fin_pll", "mout_aclk_isp0_300" };
 PNAME(group_aclk_isp1_300_user_p) = { "fin_pll", "mout_aclk_isp1_300" };
 PNAME(group_mout_mpll_user_t_p)        = { "mout_mpll_user_t" };
 
-static struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initconst = {
        /* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */
        FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0),
 };
 
-static struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initconst = {
        FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 27000000),
 };
 
-static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4415_mux_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -427,7 +427,7 @@ static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = {
                group_aclk_isp1_300_user_p, SRC_TOP_ISP1, 0, 1),
 };
 
-static struct samsung_div_clock exynos4415_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4415_div_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -566,7 +566,7 @@ static struct samsung_div_clock exynos4415_div_clks[] __initdata = {
        DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
 };
 
-static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4415_gate_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by register address in ascending
         * order and then bitfield shift in descending order, as it is done
@@ -859,7 +859,7 @@ static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = {
 /*
  * APLL & MPLL & BPLL & ISP_PLL & DISP_PLL & G3D_PLL
  */
-static struct samsung_pll_rate_table exynos4415_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos4415_pll_rates[] __initconst = {
        PLL_35XX_RATE(1600000000, 400, 3,  1),
        PLL_35XX_RATE(1500000000, 250, 2,  1),
        PLL_35XX_RATE(1400000000, 175, 3,  0),
@@ -891,7 +891,7 @@ static struct samsung_pll_rate_table exynos4415_pll_rates[] = {
 };
 
 /* EPLL */
-static struct samsung_pll_rate_table exynos4415_epll_rates[] = {
+static const struct samsung_pll_rate_table exynos4415_epll_rates[] __initconst = {
        PLL_36XX_RATE(800000000, 200, 3, 1,     0),
        PLL_36XX_RATE(288000000,  96, 2, 2,     0),
        PLL_36XX_RATE(192000000, 128, 2, 3,     0),
@@ -909,7 +909,7 @@ static struct samsung_pll_rate_table exynos4415_epll_rates[] = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_clock exynos4415_plls[] __initdata = {
+static const struct samsung_pll_clock exynos4415_plls[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
                APLL_LOCK, APLL_CON0, exynos4415_pll_rates),
        PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
@@ -922,7 +922,7 @@ static struct samsung_pll_clock exynos4415_plls[] __initdata = {
                "fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, exynos4415_pll_rates),
 };
 
-static struct samsung_cmu_info cmu_info __initdata = {
+static const struct samsung_cmu_info cmu_info __initconst = {
        .pll_clks               = exynos4415_plls,
        .nr_pll_clks            = ARRAY_SIZE(exynos4415_plls),
        .mux_clks               = exynos4415_mux_clks,
@@ -961,7 +961,7 @@ CLK_OF_DECLARE(exynos4415_cmu, "samsung,exynos4415-cmu", exynos4415_cmu_init);
 #define SRC_DMC                        0x300
 #define DIV_DMC1               0x504
 
-static unsigned long exynos4415_cmu_dmc_clk_regs[] __initdata = {
+static const unsigned long exynos4415_cmu_dmc_clk_regs[] __initconst = {
        MPLL_LOCK,
        MPLL_CON0,
        MPLL_CON1,
@@ -978,14 +978,14 @@ PNAME(mout_mpll_p)                = { "fin_pll", "fout_mpll", };
 PNAME(mout_bpll_p)             = { "fin_pll", "fout_bpll", };
 PNAME(mbpll_p)                 = { "mout_mpll", "mout_bpll", };
 
-static struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initconst = {
        MUX(CLK_DMC_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_DMC, 12, 1),
        MUX(CLK_DMC_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1),
        MUX(CLK_DMC_MOUT_DPHY, "mout_dphy", mbpll_p, SRC_DMC, 8, 1),
        MUX(CLK_DMC_MOUT_DMC_BUS, "mout_dmc_bus", mbpll_p, SRC_DMC, 4, 1),
 };
 
-static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4415_dmc_div_clks[] __initconst = {
        DIV(CLK_DMC_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3),
        DIV(CLK_DMC_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3),
        DIV(CLK_DMC_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus",
@@ -995,14 +995,14 @@ static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = {
        DIV(CLK_DMC_DIV_MPLL_PRE, "div_mpll_pre", "mout_mpll", DIV_DMC1, 8, 2),
 };
 
-static struct samsung_pll_clock exynos4415_dmc_plls[] __initdata = {
+static const struct samsung_pll_clock exynos4415_dmc_plls[] __initconst = {
        PLL(pll_35xx, CLK_DMC_FOUT_MPLL, "fout_mpll", "fin_pll",
                MPLL_LOCK, MPLL_CON0, exynos4415_pll_rates),
        PLL(pll_35xx, CLK_DMC_FOUT_BPLL, "fout_bpll", "fin_pll",
                BPLL_LOCK, BPLL_CON0, exynos4415_pll_rates),
 };
 
-static struct samsung_cmu_info cmu_dmc_info __initdata = {
+static const struct samsung_cmu_info cmu_dmc_info __initconst = {
        .pll_clks               = exynos4415_dmc_plls,
        .nr_pll_clks            = ARRAY_SIZE(exynos4415_dmc_plls),
        .mux_clks               = exynos4415_dmc_mux_clks,
index 837197db4ffbb5f1b3f9539e76ff1d755004c713..27a227d6620c7b32bedf04bf16f2f2a7f71ce49b 100644 (file)
@@ -117,7 +117,7 @@ static struct samsung_clk_reg_dump *exynos5250_save;
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
  */
-static unsigned long exynos5250_clk_regs[] __initdata = {
+static const unsigned long exynos5250_clk_regs[] __initconst = {
        SRC_CPU,
        DIV_CPU0,
        PWR_CTRL1,
@@ -190,7 +190,7 @@ static struct syscore_ops exynos5250_clk_syscore_ops = {
        .resume = exynos5250_clk_resume,
 };
 
-static void exynos5250_clk_sleep_init(void)
+static void __init exynos5250_clk_sleep_init(void)
 {
        exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs,
                                        ARRAY_SIZE(exynos5250_clk_regs));
@@ -203,7 +203,7 @@ static void exynos5250_clk_sleep_init(void)
        register_syscore_ops(&exynos5250_clk_syscore_ops);
 }
 #else
-static void exynos5250_clk_sleep_init(void) {}
+static void __init exynos5250_clk_sleep_init(void) {}
 #endif
 
 /* list of all parent clock list */
@@ -266,23 +266,23 @@ static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initda
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initconst = {
        FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 24000000),
        FRATE(0, "sclk_hdmi27m", NULL, 0, 27000000),
        FRATE(0, "sclk_dptxphy", NULL, 0, 24000000),
        FRATE(0, "sclk_uhostphy", NULL, 0, 48000000),
 };
 
-static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
        FFACTOR(0, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
 };
 
-static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initconst = {
        MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
 };
 
-static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by (clock domain, register address,
         * bitfield shift) triplet in ascending order. When adding new entries,
@@ -378,7 +378,7 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
        MUX(0, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
 };
 
-static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5250_div_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by (clock domain, register address,
         * bitfield shift) triplet in ascending order. When adding new entries,
@@ -470,7 +470,7 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
        DIV(CLK_DIV_I2S2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
 };
 
-static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
        /*
         * NOTE: Following table is sorted by (clock domain, register address,
         * bitfield shift) triplet in ascending order. When adding new entries,
@@ -698,7 +698,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
                        GATE_IP_ISP1, 7, 0, 0),
 };
 
-static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
        PLL_36XX_RATE(266000000, 266, 3, 3, 0),
@@ -707,7 +707,7 @@ static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
        { },
 };
 
-static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
        PLL_36XX_RATE(192000000, 64, 2, 2, 0),
@@ -721,7 +721,7 @@ static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
        { },
 };
 
-static struct samsung_pll_rate_table apll_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_35XX_RATE(rate, m, p, s) */
        PLL_35XX_RATE(1700000000, 425, 6, 0),
@@ -805,8 +805,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
        }
 
        ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
+
        samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
                        ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
                        ext_clk_match);
index 7a7ed075a573d78699c86b2113e8a071f8033472..a43642c36039c165061da8c572a2f2f9efb281c4 100644 (file)
@@ -22,7 +22,7 @@
  * Applicable for all 2550 Type PLLS for Exynos5260, listed below
  * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL.
  */
-static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initconst = {
        PLL_35XX_RATE(1700000000, 425, 6, 0),
        PLL_35XX_RATE(1600000000, 200, 3, 0),
        PLL_35XX_RATE(1500000000, 250, 4, 0),
@@ -55,7 +55,7 @@ static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = {
 /*
  * Applicable for 2650 Type PLL for AUD_PLL.
  */
-static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = {
        PLL_36XX_RATE(1600000000, 200, 3, 0, 0),
        PLL_36XX_RATE(1200000000, 100, 2, 0, 0),
        PLL_36XX_RATE(1000000000, 250, 3, 1, 0),
@@ -78,7 +78,7 @@ static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = {
 
 /* CMU_AUD */
 
-static unsigned long aud_clk_regs[] __initdata = {
+static const unsigned long aud_clk_regs[] __initconst = {
        MUX_SEL_AUD,
        DIV_AUD0,
        DIV_AUD1,
@@ -92,7 +92,7 @@ PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"};
 PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
 PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
 
-static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static const struct samsung_mux_clock aud_mux_clks[] __initconst = {
        MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
                        MUX_SEL_AUD, 0, 1),
        MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
@@ -101,7 +101,7 @@ static struct samsung_mux_clock aud_mux_clks[] __initdata = {
                        MUX_SEL_AUD, 8, 1),
 };
 
-static struct samsung_div_clock aud_div_clks[] __initdata = {
+static const struct samsung_div_clock aud_div_clks[] __initconst = {
        DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
                        DIV_AUD0, 0, 4),
 
@@ -113,7 +113,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = {
                        DIV_AUD1, 12, 4),
 };
 
-static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
        GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
                        EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
        GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
@@ -154,7 +154,7 @@ CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud",
 
 /* CMU_DISP */
 
-static unsigned long disp_clk_regs[] __initdata = {
+static const unsigned long disp_clk_regs[] __initconst = {
        MUX_SEL_DISP0,
        MUX_SEL_DISP1,
        MUX_SEL_DISP2,
@@ -201,7 +201,7 @@ PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll",
 PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
                        "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-static struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock disp_mux_clks[] __initconst = {
        MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
                        mout_aclk_disp_333_user_p,
                        MUX_SEL_DISP0, 0, 1),
@@ -270,7 +270,7 @@ static struct samsung_mux_clock disp_mux_clks[] __initdata = {
                        MUX_SEL_DISP4, 4, 2),
 };
 
-static struct samsung_div_clock disp_div_clks[] __initdata = {
+static const struct samsung_div_clock disp_div_clks[] __initconst = {
        DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
                        "mout_aclk_disp_222_user",
                        DIV_DISP, 8, 4),
@@ -283,7 +283,7 @@ static struct samsung_div_clock disp_div_clks[] __initdata = {
                        DIV_DISP, 16, 4),
 };
 
-static struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock disp_gate_clks[] __initconst = {
        GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
                        "mout_phyclk_hdmi_phy_pixel_clko_user",
                        EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
@@ -344,7 +344,7 @@ CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp",
 
 /* CMU_EGL */
 
-static unsigned long egl_clk_regs[] __initdata = {
+static const unsigned long egl_clk_regs[] __initconst = {
        EGL_PLL_LOCK,
        EGL_PLL_CON0,
        EGL_PLL_CON1,
@@ -361,13 +361,13 @@ static unsigned long egl_clk_regs[] __initdata = {
 PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
 PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
 
-static struct samsung_mux_clock egl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock egl_mux_clks[] __initconst = {
        MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
                        MUX_SEL_EGL, 4, 1),
        MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
 };
 
-static struct samsung_div_clock egl_div_clks[] __initdata = {
+static const struct samsung_div_clock egl_div_clks[] __initconst = {
        DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
        DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
        DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
@@ -379,7 +379,7 @@ static struct samsung_div_clock egl_div_clks[] __initdata = {
        DIV(EGL_DOUT_EGL_PLL, "dout_egl_pll", "mout_egl_b", DIV_EGL, 24, 3),
 };
 
-static struct samsung_pll_clock egl_pll_clks[] __initdata = {
+static const struct samsung_pll_clock egl_pll_clks[] __initconst = {
        PLL(pll_2550xx, EGL_FOUT_EGL_PLL, "fout_egl_pll", "fin_pll",
                EGL_PLL_LOCK, EGL_PLL_CON0,
                pll2550_24mhz_tbl),
@@ -408,7 +408,7 @@ CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl",
 
 /* CMU_FSYS */
 
-static unsigned long fsys_clk_regs[] __initdata = {
+static const unsigned long fsys_clk_regs[] __initconst = {
        MUX_SEL_FSYS0,
        MUX_SEL_FSYS1,
        EN_ACLK_FSYS,
@@ -431,7 +431,7 @@ PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll",
 PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
                        "phyclk_usbdrd30_udrd30_phyclock"};
 
-static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys_mux_clks[] __initconst = {
        MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
                        "mout_phyclk_usbdrd30_phyclock_user",
                        mout_phyclk_usbdrd30_phyclock_user_p,
@@ -454,7 +454,7 @@ static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
                        MUX_SEL_FSYS1, 16, 1),
 };
 
-static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys_gate_clks[] __initconst = {
        GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
                        "mout_phyclk_usbdrd30_phyclock_user",
                        EN_SCLK_FSYS, 1, 0, 0),
@@ -508,7 +508,7 @@ CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys",
 
 /* CMU_G2D */
 
-static unsigned long g2d_clk_regs[] __initdata = {
+static const unsigned long g2d_clk_regs[] __initconst = {
        MUX_SEL_G2D,
        MUX_STAT_G2D,
        DIV_G2D,
@@ -535,18 +535,18 @@ static unsigned long g2d_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
 
-static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g2d_mux_clks[] __initconst = {
        MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
                        mout_aclk_g2d_333_user_p,
                        MUX_SEL_G2D, 0, 1),
 };
 
-static struct samsung_div_clock g2d_div_clks[] __initdata = {
+static const struct samsung_div_clock g2d_div_clks[] __initconst = {
        DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
                        DIV_G2D, 0, 3),
 };
 
-static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g2d_gate_clks[] __initconst = {
        GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
                        EN_IP_G2D, 4, 0, 0),
        GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
@@ -599,7 +599,7 @@ CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d",
 
 /* CMU_G3D */
 
-static unsigned long g3d_clk_regs[] __initdata = {
+static const unsigned long g3d_clk_regs[] __initconst = {
        G3D_PLL_LOCK,
        G3D_PLL_CON0,
        G3D_PLL_CON1,
@@ -615,23 +615,23 @@ static unsigned long g3d_clk_regs[] __initdata = {
 
 PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
 
-static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g3d_mux_clks[] __initconst = {
        MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
                        MUX_SEL_G3D, 0, 1),
 };
 
-static struct samsung_div_clock g3d_div_clks[] __initdata = {
+static const struct samsung_div_clock g3d_div_clks[] __initconst = {
        DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
        DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
 };
 
-static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g3d_gate_clks[] __initconst = {
        GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
        GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
                        EN_IP_G3D, 3, 0, 0),
 };
 
-static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
+static const struct samsung_pll_clock g3d_pll_clks[] __initconst = {
        PLL(pll_2550, G3D_FOUT_G3D_PLL, "fout_g3d_pll", "fin_pll",
                G3D_PLL_LOCK, G3D_PLL_CON0,
                pll2550_24mhz_tbl),
@@ -662,7 +662,7 @@ CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d",
 
 /* CMU_GSCL */
 
-static unsigned long gscl_clk_regs[] __initdata = {
+static const unsigned long gscl_clk_regs[] __initconst = {
        MUX_SEL_GSCL,
        DIV_GSCL,
        EN_ACLK_GSCL,
@@ -692,7 +692,7 @@ PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
 
-static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock gscl_mux_clks[] __initconst = {
        MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
                        mout_aclk_gscl_333_user_p,
                        MUX_SEL_GSCL, 0, 1),
@@ -706,7 +706,7 @@ static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
                        MUX_SEL_GSCL, 24, 1),
 };
 
-static struct samsung_div_clock gscl_div_clks[] __initdata = {
+static const struct samsung_div_clock gscl_div_clks[] __initconst = {
        DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
                        "mout_aclk_m2m_400_user",
                        DIV_GSCL, 0, 3),
@@ -715,7 +715,7 @@ static struct samsung_div_clock gscl_div_clks[] __initdata = {
                        DIV_GSCL, 4, 3),
 };
 
-static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock gscl_gate_clks[] __initconst = {
        GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
                        EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
        GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
@@ -795,7 +795,7 @@ CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl",
 
 /* CMU_ISP */
 
-static unsigned long isp_clk_regs[] __initdata = {
+static const unsigned long isp_clk_regs[] __initconst = {
        MUX_SEL_ISP0,
        MUX_SEL_ISP1,
        DIV_ISP,
@@ -811,14 +811,14 @@ static unsigned long isp_clk_regs[] __initdata = {
 PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
 PNAME(mout_isp_266_user_p)      = {"fin_pll", "dout_aclk_isp1_266"};
 
-static struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock isp_mux_clks[] __initconst = {
        MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
                        MUX_SEL_ISP0, 0, 1),
        MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
                        MUX_SEL_ISP0, 4, 1),
 };
 
-static struct samsung_div_clock isp_div_clks[] __initdata = {
+static const struct samsung_div_clock isp_div_clks[] __initconst = {
        DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
                        DIV_ISP, 0, 3),
        DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
@@ -830,7 +830,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = {
        DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
 };
 
-static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
        GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
                        EN_IP_ISP0, 15, 0, 0),
 
@@ -914,7 +914,7 @@ CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp",
 
 /* CMU_KFC */
 
-static unsigned long kfc_clk_regs[] __initdata = {
+static const unsigned long kfc_clk_regs[] __initconst = {
        KFC_PLL_LOCK,
        KFC_PLL_CON0,
        KFC_PLL_CON1,
@@ -932,13 +932,13 @@ static unsigned long kfc_clk_regs[] __initdata = {
 PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
 PNAME(mout_kfc_p)       = {"mout_kfc_pll", "dout_media_pll"};
 
-static struct samsung_mux_clock kfc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock kfc_mux_clks[] __initconst = {
        MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
                        MUX_SEL_KFC0, 0, 1),
        MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
 };
 
-static struct samsung_div_clock kfc_div_clks[] __initdata = {
+static const struct samsung_div_clock kfc_div_clks[] __initconst = {
        DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
        DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
        DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
@@ -949,7 +949,7 @@ static struct samsung_div_clock kfc_div_clks[] __initdata = {
        DIV(KFC_DOUT_KFC_PLL, "dout_kfc_pll", "mout_kfc", DIV_KFC, 24, 3),
 };
 
-static struct samsung_pll_clock kfc_pll_clks[] __initdata = {
+static const struct samsung_pll_clock kfc_pll_clks[] __initconst = {
        PLL(pll_2550xx, KFC_FOUT_KFC_PLL, "fout_kfc_pll", "fin_pll",
                KFC_PLL_LOCK, KFC_PLL_CON0,
                pll2550_24mhz_tbl),
@@ -978,7 +978,7 @@ CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc",
 
 /* CMU_MFC */
 
-static unsigned long mfc_clk_regs[] __initdata = {
+static const unsigned long mfc_clk_regs[] __initconst = {
        MUX_SEL_MFC,
        DIV_MFC,
        EN_ACLK_MFC,
@@ -991,18 +991,18 @@ static unsigned long mfc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
 
-static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
        MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
                        mout_aclk_mfc_333_user_p,
                        MUX_SEL_MFC, 0, 1),
 };
 
-static struct samsung_div_clock mfc_div_clks[] __initdata = {
+static const struct samsung_div_clock mfc_div_clks[] __initconst = {
        DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
                        DIV_MFC, 0, 3),
 };
 
-static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mfc_gate_clks[] __initconst = {
        GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
                        EN_IP_MFC, 1, 0, 0),
        GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
@@ -1034,7 +1034,7 @@ CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc",
 
 /* CMU_MIF */
 
-static unsigned long mif_clk_regs[] __initdata = {
+static const unsigned long mif_clk_regs[] __initconst = {
        MEM_PLL_LOCK,
        BUS_PLL_LOCK,
        MEDIA_PLL_LOCK,
@@ -1076,7 +1076,7 @@ PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"};
 PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
 PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
 
-static struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mif_mux_clks[] __initconst = {
        MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
                        MUX_SEL_MIF, 0, 1),
        MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
@@ -1093,7 +1093,7 @@ static struct samsung_mux_clock mif_mux_clks[] __initdata = {
                        MUX_SEL_MIF, 24, 1),
 };
 
-static struct samsung_div_clock mif_div_clks[] __initdata = {
+static const struct samsung_div_clock mif_div_clks[] __initconst = {
        DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
                        DIV_MIF, 0, 3),
        DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
@@ -1112,7 +1112,7 @@ static struct samsung_div_clock mif_div_clks[] __initdata = {
                        DIV_MIF, 28, 4),
 };
 
-static struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mif_gate_clks[] __initconst = {
        GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
                        EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
        GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
@@ -1146,7 +1146,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_pll_clock mif_pll_clks[] __initdata = {
+static const struct samsung_pll_clock mif_pll_clks[] __initconst = {
        PLL(pll_2550xx, MIF_FOUT_MEM_PLL, "fout_mem_pll", "fin_pll",
                MEM_PLL_LOCK, MEM_PLL_CON0,
                pll2550_24mhz_tbl),
@@ -1183,7 +1183,7 @@ CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif",
 
 /* CMU_PERI */
 
-static unsigned long peri_clk_regs[] __initdata = {
+static const unsigned long peri_clk_regs[] __initconst = {
        MUX_SEL_PERI,
        MUX_SEL_PERI1,
        DIV_PERI,
@@ -1219,7 +1219,7 @@ PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud",
 PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
                        "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-static struct samsung_mux_clock peri_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
        MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
                        MUX_SEL_PERI1, 4, 2),
        MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
@@ -1228,12 +1228,12 @@ static struct samsung_mux_clock peri_mux_clks[] __initdata = {
                        MUX_SEL_PERI1, 20, 2),
 };
 
-static struct samsung_div_clock peri_div_clks[] __initdata = {
+static const struct samsung_div_clock peri_div_clks[] __initconst = {
        DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
        DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
 };
 
-static struct samsung_gate_clock peri_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
        GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
                        CLK_SET_RATE_PARENT, 0),
        GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
@@ -1389,7 +1389,7 @@ CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri",
 
 /* CMU_TOP */
 
-static unsigned long top_clk_regs[] __initdata = {
+static const unsigned long top_clk_regs[] __initconst = {
        DISP_PLL_LOCK,
        AUD_PLL_LOCK,
        DISP_PLL_CON0,
@@ -1430,7 +1430,7 @@ static unsigned long top_clk_regs[] __initdata = {
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock fixed_rate_clks[] __initconst = {
        FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
                        0, 270000000),
        FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
@@ -1513,7 +1513,7 @@ PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a",
 PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
                        "mout_mediatop_pll_user"};
 
-static struct samsung_mux_clock top_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top_mux_clks[] __initconst = {
        MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
                        mout_mediatop_pll_user_p,
                        MUX_SEL_TOP_PLL0, 0, 1),
@@ -1673,7 +1673,7 @@ static struct samsung_mux_clock top_mux_clks[] __initdata = {
                        MUX_SEL_TOP_GSCL, 20, 1),
 };
 
-static struct samsung_div_clock top_div_clks[] __initdata = {
+static const struct samsung_div_clock top_div_clks[] __initconst = {
        DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
                        DIV_TOP_G2D_MFC, 0, 3),
        DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
@@ -1794,7 +1794,7 @@ static struct samsung_div_clock top_div_clks[] __initdata = {
 
 };
 
-static struct samsung_gate_clock top_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top_gate_clks[] __initconst = {
        GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
                        "dout_sclk_fsys_mmc0_sdclkin_b",
                        EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
@@ -1809,7 +1809,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = {
                        CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_pll_clock top_pll_clks[] __initdata = {
+static const struct samsung_pll_clock top_pll_clks[] __initconst = {
        PLL(pll_2550xx, TOP_FOUT_DISP_PLL, "fout_disp_pll", "fin_pll",
                DISP_PLL_LOCK, DISP_PLL_CON0,
                pll2550_24mhz_tbl),
index d5d5dcabc4a968c490a768634f28d8cd04327c93..54ec486a5e45c2c1fdb2e203edd67e7c0b761093 100644 (file)
 #define SRC_CPU                        0x200
 #define DIV_CPU0               0x500
 #define SRC_CPERI1             0x4204
+#define GATE_IP_G2D            0x8800
 #define DIV_TOP0               0x10510
 #define DIV_TOP1               0x10514
+#define DIV_FSYS0              0x10548
 #define DIV_FSYS1              0x1054c
 #define DIV_FSYS2              0x10550
 #define DIV_PERIC0             0x10558
+#define DIV_PERIC3             0x10564
 #define SRC_TOP0               0x10210
 #define SRC_TOP1               0x10214
 #define SRC_TOP2               0x10218
@@ -44,6 +47,8 @@
 #define SRC_MASK_FSYS          0x10340
 #define SRC_MASK_PERIC0                0x10350
 #define GATE_BUS_FSYS0         0x10740
+#define GATE_TOP_SCLK_FSYS     0x10840
+#define GATE_TOP_SCLK_PERIC    0x10850
 #define GATE_IP_FSYS           0x10944
 #define GATE_IP_PERIC          0x10950
 #define GATE_IP_PERIS          0x10960
@@ -71,12 +76,13 @@ PNAME(mout_kfc_p)   = { "mout_kpll", "sclk_mpll", };
 PNAME(mpll_user_p)     = { "fin_pll", "sclk_mpll", };
 PNAME(bpll_user_p)     = { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)     = { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+PNAME(sclk_mpll_bpll_p)        = { "sclk_mpll_bpll", "fin_pll", };
 
 PNAME(group2_p)                = { "fin_pll", "fin_pll", "none", "none",
                        "none", "none", "sclk_mpll_bpll",
                         "none", "none", "sclk_cpll" };
 
-static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5410_mux_clks[] __initconst = {
        MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
        MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
 
@@ -96,16 +102,20 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
        MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
        MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
        MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+       MUX(0, "mout_usbd300", sclk_mpll_bpll_p, SRC_FSYS, 28, 1),
+       MUX(0, "mout_usbd301", sclk_mpll_bpll_p, SRC_FSYS, 29, 1),
 
        MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
        MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
        MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+       MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4),
+       MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 4),
 
        MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
        MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
 };
 
-static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5410_div_clks[] __initconst = {
        DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
        DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
 
@@ -121,6 +131,11 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
        DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
        DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
 
+       DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4),
+       DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4),
+       DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4),
+       DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4),
+
        DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
        DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
        DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
@@ -137,12 +152,19 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
        DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
        DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
 
+       DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+
        DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
+       DIV(0, "aclk266", "mpll_user_p", DIV_TOP0, 16, 3),
        DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
 };
 
-static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
+       GATE(CLK_SSS, "sss", "aclk266", GATE_IP_G2D, 2, 0, 0),
        GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+       GATE(CLK_WDT, "wdt", "aclk66", GATE_IP_PERIS, 19, 0, 0),
+       GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
+       GATE(CLK_TMU, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0),
 
        GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
                        SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
@@ -155,9 +177,31 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
        GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
        GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
 
+       GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
+            GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300",
+            GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300",
+            GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
+            GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0),
+
+       GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm",
+            GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+
        GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
        GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
        GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+       GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+       GATE(CLK_I2C0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
+       GATE(CLK_I2C1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
+       GATE(CLK_I2C2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
+       GATE(CLK_I2C3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
+       GATE(CLK_USI0, "usi0", "aclk66", GATE_IP_PERIC, 10, 0, 0),
+       GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0),
+       GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0),
+       GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0),
+       GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
        GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
                        SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
@@ -165,9 +209,15 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
                        SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
                        SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
+                       SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+
+       GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0),
+       GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0),
+       GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
 };
 
-static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
+static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = {
        [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
                APLL_CON0, NULL),
        [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
index 92382cef9f90a2cc23c0c74ed11cad6e404c37c4..bb196ca21a775f70793f36e641adf18150fa29a7 100644 (file)
@@ -160,7 +160,7 @@ static struct samsung_clk_reg_dump *exynos5800_save;
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
  */
-static unsigned long exynos5x_clk_regs[] __initdata = {
+static const unsigned long exynos5x_clk_regs[] __initconst = {
        SRC_CPU,
        DIV_CPU0,
        DIV_CPU1,
@@ -248,7 +248,7 @@ static unsigned long exynos5x_clk_regs[] __initdata = {
        DIV_KFC0,
 };
 
-static unsigned long exynos5800_clk_regs[] __initdata = {
+static const unsigned long exynos5800_clk_regs[] __initconst = {
        SRC_TOP8,
        SRC_TOP9,
        SRC_CAM,
@@ -306,7 +306,7 @@ static struct syscore_ops exynos5420_clk_syscore_ops = {
        .resume = exynos5420_clk_resume,
 };
 
-static void exynos5420_clk_sleep_init(void)
+static void __init exynos5420_clk_sleep_init(void)
 {
        exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs,
                                        ARRAY_SIZE(exynos5x_clk_regs));
@@ -333,7 +333,7 @@ err_soc:
        return;
 }
 #else
-static void exynos5420_clk_sleep_init(void) {}
+static void __init exynos5420_clk_sleep_init(void) {}
 #endif
 
 /* list of all parent clocks */
@@ -484,7 +484,7 @@ static struct samsung_fixed_rate_clock
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initconst = {
        FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 24000000),
        FRATE(0, "sclk_pwi", NULL, 0, 24000000),
        FRATE(0, "sclk_usbh20", NULL, 0, 48000000),
@@ -492,19 +492,19 @@ static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = {
        FRATE(0, "sclk_usbh20_scan_clk", NULL, 0, 480000000),
 };
 
-static struct samsung_fixed_factor_clock
-               exynos5x_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock
+               exynos5x_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "ff_hsic_12m", "fin_pll", 1, 2, 0),
        FFACTOR(0, "ff_sw_aclk66", "mout_sw_aclk66", 1, 2, 0),
 };
 
-static struct samsung_fixed_factor_clock
-               exynos5800_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock
+               exynos5800_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0),
        FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
 };
 
-static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
        MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
        MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
        MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
@@ -553,7 +553,7 @@ static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
        MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
 };
 
-static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5800_div_clks[] __initconst = {
        DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore",
                        "mout_aclk400_wcore", DIV_TOP0, 16, 3),
        DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
@@ -569,14 +569,14 @@ static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
        DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
 };
 
-static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
        GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
                                GATE_BUS_TOP, 24, 0, 0),
        GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
                                GATE_BUS_TOP, 27, 0, 0),
 };
 
-static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
        MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
        MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
                                TOP_SPARE2, 4, 1),
@@ -606,12 +606,12 @@ static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
        MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
 };
 
-static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5420_div_clks[] __initconst = {
        DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore",
                        "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3),
 };
 
-static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
        MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p,
                        SRC_TOP7, 4, 1),
        MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
@@ -778,7 +778,7 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
        MUX(0, "mout_isp_sensor", mout_group2_p, SRC_ISP, 28, 3),
 };
 
-static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
        DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
        DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3),
@@ -911,7 +911,7 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
                        CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        /* G2D */
        GATE(CLK_MDMA0, "mdma0", "aclk266_g2d", GATE_IP_G2D, 1, 0, 0),
        GATE(CLK_SSS, "sss", "aclk266_g2d", GATE_IP_G2D, 2, 0, 0),
@@ -946,7 +946,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_user_aclk333",
+       GATE(CLK_ACLK333, "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),
@@ -1219,7 +1219,7 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
        GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
 };
 
-static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = {
+static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
        PLL_35XX_RATE(2000000000, 250, 3, 0),
        PLL_35XX_RATE(1900000000, 475, 6, 0),
        PLL_35XX_RATE(1800000000, 225, 3, 0),
@@ -1356,8 +1356,6 @@ static void __init exynos5x_clk_init(struct device_node *np,
        exynos5x_soc = soc;
 
        ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
                        ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
index 128527b8fbeb8e54a06d8abbeabe4a6e9f5f9903..ea1608682d7fe90b3b20ede863386d82c4f23e7b 100644 (file)
 
 #include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <dt-bindings/clock/exynos5433.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 #include "clk-pll.h"
 
 /*
 #define ENABLE_CMU_TOP                 0x0c00
 #define ENABLE_CMU_TOP_DIV_STAT                0x0c04
 
-static unsigned long top_clk_regs[] __initdata = {
+static const unsigned long top_clk_regs[] __initconst = {
        ISP_PLL_LOCK,
        AUD_PLL_LOCK,
        ISP_PLL_CON0,
@@ -218,11 +220,11 @@ PNAME(mout_sclk_audio0_p) = { "ioclk_audiocdclk0", "oscclk",
 
 PNAME(mout_sclk_hdmi_spdif_p)  = { "sclk_audio1", "ioclk_spdif_extclk", };
 
-static struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "oscclk_efuse_common", "oscclk", 1, 1, 0),
 };
 
-static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock top_fixed_clks[] __initconst = {
        /* Xi2s{0|1}CDCLK input clock for I2S/PCM */
        FRATE(0, "ioclk_audiocdclk1", NULL, 0, 100000000),
        FRATE(0, "ioclk_audiocdclk0", NULL, 0, 100000000),
@@ -238,7 +240,7 @@ static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = {
        FRATE(0, "ioclk_i2s1_bclk_in", NULL, 0, 12288000),
 };
 
-static struct samsung_mux_clock top_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top_mux_clks[] __initconst = {
        /* MUX_SEL_TOP0 */
        MUX(CLK_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p, MUX_SEL_TOP0,
                        4, 1),
@@ -374,7 +376,7 @@ static struct samsung_mux_clock top_mux_clks[] __initdata = {
                        mout_sclk_hdmi_spdif_p, MUX_SEL_TOP_DISP, 0, 1),
 };
 
-static struct samsung_div_clock top_div_clks[] __initdata = {
+static const struct samsung_div_clock top_div_clks[] __initconst = {
        /* DIV_TOP0 */
        DIV(CLK_DIV_ACLK_CAM1_333, "div_aclk_cam1_333", "mout_aclk_cam1_333",
                        DIV_TOP0, 28, 3),
@@ -538,7 +540,7 @@ static struct samsung_div_clock top_div_clks[] __initdata = {
                        DIV_TOP_PERIC4, 0, 4),
 };
 
-static struct samsung_gate_clock top_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top_gate_clks[] __initconst = {
        /* ENABLE_ACLK_TOP */
        GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
                        ENABLE_ACLK_TOP, 30, 0, 0),
@@ -639,7 +641,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = {
 
        /* ENABLE_SCLK_TOP_FSYS */
        GATE(CLK_SCLK_PCIE_100_FSYS, "sclk_pcie_100_fsys", "div_sclk_pcie_100",
-                       ENABLE_SCLK_TOP_FSYS, 7, 0, 0),
+                       ENABLE_SCLK_TOP_FSYS, 7, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_MMC2_FSYS, "sclk_mmc2_fsys", "div_sclk_mmc2_b",
                        ENABLE_SCLK_TOP_FSYS, 6, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_MMC1_FSYS, "sclk_mmc1_fsys", "div_sclk_mmc1_b",
@@ -668,11 +670,14 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = {
        GATE(CLK_SCLK_PCM1_PERIC, "sclk_pcm1_peric", "div_sclk_pcm1",
                        ENABLE_SCLK_TOP_PERIC, 7, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_UART2_PERIC, "sclk_uart2_peric", "div_sclk_uart2",
-                       ENABLE_SCLK_TOP_PERIC, 5, CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_TOP_PERIC, 5, CLK_SET_RATE_PARENT |
+                       CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_UART1_PERIC, "sclk_uart1_peric", "div_sclk_uart1",
-                       ENABLE_SCLK_TOP_PERIC, 4, CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_TOP_PERIC, 4, CLK_SET_RATE_PARENT |
+                       CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_UART0_PERIC, "sclk_uart0_peric", "div_sclk_uart0",
-                       ENABLE_SCLK_TOP_PERIC, 3, CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_TOP_PERIC, 3, CLK_SET_RATE_PARENT |
+                       CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_SPI2_PERIC, "sclk_spi2_peric", "div_sclk_spi2_b",
                        ENABLE_SCLK_TOP_PERIC, 2, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_SPI1_PERIC, "sclk_spi1_peric", "div_sclk_spi1_b",
@@ -693,7 +698,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = {
  * ATLAS_PLL & APOLLO_PLL & MEM0_PLL & MEM1_PLL & BUS_PLL & MFC_PLL
  * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL
  */
-static struct samsung_pll_rate_table exynos5443_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos5443_pll_rates[] __initconst = {
        PLL_35XX_RATE(2500000000U, 625, 6,  0),
        PLL_35XX_RATE(2400000000U, 500, 5,  0),
        PLL_35XX_RATE(2300000000U, 575, 6,  0),
@@ -744,7 +749,7 @@ static struct samsung_pll_rate_table exynos5443_pll_rates[] = {
 };
 
 /* AUD_PLL */
-static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] __initconst = {
        PLL_36XX_RATE(400000000U, 200, 3, 2,      0),
        PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
        PLL_36XX_RATE(384000000U, 128, 2, 2,      0),
@@ -757,14 +762,14 @@ static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
        { /* sentinel */ }
 };
 
-static struct samsung_pll_clock top_pll_clks[] __initdata = {
+static const struct samsung_pll_clock top_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "oscclk",
                ISP_PLL_LOCK, ISP_PLL_CON0, exynos5443_pll_rates),
        PLL(pll_36xx, CLK_FOUT_AUD_PLL, "fout_aud_pll", "oscclk",
                AUD_PLL_LOCK, AUD_PLL_CON0, exynos5443_aud_pll_rates),
 };
 
-static struct samsung_cmu_info top_cmu_info __initdata = {
+static const struct samsung_cmu_info top_cmu_info __initconst = {
        .pll_clks               = top_pll_clks,
        .nr_pll_clks            = ARRAY_SIZE(top_pll_clks),
        .mux_clks               = top_mux_clks,
@@ -800,7 +805,7 @@ CLK_OF_DECLARE(exynos5433_cmu_top, "samsung,exynos5433-cmu-top",
 #define DIV_CPIF               0x0600
 #define ENABLE_SCLK_CPIF       0x0a00
 
-static unsigned long cpif_clk_regs[] __initdata = {
+static const unsigned long cpif_clk_regs[] __initconst = {
        MPHY_PLL_LOCK,
        MPHY_PLL_CON0,
        MPHY_PLL_CON1,
@@ -813,32 +818,32 @@ static unsigned long cpif_clk_regs[] __initdata = {
 /* list of all parent clock list */
 PNAME(mout_mphy_pll_p)         = { "oscclk", "fout_mphy_pll", };
 
-static struct samsung_pll_clock cpif_pll_clks[] __initdata = {
+static const struct samsung_pll_clock cpif_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_MPHY_PLL, "fout_mphy_pll", "oscclk",
                MPHY_PLL_LOCK, MPHY_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock cpif_mux_clks[] __initdata = {
+static const struct samsung_mux_clock cpif_mux_clks[] __initconst = {
        /* MUX_SEL_CPIF0 */
        MUX(CLK_MOUT_MPHY_PLL, "mout_mphy_pll", mout_mphy_pll_p, MUX_SEL_CPIF0,
                        0, 1),
 };
 
-static struct samsung_div_clock cpif_div_clks[] __initdata = {
+static const struct samsung_div_clock cpif_div_clks[] __initconst = {
        /* DIV_CPIF */
        DIV(CLK_DIV_SCLK_MPHY, "div_sclk_mphy", "mout_mphy_pll", DIV_CPIF,
                        0, 6),
 };
 
-static struct samsung_gate_clock cpif_gate_clks[] __initdata = {
+static const struct samsung_gate_clock cpif_gate_clks[] __initconst = {
        /* ENABLE_SCLK_CPIF */
        GATE(CLK_SCLK_MPHY_PLL, "sclk_mphy_pll", "mout_mphy_pll",
-                       ENABLE_SCLK_CPIF, 9, 0, 0),
+                       ENABLE_SCLK_CPIF, 9, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_UFS_MPHY, "sclk_ufs_mphy", "div_sclk_mphy",
                        ENABLE_SCLK_CPIF, 4, 0, 0),
 };
 
-static struct samsung_cmu_info cpif_cmu_info __initdata = {
+static const struct samsung_cmu_info cpif_cmu_info __initconst = {
        .pll_clks               = cpif_pll_clks,
        .nr_pll_clks            = ARRAY_SIZE(cpif_pll_clks),
        .mux_clks               = cpif_mux_clks,
@@ -939,7 +944,7 @@ CLK_OF_DECLARE(exynos5433_cmu_cpif, "samsung,exynos5433-cmu-cpif",
 #define PAUSE                          0x1008
 #define DDRPHY_LOCK_CTRL               0x100c
 
-static unsigned long mif_clk_regs[] __initdata = {
+static const unsigned long mif_clk_regs[] __initconst = {
        MEM0_PLL_LOCK,
        MEM1_PLL_LOCK,
        BUS_PLL_LOCK,
@@ -1004,7 +1009,7 @@ static unsigned long mif_clk_regs[] __initdata = {
        DDRPHY_LOCK_CTRL,
 };
 
-static struct samsung_pll_clock mif_pll_clks[] __initdata = {
+static const struct samsung_pll_clock mif_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_MEM0_PLL, "fout_mem0_pll", "oscclk",
                MEM0_PLL_LOCK, MEM0_PLL_CON0, exynos5443_pll_rates),
        PLL(pll_35xx, CLK_FOUT_MEM1_PLL, "fout_mem1_pll", "oscclk",
@@ -1065,7 +1070,7 @@ PNAME(mout_sclk_decon_tv_vclk_b_p) = { "mout_sclk_decon_tv_vclk_a",
 PNAME(mout_sclk_dsim1_c_p)     = { "mout_sclk_dsim1_b", "sclk_mphy_pll", };
 PNAME(mout_sclk_dsim1_b_p)     = { "mout_sclk_dsim1_a", "mout_mfc_pll_div2",};
 
-static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initconst = {
        /* dout_{mfc|bus|mem1|mem0}_pll is half fixed rate from parent mux */
        FFACTOR(CLK_DOUT_MFC_PLL, "dout_mfc_pll", "mout_mfc_pll", 1, 1, 0),
        FFACTOR(CLK_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll", 1, 1, 0),
@@ -1073,7 +1078,7 @@ static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = {
        FFACTOR(CLK_DOUT_MEM0_PLL, "dout_mem0_pll", "mout_mem0_pll", 1, 1, 0),
 };
 
-static struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mif_mux_clks[] __initconst = {
        /* MUX_SEL_MIF0 */
        MUX(CLK_MOUT_MFC_PLL_DIV2, "mout_mfc_pll_div2", mout_mfc_pll_div2_p,
                        MUX_SEL_MIF0, 28, 1),
@@ -1169,7 +1174,7 @@ static struct samsung_mux_clock mif_mux_clks[] __initdata = {
                        MUX_SEL_MIF7, 0, 1),
 };
 
-static struct samsung_div_clock mif_div_clks[] __initdata = {
+static const struct samsung_div_clock mif_div_clks[] __initconst = {
        /* DIV_MIF1 */
        DIV(CLK_DIV_SCLK_HPM_MIF, "div_sclk_hpm_mif", "div_clk2x_phy",
                        DIV_MIF1, 16, 2),
@@ -1223,7 +1228,7 @@ static struct samsung_div_clock mif_div_clks[] __initdata = {
                        0, 3),
 };
 
-static struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mif_gate_clks[] __initconst = {
        /* ENABLE_ACLK_MIF0 */
        GATE(CLK_CLK2X_PHY1, "clk2k_phy1", "div_clk2x_phy", ENABLE_ACLK_MIF0,
                        19, CLK_IGNORE_UNUSED, 0),
@@ -1440,11 +1445,13 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
 
        /* ENABLE_PCLK_MIF_SECURE_DREX0_TZ */
        GATE(CLK_PCLK_DREX0_TZ, "pclk_drex0_tz", "div_aclk_mif_133",
-                       ENABLE_PCLK_MIF_SECURE_DREX0_TZ, 0, 0, 0),
+                       ENABLE_PCLK_MIF_SECURE_DREX0_TZ, 0,
+                       CLK_IGNORE_UNUSED, 0),
 
        /* ENABLE_PCLK_MIF_SECURE_DREX1_TZ */
        GATE(CLK_PCLK_DREX1_TZ, "pclk_drex1_tz", "div_aclk_mif_133",
-                       ENABLE_PCLK_MIF_SECURE_DREX1_TZ, 0, 0, 0),
+                       ENABLE_PCLK_MIF_SECURE_DREX1_TZ, 0,
+                       CLK_IGNORE_UNUSED, 0),
 
        /* ENABLE_PCLK_MIF_SECURE_MONOTONIC_CNT */
        GATE(CLK_PCLK_MONOTONIC_CNT, "pclk_monotonic_cnt", "div_aclk_mif_133",
@@ -1486,7 +1493,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
                        ENABLE_SCLK_MIF, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info mif_cmu_info __initdata = {
+static const struct samsung_cmu_info mif_cmu_info __initconst = {
        .pll_clks               = mif_pll_clks,
        .nr_pll_clks            = ARRAY_SIZE(mif_pll_clks),
        .mux_clks               = mif_mux_clks,
@@ -1522,7 +1529,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mif, "samsung,exynos5433-cmu-mif",
 #define ENABLE_IP_PERIC1               0x0B04
 #define ENABLE_IP_PERIC2               0x0B08
 
-static unsigned long peric_clk_regs[] __initdata = {
+static const unsigned long peric_clk_regs[] __initconst = {
        DIV_PERIC,
        ENABLE_ACLK_PERIC,
        ENABLE_PCLK_PERIC0,
@@ -1533,13 +1540,13 @@ static unsigned long peric_clk_regs[] __initdata = {
        ENABLE_IP_PERIC2,
 };
 
-static struct samsung_div_clock peric_div_clks[] __initdata = {
+static const struct samsung_div_clock peric_div_clks[] __initconst = {
        /* DIV_PERIC */
        DIV(CLK_DIV_SCLK_SCI, "div_sclk_sci", "oscclk", DIV_PERIC, 4, 4),
        DIV(CLK_DIV_SCLK_SC_IN, "div_sclk_sc_in", "oscclk", DIV_PERIC, 0, 4),
 };
 
-static struct samsung_gate_clock peric_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peric_gate_clks[] __initconst = {
        /* ENABLE_ACLK_PERIC */
        GATE(CLK_ACLK_AHB2APB_PERIC2P, "aclk_ahb2apb_peric2p", "aclk_peric_66",
                        ENABLE_ACLK_PERIC, 3, CLK_IGNORE_UNUSED, 0),
@@ -1654,8 +1661,7 @@ static struct samsung_gate_clock peric_gate_clks[] __initdata = {
        GATE(CLK_SCLK_IOCLK_SPI2, "sclk_ioclk_spi2", "ioclk_spi2_clk_in",
                        ENABLE_SCLK_PERIC, 13, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_IOCLK_SPI1, "sclk_ioclk_spi1", "ioclk_spi1_clk_in",
-                       ENABLE_SCLK_PERIC, 12,
-                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_PERIC, 12, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_IOCLK_SPI0, "sclk_ioclk_spi0", "ioclk_spi0_clk_in",
                        ENABLE_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_IOCLK_I2S1_BCLK, "sclk_ioclk_i2s1_bclk",
@@ -1670,18 +1676,21 @@ static struct samsung_gate_clock peric_gate_clks[] __initdata = {
        GATE(CLK_SCLK_SPI2, "sclk_spi2", "sclk_spi2_peric", ENABLE_SCLK_PERIC,
                        5, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_SPI1, "sclk_spi1", "sclk_spi1_peric", ENABLE_SCLK_PERIC,
-                       4, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+                       4, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_SPI0, "sclk_spi0", "sclk_spi0_peric", ENABLE_SCLK_PERIC,
                        3, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_UART2, "sclk_uart2", "sclk_uart2_peric",
-                       ENABLE_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_PERIC, 2,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_UART1, "sclk_uart1", "sclk_uart1_peric",
-                       ENABLE_SCLK_PERIC, 1, CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_PERIC, 1,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_UART0, "sclk_uart0", "sclk_uart0_peric",
-                       ENABLE_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0),
+                       ENABLE_SCLK_PERIC, 0,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info peric_cmu_info __initdata = {
+static const struct samsung_cmu_info peric_cmu_info __initconst = {
        .div_clks               = peric_div_clks,
        .nr_div_clks            = ARRAY_SIZE(peric_div_clks),
        .gate_clks              = peric_gate_clks,
@@ -1728,7 +1737,7 @@ CLK_OF_DECLARE(exynos5433_cmu_peric, "samsung,exynos5433-cmu-peric",
 #define ENABLE_IP_PERIS_SECURE_ANTIBRK_CNT             0x0b1c
 #define ENABLE_IP_PERIS_SECURE_OTP_CON                 0x0b20
 
-static unsigned long peris_clk_regs[] __initdata = {
+static const unsigned long peris_clk_regs[] __initconst = {
        ENABLE_ACLK_PERIS,
        ENABLE_PCLK_PERIS,
        ENABLE_PCLK_PERIS_SECURE_TZPC,
@@ -1756,7 +1765,7 @@ static unsigned long peris_clk_regs[] __initdata = {
        ENABLE_IP_PERIS_SECURE_OTP_CON,
 };
 
-static struct samsung_gate_clock peris_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peris_gate_clks[] __initconst = {
        /* ENABLE_ACLK_PERIS */
        GATE(CLK_ACLK_AHB2APB_PERIS1P, "aclk_ahb2apb_peris1p", "aclk_peris_66",
                        ENABLE_ACLK_PERIS, 2, CLK_IGNORE_UNUSED, 0),
@@ -1875,7 +1884,7 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
                        ENABLE_SCLK_PERIS_SECURE_OTP_CON, 0, 0, 0),
 };
 
-static struct samsung_cmu_info peris_cmu_info __initdata = {
+static const struct samsung_cmu_info peris_cmu_info __initconst = {
        .gate_clks              = peris_gate_clks,
        .nr_gate_clks           = ARRAY_SIZE(peris_gate_clks),
        .nr_clk_ids             = PERIS_NR_CLK,
@@ -1959,7 +1968,7 @@ PNAME(mout_sclk_mphy_p)
                = { "mout_sclk_ufs_mphy_user",
                            "mout_phyclk_lli_mphy_to_ufs_user", };
 
-static unsigned long fsys_clk_regs[] __initdata = {
+static const unsigned long fsys_clk_regs[] __initconst = {
        MUX_SEL_FSYS0,
        MUX_SEL_FSYS1,
        MUX_SEL_FSYS2,
@@ -1980,7 +1989,7 @@ static unsigned long fsys_clk_regs[] __initdata = {
        ENABLE_IP_FSYS1,
 };
 
-static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = {
        /* PHY clocks from USBDRD30_PHY */
        FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY,
                        "phyclk_usbdrd30_udrd30_phyclock_phy", NULL,
@@ -2020,7 +2029,7 @@ static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = {
                        NULL, 0, 26000000),
 };
 
-static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys_mux_clks[] __initconst = {
        /* MUX_SEL_FSYS0 */
        MUX(CLK_MOUT_SCLK_UFS_MPHY_USER, "mout_sclk_ufs_mphy_user",
                        mout_sclk_ufs_mphy_user_p, MUX_SEL_FSYS0, 4, 1),
@@ -2104,7 +2113,7 @@ static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
                        MUX_SEL_FSYS4, 0, 1),
 };
 
-static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys_gate_clks[] __initconst = {
        /* ENABLE_ACLK_FSYS0 */
        GATE(CLK_ACLK_PCIE, "aclk_pcie", "mout_aclk_fsys_200_user",
                        ENABLE_ACLK_FSYS0, 13, CLK_IGNORE_UNUSED, 0),
@@ -2138,7 +2147,7 @@ static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
        GATE(CLK_ACLK_SMMU_PDMA1, "aclk_smmu_pdma1", "mout_aclk_fsys_200_user",
                        ENABLE_ACLK_FSYS1, 25, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_BTS_PCIE, "aclk_bts_pcie", "mout_aclk_fsys_200_user",
-                       ENABLE_ACLK_FSYS1, 24, 0, 0),
+                       ENABLE_ACLK_FSYS1, 24, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_AXIUS_PDMA1, "aclk_axius_pdma1",
                        "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
                        22, CLK_IGNORE_UNUSED, 0),
@@ -2185,13 +2194,13 @@ static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
 
        /* ENABLE_PCLK_FSYS */
        GATE(CLK_PCLK_PCIE_CTRL, "pclk_pcie_ctrl", "mout_aclk_fsys_200_user",
-                       ENABLE_PCLK_FSYS, 17, 0, 0),
+                       ENABLE_PCLK_FSYS, 17, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_PCLK_SMMU_PDMA1, "pclk_smmu_pdma1", "mout_aclk_fsys_200_user",
                        ENABLE_PCLK_FSYS, 16, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_PCLK_PCIE_PHY, "pclk_pcie_phy", "mout_aclk_fsys_200_user",
-                       ENABLE_PCLK_FSYS, 14, 0, 0),
+                       ENABLE_PCLK_FSYS, 14, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_PCLK_BTS_PCIE, "pclk_bts_pcie", "mout_aclk_fsys_200_user",
-                       ENABLE_PCLK_FSYS, 13, 0, 0),
+                       ENABLE_PCLK_FSYS, 13, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_PCLK_SMMU_PDMA0, "pclk_smmu_pdma0", "mout_aclk_fsys_200_user",
                        ENABLE_PCLK_FSYS, 8, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_PCLK_BTS_UFS, "pclk_bts_ufs", "mout_aclk_fsys_200_user",
@@ -2270,11 +2279,12 @@ static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
                        ENABLE_SCLK_FSYS, 0, 0, 0),
 
        /* ENABLE_IP_FSYS0 */
+       GATE(CLK_PCIE, "pcie", "sclk_pcie_100", ENABLE_IP_FSYS0, 17, 0, 0),
        GATE(CLK_PDMA1, "pdma1", "aclk_pdma1", ENABLE_IP_FSYS0, 15, 0, 0),
        GATE(CLK_PDMA0, "pdma0", "aclk_pdma0", ENABLE_IP_FSYS0, 0, 0, 0),
 };
 
-static struct samsung_cmu_info fsys_cmu_info __initdata = {
+static const struct samsung_cmu_info fsys_cmu_info __initconst = {
        .mux_clks               = fsys_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(fsys_mux_clks),
        .gate_clks              = fsys_gate_clks,
@@ -2310,7 +2320,7 @@ CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys",
 #define DIV_ENABLE_IP_G2D1                     0x0b04
 #define DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D      0x0b08
 
-static unsigned long g2d_clk_regs[] __initdata = {
+static const unsigned long g2d_clk_regs[] __initconst = {
        MUX_SEL_G2D0,
        MUX_SEL_ENABLE_G2D0,
        DIV_G2D,
@@ -2327,7 +2337,7 @@ static unsigned long g2d_clk_regs[] __initdata = {
 PNAME(mout_aclk_g2d_266_user_p)                = { "oscclk", "aclk_g2d_266", };
 PNAME(mout_aclk_g2d_400_user_p)                = { "oscclk", "aclk_g2d_400", };
 
-static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g2d_mux_clks[] __initconst = {
        /* MUX_SEL_G2D0 */
        MUX(CLK_MUX_ACLK_G2D_266_USER, "mout_aclk_g2d_266_user",
                        mout_aclk_g2d_266_user_p, MUX_SEL_G2D0, 4, 1),
@@ -2335,13 +2345,13 @@ static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
                        mout_aclk_g2d_400_user_p, MUX_SEL_G2D0, 0, 1),
 };
 
-static struct samsung_div_clock g2d_div_clks[] __initdata = {
+static const struct samsung_div_clock g2d_div_clks[] __initconst = {
        /* DIV_G2D */
        DIV(CLK_DIV_PCLK_G2D, "div_pclk_g2d", "mout_aclk_g2d_266_user",
                        DIV_G2D, 0, 2),
 };
 
-static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g2d_gate_clks[] __initconst = {
        /* DIV_ENABLE_ACLK_G2D */
        GATE(CLK_ACLK_SMMU_MDMA1, "aclk_smmu_mdma1", "mout_aclk_g2d_266_user",
                        DIV_ENABLE_ACLK_G2D, 12, 0, 0),
@@ -2398,7 +2408,7 @@ static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
                DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D, 0, 0, 0),
 };
 
-static struct samsung_cmu_info g2d_cmu_info __initdata = {
+static const struct samsung_cmu_info g2d_cmu_info __initconst = {
        .mux_clks               = g2d_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(g2d_mux_clks),
        .div_clks               = g2d_div_clks,
@@ -2454,7 +2464,7 @@ CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d",
 #define CLKOUT_CMU_DISP                        0x0c00
 #define CLKOUT_CMU_DISP_DIV_STAT       0x0c04
 
-static unsigned long disp_clk_regs[] __initdata = {
+static const unsigned long disp_clk_regs[] __initconst = {
        DISP_PLL_LOCK,
        DISP_PLL_CON0,
        DISP_PLL_CON1,
@@ -2527,12 +2537,12 @@ PNAME(mout_sclk_decon_tv_vclk_c_disp_p) = {
 PNAME(mout_sclk_decon_tv_vclk_b_disp_p)        = { "mout_sclk_decon_tv_vclk_a_disp",
                                            "mout_sclk_decon_tv_vclk_user", };
 
-static struct samsung_pll_clock disp_pll_clks[] __initdata = {
+static const struct samsung_pll_clock disp_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll", "oscclk",
                DISP_PLL_LOCK, DISP_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initconst = {
        /*
         * sclk_rgb_{vclk|tv_vclk} is half clock of sclk_decon_{vclk|tv_vclk}.
         * The divider has fixed value (2) between sclk_rgb_{vclk|tv_vclk}
@@ -2544,7 +2554,7 @@ static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = {
                        1, 2, 0),
 };
 
-static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock disp_fixed_clks[] __initconst = {
        /* PHY clocks from MIPI_DPHY1 */
        FRATE(0, "phyclk_mipidphy1_bitclkdiv8_phy", NULL, 0, 188000000),
        FRATE(0, "phyclk_mipidphy1_rxclkesc0_phy", NULL, 0, 100000000),
@@ -2558,7 +2568,7 @@ static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = {
                        NULL, 0, 166000000),
 };
 
-static struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock disp_mux_clks[] __initconst = {
        /* MUX_SEL_DISP0 */
        MUX(CLK_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, MUX_SEL_DISP0,
                        0, 1),
@@ -2633,7 +2643,7 @@ static struct samsung_mux_clock disp_mux_clks[] __initdata = {
                        mout_sclk_decon_vclk_p, MUX_SEL_DISP4, 0, 1),
 };
 
-static struct samsung_div_clock disp_div_clks[] __initdata = {
+static const struct samsung_div_clock disp_div_clks[] __initconst = {
        /* DIV_DISP */
        DIV(CLK_DIV_SCLK_DSIM1_DISP, "div_sclk_dsim1_disp",
                        "mout_sclk_dsim1_b_disp", DIV_DISP, 24, 3),
@@ -2651,7 +2661,7 @@ static struct samsung_div_clock disp_div_clks[] __initdata = {
                        DIV_DISP, 0, 2),
 };
 
-static struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock disp_gate_clks[] __initconst = {
        /* ENABLE_ACLK_DISP0 */
        GATE(CLK_ACLK_DECON_TV, "aclk_decon_tv", "mout_aclk_disp_333_user",
                        ENABLE_ACLK_DISP0, 2, 0, 0),
@@ -2811,7 +2821,7 @@ static struct samsung_gate_clock disp_gate_clks[] __initdata = {
                        "div_sclk_decon_eclk_disp", ENABLE_SCLK_DISP, 2, 0, 0),
 };
 
-static struct samsung_cmu_info disp_cmu_info __initdata = {
+static const struct samsung_cmu_info disp_cmu_info __initconst = {
        .pll_clks               = disp_pll_clks,
        .nr_pll_clks            = ARRAY_SIZE(disp_pll_clks),
        .mux_clks               = disp_mux_clks,
@@ -2856,7 +2866,7 @@ CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp",
 #define ENABLE_IP_AUD0                 0x0b00
 #define ENABLE_IP_AUD1                 0x0b04
 
-static unsigned long aud_clk_regs[] __initdata = {
+static const unsigned long aud_clk_regs[] __initconst = {
        MUX_SEL_AUD0,
        MUX_SEL_AUD1,
        MUX_ENABLE_AUD0,
@@ -2875,13 +2885,13 @@ static unsigned long aud_clk_regs[] __initdata = {
 PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", };
 PNAME(mout_sclk_aud_pcm_p)     = { "mout_aud_pll_user", "ioclk_audiocdclk0",};
 
-static struct samsung_fixed_rate_clock aud_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock aud_fixed_clks[] __initconst = {
        FRATE(0, "ioclk_jtag_tclk", NULL, 0, 33000000),
        FRATE(0, "ioclk_slimbus_clk", NULL, 0, 25000000),
        FRATE(0, "ioclk_i2s_bclk", NULL, 0, 50000000),
 };
 
-static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static const struct samsung_mux_clock aud_mux_clks[] __initconst = {
        /* MUX_SEL_AUD0 */
        MUX(CLK_MOUT_AUD_PLL_USER, "mout_aud_pll_user",
                        mout_aud_pll_user_aud_p, MUX_SEL_AUD0, 0, 1),
@@ -2893,7 +2903,7 @@ static struct samsung_mux_clock aud_mux_clks[] __initdata = {
                        MUX_SEL_AUD1, 0, 1),
 };
 
-static struct samsung_div_clock aud_div_clks[] __initdata = {
+static const struct samsung_div_clock aud_div_clks[] __initconst = {
        /* DIV_AUD0 */
        DIV(CLK_DIV_ATCLK_AUD, "div_atclk_aud", "div_aud_ca5", DIV_AUD0,
                        12, 4),
@@ -2915,7 +2925,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = {
                        DIV_AUD1, 0, 4),
 };
 
-static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
        /* ENABLE_ACLK_AUD */
        GATE(CLK_ACLK_INTR_CTRL, "aclk_intr_ctrl", "div_aclk_aud",
                        ENABLE_ACLK_AUD, 12, 0, 0),
@@ -2962,7 +2972,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
 
        /* ENABLE_SCLK_AUD0 */
        GATE(CLK_ATCLK_AUD, "atclk_aud", "div_atclk_aud", ENABLE_SCLK_AUD0,
-                       2, 0, 0),
+                       2, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_PCLK_DBG_AUD, "pclk_dbg_aud", "div_pclk_dbg_aud",
                        ENABLE_SCLK_AUD0, 1, 0, 0),
        GATE(CLK_SCLK_AUD_CA5, "sclk_aud_ca5", "div_aud_ca5", ENABLE_SCLK_AUD0,
@@ -2976,7 +2986,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
        GATE(CLK_SCLK_AUD_SLIMBUS, "sclk_aud_slimbus", "div_sclk_aud_slimbus",
                        ENABLE_SCLK_AUD1, 4, 0, 0),
        GATE(CLK_SCLK_AUD_UART, "sclk_aud_uart", "div_sclk_aud_uart",
-                       ENABLE_SCLK_AUD1, 3, 0, 0),
+                       ENABLE_SCLK_AUD1, 3, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_AUD_PCM, "sclk_aud_pcm", "div_sclk_aud_pcm",
                        ENABLE_SCLK_AUD1, 2, 0, 0),
        GATE(CLK_SCLK_I2S_BCLK, "sclk_i2s_bclk", "ioclk_i2s_bclk",
@@ -2985,7 +2995,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
                        ENABLE_SCLK_AUD1, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info aud_cmu_info __initdata = {
+static const struct samsung_cmu_info aud_cmu_info __initconst = {
        .mux_clks               = aud_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(aud_mux_clks),
        .div_clks               = aud_div_clks,
@@ -3031,24 +3041,24 @@ PNAME(mout_aclk_bus2_400_p)     = { "oscclk", "aclk_bus2_400", };
        ENABLE_IP_BUS0,         \
        ENABLE_IP_BUS1
 
-static unsigned long bus01_clk_regs[] __initdata = {
+static const unsigned long bus01_clk_regs[] __initconst = {
        CMU_BUS_COMMON_CLK_REGS,
 };
 
-static unsigned long bus2_clk_regs[] __initdata = {
+static const unsigned long bus2_clk_regs[] __initconst = {
        MUX_SEL_BUS2,
        MUX_ENABLE_BUS2,
        CMU_BUS_COMMON_CLK_REGS,
 };
 
-static struct samsung_div_clock bus0_div_clks[] __initdata = {
+static const struct samsung_div_clock bus0_div_clks[] __initconst = {
        /* DIV_BUS0 */
        DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus0_133", "aclk_bus0_400",
                        DIV_BUS, 0, 3),
 };
 
 /* CMU_BUS0 clocks */
-static struct samsung_gate_clock bus0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock bus0_gate_clks[] __initconst = {
        /* ENABLE_ACLK_BUS0 */
        GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus0p", "div_pclk_bus0_133",
                        ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0),
@@ -3067,13 +3077,13 @@ static struct samsung_gate_clock bus0_gate_clks[] __initdata = {
 };
 
 /* CMU_BUS1 clocks */
-static struct samsung_div_clock bus1_div_clks[] __initdata = {
+static const struct samsung_div_clock bus1_div_clks[] __initconst = {
        /* DIV_BUS1 */
        DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus1_133", "aclk_bus1_400",
                        DIV_BUS, 0, 3),
 };
 
-static struct samsung_gate_clock bus1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock bus1_gate_clks[] __initconst = {
        /* ENABLE_ACLK_BUS1 */
        GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus1p", "div_pclk_bus1_133",
                        ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0),
@@ -3092,19 +3102,19 @@ static struct samsung_gate_clock bus1_gate_clks[] __initdata = {
 };
 
 /* CMU_BUS2 clocks */
-static struct samsung_mux_clock bus2_mux_clks[] __initdata = {
+static const struct samsung_mux_clock bus2_mux_clks[] __initconst = {
        /* MUX_SEL_BUS2 */
        MUX(CLK_MOUT_ACLK_BUS2_400_USER, "mout_aclk_bus2_400_user",
                        mout_aclk_bus2_400_p, MUX_SEL_BUS2, 0, 1),
 };
 
-static struct samsung_div_clock bus2_div_clks[] __initdata = {
+static const struct samsung_div_clock bus2_div_clks[] __initconst = {
        /* DIV_BUS2 */
        DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus2_133",
                        "mout_aclk_bus2_400_user", DIV_BUS, 0, 3),
 };
 
-static struct samsung_gate_clock bus2_gate_clks[] __initdata = {
+static const struct samsung_gate_clock bus2_gate_clks[] __initconst = {
        /* ENABLE_ACLK_BUS2 */
        GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus2p", "div_pclk_bus2_133",
                        ENABLE_ACLK_BUS, 3, CLK_IGNORE_UNUSED, 0),
@@ -3133,19 +3143,19 @@ static struct samsung_gate_clock bus2_gate_clks[] __initdata = {
        .nr_gate_clks           = ARRAY_SIZE(bus##id##_gate_clks),      \
        .nr_clk_ids             = BUSx_NR_CLK
 
-static struct samsung_cmu_info bus0_cmu_info __initdata = {
+static const struct samsung_cmu_info bus0_cmu_info __initconst = {
        CMU_BUS_INFO_CLKS(0),
        .clk_regs               = bus01_clk_regs,
        .nr_clk_regs            = ARRAY_SIZE(bus01_clk_regs),
 };
 
-static struct samsung_cmu_info bus1_cmu_info __initdata = {
+static const struct samsung_cmu_info bus1_cmu_info __initconst = {
        CMU_BUS_INFO_CLKS(1),
        .clk_regs               = bus01_clk_regs,
        .nr_clk_regs            = ARRAY_SIZE(bus01_clk_regs),
 };
 
-static struct samsung_cmu_info bus2_cmu_info __initdata = {
+static const struct samsung_cmu_info bus2_cmu_info __initconst = {
        CMU_BUS_INFO_CLKS(2),
        .mux_clks               = bus2_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(bus2_mux_clks),
@@ -3189,7 +3199,7 @@ exynos5433_cmu_bus_init(2);
 #define CLKOUT_CMU_G3D_DIV_STAT                0x0c04
 #define CLK_STOPCTRL                   0x1000
 
-static unsigned long g3d_clk_regs[] __initdata = {
+static const unsigned long g3d_clk_regs[] __initconst = {
        G3D_PLL_LOCK,
        G3D_PLL_CON0,
        G3D_PLL_CON1,
@@ -3212,12 +3222,12 @@ static unsigned long g3d_clk_regs[] __initdata = {
 PNAME(mout_aclk_g3d_400_p)     = { "mout_g3d_pll", "aclk_g3d_400", };
 PNAME(mout_g3d_pll_p)          = { "oscclk", "fout_g3d_pll", };
 
-static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
+static const struct samsung_pll_clock g3d_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll", "oscclk",
                G3D_PLL_LOCK, G3D_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g3d_mux_clks[] __initconst = {
        /* MUX_SEL_G3D */
        MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
                        MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0),
@@ -3225,7 +3235,7 @@ static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
                        MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock g3d_div_clks[] __initdata = {
+static const struct samsung_div_clock g3d_div_clks[] __initconst = {
        /* DIV_G3D */
        DIV(CLK_DIV_SCLK_HPM_G3D, "div_sclk_hpm_g3d", "mout_g3d_pll", DIV_G3D,
                        8, 2),
@@ -3235,7 +3245,7 @@ static struct samsung_div_clock g3d_div_clks[] __initdata = {
                        0, 3, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g3d_gate_clks[] __initconst = {
        /* ENABLE_ACLK_G3D */
        GATE(CLK_ACLK_BTS_G3D1, "aclk_bts_g3d1", "div_aclk_g3d",
                        ENABLE_ACLK_G3D, 7, 0, 0),
@@ -3269,7 +3279,7 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
                        ENABLE_SCLK_G3D, 0, 0, 0),
 };
 
-static struct samsung_cmu_info g3d_cmu_info __initdata = {
+static const struct samsung_cmu_info g3d_cmu_info __initconst = {
        .pll_clks               = g3d_pll_clks,
        .nr_pll_clks            = ARRAY_SIZE(g3d_pll_clks),
        .mux_clks               = g3d_mux_clks,
@@ -3310,7 +3320,7 @@ CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d",
 #define ENABLE_IP_GSCL_SECURE_SMMU_GSCL1       0x0b0c
 #define ENABLE_IP_GSCL_SECURE_SMMU_GSCL2       0x0b10
 
-static unsigned long gscl_clk_regs[] __initdata = {
+static const unsigned long gscl_clk_regs[] __initconst = {
        MUX_SEL_GSCL,
        MUX_ENABLE_GSCL,
        ENABLE_ACLK_GSCL,
@@ -3332,7 +3342,7 @@ static unsigned long gscl_clk_regs[] __initdata = {
 PNAME(aclk_gscl_111_user_p)    = { "oscclk", "aclk_gscl_111", };
 PNAME(aclk_gscl_333_user_p)    = { "oscclk", "aclk_gscl_333", };
 
-static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock gscl_mux_clks[] __initconst = {
        /* MUX_SEL_GSCL */
        MUX(CLK_MOUT_ACLK_GSCL_111_USER, "mout_aclk_gscl_111_user",
                        aclk_gscl_111_user_p, MUX_SEL_GSCL, 4, 1),
@@ -3340,7 +3350,7 @@ static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
                        aclk_gscl_333_user_p, MUX_SEL_GSCL, 0, 1),
 };
 
-static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock gscl_gate_clks[] __initconst = {
        /* ENABLE_ACLK_GSCL */
        GATE(CLK_ACLK_BTS_GSCL2, "aclk_bts_gscl2", "mout_aclk_gscl_333_user",
                        ENABLE_ACLK_GSCL, 11, 0, 0),
@@ -3356,9 +3366,11 @@ static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
        GATE(CLK_ACLK_GSCLNP_111, "aclk_gsclnp_111", "mout_aclk_gscl_111_user",
                        ENABLE_ACLK_GSCL, 6, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_GSCLRTND_333, "aclk_gsclrtnd_333",
-                       "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 5, 0, 0),
+                       "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 5,
+                       CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_GSCLBEND_333, "aclk_gsclbend_333",
-                       "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 4, 0, 0),
+                       "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 4,
+                       CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_GSD, "aclk_gsd", "mout_aclk_gscl_333_user",
                        ENABLE_ACLK_GSCL, 3, 0, 0),
        GATE(CLK_ACLK_GSCL2, "aclk_gscl2", "mout_aclk_gscl_333_user",
@@ -3412,7 +3424,7 @@ static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
                ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL2, 0, 0, 0),
 };
 
-static struct samsung_cmu_info gscl_cmu_info __initdata = {
+static const struct samsung_cmu_info gscl_cmu_info __initconst = {
        .mux_clks               = gscl_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(gscl_mux_clks),
        .gate_clks              = gscl_gate_clks,
@@ -3465,7 +3477,7 @@ CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl",
 #define APOLLO_INTR_SPREAD_USE_STANDBYWFI      0x1084
 #define APOLLO_INTR_SPREAD_BLOCKING_DURATION   0x1088
 
-static unsigned long apollo_clk_regs[] __initdata = {
+static const unsigned long apollo_clk_regs[] __initconst = {
        APOLLO_PLL_LOCK,
        APOLLO_PLL_CON0,
        APOLLO_PLL_CON1,
@@ -3500,15 +3512,16 @@ PNAME(mout_bus_pll_apollo_user_p)       = { "oscclk", "sclk_bus_pll_apollo", };
 PNAME(mout_apollo_p)                   = { "mout_apollo_pll",
                                            "mout_bus_pll_apollo_user", };
 
-static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
+static const struct samsung_pll_clock apollo_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_APOLLO_PLL, "fout_apollo_pll", "oscclk",
                APOLLO_PLL_LOCK, APOLLO_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
+static const struct samsung_mux_clock apollo_mux_clks[] __initconst = {
        /* MUX_SEL_APOLLO0 */
        MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
-                       MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
+                       MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT |
+                       CLK_RECALC_NEW_RATES, 0),
 
        /* MUX_SEL_APOLLO1 */
        MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
@@ -3519,7 +3532,7 @@ static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
                        0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock apollo_div_clks[] __initdata = {
+static const struct samsung_div_clock apollo_div_clks[] __initconst = {
        /* DIV_APOLLO0 */
        DIV_F(CLK_DIV_CNTCLK_APOLLO, "div_cntclk_apollo", "div_apollo2",
                        DIV_APOLLO0, 24, 3, CLK_GET_RATE_NOCACHE,
@@ -3550,7 +3563,7 @@ static struct samsung_div_clock apollo_div_clks[] __initdata = {
                        CLK_DIVIDER_READ_ONLY),
 };
 
-static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
+static const struct samsung_gate_clock apollo_gate_clks[] __initconst = {
        /* ENABLE_ACLK_APOLLO */
        GATE(CLK_ACLK_ASATBSLV_APOLLO_3_CSSYS, "aclk_asatbslv_apollo_3_cssys",
                        "div_atclk_apollo", ENABLE_ACLK_APOLLO,
@@ -3589,28 +3602,64 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
                        ENABLE_SCLK_APOLLO, 3, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
                        ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
-       GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2",
-                       ENABLE_SCLK_APOLLO, 0,
-                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info apollo_cmu_info __initdata = {
-       .pll_clks               = apollo_pll_clks,
-       .nr_pll_clks            = ARRAY_SIZE(apollo_pll_clks),
-       .mux_clks               = apollo_mux_clks,
-       .nr_mux_clks            = ARRAY_SIZE(apollo_mux_clks),
-       .div_clks               = apollo_div_clks,
-       .nr_div_clks            = ARRAY_SIZE(apollo_div_clks),
-       .gate_clks              = apollo_gate_clks,
-       .nr_gate_clks           = ARRAY_SIZE(apollo_gate_clks),
-       .nr_clk_ids             = APOLLO_NR_CLK,
-       .clk_regs               = apollo_clk_regs,
-       .nr_clk_regs            = ARRAY_SIZE(apollo_clk_regs),
+#define E5433_APOLLO_DIV0(cntclk, pclk_dbg, atclk, pclk, aclk) \
+               (((cntclk) << 24) | ((pclk_dbg) << 20) | ((atclk) << 16) | \
+                ((pclk) << 12) | ((aclk) << 8))
+
+#define E5433_APOLLO_DIV1(hpm, copy) \
+               (((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data exynos5433_apolloclk_d[] __initconst = {
+       { 1300000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       { 1200000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       { 1100000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       { 1000000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       {  900000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       {  800000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       {  700000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+       {  600000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), },
+       {  500000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), },
+       {  400000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), },
+       {  0 },
 };
 
 static void __init exynos5433_cmu_apollo_init(struct device_node *np)
 {
-       samsung_cmu_register_one(np, &apollo_cmu_info);
+       void __iomem *reg_base;
+       struct samsung_clk_provider *ctx;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               panic("%s: failed to map registers\n", __func__);
+               return;
+       }
+
+       ctx = samsung_clk_init(np, reg_base, APOLLO_NR_CLK);
+       if (!ctx) {
+               panic("%s: unable to allocate ctx\n", __func__);
+               return;
+       }
+
+       samsung_clk_register_pll(ctx, apollo_pll_clks,
+                                ARRAY_SIZE(apollo_pll_clks), reg_base);
+       samsung_clk_register_mux(ctx, apollo_mux_clks,
+                                ARRAY_SIZE(apollo_mux_clks));
+       samsung_clk_register_div(ctx, apollo_div_clks,
+                                ARRAY_SIZE(apollo_div_clks));
+       samsung_clk_register_gate(ctx, apollo_gate_clks,
+                                 ARRAY_SIZE(apollo_gate_clks));
+
+       exynos_register_cpu_clock(ctx, CLK_SCLK_APOLLO, "apolloclk",
+               mout_apollo_p[0], mout_apollo_p[1], 0x200,
+               exynos5433_apolloclk_d, ARRAY_SIZE(exynos5433_apolloclk_d),
+               CLK_CPU_HAS_E5433_REGS_LAYOUT);
+
+       samsung_clk_sleep_init(reg_base, apollo_clk_regs,
+                              ARRAY_SIZE(apollo_clk_regs));
+
+       samsung_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo",
                exynos5433_cmu_apollo_init);
@@ -3651,7 +3700,7 @@ CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo",
 #define ATLAS_INTR_SPREAD_USE_STANDBYWFI       0x1084
 #define ATLAS_INTR_SPREAD_BLOCKING_DURATION    0x1088
 
-static unsigned long atlas_clk_regs[] __initdata = {
+static const unsigned long atlas_clk_regs[] __initconst = {
        ATLAS_PLL_LOCK,
        ATLAS_PLL_CON0,
        ATLAS_PLL_CON1,
@@ -3686,15 +3735,16 @@ PNAME(mout_bus_pll_atlas_user_p)        = { "oscclk", "sclk_bus_pll_atlas", };
 PNAME(mout_atlas_p)                    = { "mout_atlas_pll",
                                            "mout_bus_pll_atlas_user", };
 
-static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
+static const struct samsung_pll_clock atlas_pll_clks[] __initconst = {
        PLL(pll_35xx, CLK_FOUT_ATLAS_PLL, "fout_atlas_pll", "oscclk",
                ATLAS_PLL_LOCK, ATLAS_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
+static const struct samsung_mux_clock atlas_mux_clks[] __initconst = {
        /* MUX_SEL_ATLAS0 */
        MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
-                       MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
+                       MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT |
+                       CLK_RECALC_NEW_RATES, 0),
 
        /* MUX_SEL_ATLAS1 */
        MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
@@ -3705,7 +3755,7 @@ static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
                        0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock atlas_div_clks[] __initdata = {
+static const struct samsung_div_clock atlas_div_clks[] __initconst = {
        /* DIV_ATLAS0 */
        DIV_F(CLK_DIV_CNTCLK_ATLAS, "div_cntclk_atlas", "div_atlas2",
                        DIV_ATLAS0, 24, 3, CLK_GET_RATE_NOCACHE,
@@ -3736,7 +3786,7 @@ static struct samsung_div_clock atlas_div_clks[] __initdata = {
                        CLK_DIVIDER_READ_ONLY),
 };
 
-static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
+static const struct samsung_gate_clock atlas_gate_clks[] __initconst = {
        /* ENABLE_ACLK_ATLAS */
        GATE(CLK_ACLK_ATB_AUD_CSSYS, "aclk_atb_aud_cssys",
                        "div_atclk_atlas", ENABLE_ACLK_ATLAS,
@@ -3801,28 +3851,69 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
                        ENABLE_SCLK_ATLAS, 2, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
                        ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
-       GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
-                       ENABLE_SCLK_ATLAS, 0,
-                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info atlas_cmu_info __initdata = {
-       .pll_clks               = atlas_pll_clks,
-       .nr_pll_clks            = ARRAY_SIZE(atlas_pll_clks),
-       .mux_clks               = atlas_mux_clks,
-       .nr_mux_clks            = ARRAY_SIZE(atlas_mux_clks),
-       .div_clks               = atlas_div_clks,
-       .nr_div_clks            = ARRAY_SIZE(atlas_div_clks),
-       .gate_clks              = atlas_gate_clks,
-       .nr_gate_clks           = ARRAY_SIZE(atlas_gate_clks),
-       .nr_clk_ids             = ATLAS_NR_CLK,
-       .clk_regs               = atlas_clk_regs,
-       .nr_clk_regs            = ARRAY_SIZE(atlas_clk_regs),
+#define E5433_ATLAS_DIV0(cntclk, pclk_dbg, atclk, pclk, aclk) \
+               (((cntclk) << 24) | ((pclk_dbg) << 20) | ((atclk) << 16) | \
+                ((pclk) << 12) | ((aclk) << 8))
+
+#define E5433_ATLAS_DIV1(hpm, copy) \
+               (((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data exynos5433_atlasclk_d[] __initconst = {
+       { 1900000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+       { 1800000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+       { 1700000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+       { 1600000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+       { 1500000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+       { 1400000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+       { 1300000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+       { 1200000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+       { 1100000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+       { 1000000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+       {  900000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+       {  800000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+       {  700000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+       {  600000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+       {  500000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+       {  0 },
 };
 
 static void __init exynos5433_cmu_atlas_init(struct device_node *np)
 {
-       samsung_cmu_register_one(np, &atlas_cmu_info);
+       void __iomem *reg_base;
+       struct samsung_clk_provider *ctx;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               panic("%s: failed to map registers\n", __func__);
+               return;
+       }
+
+       ctx = samsung_clk_init(np, reg_base, ATLAS_NR_CLK);
+       if (!ctx) {
+               panic("%s: unable to allocate ctx\n", __func__);
+               return;
+       }
+
+       samsung_clk_register_pll(ctx, atlas_pll_clks,
+                                ARRAY_SIZE(atlas_pll_clks), reg_base);
+       samsung_clk_register_mux(ctx, atlas_mux_clks,
+                                ARRAY_SIZE(atlas_mux_clks));
+       samsung_clk_register_div(ctx, atlas_div_clks,
+                                ARRAY_SIZE(atlas_div_clks));
+       samsung_clk_register_gate(ctx, atlas_gate_clks,
+                                 ARRAY_SIZE(atlas_gate_clks));
+
+       exynos_register_cpu_clock(ctx, CLK_SCLK_ATLAS, "atlasclk",
+               mout_atlas_p[0], mout_atlas_p[1], 0x200,
+               exynos5433_atlasclk_d, ARRAY_SIZE(exynos5433_atlasclk_d),
+               CLK_CPU_HAS_E5433_REGS_LAYOUT);
+
+       samsung_clk_sleep_init(reg_base, atlas_clk_regs,
+                              ARRAY_SIZE(atlas_clk_regs));
+
+       samsung_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas",
                exynos5433_cmu_atlas_init);
@@ -3853,7 +3944,7 @@ CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas",
 #define ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER1          0x0b0c
 #define ENABLE_IP_MSCL_SECURE_SMMU_JPEG                        0x0b10
 
-static unsigned long mscl_clk_regs[] __initdata = {
+static const unsigned long mscl_clk_regs[] __initconst = {
        MUX_SEL_MSCL0,
        MUX_SEL_MSCL1,
        MUX_ENABLE_MSCL0,
@@ -3881,7 +3972,7 @@ PNAME(mout_aclk_mscl_400_user_p)  = { "oscclk", "aclk_mscl_400", };
 PNAME(mout_sclk_jpeg_p)                        = { "mout_sclk_jpeg_user",
                                        "mout_aclk_mscl_400_user", };
 
-static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mscl_mux_clks[] __initconst = {
        /* MUX_SEL_MSCL0 */
        MUX(CLK_MOUT_SCLK_JPEG_USER, "mout_sclk_jpeg_user",
                        mout_sclk_jpeg_user_p, MUX_SEL_MSCL0, 4, 1),
@@ -3893,13 +3984,13 @@ static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
                        MUX_SEL_MSCL1, 0, 1),
 };
 
-static struct samsung_div_clock mscl_div_clks[] __initdata = {
+static const struct samsung_div_clock mscl_div_clks[] __initconst = {
        /* DIV_MSCL */
        DIV(CLK_DIV_PCLK_MSCL, "div_pclk_mscl", "mout_aclk_mscl_400_user",
                        DIV_MSCL, 0, 3),
 };
 
-static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mscl_gate_clks[] __initconst = {
        /* ENABLE_ACLK_MSCL */
        GATE(CLK_ACLK_BTS_JPEG, "aclk_bts_jpeg", "mout_aclk_mscl_400_user",
                        ENABLE_ACLK_MSCL, 9, 0, 0),
@@ -3977,7 +4068,7 @@ static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info mscl_cmu_info __initdata = {
+static const struct samsung_cmu_info mscl_cmu_info __initconst = {
        .mux_clks               = mscl_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(mscl_mux_clks),
        .div_clks               = mscl_div_clks,
@@ -4012,7 +4103,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl",
 #define ENABLE_IP_MFC1                         0x0b04
 #define ENABLE_IP_MFC_SECURE_SMMU_MFC          0x0b08
 
-static unsigned long mfc_clk_regs[] __initdata = {
+static const unsigned long mfc_clk_regs[] __initconst = {
        MUX_SEL_MFC,
        MUX_ENABLE_MFC,
        DIV_MFC,
@@ -4027,19 +4118,19 @@ static unsigned long mfc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_mfc_400_user_p)                = { "oscclk", "aclk_mfc_400", };
 
-static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
        /* MUX_SEL_MFC */
        MUX(CLK_MOUT_ACLK_MFC_400_USER, "mout_aclk_mfc_400_user",
                        mout_aclk_mfc_400_user_p, MUX_SEL_MFC, 0, 0),
 };
 
-static struct samsung_div_clock mfc_div_clks[] __initdata = {
+static const struct samsung_div_clock mfc_div_clks[] __initconst = {
        /* DIV_MFC */
        DIV(CLK_DIV_PCLK_MFC, "div_pclk_mfc", "mout_aclk_mfc_400_user",
                        DIV_MFC, 0, 2),
 };
 
-static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mfc_gate_clks[] __initconst = {
        /* ENABLE_ACLK_MFC */
        GATE(CLK_ACLK_BTS_MFC_1, "aclk_bts_mfc_1", "mout_aclk_mfc_400_user",
                        ENABLE_ACLK_MFC, 6, 0, 0),
@@ -4085,7 +4176,7 @@ static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
                        0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info mfc_cmu_info __initdata = {
+static const struct samsung_cmu_info mfc_cmu_info __initconst = {
        .mux_clks               = mfc_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(mfc_mux_clks),
        .div_clks               = mfc_div_clks,
@@ -4120,7 +4211,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc",
 #define ENABLE_IP_HEVC1                                0x0b04
 #define ENABLE_IP_HEVC_SECURE_SMMU_HEVC                0x0b08
 
-static unsigned long hevc_clk_regs[] __initdata = {
+static const unsigned long hevc_clk_regs[] __initconst = {
        MUX_SEL_HEVC,
        MUX_ENABLE_HEVC,
        DIV_HEVC,
@@ -4135,19 +4226,19 @@ static unsigned long hevc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_hevc_400_user_p)       = { "oscclk", "aclk_hevc_400", };
 
-static struct samsung_mux_clock hevc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock hevc_mux_clks[] __initconst = {
        /* MUX_SEL_HEVC */
        MUX(CLK_MOUT_ACLK_HEVC_400_USER, "mout_aclk_hevc_400_user",
                        mout_aclk_hevc_400_user_p, MUX_SEL_HEVC, 0, 0),
 };
 
-static struct samsung_div_clock hevc_div_clks[] __initdata = {
+static const struct samsung_div_clock hevc_div_clks[] __initconst = {
        /* DIV_HEVC */
        DIV(CLK_DIV_PCLK_HEVC, "div_pclk_hevc", "mout_aclk_hevc_400_user",
                        DIV_HEVC, 0, 2),
 };
 
-static struct samsung_gate_clock hevc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock hevc_gate_clks[] __initconst = {
        /* ENABLE_ACLK_HEVC */
        GATE(CLK_ACLK_BTS_HEVC_1, "aclk_bts_hevc_1", "mout_aclk_hevc_400_user",
                        ENABLE_ACLK_HEVC, 6, 0, 0),
@@ -4195,7 +4286,7 @@ static struct samsung_gate_clock hevc_gate_clks[] __initdata = {
                        0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info hevc_cmu_info __initdata = {
+static const struct samsung_cmu_info hevc_cmu_info __initconst = {
        .mux_clks               = hevc_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(hevc_mux_clks),
        .div_clks               = hevc_div_clks,
@@ -4232,7 +4323,7 @@ CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc",
 #define ENABLE_IP_ISP2                 0x0b08
 #define ENABLE_IP_ISP3                 0x0b0c
 
-static unsigned long isp_clk_regs[] __initdata = {
+static const unsigned long isp_clk_regs[] __initconst = {
        MUX_SEL_ISP,
        MUX_ENABLE_ISP,
        DIV_ISP,
@@ -4250,7 +4341,7 @@ static unsigned long isp_clk_regs[] __initdata = {
 PNAME(mout_aclk_isp_dis_400_user_p)    = { "oscclk", "aclk_isp_dis_400", };
 PNAME(mout_aclk_isp_400_user_p)                = { "oscclk", "aclk_isp_400", };
 
-static struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock isp_mux_clks[] __initconst = {
        /* MUX_SEL_ISP */
        MUX(CLK_MOUT_ACLK_ISP_DIS_400_USER, "mout_aclk_isp_dis_400_user",
                        mout_aclk_isp_dis_400_user_p, MUX_SEL_ISP, 4, 0),
@@ -4258,7 +4349,7 @@ static struct samsung_mux_clock isp_mux_clks[] __initdata = {
                        mout_aclk_isp_400_user_p, MUX_SEL_ISP, 0, 0),
 };
 
-static struct samsung_div_clock isp_div_clks[] __initdata = {
+static const struct samsung_div_clock isp_div_clks[] __initconst = {
        /* DIV_ISP */
        DIV(CLK_DIV_PCLK_ISP_DIS, "div_pclk_isp_dis",
                        "mout_aclk_isp_dis_400_user", DIV_ISP, 12, 3),
@@ -4270,7 +4361,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = {
                        "mout_aclk_isp_400_user", DIV_ISP, 0, 3),
 };
 
-static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
        /* ENABLE_ACLK_ISP0 */
        GATE(CLK_ACLK_ISP_D_GLUE, "aclk_isp_d_glue", "mout_aclk_isp_400_user",
                        ENABLE_ACLK_ISP0, 6, CLK_IGNORE_UNUSED, 0),
@@ -4448,7 +4539,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = {
                        0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info isp_cmu_info __initdata = {
+static const struct samsung_cmu_info isp_cmu_info __initconst = {
        .mux_clks               = isp_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(isp_mux_clks),
        .div_clks               = isp_div_clks,
@@ -4504,7 +4595,7 @@ CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp",
 #define ENABLE_IP_CAM02                        0X0b08
 #define ENABLE_IP_CAM03                        0X0b0C
 
-static unsigned long cam0_clk_regs[] __initdata = {
+static const unsigned long cam0_clk_regs[] __initconst = {
        MUX_SEL_CAM00,
        MUX_SEL_CAM01,
        MUX_SEL_CAM02,
@@ -4588,14 +4679,14 @@ PNAME(mout_sclk_pixelasync_lite_c_init_a_p) = {
                                        "mout_aclk_cam0_552_user",
                                        "mout_aclk_cam0_400_user", };
 
-static struct samsung_fixed_rate_clock cam0_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock cam0_fixed_clks[] __initconst = {
        FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S4_PHY, "phyclk_rxbyteclkhs0_s4_phy",
                        NULL, 0, 100000000),
        FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2A_PHY, "phyclk_rxbyteclkhs0_s2a_phy",
                        NULL, 0, 100000000),
 };
 
-static struct samsung_mux_clock cam0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock cam0_mux_clks[] __initconst = {
        /* MUX_SEL_CAM00 */
        MUX(CLK_MOUT_ACLK_CAM0_333_USER, "mout_aclk_cam0_333_user",
                        mout_aclk_cam0_333_user_p, MUX_SEL_CAM00, 8, 1),
@@ -4669,7 +4760,7 @@ static struct samsung_mux_clock cam0_mux_clks[] __initdata = {
                        MUX_SEL_CAM04, 0, 1),
 };
 
-static struct samsung_div_clock cam0_div_clks[] __initdata = {
+static const struct samsung_div_clock cam0_div_clks[] __initconst = {
        /* DIV_CAM00 */
        DIV(CLK_DIV_PCLK_CAM0_50, "div_pclk_cam0_50", "div_aclk_cam0_200",
                        DIV_CAM00, 8, 2),
@@ -4716,7 +4807,7 @@ static struct samsung_div_clock cam0_div_clks[] __initdata = {
                        "mout_sclk_pixelasync_lite_c_init_b", DIV_CAM03, 0, 3),
 };
 
-static struct samsung_gate_clock cam0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock cam0_gate_clks[] __initconst = {
        /* ENABLE_ACLK_CAM00 */
        GATE(CLK_ACLK_CSIS1, "aclk_csis1", "div_aclk_csis1", ENABLE_ACLK_CAM00,
                        6, 0, 0),
@@ -4923,7 +5014,7 @@ static struct samsung_gate_clock cam0_gate_clks[] __initdata = {
                        ENABLE_SCLK_CAM0, 0, 0, 0),
 };
 
-static struct samsung_cmu_info cam0_cmu_info __initdata = {
+static const struct samsung_cmu_info cam0_cmu_info __initconst = {
        .mux_clks               = cam0_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(cam0_mux_clks),
        .div_clks               = cam0_div_clks,
@@ -4970,7 +5061,7 @@ CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0",
 #define ENABLE_IP_CAM11                        0X0b04
 #define ENABLE_IP_CAM12                        0X0b08
 
-static unsigned long cam1_clk_regs[] __initdata = {
+static const unsigned long cam1_clk_regs[] __initconst = {
        MUX_SEL_CAM10,
        MUX_SEL_CAM11,
        MUX_SEL_CAM12,
@@ -5016,12 +5107,12 @@ PNAME(mout_aclk_lite_c_b_p)             = { "mout_aclk_lite_c_a",
 PNAME(mout_aclk_lite_c_a_p)            = { "mout_aclk_cam1_552_user",
                                            "mout_aclk_cam1_400_user", };
 
-static struct samsung_fixed_rate_clock cam1_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock cam1_fixed_clks[] __initconst = {
        FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2B, "phyclk_rxbyteclkhs0_s2b_phy", NULL,
                        0, 100000000),
 };
 
-static struct samsung_mux_clock cam1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock cam1_mux_clks[] __initconst = {
        /* MUX_SEL_CAM10 */
        MUX(CLK_MOUT_SCLK_ISP_UART_USER, "mout_sclk_isp_uart_user",
                        mout_sclk_isp_uart_user_p, MUX_SEL_CAM10, 20, 1),
@@ -5057,7 +5148,7 @@ static struct samsung_mux_clock cam1_mux_clks[] __initdata = {
                        MUX_SEL_CAM12, 0, 1),
 };
 
-static struct samsung_div_clock cam1_div_clks[] __initdata = {
+static const struct samsung_div_clock cam1_div_clks[] __initconst = {
        /* DIV_CAM10 */
        DIV(CLK_DIV_SCLK_ISP_MPWM, "div_sclk_isp_mpwm",
                        "div_pclk_cam1_83", DIV_CAM10, 16, 2),
@@ -5081,7 +5172,7 @@ static struct samsung_div_clock cam1_div_clks[] __initdata = {
                        DIV_CAM11, 0, 3),
 };
 
-static struct samsung_gate_clock cam1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock cam1_gate_clks[] __initconst = {
        /* ENABLE_ACLK_CAM10 */
        GATE(CLK_ACLK_ISP_GIC, "aclk_isp_gic", "mout_aclk_cam1_333_user",
                        ENABLE_ACLK_CAM10, 4, 0, 0),
@@ -5296,7 +5387,7 @@ static struct samsung_gate_clock cam1_gate_clks[] __initdata = {
                        ENABLE_SCLK_CAM1, 0, 0, 0),
 };
 
-static struct samsung_cmu_info cam1_cmu_info __initdata = {
+static const struct samsung_cmu_info cam1_cmu_info __initconst = {
        .mux_clks               = cam1_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(cam1_mux_clks),
        .div_clks               = cam1_div_clks,
index c57cff1e17980170cecc0cb33891241d9d214b40..a57d01b99b766bdcc570a136018179cde688d884 100644 (file)
@@ -35,7 +35,7 @@ static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initda
 };
 
 /* fixed rate clocks */
-static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = {
        FRATE(0, "ppll", NULL, 0, 1000000000),
        FRATE(0, "usb_phy0", NULL, 0, 60000000),
        FRATE(0, "usb_phy1", NULL, 0, 60000000),
@@ -44,26 +44,26 @@ static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata =
 };
 
 /* fixed factor clocks */
-static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "div250", "ppll", 1, 4, 0),
        FFACTOR(0, "div200", "ppll", 1, 5, 0),
        FFACTOR(0, "div125", "div250", 1, 2, 0),
 };
 
 /* mux clocks */
-static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
        MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
        MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p,
                        CPU_CLK_STATUS, 0, 1, "armclk"),
 };
 
 /* divider clocks */
-static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5440_div_clks[] __initconst = {
        DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
 };
 
 /* gate clocks */
-static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = {
        GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
        GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
        GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
@@ -125,8 +125,6 @@ static void __init exynos5440_clk_init(struct device_node *np)
        }
 
        ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
                ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
index ad68d463b12c66664d16487ba88e8996f5446ad2..5931a4140c3d3f264d75510c277e06401dc31944 100644 (file)
@@ -36,7 +36,7 @@
 #define ENABLE_ACLK_TOPC1      0x0804
 #define ENABLE_SCLK_TOPC1      0x0A04
 
-static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_topc_bus0_pll", 1, 2, 0),
        FFACTOR(0, "ffac_topc_bus0_pll_div4",
                "ffac_topc_bus0_pll_div2", 1, 2, 0),
@@ -69,7 +69,7 @@ PNAME(mout_topc_mfc_pll_half_p) = { "mout_topc_mfc_pll",
 PNAME(mout_topc_bus0_pll_out_p) = {"mout_topc_bus0_pll",
        "ffac_topc_bus0_pll_div2"};
 
-static unsigned long topc_clk_regs[] __initdata = {
+static const unsigned long topc_clk_regs[] __initconst = {
        CC_PLL_LOCK,
        BUS0_PLL_LOCK,
        BUS1_DPLL_LOCK,
@@ -89,7 +89,7 @@ static unsigned long topc_clk_regs[] __initdata = {
        DIV_TOPC3,
 };
 
-static struct samsung_mux_clock topc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock topc_mux_clks[] __initconst = {
        MUX(0, "mout_topc_bus0_pll", mout_topc_bus0_pll_ctrl_p,
                MUX_SEL_TOPC0, 0, 1),
        MUX(0, "mout_topc_bus1_pll", mout_topc_bus1_pll_ctrl_p,
@@ -118,7 +118,7 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = {
        MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2),
 };
 
-static struct samsung_div_clock topc_div_clks[] __initdata = {
+static const struct samsung_div_clock topc_div_clks[] __initconst = {
        DIV(DOUT_ACLK_CCORE_133, "dout_aclk_ccore_133", "mout_aclk_ccore_133",
                DIV_TOPC0, 4, 4),
 
@@ -139,14 +139,14 @@ static struct samsung_div_clock topc_div_clks[] __initdata = {
                DIV_TOPC3, 28, 4),
 };
 
-static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = {
        PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
        {},
 };
 
-static struct samsung_gate_clock topc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock topc_gate_clks[] __initconst = {
        GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133",
-               ENABLE_ACLK_TOPC0, 4, 0, 0),
+               ENABLE_ACLK_TOPC0, 4, CLK_IS_CRITICAL, 0),
 
        GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532",
                ENABLE_ACLK_TOPC1, 20, 0, 0),
@@ -174,7 +174,7 @@ static struct samsung_gate_clock topc_gate_clks[] __initdata = {
                ENABLE_SCLK_TOPC1, 0, 0, 0),
 };
 
-static struct samsung_pll_clock topc_pll_clks[] __initdata = {
+static const struct samsung_pll_clock topc_pll_clks[] __initconst = {
        PLL(pll_1451x, 0, "fout_bus0_pll", "fin_pll", BUS0_PLL_LOCK,
                BUS0_PLL_CON0, NULL),
        PLL(pll_1452x, 0, "fout_cc_pll", "fin_pll", CC_PLL_LOCK,
@@ -187,7 +187,7 @@ static struct samsung_pll_clock topc_pll_clks[] __initdata = {
                AUD_PLL_CON0, pll1460x_24mhz_tbl),
 };
 
-static struct samsung_cmu_info topc_cmu_info __initdata = {
+static const struct samsung_cmu_info topc_cmu_info __initconst = {
        .pll_clks               = topc_pll_clks,
        .nr_pll_clks            = ARRAY_SIZE(topc_pll_clks),
        .mux_clks               = topc_mux_clks,
@@ -256,7 +256,7 @@ PNAME(mout_top0_group3) = {"ioclk_audiocdclk0",
 PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll_user",
        "mout_top0_bus0_pll_half", "mout_top0_bus1_pll_half"};
 
-static unsigned long top0_clk_regs[] __initdata = {
+static const unsigned long top0_clk_regs[] __initconst = {
        MUX_SEL_TOP00,
        MUX_SEL_TOP01,
        MUX_SEL_TOP03,
@@ -275,7 +275,7 @@ static unsigned long top0_clk_regs[] __initdata = {
        ENABLE_SCLK_TOP0_PERIC3,
 };
 
-static struct samsung_mux_clock top0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top0_mux_clks[] __initconst = {
        MUX(0, "mout_top0_aud_pll_user", mout_top0_aud_pll_user_p,
                MUX_SEL_TOP00, 0, 1),
        MUX(0, "mout_top0_mfc_pll_user", mout_top0_mfc_pll_user_p,
@@ -315,7 +315,7 @@ static struct samsung_mux_clock top0_mux_clks[] __initdata = {
        MUX(0, "mout_sclk_spi4", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 20, 2),
 };
 
-static struct samsung_div_clock top0_div_clks[] __initdata = {
+static const struct samsung_div_clock top0_div_clks[] __initconst = {
        DIV(DOUT_ACLK_PERIC1, "dout_aclk_peric1_66", "mout_aclk_peric1_66",
                DIV_TOP03, 12, 6),
        DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66",
@@ -338,7 +338,7 @@ static struct samsung_div_clock top0_div_clks[] __initdata = {
        DIV(0, "dout_sclk_spi4", "mout_sclk_spi4", DIV_TOP0_PERIC3, 20, 12),
 };
 
-static struct samsung_gate_clock top0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top0_gate_clks[] __initconst = {
        GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66",
                ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_PERIC1_66, "aclk_peric1_66", "dout_aclk_peric1_66",
@@ -372,7 +372,7 @@ static struct samsung_gate_clock top0_gate_clks[] __initdata = {
                ENABLE_SCLK_TOP0_PERIC3, 20, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll_user",
                1, 2, 0),
        FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll_user",
@@ -381,7 +381,7 @@ static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
        FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll_user", 1, 2, 0),
 };
 
-static struct samsung_cmu_info top0_cmu_info __initdata = {
+static const struct samsung_cmu_info top0_cmu_info __initconst = {
        .mux_clks               = top0_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(top0_mux_clks),
        .div_clks               = top0_div_clks,
@@ -438,7 +438,7 @@ PNAME(mout_top1_group1) = {"mout_top1_bus0_pll_half",
        "mout_top1_bus1_pll_half", "mout_top1_cc_pll_half",
        "mout_top1_mfc_pll_half"};
 
-static unsigned long top1_clk_regs[] __initdata = {
+static const unsigned long top1_clk_regs[] __initconst = {
        MUX_SEL_TOP10,
        MUX_SEL_TOP11,
        MUX_SEL_TOP13,
@@ -455,7 +455,7 @@ static unsigned long top1_clk_regs[] __initdata = {
        ENABLE_SCLK_TOP1_FSYS11,
 };
 
-static struct samsung_mux_clock top1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top1_mux_clks[] __initconst = {
        MUX(0, "mout_top1_mfc_pll_user", mout_top1_mfc_pll_user_p,
                MUX_SEL_TOP10, 4, 1),
        MUX(0, "mout_top1_cc_pll_user", mout_top1_cc_pll_user_p,
@@ -494,7 +494,7 @@ static struct samsung_mux_clock top1_mux_clks[] __initdata = {
                MUX_SEL_TOP1_FSYS11, 24, 2),
 };
 
-static struct samsung_div_clock top1_div_clks[] __initdata = {
+static const struct samsung_div_clock top1_div_clks[] __initconst = {
        DIV(DOUT_ACLK_FSYS1_200, "dout_aclk_fsys1_200", "mout_aclk_fsys1_200",
                DIV_TOP13, 24, 4),
        DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200",
@@ -521,7 +521,7 @@ static struct samsung_div_clock top1_div_clks[] __initdata = {
                "mout_sclk_phy_fsys1_26m", DIV_TOP1_FSYS11, 24, 6),
 };
 
-static struct samsung_gate_clock top1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top1_gate_clks[] __initconst = {
        GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2",
                ENABLE_SCLK_TOP1_FSYS0, 16, CLK_SET_RATE_PARENT, 0),
        GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300",
@@ -539,7 +539,8 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = {
                ENABLE_SCLK_TOP1_FSYS11, 12, CLK_SET_RATE_PARENT, 0),
 
        GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200",
-               ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0),
+               ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT |
+               CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200",
                ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0),
 
@@ -548,7 +549,7 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = {
                24, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll_user",
                1, 2, 0),
        FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll_user",
@@ -557,7 +558,7 @@ static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
        FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll_user", 1, 2, 0),
 };
 
-static struct samsung_cmu_info top1_cmu_info __initdata = {
+static const struct samsung_cmu_info top1_cmu_info __initconst = {
        .mux_clks               = top1_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(top1_mux_clks),
        .div_clks               = top1_div_clks,
@@ -591,22 +592,22 @@ CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1",
  */
 PNAME(mout_aclk_ccore_133_user_p)      = { "fin_pll", "aclk_ccore_133" };
 
-static unsigned long ccore_clk_regs[] __initdata = {
+static const unsigned long ccore_clk_regs[] __initconst = {
        MUX_SEL_CCORE,
        ENABLE_PCLK_CCORE,
 };
 
-static struct samsung_mux_clock ccore_mux_clks[] __initdata = {
+static const struct samsung_mux_clock ccore_mux_clks[] __initconst = {
        MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_user_p,
                MUX_SEL_CCORE, 1, 1),
 };
 
-static struct samsung_gate_clock ccore_gate_clks[] __initdata = {
+static const struct samsung_gate_clock ccore_gate_clks[] __initconst = {
        GATE(PCLK_RTC, "pclk_rtc", "mout_aclk_ccore_133_user",
                ENABLE_PCLK_CCORE, 8, 0, 0),
 };
 
-static struct samsung_cmu_info ccore_cmu_info __initdata = {
+static const struct samsung_cmu_info ccore_cmu_info __initconst = {
        .mux_clks               = ccore_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(ccore_mux_clks),
        .gate_clks              = ccore_gate_clks,
@@ -633,20 +634,20 @@ CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore",
 PNAME(mout_aclk_peric0_66_user_p)      = { "fin_pll", "aclk_peric0_66" };
 PNAME(mout_sclk_uart0_user_p)  = { "fin_pll", "sclk_uart0" };
 
-static unsigned long peric0_clk_regs[] __initdata = {
+static const unsigned long peric0_clk_regs[] __initconst = {
        MUX_SEL_PERIC0,
        ENABLE_PCLK_PERIC0,
        ENABLE_SCLK_PERIC0,
 };
 
-static struct samsung_mux_clock peric0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peric0_mux_clks[] __initconst = {
        MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_user_p,
                MUX_SEL_PERIC0, 0, 1),
        MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_user_p,
                MUX_SEL_PERIC0, 16, 1),
 };
 
-static struct samsung_gate_clock peric0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
        GATE(PCLK_HSI2C0, "pclk_hsi2c0", "mout_aclk_peric0_66_user",
                ENABLE_PCLK_PERIC0, 8, 0, 0),
        GATE(PCLK_HSI2C1, "pclk_hsi2c1", "mout_aclk_peric0_66_user",
@@ -673,7 +674,7 @@ static struct samsung_gate_clock peric0_gate_clks[] __initdata = {
        GATE(SCLK_PWM, "sclk_pwm", "fin_pll", ENABLE_SCLK_PERIC0, 21, 0, 0),
 };
 
-static struct samsung_cmu_info peric0_cmu_info __initdata = {
+static const struct samsung_cmu_info peric0_cmu_info __initconst = {
        .mux_clks               = peric0_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(peric0_mux_clks),
        .gate_clks              = peric0_gate_clks,
@@ -709,7 +710,7 @@ PNAME(mout_sclk_spi2_user_p)                = { "fin_pll", "sclk_spi2" };
 PNAME(mout_sclk_spi3_user_p)           = { "fin_pll", "sclk_spi3" };
 PNAME(mout_sclk_spi4_user_p)           = { "fin_pll", "sclk_spi4" };
 
-static unsigned long peric1_clk_regs[] __initdata = {
+static const unsigned long peric1_clk_regs[] __initconst = {
        MUX_SEL_PERIC10,
        MUX_SEL_PERIC11,
        MUX_SEL_PERIC12,
@@ -717,7 +718,7 @@ static unsigned long peric1_clk_regs[] __initdata = {
        ENABLE_SCLK_PERIC10,
 };
 
-static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peric1_mux_clks[] __initconst = {
        MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_user_p,
                MUX_SEL_PERIC10, 0, 1),
 
@@ -739,7 +740,7 @@ static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
                MUX_SEL_PERIC11, 28, 1),
 };
 
-static struct samsung_gate_clock peric1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peric1_gate_clks[] __initconst = {
        GATE(PCLK_HSI2C2, "pclk_hsi2c2", "mout_aclk_peric1_66_user",
                ENABLE_PCLK_PERIC1, 4, 0, 0),
        GATE(PCLK_HSI2C3, "pclk_hsi2c3", "mout_aclk_peric1_66_user",
@@ -797,7 +798,7 @@ static struct samsung_gate_clock peric1_gate_clks[] __initdata = {
                ENABLE_SCLK_PERIC10, 19, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info peric1_cmu_info __initdata = {
+static const struct samsung_cmu_info peric1_cmu_info __initconst = {
        .mux_clks               = peric1_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(peric1_mux_clks),
        .gate_clks              = peric1_gate_clks,
@@ -825,7 +826,7 @@ CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1",
 /* List of parent clocks for Muxes in CMU_PERIS */
 PNAME(mout_aclk_peris_66_user_p) = { "fin_pll", "aclk_peris_66" };
 
-static unsigned long peris_clk_regs[] __initdata = {
+static const unsigned long peris_clk_regs[] __initconst = {
        MUX_SEL_PERIS,
        ENABLE_PCLK_PERIS,
        ENABLE_PCLK_PERIS_SECURE_CHIPID,
@@ -833,12 +834,12 @@ static unsigned long peris_clk_regs[] __initdata = {
        ENABLE_SCLK_PERIS_SECURE_CHIPID,
 };
 
-static struct samsung_mux_clock peris_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peris_mux_clks[] __initconst = {
        MUX(0, "mout_aclk_peris_66_user",
                mout_aclk_peris_66_user_p, MUX_SEL_PERIS, 0, 1),
 };
 
-static struct samsung_gate_clock peris_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peris_gate_clks[] __initconst = {
        GATE(PCLK_WDT, "pclk_wdt", "mout_aclk_peris_66_user",
                ENABLE_PCLK_PERIS, 6, 0, 0),
        GATE(PCLK_TMU, "pclk_tmu_apbif", "mout_aclk_peris_66_user",
@@ -852,7 +853,7 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
        GATE(SCLK_TMU, "sclk_tmu", "fin_pll", ENABLE_SCLK_PERIS, 10, 0, 0),
 };
 
-static struct samsung_cmu_info peris_cmu_info __initdata = {
+static const struct samsung_cmu_info peris_cmu_info __initconst = {
        .mux_clks               = peris_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(peris_mux_clks),
        .gate_clks              = peris_gate_clks,
@@ -893,12 +894,12 @@ PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p)      = { "fin_pll",
                                "phyclk_usbdrd300_udrd30_pipe_pclk" };
 
 /* fixed rate clocks used in the FSYS0 block */
-static struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
+static const struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initconst = {
        FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL, 0, 60000000),
        FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL, 0, 125000000),
 };
 
-static unsigned long fsys0_clk_regs[] __initdata = {
+static const unsigned long fsys0_clk_regs[] __initconst = {
        MUX_SEL_FSYS00,
        MUX_SEL_FSYS01,
        MUX_SEL_FSYS02,
@@ -909,7 +910,7 @@ static unsigned long fsys0_clk_regs[] __initdata = {
        ENABLE_SCLK_FSYS04,
 };
 
-static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys0_mux_clks[] __initconst = {
        MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_user_p,
                MUX_SEL_FSYS00, 24, 1),
 
@@ -926,7 +927,7 @@ static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
                MUX_SEL_FSYS02, 28, 1),
 };
 
-static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys0_gate_clks[] __initconst = {
        GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user",
                        ENABLE_ACLK_FSYS00, 3, 0, 0),
        GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user",
@@ -960,7 +961,7 @@ static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
                ENABLE_SCLK_FSYS04, 28, 0, 0),
 };
 
-static struct samsung_cmu_info fsys0_cmu_info __initdata = {
+static const struct samsung_cmu_info fsys0_cmu_info __initconst = {
        .fixed_clks             = fixed_rate_clks_fsys0,
        .nr_fixed_clks          = ARRAY_SIZE(fixed_rate_clks_fsys0),
        .mux_clks               = fsys0_mux_clks,
@@ -1005,7 +1006,7 @@ PNAME(mout_phyclk_ufs20_rx0_user_p) = { "fin_pll", "phyclk_ufs20_rx0_symbol" };
 PNAME(mout_phyclk_ufs20_rx1_user_p) = { "fin_pll", "phyclk_ufs20_rx1_symbol" };
 
 /* fixed rate clocks used in the FSYS1 block */
-static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = {
+static const struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initconst = {
        FRATE(PHYCLK_UFS20_TX0_SYMBOL, "phyclk_ufs20_tx0_symbol", NULL,
                        0, 300000000),
        FRATE(PHYCLK_UFS20_RX0_SYMBOL, "phyclk_ufs20_rx0_symbol", NULL,
@@ -1014,7 +1015,7 @@ static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = {
                        0, 300000000),
 };
 
-static unsigned long fsys1_clk_regs[] __initdata = {
+static const unsigned long fsys1_clk_regs[] __initconst = {
        MUX_SEL_FSYS10,
        MUX_SEL_FSYS11,
        MUX_SEL_FSYS12,
@@ -1026,7 +1027,7 @@ static unsigned long fsys1_clk_regs[] __initdata = {
        ENABLE_SCLK_FSYS13,
 };
 
-static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys1_mux_clks[] __initconst = {
        MUX(MOUT_FSYS1_PHYCLK_SEL1, "mout_fsys1_phyclk_sel1",
                mout_fsys1_group_p, MUX_SEL_FSYS10, 16, 2),
        MUX(0, "mout_fsys1_phyclk_sel0", mout_fsys1_group_p,
@@ -1049,12 +1050,12 @@ static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
                mout_phyclk_ufs20_tx0_user_p, MUX_SEL_FSYS12, 28, 1),
 };
 
-static struct samsung_div_clock fsys1_div_clks[] __initdata = {
+static const struct samsung_div_clock fsys1_div_clks[] __initconst = {
        DIV(DOUT_PCLK_FSYS1, "dout_pclk_fsys1", "mout_aclk_fsys1_200_user",
                DIV_FSYS1, 0, 2),
 };
 
-static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys1_gate_clks[] __initconst = {
        GATE(SCLK_UFSUNIPRO20_USER, "sclk_ufsunipro20_user",
                "mout_sclk_ufsunipro20_user",
                ENABLE_SCLK_FSYS11, 20, 0, 0),
@@ -1089,7 +1090,7 @@ static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
                ENABLE_SCLK_FSYS13, 24, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info fsys1_cmu_info __initdata = {
+static const struct samsung_cmu_info fsys1_cmu_info __initconst = {
        .fixed_clks             = fixed_rate_clks_fsys1,
        .nr_fixed_clks          = ARRAY_SIZE(fixed_rate_clks_fsys1),
        .mux_clks               = fsys1_mux_clks,
@@ -1119,22 +1120,22 @@ CLK_OF_DECLARE(exynos7_clk_fsys1, "samsung,exynos7-clock-fsys1",
 /* List of parent clocks for Muxes in CMU_MSCL */
 PNAME(mout_aclk_mscl_532_user_p)       = { "fin_pll", "aclk_mscl_532" };
 
-static unsigned long mscl_clk_regs[] __initdata = {
+static const unsigned long mscl_clk_regs[] __initconst = {
        MUX_SEL_MSCL,
        DIV_MSCL,
        ENABLE_ACLK_MSCL,
        ENABLE_PCLK_MSCL,
 };
 
-static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mscl_mux_clks[] __initconst = {
        MUX(USERMUX_ACLK_MSCL_532, "usermux_aclk_mscl_532",
                mout_aclk_mscl_532_user_p, MUX_SEL_MSCL, 0, 1),
 };
-static struct samsung_div_clock mscl_div_clks[] __initdata = {
+static const struct samsung_div_clock mscl_div_clks[] __initconst = {
        DIV(DOUT_PCLK_MSCL, "dout_pclk_mscl", "usermux_aclk_mscl_532",
                        DIV_MSCL, 0, 3),
 };
-static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mscl_gate_clks[] __initconst = {
 
        GATE(ACLK_MSCL_0, "aclk_mscl_0", "usermux_aclk_mscl_532",
                        ENABLE_ACLK_MSCL, 31, 0, 0),
@@ -1204,7 +1205,7 @@ static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
                        ENABLE_PCLK_MSCL, 20, 0, 0),
 };
 
-static struct samsung_cmu_info mscl_cmu_info __initdata = {
+static const struct samsung_cmu_info mscl_cmu_info __initconst = {
        .mux_clks               = mscl_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(mscl_mux_clks),
        .div_clks               = mscl_div_clks,
@@ -1238,7 +1239,7 @@ CLK_OF_DECLARE(exynos7_clk_mscl, "samsung,exynos7-clock-mscl",
 PNAME(mout_aud_pll_user_p) = { "fin_pll", "fout_aud_pll" };
 PNAME(mout_aud_group_p) = { "dout_aud_cdclk", "ioclk_audiocdclk0" };
 
-static unsigned long aud_clk_regs[] __initdata = {
+static const unsigned long aud_clk_regs[] __initconst = {
        MUX_SEL_AUD,
        DIV_AUD0,
        DIV_AUD1,
@@ -1247,13 +1248,13 @@ static unsigned long aud_clk_regs[] __initdata = {
        ENABLE_SCLK_AUD,
 };
 
-static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static const struct samsung_mux_clock aud_mux_clks[] __initconst = {
        MUX(0, "mout_sclk_i2s", mout_aud_group_p, MUX_SEL_AUD, 12, 1),
        MUX(0, "mout_sclk_pcm", mout_aud_group_p, MUX_SEL_AUD, 16, 1),
        MUX(0, "mout_aud_pll_user", mout_aud_pll_user_p, MUX_SEL_AUD, 20, 1),
 };
 
-static struct samsung_div_clock aud_div_clks[] __initdata = {
+static const struct samsung_div_clock aud_div_clks[] __initconst = {
        DIV(0, "dout_aud_ca5", "mout_aud_pll_user", DIV_AUD0, 0, 4),
        DIV(0, "dout_aclk_aud", "dout_aud_ca5", DIV_AUD0, 4, 4),
        DIV(0, "dout_aud_pclk_dbg", "dout_aud_ca5", DIV_AUD0, 8, 4),
@@ -1265,7 +1266,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = {
        DIV(0, "dout_aud_cdclk", "mout_aud_pll_user", DIV_AUD1, 24, 4),
 };
 
-static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
        GATE(SCLK_PCM, "sclk_pcm", "dout_sclk_pcm",
                        ENABLE_SCLK_AUD, 27, CLK_SET_RATE_PARENT, 0),
        GATE(SCLK_I2S, "sclk_i2s", "dout_sclk_i2s",
@@ -1293,7 +1294,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
        GATE(ACLK_ADMA, "aclk_dmac", "dout_aclk_aud", ENABLE_ACLK_AUD, 31, 0, 0),
 };
 
-static struct samsung_cmu_info aud_cmu_info __initdata = {
+static const struct samsung_cmu_info aud_cmu_info __initconst = {
        .mux_clks               = aud_mux_clks,
        .nr_mux_clks            = ARRAY_SIZE(aud_mux_clks),
        .div_clks               = aud_div_clks,
index b7dd396100d8118381caebffade2ff7e3acf831d..48139bd510f1078ccc80873ddaa1369a46b024a0 100644 (file)
@@ -79,7 +79,7 @@ static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
        u32 pll_con, mdiv, pdiv, sdiv;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
        pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
        sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
@@ -112,7 +112,7 @@ static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
        u32 pll_con, mdiv, pdiv, sdiv;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
        pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
        sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
@@ -149,7 +149,7 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
        u32 mdiv, pdiv, sdiv, pll_con;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
        pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
        sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
@@ -186,19 +186,19 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       tmp = __raw_readl(pll->con_reg);
+       tmp = readl_relaxed(pll->con_reg);
 
        if (!(samsung_pll35xx_mp_change(rate, tmp))) {
                /* If only s change, change just s value only*/
                tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
                tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
-               __raw_writel(tmp, pll->con_reg);
+               writel_relaxed(tmp, pll->con_reg);
 
                return 0;
        }
 
        /* Set PLL lock time. */
-       __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+       writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
                        pll->lock_reg);
 
        /* Change PLL PMS values */
@@ -208,12 +208,12 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
        tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
                        (rate->pdiv << PLL35XX_PDIV_SHIFT) |
                        (rate->sdiv << PLL35XX_SDIV_SHIFT);
-       __raw_writel(tmp, pll->con_reg);
+       writel_relaxed(tmp, pll->con_reg);
 
        /* wait_lock_time */
        do {
                cpu_relax();
-               tmp = __raw_readl(pll->con_reg);
+               tmp = readl_relaxed(pll->con_reg);
        } while (!(tmp & (PLL35XX_LOCK_STAT_MASK
                                << PLL35XX_LOCK_STAT_SHIFT)));
        return 0;
@@ -253,8 +253,8 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
        s16 kdiv;
        u64 fvco = parent_rate;
 
-       pll_con0 = __raw_readl(pll->con_reg);
-       pll_con1 = __raw_readl(pll->con_reg + 4);
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con1 = readl_relaxed(pll->con_reg + 4);
        mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
        pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
        sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
@@ -294,20 +294,20 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       pll_con0 = __raw_readl(pll->con_reg);
-       pll_con1 = __raw_readl(pll->con_reg + 4);
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con1 = readl_relaxed(pll->con_reg + 4);
 
        if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
                /* If only s change, change just s value only*/
                pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
                pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
-               __raw_writel(pll_con0, pll->con_reg);
+               writel_relaxed(pll_con0, pll->con_reg);
 
                return 0;
        }
 
        /* Set PLL lock time. */
-       __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+       writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
 
         /* Change PLL PMS values */
        pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
@@ -316,16 +316,16 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
        pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
                        (rate->pdiv << PLL36XX_PDIV_SHIFT) |
                        (rate->sdiv << PLL36XX_SDIV_SHIFT);
-       __raw_writel(pll_con0, pll->con_reg);
+       writel_relaxed(pll_con0, pll->con_reg);
 
        pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
        pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
-       __raw_writel(pll_con1, pll->con_reg + 4);
+       writel_relaxed(pll_con1, pll->con_reg + 4);
 
        /* wait_lock_time */
        do {
                cpu_relax();
-               tmp = __raw_readl(pll->con_reg);
+               tmp = readl_relaxed(pll->con_reg);
        } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
 
        return 0;
@@ -366,7 +366,7 @@ static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
        u32 mdiv, pdiv, sdiv, pll_con;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
        pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
        sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
@@ -409,14 +409,14 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       con0 = __raw_readl(pll->con_reg);
-       con1 = __raw_readl(pll->con_reg + 0x4);
+       con0 = readl_relaxed(pll->con_reg);
+       con1 = readl_relaxed(pll->con_reg + 0x4);
 
        if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
                /* If only s change, change just s value only*/
                con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
                con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
-               __raw_writel(con0, pll->con_reg);
+               writel_relaxed(con0, pll->con_reg);
 
                return 0;
        }
@@ -430,29 +430,29 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
                        (rate->sdiv << PLL45XX_SDIV_SHIFT);
 
        /* Set PLL AFC value. */
-       con1 = __raw_readl(pll->con_reg + 0x4);
+       con1 = readl_relaxed(pll->con_reg + 0x4);
        con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
        con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
 
        /* Set PLL lock time. */
        switch (pll->type) {
        case pll_4502:
-               __raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
+               writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
                break;
        case pll_4508:
-               __raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
+               writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
                break;
        default:
                break;
        }
 
        /* Set new configuration. */
-       __raw_writel(con1, pll->con_reg + 0x4);
-       __raw_writel(con0, pll->con_reg);
+       writel_relaxed(con1, pll->con_reg + 0x4);
+       writel_relaxed(con0, pll->con_reg);
 
        /* Wait for locking. */
        start = ktime_get();
-       while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) {
+       while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) {
                ktime_t delta = ktime_sub(ktime_get(), start);
 
                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
@@ -513,8 +513,8 @@ static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
        u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
        u64 fvco = parent_rate;
 
-       pll_con0 = __raw_readl(pll->con_reg);
-       pll_con1 = __raw_readl(pll->con_reg + 4);
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con1 = readl_relaxed(pll->con_reg + 4);
        mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
                                PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
        pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
@@ -560,14 +560,14 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       con0 = __raw_readl(pll->con_reg);
-       con1 = __raw_readl(pll->con_reg + 0x4);
+       con0 = readl_relaxed(pll->con_reg);
+       con1 = readl_relaxed(pll->con_reg + 0x4);
 
        if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
                /* If only s change, change just s value only*/
                con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
                con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
-               __raw_writel(con0, pll->con_reg);
+               writel_relaxed(con0, pll->con_reg);
 
                return 0;
        }
@@ -596,7 +596,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
                        (rate->sdiv << PLL46XX_SDIV_SHIFT);
 
        /* Set PLL K, MFR and MRR values. */
-       con1 = __raw_readl(pll->con_reg + 0x4);
+       con1 = readl_relaxed(pll->con_reg + 0x4);
        con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
                        (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
                        (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
@@ -605,13 +605,13 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
                        (rate->mrr << PLL46XX_MRR_SHIFT);
 
        /* Write configuration to PLL */
-       __raw_writel(lock, pll->lock_reg);
-       __raw_writel(con0, pll->con_reg);
-       __raw_writel(con1, pll->con_reg + 0x4);
+       writel_relaxed(lock, pll->lock_reg);
+       writel_relaxed(con0, pll->con_reg);
+       writel_relaxed(con1, pll->con_reg + 0x4);
 
        /* Wait for locking. */
        start = ktime_get();
-       while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) {
+       while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) {
                ktime_t delta = ktime_sub(ktime_get(), start);
 
                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
@@ -656,7 +656,7 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
        u32 mdiv, pdiv, sdiv, pll_con;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        if (pll->type == pll_6552_s3c2416) {
                mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
                pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
@@ -696,8 +696,8 @@ static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
        u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
        u64 fvco = parent_rate;
 
-       pll_con0 = __raw_readl(pll->con_reg);
-       pll_con1 = __raw_readl(pll->con_reg + 0x4);
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con1 = readl_relaxed(pll->con_reg + 0x4);
        mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
        pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
        sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
@@ -734,7 +734,7 @@ static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
        u32 pll_con, mdiv, pdiv, sdiv;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
        pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
        sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
@@ -752,7 +752,7 @@ static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
        u32 pll_con, mdiv, pdiv, sdiv;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
        pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
        sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
@@ -778,7 +778,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       tmp = __raw_readl(pll->con_reg);
+       tmp = readl_relaxed(pll->con_reg);
 
        /* Change PLL PMS values */
        tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
@@ -787,7 +787,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
                        (rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
                        (rate->sdiv << PLLS3C2410_SDIV_SHIFT);
-       __raw_writel(tmp, pll->con_reg);
+       writel_relaxed(tmp, pll->con_reg);
 
        /* Time to settle according to the manual */
        udelay(300);
@@ -798,7 +798,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
 {
        struct samsung_clk_pll *pll = to_clk_pll(hw);
-       u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
+       u32 pll_en = readl_relaxed(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
        u32 pll_en_orig = pll_en;
 
        if (enable)
@@ -806,7 +806,7 @@ static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
        else
                pll_en |= BIT(bit);
 
-       __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
+       writel_relaxed(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
 
        /* if we started the UPLL, then allow to settle */
        if (enable && (pll_en_orig & BIT(bit)))
@@ -905,7 +905,7 @@ static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
        u32 r, p, m, s, pll_stat;
        u64 fvco = parent_rate;
 
-       pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
+       pll_stat = readl_relaxed(pll->reg_base + pll->offset * 3);
        r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
        if (!r)
                return 0;
@@ -983,7 +983,7 @@ static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
        u32 mdiv, pdiv, sdiv, pll_con;
        u64 fvco = parent_rate;
 
-       pll_con = __raw_readl(pll->con_reg);
+       pll_con = readl_relaxed(pll->con_reg);
        mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
        pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
        sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK;
@@ -1019,19 +1019,19 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       tmp = __raw_readl(pll->con_reg);
+       tmp = readl_relaxed(pll->con_reg);
 
        if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) {
                /* If only s change, change just s value only*/
                tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT);
                tmp |= rate->sdiv << PLL2550XX_S_SHIFT;
-               __raw_writel(tmp, pll->con_reg);
+               writel_relaxed(tmp, pll->con_reg);
 
                return 0;
        }
 
        /* Set PLL lock time. */
-       __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
+       writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
 
        /* Change PLL PMS values */
        tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) |
@@ -1040,12 +1040,12 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
        tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) |
                        (rate->pdiv << PLL2550XX_P_SHIFT) |
                        (rate->sdiv << PLL2550XX_S_SHIFT);
-       __raw_writel(tmp, pll->con_reg);
+       writel_relaxed(tmp, pll->con_reg);
 
        /* wait_lock_time */
        do {
                cpu_relax();
-               tmp = __raw_readl(pll->con_reg);
+               tmp = readl_relaxed(pll->con_reg);
        } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
                        << PLL2550XX_LOCK_STAT_SHIFT)));
 
@@ -1089,8 +1089,8 @@ static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
        s16 kdiv;
        u64 fvco = parent_rate;
 
-       pll_con0 = __raw_readl(pll->con_reg);
-       pll_con2 = __raw_readl(pll->con_reg + 8);
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con2 = readl_relaxed(pll->con_reg + 8);
        mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK;
        pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK;
        sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK;
@@ -1117,8 +1117,8 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
                return -EINVAL;
        }
 
-       pll_con0 = __raw_readl(pll->con_reg);
-       pll_con2 = __raw_readl(pll->con_reg + 8);
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con2 = readl_relaxed(pll->con_reg + 8);
 
         /* Change PLL PMS values */
        pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT |
@@ -1135,13 +1135,13 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
                        << PLL2650XX_KDIV_SHIFT;
 
        /* Set PLL lock time. */
-       __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
+       writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
 
-       __raw_writel(pll_con0, pll->con_reg);
-       __raw_writel(pll_con2, pll->con_reg + 8);
+       writel_relaxed(pll_con0, pll->con_reg);
+       writel_relaxed(pll_con2, pll->con_reg + 8);
 
        do {
-               tmp = __raw_readl(pll->con_reg);
+               tmp = readl_relaxed(pll->con_reg);
        } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
 
        return 0;
index ec6fb14d951c728044e477265639fe18881da413..ae9a595c72d0e3489036b93aba3acae2c934a9e9 100644 (file)
@@ -428,8 +428,9 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
 
 static struct platform_driver s3c24xx_dclk_driver = {
        .driver = {
-               .name           = "s3c24xx-dclk",
-               .pm             = &s3c24xx_dclk_pm_ops,
+               .name                   = "s3c24xx-dclk",
+               .pm                     = &s3c24xx_dclk_pm_ops,
+               .suppress_bind_attrs    = true,
        },
        .probe = s3c24xx_dclk_probe,
        .remove = s3c24xx_dclk_remove,
index d7b011c1fcf8859bbddd514a361d8d39e00f11ae..d7a1e772d95a97d67c8b6da5104af27358a7145a 100644 (file)
@@ -374,8 +374,6 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
        }
 
        ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        /* Register external clocks only in non-dt cases */
        if (!np)
index effe3736ec6b69bfa753e55d54e6615fde1caa98..ec873ee15d377b6f720e319cb6327744b4489d99 100644 (file)
@@ -265,8 +265,6 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
        }
 
        ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        /* Register external clocks only in non-dt cases */
        if (!np)
index 37562783b25e1733a36ac86b94ac31892ab002b9..5e24a17e10e676e2e76ae5efec06af0d9eb0e847 100644 (file)
@@ -400,8 +400,6 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
        }
 
        ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        /* Register external clocks only in non-dt cases */
        if (!np)
index 60aa775bd3745de6e6ce514b16e2c57be9a321cf..a48bd5f173301e9c0d1c21a94f0e27e52eeb6a9d 100644 (file)
@@ -471,8 +471,6 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
        }
 
        ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        /* Register external clocks. */
        if (!np)
index eefb84b2256650294618b168a23b60d4ca170f74..c66ed2d1450e5c52c894eacf72b3d7794b6fd093 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 
 #include <dt-bindings/clock/s5pv210-audss.h>
@@ -194,20 +194,6 @@ unregister:
        return ret;
 }
 
-static int s5pv210_audss_clk_remove(struct platform_device *pdev)
-{
-       int i;
-
-       of_clk_del_provider(pdev->dev.of_node);
-
-       for (i = 0; i < clk_data.clk_num; i++) {
-               if (!IS_ERR(clk_table[i]))
-                       clk_unregister(clk_table[i]);
-       }
-
-       return 0;
-}
-
 static const struct of_device_id s5pv210_audss_clk_of_match[] = {
        { .compatible = "samsung,s5pv210-audss-clock", },
        {},
@@ -216,10 +202,10 @@ static const struct of_device_id s5pv210_audss_clk_of_match[] = {
 static struct platform_driver s5pv210_audss_clk_driver = {
        .driver = {
                .name = "s5pv210-audss-clk",
+               .suppress_bind_attrs = true,
                .of_match_table = s5pv210_audss_clk_of_match,
        },
        .probe = s5pv210_audss_clk_probe,
-       .remove = s5pv210_audss_clk_remove,
 };
 
 static int __init s5pv210_audss_clk_init(void)
@@ -227,14 +213,3 @@ static int __init s5pv210_audss_clk_init(void)
        return platform_driver_register(&s5pv210_audss_clk_driver);
 }
 core_initcall(s5pv210_audss_clk_init);
-
-static void __exit s5pv210_audss_clk_exit(void)
-{
-       platform_driver_unregister(&s5pv210_audss_clk_driver);
-}
-module_exit(s5pv210_audss_clk_exit);
-
-MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
-MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s5pv210-audss-clk");
index 52302262045d4cbd9bca00cda8d79d597f8cd14e..fd2725710a6fa968437e45a108555a7eb506dbc2 100644 (file)
@@ -784,8 +784,6 @@ static void __init __s5pv210_clk_init(struct device_node *np,
        struct samsung_clk_provider *ctx;
 
        ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-       if (!ctx)
-               panic("%s: unable to allocate context.\n", __func__);
 
        samsung_clk_register_mux(ctx, early_mux_clks,
                                        ARRAY_SIZE(early_mux_clks));
index f38a6c49f7449cc1293910ec5c9eacf8df8544aa..b7d87d6db9dc4de9cc186bdd2717bc5edb958245 100644 (file)
@@ -346,9 +346,9 @@ static struct syscore_ops samsung_clk_syscore_ops = {
        .resume = samsung_clk_resume,
 };
 
-static void samsung_clk_sleep_init(void __iomem *reg_base,
-               const unsigned long *rdump,
-               unsigned long nr_rdump)
+void samsung_clk_sleep_init(void __iomem *reg_base,
+                       const unsigned long *rdump,
+                       unsigned long nr_rdump)
 {
        struct samsung_clock_reg_cache *reg_cache;
 
@@ -370,9 +370,9 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
 }
 
 #else
-static void samsung_clk_sleep_init(void __iomem *reg_base,
-               const unsigned long *rdump,
-               unsigned long nr_rdump) {}
+void samsung_clk_sleep_init(void __iomem *reg_base,
+                       const unsigned long *rdump,
+                       unsigned long nr_rdump) {}
 #endif
 
 /*
@@ -381,7 +381,7 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
  */
 struct samsung_clk_provider * __init samsung_cmu_register_one(
                        struct device_node *np,
-                       struct samsung_cmu_info *cmu)
+                       const struct samsung_cmu_info *cmu)
 {
        void __iomem *reg_base;
        struct samsung_clk_provider *ctx;
index aa872d2c51052a7f81181aabd57b249c55ea0afc..da3bdebabf1e32674c6875fb059461e09fef56ae 100644 (file)
@@ -261,7 +261,7 @@ struct samsung_gate_clock {
 #define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a)      \
        __GATE(_id, dname, cname, pname, o, b, f, gf, a)
 
-#define PNAME(x) static const char *x[] __initdata
+#define PNAME(x) static const char * const x[] __initconst
 
 /**
  * struct samsung_clk_reg_dump: register dump of clock controller registers.
@@ -330,28 +330,28 @@ struct samsung_clock_reg_cache {
 
 struct samsung_cmu_info {
        /* list of pll clocks and respective count */
-       struct samsung_pll_clock *pll_clks;
+       const struct samsung_pll_clock *pll_clks;
        unsigned int nr_pll_clks;
        /* list of mux clocks and respective count */
-       struct samsung_mux_clock *mux_clks;
+       const struct samsung_mux_clock *mux_clks;
        unsigned int nr_mux_clks;
        /* list of div clocks and respective count */
-       struct samsung_div_clock *div_clks;
+       const struct samsung_div_clock *div_clks;
        unsigned int nr_div_clks;
        /* list of gate clocks and respective count */
-       struct samsung_gate_clock *gate_clks;
+       const struct samsung_gate_clock *gate_clks;
        unsigned int nr_gate_clks;
        /* list of fixed clocks and respective count */
-       struct samsung_fixed_rate_clock *fixed_clks;
+       const struct samsung_fixed_rate_clock *fixed_clks;
        unsigned int nr_fixed_clks;
        /* list of fixed factor clocks and respective count */
-       struct samsung_fixed_factor_clock *fixed_factor_clks;
+       const struct samsung_fixed_factor_clock *fixed_factor_clks;
        unsigned int nr_fixed_factor_clks;
        /* total number of clocks with IDs assigned*/
        unsigned int nr_clk_ids;
 
        /* list and number of clocks registers */
-       unsigned long *clk_regs;
+       const unsigned long *clk_regs;
        unsigned int nr_clk_regs;
 };
 
@@ -395,10 +395,14 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 
 extern struct samsung_clk_provider __init *samsung_cmu_register_one(
                        struct device_node *,
-                       struct samsung_cmu_info *);
+                       const struct samsung_cmu_info *);
 
 extern unsigned long _get_rate(const char *clk_name);
 
+extern void samsung_clk_sleep_init(void __iomem *reg_base,
+                       const unsigned long *rdump,
+                       unsigned long nr_rdump);
+
 extern void samsung_clk_save(void __iomem *base,
                        struct samsung_clk_reg_dump *rd,
                        unsigned int num_regs);
index 627267c7ec5c0be3a09ca12fca851e039e0baf06..546bd79c8e3a68eb86ccd7b51f50bf5225b15f62 100644 (file)
@@ -267,7 +267,6 @@ static void __init st_of_flexgen_setup(struct device_node *np)
        const char **parents;
        int num_parents, i;
        spinlock_t *rlock = NULL;
-       unsigned long flex_flags = 0;
        int ret;
 
        pnode = of_get_parent(np);
@@ -308,12 +307,15 @@ static void __init st_of_flexgen_setup(struct device_node *np)
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
                const char *clk_name;
+               unsigned long flex_flags = 0;
 
                if (of_property_read_string_index(np, "clock-output-names",
                                                  i, &clk_name)) {
                        break;
                }
 
+               of_clk_detect_critical(np, i, &flex_flags);
+
                /*
                 * If we read an empty clock name then the output is unused
                 */
index dec4eaaecc0006c24aadac0a969e050505bb141c..09afeb85109c7fc41bd14661891e25488849b616 100644 (file)
@@ -1027,7 +1027,7 @@ static const struct clk_ops st_quadfs_ops = {
 static struct clk * __init st_clk_register_quadfs_fsynth(
                const char *name, const char *parent_name,
                struct clkgen_quadfs_data *quadfs, void __iomem *reg, u32 chan,
-               spinlock_t *lock)
+               unsigned long flags, spinlock_t *lock)
 {
        struct st_clk_quadfs_fsynth *fs;
        struct clk *clk;
@@ -1045,7 +1045,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth(
 
        init.name = name;
        init.ops = &st_quadfs_ops;
-       init.flags = CLK_GET_RATE_NOCACHE | CLK_IS_BASIC;
+       init.flags = flags | CLK_GET_RATE_NOCACHE | CLK_IS_BASIC;
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
@@ -1115,6 +1115,7 @@ static void __init st_of_create_quadfs_fsynths(
        for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) {
                struct clk *clk;
                const char *clk_name;
+               unsigned long flags = 0;
 
                if (of_property_read_string_index(np, "clock-output-names",
                                                  fschan, &clk_name)) {
@@ -1127,8 +1128,11 @@ static void __init st_of_create_quadfs_fsynths(
                if (*clk_name == '\0')
                        continue;
 
+               of_clk_detect_critical(np, fschan, &flags);
+
                clk = st_clk_register_quadfs_fsynth(clk_name, pll_name,
-                               quadfs, reg, fschan, lock);
+                                                   quadfs, reg, fschan,
+                                                   flags, lock);
 
                /*
                 * If there was an error registering this clock output, clean
index 38f6f3a9098e0279789f370b1a518414cd14eb81..0b5990e82e0d26b96e3b21d22844aa693b385a72 100644 (file)
@@ -840,7 +840,7 @@ static const struct clk_ops stm_pll4600c28_ops = {
 
 static struct clk * __init clkgen_pll_register(const char *parent_name,
                                struct clkgen_pll_data  *pll_data,
-                               void __iomem *reg,
+                               void __iomem *reg, unsigned long pll_flags,
                                const char *clk_name, spinlock_t *lock)
 {
        struct clkgen_pll *pll;
@@ -854,7 +854,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name,
        init.name = clk_name;
        init.ops = pll_data->ops;
 
-       init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE;
+       init.flags = pll_flags | CLK_IS_BASIC | CLK_GET_RATE_NOCACHE;
        init.parent_names = &parent_name;
        init.num_parents  = 1;
 
@@ -948,7 +948,7 @@ static void __init clkgena_c65_pll_setup(struct device_node *np)
         */
        clk_data->clks[0] = clkgen_pll_register(parent_name,
                        (struct clkgen_pll_data *) &st_pll1600c65_ax,
-                       reg + CLKGENAx_PLL0_OFFSET, clk_name, NULL);
+                       reg + CLKGENAx_PLL0_OFFSET, 0, clk_name, NULL);
 
        if (IS_ERR(clk_data->clks[0]))
                goto err;
@@ -977,7 +977,7 @@ static void __init clkgena_c65_pll_setup(struct device_node *np)
         */
        clk_data->clks[2] = clkgen_pll_register(parent_name,
                        (struct clkgen_pll_data *) &st_pll800c65_ax,
-                       reg + CLKGENAx_PLL1_OFFSET, clk_name, NULL);
+                       reg + CLKGENAx_PLL1_OFFSET, 0, clk_name, NULL);
 
        if (IS_ERR(clk_data->clks[2]))
                goto err;
@@ -995,7 +995,7 @@ CLK_OF_DECLARE(clkgena_c65_plls,
 static struct clk * __init clkgen_odf_register(const char *parent_name,
                                               void __iomem *reg,
                                               struct clkgen_pll_data *pll_data,
-                                              int odf,
+                                              unsigned long pll_flags, int odf,
                                               spinlock_t *odf_lock,
                                               const char *odf_name)
 {
@@ -1004,7 +1004,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
        struct clk_gate *gate;
        struct clk_divider *div;
 
-       flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT;
+       flags = pll_flags | CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT;
 
        gate = kzalloc(sizeof(*gate), GFP_KERNEL);
        if (!gate)
@@ -1099,6 +1099,7 @@ static void __init clkgen_c32_pll_setup(struct device_node *np)
        int num_odfs, odf;
        struct clk_onecell_data *clk_data;
        struct clkgen_pll_data  *data;
+       unsigned long pll_flags = 0;
 
        match = of_match_node(c32_pll_of_match, np);
        if (!match) {
@@ -1116,8 +1117,10 @@ static void __init clkgen_c32_pll_setup(struct device_node *np)
        if (!pll_base)
                return;
 
-       clk = clkgen_pll_register(parent_name, data, pll_base, np->name,
-                                 data->lock);
+       of_clk_detect_critical(np, 0, &pll_flags);
+
+       clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags,
+                                 np->name, data->lock);
        if (IS_ERR(clk))
                return;
 
@@ -1139,12 +1142,15 @@ static void __init clkgen_c32_pll_setup(struct device_node *np)
        for (odf = 0; odf < num_odfs; odf++) {
                struct clk *clk;
                const char *clk_name;
+               unsigned long odf_flags = 0;
 
                if (of_property_read_string_index(np, "clock-output-names",
                                                  odf, &clk_name))
                        return;
 
-               clk = clkgen_odf_register(pll_name, pll_base, data,
+               of_clk_detect_critical(np, odf, &odf_flags);
+
+               clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags,
                                odf, &clkgena_c32_odf_lock, clk_name);
                if (IS_ERR(clk))
                        goto err;
@@ -1206,7 +1212,8 @@ static void __init clkgengpu_c32_pll_setup(struct device_node *np)
        /*
         * PLL 1200MHz output
         */
-       clk = clkgen_pll_register(parent_name, data, reg, clk_name, data->lock);
+       clk = clkgen_pll_register(parent_name, data, reg,
+                                 0, clk_name, data->lock);
 
        if (!IS_ERR(clk))
                of_clk_add_provider(np, of_clk_src_simple_get, clk);
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
new file mode 100644 (file)
index 0000000..2afcbd3
--- /dev/null
@@ -0,0 +1,65 @@
+config SUNXI_CCU
+       bool "Clock support for Allwinner SoCs"
+       default ARCH_SUNXI
+
+if SUNXI_CCU
+
+# Base clock types
+
+config SUNXI_CCU_DIV
+       bool
+       select SUNXI_CCU_MUX
+
+config SUNXI_CCU_FRAC
+       bool
+
+config SUNXI_CCU_GATE
+       bool
+
+config SUNXI_CCU_MUX
+       bool
+
+config SUNXI_CCU_PHASE
+       bool
+
+# Multi-factor clocks
+
+config SUNXI_CCU_NK
+       bool
+       select SUNXI_CCU_GATE
+
+config SUNXI_CCU_NKM
+       bool
+       select RATIONAL
+       select SUNXI_CCU_GATE
+
+config SUNXI_CCU_NKMP
+       bool
+       select RATIONAL
+       select SUNXI_CCU_GATE
+
+config SUNXI_CCU_NM
+       bool
+       select RATIONAL
+       select SUNXI_CCU_FRAC
+       select SUNXI_CCU_GATE
+
+config SUNXI_CCU_MP
+       bool
+       select SUNXI_CCU_GATE
+       select SUNXI_CCU_MUX
+
+# SoC Drivers
+
+config SUN8I_H3_CCU
+       bool "Support for the Allwinner H3 CCU"
+       select SUNXI_CCU_DIV
+       select SUNXI_CCU_NK
+       select SUNXI_CCU_NKM
+       select SUNXI_CCU_NKMP
+       select SUNXI_CCU_NM
+       select SUNXI_CCU_MP
+       select SUNXI_CCU_PHASE
+       default MACH_SUN8I
+
+endif
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
new file mode 100644 (file)
index 0000000..633ce64
--- /dev/null
@@ -0,0 +1,20 @@
+# Common objects
+obj-$(CONFIG_SUNXI_CCU)                += ccu_common.o
+obj-$(CONFIG_SUNXI_CCU)                += ccu_reset.o
+
+# Base clock types
+obj-$(CONFIG_SUNXI_CCU_DIV)    += ccu_div.o
+obj-$(CONFIG_SUNXI_CCU_FRAC)   += ccu_frac.o
+obj-$(CONFIG_SUNXI_CCU_GATE)   += ccu_gate.o
+obj-$(CONFIG_SUNXI_CCU_MUX)    += ccu_mux.o
+obj-$(CONFIG_SUNXI_CCU_PHASE)  += ccu_phase.o
+
+# Multi-factor clocks
+obj-$(CONFIG_SUNXI_CCU_NK)     += ccu_nk.o
+obj-$(CONFIG_SUNXI_CCU_NKM)    += ccu_nkm.o
+obj-$(CONFIG_SUNXI_CCU_NKMP)   += ccu_nkmp.o
+obj-$(CONFIG_SUNXI_CCU_NM)     += ccu_nm.o
+obj-$(CONFIG_SUNXI_CCU_MP)     += ccu_mp.o
+
+# SoC support
+obj-$(CONFIG_SUN8I_H3_CCU)     += ccu-sun8i-h3.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
new file mode 100644 (file)
index 0000000..9af3595
--- /dev/null
@@ -0,0 +1,826 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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/clk-provider.h>
+#include <linux/of_address.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+#include "ccu_phase.h"
+
+#include "ccu-sun8i-h3.h"
+
+static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux",
+                                    "osc24M", 0x000,
+                                    8, 5,      /* N */
+                                    4, 2,      /* K */
+                                    0, 2,      /* M */
+                                    16, 2,     /* P */
+                                    BIT(31),   /* gate */
+                                    BIT(28),   /* lock */
+                                    0);
+
+/*
+ * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
+ * the base (2x, 4x and 8x), and one variable divider (the one true
+ * pll audio).
+ *
+ * We don't have any need for the variable divider for now, so we just
+ * hardcode it to match with the clock names
+ */
+#define SUN8I_H3_PLL_AUDIO_REG 0x008
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
+                                  "osc24M", 0x008,
+                                  8, 7,        /* N */
+                                  0, 5,        /* M */
+                                  BIT(31),     /* gate */
+                                  BIT(28),     /* lock */
+                                  0);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
+                                       "osc24M", 0x0010,
+                                       8, 7,           /* N */
+                                       0, 4,           /* M */
+                                       BIT(24),        /* frac enable */
+                                       BIT(25),        /* frac select */
+                                       270000000,      /* frac rate 0 */
+                                       297000000,      /* frac rate 1 */
+                                       BIT(31),        /* gate */
+                                       BIT(28),        /* lock */
+                                       0);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
+                                       "osc24M", 0x0018,
+                                       8, 7,           /* N */
+                                       0, 4,           /* M */
+                                       BIT(24),        /* frac enable */
+                                       BIT(25),        /* frac select */
+                                       270000000,      /* frac rate 0 */
+                                       297000000,      /* frac rate 1 */
+                                       BIT(31),        /* gate */
+                                       BIT(28),        /* lock */
+                                       0);
+
+static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr",
+                                   "osc24M", 0x020,
+                                   8, 5,       /* N */
+                                   4, 2,       /* K */
+                                   0, 2,       /* M */
+                                   BIT(31),    /* gate */
+                                   BIT(28),    /* lock */
+                                   0);
+
+static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0",
+                                          "osc24M", 0x028,
+                                          8, 5,        /* N */
+                                          4, 2,        /* K */
+                                          BIT(31),     /* gate */
+                                          BIT(28),     /* lock */
+                                          2,           /* post-div */
+                                          0);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
+                                       "osc24M", 0x0038,
+                                       8, 7,           /* N */
+                                       0, 4,           /* M */
+                                       BIT(24),        /* frac enable */
+                                       BIT(25),        /* frac select */
+                                       270000000,      /* frac rate 0 */
+                                       297000000,      /* frac rate 1 */
+                                       BIT(31),        /* gate */
+                                       BIT(28),        /* lock */
+                                       0);
+
+static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1",
+                                          "osc24M", 0x044,
+                                          8, 5,        /* N */
+                                          4, 2,        /* K */
+                                          BIT(31),     /* gate */
+                                          BIT(28),     /* lock */
+                                          2,           /* post-div */
+                                          0);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
+                                       "osc24M", 0x0048,
+                                       8, 7,           /* N */
+                                       0, 4,           /* M */
+                                       BIT(24),        /* frac enable */
+                                       BIT(25),        /* frac select */
+                                       270000000,      /* frac rate 0 */
+                                       297000000,      /* frac rate 1 */
+                                       BIT(31),        /* gate */
+                                       BIT(28),        /* lock */
+                                       0);
+
+static const char * const cpux_parents[] = { "osc32k", "osc24M",
+                                            "pll-cpux" , "pll-cpux" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+                    0x050, 16, 2, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
+
+static const char * const ahb1_parents[] = { "osc32k", "osc24M",
+                                            "axi" , "pll-periph0" };
+static struct ccu_div ahb1_clk = {
+       .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
+
+       .mux            = {
+               .shift  = 12,
+               .width  = 2,
+
+               .variable_prediv        = {
+                       .index  = 3,
+                       .shift  = 6,
+                       .width  = 2,
+               },
+       },
+
+       .common         = {
+               .reg            = 0x054,
+               .features       = CCU_FEATURE_VARIABLE_PREDIV,
+               .hw.init        = CLK_HW_INIT_PARENTS("ahb1",
+                                                     ahb1_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static struct clk_div_table apb1_div_table[] = {
+       { .val = 0, .div = 2 },
+       { .val = 1, .div = 2 },
+       { .val = 2, .div = 4 },
+       { .val = 3, .div = 8 },
+       { /* Sentinel */ },
+};
+static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1",
+                          0x054, 8, 2, apb1_div_table, 0);
+
+static const char * const apb2_parents[] = { "osc32k", "osc24M",
+                                            "pll-periph0" , "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
+                            0, 5,      /* M */
+                            16, 2,     /* P */
+                            24, 2,     /* mux */
+                            0);
+
+static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" };
+static struct ccu_mux ahb2_clk = {
+       .mux            = {
+               .shift  = 0,
+               .width  = 1,
+
+               .fixed_prediv   = {
+                       .index  = 1,
+                       .div    = 2,
+               },
+       },
+
+       .common         = {
+               .reg            = 0x05c,
+               .features       = CCU_FEATURE_FIXED_PREDIV,
+               .hw.init        = CLK_HW_INIT_PARENTS("ahb2",
+                                                     ahb2_parents,
+                                                     &ccu_mux_ops,
+                                                     0),
+       },
+};
+
+static SUNXI_CCU_GATE(bus_ce_clk,      "bus-ce",       "ahb1",
+                     0x060, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_dma_clk,     "bus-dma",      "ahb1",
+                     0x060, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_mmc0_clk,    "bus-mmc0",     "ahb1",
+                     0x060, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk,    "bus-mmc1",     "ahb1",
+                     0x060, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk,    "bus-mmc2",     "ahb1",
+                     0x060, BIT(10), 0);
+static SUNXI_CCU_GATE(bus_nand_clk,    "bus-nand",     "ahb1",
+                     0x060, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_dram_clk,    "bus-dram",     "ahb1",
+                     0x060, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_emac_clk,    "bus-emac",     "ahb2",
+                     0x060, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_ts_clk,      "bus-ts",       "ahb1",
+                     0x060, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer",  "ahb1",
+                     0x060, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_spi0_clk,    "bus-spi0",     "ahb1",
+                     0x060, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk,    "bus-spi1",     "ahb1",
+                     0x060, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_otg_clk,     "bus-otg",      "ahb1",
+                     0x060, BIT(23), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk,   "bus-ehci0",    "ahb1",
+                     0x060, BIT(24), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk,   "bus-ehci1",    "ahb2",
+                     0x060, BIT(25), 0);
+static SUNXI_CCU_GATE(bus_ehci2_clk,   "bus-ehci2",    "ahb2",
+                     0x060, BIT(26), 0);
+static SUNXI_CCU_GATE(bus_ehci3_clk,   "bus-ehci3",    "ahb2",
+                     0x060, BIT(27), 0);
+static SUNXI_CCU_GATE(bus_ohci0_clk,   "bus-ohci0",    "ahb1",
+                     0x060, BIT(28), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk,   "bus-ohci1",    "ahb2",
+                     0x060, BIT(29), 0);
+static SUNXI_CCU_GATE(bus_ohci2_clk,   "bus-ohci2",    "ahb2",
+                     0x060, BIT(30), 0);
+static SUNXI_CCU_GATE(bus_ohci3_clk,   "bus-ohci3",    "ahb2",
+                     0x060, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_ve_clk,      "bus-ve",       "ahb1",
+                     0x064, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon0_clk,   "bus-tcon0",    "ahb1",
+                     0x064, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_tcon1_clk,   "bus-tcon1",    "ahb1",
+                     0x064, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_deinterlace_clk,     "bus-deinterlace",      "ahb1",
+                     0x064, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_csi_clk,     "bus-csi",      "ahb1",
+                     0x064, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_tve_clk,     "bus-tve",      "ahb1",
+                     0x064, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_hdmi_clk,    "bus-hdmi",     "ahb1",
+                     0x064, BIT(11), 0);
+static SUNXI_CCU_GATE(bus_de_clk,      "bus-de",       "ahb1",
+                     0x064, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_gpu_clk,     "bus-gpu",      "ahb1",
+                     0x064, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_msgbox_clk,  "bus-msgbox",   "ahb1",
+                     0x064, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_spinlock_clk,        "bus-spinlock", "ahb1",
+                     0x064, BIT(22), 0);
+
+static SUNXI_CCU_GATE(bus_codec_clk,   "bus-codec",    "apb1",
+                     0x068, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spdif_clk,   "bus-spdif",    "apb1",
+                     0x068, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_pio_clk,     "bus-pio",      "apb1",
+                     0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ths_clk,     "bus-ths",      "apb1",
+                     0x068, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_i2s0_clk,    "bus-i2s0",     "apb1",
+                     0x068, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk,    "bus-i2s1",     "apb1",
+                     0x068, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_i2s2_clk,    "bus-i2s2",     "apb1",
+                     0x068, BIT(14), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk,    "bus-i2c0",     "apb2",
+                     0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk,    "bus-i2c1",     "apb2",
+                     0x06c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk,    "bus-i2c2",     "apb2",
+                     0x06c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart0_clk,   "bus-uart0",    "apb2",
+                     0x06c, BIT(16), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk,   "bus-uart1",    "apb2",
+                     0x06c, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk,   "bus-uart2",    "apb2",
+                     0x06c, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk,   "bus-uart3",    "apb2",
+                     0x06c, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_scr_clk,     "bus-scr",      "apb2",
+                     0x06c, BIT(20), 0);
+
+static SUNXI_CCU_GATE(bus_ephy_clk,    "bus-ephy",     "ahb1",
+                     0x070, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_dbg_clk,     "bus-dbg",      "ahb1",
+                     0x070, BIT(7), 0);
+
+static struct clk_div_table ths_div_table[] = {
+       { .val = 0, .div = 1 },
+       { .val = 1, .div = 2 },
+       { .val = 2, .div = 4 },
+       { .val = 3, .div = 6 },
+};
+static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M",
+                                    0x074, 0, 2, ths_div_table, BIT(31), 0);
+
+static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0",
+                                                    "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
+                      0x088, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
+                      0x088, 8, 3, 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
+                      0x08c, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
+                      0x08c, 8, 3, 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
+                      0x090, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
+                      0x090, 8, 3, 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mod0_default_parents, 0x09c,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
+                                           "pll-audio-2x", "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
+                              0x0b0, 16, 2, BIT(31), 0);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
+                              0x0b4, 16, 2, BIT(31), 0);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
+                              0x0b8, 16, 2, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
+                            0x0c0, 0, 4, BIT(31), 0);
+
+static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",     "osc24M",
+                     0x0cc, BIT(8), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk,    "usb-phy1",     "osc24M",
+                     0x0cc, BIT(9), 0);
+static SUNXI_CCU_GATE(usb_phy2_clk,    "usb-phy2",     "osc24M",
+                     0x0cc, BIT(10), 0);
+static SUNXI_CCU_GATE(usb_phy3_clk,    "usb-phy3",     "osc24M",
+                     0x0cc, BIT(11), 0);
+static SUNXI_CCU_GATE(usb_ohci0_clk,   "usb-ohci0",    "osc24M",
+                     0x0cc, BIT(16), 0);
+static SUNXI_CCU_GATE(usb_ohci1_clk,   "usb-ohci1",    "osc24M",
+                     0x0cc, BIT(17), 0);
+static SUNXI_CCU_GATE(usb_ohci2_clk,   "usb-ohci2",    "osc24M",
+                     0x0cc, BIT(18), 0);
+static SUNXI_CCU_GATE(usb_ohci3_clk,   "usb-ohci3",    "osc24M",
+                     0x0cc, BIT(19), 0);
+
+static const char * const dram_parents[] = { "pll-ddr", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents,
+                           0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_GATE(dram_ve_clk,     "dram-ve",      "dram",
+                     0x100, BIT(0), 0);
+static SUNXI_CCU_GATE(dram_csi_clk,    "dram-csi",     "dram",
+                     0x100, BIT(1), 0);
+static SUNXI_CCU_GATE(dram_deinterlace_clk,    "dram-deinterlace",     "dram",
+                     0x100, BIT(2), 0);
+static SUNXI_CCU_GATE(dram_ts_clk,     "dram-ts",      "dram",
+                     0x100, BIT(3), 0);
+
+static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
+                                0x104, 0, 4, 24, 3, BIT(31), 0);
+
+static const char * const tcon_parents[] = { "pll-video" };
+static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
+                                0x118, 0, 4, 24, 3, BIT(31), 0);
+
+static const char * const tve_parents[] = { "pll-de", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(tve_clk, "tve", tve_parents,
+                                0x120, 0, 4, 24, 3, BIT(31), 0);
+
+static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
+                                0x124, 0, 4, 24, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(csi_misc_clk,    "csi-misc",     "osc24M",
+                     0x130, BIT(31), 0);
+
+static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents,
+                                0x134, 16, 4, 24, 3, BIT(31), 0);
+
+static const char * const csi_mclk_parents[] = { "osc24M", "pll-video", "pll-periph0" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents,
+                                0x134, 0, 5, 8, 3, BIT(15), 0);
+
+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
+                            0x13c, 16, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(ac_dig_clk,      "ac-dig",       "pll-audio",
+                     0x140, BIT(31), 0);
+static SUNXI_CCU_GATE(avs_clk,         "avs",          "osc24M",
+                     0x144, BIT(31), 0);
+
+static const char * const hdmi_parents[] = { "pll-video" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
+                                0x150, 0, 4, 24, 2, BIT(31), 0);
+
+static SUNXI_CCU_GATE(hdmi_ddc_clk,    "hdmi-ddc",     "osc24M",
+                     0x154, BIT(31), 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", "pll-ddr" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+                                0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
+                            0x1a0, 0, 3, BIT(31), 0);
+
+static struct ccu_common *sun8i_h3_ccu_clks[] = {
+       &pll_cpux_clk.common,
+       &pll_audio_base_clk.common,
+       &pll_video_clk.common,
+       &pll_ve_clk.common,
+       &pll_ddr_clk.common,
+       &pll_periph0_clk.common,
+       &pll_gpu_clk.common,
+       &pll_periph1_clk.common,
+       &pll_de_clk.common,
+       &cpux_clk.common,
+       &axi_clk.common,
+       &ahb1_clk.common,
+       &apb1_clk.common,
+       &apb2_clk.common,
+       &ahb2_clk.common,
+       &bus_ce_clk.common,
+       &bus_dma_clk.common,
+       &bus_mmc0_clk.common,
+       &bus_mmc1_clk.common,
+       &bus_mmc2_clk.common,
+       &bus_nand_clk.common,
+       &bus_dram_clk.common,
+       &bus_emac_clk.common,
+       &bus_ts_clk.common,
+       &bus_hstimer_clk.common,
+       &bus_spi0_clk.common,
+       &bus_spi1_clk.common,
+       &bus_otg_clk.common,
+       &bus_ehci0_clk.common,
+       &bus_ehci1_clk.common,
+       &bus_ehci2_clk.common,
+       &bus_ehci3_clk.common,
+       &bus_ohci0_clk.common,
+       &bus_ohci1_clk.common,
+       &bus_ohci2_clk.common,
+       &bus_ohci3_clk.common,
+       &bus_ve_clk.common,
+       &bus_tcon0_clk.common,
+       &bus_tcon1_clk.common,
+       &bus_deinterlace_clk.common,
+       &bus_csi_clk.common,
+       &bus_tve_clk.common,
+       &bus_hdmi_clk.common,
+       &bus_de_clk.common,
+       &bus_gpu_clk.common,
+       &bus_msgbox_clk.common,
+       &bus_spinlock_clk.common,
+       &bus_codec_clk.common,
+       &bus_spdif_clk.common,
+       &bus_pio_clk.common,
+       &bus_ths_clk.common,
+       &bus_i2s0_clk.common,
+       &bus_i2s1_clk.common,
+       &bus_i2s2_clk.common,
+       &bus_i2c0_clk.common,
+       &bus_i2c1_clk.common,
+       &bus_i2c2_clk.common,
+       &bus_uart0_clk.common,
+       &bus_uart1_clk.common,
+       &bus_uart2_clk.common,
+       &bus_uart3_clk.common,
+       &bus_scr_clk.common,
+       &bus_ephy_clk.common,
+       &bus_dbg_clk.common,
+       &ths_clk.common,
+       &nand_clk.common,
+       &mmc0_clk.common,
+       &mmc0_sample_clk.common,
+       &mmc0_output_clk.common,
+       &mmc1_clk.common,
+       &mmc1_sample_clk.common,
+       &mmc1_output_clk.common,
+       &mmc2_clk.common,
+       &mmc2_sample_clk.common,
+       &mmc2_output_clk.common,
+       &ts_clk.common,
+       &ce_clk.common,
+       &spi0_clk.common,
+       &spi1_clk.common,
+       &i2s0_clk.common,
+       &i2s1_clk.common,
+       &i2s2_clk.common,
+       &spdif_clk.common,
+       &usb_phy0_clk.common,
+       &usb_phy1_clk.common,
+       &usb_phy2_clk.common,
+       &usb_phy3_clk.common,
+       &usb_ohci0_clk.common,
+       &usb_ohci1_clk.common,
+       &usb_ohci2_clk.common,
+       &usb_ohci3_clk.common,
+       &dram_clk.common,
+       &dram_ve_clk.common,
+       &dram_csi_clk.common,
+       &dram_deinterlace_clk.common,
+       &dram_ts_clk.common,
+       &de_clk.common,
+       &tcon_clk.common,
+       &tve_clk.common,
+       &deinterlace_clk.common,
+       &csi_misc_clk.common,
+       &csi_sclk_clk.common,
+       &csi_mclk_clk.common,
+       &ve_clk.common,
+       &ac_dig_clk.common,
+       &avs_clk.common,
+       &hdmi_clk.common,
+       &hdmi_ddc_clk.common,
+       &mbus_clk.common,
+       &gpu_clk.common,
+};
+
+/* We hardcode the divider to 4 for now */
+static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
+                       "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
+                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
+                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
+                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
+                       "pll-periph0", 1, 2, 0);
+
+static struct clk_hw_onecell_data sun8i_h3_hw_clks = {
+       .hws    = {
+               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
+               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
+               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
+               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
+               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
+               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
+               [CLK_PLL_VIDEO]         = &pll_video_clk.common.hw,
+               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
+               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
+               [CLK_PLL_PERIPH0]       = &pll_periph0_clk.common.hw,
+               [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
+               [CLK_PLL_GPU]           = &pll_gpu_clk.common.hw,
+               [CLK_PLL_PERIPH1]       = &pll_periph1_clk.common.hw,
+               [CLK_PLL_DE]            = &pll_de_clk.common.hw,
+               [CLK_CPUX]              = &cpux_clk.common.hw,
+               [CLK_AXI]               = &axi_clk.common.hw,
+               [CLK_AHB1]              = &ahb1_clk.common.hw,
+               [CLK_APB1]              = &apb1_clk.common.hw,
+               [CLK_APB2]              = &apb2_clk.common.hw,
+               [CLK_AHB2]              = &ahb2_clk.common.hw,
+               [CLK_BUS_CE]            = &bus_ce_clk.common.hw,
+               [CLK_BUS_DMA]           = &bus_dma_clk.common.hw,
+               [CLK_BUS_MMC0]          = &bus_mmc0_clk.common.hw,
+               [CLK_BUS_MMC1]          = &bus_mmc1_clk.common.hw,
+               [CLK_BUS_MMC2]          = &bus_mmc2_clk.common.hw,
+               [CLK_BUS_NAND]          = &bus_nand_clk.common.hw,
+               [CLK_BUS_DRAM]          = &bus_dram_clk.common.hw,
+               [CLK_BUS_EMAC]          = &bus_emac_clk.common.hw,
+               [CLK_BUS_TS]            = &bus_ts_clk.common.hw,
+               [CLK_BUS_HSTIMER]       = &bus_hstimer_clk.common.hw,
+               [CLK_BUS_SPI0]          = &bus_spi0_clk.common.hw,
+               [CLK_BUS_SPI1]          = &bus_spi1_clk.common.hw,
+               [CLK_BUS_OTG]           = &bus_otg_clk.common.hw,
+               [CLK_BUS_EHCI0]         = &bus_ehci0_clk.common.hw,
+               [CLK_BUS_EHCI1]         = &bus_ehci1_clk.common.hw,
+               [CLK_BUS_EHCI2]         = &bus_ehci2_clk.common.hw,
+               [CLK_BUS_EHCI3]         = &bus_ehci3_clk.common.hw,
+               [CLK_BUS_OHCI0]         = &bus_ohci0_clk.common.hw,
+               [CLK_BUS_OHCI1]         = &bus_ohci1_clk.common.hw,
+               [CLK_BUS_OHCI2]         = &bus_ohci2_clk.common.hw,
+               [CLK_BUS_OHCI3]         = &bus_ohci3_clk.common.hw,
+               [CLK_BUS_VE]            = &bus_ve_clk.common.hw,
+               [CLK_BUS_TCON0]         = &bus_tcon0_clk.common.hw,
+               [CLK_BUS_TCON1]         = &bus_tcon1_clk.common.hw,
+               [CLK_BUS_DEINTERLACE]   = &bus_deinterlace_clk.common.hw,
+               [CLK_BUS_CSI]           = &bus_csi_clk.common.hw,
+               [CLK_BUS_TVE]           = &bus_tve_clk.common.hw,
+               [CLK_BUS_HDMI]          = &bus_hdmi_clk.common.hw,
+               [CLK_BUS_DE]            = &bus_de_clk.common.hw,
+               [CLK_BUS_GPU]           = &bus_gpu_clk.common.hw,
+               [CLK_BUS_MSGBOX]        = &bus_msgbox_clk.common.hw,
+               [CLK_BUS_SPINLOCK]      = &bus_spinlock_clk.common.hw,
+               [CLK_BUS_CODEC]         = &bus_codec_clk.common.hw,
+               [CLK_BUS_SPDIF]         = &bus_spdif_clk.common.hw,
+               [CLK_BUS_PIO]           = &bus_pio_clk.common.hw,
+               [CLK_BUS_THS]           = &bus_ths_clk.common.hw,
+               [CLK_BUS_I2S0]          = &bus_i2s0_clk.common.hw,
+               [CLK_BUS_I2S1]          = &bus_i2s1_clk.common.hw,
+               [CLK_BUS_I2S2]          = &bus_i2s2_clk.common.hw,
+               [CLK_BUS_I2C0]          = &bus_i2c0_clk.common.hw,
+               [CLK_BUS_I2C1]          = &bus_i2c1_clk.common.hw,
+               [CLK_BUS_I2C2]          = &bus_i2c2_clk.common.hw,
+               [CLK_BUS_UART0]         = &bus_uart0_clk.common.hw,
+               [CLK_BUS_UART1]         = &bus_uart1_clk.common.hw,
+               [CLK_BUS_UART2]         = &bus_uart2_clk.common.hw,
+               [CLK_BUS_UART3]         = &bus_uart3_clk.common.hw,
+               [CLK_BUS_SCR]           = &bus_scr_clk.common.hw,
+               [CLK_BUS_EPHY]          = &bus_ephy_clk.common.hw,
+               [CLK_BUS_DBG]           = &bus_dbg_clk.common.hw,
+               [CLK_THS]               = &ths_clk.common.hw,
+               [CLK_NAND]              = &nand_clk.common.hw,
+               [CLK_MMC0]              = &mmc0_clk.common.hw,
+               [CLK_MMC0_SAMPLE]       = &mmc0_sample_clk.common.hw,
+               [CLK_MMC0_OUTPUT]       = &mmc0_output_clk.common.hw,
+               [CLK_MMC1]              = &mmc1_clk.common.hw,
+               [CLK_MMC1_SAMPLE]       = &mmc1_sample_clk.common.hw,
+               [CLK_MMC1_OUTPUT]       = &mmc1_output_clk.common.hw,
+               [CLK_MMC2]              = &mmc2_clk.common.hw,
+               [CLK_MMC2_SAMPLE]       = &mmc2_sample_clk.common.hw,
+               [CLK_MMC2_OUTPUT]       = &mmc2_output_clk.common.hw,
+               [CLK_TS]                = &ts_clk.common.hw,
+               [CLK_CE]                = &ce_clk.common.hw,
+               [CLK_SPI0]              = &spi0_clk.common.hw,
+               [CLK_SPI1]              = &spi1_clk.common.hw,
+               [CLK_I2S0]              = &i2s0_clk.common.hw,
+               [CLK_I2S1]              = &i2s1_clk.common.hw,
+               [CLK_I2S2]              = &i2s2_clk.common.hw,
+               [CLK_SPDIF]             = &spdif_clk.common.hw,
+               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
+               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
+               [CLK_USB_PHY2]          = &usb_phy2_clk.common.hw,
+               [CLK_USB_PHY3]          = &usb_phy3_clk.common.hw,
+               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
+               [CLK_USB_OHCI1]         = &usb_ohci1_clk.common.hw,
+               [CLK_USB_OHCI2]         = &usb_ohci2_clk.common.hw,
+               [CLK_USB_OHCI3]         = &usb_ohci3_clk.common.hw,
+               [CLK_DRAM]              = &dram_clk.common.hw,
+               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
+               [CLK_DRAM_CSI]          = &dram_csi_clk.common.hw,
+               [CLK_DRAM_DEINTERLACE]  = &dram_deinterlace_clk.common.hw,
+               [CLK_DRAM_TS]           = &dram_ts_clk.common.hw,
+               [CLK_DE]                = &de_clk.common.hw,
+               [CLK_TCON0]             = &tcon_clk.common.hw,
+               [CLK_TVE]               = &tve_clk.common.hw,
+               [CLK_DEINTERLACE]       = &deinterlace_clk.common.hw,
+               [CLK_CSI_MISC]          = &csi_misc_clk.common.hw,
+               [CLK_CSI_SCLK]          = &csi_sclk_clk.common.hw,
+               [CLK_CSI_MCLK]          = &csi_mclk_clk.common.hw,
+               [CLK_VE]                = &ve_clk.common.hw,
+               [CLK_AC_DIG]            = &ac_dig_clk.common.hw,
+               [CLK_AVS]               = &avs_clk.common.hw,
+               [CLK_HDMI]              = &hdmi_clk.common.hw,
+               [CLK_HDMI_DDC]          = &hdmi_ddc_clk.common.hw,
+               [CLK_MBUS]              = &mbus_clk.common.hw,
+               [CLK_GPU]               = &gpu_clk.common.hw,
+       },
+       .num    = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
+       [RST_USB_PHY0]          =  { 0x0cc, BIT(0) },
+       [RST_USB_PHY1]          =  { 0x0cc, BIT(1) },
+       [RST_USB_PHY2]          =  { 0x0cc, BIT(2) },
+       [RST_USB_PHY3]          =  { 0x0cc, BIT(3) },
+
+       [RST_MBUS]              =  { 0x0fc, BIT(31) },
+
+       [RST_BUS_CE]            =  { 0x2c0, BIT(5) },
+       [RST_BUS_DMA]           =  { 0x2c0, BIT(6) },
+       [RST_BUS_MMC0]          =  { 0x2c0, BIT(8) },
+       [RST_BUS_MMC1]          =  { 0x2c0, BIT(9) },
+       [RST_BUS_MMC2]          =  { 0x2c0, BIT(10) },
+       [RST_BUS_NAND]          =  { 0x2c0, BIT(13) },
+       [RST_BUS_DRAM]          =  { 0x2c0, BIT(14) },
+       [RST_BUS_EMAC]          =  { 0x2c0, BIT(17) },
+       [RST_BUS_TS]            =  { 0x2c0, BIT(18) },
+       [RST_BUS_HSTIMER]       =  { 0x2c0, BIT(19) },
+       [RST_BUS_SPI0]          =  { 0x2c0, BIT(20) },
+       [RST_BUS_SPI1]          =  { 0x2c0, BIT(21) },
+       [RST_BUS_OTG]           =  { 0x2c0, BIT(23) },
+       [RST_BUS_EHCI0]         =  { 0x2c0, BIT(24) },
+       [RST_BUS_EHCI1]         =  { 0x2c0, BIT(25) },
+       [RST_BUS_EHCI2]         =  { 0x2c0, BIT(26) },
+       [RST_BUS_EHCI3]         =  { 0x2c0, BIT(27) },
+       [RST_BUS_OHCI0]         =  { 0x2c0, BIT(28) },
+       [RST_BUS_OHCI1]         =  { 0x2c0, BIT(29) },
+       [RST_BUS_OHCI2]         =  { 0x2c0, BIT(30) },
+       [RST_BUS_OHCI3]         =  { 0x2c0, BIT(31) },
+
+       [RST_BUS_VE]            =  { 0x2c4, BIT(0) },
+       [RST_BUS_TCON0]         =  { 0x2c4, BIT(3) },
+       [RST_BUS_TCON1]         =  { 0x2c4, BIT(4) },
+       [RST_BUS_DEINTERLACE]   =  { 0x2c4, BIT(5) },
+       [RST_BUS_CSI]           =  { 0x2c4, BIT(8) },
+       [RST_BUS_TVE]           =  { 0x2c4, BIT(9) },
+       [RST_BUS_HDMI0]         =  { 0x2c4, BIT(10) },
+       [RST_BUS_HDMI1]         =  { 0x2c4, BIT(11) },
+       [RST_BUS_DE]            =  { 0x2c4, BIT(12) },
+       [RST_BUS_GPU]           =  { 0x2c4, BIT(20) },
+       [RST_BUS_MSGBOX]        =  { 0x2c4, BIT(21) },
+       [RST_BUS_SPINLOCK]      =  { 0x2c4, BIT(22) },
+       [RST_BUS_DBG]           =  { 0x2c4, BIT(31) },
+
+       [RST_BUS_EPHY]          =  { 0x2c8, BIT(2) },
+
+       [RST_BUS_CODEC]         =  { 0x2d0, BIT(0) },
+       [RST_BUS_SPDIF]         =  { 0x2d0, BIT(1) },
+       [RST_BUS_THS]           =  { 0x2d0, BIT(8) },
+       [RST_BUS_I2S0]          =  { 0x2d0, BIT(12) },
+       [RST_BUS_I2S1]          =  { 0x2d0, BIT(13) },
+       [RST_BUS_I2S2]          =  { 0x2d0, BIT(14) },
+
+       [RST_BUS_I2C0]          =  { 0x2d4, BIT(0) },
+       [RST_BUS_I2C1]          =  { 0x2d4, BIT(1) },
+       [RST_BUS_I2C2]          =  { 0x2d4, BIT(2) },
+       [RST_BUS_UART0]         =  { 0x2d4, BIT(16) },
+       [RST_BUS_UART1]         =  { 0x2d4, BIT(17) },
+       [RST_BUS_UART2]         =  { 0x2d4, BIT(18) },
+       [RST_BUS_UART3]         =  { 0x2d4, BIT(19) },
+       [RST_BUS_SCR]           =  { 0x2d4, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
+       .ccu_clks       = sun8i_h3_ccu_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun8i_h3_ccu_clks),
+
+       .hw_clks        = &sun8i_h3_hw_clks,
+
+       .resets         = sun8i_h3_ccu_resets,
+       .num_resets     = ARRAY_SIZE(sun8i_h3_ccu_resets),
+};
+
+static void __init sun8i_h3_ccu_setup(struct device_node *node)
+{
+       void __iomem *reg;
+       u32 val;
+
+       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+       if (IS_ERR(reg)) {
+               pr_err("%s: Could not map the clock registers\n",
+                      of_node_full_name(node));
+               return;
+       }
+
+       /* Force the PLL-Audio-1x divider to 4 */
+       val = readl(reg + SUN8I_H3_PLL_AUDIO_REG);
+       val &= ~GENMASK(19, 16);
+       writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
+
+       sunxi_ccu_probe(node, reg, &sun8i_h3_ccu_desc);
+}
+CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu",
+              sun8i_h3_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
new file mode 100644 (file)
index 0000000..78be712
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef _CCU_SUN8I_H3_H_
+#define _CCU_SUN8I_H3_H_
+
+#include <dt-bindings/clock/sun8i-h3-ccu.h>
+#include <dt-bindings/reset/sun8i-h3-ccu.h>
+
+#define CLK_PLL_CPUX           0
+#define CLK_PLL_AUDIO_BASE     1
+#define CLK_PLL_AUDIO          2
+#define CLK_PLL_AUDIO_2X       3
+#define CLK_PLL_AUDIO_4X       4
+#define CLK_PLL_AUDIO_8X       5
+#define CLK_PLL_VIDEO          6
+#define CLK_PLL_VE             7
+#define CLK_PLL_DDR            8
+#define CLK_PLL_PERIPH0                9
+#define CLK_PLL_PERIPH0_2X     10
+#define CLK_PLL_GPU            11
+#define CLK_PLL_PERIPH1                12
+#define CLK_PLL_DE             13
+
+/* The CPUX clock is exported */
+
+#define CLK_AXI                        15
+#define CLK_AHB1               16
+#define CLK_APB1               17
+#define CLK_APB2               18
+#define CLK_AHB2               19
+
+/* All the bus gates are exported */
+
+/* The first bunch of module clocks are exported */
+
+#define CLK_DRAM               96
+
+/* All the DRAM gates are exported */
+
+/* Some more module clocks are exported */
+
+#define CLK_MBUS               113
+
+/* And the GPU module clock is exported */
+
+#define CLK_NUMBER             (CLK_GPU + 1)
+
+#endif /* _CCU_SUN8I_H3_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
new file mode 100644 (file)
index 0000000..fc17b52
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2016 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-provider.h>
+#include <linux/iopoll.h>
+#include <linux/slab.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+static DEFINE_SPINLOCK(ccu_lock);
+
+void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
+{
+       u32 reg;
+
+       if (!lock)
+               return;
+
+       WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
+                                          !(reg & lock), 100, 70000));
+}
+
+int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+                   const struct sunxi_ccu_desc *desc)
+{
+       struct ccu_reset *reset;
+       int i, ret;
+
+       for (i = 0; i < desc->num_ccu_clks; i++) {
+               struct ccu_common *cclk = desc->ccu_clks[i];
+
+               if (!cclk)
+                       continue;
+
+               cclk->base = reg;
+               cclk->lock = &ccu_lock;
+       }
+
+       for (i = 0; i < desc->hw_clks->num ; i++) {
+               struct clk_hw *hw = desc->hw_clks->hws[i];
+
+               if (!hw)
+                       continue;
+
+               ret = clk_hw_register(NULL, hw);
+               if (ret) {
+                       pr_err("Couldn't register clock %s\n",
+                              clk_hw_get_name(hw));
+                       goto err_clk_unreg;
+               }
+       }
+
+       ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+                                    desc->hw_clks);
+       if (ret)
+               goto err_clk_unreg;
+
+       reset = kzalloc(sizeof(*reset), GFP_KERNEL);
+       reset->rcdev.of_node = node;
+       reset->rcdev.ops = &ccu_reset_ops;
+       reset->rcdev.owner = THIS_MODULE;
+       reset->rcdev.nr_resets = desc->num_resets;
+       reset->base = reg;
+       reset->lock = &ccu_lock;
+       reset->reset_map = desc->resets;
+
+       ret = reset_controller_register(&reset->rcdev);
+       if (ret)
+               goto err_of_clk_unreg;
+
+       return 0;
+
+err_of_clk_unreg:
+err_clk_unreg:
+       return ret;
+}
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
new file mode 100644 (file)
index 0000000..b3d9abf
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _COMMON_H_
+#define _COMMON_H_
+
+#include <linux/compiler.h>
+#include <linux/clk-provider.h>
+
+#define CCU_FEATURE_FRACTIONAL         BIT(0)
+#define CCU_FEATURE_VARIABLE_PREDIV    BIT(1)
+#define CCU_FEATURE_FIXED_PREDIV       BIT(2)
+#define CCU_FEATURE_FIXED_POSTDIV      BIT(3)
+
+struct device_node;
+
+#define CLK_HW_INIT(_name, _parent, _ops, _flags)                      \
+       &(struct clk_init_data) {                                       \
+               .flags          = _flags,                               \
+               .name           = _name,                                \
+               .parent_names   = (const char *[]) { _parent },         \
+               .num_parents    = 1,                                    \
+               .ops            = _ops,                                 \
+       }
+
+#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags)             \
+       &(struct clk_init_data) {                                       \
+               .flags          = _flags,                               \
+               .name           = _name,                                \
+               .parent_names   = _parents,                             \
+               .num_parents    = ARRAY_SIZE(_parents),                 \
+               .ops            = _ops,                                 \
+       }
+
+#define CLK_FIXED_FACTOR(_struct, _name, _parent,                      \
+                       _div, _mult, _flags)                            \
+       struct clk_fixed_factor _struct = {                             \
+               .div            = _div,                                 \
+               .mult           = _mult,                                \
+               .hw.init        = CLK_HW_INIT(_name,                    \
+                                             _parent,                  \
+                                             &clk_fixed_factor_ops,    \
+                                             _flags),                  \
+       }
+
+struct ccu_common {
+       void __iomem    *base;
+       u16             reg;
+
+       unsigned long   features;
+       spinlock_t      *lock;
+       struct clk_hw   hw;
+};
+
+static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
+{
+       return container_of(hw, struct ccu_common, hw);
+}
+
+struct sunxi_ccu_desc {
+       struct ccu_common               **ccu_clks;
+       unsigned long                   num_ccu_clks;
+
+       struct clk_hw_onecell_data      *hw_clks;
+
+       struct ccu_reset_map            *resets;
+       unsigned long                   num_resets;
+};
+
+void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
+
+int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+                   const struct sunxi_ccu_desc *desc);
+
+#endif /* _COMMON_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
new file mode 100644 (file)
index 0000000..8659b4c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_div.h"
+
+static unsigned long ccu_div_round_rate(struct ccu_mux_internal *mux,
+                                       unsigned long parent_rate,
+                                       unsigned long rate,
+                                       void *data)
+{
+       struct ccu_div *cd = data;
+       unsigned long val;
+
+       /*
+        * We can't use divider_round_rate that assumes that there's
+        * several parents, while we might be called to evaluate
+        * several different parents.
+        */
+       val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width,
+                             cd->div.flags);
+
+       return divider_recalc_rate(&cd->common.hw, parent_rate, val,
+                                  cd->div.table, cd->div.flags);
+}
+
+static void ccu_div_disable(struct clk_hw *hw)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+
+       return ccu_gate_helper_disable(&cd->common, cd->enable);
+}
+
+static int ccu_div_enable(struct clk_hw *hw)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+
+       return ccu_gate_helper_enable(&cd->common, cd->enable);
+}
+
+static int ccu_div_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+
+       return ccu_gate_helper_is_enabled(&cd->common, cd->enable);
+}
+
+static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+       unsigned long val;
+       u32 reg;
+
+       reg = readl(cd->common.base + cd->common.reg);
+       val = reg >> cd->div.shift;
+       val &= (1 << cd->div.width) - 1;
+
+       ccu_mux_helper_adjust_parent_for_prediv(&cd->common, &cd->mux, -1,
+                                               &parent_rate);
+
+       return divider_recalc_rate(hw, parent_rate, val, cd->div.table,
+                                  cd->div.flags);
+}
+
+static int ccu_div_determine_rate(struct clk_hw *hw,
+                               struct clk_rate_request *req)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+
+       return ccu_mux_helper_determine_rate(&cd->common, &cd->mux,
+                                            req, ccu_div_round_rate, cd);
+}
+
+static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
+                          unsigned long parent_rate)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+       unsigned long flags;
+       unsigned long val;
+       u32 reg;
+
+       ccu_mux_helper_adjust_parent_for_prediv(&cd->common, &cd->mux, -1,
+                                               &parent_rate);
+
+       val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width,
+                             cd->div.flags);
+
+       spin_lock_irqsave(cd->common.lock, flags);
+
+       reg = readl(cd->common.base + cd->common.reg);
+       reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
+
+       writel(reg | (val << cd->div.shift),
+              cd->common.base + cd->common.reg);
+
+       spin_unlock_irqrestore(cd->common.lock, flags);
+
+       return 0;
+}
+
+static u8 ccu_div_get_parent(struct clk_hw *hw)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+
+       return ccu_mux_helper_get_parent(&cd->common, &cd->mux);
+}
+
+static int ccu_div_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct ccu_div *cd = hw_to_ccu_div(hw);
+
+       return ccu_mux_helper_set_parent(&cd->common, &cd->mux, index);
+}
+
+const struct clk_ops ccu_div_ops = {
+       .disable        = ccu_div_disable,
+       .enable         = ccu_div_enable,
+       .is_enabled     = ccu_div_is_enabled,
+
+       .get_parent     = ccu_div_get_parent,
+       .set_parent     = ccu_div_set_parent,
+
+       .determine_rate = ccu_div_determine_rate,
+       .recalc_rate    = ccu_div_recalc_rate,
+       .set_rate       = ccu_div_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
new file mode 100644 (file)
index 0000000..653ade5
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_DIV_H_
+#define _CCU_DIV_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_mux.h"
+
+struct _ccu_div {
+       u8                      shift;
+       u8                      width;
+
+       u32                     flags;
+
+       struct clk_div_table    *table;
+};
+
+#define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags)     \
+       {                                                               \
+               .shift  = _shift,                                       \
+               .width  = _width,                                       \
+               .flags  = _flags,                                       \
+               .table  = _table,                                       \
+       }
+
+#define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)                   \
+       _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, NULL, _flags)
+
+#define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)                   \
+       _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
+
+#define _SUNXI_CCU_DIV(_shift, _width)                                 \
+       _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, NULL, 0)
+
+struct ccu_div {
+       u32                     enable;
+
+       struct _ccu_div         div;
+       struct ccu_mux_internal mux;
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,   \
+                                     _shift, _width,                   \
+                                     _table, _gate, _flags)            \
+       struct ccu_div _struct = {                                      \
+               .div            = _SUNXI_CCU_DIV_TABLE(_shift, _width,  \
+                                                      _table),         \
+               .enable         = _gate,                                \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_div_ops,     \
+                                                     _flags),          \
+               }                                                       \
+       }
+
+
+#define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,             \
+                           _shift, _width,                             \
+                           _table, _flags)                             \
+       SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
+                                     _shift, _width, _table, 0,        \
+                                     _flags)
+
+#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
+                                 _mshift, _mwidth, _muxshift, _muxwidth, \
+                                 _gate, _flags)                        \
+       struct ccu_div _struct = {                                      \
+               .enable = _gate,                                        \
+               .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
+               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
+                                                             _parents, \
+                                                             &ccu_div_ops, \
+                                                             _flags),  \
+               },                                                      \
+       }
+
+#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,           \
+                            _mshift, _mwidth, _muxshift, _muxwidth,    \
+                            _flags)                                    \
+       SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,       \
+                                 _mshift, _mwidth, _muxshift, _muxwidth, \
+                                 0, _flags)
+
+
+#define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,           \
+                             _mshift, _mwidth, _gate,                  \
+                             _flags)                                   \
+       struct ccu_div _struct = {                                      \
+               .enable = _gate,                                        \
+               .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_div_ops,     \
+                                                     _flags),          \
+               },                                                      \
+       }
+
+#define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,   \
+                   _flags)                                             \
+       SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,            \
+                             _mshift, _mwidth, 0, _flags)
+
+static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_div, common);
+}
+
+extern const struct clk_ops ccu_div_ops;
+
+#endif /* _CCU_DIV_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c
new file mode 100644 (file)
index 0000000..5c4b10c
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+
+#include "ccu_frac.h"
+
+bool ccu_frac_helper_is_enabled(struct ccu_common *common,
+                               struct _ccu_frac *cf)
+{
+       if (!(common->features & CCU_FEATURE_FRACTIONAL))
+               return false;
+
+       return !(readl(common->base + common->reg) & cf->enable);
+}
+
+void ccu_frac_helper_enable(struct ccu_common *common,
+                           struct _ccu_frac *cf)
+{
+       unsigned long flags;
+       u32 reg;
+
+       if (!(common->features & CCU_FEATURE_FRACTIONAL))
+               return;
+
+       spin_lock_irqsave(common->lock, flags);
+       reg = readl(common->base + common->reg);
+       writel(reg & ~cf->enable, common->base + common->reg);
+       spin_unlock_irqrestore(common->lock, flags);
+}
+
+void ccu_frac_helper_disable(struct ccu_common *common,
+                            struct _ccu_frac *cf)
+{
+       unsigned long flags;
+       u32 reg;
+
+       if (!(common->features & CCU_FEATURE_FRACTIONAL))
+               return;
+
+       spin_lock_irqsave(common->lock, flags);
+       reg = readl(common->base + common->reg);
+       writel(reg | cf->enable, common->base + common->reg);
+       spin_unlock_irqrestore(common->lock, flags);
+}
+
+bool ccu_frac_helper_has_rate(struct ccu_common *common,
+                             struct _ccu_frac *cf,
+                             unsigned long rate)
+{
+       if (!(common->features & CCU_FEATURE_FRACTIONAL))
+               return false;
+
+       return (cf->rates[0] == rate) || (cf->rates[1] == rate);
+}
+
+unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
+                                       struct _ccu_frac *cf)
+{
+       u32 reg;
+
+       printk("%s: Read fractional\n", clk_hw_get_name(&common->hw));
+
+       if (!(common->features & CCU_FEATURE_FRACTIONAL))
+               return 0;
+
+       printk("%s: clock is fractional (rates %lu and %lu)\n",
+              clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]);
+
+       reg = readl(common->base + common->reg);
+
+       printk("%s: clock reg is 0x%x (select is 0x%x)\n",
+              clk_hw_get_name(&common->hw), reg, cf->select);
+
+       return (reg & cf->select) ? cf->rates[1] : cf->rates[0];
+}
+
+int ccu_frac_helper_set_rate(struct ccu_common *common,
+                            struct _ccu_frac *cf,
+                            unsigned long rate)
+{
+       unsigned long flags;
+       u32 reg, sel;
+
+       if (!(common->features & CCU_FEATURE_FRACTIONAL))
+               return -EINVAL;
+
+       if (cf->rates[0] == rate)
+               sel = 0;
+       else if (cf->rates[1] == rate)
+               sel = cf->select;
+       else
+               return -EINVAL;
+
+       spin_lock_irqsave(common->lock, flags);
+       reg = readl(common->base + common->reg);
+       reg &= ~cf->select;
+       writel(reg | sel, common->base + common->reg);
+       spin_unlock_irqrestore(common->lock, flags);
+
+       return 0;
+}
diff --git a/drivers/clk/sunxi-ng/ccu_frac.h b/drivers/clk/sunxi-ng/ccu_frac.h
new file mode 100644 (file)
index 0000000..e4c670b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_FRAC_H_
+#define _CCU_FRAC_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct _ccu_frac {
+       u32             enable;
+       u32             select;
+
+       unsigned long   rates[2];
+};
+
+#define _SUNXI_CCU_FRAC(_enable, _select, _rate1, _rate2)              \
+       {                                                               \
+               .enable = _enable,                                      \
+               .select = _select,                                      \
+               .rates = { _rate1, _rate2 },                            \
+       }
+
+bool ccu_frac_helper_is_enabled(struct ccu_common *common,
+                               struct _ccu_frac *cf);
+void ccu_frac_helper_enable(struct ccu_common *common,
+                           struct _ccu_frac *cf);
+void ccu_frac_helper_disable(struct ccu_common *common,
+                            struct _ccu_frac *cf);
+
+bool ccu_frac_helper_has_rate(struct ccu_common *common,
+                             struct _ccu_frac *cf,
+                             unsigned long rate);
+
+unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
+                                       struct _ccu_frac *cf);
+
+int ccu_frac_helper_set_rate(struct ccu_common *common,
+                            struct _ccu_frac *cf,
+                            unsigned long rate);
+
+#endif /* _CCU_FRAC_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
new file mode 100644 (file)
index 0000000..8a81f9d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+
+void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
+{
+       unsigned long flags;
+       u32 reg;
+
+       if (!gate)
+               return;
+
+       spin_lock_irqsave(common->lock, flags);
+
+       reg = readl(common->base + common->reg);
+       writel(reg & ~gate, common->base + common->reg);
+
+       spin_unlock_irqrestore(common->lock, flags);
+}
+
+static void ccu_gate_disable(struct clk_hw *hw)
+{
+       struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+       return ccu_gate_helper_disable(&cg->common, cg->enable);
+}
+
+int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
+{
+       unsigned long flags;
+       u32 reg;
+
+       if (!gate)
+               return 0;
+
+       spin_lock_irqsave(common->lock, flags);
+
+       reg = readl(common->base + common->reg);
+       writel(reg | gate, common->base + common->reg);
+
+       spin_unlock_irqrestore(common->lock, flags);
+
+       return 0;
+}
+
+static int ccu_gate_enable(struct clk_hw *hw)
+{
+       struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+       return ccu_gate_helper_enable(&cg->common, cg->enable);
+}
+
+int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)
+{
+       if (!gate)
+               return 1;
+
+       return readl(common->base + common->reg) & gate;
+}
+
+static int ccu_gate_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+       return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
+}
+
+const struct clk_ops ccu_gate_ops = {
+       .disable        = ccu_gate_disable,
+       .enable         = ccu_gate_enable,
+       .is_enabled     = ccu_gate_is_enabled,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_gate.h b/drivers/clk/sunxi-ng/ccu_gate.h
new file mode 100644 (file)
index 0000000..4466169
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_GATE_H_
+#define _CCU_GATE_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct ccu_gate {
+       u32                     enable;
+
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_GATE(_struct, _name, _parent, _reg, _gate, _flags)   \
+       struct ccu_gate _struct = {                                     \
+               .enable = _gate,                                        \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_gate_ops,    \
+                                                     _flags),          \
+               }                                                       \
+       }
+
+static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_gate, common);
+}
+
+void ccu_gate_helper_disable(struct ccu_common *common, u32 gate);
+int ccu_gate_helper_enable(struct ccu_common *common, u32 gate);
+int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate);
+
+extern const struct clk_ops ccu_gate_ops;
+
+#endif /* _CCU_GATE_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
new file mode 100644 (file)
index 0000000..cbf33ef
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+
+static void ccu_mp_find_best(unsigned long parent, unsigned long rate,
+                            unsigned int max_m, unsigned int max_p,
+                            unsigned int *m, unsigned int *p)
+{
+       unsigned long best_rate = 0;
+       unsigned int best_m = 0, best_p = 0;
+       unsigned int _m, _p;
+
+       for (_p = 0; _p <= max_p; _p++) {
+               for (_m = 1; _m <= max_m; _m++) {
+                       unsigned long tmp_rate = (parent >> _p) / _m;
+
+                       if (tmp_rate > rate)
+                               continue;
+
+                       if ((rate - tmp_rate) < (rate - best_rate)) {
+                               best_rate = tmp_rate;
+                               best_m = _m;
+                               best_p = _p;
+                       }
+               }
+       }
+
+       *m = best_m;
+       *p = best_p;
+}
+
+static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
+                                      unsigned long parent_rate,
+                                      unsigned long rate,
+                                      void *data)
+{
+       struct ccu_mp *cmp = data;
+       unsigned int m, p;
+
+       ccu_mp_find_best(parent_rate, rate,
+                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
+                        &m, &p);
+
+       return (parent_rate >> p) / m;
+}
+
+static void ccu_mp_disable(struct clk_hw *hw)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+       return ccu_gate_helper_disable(&cmp->common, cmp->enable);
+}
+
+static int ccu_mp_enable(struct clk_hw *hw)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+       return ccu_gate_helper_enable(&cmp->common, cmp->enable);
+}
+
+static int ccu_mp_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+       return ccu_gate_helper_is_enabled(&cmp->common, cmp->enable);
+}
+
+static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+       unsigned int m, p;
+       u32 reg;
+
+       reg = readl(cmp->common.base + cmp->common.reg);
+
+       m = reg >> cmp->m.shift;
+       m &= (1 << cmp->m.width) - 1;
+
+       p = reg >> cmp->p.shift;
+       p &= (1 << cmp->p.width) - 1;
+
+       return (parent_rate >> p) / (m + 1);
+}
+
+static int ccu_mp_determine_rate(struct clk_hw *hw,
+                                struct clk_rate_request *req)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+       return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux,
+                                            req, ccu_mp_round_rate, cmp);
+}
+
+static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
+                          unsigned long parent_rate)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+       unsigned long flags;
+       unsigned int m, p;
+       u32 reg;
+
+       ccu_mp_find_best(parent_rate, rate,
+                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
+                        &m, &p);
+
+
+       spin_lock_irqsave(cmp->common.lock, flags);
+
+       reg = readl(cmp->common.base + cmp->common.reg);
+       reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
+       reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
+
+       writel(reg | (p << cmp->p.shift) | ((m - 1) << cmp->m.shift),
+              cmp->common.base + cmp->common.reg);
+
+       spin_unlock_irqrestore(cmp->common.lock, flags);
+
+       return 0;
+}
+
+static u8 ccu_mp_get_parent(struct clk_hw *hw)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+       return ccu_mux_helper_get_parent(&cmp->common, &cmp->mux);
+}
+
+static int ccu_mp_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+       return ccu_mux_helper_set_parent(&cmp->common, &cmp->mux, index);
+}
+
+const struct clk_ops ccu_mp_ops = {
+       .disable        = ccu_mp_disable,
+       .enable         = ccu_mp_enable,
+       .is_enabled     = ccu_mp_is_enabled,
+
+       .get_parent     = ccu_mp_get_parent,
+       .set_parent     = ccu_mp_set_parent,
+
+       .determine_rate = ccu_mp_determine_rate,
+       .recalc_rate    = ccu_mp_recalc_rate,
+       .set_rate       = ccu_mp_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
new file mode 100644 (file)
index 0000000..3cf12bf
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_MP_H_
+#define _CCU_MP_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_mult.h"
+#include "ccu_mux.h"
+
+/*
+ * struct ccu_mp - Definition of an M-P clock
+ *
+ * Clocks based on the formula parent >> P / M
+ */
+struct ccu_mp {
+       u32                     enable;
+
+       struct _ccu_div         m;
+       struct _ccu_div         p;
+       struct ccu_mux_internal mux;
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,     \
+                                  _mshift, _mwidth,                    \
+                                  _pshift, _pwidth,                    \
+                                  _muxshift, _muxwidth,                \
+                                  _gate, _flags)                       \
+       struct ccu_mp _struct = {                                       \
+               .enable = _gate,                                        \
+               .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
+               .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
+               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
+                                                             _parents, \
+                                                             &ccu_mp_ops, \
+                                                             _flags),  \
+               }                                                       \
+       }
+
+#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,          \
+                             _mshift, _mwidth,                         \
+                             _pshift, _pwidth,                         \
+                             _muxshift, _muxwidth,                     \
+                             _flags)                                   \
+       SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
+                                  _mshift, _mwidth,                    \
+                                  _pshift, _pwidth,                    \
+                                  _muxshift, _muxwidth,                \
+                                  0, _flags)
+
+static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_mp, common);
+}
+
+extern const struct clk_ops ccu_mp_ops;
+
+#endif /* _CCU_MP_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mult.h b/drivers/clk/sunxi-ng/ccu_mult.h
new file mode 100644 (file)
index 0000000..609db66
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _CCU_MULT_H_
+#define _CCU_MULT_H_
+
+struct _ccu_mult {
+       u8      shift;
+       u8      width;
+};
+
+#define _SUNXI_CCU_MULT(_shift, _width)                \
+       {                                       \
+               .shift  = _shift,               \
+               .width  = _width,               \
+       }
+
+#endif /* _CCU_MULT_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
new file mode 100644 (file)
index 0000000..58fc36e
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_mux.h"
+
+void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
+                                            struct ccu_mux_internal *cm,
+                                            int parent_index,
+                                            unsigned long *parent_rate)
+{
+       u8 prediv = 1;
+       u32 reg;
+
+       if (!((common->features & CCU_FEATURE_FIXED_PREDIV) ||
+             (common->features & CCU_FEATURE_VARIABLE_PREDIV)))
+               return;
+
+       reg = readl(common->base + common->reg);
+       if (parent_index < 0) {
+               parent_index = reg >> cm->shift;
+               parent_index &= (1 << cm->width) - 1;
+       }
+
+       if (common->features & CCU_FEATURE_FIXED_PREDIV)
+               if (parent_index == cm->fixed_prediv.index)
+                       prediv = cm->fixed_prediv.div;
+
+       if (common->features & CCU_FEATURE_VARIABLE_PREDIV)
+               if (parent_index == cm->variable_prediv.index) {
+                       u8 div;
+
+                       div = reg >> cm->variable_prediv.shift;
+                       div &= (1 << cm->variable_prediv.width) - 1;
+                       prediv = div + 1;
+               }
+
+       *parent_rate = *parent_rate / prediv;
+}
+
+int ccu_mux_helper_determine_rate(struct ccu_common *common,
+                                 struct ccu_mux_internal *cm,
+                                 struct clk_rate_request *req,
+                                 unsigned long (*round)(struct ccu_mux_internal *,
+                                                        unsigned long,
+                                                        unsigned long,
+                                                        void *),
+                                 void *data)
+{
+       unsigned long best_parent_rate = 0, best_rate = 0;
+       struct clk_hw *best_parent, *hw = &common->hw;
+       unsigned int i;
+
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+               unsigned long tmp_rate, parent_rate;
+               struct clk_hw *parent;
+
+               parent = clk_hw_get_parent_by_index(hw, i);
+               if (!parent)
+                       continue;
+
+               parent_rate = clk_hw_get_rate(parent);
+               ccu_mux_helper_adjust_parent_for_prediv(common, cm, i,
+                                                       &parent_rate);
+
+               tmp_rate = round(cm, clk_hw_get_rate(parent), req->rate, data);
+               if (tmp_rate == req->rate) {
+                       best_parent = parent;
+                       best_parent_rate = parent_rate;
+                       best_rate = tmp_rate;
+                       goto out;
+               }
+
+               if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
+                       best_rate = tmp_rate;
+                       best_parent_rate = parent_rate;
+                       best_parent = parent;
+               }
+       }
+
+       if (best_rate == 0)
+               return -EINVAL;
+
+out:
+       req->best_parent_hw = best_parent;
+       req->best_parent_rate = best_parent_rate;
+       req->rate = best_rate;
+       return 0;
+}
+
+u8 ccu_mux_helper_get_parent(struct ccu_common *common,
+                            struct ccu_mux_internal *cm)
+{
+       u32 reg;
+       u8 parent;
+
+       reg = readl(common->base + common->reg);
+       parent = reg >> cm->shift;
+       parent &= (1 << cm->width) - 1;
+
+       return parent;
+}
+
+int ccu_mux_helper_set_parent(struct ccu_common *common,
+                             struct ccu_mux_internal *cm,
+                             u8 index)
+{
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(common->lock, flags);
+
+       reg = readl(common->base + common->reg);
+       reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
+       writel(reg | (index << cm->shift), common->base + common->reg);
+
+       spin_unlock_irqrestore(common->lock, flags);
+
+       return 0;
+}
+
+static void ccu_mux_disable(struct clk_hw *hw)
+{
+       struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+       return ccu_gate_helper_disable(&cm->common, cm->enable);
+}
+
+static int ccu_mux_enable(struct clk_hw *hw)
+{
+       struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+       return ccu_gate_helper_enable(&cm->common, cm->enable);
+}
+
+static int ccu_mux_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+       return ccu_gate_helper_is_enabled(&cm->common, cm->enable);
+}
+
+static u8 ccu_mux_get_parent(struct clk_hw *hw)
+{
+       struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+       return ccu_mux_helper_get_parent(&cm->common, &cm->mux);
+}
+
+static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+       return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
+}
+
+static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+       ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
+                                               &parent_rate);
+
+       return parent_rate;
+}
+
+const struct clk_ops ccu_mux_ops = {
+       .disable        = ccu_mux_disable,
+       .enable         = ccu_mux_enable,
+       .is_enabled     = ccu_mux_is_enabled,
+
+       .get_parent     = ccu_mux_get_parent,
+       .set_parent     = ccu_mux_set_parent,
+
+       .determine_rate = __clk_mux_determine_rate,
+       .recalc_rate    = ccu_mux_recalc_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
new file mode 100644 (file)
index 0000000..9450826
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _CCU_MUX_H_
+#define _CCU_MUX_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct ccu_mux_internal {
+       u8      shift;
+       u8      width;
+
+       struct {
+               u8      index;
+               u8      div;
+       } fixed_prediv;
+
+       struct {
+               u8      index;
+               u8      shift;
+               u8      width;
+       } variable_prediv;
+};
+
+#define SUNXI_CLK_MUX(_shift, _width)  \
+       {                                       \
+               .shift  = _shift,               \
+               .width  = _width,               \
+       }
+
+struct ccu_mux {
+       u16                     reg;
+       u32                     enable;
+
+       struct ccu_mux_internal mux;
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width, _flags) \
+       struct ccu_mux _struct = {                                      \
+               .mux    = SUNXI_CLK_MUX(_shift, _width),                \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
+                                                             _parents, \
+                                                             &ccu_mux_ops, \
+                                                             _flags),  \
+               }                                                       \
+       }
+
+#define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,                \
+                               _shift, _width, _gate, _flags)          \
+       struct ccu_mux _struct = {                                      \
+               .enable = _gate,                                        \
+               .mux    = SUNXI_CLK_MUX(_shift, _width),                \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
+                                                             _parents, \
+                                                             &ccu_mux_ops, \
+                                                             _flags),  \
+               }                                                       \
+       }
+
+static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_mux, common);
+}
+
+extern const struct clk_ops ccu_mux_ops;
+
+void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
+                                            struct ccu_mux_internal *cm,
+                                            int parent_index,
+                                            unsigned long *parent_rate);
+int ccu_mux_helper_determine_rate(struct ccu_common *common,
+                                 struct ccu_mux_internal *cm,
+                                 struct clk_rate_request *req,
+                                 unsigned long (*round)(struct ccu_mux_internal *,
+                                                        unsigned long,
+                                                        unsigned long,
+                                                        void *),
+                                 void *data);
+u8 ccu_mux_helper_get_parent(struct ccu_common *common,
+                            struct ccu_mux_internal *cm);
+int ccu_mux_helper_set_parent(struct ccu_common *common,
+                             struct ccu_mux_internal *cm,
+                             u8 index);
+
+#endif /* _CCU_MUX_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
new file mode 100644 (file)
index 0000000..4470ffc
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nk.h"
+
+void ccu_nk_find_best(unsigned long parent, unsigned long rate,
+                     unsigned int max_n, unsigned int max_k,
+                     unsigned int *n, unsigned int *k)
+{
+       unsigned long best_rate = 0;
+       unsigned int best_k = 0, best_n = 0;
+       unsigned int _k, _n;
+
+       for (_k = 1; _k <= max_k; _k++) {
+               for (_n = 1; _n <= max_n; _n++) {
+                       unsigned long tmp_rate = parent * _n * _k;
+
+                       if (tmp_rate > rate)
+                               continue;
+
+                       if ((rate - tmp_rate) < (rate - best_rate)) {
+                               best_rate = tmp_rate;
+                               best_k = _k;
+                               best_n = _n;
+                       }
+               }
+       }
+
+       *k = best_k;
+       *n = best_n;
+}
+
+static void ccu_nk_disable(struct clk_hw *hw)
+{
+       struct ccu_nk *nk = hw_to_ccu_nk(hw);
+
+       return ccu_gate_helper_disable(&nk->common, nk->enable);
+}
+
+static int ccu_nk_enable(struct clk_hw *hw)
+{
+       struct ccu_nk *nk = hw_to_ccu_nk(hw);
+
+       return ccu_gate_helper_enable(&nk->common, nk->enable);
+}
+
+static int ccu_nk_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_nk *nk = hw_to_ccu_nk(hw);
+
+       return ccu_gate_helper_is_enabled(&nk->common, nk->enable);
+}
+
+static unsigned long ccu_nk_recalc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       struct ccu_nk *nk = hw_to_ccu_nk(hw);
+       unsigned long rate, n, k;
+       u32 reg;
+
+       reg = readl(nk->common.base + nk->common.reg);
+
+       n = reg >> nk->n.shift;
+       n &= (1 << nk->n.width) - 1;
+
+       k = reg >> nk->k.shift;
+       k &= (1 << nk->k.width) - 1;
+
+       rate = parent_rate * (n + 1) * (k + 1);
+
+       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate /= nk->fixed_post_div;
+
+       return rate;
+}
+
+static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long *parent_rate)
+{
+       struct ccu_nk *nk = hw_to_ccu_nk(hw);
+       unsigned int n, k;
+
+       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate *= nk->fixed_post_div;
+
+       ccu_nk_find_best(*parent_rate, rate,
+                        1 << nk->n.width, 1 << nk->k.width,
+                        &n, &k);
+
+       rate = *parent_rate * n * k;
+       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate = rate / nk->fixed_post_div;
+
+       return rate;
+}
+
+static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
+                          unsigned long parent_rate)
+{
+       struct ccu_nk *nk = hw_to_ccu_nk(hw);
+       unsigned long flags;
+       unsigned int n, k;
+       u32 reg;
+
+       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate = rate * nk->fixed_post_div;
+
+       ccu_nk_find_best(parent_rate, rate,
+                        1 << nk->n.width, 1 << nk->k.width,
+                        &n, &k);
+
+       spin_lock_irqsave(nk->common.lock, flags);
+
+       reg = readl(nk->common.base + nk->common.reg);
+       reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift);
+       reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift);
+
+       writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift),
+              nk->common.base + nk->common.reg);
+
+       spin_unlock_irqrestore(nk->common.lock, flags);
+
+       ccu_helper_wait_for_lock(&nk->common, nk->lock);
+
+       return 0;
+}
+
+const struct clk_ops ccu_nk_ops = {
+       .disable        = ccu_nk_disable,
+       .enable         = ccu_nk_enable,
+       .is_enabled     = ccu_nk_is_enabled,
+
+       .recalc_rate    = ccu_nk_recalc_rate,
+       .round_rate     = ccu_nk_round_rate,
+       .set_rate       = ccu_nk_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nk.h b/drivers/clk/sunxi-ng/ccu_nk.h
new file mode 100644 (file)
index 0000000..4b52da0
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_NK_H_
+#define _CCU_NK_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_mult.h"
+
+/*
+ * struct ccu_nk - Definition of an N-K clock
+ *
+ * Clocks based on the formula parent * N * K
+ */
+struct ccu_nk {
+       u16                     reg;
+       u32                     enable;
+       u32                     lock;
+
+       struct _ccu_mult        n;
+       struct _ccu_mult        k;
+
+       unsigned int            fixed_post_div;
+
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(_struct, _name, _parent, _reg, \
+                                           _nshift, _nwidth,           \
+                                           _kshift, _kwidth,           \
+                                           _gate, _lock, _postdiv,     \
+                                           _flags)                     \
+       struct ccu_nk _struct = {                                       \
+               .enable         = _gate,                                \
+               .lock           = _lock,                                \
+               .k              = _SUNXI_CCU_MULT(_kshift, _kwidth),    \
+               .n              = _SUNXI_CCU_MULT(_nshift, _nwidth),    \
+               .fixed_post_div = _postdiv,                             \
+               .common         = {                                     \
+                       .reg            = _reg,                         \
+                       .features       = CCU_FEATURE_FIXED_POSTDIV,    \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_nk_ops,      \
+                                                     _flags),          \
+               },                                                      \
+       }
+
+static inline struct ccu_nk *hw_to_ccu_nk(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_nk, common);
+}
+
+extern const struct clk_ops ccu_nk_ops;
+
+#endif /* _CCU_NK_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
new file mode 100644 (file)
index 0000000..2071822
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nkm.h"
+
+struct _ccu_nkm {
+       unsigned long   n, max_n;
+       unsigned long   k, max_k;
+       unsigned long   m, max_m;
+};
+
+static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
+                             struct _ccu_nkm *nkm)
+{
+       unsigned long best_rate = 0;
+       unsigned long best_n = 0, best_k = 0, best_m = 0;
+       unsigned long _n, _k, _m;
+
+       for (_k = 1; _k <= nkm->max_k; _k++) {
+               unsigned long tmp_rate;
+
+               rational_best_approximation(rate / _k, parent,
+                                           nkm->max_n, nkm->max_m, &_n, &_m);
+
+               tmp_rate = parent * _n * _k / _m;
+
+               if (tmp_rate > rate)
+                       continue;
+
+               if ((rate - tmp_rate) < (rate - best_rate)) {
+                       best_rate = tmp_rate;
+                       best_n = _n;
+                       best_k = _k;
+                       best_m = _m;
+               }
+       }
+
+       nkm->n = best_n;
+       nkm->k = best_k;
+       nkm->m = best_m;
+}
+
+static void ccu_nkm_disable(struct clk_hw *hw)
+{
+       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+
+       return ccu_gate_helper_disable(&nkm->common, nkm->enable);
+}
+
+static int ccu_nkm_enable(struct clk_hw *hw)
+{
+       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+
+       return ccu_gate_helper_enable(&nkm->common, nkm->enable);
+}
+
+static int ccu_nkm_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+
+       return ccu_gate_helper_is_enabled(&nkm->common, nkm->enable);
+}
+
+static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+       unsigned long n, m, k;
+       u32 reg;
+
+       reg = readl(nkm->common.base + nkm->common.reg);
+
+       n = reg >> nkm->n.shift;
+       n &= (1 << nkm->n.width) - 1;
+
+       k = reg >> nkm->k.shift;
+       k &= (1 << nkm->k.width) - 1;
+
+       m = reg >> nkm->m.shift;
+       m &= (1 << nkm->m.width) - 1;
+
+       return parent_rate * (n + 1) * (k + 1) / (m + 1);
+}
+
+static long ccu_nkm_round_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long *parent_rate)
+{
+       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+       struct _ccu_nkm _nkm;
+
+       _nkm.max_n = 1 << nkm->n.width;
+       _nkm.max_k = 1 << nkm->k.width;
+       _nkm.max_m = 1 << nkm->m.width;
+
+       ccu_nkm_find_best(*parent_rate, rate, &_nkm);
+
+       return *parent_rate * _nkm.n * _nkm.k / _nkm.m;
+}
+
+static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
+                          unsigned long parent_rate)
+{
+       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+       struct _ccu_nkm _nkm;
+       unsigned long flags;
+       u32 reg;
+
+       _nkm.max_n = 1 << nkm->n.width;
+       _nkm.max_k = 1 << nkm->k.width;
+       _nkm.max_m = 1 << nkm->m.width;
+
+       ccu_nkm_find_best(parent_rate, rate, &_nkm);
+
+       spin_lock_irqsave(nkm->common.lock, flags);
+
+       reg = readl(nkm->common.base + nkm->common.reg);
+       reg &= ~GENMASK(nkm->n.width + nkm->n.shift - 1, nkm->n.shift);
+       reg &= ~GENMASK(nkm->k.width + nkm->k.shift - 1, nkm->k.shift);
+       reg &= ~GENMASK(nkm->m.width + nkm->m.shift - 1, nkm->m.shift);
+
+       reg |= (_nkm.n - 1) << nkm->n.shift;
+       reg |= (_nkm.k - 1) << nkm->k.shift;
+       reg |= (_nkm.m - 1) << nkm->m.shift;
+
+       writel(reg, nkm->common.base + nkm->common.reg);
+
+       spin_unlock_irqrestore(nkm->common.lock, flags);
+
+       ccu_helper_wait_for_lock(&nkm->common, nkm->lock);
+
+       return 0;
+}
+
+const struct clk_ops ccu_nkm_ops = {
+       .disable        = ccu_nkm_disable,
+       .enable         = ccu_nkm_enable,
+       .is_enabled     = ccu_nkm_is_enabled,
+
+       .recalc_rate    = ccu_nkm_recalc_rate,
+       .round_rate     = ccu_nkm_round_rate,
+       .set_rate       = ccu_nkm_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
new file mode 100644 (file)
index 0000000..1936ac1
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_NKM_H_
+#define _CCU_NKM_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_mult.h"
+
+/*
+ * struct ccu_nkm - Definition of an N-K-M clock
+ *
+ * Clocks based on the formula parent * N * K / M
+ */
+struct ccu_nkm {
+       u32                     enable;
+       u32                     lock;
+
+       struct _ccu_mult        n;
+       struct _ccu_mult        k;
+       struct _ccu_div         m;
+
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_NKM_WITH_GATE_LOCK(_struct, _name, _parent, _reg,    \
+                                    _nshift, _nwidth,                  \
+                                    _kshift, _kwidth,                  \
+                                    _mshift, _mwidth,                  \
+                                    _gate, _lock, _flags)              \
+       struct ccu_nkm _struct = {                                      \
+               .enable         = _gate,                                \
+               .lock           = _lock,                                \
+               .k              = _SUNXI_CCU_MULT(_kshift, _kwidth),    \
+               .n              = _SUNXI_CCU_MULT(_nshift, _nwidth),    \
+               .m              = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
+               .common         = {                                     \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_nkm_ops,     \
+                                                     _flags),          \
+               },                                                      \
+       }
+
+static inline struct ccu_nkm *hw_to_ccu_nkm(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_nkm, common);
+}
+
+extern const struct clk_ops ccu_nkm_ops;
+
+#endif /* _CCU_NKM_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
new file mode 100644 (file)
index 0000000..9f2b98e
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nkmp.h"
+
+struct _ccu_nkmp {
+       unsigned long   n, max_n;
+       unsigned long   k, max_k;
+       unsigned long   m, max_m;
+       unsigned long   p, max_p;
+};
+
+static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
+                              struct _ccu_nkmp *nkmp)
+{
+       unsigned long best_rate = 0;
+       unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
+       unsigned long _n, _k, _m, _p;
+
+       for (_k = 1; _k <= nkmp->max_k; _k++) {
+               for (_p = 0; _p <= nkmp->max_p; _p++) {
+                       unsigned long tmp_rate;
+
+                       rational_best_approximation(rate / _k, parent >> _p,
+                                                   nkmp->max_n, nkmp->max_m,
+                                                   &_n, &_m);
+
+                       tmp_rate = (parent * _n * _k >> _p) / _m;
+
+                       if (tmp_rate > rate)
+                               continue;
+
+                       if ((rate - tmp_rate) < (rate - best_rate)) {
+                               best_rate = tmp_rate;
+                               best_n = _n;
+                               best_k = _k;
+                               best_m = _m;
+                               best_p = _p;
+                       }
+               }
+       }
+
+       nkmp->n = best_n;
+       nkmp->k = best_k;
+       nkmp->m = best_m;
+       nkmp->p = best_p;
+}
+
+static void ccu_nkmp_disable(struct clk_hw *hw)
+{
+       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+
+       return ccu_gate_helper_disable(&nkmp->common, nkmp->enable);
+}
+
+static int ccu_nkmp_enable(struct clk_hw *hw)
+{
+       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+
+       return ccu_gate_helper_enable(&nkmp->common, nkmp->enable);
+}
+
+static int ccu_nkmp_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+
+       return ccu_gate_helper_is_enabled(&nkmp->common, nkmp->enable);
+}
+
+static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+       unsigned long n, m, k, p;
+       u32 reg;
+
+       reg = readl(nkmp->common.base + nkmp->common.reg);
+
+       n = reg >> nkmp->n.shift;
+       n &= (1 << nkmp->n.width) - 1;
+
+       k = reg >> nkmp->k.shift;
+       k &= (1 << nkmp->k.width) - 1;
+
+       m = reg >> nkmp->m.shift;
+       m &= (1 << nkmp->m.width) - 1;
+
+       p = reg >> nkmp->p.shift;
+       p &= (1 << nkmp->p.width) - 1;
+
+       return (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1);
+}
+
+static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long *parent_rate)
+{
+       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+       struct _ccu_nkmp _nkmp;
+
+       _nkmp.max_n = 1 << nkmp->n.width;
+       _nkmp.max_k = 1 << nkmp->k.width;
+       _nkmp.max_m = 1 << nkmp->m.width;
+       _nkmp.max_p = (1 << nkmp->p.width) - 1;
+
+       ccu_nkmp_find_best(*parent_rate, rate,
+                          &_nkmp);
+
+       return (*parent_rate * _nkmp.n * _nkmp.k >> _nkmp.p) / _nkmp.m;
+}
+
+static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
+                          unsigned long parent_rate)
+{
+       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+       struct _ccu_nkmp _nkmp;
+       unsigned long flags;
+       u32 reg;
+
+       _nkmp.max_n = 1 << nkmp->n.width;
+       _nkmp.max_k = 1 << nkmp->k.width;
+       _nkmp.max_m = 1 << nkmp->m.width;
+       _nkmp.max_p = (1 << nkmp->p.width) - 1;
+
+       ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
+
+       spin_lock_irqsave(nkmp->common.lock, flags);
+
+       reg = readl(nkmp->common.base + nkmp->common.reg);
+       reg &= ~GENMASK(nkmp->n.width + nkmp->n.shift - 1, nkmp->n.shift);
+       reg &= ~GENMASK(nkmp->k.width + nkmp->k.shift - 1, nkmp->k.shift);
+       reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift);
+       reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift);
+
+       reg |= (_nkmp.n - 1) << nkmp->n.shift;
+       reg |= (_nkmp.k - 1) << nkmp->k.shift;
+       reg |= (_nkmp.m - 1) << nkmp->m.shift;
+       reg |= _nkmp.p << nkmp->p.shift;
+
+       writel(reg, nkmp->common.base + nkmp->common.reg);
+
+       spin_unlock_irqrestore(nkmp->common.lock, flags);
+
+       ccu_helper_wait_for_lock(&nkmp->common, nkmp->lock);
+
+       return 0;
+}
+
+const struct clk_ops ccu_nkmp_ops = {
+       .disable        = ccu_nkmp_disable,
+       .enable         = ccu_nkmp_enable,
+       .is_enabled     = ccu_nkmp_is_enabled,
+
+       .recalc_rate    = ccu_nkmp_recalc_rate,
+       .round_rate     = ccu_nkmp_round_rate,
+       .set_rate       = ccu_nkmp_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h
new file mode 100644 (file)
index 0000000..5adb0c9
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_NKMP_H_
+#define _CCU_NKMP_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_mult.h"
+
+/*
+ * struct ccu_nkmp - Definition of an N-K-M-P clock
+ *
+ * Clocks based on the formula parent * N * K >> P / M
+ */
+struct ccu_nkmp {
+       u32                     enable;
+       u32                     lock;
+
+       struct _ccu_mult        n;
+       struct _ccu_mult        k;
+       struct _ccu_div         m;
+       struct _ccu_div         p;
+
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_NKMP_WITH_GATE_LOCK(_struct, _name, _parent, _reg,   \
+                                     _nshift, _nwidth,                 \
+                                     _kshift, _kwidth,                 \
+                                     _mshift, _mwidth,                 \
+                                     _pshift, _pwidth,                 \
+                                     _gate, _lock, _flags)             \
+       struct ccu_nkmp _struct = {                                     \
+               .enable         = _gate,                                \
+               .lock           = _lock,                                \
+               .n              = _SUNXI_CCU_MULT(_nshift, _nwidth),    \
+               .k              = _SUNXI_CCU_MULT(_kshift, _kwidth),    \
+               .m              = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
+               .p              = _SUNXI_CCU_DIV(_pshift, _pwidth),     \
+               .common         = {                                     \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_nkmp_ops,    \
+                                                     _flags),          \
+               },                                                      \
+       }
+
+static inline struct ccu_nkmp *hw_to_ccu_nkmp(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_nkmp, common);
+}
+
+extern const struct clk_ops ccu_nkmp_ops;
+
+#endif /* _CCU_NKMP_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
new file mode 100644 (file)
index 0000000..e35ddd8
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_frac.h"
+#include "ccu_gate.h"
+#include "ccu_nm.h"
+
+static void ccu_nm_disable(struct clk_hw *hw)
+{
+       struct ccu_nm *nm = hw_to_ccu_nm(hw);
+
+       return ccu_gate_helper_disable(&nm->common, nm->enable);
+}
+
+static int ccu_nm_enable(struct clk_hw *hw)
+{
+       struct ccu_nm *nm = hw_to_ccu_nm(hw);
+
+       return ccu_gate_helper_enable(&nm->common, nm->enable);
+}
+
+static int ccu_nm_is_enabled(struct clk_hw *hw)
+{
+       struct ccu_nm *nm = hw_to_ccu_nm(hw);
+
+       return ccu_gate_helper_is_enabled(&nm->common, nm->enable);
+}
+
+static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       struct ccu_nm *nm = hw_to_ccu_nm(hw);
+       unsigned long n, m;
+       u32 reg;
+
+       if (ccu_frac_helper_is_enabled(&nm->common, &nm->frac))
+               return ccu_frac_helper_read_rate(&nm->common, &nm->frac);
+
+       reg = readl(nm->common.base + nm->common.reg);
+
+       n = reg >> nm->n.shift;
+       n &= (1 << nm->n.width) - 1;
+
+       m = reg >> nm->m.shift;
+       m &= (1 << nm->m.width) - 1;
+
+       return parent_rate * (n + 1) / (m + 1);
+}
+
+static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long *parent_rate)
+{
+       struct ccu_nm *nm = hw_to_ccu_nm(hw);
+       unsigned long n, m;
+
+       rational_best_approximation(rate, *parent_rate,
+                                   1 << nm->n.width, 1 << nm->m.width,
+                                   &n, &m);
+
+       return *parent_rate * n / m;
+}
+
+static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
+                          unsigned long parent_rate)
+{
+       struct ccu_nm *nm = hw_to_ccu_nm(hw);
+       unsigned long flags;
+       unsigned long n, m;
+       u32 reg;
+
+       if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
+               return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate);
+       else
+               ccu_frac_helper_disable(&nm->common, &nm->frac);
+
+       rational_best_approximation(rate, parent_rate,
+                                   1 << nm->n.width, 1 << nm->m.width,
+                                   &n, &m);
+
+       spin_lock_irqsave(nm->common.lock, flags);
+
+       reg = readl(nm->common.base + nm->common.reg);
+       reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift);
+       reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift);
+
+       writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift),
+              nm->common.base + nm->common.reg);
+
+       spin_unlock_irqrestore(nm->common.lock, flags);
+
+       ccu_helper_wait_for_lock(&nm->common, nm->lock);
+
+       return 0;
+}
+
+const struct clk_ops ccu_nm_ops = {
+       .disable        = ccu_nm_disable,
+       .enable         = ccu_nm_enable,
+       .is_enabled     = ccu_nm_is_enabled,
+
+       .recalc_rate    = ccu_nm_recalc_rate,
+       .round_rate     = ccu_nm_round_rate,
+       .set_rate       = ccu_nm_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
new file mode 100644 (file)
index 0000000..0b7bcd3
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_NM_H_
+#define _CCU_NM_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_frac.h"
+#include "ccu_mult.h"
+
+/*
+ * struct ccu_nm - Definition of an N-M clock
+ *
+ * Clocks based on the formula parent * N / M
+ */
+struct ccu_nm {
+       u32                     enable;
+       u32                     lock;
+
+       struct _ccu_mult        n;
+       struct _ccu_div         m;
+       struct _ccu_frac        frac;
+
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(_struct, _name, _parent, _reg,        \
+                                        _nshift, _nwidth,              \
+                                        _mshift, _mwidth,              \
+                                        _frac_en, _frac_sel,           \
+                                        _frac_rate_0, _frac_rate_1,    \
+                                        _gate, _lock, _flags)          \
+       struct ccu_nm _struct = {                                       \
+               .enable         = _gate,                                \
+               .lock           = _lock,                                \
+               .n              = _SUNXI_CCU_MULT(_nshift, _nwidth),    \
+               .m              = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
+               .frac           = _SUNXI_CCU_FRAC(_frac_en, _frac_sel,  \
+                                                 _frac_rate_0,         \
+                                                 _frac_rate_1),        \
+               .common         = {                                     \
+                       .reg            = _reg,                         \
+                       .features       = CCU_FEATURE_FRACTIONAL,       \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_nm_ops,      \
+                                                     _flags),          \
+               },                                                      \
+       }
+
+#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg,     \
+                                   _nshift, _nwidth,                   \
+                                   _mshift, _mwidth,                   \
+                                   _gate, _lock, _flags)               \
+       struct ccu_nm _struct = {                                       \
+               .enable         = _gate,                                \
+               .lock           = _lock,                                \
+               .n              = _SUNXI_CCU_MULT(_nshift, _nwidth),    \
+               .m              = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
+               .common         = {                                     \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_nm_ops,      \
+                                                     _flags),          \
+               },                                                      \
+       }
+
+static inline struct ccu_nm *hw_to_ccu_nm(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_nm, common);
+}
+
+extern const struct clk_ops ccu_nm_ops;
+
+#endif /* _CCU_NM_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_phase.c b/drivers/clk/sunxi-ng/ccu_phase.c
new file mode 100644 (file)
index 0000000..400c58a
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+
+#include "ccu_phase.h"
+
+static int ccu_phase_get_phase(struct clk_hw *hw)
+{
+       struct ccu_phase *phase = hw_to_ccu_phase(hw);
+       struct clk_hw *parent, *grandparent;
+       unsigned int parent_rate, grandparent_rate;
+       u16 step, parent_div;
+       u32 reg;
+       u8 delay;
+
+       reg = readl(phase->common.base + phase->common.reg);
+       delay = (reg >> phase->shift);
+       delay &= (1 << phase->width) - 1;
+
+       if (!delay)
+               return 180;
+
+       /* Get our parent clock, it's the one that can adjust its rate */
+       parent = clk_hw_get_parent(hw);
+       if (!parent)
+               return -EINVAL;
+
+       /* And its rate */
+       parent_rate = clk_hw_get_rate(parent);
+       if (!parent_rate)
+               return -EINVAL;
+
+       /* Now, get our parent's parent (most likely some PLL) */
+       grandparent = clk_hw_get_parent(parent);
+       if (!grandparent)
+               return -EINVAL;
+
+       /* And its rate */
+       grandparent_rate = clk_hw_get_rate(grandparent);
+       if (!grandparent_rate)
+               return -EINVAL;
+
+       /* Get our parent clock divider */
+       parent_div = grandparent_rate / parent_rate;
+
+       step = DIV_ROUND_CLOSEST(360, parent_div);
+       return delay * step;
+}
+
+static int ccu_phase_set_phase(struct clk_hw *hw, int degrees)
+{
+       struct ccu_phase *phase = hw_to_ccu_phase(hw);
+       struct clk_hw *parent, *grandparent;
+       unsigned int parent_rate, grandparent_rate;
+       unsigned long flags;
+       u32 reg;
+       u8 delay;
+
+       /* Get our parent clock, it's the one that can adjust its rate */
+       parent = clk_hw_get_parent(hw);
+       if (!parent)
+               return -EINVAL;
+
+       /* And its rate */
+       parent_rate = clk_hw_get_rate(parent);
+       if (!parent_rate)
+               return -EINVAL;
+
+       /* Now, get our parent's parent (most likely some PLL) */
+       grandparent = clk_hw_get_parent(parent);
+       if (!grandparent)
+               return -EINVAL;
+
+       /* And its rate */
+       grandparent_rate = clk_hw_get_rate(grandparent);
+       if (!grandparent_rate)
+               return -EINVAL;
+
+       if (degrees != 180) {
+               u16 step, parent_div;
+
+               /* Get our parent divider */
+               parent_div = grandparent_rate / parent_rate;
+
+               /*
+                * We can only outphase the clocks by multiple of the
+                * PLL's period.
+                *
+                * Since our parent clock is only a divider, and the
+                * formula to get the outphasing in degrees is deg =
+                * 360 * delta / period
+                *
+                * If we simplify this formula, we can see that the
+                * only thing that we're concerned about is the number
+                * of period we want to outphase our clock from, and
+                * the divider set by our parent clock.
+                */
+               step = DIV_ROUND_CLOSEST(360, parent_div);
+               delay = DIV_ROUND_CLOSEST(degrees, step);
+       } else {
+               delay = 0;
+       }
+
+       spin_lock_irqsave(phase->common.lock, flags);
+       reg = readl(phase->common.base + phase->common.reg);
+       reg &= ~GENMASK(phase->width + phase->shift - 1, phase->shift);
+       writel(reg | (delay << phase->shift),
+              phase->common.base + phase->common.reg);
+       spin_unlock_irqrestore(phase->common.lock, flags);
+
+       return 0;
+}
+
+const struct clk_ops ccu_phase_ops = {
+       .get_phase      = ccu_phase_get_phase,
+       .set_phase      = ccu_phase_set_phase,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_phase.h b/drivers/clk/sunxi-ng/ccu_phase.h
new file mode 100644 (file)
index 0000000..75a091a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_PHASE_H_
+#define _CCU_PHASE_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct ccu_phase {
+       u8                      shift;
+       u8                      width;
+
+       struct ccu_common       common;
+};
+
+#define SUNXI_CCU_PHASE(_struct, _name, _parent, _reg, _shift, _width, _flags) \
+       struct ccu_phase _struct = {                                    \
+               .shift  = _shift,                                       \
+               .width  = _width,                                       \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_phase_ops,   \
+                                                     _flags),          \
+               }                                                       \
+       }
+
+static inline struct ccu_phase *hw_to_ccu_phase(struct clk_hw *hw)
+{
+       struct ccu_common *common = hw_to_ccu_common(hw);
+
+       return container_of(common, struct ccu_phase, common);
+}
+
+extern const struct clk_ops ccu_phase_ops;
+
+#endif /* _CCU_PHASE_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
new file mode 100644 (file)
index 0000000..6c31d48
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/io.h>
+#include <linux/reset-controller.h>
+
+#include "ccu_reset.h"
+
+static int ccu_reset_assert(struct reset_controller_dev *rcdev,
+                           unsigned long id)
+{
+       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
+       const struct ccu_reset_map *map = &ccu->reset_map[id];
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(ccu->lock, flags);
+
+       reg = readl(ccu->base + map->reg);
+       writel(reg & ~map->bit, ccu->base + map->reg);
+
+       spin_unlock_irqrestore(ccu->lock, flags);
+
+       return 0;
+}
+
+static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
+       const struct ccu_reset_map *map = &ccu->reset_map[id];
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(ccu->lock, flags);
+
+       reg = readl(ccu->base + map->reg);
+       writel(reg | map->bit, ccu->base + map->reg);
+
+       spin_unlock_irqrestore(ccu->lock, flags);
+
+       return 0;
+}
+
+const struct reset_control_ops ccu_reset_ops = {
+       .assert         = ccu_reset_assert,
+       .deassert       = ccu_reset_deassert,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
new file mode 100644 (file)
index 0000000..36a4679
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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 _CCU_RESET_H_
+#define _CCU_RESET_H_
+
+#include <linux/reset-controller.h>
+
+struct ccu_reset_map {
+       u16     reg;
+       u32     bit;
+};
+
+
+struct ccu_reset {
+       void __iomem                    *base;
+       struct ccu_reset_map            *reset_map;
+       spinlock_t                      *lock;
+
+       struct reset_controller_dev     rcdev;
+};
+
+static inline struct ccu_reset *rcdev_to_ccu_reset(struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct ccu_reset, rcdev);
+}
+
+extern const struct reset_control_ops ccu_reset_ops;
+
+#endif /* _CCU_RESET_H_ */
index ddefe9668863b0ffbaebfc5e33c709c49c2486e2..dfe5e3e32d28f050388f05cb0247f101eb69dc74 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/string.h>
index 68021fa5ecd9af5026a941940e0496329b567d5a..09cdb9874636fce5a0079b7a704a93a2e92086c4 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -33,7 +33,6 @@ static const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
        { .compatible = "allwinner,sun8i-a23-apb0-gates-clk", .data = &sun8i_a23_apb0_gates },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, sun6i_a31_apb0_gates_clk_dt_ids);
 
 static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
 {
@@ -102,8 +101,4 @@ static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
        },
        .probe = sun6i_a31_apb0_gates_clk_probe,
 };
-module_platform_driver(sun6i_a31_apb0_gates_clk_driver);
-
-MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
-MODULE_DESCRIPTION("Allwinner A31 APB0 gate clocks driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(sun6i_a31_apb0_gates_clk_driver);
index e703e1895b76bf3affb282be6c1827ea1f5a7e61..b9c8d359288c9c32dfd51c603bfd7b56562307d4 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
@@ -61,7 +61,6 @@ static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
        { .compatible = "allwinner,sun6i-a31-apb0-clk" },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, sun6i_a31_apb0_clk_dt_ids);
 
 static struct platform_driver sun6i_a31_apb0_clk_driver = {
        .driver = {
@@ -70,8 +69,4 @@ static struct platform_driver sun6i_a31_apb0_clk_driver = {
        },
        .probe = sun6i_a31_apb0_clk_probe,
 };
-module_platform_driver(sun6i_a31_apb0_clk_driver);
-
-MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
-MODULE_DESCRIPTION("Allwinner A31 APB0 clock Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(sun6i_a31_apb0_clk_driver);
index 84a187e55360fce909cdb5564aeffa423193d84c..64ca3e9e38e6d41f29424292ebc5c9a73e43ee2d 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/bitops.h>
 #include <linux/clk-provider.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
@@ -91,32 +91,17 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int sun6i_a31_ar100_clk_remove(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct clk *clk = platform_get_drvdata(pdev);
-
-       sunxi_factors_unregister(np, clk);
-
-       return 0;
-}
-
 static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
        { .compatible = "allwinner,sun6i-a31-ar100-clk" },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, sun6i_a31_ar100_clk_dt_ids);
 
 static struct platform_driver sun6i_a31_ar100_clk_driver = {
        .driver = {
                .name = "sun6i-a31-ar100-clk",
                .of_match_table = sun6i_a31_ar100_clk_dt_ids,
+               .suppress_bind_attrs = true,
        },
        .probe = sun6i_a31_ar100_clk_probe,
-       .remove = sun6i_a31_ar100_clk_remove,
 };
-module_platform_driver(sun6i_a31_ar100_clk_driver);
-
-MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
-MODULE_DESCRIPTION("Allwinner A31 AR100 clock Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(sun6i_a31_ar100_clk_driver);
index 2ea61debffc180162d51cc437b173dc4ee831890..a5666e1d0ce708f51fb2d7c492ee72d28d5a61b0 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -108,7 +108,6 @@ static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
        { .compatible = "allwinner,sun8i-a23-apb0-clk" },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, sun8i_a23_apb0_clk_dt_ids);
 
 static struct platform_driver sun8i_a23_apb0_clk_driver = {
        .driver = {
@@ -117,8 +116,4 @@ static struct platform_driver sun8i_a23_apb0_clk_driver = {
        },
        .probe = sun8i_a23_apb0_clk_probe,
 };
-module_platform_driver(sun8i_a23_apb0_clk_driver);
-
-MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
-MODULE_DESCRIPTION("Allwinner A23 APB0 clock Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(sun8i_a23_apb0_clk_driver);
index 716737388b7d28c911c1b0e79e6daa1e57964b02..6041bdba2e971ecb93c3047c14854e676750bf5e 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/reset.h>
@@ -183,39 +183,17 @@ err_clk_register:
        return ret;
 }
 
-static int sun9i_a80_mmc_config_clk_remove(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct sun9i_mmc_clk_data *data = platform_get_drvdata(pdev);
-       struct clk_onecell_data *clk_data = &data->clk_data;
-       int i;
-
-       reset_controller_unregister(&data->rcdev);
-       of_clk_del_provider(np);
-       for (i = 0; i < clk_data->clk_num; i++)
-               clk_unregister(clk_data->clks[i]);
-
-       reset_control_assert(data->reset);
-
-       return 0;
-}
-
 static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = {
        { .compatible = "allwinner,sun9i-a80-mmc-config-clk" },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, sun9i_a80_mmc_config_clk_dt_ids);
 
 static struct platform_driver sun9i_a80_mmc_config_clk_driver = {
        .driver = {
                .name = "sun9i-a80-mmc-config-clk",
+               .suppress_bind_attrs = true,
                .of_match_table = sun9i_a80_mmc_config_clk_dt_ids,
        },
        .probe = sun9i_a80_mmc_config_clk_probe,
-       .remove = sun9i_a80_mmc_config_clk_remove,
 };
-module_platform_driver(sun9i_a80_mmc_config_clk_driver);
-
-MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
-MODULE_DESCRIPTION("Allwinner A80 MMC clock/reset Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(sun9i_a80_mmc_config_clk_driver);
index 36c974916d4fb73ffb7dbcc57e57eb739392fc80..5738635c52741c555e68f3feaba1ed28a5c3cdcf 100644 (file)
@@ -238,7 +238,6 @@ enum clk_id {
        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,
index 4e194ecc8d5e016121941b8381de5585cd1a6f7e..b3855360d6bc0d64121abc127f50e58411b67db7 100644 (file)
 #define PLLSS_REF_SRC_SEL_SHIFT        25
 #define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)
 
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+
+#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_CFG2_PHY_XTAL_CLOCKEN BIT(30)
+
+#define UTMIPLL_HW_PWRDN_CFG0 0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
+
+#define PLLU_HW_PWRDN_CFG0 0x530
+#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL BIT(0)
+#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
+#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT BIT(7)
+#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
+#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(28)
+
+#define XUSB_PLL_CFG0 0x534
+#define XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY 0x3ff
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY (0x3ff << 14)
+
+#define PLLU_BASE_CLKENABLE_USB BIT(21)
+#define PLLU_BASE_OVERRIDE BIT(24)
+
 #define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
 #define pll_readl_base(p) pll_readl(p->params->base_reg, p)
 #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
@@ -973,6 +1020,133 @@ const struct clk_ops tegra_clk_plle_ops = {
        .enable = clk_plle_enable,
 };
 
+/*
+ * Structure defining the fields for USB UTMI clocks Parameters.
+ */
+struct utmi_clk_param {
+       /* Oscillator Frequency in Hz */
+       u32 osc_frequency;
+       /* UTMIP PLL Enable Delay Count  */
+       u8 enable_delay_count;
+       /* UTMIP PLL Stable count */
+       u8 stable_count;
+       /*  UTMIP PLL Active delay count */
+       u8 active_delay_count;
+       /* UTMIP PLL Xtal frequency count */
+       u8 xtal_freq_count;
+};
+
+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 = 38400000, .enable_delay_count = 0x0,
+               .stable_count = 0x0, .active_delay_count = 0x6,
+               .xtal_freq_count = 0x80
+       },
+};
+
+static int clk_pllu_enable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       struct clk_hw *pll_ref = clk_hw_get_parent(hw);
+       struct clk_hw *osc = clk_hw_get_parent(pll_ref);
+       const struct utmi_clk_param *params = NULL;
+       unsigned long flags = 0, input_rate;
+       unsigned int i;
+       int ret = 0;
+       u32 value;
+
+       if (!osc) {
+               pr_err("%s: failed to get OSC clock\n", __func__);
+               return -EINVAL;
+       }
+
+       input_rate = clk_hw_get_rate(osc);
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pll_enable(hw);
+
+       ret = clk_pll_wait_for_lock(pll);
+       if (ret < 0)
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (input_rate == utmi_parameters[i].osc_frequency) {
+                       params = &utmi_parameters[i];
+                       break;
+               }
+       }
+
+       if (!params) {
+               pr_err("%s: unexpected input rate %lu Hz\n", __func__,
+                      input_rate);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       value = pll_readl_base(pll);
+       value &= ~PLLU_BASE_OVERRIDE;
+       pll_writel_base(value, pll);
+
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
+       /* Program UTMIP PLL stable and active counts */
+       value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
+       value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+       value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
+       /* Remove power downs from UTMIP PLL control bits */
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
+
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+       value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
+       value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
+       /* Remove power downs from UTMIP PLL control bits */
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
+
+out:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static const struct clk_ops tegra_clk_pllu_ops = {
+       .is_enabled = clk_pll_is_enabled,
+       .enable = clk_pllu_enable,
+       .disable = clk_pll_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+};
+
 static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
                           unsigned long parent_rate)
 {
@@ -1505,6 +1679,112 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw)
        if (pll->lock)
                spin_unlock_irqrestore(pll->lock, flags);
 }
+
+static int clk_pllu_tegra114_enable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       const struct utmi_clk_param *params = NULL;
+       struct clk *osc = __clk_lookup("osc");
+       unsigned long flags = 0, input_rate;
+       unsigned int i;
+       int ret = 0;
+       u32 value;
+
+       if (!osc) {
+               pr_err("%s: failed to get OSC clock\n", __func__);
+               return -EINVAL;
+       }
+
+       input_rate = clk_hw_get_rate(__clk_get_hw(osc));
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pll_enable(hw);
+
+       ret = clk_pll_wait_for_lock(pll);
+       if (ret < 0)
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (input_rate == utmi_parameters[i].osc_frequency) {
+                       params = &utmi_parameters[i];
+                       break;
+               }
+       }
+
+       if (!params) {
+               pr_err("%s: unexpected input rate %lu Hz\n", __func__,
+                      input_rate);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       value = pll_readl_base(pll);
+       value &= ~PLLU_BASE_OVERRIDE;
+       pll_writel_base(value, pll);
+
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
+       /* Program UTMIP PLL stable and active counts */
+       value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
+       value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+       value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
+       /* Remove power downs from UTMIP PLL control bits */
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
+
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+       value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
+       value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
+       /* Remove power downs from UTMIP PLL control bits */
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
+
+       /* Setup HW control of UTMIPLL */
+       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+       value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+       value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
+       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
+
+       udelay(1);
+
+       /*
+        * Setup SW override of UTMIPLL assuming USB2.0 ports are assigned
+        * to USB2
+        */
+       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       value |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
+       value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       udelay(1);
+
+       /* Enable HW control of UTMIPLL */
+       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+out:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
 #endif
 
 static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
@@ -1614,6 +1894,27 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
        return clk;
 }
 
+struct clk *tegra_clk_register_pllu(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;
+
+       pll_params->flags |= TEGRA_PLLU;
+
+       pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllu_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
 #if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
        defined(CONFIG_ARCH_TEGRA_124_SOC) || \
        defined(CONFIG_ARCH_TEGRA_132_SOC) || \
@@ -1652,6 +1953,12 @@ static const struct clk_ops tegra_clk_plle_tegra114_ops = {
        .recalc_rate = clk_pll_recalc_rate,
 };
 
+static const struct clk_ops tegra_clk_pllu_tegra114_ops = {
+       .is_enabled =  clk_pll_is_enabled,
+       .enable = clk_pllu_tegra114_enable,
+       .disable = clk_pll_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+};
 
 struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
                          void __iomem *clk_base, void __iomem *pmc,
@@ -1919,6 +2226,29 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
 
        return clk;
 }
+
+struct clk *
+tegra_clk_register_pllu_tegra114(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;
+
+       pll_params->flags |= TEGRA_PLLU;
+
+       pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllu_tegra114_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
 #endif
 
 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
@@ -2187,6 +2517,152 @@ static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
        return val & PLLE_BASE_ENABLE ? 1 : 0;
 }
 
+static int clk_pllu_tegra210_enable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       struct clk_hw *pll_ref = clk_hw_get_parent(hw);
+       struct clk_hw *osc = clk_hw_get_parent(pll_ref);
+       const struct utmi_clk_param *params = NULL;
+       unsigned long flags = 0, input_rate;
+       unsigned int i;
+       int ret = 0;
+       u32 value;
+
+       if (!osc) {
+               pr_err("%s: failed to get OSC clock\n", __func__);
+               return -EINVAL;
+       }
+
+       input_rate = clk_hw_get_rate(osc);
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pll_enable(hw);
+
+       ret = clk_pll_wait_for_lock(pll);
+       if (ret < 0)
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (input_rate == utmi_parameters[i].osc_frequency) {
+                       params = &utmi_parameters[i];
+                       break;
+               }
+       }
+
+       if (!params) {
+               pr_err("%s: unexpected input rate %lu Hz\n", __func__,
+                      input_rate);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       value = pll_readl_base(pll);
+       value &= ~PLLU_BASE_OVERRIDE;
+       pll_writel_base(value, pll);
+
+       /* Put PLLU under HW control */
+       value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
+       value |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
+                PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
+                PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
+       value &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
+                  PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
+       writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
+
+       value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
+       value &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY;
+       writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
+
+       udelay(1);
+
+       value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
+       value |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
+       writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
+
+       udelay(1);
+
+       /* Disable PLLU clock branch to UTMIPLL since it uses OSC */
+       value = pll_readl_base(pll);
+       value &= ~PLLU_BASE_CLKENABLE_USB;
+       pll_writel_base(value, pll);
+
+       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       if (value & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE) {
+               pr_debug("UTMIPLL already enabled\n");
+               goto out;
+       }
+
+       value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       /* Program UTMIP PLL stable and active counts */
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
+       value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
+       value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+       value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
+       value |= UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
+       value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+       value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
+       value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       value |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       writel(value, pll->clk_base + UTMIP_PLL_CFG1);
+
+       udelay(1);
+
+       /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
+       value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
+       value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
+       value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
+
+       /* Setup HW control of UTMIPLL */
+       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
+
+       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+       value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       udelay(1);
+
+       value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
+       value &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
+       writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
+
+       udelay(1);
+
+       /* Enable HW control of UTMIPLL */
+       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+out:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
        .is_enabled =  clk_plle_tegra210_is_enabled,
        .enable = clk_plle_tegra210_enable,
@@ -2194,6 +2670,13 @@ static const struct clk_ops tegra_clk_plle_tegra210_ops = {
        .recalc_rate = clk_pll_recalc_rate,
 };
 
+static const struct clk_ops tegra_clk_pllu_tegra210_ops = {
+       .is_enabled =  clk_pll_is_enabled,
+       .enable = clk_pllu_tegra210_enable,
+       .disable = clk_pll_disable,
+       .recalc_rate = clk_pllre_recalc_rate,
+};
+
 struct clk *tegra_clk_register_plle_tegra210(const char *name,
                                const char *parent_name,
                                void __iomem *clk_base, unsigned long flags,
@@ -2434,4 +2917,26 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
 
        return clk;
 }
+
+struct clk *tegra_clk_register_pllu_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;
+
+       pll_params->flags |= TEGRA_PLLU;
+
+       pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllu_tegra210_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
 #endif
index 29d04c663abfbbb3eabad5e07c29d578354d8934..4ce4e7fb1124d0aa38323454af5a782edffae42c 100644 (file)
@@ -594,15 +594,17 @@ 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_sor_safe_sor1_brick_sor1_src[] = {
+       /*
+        * Bit 0 of the mux selects sor1_brick, irrespective of bit 1, so the
+        * sor1_brick parent appears twice in the list below. This is merely
+        * to support clk_get_parent() if firmware happened to set these bits
+        * to 0b11. While not an invalid setting, code should always set the
+        * bits to 0b01 to select sor1_brick.
+        */
+       "sor_safe", "sor1_brick", "sor1_src", "sor1_brick"
+};
+#define mux_sor_safe_sor1_brick_sor1_src_idx NULL
 
 static const char *mux_pllp_pllre_clkm[] = {
        "pll_p", "pll_re_out1", "clk_m"
@@ -778,8 +780,7 @@ static struct tegra_periph_init_data periph_clks[] = {
        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),
+       NODIV("sor1", mux_sor_safe_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 14, MASK(2), 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),
        I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c),
@@ -791,7 +792,7 @@ static struct tegra_periph_init_data periph_clks[] = {
 
 static struct tegra_periph_init_data gate_clks[] = {
        GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0),
-       GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0),
+       GATE("timer", "clk_m", 5, 0, tegra_clk_timer, CLK_IS_CRITICAL),
        GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0),
        GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
        GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
index b78054fac0a8771c7a892b7478b93722a9c1c65a..64da7b79a6e47fd4acf9098f1ff6c17ad07741da 100644 (file)
 
 #define CCLKG_BURST_POLICY 0x368
 
-#define UTMIP_PLL_CFG2 0x488
-#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 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_B_POWERDOWN BIT(2)
-#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
-
-#define UTMIP_PLL_CFG1 0x484
-#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
-#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_SEQ_START_STATE  BIT(25)
-#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE       BIT(24)
-#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 CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 
@@ -649,43 +623,6 @@ static unsigned long tegra114_input_freq[] = {
 
 #define MASK(x) (BIT(x) - 1)
 
-struct utmi_clk_param {
-       /* Oscillator Frequency in KHz */
-       u32 osc_frequency;
-       /* UTMIP PLL Enable Delay Count  */
-       u8 enable_delay_count;
-       /* UTMIP PLL Stable count */
-       u8 stable_count;
-       /*  UTMIP PLL Active delay count */
-       u8 active_delay_count;
-       /* UTMIP PLL Xtal frequency count */
-       u8 xtal_freq_count;
-};
-
-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
-       },
-};
-
 /* peripheral mux definitions */
 
 static const char *mux_plld_out0_plld2_out0[] = {
@@ -986,92 +923,9 @@ 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;
-
-       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 + 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);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       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_C_POWERDOWN;
-
-       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);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
-       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
-
-       /* Setup HW control of UTMIPLL */
-       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
-       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
-       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
-       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
-
-       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
-
-       udelay(1);
-
-       /* Setup SW override of UTMIPLL assuming USB2.0
-          ports are assigned to USB2 */
-       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
-       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
-       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_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 void __init tegra114_pll_init(void __iomem *clk_base,
                                     void __iomem *pmc)
 {
-       u32 val;
        struct clk *clk;
 
        /* PLLC */
@@ -1118,16 +972,10 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
                                        CLK_SET_RATE_PARENT, 1, 1);
 
        /* PLLU */
-       val = readl(clk_base + pll_u_params.base_reg);
-       val &= ~BIT(24); /* disable PLLU_OVERRIDE */
-       writel(val, clk_base + pll_u_params.base_reg);
-
-       clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
-                           &pll_u_params, &pll_u_lock);
+       clk = tegra_clk_register_pllu_tegra114("pll_u", "pll_ref", clk_base, 0,
+                                              &pll_u_params, &pll_u_lock);
        clks[TEGRA114_CLK_PLL_U] = clk;
 
-       tegra114_utmi_param_configure(clk_base);
-
        /* PLLU_480M */
        clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
                                CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
index f4fbbf16a056fe6d394782fbc37d1de49509f4ad..a112d3d2bff11ee2bf135e10d78d2584705fb073 100644 (file)
 
 #define CCLKG_BURST_POLICY 0x368
 
-#define UTMIP_PLL_CFG2 0x488
-#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 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_B_POWERDOWN BIT(2)
-#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
-
-#define UTMIP_PLL_CFG1 0x484
-#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
-#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_SEQ_START_STATE  BIT(25)
-#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE       BIT(24)
-#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)
-
 /* Tegra CPU clock and reset control regs */
 #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS    0x470
 
@@ -764,43 +738,6 @@ static struct tegra_clk_pll_params pll_u_params = {
                 TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
 };
 
-struct utmi_clk_param {
-       /* Oscillator Frequency in KHz */
-       u32 osc_frequency;
-       /* UTMIP PLL Enable Delay Count  */
-       u8 enable_delay_count;
-       /* UTMIP PLL Stable count */
-       u8 stable_count;
-       /*  UTMIP PLL Active delay count */
-       u8 active_delay_count;
-       /* UTMIP PLL Xtal frequency count */
-       u8 xtal_freq_count;
-};
-
-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
-       },
-};
-
 static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
        [tegra_clk_ispb] = { .dt_id = TEGRA124_CLK_ISPB, .present = true },
        [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true },
@@ -1063,88 +1000,6 @@ static struct tegra_devclk devclks[] __initdata = {
 
 static struct clk **clks;
 
-static void tegra124_utmi_param_configure(void __iomem *clk_base)
-{
-       unsigned int i;
-       u32 reg;
-
-       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 + 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);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       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_C_POWERDOWN;
-
-       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);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
-       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
-
-       /* Setup HW control of UTMIPLL */
-       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
-       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
-       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
-       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
-
-       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
-
-       udelay(1);
-
-       /* Setup SW override of UTMIPLL assuming USB2.0
-          ports are assigned to USB2 */
-       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
-       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
-       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_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 tegra124_periph_clk_init(void __iomem *clk_base,
                                            void __iomem *pmc_base)
 {
@@ -1195,7 +1050,6 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
 static void __init tegra124_pll_init(void __iomem *clk_base,
                                     void __iomem *pmc)
 {
-       u32 val;
        struct clk *clk;
 
        /* PLLC */
@@ -1256,17 +1110,11 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
        clks[TEGRA124_CLK_PLL_M_UD] = clk;
 
        /* PLLU */
-       val = readl(clk_base + pll_u_params.base_reg);
-       val &= ~BIT(24); /* disable PLLU_OVERRIDE */
-       writel(val, clk_base + pll_u_params.base_reg);
-
-       clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
-                           &pll_u_params, &pll_u_lock);
+       clk = tegra_clk_register_pllu_tegra114("pll_u", "pll_ref", clk_base, 0,
+                                              &pll_u_params, &pll_u_lock);
        clk_register_clkdev(clk, "pll_u", NULL);
        clks[TEGRA124_CLK_PLL_U] = clk;
 
-       tegra124_utmi_param_configure(clk_base);
-
        /* PLLU_480M */
        clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
                                CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
index 456cf586d2c2b86a23d74680787190ac44048989..2896d2e783cecc363ec4966bdd8bb408bc9faee4 100644 (file)
 #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 SATA_PLL_CFG0                          0x490
 #define SATA_PLL_CFG0_PADPLL_RESET_SWCTL       BIT(0)
 #define SATA_PLL_CFG0_PADPLL_USE_LOCKDET       BIT(2)
@@ -1366,9 +1345,9 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
 
 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 */
+       { 12000000, 1000000000, 166, 1, 2, 0 }, /* actual: 996.0 MHz */
+       { 13000000, 1000000000, 153, 1, 2, 0 }, /* actual: 994.0 MHz */
+       { 38400000, 1000000000, 156, 3, 2, 0 }, /* actual: 998.4 MHz */
        {        0,          0,   0, 0, 0, 0 },
 };
 
@@ -1417,9 +1396,9 @@ static struct div_nmp pllc_nmp = {
 };
 
 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 */
+       { 12000000, 510000000, 85, 1, 2, 0 },
+       { 13000000, 510000000, 78, 1, 2, 0 }, /* actual: 507.0 MHz */
+       { 38400000, 510000000, 79, 3, 2, 0 }, /* actual: 505.6 MHz */
        {        0,         0,  0, 0, 0, 0 },
 };
 
@@ -1532,9 +1511,9 @@ static struct div_nmp pllss_nmp = {
 };
 
 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 */
+       { 12000000, 600000000, 50, 1, 1, 0 },
+       { 13000000, 600000000, 46, 1, 1, 0 }, /* actual: 598.0 MHz */
+       { 38400000, 600000000, 62, 4, 1, 0 }, /* actual: 595.2 MHz */
        {        0,         0,  0, 0, 0, 0 },
 };
 
@@ -1583,19 +1562,19 @@ static struct tegra_clk_pll_params pll_c4_vco_params = {
 };
 
 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 },
+       { 12000000,  800000000,  66, 1, 1, 0 }, /* actual: 792.0 MHz */
+       { 13000000,  800000000,  61, 1, 1, 0 }, /* actual: 793.0 MHz */
+       { 38400000,  297600000,  93, 4, 3, 0 },
+       { 38400000,  400000000, 125, 4, 3, 0 },
+       { 38400000,  532800000, 111, 4, 2, 0 },
+       { 38400000,  665600000, 104, 3, 2, 0 },
+       { 38400000,  800000000, 125, 3, 2, 0 },
+       { 38400000,  931200000,  97, 4, 1, 0 },
+       { 38400000, 1065600000, 111, 4, 1, 0 },
+       { 38400000, 1200000000, 125, 4, 1, 0 },
+       { 38400000, 1331200000, 104, 3, 1, 0 },
+       { 38400000, 1459200000,  76, 2, 1, 0 },
+       { 38400000, 1600000000, 125, 3, 1, 0 },
        {        0,          0,   0, 0, 0, 0 },
 };
 
@@ -1705,9 +1684,9 @@ static struct tegra_clk_pll_params pll_e_params = {
 };
 
 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 },
+       { 12000000, 672000000, 56, 1, 1, 0 },
+       { 13000000, 672000000, 51, 1, 1, 0 }, /* actual: 663.0 MHz */
+       { 38400000, 672000000, 70, 4, 1, 0 },
        {        0,         0,  0, 0, 0, 0 },
 };
 
@@ -1754,8 +1733,8 @@ static struct div_nmp pllp_nmp = {
 };
 
 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 */
+       { 12000000, 408000000, 34, 1, 1, 0 },
+       { 38400000, 408000000, 85, 8, 1, 0 }, /* cf = 4.8MHz, allowed exception */
        {        0,         0,  0, 0, 0, 0 },
 };
 
@@ -1820,14 +1799,14 @@ static struct div_nmp plla_nmp = {
 };
 
 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 */
+       { 12000000, 282240000, 47, 1, 2, 1, 0xf148 }, /* actual: 282240234 */
+       { 12000000, 368640000, 61, 1, 2, 1, 0xfe15 }, /* actual: 368640381 */
+       { 12000000, 240000000, 60, 1, 3, 1,      0 },
+       { 13000000, 282240000, 43, 1, 2, 1, 0xfd7d }, /* actual: 282239807 */
+       { 13000000, 368640000, 56, 1, 2, 1, 0x06d8 }, /* actual: 368640137 */
+       { 13000000, 240000000, 55, 1, 3, 1,      0 }, /* actual: 238.3 MHz */
+       { 38400000, 282240000, 44, 3, 2, 1, 0xf333 }, /* actual: 282239844 */
+       { 38400000, 368640000, 57, 3, 2, 1, 0x0333 }, /* actual: 368639844 */
        { 38400000, 240000000, 75, 3, 3, 1,      0 },
        {        0,         0,  0, 0, 0, 0,      0 },
 };
@@ -1873,9 +1852,9 @@ static struct div_nmp plld_nmp = {
 };
 
 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 },
+       { 12000000, 594000000, 99, 1, 2, 0,      0 },
+       { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f }, /* actual: 594000183 */
+       { 38400000, 594000000, 30, 1, 2, 0, 0x0e00 },
        {        0,         0,  0, 0, 0, 0,      0 },
 };
 
@@ -1911,9 +1890,9 @@ static struct tegra_clk_pll_params pll_d_params = {
 };
 
 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 },
+       { 12000000, 594000000, 99, 1, 2, 0, 0xf000 },
+       { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f }, /* actual: 594000183 */
+       { 38400000, 594000000, 30, 1, 2, 0, 0x0e00 },
        {        0,         0,  0, 0, 0, 0,      0 },
 };
 
@@ -1935,8 +1914,9 @@ static struct tegra_clk_pll_params pll_d2_params = {
        .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,
+       /* disable spread-spectrum for pll_d2 */
+       .ssc_ctrl_reg = 0,
+       .ssc_ctrl_en_mask = 0,
        .round_p_to_pdiv = pll_qlin_p_to_pdiv,
        .pdiv_tohw = pll_qlin_pdiv_to_hw,
        .div_nmp = &pllss_nmp,
@@ -1955,9 +1935,9 @@ static struct tegra_clk_pll_params pll_d2_params = {
 };
 
 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 },
+       { 12000000, 270000000, 90, 1, 4, 0, 0xf000 },
+       { 13000000, 270000000, 83, 1, 4, 0, 0xf000 }, /* actual: 269.8 MHz */
+       { 38400000, 270000000, 28, 1, 4, 0, 0xf400 },
        {        0,         0,  0, 0, 0, 0,      0 },
 };
 
@@ -2007,9 +1987,9 @@ static struct div_nmp pllu_nmp = {
 };
 
 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 },
+       { 12000000, 480000000, 40, 1, 1, 0 },
+       { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */
+       { 38400000, 480000000, 25, 2, 1, 0 },
        {        0,         0,  0, 0, 0, 0 },
 };
 
@@ -2037,47 +2017,6 @@ static struct tegra_clk_pll_params pll_u_vco_params = {
        .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 },
@@ -2154,6 +2093,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
        [tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .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_sor1] = { .dt_id = TEGRA210_CLK_SOR1, .present = true },
+       [tegra_clk_sor1_src] = { .dt_id = TEGRA210_CLK_SOR1_SRC, .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 },
@@ -2345,114 +2286,6 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = {
 
 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)
 {
@@ -2463,18 +2296,18 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
                                        1, 2);
        clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk;
 
-       clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
+       clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base,
+                                             1, 17, 222);
+       clks[TEGRA210_CLK_SOR_SAFE] = clk;
+
+       clk = tegra_clk_register_periph_fixed("dpaux", "sor_safe", 0, clk_base,
                                              1, 17, 181);
        clks[TEGRA210_CLK_DPAUX] = clk;
 
-       clk = tegra_clk_register_periph_fixed("dpaux1", "pll_p", 0, clk_base,
+       clk = tegra_clk_register_periph_fixed("dpaux1", "sor_safe", 0, clk_base,
                                              1, 17, 207);
        clks[TEGRA210_CLK_DPAUX1] = clk;
 
-       clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base,
-                                             1, 17, 222);
-       clks[TEGRA210_CLK_SOR_SAFE] = 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);
@@ -2520,7 +2353,6 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
 static void __init tegra210_pll_init(void __iomem *clk_base,
                                     void __iomem *pmc)
 {
-       u32 val;
        struct clk *clk;
 
        /* PLLC */
@@ -2580,12 +2412,9 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
        clks[TEGRA210_CLK_PLL_M_UD] = clk;
 
        /* PLLU_VCO */
-       val = readl(clk_base + pll_u_vco_params.base_reg);
-       val &= ~PLLU_BASE_OVERRIDE; /* 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 = tegra_clk_register_pllu_tegra210("pll_u_vco", "pll_ref",
+                                              clk_base, 0, &pll_u_vco_params,
+                                              &pll_u_lock);
        clk_register_clkdev(clk, "pll_u_vco", NULL);
        clks[TEGRA210_CLK_PLL_U] = clk;
 
@@ -2618,8 +2447,6 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
        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,
index 9396f4930da71fabdd9f928c97f15d08b5747216..8e2db5ead8da683500826a2968bd165ca88943b6 100644 (file)
 
 #define AUDIO_SYNC_DOUBLER 0x49c
 
-#define UTMIP_PLL_CFG2 0x488
-#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 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_B_POWERDOWN BIT(2)
-#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
-
-#define UTMIP_PLL_CFG1 0x484
-#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
-#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
-#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
-#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
-#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
-
 /* Tegra CPU clock and reset control regs */
 #define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX         0x4c
 #define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET     0x340
@@ -207,46 +193,6 @@ static DEFINE_SPINLOCK(emc_lock);
 
 static struct clk **clks;
 
-/*
- * Structure defining the fields for USB UTMI clocks Parameters.
- */
-struct utmi_clk_param {
-       /* Oscillator Frequency in KHz */
-       u32 osc_frequency;
-       /* UTMIP PLL Enable Delay Count  */
-       u8 enable_delay_count;
-       /* UTMIP PLL Stable count */
-       u8 stable_count;
-       /*  UTMIP PLL Active delay count */
-       u8 active_delay_count;
-       /* UTMIP PLL Xtal frequency count */
-       u8 xtal_freq_count;
-};
-
-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
-       },
-};
-
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
        { 12000000, 1040000000, 520,  6, 1, 8 },
        { 13000000, 1040000000, 480,  6, 1, 8 },
@@ -873,59 +819,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
        [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;
-
-       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
-               if (input_freq == utmi_parameters[i].osc_frequency)
-                       break;
-       }
-
-       if (i >= ARRAY_SIZE(utmi_parameters)) {
-               pr_err("%s: Unexpected input rate %lu\n", __func__, input_freq);
-               return;
-       }
-
-       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
-
-       /* Program UTMIP PLL stable and active counts */
-       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);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       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_C_POWERDOWN;
-
-       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);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
-
-       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
-}
-
 static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
 
 static void __init tegra30_pll_init(void)
@@ -972,12 +865,10 @@ static void __init tegra30_pll_init(void)
        clks[TEGRA30_CLK_PLL_X_OUT0] = clk;
 
        /* PLLU */
-       clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0,
-                           &pll_u_params, NULL);
+       clk = tegra_clk_register_pllu("pll_u", "pll_ref", clk_base, 0,
+                                     &pll_u_params, NULL);
        clks[TEGRA30_CLK_PLL_U] = clk;
 
-       tegra30_utmi_param_configure();
-
        /* PLLD */
        clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0,
                            &pll_d_params, &pll_d_lock);
index 9421f0310999fe70242f21aff89ce96ca29bf2f0..6ba82ecffd4d40fdf4a00b366d8aaea5c12e3671 100644 (file)
@@ -427,6 +427,23 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
                           struct tegra_clk_pll_params *pll_params,
                           spinlock_t *lock);
 
+struct clk *tegra_clk_register_pllu(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_pllu_tegra114(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_pllu_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_out - PLL divider down clock
  *
index 9b180f032e2db394b817702c3a0264eaccca5a96..85b467b3a20718be416386713b6b362d67c5b02b 100644 (file)
@@ -1,33 +1,65 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * 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.
+ *
+ * Device Tree binding constants for Exynos5421 clock controller.
+*/
+
 #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 
 /* core clocks */
-#define CLK_FIN_PLL 1
-#define CLK_FOUT_APLL 2
-#define CLK_FOUT_CPLL 3
-#define CLK_FOUT_MPLL 4
-#define CLK_FOUT_BPLL 5
-#define CLK_FOUT_KPLL 6
+#define CLK_FIN_PLL            1
+#define CLK_FOUT_APLL          2
+#define CLK_FOUT_CPLL          3
+#define CLK_FOUT_MPLL          4
+#define CLK_FOUT_BPLL          5
+#define CLK_FOUT_KPLL          6
 
 /* gate for special clocks (sclk) */
-#define CLK_SCLK_UART0 128
-#define CLK_SCLK_UART1 129
-#define CLK_SCLK_UART2 130
-#define CLK_SCLK_UART3 131
-#define CLK_SCLK_MMC0 132
-#define CLK_SCLK_MMC1 133
-#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_UART0         128
+#define CLK_SCLK_UART1         129
+#define CLK_SCLK_UART2         130
+#define CLK_SCLK_UART3         131
+#define CLK_SCLK_MMC0          132
+#define CLK_SCLK_MMC1          133
+#define CLK_SCLK_MMC2          134
+#define CLK_SCLK_USBD300       150
+#define CLK_SCLK_USBD301       151
+#define CLK_SCLK_USBPHY300     152
+#define CLK_SCLK_USBPHY301     153
+#define CLK_SCLK_PWM           155
 
 /* gate clocks */
-#define CLK_UART0 257
-#define CLK_UART1 258
-#define CLK_UART2 259
-#define CLK_UART3 260
-#define CLK_MCT 315
-#define CLK_MMC0 351
-#define CLK_MMC1 352
-#define CLK_MMC2 353
+#define CLK_UART0              257
+#define CLK_UART1              258
+#define CLK_UART2              259
+#define CLK_I2C0               261
+#define CLK_I2C1               262
+#define CLK_I2C2               263
+#define CLK_I2C3               264
+#define CLK_USI0               265
+#define CLK_USI1               266
+#define CLK_USI2               267
+#define CLK_USI3               268
+#define CLK_UART3              260
+#define CLK_PWM                        279
+#define CLK_MCT                        315
+#define CLK_WDT                        316
+#define CLK_RTC                        317
+#define CLK_TMU                        318
+#define CLK_MMC0               351
+#define CLK_MMC1               352
+#define CLK_MMC2               353
+#define CLK_USBH20             365
+#define CLK_USBD300            366
+#define CLK_USBD301            367
+#define CLK_SSS                        471
 
-#define CLK_NR_CLKS 512
+#define CLK_NR_CLKS            512
 
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
index 8e024fea26e7e59bbe3fdee61544b0d25a1c49c2..4fa6bb2136e373205d47e592eb441db003c4d3df 100644 (file)
 #define CLK_SCLK_UFSUNIPRO             112
 #define CLK_SCLK_USBHOST30             113
 #define CLK_SCLK_USBDRD30              114
+#define CLK_PCIE                       115
 
-#define FSYS_NR_CLK                    115
+#define FSYS_NR_CLK                    116
 
 /* CMU_G2D */
 #define CLK_MUX_ACLK_G2D_266_USER      1
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
new file mode 100644 (file)
index 0000000..f889d80
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * GXBB clock tree IDs
+ */
+
+#ifndef __GXBB_CLKC_H
+#define __GXBB_CLKC_H
+
+#define CLKID_CPUCLK           1
+#define CLKID_CLK81            12
+#define CLKID_ETH              36
+
+#endif /* __GXBB_CLKC_H */
index 70ee3833a7a0f76e183b823b52220f867080e5e7..6b03c84f42783635573307c053d63e9f0d3ee083 100644 (file)
@@ -55,8 +55,9 @@
 #define HI6220_TIMER7_PCLK     34
 #define HI6220_TIMER8_PCLK     35
 #define HI6220_UART0_PCLK      36
-
-#define HI6220_AO_NR_CLKS      37
+#define HI6220_RTC0_PCLK       37
+#define HI6220_RTC1_PCLK       38
+#define HI6220_AO_NR_CLKS      39
 
 /* clk in Hi6220 systrl */
 /* gate clock */
index d41b6fea145079d0da22a5d195ab7f001e7335a7..e624d3a527983135e14862a5580e7e1a4112ee53 100644 (file)
@@ -48,6 +48,7 @@
 #define LPC32XX_CLK_PWM2       33
 #define LPC32XX_CLK_ADC                34
 #define LPC32XX_CLK_HCLK_PLL   35
+#define LPC32XX_CLK_PERIPH     36
 
 /* LPC32XX USB clocks */
 #define LPC32XX_USB_CLK_I2C    1
index bd2720d58e0c3a21363fba9e0951d9e42a03c2d9..595a58d0969ac5d79473686192d17ac5face9b43 100644 (file)
@@ -19,7 +19,9 @@
 #define CLKID_MALI             11
 #define CLKID_CPUCLK           12
 #define CLKID_ZERO             13
+#define CLKID_MPEG_SEL         14
+#define CLKID_MPEG_DIV         15
 
-#define CLK_NR_CLKS            (CLKID_ZERO + 1)
+#define CLK_NR_CLKS            (CLKID_MPEG_DIV + 1)
 
 #endif /* __MESON8B_CLKC_H */
diff --git a/include/dt-bindings/clock/r8a7796-cpg-mssr.h b/include/dt-bindings/clock/r8a7796-cpg-mssr.h
new file mode 100644 (file)
index 0000000..1e59426
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A7796_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A7796_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a7796 CPG Core Clocks */
+#define R8A7796_CLK_Z                  0
+#define R8A7796_CLK_Z2                 1
+#define R8A7796_CLK_ZR                 2
+#define R8A7796_CLK_ZG                 3
+#define R8A7796_CLK_ZTR                        4
+#define R8A7796_CLK_ZTRD2              5
+#define R8A7796_CLK_ZT                 6
+#define R8A7796_CLK_ZX                 7
+#define R8A7796_CLK_S0D1               8
+#define R8A7796_CLK_S0D2               9
+#define R8A7796_CLK_S0D3               10
+#define R8A7796_CLK_S0D4               11
+#define R8A7796_CLK_S0D6               12
+#define R8A7796_CLK_S0D8               13
+#define R8A7796_CLK_S0D12              14
+#define R8A7796_CLK_S1D1               15
+#define R8A7796_CLK_S1D2               16
+#define R8A7796_CLK_S1D4               17
+#define R8A7796_CLK_S2D1               18
+#define R8A7796_CLK_S2D2               19
+#define R8A7796_CLK_S2D4               20
+#define R8A7796_CLK_S3D1               21
+#define R8A7796_CLK_S3D2               22
+#define R8A7796_CLK_S3D4               23
+#define R8A7796_CLK_LB                 24
+#define R8A7796_CLK_CL                 25
+#define R8A7796_CLK_ZB3                        26
+#define R8A7796_CLK_ZB3D2              27
+#define R8A7796_CLK_ZB3D4              28
+#define R8A7796_CLK_CR                 29
+#define R8A7796_CLK_CRD2               30
+#define R8A7796_CLK_SD0H               31
+#define R8A7796_CLK_SD0                        32
+#define R8A7796_CLK_SD1H               33
+#define R8A7796_CLK_SD1                        34
+#define R8A7796_CLK_SD2H               35
+#define R8A7796_CLK_SD2                        36
+#define R8A7796_CLK_SD3H               37
+#define R8A7796_CLK_SD3                        38
+#define R8A7796_CLK_SSP2               39
+#define R8A7796_CLK_SSP1               40
+#define R8A7796_CLK_SSPRS              41
+#define R8A7796_CLK_RPC                        42
+#define R8A7796_CLK_RPCD2              43
+#define R8A7796_CLK_MSO                        44
+#define R8A7796_CLK_CANFD              45
+#define R8A7796_CLK_HDMI               46
+#define R8A7796_CLK_CSI0               47
+#define R8A7796_CLK_CSIREF             48
+#define R8A7796_CLK_CP                 49
+#define R8A7796_CLK_CPEX               50
+#define R8A7796_CLK_R                  51
+#define R8A7796_CLK_OSC                        52
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7796_CPG_MSSR_H__ */
index 5d43ed9b05ad1521fa8a2990a22d35cf29d7403b..b27e2b1a65e3cb66424c0a90ce69fb9e84a21694 100644 (file)
 #define SCLK_EMMC_SAMPLE       121
 #define SCLK_VOP               122
 #define SCLK_HDMI_HDCP         123
+#define SCLK_MAC_SRC           124
+#define SCLK_MAC_EXTCLK                125
+#define SCLK_MAC               126
+#define SCLK_MAC_REFOUT                127
+#define SCLK_MAC_REF           128
+#define SCLK_MAC_RX            129
+#define SCLK_MAC_TX            130
+#define SCLK_MAC_PHY           131
+#define SCLK_MAC_OUT           132
 
 /* dclk gates */
 #define DCLK_VOP               190
@@ -61,6 +70,7 @@
 #define ACLK_DMAC              194
 #define ACLK_PERI              210
 #define ACLK_VOP               211
+#define ACLK_GMAC              212
 
 /* pclk gates */
 #define PCLK_GPIO0             320
 #define PCLK_PERI              363
 #define PCLK_HDMI_CTRL         364
 #define PCLK_HDMI_PHY          365
+#define PCLK_GMAC              367
 
 /* hclk gates */
+#define HCLK_I2S0_8CH          442
+#define HCLK_I2S1_8CH          443
+#define HCLK_I2S2_2CH          444
+#define HCLK_SPDIF_8CH         445
 #define HCLK_VOP               452
 #define HCLK_NANDC             453
 #define HCLK_SDMMC             456
diff --git a/include/dt-bindings/clock/sun8i-h3-ccu.h b/include/dt-bindings/clock/sun8i-h3-ccu.h
new file mode 100644 (file)
index 0000000..efb7ba2
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
+#define _DT_BINDINGS_CLK_SUN8I_H3_H_
+
+#define CLK_CPUX               14
+
+#define CLK_BUS_CE             20
+#define CLK_BUS_DMA            21
+#define CLK_BUS_MMC0           22
+#define CLK_BUS_MMC1           23
+#define CLK_BUS_MMC2           24
+#define CLK_BUS_NAND           25
+#define CLK_BUS_DRAM           26
+#define CLK_BUS_EMAC           27
+#define CLK_BUS_TS             28
+#define CLK_BUS_HSTIMER                29
+#define CLK_BUS_SPI0           30
+#define CLK_BUS_SPI1           31
+#define CLK_BUS_OTG            32
+#define CLK_BUS_EHCI0          33
+#define CLK_BUS_EHCI1          34
+#define CLK_BUS_EHCI2          35
+#define CLK_BUS_EHCI3          36
+#define CLK_BUS_OHCI0          37
+#define CLK_BUS_OHCI1          38
+#define CLK_BUS_OHCI2          39
+#define CLK_BUS_OHCI3          40
+#define CLK_BUS_VE             41
+#define CLK_BUS_TCON0          42
+#define CLK_BUS_TCON1          43
+#define CLK_BUS_DEINTERLACE    44
+#define CLK_BUS_CSI            45
+#define CLK_BUS_TVE            46
+#define CLK_BUS_HDMI           47
+#define CLK_BUS_DE             48
+#define CLK_BUS_GPU            49
+#define CLK_BUS_MSGBOX         50
+#define CLK_BUS_SPINLOCK       51
+#define CLK_BUS_CODEC          52
+#define CLK_BUS_SPDIF          53
+#define CLK_BUS_PIO            54
+#define CLK_BUS_THS            55
+#define CLK_BUS_I2S0           56
+#define CLK_BUS_I2S1           57
+#define CLK_BUS_I2S2           58
+#define CLK_BUS_I2C0           59
+#define CLK_BUS_I2C1           60
+#define CLK_BUS_I2C2           61
+#define CLK_BUS_UART0          62
+#define CLK_BUS_UART1          63
+#define CLK_BUS_UART2          64
+#define CLK_BUS_UART3          65
+#define CLK_BUS_SCR            66
+#define CLK_BUS_EPHY           67
+#define CLK_BUS_DBG            68
+
+#define CLK_THS                        69
+#define CLK_NAND               70
+#define CLK_MMC0               71
+#define CLK_MMC0_SAMPLE                72
+#define CLK_MMC0_OUTPUT                73
+#define CLK_MMC1               74
+#define CLK_MMC1_SAMPLE                75
+#define CLK_MMC1_OUTPUT                76
+#define CLK_MMC2               77
+#define CLK_MMC2_SAMPLE                78
+#define CLK_MMC2_OUTPUT                79
+#define CLK_TS                 80
+#define CLK_CE                 81
+#define CLK_SPI0               82
+#define CLK_SPI1               83
+#define CLK_I2S0               84
+#define CLK_I2S1               85
+#define CLK_I2S2               86
+#define CLK_SPDIF              87
+#define CLK_USB_PHY0           88
+#define CLK_USB_PHY1           89
+#define CLK_USB_PHY2           90
+#define CLK_USB_PHY3           91
+#define CLK_USB_OHCI0          92
+#define CLK_USB_OHCI1          93
+#define CLK_USB_OHCI2          94
+#define CLK_USB_OHCI3          95
+
+#define CLK_DRAM_VE            97
+#define CLK_DRAM_CSI           98
+#define CLK_DRAM_DEINTERLACE   99
+#define CLK_DRAM_TS            100
+#define CLK_DE                 101
+#define CLK_TCON0              102
+#define CLK_TVE                        103
+#define CLK_DEINTERLACE                104
+#define CLK_CSI_MISC           105
+#define CLK_CSI_SCLK           106
+#define CLK_CSI_MCLK           107
+#define CLK_VE                 108
+#define CLK_AC_DIG             109
+#define CLK_AVS                        110
+#define CLK_HDMI               111
+#define CLK_HDMI_DDC           112
+
+#define CLK_GPU                        114
+
+#endif /* _DT_BINDINGS_CLK_SUN8I_H3_H_ */
index bd3530e56d4699e8a9b87f7e3bdb136b648065a6..35288b20f2c9cffcaebdf5075946b25dce6fad4b 100644 (file)
 #define TEGRA210_CLK_CLK_OUT_3 279
 #define TEGRA210_CLK_BLINK 280
 /* 281 */
-/* 282 */
+#define TEGRA210_CLK_SOR1_SRC 282
 /* 283 */
 #define TEGRA210_CLK_XUSB_HOST_SRC 284
 #define TEGRA210_CLK_XUSB_FALCON_SRC 285
diff --git a/include/dt-bindings/reset/sun8i-h3-ccu.h b/include/dt-bindings/reset/sun8i-h3-ccu.h
new file mode 100644 (file)
index 0000000..6b7af80
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN8I_H3_H_
+#define _DT_BINDINGS_RST_SUN8I_H3_H_
+
+#define RST_USB_PHY0           0
+#define RST_USB_PHY1           1
+#define RST_USB_PHY2           2
+#define RST_USB_PHY3           3
+
+#define RST_MBUS               4
+
+#define RST_BUS_CE             5
+#define RST_BUS_DMA            6
+#define RST_BUS_MMC0           7
+#define RST_BUS_MMC1           8
+#define RST_BUS_MMC2           9
+#define RST_BUS_NAND           10
+#define RST_BUS_DRAM           11
+#define RST_BUS_EMAC           12
+#define RST_BUS_TS             13
+#define RST_BUS_HSTIMER                14
+#define RST_BUS_SPI0           15
+#define RST_BUS_SPI1           16
+#define RST_BUS_OTG            17
+#define RST_BUS_EHCI0          18
+#define RST_BUS_EHCI1          19
+#define RST_BUS_EHCI2          20
+#define RST_BUS_EHCI3          21
+#define RST_BUS_OHCI0          22
+#define RST_BUS_OHCI1          23
+#define RST_BUS_OHCI2          24
+#define RST_BUS_OHCI3          25
+#define RST_BUS_VE             26
+#define RST_BUS_TCON0          27
+#define RST_BUS_TCON1          28
+#define RST_BUS_DEINTERLACE    29
+#define RST_BUS_CSI            30
+#define RST_BUS_TVE            31
+#define RST_BUS_HDMI0          32
+#define RST_BUS_HDMI1          33
+#define RST_BUS_DE             34
+#define RST_BUS_GPU            35
+#define RST_BUS_MSGBOX         36
+#define RST_BUS_SPINLOCK       37
+#define RST_BUS_DBG            38
+#define RST_BUS_EPHY           39
+#define RST_BUS_CODEC          40
+#define RST_BUS_SPDIF          41
+#define RST_BUS_THS            42
+#define RST_BUS_I2S0           43
+#define RST_BUS_I2S1           44
+#define RST_BUS_I2S2           45
+#define RST_BUS_I2C0           46
+#define RST_BUS_I2C1           47
+#define RST_BUS_I2C2           48
+#define RST_BUS_UART0          49
+#define RST_BUS_UART1          50
+#define RST_BUS_UART2          51
+#define RST_BUS_UART3          52
+#define RST_BUS_SCR            53
+
+#endif /* _DT_BINDINGS_RST_SUN8I_H3_H_ */
index fb39d5add173f94a3f9be0e77455e0f5b54764d8..a39c0c530778251b6d43920c6ff9de6f05c5e738 100644 (file)
@@ -33,6 +33,8 @@
 #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 */
 #define CLK_IS_CRITICAL                BIT(11) /* do not gate, ever */
+/* parents need enable during gate/ungate, set rate and re-parent */
+#define CLK_OPS_PARENT_ENABLE  BIT(12)
 
 struct clk;
 struct clk_hw;
@@ -293,6 +295,7 @@ void clk_unregister_fixed_rate(struct clk *clk);
 struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
                const char *name, const char *parent_name, unsigned long flags,
                unsigned long fixed_rate, unsigned long fixed_accuracy);
+void clk_hw_unregister_fixed_rate(struct clk_hw *hw);
 
 void of_fixed_clk_setup(struct device_node *np);
 
index 834179f3fa72a4508509f0a3991385f63cfed417..123c02788807f553feeeca0d2ea9c39cddab537f 100644 (file)
@@ -20,8 +20,6 @@ struct device;
 
 struct clk;
 
-#ifdef CONFIG_COMMON_CLK
-
 /**
  * DOC: clk notifier callback types
  *
@@ -78,6 +76,8 @@ struct clk_notifier_data {
        unsigned long           new_rate;
 };
 
+#ifdef CONFIG_COMMON_CLK
+
 /**
  * clk_notifier_register: register a clock rate-change notifier callback
  * @clk: clock whose rate we are interested in
@@ -140,6 +140,18 @@ bool clk_is_match(const struct clk *p, const struct clk *q);
 
 #else
 
+static inline int clk_notifier_register(struct clk *clk,
+                                       struct notifier_block *nb)
+{
+       return -ENOTSUPP;
+}
+
+static inline int clk_notifier_unregister(struct clk *clk,
+                                         struct notifier_block *nb)
+{
+       return -ENOTSUPP;
+}
+
 static inline long clk_get_accuracy(struct clk *clk)
 {
        return -ENOTSUPP;