]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 13 Dec 2016 16:54:27 +0000 (08:54 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 13 Dec 2016 16:54:27 +0000 (08:54 -0800)
Pull clk updates from Stephen Boyd:
 "This is a fairly quiet release. We don't have any patches to the core
  framework. The only patch that can even be considered "core" adds
  another clk_get() variant. The rest of the changes are in drivers for
  various SoCs, and we have a few bits for ARM shmobile architecture
  code (dts and mach) due to the dependency we're breaking between
  shmobile architecture code and its clk driver. Those shmobile bits
  have also been pulled into arm-soc tree. Here's the summary:

  Core:

   - Support for devm_get_clk_from_child() used with DT bindings that
     have subnodes with the 'clocks' property

  New Drivers:

   - Allwinner A64 (sun50i)
   - i.MX imx6ull
   - Socionext's UniPhier SoC CPUs
   - Mediatek MT2701 SoCs
   - Rockchip rk1108 SoCs
   - Qualcomm MSM8994/MSM8992 SoCS
   - Qualcomm RPM Clocks
   - Hisilicon Hi3516CV300 and Hi3798CV200 CRG
   - Oxford Semiconductor OX820 and OX810SE SoCs
   - Renesas RZ/G1M and RZ/GIE SoCs
   - Renesas R-Car RST driver for mode pin states

  Updates:

   - Four Allwinner SoCs are migrated to the new style clk driver
   - Rockchip rk3399,rk3066 PLL optimizations
   - i.MX LVDS display glitch fixes and AV PLL precision improvements
   - Qualcomm MSM8996 GPU GDSCs, hw controlled GDSCs, and Alpha PLL
     support
   - Explicit demodularization of always builtin drivers
   - Freescale Qoriq ls1012a and ls1046a support
   - Exynos 5433 parent typo fix and critical clock tagging
   - Renesas r8a7743/r8a7745 CPG
   - Renesas R-Car M3-W CSI2/VIN/SYS-DMAC/(H)SCIF/I2C/DRIF/gfx support
   - stm32f4* LSI, LSE, RTC, and QSPI clocks
   - pxa27x and pxa25x cpufreq as clks
   - TI omap36xx sprz319 advisory 2.1 workaround
   - Broadcom bcm2835 rate change propogation to PLLH_AUX from VEC"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (150 commits)
  clk: bcm: Fix 'maybe-uninitialized' warning in bcm2835_clock_choose_div_and_prate()
  clk: add devm_get_clk_from_child() API
  clk: st: clk-flexgen: Unmap region obtained by of_iomap
  clk: keystone: pll: Unmap region obtained by of_iomap
  clk:mmp:clk-of-mmp2: Free memory and Unmap region obtained by kzalloc and of_iomap
  clk:mmp:clk-of-pxa910: Free memory and Unmap region obtained by kzmalloc and of_iomap
  clk: mmp: clk-of-pxa1928: Free memory obtained by kzalloc
  clk: cdce925: Fix limit check
  clk: bcm: Make COMMON_CLK_IPROC into a library
  clk: qoriq: added ls1012a clock configuration
  clk: ti: dra7: fix "failed to lookup clock node gmac_gmii_ref_clk_div" boot message
  clk: bcm: Allow rate change propagation to PLLH_AUX on VEC clock
  clk: bcm: Support rate change propagation on bcm2835 clocks
  clk: bcm2835: Avoid overwriting the div info when disabling a pll_div clk
  clk: ti: omap36xx: Work around sprz319 advisory 2.1
  clk: clk-wm831x: fix a logic error
  clk: uniphier: add cpufreq data for LD11, LD20 SoCs
  clk: uniphier: add CPU-gear change (cpufreq) support
  clk: qcom: Put venus core0/1 gdscs to hw control mode
  clk: qcom: gdsc: Add support for gdscs with HW control
  ...

166 files changed:
Documentation/devicetree/bindings/clock/exynos5433-clock.txt
Documentation/devicetree/bindings/clock/hi3519-crg.txt [deleted file]
Documentation/devicetree/bindings/clock/hisi-crg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/oxnas,stdclk.txt
Documentation/devicetree/bindings/clock/qcom,gcc.txt
Documentation/devicetree/bindings/clock/qcom,rpmcc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
Documentation/devicetree/bindings/clock/sunxi-ccu.txt
Documentation/devicetree/bindings/reset/renesas,rst.txt [new file with mode: 0644]
arch/arm/boot/dts/r8a7778.dtsi
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791.dtsi
arch/arm/boot/dts/r8a7792.dtsi
arch/arm/boot/dts/r8a7793.dtsi
arch/arm/boot/dts/r8a7794.dtsi
arch/arm/mach-shmobile/setup-r8a7778.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-rcar-gen2.c
arch/arm64/boot/dts/renesas/r8a7795.dtsi
arch/arm64/boot/dts/renesas/r8a7796.dtsi
drivers/clk/Kconfig
drivers/clk/bcm/Kconfig
drivers/clk/bcm/clk-bcm2835.c
drivers/clk/clk-cdce925.c
drivers/clk/clk-devres.c
drivers/clk/clk-gate.c
drivers/clk/clk-oxnas.c
drivers/clk/clk-qoriq.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-wm831x.c
drivers/clk/hisilicon/Kconfig
drivers/clk/hisilicon/Makefile
drivers/clk/hisilicon/crg-hi3516cv300.c [new file with mode: 0644]
drivers/clk/hisilicon/crg-hi3798cv200.c [new file with mode: 0644]
drivers/clk/hisilicon/crg.h [new file with mode: 0644]
drivers/clk/imx/clk-imx6q.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/imx/clk-pllv3.c
drivers/clk/imx/clk.h
drivers/clk/keystone/pll.c
drivers/clk/mediatek/Kconfig
drivers/clk/mediatek/Makefile
drivers/clk/mediatek/clk-gate.c
drivers/clk/mediatek/clk-gate.h
drivers/clk/mediatek/clk-mt2701-bdp.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701-eth.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701-hif.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701-img.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701-mm.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701-vdec.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mtk.c
drivers/clk/mediatek/clk-mtk.h
drivers/clk/mediatek/clk-pll.c
drivers/clk/mmp/clk-of-mmp2.c
drivers/clk/mmp/clk-of-pxa1928.c
drivers/clk/mmp/clk-of-pxa910.c
drivers/clk/mvebu/ap806-system-controller.c
drivers/clk/mvebu/cp110-system-controller.c
drivers/clk/nxp/clk-lpc18xx-ccu.c
drivers/clk/nxp/clk-lpc32xx.c
drivers/clk/pxa/clk-pxa.c
drivers/clk/pxa/clk-pxa.h
drivers/clk/pxa/clk-pxa25x.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/Makefile
drivers/clk/qcom/clk-alpha-pll.c
drivers/clk/qcom/clk-alpha-pll.h
drivers/clk/qcom/clk-pll.c
drivers/clk/qcom/clk-rcg.h
drivers/clk/qcom/clk-rcg2.c
drivers/clk/qcom/clk-rpm.c [new file with mode: 0644]
drivers/clk/qcom/clk-smd-rpm.c [new file with mode: 0644]
drivers/clk/qcom/common.c
drivers/clk/qcom/common.h
drivers/clk/qcom/gcc-apq8084.c
drivers/clk/qcom/gcc-ipq4019.c
drivers/clk/qcom/gcc-ipq806x.c
drivers/clk/qcom/gcc-msm8916.c
drivers/clk/qcom/gcc-msm8974.c
drivers/clk/qcom/gcc-msm8994.c [new file with mode: 0644]
drivers/clk/qcom/gcc-msm8996.c
drivers/clk/qcom/gdsc.c
drivers/clk/qcom/gdsc.h
drivers/clk/qcom/lcc-ipq806x.c
drivers/clk/qcom/mmcc-msm8996.c
drivers/clk/renesas/Kconfig
drivers/clk/renesas/Makefile
drivers/clk/renesas/clk-r8a7778.c
drivers/clk/renesas/clk-r8a7779.c
drivers/clk/renesas/clk-rcar-gen2.c
drivers/clk/renesas/r8a7743-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r8a7745-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c
drivers/clk/renesas/rcar-gen2-cpg.c [new file with mode: 0644]
drivers/clk/renesas/rcar-gen2-cpg.h [new file with mode: 0644]
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/rockchip/Makefile
drivers/clk/rockchip/clk-cpu.c
drivers/clk/rockchip/clk-pll.c
drivers/clk/rockchip/clk-rk1108.c [new file with mode: 0644]
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/rockchip/clk.h
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/st/clk-flexgen.c
drivers/clk/sunxi-ng/Kconfig
drivers/clk/sunxi-ng/Makefile
drivers/clk/sunxi-ng/ccu-sun50i-a64.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun50i-a64.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun8i-a23.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu_div.h
drivers/clk/sunxi-ng/ccu_frac.c
drivers/clk/sunxi-ng/ccu_frac.h
drivers/clk/sunxi-ng/ccu_mp.h
drivers/clk/sunxi-ng/ccu_mult.c
drivers/clk/sunxi-ng/ccu_mult.h
drivers/clk/sunxi-ng/ccu_nk.c
drivers/clk/sunxi-ng/ccu_nk.h
drivers/clk/sunxi-ng/ccu_nkm.c
drivers/clk/sunxi-ng/ccu_nkm.h
drivers/clk/sunxi-ng/ccu_nkmp.c
drivers/clk/sunxi-ng/ccu_nkmp.h
drivers/clk/sunxi-ng/ccu_nm.c
drivers/clk/sunxi-ng/ccu_nm.h
drivers/clk/sunxi/clk-mod0.c
drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
drivers/clk/tegra/cvb.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clock.h
drivers/clk/ti/dpll.c
drivers/clk/ti/dpll3xxx.c
drivers/clk/uniphier/Makefile
drivers/clk/uniphier/clk-uniphier-core.c
drivers/clk/uniphier/clk-uniphier-cpugear.c [new file with mode: 0644]
drivers/clk/uniphier/clk-uniphier-sys.c
drivers/clk/uniphier/clk-uniphier.h
drivers/soc/renesas/Makefile
drivers/soc/renesas/rcar-rst.c [new file with mode: 0644]
include/dt-bindings/clock/hi3516cv300-clock.h [new file with mode: 0644]
include/dt-bindings/clock/histb-clock.h [new file with mode: 0644]
include/dt-bindings/clock/imx6ul-clock.h
include/dt-bindings/clock/oxsemi,ox810se.h [new file with mode: 0644]
include/dt-bindings/clock/oxsemi,ox820.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,gcc-msm8994.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,rpmcc.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7743-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7745-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/rk1108-cru.h [new file with mode: 0644]
include/dt-bindings/clock/rk3188-cru-common.h
include/dt-bindings/clock/sun50i-a64-ccu.h [new file with mode: 0644]
include/dt-bindings/reset/sun50i-a64-ccu.h [new file with mode: 0644]
include/linux/clk.h
include/linux/clk/renesas.h
include/linux/soc/renesas/rcar-rst.h [new file with mode: 0644]

index 63379b04e05224331cf7abf4d7948c8848287e41..1dc80f8811fe8ba03b13c1180301a255983d33ad 100644 (file)
@@ -79,7 +79,7 @@ Required Properties:
        Input clocks for fsys clock controller:
                - oscclk
                - sclk_ufs_mphy
-               - div_aclk_fsys_200
+               - aclk_fsys_200
                - sclk_pcie_100_fsys
                - sclk_ufsunipro_fsys
                - sclk_mmc2_fsys
@@ -104,6 +104,10 @@ Required Properties:
                - sclk_decon_tv_vclk_disp
                - aclk_disp_333
 
+       Input clocks for audio clock controller:
+               - oscclk
+               - fout_aud_pll
+
        Input clocks for bus0 clock controller:
                - aclk_bus0_400
 
@@ -235,7 +239,7 @@ Example 2: Examples of clock controller nodes are listed below.
 
                clock-names = "oscclk",
                        "sclk_ufs_mphy",
-                       "div_aclk_fsys_200",
+                       "aclk_fsys_200",
                        "sclk_pcie_100_fsys",
                        "sclk_ufsunipro_fsys",
                        "sclk_mmc2_fsys",
@@ -245,7 +249,7 @@ Example 2: Examples of clock controller nodes are listed below.
                        "sclk_usbdrd30_fsys";
                clocks = <&xxti>,
                       <&cmu_cpif CLK_SCLK_UFS_MPHY>,
-                      <&cmu_top CLK_DIV_ACLK_FSYS_200>,
+                      <&cmu_top CLK_ACLK_FSYS_200>,
                       <&cmu_top CLK_SCLK_PCIE_100_FSYS>,
                       <&cmu_top CLK_SCLK_UFSUNIPRO_FSYS>,
                       <&cmu_top CLK_SCLK_MMC2_FSYS>,
@@ -297,6 +301,9 @@ Example 2: Examples of clock controller nodes are listed below.
                compatible = "samsung,exynos5433-cmu-aud";
                reg = <0x114c0000 0x0b04>;
                #clock-cells = <1>;
+
+               clock-names = "oscclk", "fout_aud_pll";
+               clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>;
        };
 
        cmu_bus0: clock-controller@13600000 {
diff --git a/Documentation/devicetree/bindings/clock/hi3519-crg.txt b/Documentation/devicetree/bindings/clock/hi3519-crg.txt
deleted file mode 100644 (file)
index acd1f23..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-* Hisilicon Hi3519 Clock and Reset Generator(CRG)
-
-The Hi3519 CRG module provides clock and reset signals to various
-controllers within the SoC.
-
-This binding uses the following bindings:
-    Documentation/devicetree/bindings/clock/clock-bindings.txt
-    Documentation/devicetree/bindings/reset/reset.txt
-
-Required Properties:
-
-- compatible: should be one of the following.
-  - "hisilicon,hi3519-crg" - controller compatible with Hi3519 SoC.
-
-- reg: physical base address of the controller and length of memory mapped
-  region.
-
-- #clock-cells: should be 1.
-
-Each clock is assigned an identifier and client nodes use this identifier
-to specify the clock which they consume.
-
-All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
-
-- #reset-cells: should be 2.
-
-A reset signal can be controlled by writing a bit register in the CRG module.
-The reset specifier consists of two cells. The first cell represents the
-register offset relative to the base address. The second cell represents the
-bit index in the register.
-
-Example: CRG nodes
-CRG: clock-reset-controller@12010000 {
-       compatible = "hisilicon,hi3519-crg";
-       reg = <0x12010000 0x10000>;
-       #clock-cells = <1>;
-       #reset-cells = <2>;
-};
-
-Example: consumer nodes
-i2c0: i2c@12110000 {
-       compatible = "hisilicon,hi3519-i2c";
-       reg = <0x12110000 0x1000>;
-       clocks = <&CRG HI3519_I2C0_RST>;
-       resets = <&CRG 0xe4 0>;
-};
diff --git a/Documentation/devicetree/bindings/clock/hisi-crg.txt b/Documentation/devicetree/bindings/clock/hisi-crg.txt
new file mode 100644 (file)
index 0000000..cc60b3d
--- /dev/null
@@ -0,0 +1,50 @@
+* HiSilicon Clock and Reset Generator(CRG)
+
+The CRG module provides clock and reset signals to various
+modules within the SoC.
+
+This binding uses the following bindings:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+    Documentation/devicetree/bindings/reset/reset.txt
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "hisilicon,hi3516cv300-crg"
+  - "hisilicon,hi3516cv300-sysctrl"
+  - "hisilicon,hi3519-crg"
+  - "hisilicon,hi3798cv200-crg"
+  - "hisilicon,hi3798cv200-sysctrl"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
+
+- #reset-cells: should be 2.
+
+A reset signal can be controlled by writing a bit register in the CRG module.
+The reset specifier consists of two cells. The first cell represents the
+register offset relative to the base address. The second cell represents the
+bit index in the register.
+
+Example: CRG nodes
+CRG: clock-reset-controller@12010000 {
+       compatible = "hisilicon,hi3519-crg";
+       reg = <0x12010000 0x10000>;
+       #clock-cells = <1>;
+       #reset-cells = <2>;
+};
+
+Example: consumer nodes
+i2c0: i2c@12110000 {
+       compatible = "hisilicon,hi3519-i2c";
+       reg = <0x12110000 0x1000>;
+       clocks = <&CRG HI3519_I2C0_RST>;
+       resets = <&CRG 0xe4 0>;
+};
index 208cca6ac4ecebdf2207c9cf4299b0127f362a24..b652f3fb77965cf70318349c449904d72b31c86d 100644 (file)
@@ -5,22 +5,15 @@ Please also refer to clock-bindings.txt in this directory for common clock
 bindings usage.
 
 Required properties:
-- compatible: Should be "oxsemi,ox810se-stdclk"
+- compatible: For OX810SE, should be "oxsemi,ox810se-stdclk"
+             For OX820, should be "oxsemi,ox820-stdclk"
 - #clock-cells: 1, see below
 
 Parent node should have the following properties :
-- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
-
-For OX810SE, the clock indices are :
- - 0: LEON
- - 1: DMA_SGDMA
- - 2: CIPHER
- - 3: SATA
- - 4: AUDIO
- - 5: USBMPH
- - 6: ETHA
- - 7: PCIA
- - 8: NAND
+- compatible: For OX810SE, should be
+               "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+             For OX820, should be
+               "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd"
 
 example:
 
index 3cf44217068e4d7097203e09177b125fdaa96cf5..5b4dfc1ea54fb592cc1ce3fd10d9d6a1c105d525 100644 (file)
@@ -14,6 +14,7 @@ Required properties :
                        "qcom,gcc-msm8974"
                        "qcom,gcc-msm8974pro"
                        "qcom,gcc-msm8974pro-ac"
+                       "qcom,gcc-msm8994"
                        "qcom,gcc-msm8996"
                        "qcom,gcc-mdm9615"
 
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
new file mode 100644 (file)
index 0000000..87d3714
--- /dev/null
@@ -0,0 +1,37 @@
+Qualcomm RPM Clock Controller Binding
+------------------------------------------------
+The RPM is a dedicated hardware engine for managing the shared
+SoC resources in order to keep the lowest power profile. It
+communicates with other hardware subsystems via shared memory
+and accepts clock requests, aggregates the requests and turns
+the clocks on/off or scales them on demand.
+
+Required properties :
+- compatible : shall contain only one of the following. The generic
+               compatible "qcom,rpmcc" should be also included.
+
+                       "qcom,rpmcc-msm8916", "qcom,rpmcc"
+                       "qcom,rpmcc-apq8064", "qcom,rpmcc"
+
+- #clock-cells : shall contain 1
+
+Example:
+       smd {
+               compatible = "qcom,smd";
+
+               rpm {
+                       interrupts = <0 168 1>;
+                       qcom,ipc = <&apcs 8 0>;
+                       qcom,smd-edge = <15>;
+
+                       rpm_requests {
+                               compatible = "qcom,rpm-msm8916";
+                               qcom,smd-channels = "rpm_requests";
+
+                               rpmcc: clock-controller {
+                                       compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc";
+                                       #clock-cells = <1>;
+                               };
+                       };
+               };
+       };
index 394d725ac7e0baa3bf8ba8429409ba5d0c017d4c..c469194129536332ee88c8d8ed47e9a4d507336c 100644 (file)
@@ -13,6 +13,8 @@ They provide the following functionalities:
 
 Required Properties:
   - compatible: Must be one of:
+      - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
+      - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
       - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
       - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
 
@@ -22,8 +24,9 @@ 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, r8a7796)
+      - "extal" (r8a7743, r8a7745, r8a7795, r8a7796)
       - "extalr" (r8a7795, r8a7796)
+      - "usb_extal" (r8a7743, r8a7745)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
new file mode 100644 (file)
index 0000000..4da1261
--- /dev/null
@@ -0,0 +1,59 @@
+* Rockchip RK1108 Clock and Reset Unit
+
+The RK1108 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk1108-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk1108-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_vip" - external VIP clock - optional
+ - "ext_i2s" - external I2S clock - optional
+ - "ext_gmac" - external GMAC clock - optional
+ - "hdmiphy" - external clock input derived from HDMI PHY - optional
+ - "usbphy" - external clock input derived from USB PHY - optional
+
+Example: Clock controller node:
+
+       cru: cru@20200000 {
+               compatible = "rockchip,rk1108-cru";
+               reg = <0x20200000 0x1000>;
+               rockchip,grf = <&grf>;
+
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+       uart0: serial@10230000 {
+               compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+               reg = <0x10230000 0x100>;
+               interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               clocks = <&cru SCLK_UART0>;
+       };
index c209de6cfadbf0fe0d8350f302577075b7881aa7..0532d815dae322045de67032428ac411c6b82f9d 100644 (file)
@@ -7,7 +7,9 @@ Please refer to clock-bindings.txt for common clock controller binding usage.
 Please also refer to reset.txt for common reset controller binding usage.
 
 Required properties:
-- compatible: Should be "st,stm32f42xx-rcc"
+- compatible: Should be:
+  "st,stm32f42xx-rcc"
+  "st,stm32f469-rcc"
 - reg: should be register base and length as documented in the
   datasheet
 - #reset-cells: 1, see below
index 3868458a5feb7cdc2f2c1c7bc54df465bb530ab4..74d44a4273f2d19b728989d85e852b1df0f2c2e7 100644 (file)
@@ -7,6 +7,7 @@ Required properties :
                - "allwinner,sun8i-a23-ccu"
                - "allwinner,sun8i-a33-ccu"
                - "allwinner,sun8i-h3-ccu"
+               - "allwinner,sun50i-a64-ccu"
 
 - reg: Must contain the registers base address and length
 - clocks: phandle to the oscillators feeding the CCU. Two are needed:
diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.txt b/Documentation/devicetree/bindings/reset/renesas,rst.txt
new file mode 100644 (file)
index 0000000..fe5e0f3
--- /dev/null
@@ -0,0 +1,37 @@
+DT bindings for the Renesas R-Car and RZ/G Reset Controllers
+
+The R-Car and RZ/G Reset Controllers provide reset control, and implement the
+following functions:
+  - Latching of the levels on mode pins when PRESET# is negated,
+  - Mode monitoring register,
+  - Reset control of peripheral devices (on R-Car Gen1),
+  - Watchdog timer (on R-Car Gen1),
+  - Register-based reset control and boot address registers for the various CPU
+    cores (on R-Car Gen2 and Gen3, and on RZ/G).
+
+
+Required properties:
+  - compatible: Should be
+                 - "renesas,<soctype>-reset-wdt" for R-Car Gen1,
+                 - "renesas,<soctype>-rst" for R-Car Gen2 and Gen3, and RZ/G
+               Examples with soctypes are:
+                 - "renesas,r8a7743-rst" (RZ/G1M)
+                 - "renesas,r8a7745-rst" (RZ/G1E)
+                 - "renesas,r8a7778-reset-wdt" (R-Car M1A)
+                 - "renesas,r8a7779-reset-wdt" (R-Car H1)
+                 - "renesas,r8a7790-rst" (R-Car H2)
+                 - "renesas,r8a7791-rst" (R-Car M2-W)
+                 - "renesas,r8a7792-rst" (R-Car V2H
+                 - "renesas,r8a7793-rst" (R-Car M2-N)
+                 - "renesas,r8a7794-rst" (R-Car E2)
+                 - "renesas,r8a7795-rst" (R-Car H3)
+                 - "renesas,r8a7796-rst" (R-Car M3-W)
+  - reg: Address start and address range for the device.
+
+
+Example:
+
+       rst: reset-controller@e6160000 {
+               compatible = "renesas,r8a7795-rst";
+               reg = <0 0xe6160000 0 0x0200>;
+       };
index e571d66ea0fe17218d02b9f0d349b82efd24d604..3d0a18abd408c76d2997d6c44063513ec22c336e 100644 (file)
                                "sru-src6", "sru-src7", "sru-src8";
                };
        };
+
+       rst: reset-controller@ffcc0000 {
+               compatible = "renesas,r8a7778-reset-wdt";
+               reg = <0xffcc0000 0x40>;
+       };
 };
index b9bbcce69dfbd5b9efda7ae20a83752cf459c925..8cf16008a09b9a26be041b4e7dadf64eaf18635b 100644 (file)
                };
        };
 
+       rst: reset-controller@ffcc0000 {
+               compatible = "renesas,r8a7779-reset-wdt";
+               reg = <0xffcc0000 0x48>;
+       };
+
        sysc: system-controller@ffd85000 {
                compatible = "renesas,r8a7779-sysc";
                reg = <0xffd85000 0x0200>;
index 351fcc2f87df6b28b83e29f14e52b95a9dd6b553..3f10b0bf1b08fa89cf3744579366ec6a73c5f4d8 100644 (file)
                };
        };
 
+       rst: reset-controller@e6160000 {
+               compatible = "renesas,r8a7790-rst";
+               reg = <0 0xe6160000 0 0x0100>;
+       };
+
        sysc: system-controller@e6180000 {
                compatible = "renesas,r8a7790-sysc";
                reg = <0 0xe6180000 0 0x0200>;
index 162b55c665a3519ea9f6895b93c7ddd6b6cfc909..c465c79bcca6e8f31503fd1875bf6bc84e612d7d 100644 (file)
                };
        };
 
+       rst: reset-controller@e6160000 {
+               compatible = "renesas,r8a7791-rst";
+               reg = <0 0xe6160000 0 0x0100>;
+       };
+
        sysc: system-controller@e6180000 {
                compatible = "renesas,r8a7791-sysc";
                reg = <0 0xe6180000 0 0x0200>;
index 713141d38b3ea960fcee7dfdbd9317bbc0527536..6e1f61f65d292b0bea394ff3e36d4feaf8330839 100644 (file)
                                      IRQ_TYPE_LEVEL_LOW)>;
                };
 
+               rst: reset-controller@e6160000 {
+                       compatible = "renesas,r8a7792-rst";
+                       reg = <0 0xe6160000 0 0x0100>;
+               };
+
                sysc: system-controller@e6180000 {
                        compatible = "renesas,r8a7792-sysc";
                        reg = <0 0xe6180000 0 0x0200>;
index 8d02aacf2892627155ea82c3f6414c614b33ebb5..e4b385eccf74e95e381dcf7fc4cf308b8c38c5b1 100644 (file)
                };
        };
 
+       rst: reset-controller@e6160000 {
+               compatible = "renesas,r8a7793-rst";
+               reg = <0 0xe6160000 0 0x0100>;
+       };
+
        sysc: system-controller@e6180000 {
                compatible = "renesas,r8a7793-sysc";
                reg = <0 0xe6180000 0 0x0200>;
index 9365580a194facc788ad5e3f76fa4808da69eb68..69e4f4fad89b23230c2e29053f4f3333b3db124f 100644 (file)
                };
        };
 
+       rst: reset-controller@e6160000 {
+               compatible = "renesas,r8a7794-rst";
+               reg = <0 0xe6160000 0 0x0100>;
+       };
+
        sysc: system-controller@e6180000 {
                compatible = "renesas,r8a7794-sysc";
                reg = <0 0xe6180000 0 0x0200>;
index cf236db686a9dd47458f96c7da9e247c1d11f0ea..7fa4a0b5f6549287c7db537f36aaabdc48e04093 100644 (file)
@@ -15,7 +15,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/clk/renesas.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
 
 
 #include "common.h"
 
-#define MODEMR 0xffcc0020
-
-static void __init r8a7778_timer_init(void)
-{
-       u32 mode;
-       void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-
-       BUG_ON(!modemr);
-       mode = ioread32(modemr);
-       iounmap(modemr);
-       r8a7778_clocks_init(mode);
-}
-
 #define INT2SMSKCR0    0x82288 /* 0xfe782288 */
 #define INT2SMSKCR1    0x8228c /* 0xfe78228c */
 
@@ -70,6 +56,5 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
        .init_early     = shmobile_init_delay,
        .init_irq       = r8a7778_init_irq_dt,
        .init_late      = shmobile_init_late,
-       .init_time      = r8a7778_timer_init,
        .dt_compat      = r8a7778_compat_dt,
 MACHINE_END
index 0007ff51d180379ffa2f674323ea9847ed883837..0686112f243525b64ba771f31d3e6b93d7b3d9a1 100644 (file)
@@ -14,8 +14,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <linux/clk/renesas.h>
-#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
@@ -76,30 +74,6 @@ static void __init r8a7779_init_irq_dt(void)
        __raw_writel(0x003fee3f, INT2SMSKCR4);
 }
 
-#define MODEMR         0xffcc0020
-
-static u32 __init r8a7779_read_mode_pins(void)
-{
-       static u32 mode;
-       static bool mode_valid;
-
-       if (!mode_valid) {
-               void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
-               BUG_ON(!modemr);
-               mode = ioread32(modemr);
-               iounmap(modemr);
-               mode_valid = true;
-       }
-
-       return mode;
-}
-
-static void __init r8a7779_init_time(void)
-{
-       r8a7779_clocks_init(r8a7779_read_mode_pins());
-       clocksource_probe();
-}
-
 static const char *const r8a7779_compat_dt[] __initconst = {
        "renesas,r8a7779",
        NULL,
@@ -109,7 +83,6 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
        .smp            = smp_ops(r8a7779_smp_ops),
        .map_io         = r8a7779_map_io,
        .init_early     = shmobile_init_delay,
-       .init_time      = r8a7779_init_time,
        .init_irq       = r8a7779_init_irq_dt,
        .init_late      = shmobile_init_late,
        .dt_compat      = r8a7779_compat_dt,
index afb9fdcd3d9084e26747fb1b34eb226493b43401..b527258e0a62e806b911ddf10612af41b30dd4c9 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/clk/renesas.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/device.h>
 #include <linux/dma-contiguous.h>
@@ -71,7 +71,6 @@ static unsigned int __init get_extal_freq(void)
 
 void __init rcar_gen2_timer_init(void)
 {
-       u32 mode = rcar_gen2_read_mode_pins();
 #ifdef CONFIG_ARM_ARCH_TIMER
        void __iomem *base;
        u32 freq;
@@ -130,7 +129,7 @@ void __init rcar_gen2_timer_init(void)
        iounmap(base);
 #endif /* CONFIG_ARM_ARCH_TIMER */
 
-       rcar_gen2_clocks_init(mode);
+       of_clk_init(NULL);
        clocksource_probe();
 }
 
index 8c15040f2540d63ada01a1c5acb62692268687fe..625dda713548da785d1fe3ced864d469dd4b4276 100644 (file)
                        #power-domain-cells = <0>;
                };
 
+               rst: reset-controller@e6160000 {
+                       compatible = "renesas,r8a7795-rst";
+                       reg = <0 0xe6160000 0 0x0200>;
+               };
+
                sysc: system-controller@e6180000 {
                        compatible = "renesas,r8a7795-sysc";
                        reg = <0 0xe6180000 0 0x0400>;
index 9217da9835256573477667cce41bc20355b7759c..75c8c55a824835bf29e61f162aef99c76ffc65d0 100644 (file)
                        #power-domain-cells = <0>;
                };
 
+               rst: reset-controller@e6160000 {
+                       compatible = "renesas,r8a7796-rst";
+                       reg = <0 0xe6160000 0 0x0200>;
+               };
+
                sysc: system-controller@e6180000 {
                        compatible = "renesas,r8a7796-sysc";
                        reg = <0 0xe6180000 0 0x0400>;
index 6a8ac04bedebdf13c2a2d1ff9c6e4543d7cc792b..56c1998ced3e12183e2a3a58e1ef27c0d7135556 100644 (file)
@@ -33,7 +33,7 @@ source "drivers/clk/versatile/Kconfig"
 
 config COMMON_CLK_MAX77686
        tristate "Clock driver for Maxim 77620/77686/77802 MFD"
-       depends on MFD_MAX77686 || MFD_MAX77620
+       depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST
        ---help---
          This driver supports Maxim 77620/77686/77802 crystal oscillator
          clock.
@@ -119,7 +119,7 @@ config COMMON_CLK_CS2000_CP
 
 config COMMON_CLK_S2MPS11
        tristate "Clock driver for S2MPS1X/S5M8767 MFD"
-       depends on MFD_SEC_CORE
+       depends on MFD_SEC_CORE || COMPILE_TEST
        ---help---
          This driver supports S2MPS11/S2MPS14/S5M8767 crystal oscillator
          clock. These multi-function devices have two (S2MPS14) or three
index e3eed5a784044c3db5e1260d82e7a200ff4b62e6..b5ae5311b0a24ecb5738d8f00eddebae6f3f72e0 100644 (file)
@@ -1,7 +1,6 @@
 config CLK_BCM_63XX
        bool "Broadcom BCM63xx clock support"
        depends on ARCH_BCM_63XX || COMPILE_TEST
-       depends on COMMON_CLK
        select COMMON_CLK_IPROC
        default ARCH_BCM_63XX
        help
@@ -11,27 +10,22 @@ config CLK_BCM_63XX
 config CLK_BCM_KONA
        bool "Broadcom Kona CCU clock support"
        depends on ARCH_BCM_MOBILE || COMPILE_TEST
-       depends on COMMON_CLK
-       default y
+       default ARCH_BCM_MOBILE
        help
          Enable common clock framework support for Broadcom SoCs
          using "Kona" style clock control units, including those
          in the BCM281xx and BCM21664 families.
 
 config COMMON_CLK_IPROC
-       bool "Broadcom iProc clock support"
-       depends on ARCH_BCM_IPROC || ARCH_BCM_63XX || COMPILE_TEST
-       depends on COMMON_CLK
-       default ARCH_BCM_IPROC
+       bool
        help
          Enable common clock framework support for Broadcom SoCs
          based on the iProc architecture
 
-if COMMON_CLK_IPROC
-
 config CLK_BCM_CYGNUS
        bool "Broadcom Cygnus clock support"
        depends on ARCH_BCM_CYGNUS || COMPILE_TEST
+       select COMMON_CLK_IPROC
        default ARCH_BCM_CYGNUS
        help
          Enable common clock framework support for the Broadcom Cygnus SoC
@@ -39,6 +33,7 @@ config CLK_BCM_CYGNUS
 config CLK_BCM_NSP
        bool "Broadcom Northstar/Northstar Plus clock support"
        depends on ARCH_BCM_5301X || ARCH_BCM_NSP || COMPILE_TEST
+       select COMMON_CLK_IPROC
        default ARCH_BCM_5301X || ARCH_BCM_NSP
        help
          Enable common clock framework support for the Broadcom Northstar and
@@ -47,8 +42,7 @@ config CLK_BCM_NSP
 config CLK_BCM_NS2
        bool "Broadcom Northstar 2 clock support"
        depends on ARCH_BCM_IPROC || COMPILE_TEST
+       select COMMON_CLK_IPROC
        default ARCH_BCM_IPROC
        help
          Enable common clock framework support for the Broadcom Northstar 2 SoC
-
-endif
index 8c7763fd9efc52b30f02d9ebcd4fdb10d2876465..0d14409097e777ce4546de30e9278fdebf74ec44 100644 (file)
@@ -436,6 +436,9 @@ struct bcm2835_clock_data {
        const char *const *parents;
        int num_mux_parents;
 
+       /* Bitmap encoding which parents accept rate change propagation. */
+       unsigned int set_rate_parent;
+
        u32 ctl_reg;
        u32 div_reg;
 
@@ -751,7 +754,9 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
        cprman_write(cprman, data->cm_reg,
                     (cprman_read(cprman, data->cm_reg) &
                      ~data->load_mask) | data->hold_mask);
-       cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+       cprman_write(cprman, data->a2w_reg,
+                    cprman_read(cprman, data->a2w_reg) |
+                    A2W_PLL_CHANNEL_DISABLE);
        spin_unlock(&cprman->regs_lock);
 }
 
@@ -1015,10 +1020,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw)
        return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
 }
 
+static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+                                                       int parent_idx,
+                                                       unsigned long rate,
+                                                       u32 *div,
+                                                       unsigned long *prate)
+{
+       struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+       struct bcm2835_cprman *cprman = clock->cprman;
+       const struct bcm2835_clock_data *data = clock->data;
+       unsigned long best_rate = 0;
+       u32 curdiv, mindiv, maxdiv;
+       struct clk_hw *parent;
+
+       parent = clk_hw_get_parent_by_index(hw, parent_idx);
+
+       if (!(BIT(parent_idx) & data->set_rate_parent)) {
+               *prate = clk_hw_get_rate(parent);
+               *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
+
+               return bcm2835_clock_rate_from_divisor(clock, *prate,
+                                                      *div);
+       }
+
+       if (data->frac_bits)
+               dev_warn(cprman->dev,
+                       "frac bits are not used when propagating rate change");
+
+       /* clamp to min divider of 2 if we're dealing with a mash clock */
+       mindiv = data->is_mash_clock ? 2 : 1;
+       maxdiv = BIT(data->int_bits) - 1;
+
+       /* TODO: Be smart, and only test a subset of the available divisors. */
+       for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
+               unsigned long tmp_rate;
+
+               tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
+               tmp_rate /= curdiv;
+               if (curdiv == mindiv ||
+                   (tmp_rate > best_rate && tmp_rate <= rate))
+                       best_rate = tmp_rate;
+
+               if (best_rate == rate)
+                       break;
+       }
+
+       *div = curdiv << CM_DIV_FRAC_BITS;
+       *prate = curdiv * best_rate;
+
+       return best_rate;
+}
+
 static int bcm2835_clock_determine_rate(struct clk_hw *hw,
                                        struct clk_rate_request *req)
 {
-       struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
        struct clk_hw *parent, *best_parent = NULL;
        bool current_parent_is_pllc;
        unsigned long rate, best_rate = 0;
@@ -1046,9 +1101,8 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
                if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
                        continue;
 
-               prate = clk_hw_get_rate(parent);
-               div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
-               rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
+               rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
+                                                         &div, &prate);
                if (rate > best_rate && rate <= req->rate) {
                        best_parent = parent;
                        best_prate = prate;
@@ -1260,6 +1314,13 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
        init.name = data->name;
        init.flags = data->flags | CLK_IGNORE_UNUSED;
 
+       /*
+        * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
+        * rate changes on at least of the parents.
+        */
+       if (data->set_rate_parent)
+               init.flags |= CLK_SET_RATE_PARENT;
+
        if (data->is_vpu_clock) {
                init.ops = &bcm2835_vpu_clock_clk_ops;
        } else {
@@ -1596,7 +1657,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
                .a2w_reg = A2W_PLLH_AUX,
                .load_mask = CM_PLLH_LOADAUX,
                .hold_mask = 0,
-               .fixed_divider = 10),
+               .fixed_divider = 1),
        [BCM2835_PLLH_PIX]      = REGISTER_PLL_DIV(
                .name = "pllh_pix",
                .source_pll = "pllh",
@@ -1800,7 +1861,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
                .ctl_reg = CM_VECCTL,
                .div_reg = CM_VECDIV,
                .int_bits = 4,
-               .frac_bits = 0),
+               .frac_bits = 0,
+               /*
+                * Allow rate change propagation only on PLLH_AUX which is
+                * assigned index 7 in the parent array.
+                */
+               .set_rate_parent = BIT(7)),
 
        /* dsi clocks */
        [BCM2835_CLOCK_DSI0E]   = REGISTER_PER_CLK(
index b8459c14a1b7245855a4b91eba0783da0cbf3d6d..f793b2d9238cea8df7d135e3a2d4fcbe20a37da4 100644 (file)
@@ -216,7 +216,7 @@ static int cdce925_pll_prepare(struct clk_hw *hw)
                nn = n * BIT(p);
                /* q = int(nn/m) */
                q = nn / m;
-               if ((q < 16) || (1 > 64)) {
+               if ((q < 16) || (q > 63)) {
                        pr_debug("%s invalid q=%d\n", __func__, q);
                        return -EINVAL;
                }
index 8f571548870f4b46b37854b3a6ebf90105f68154..3a218c3a06ae8d8169c384b722b5f08dd738ca5a 100644 (file)
@@ -53,3 +53,24 @@ void devm_clk_put(struct device *dev, struct clk *clk)
        WARN_ON(ret);
 }
 EXPORT_SYMBOL(devm_clk_put);
+
+struct clk *devm_get_clk_from_child(struct device *dev,
+                                   struct device_node *np, const char *con_id)
+{
+       struct clk **ptr, *clk;
+
+       ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       clk = of_clk_get_by_name(np, con_id);
+       if (!IS_ERR(clk)) {
+               *ptr = clk;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return clk;
+}
+EXPORT_SYMBOL(devm_get_clk_from_child);
index 4e691e35483a7ee5425b36f6d33668f741bdca6a..4e0c054a787c07f93c287c4d38b306dffd3ee409 100644 (file)
@@ -145,8 +145,8 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
        init.name = name;
        init.ops = &clk_gate_ops;
        init.flags = flags | CLK_IS_BASIC;
-       init.parent_names = (parent_name ? &parent_name: NULL);
-       init.num_parents = (parent_name ? 1 : 0);
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.num_parents = parent_name ? 1 : 0;
 
        /* struct clk_gate assignments */
        gate->reg = reg;
index 47649ac5d3993d08c2eae6a7db719cef96790949..e51e0023fc6ec5237624df015bb76f6adf6f0d7c 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/stringify.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
+#include <dt-bindings/clock/oxsemi,ox810se.h>
+#include <dt-bindings/clock/oxsemi,ox820.h>
+
 /* Standard regmap gate clocks */
-struct clk_oxnas {
+struct clk_oxnas_gate {
        struct clk_hw hw;
-       signed char bit;
+       unsigned int bit;
        struct regmap *regmap;
 };
 
+struct oxnas_stdclk_data {
+       struct clk_hw_onecell_data *onecell_data;
+       struct clk_oxnas_gate **gates;
+       unsigned int ngates;
+       struct clk_oxnas_pll **plls;
+       unsigned int nplls;
+};
+
 /* Regmap offsets */
 #define CLK_STAT_REGOFFSET     0x24
 #define CLK_SET_REGOFFSET      0x2c
 #define CLK_CLR_REGOFFSET      0x30
 
-static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw)
+static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
 {
-       return container_of(hw, struct clk_oxnas, hw);
+       return container_of(hw, struct clk_oxnas_gate, hw);
 }
 
-static int oxnas_clk_is_enabled(struct clk_hw *hw)
+static int oxnas_clk_gate_is_enabled(struct clk_hw *hw)
 {
-       struct clk_oxnas *std = to_clk_oxnas(hw);
+       struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
        int ret;
        unsigned int val;
 
@@ -55,29 +67,29 @@ static int oxnas_clk_is_enabled(struct clk_hw *hw)
        return val & BIT(std->bit);
 }
 
-static int oxnas_clk_enable(struct clk_hw *hw)
+static int oxnas_clk_gate_enable(struct clk_hw *hw)
 {
-       struct clk_oxnas *std = to_clk_oxnas(hw);
+       struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
 
        regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
 
        return 0;
 }
 
-static void oxnas_clk_disable(struct clk_hw *hw)
+static void oxnas_clk_gate_disable(struct clk_hw *hw)
 {
-       struct clk_oxnas *std = to_clk_oxnas(hw);
+       struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
 
        regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
 }
 
-static const struct clk_ops oxnas_clk_ops = {
-       .enable = oxnas_clk_enable,
-       .disable = oxnas_clk_disable,
-       .is_enabled = oxnas_clk_is_enabled,
+static const struct clk_ops oxnas_clk_gate_ops = {
+       .enable = oxnas_clk_gate_enable,
+       .disable = oxnas_clk_gate_disable,
+       .is_enabled = oxnas_clk_gate_is_enabled,
 };
 
-static const char *const oxnas_clk_parents[] = {
+static const char *const osc_parents[] = {
        "oscillator",
 };
 
@@ -85,63 +97,138 @@ static const char *const eth_parents[] = {
        "gmacclk",
 };
 
-#define DECLARE_STD_CLKP(__clk, __parent)                      \
-static const struct clk_init_data clk_##__clk##_init = {       \
-       .name = __stringify(__clk),                             \
-       .ops = &oxnas_clk_ops,                                  \
-       .parent_names = __parent,                               \
-       .num_parents = ARRAY_SIZE(__parent),                    \
+#define OXNAS_GATE(_name, _bit, _parents)                              \
+struct clk_oxnas_gate _name = {                                                \
+       .bit = (_bit),                                                  \
+       .hw.init = &(struct clk_init_data) {                            \
+               .name = #_name,                                         \
+               .ops = &oxnas_clk_gate_ops,                             \
+               .parent_names = _parents,                               \
+               .num_parents = ARRAY_SIZE(_parents),                    \
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
+       },                                                              \
 }
 
-#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents)
+static OXNAS_GATE(ox810se_leon, 0, osc_parents);
+static OXNAS_GATE(ox810se_dma_sgdma, 1, osc_parents);
+static OXNAS_GATE(ox810se_cipher, 2, osc_parents);
+static OXNAS_GATE(ox810se_sata, 4, osc_parents);
+static OXNAS_GATE(ox810se_audio, 5, osc_parents);
+static OXNAS_GATE(ox810se_usbmph, 6, osc_parents);
+static OXNAS_GATE(ox810se_etha, 7, eth_parents);
+static OXNAS_GATE(ox810se_pciea, 8, osc_parents);
+static OXNAS_GATE(ox810se_nand, 9, osc_parents);
+
+static struct clk_oxnas_gate *ox810se_gates[] = {
+       &ox810se_leon,
+       &ox810se_dma_sgdma,
+       &ox810se_cipher,
+       &ox810se_sata,
+       &ox810se_audio,
+       &ox810se_usbmph,
+       &ox810se_etha,
+       &ox810se_pciea,
+       &ox810se_nand,
+};
+
+static OXNAS_GATE(ox820_leon, 0, osc_parents);
+static OXNAS_GATE(ox820_dma_sgdma, 1, osc_parents);
+static OXNAS_GATE(ox820_cipher, 2, osc_parents);
+static OXNAS_GATE(ox820_sd, 3, osc_parents);
+static OXNAS_GATE(ox820_sata, 4, osc_parents);
+static OXNAS_GATE(ox820_audio, 5, osc_parents);
+static OXNAS_GATE(ox820_usbmph, 6, osc_parents);
+static OXNAS_GATE(ox820_etha, 7, eth_parents);
+static OXNAS_GATE(ox820_pciea, 8, osc_parents);
+static OXNAS_GATE(ox820_nand, 9, osc_parents);
+static OXNAS_GATE(ox820_ethb, 10, eth_parents);
+static OXNAS_GATE(ox820_pcieb, 11, osc_parents);
+static OXNAS_GATE(ox820_ref600, 12, osc_parents);
+static OXNAS_GATE(ox820_usbdev, 13, osc_parents);
+
+static struct clk_oxnas_gate *ox820_gates[] = {
+       &ox820_leon,
+       &ox820_dma_sgdma,
+       &ox820_cipher,
+       &ox820_sd,
+       &ox820_sata,
+       &ox820_audio,
+       &ox820_usbmph,
+       &ox820_etha,
+       &ox820_pciea,
+       &ox820_nand,
+       &ox820_etha,
+       &ox820_pciea,
+       &ox820_ref600,
+       &ox820_usbdev,
+};
+
+static struct clk_hw_onecell_data ox810se_hw_onecell_data = {
+       .hws = {
+               [CLK_810_LEON]  = &ox810se_leon.hw,
+               [CLK_810_DMA_SGDMA]     = &ox810se_dma_sgdma.hw,
+               [CLK_810_CIPHER]        = &ox810se_cipher.hw,
+               [CLK_810_SATA]  = &ox810se_sata.hw,
+               [CLK_810_AUDIO] = &ox810se_audio.hw,
+               [CLK_810_USBMPH]        = &ox810se_usbmph.hw,
+               [CLK_810_ETHA]  = &ox810se_etha.hw,
+               [CLK_810_PCIEA] = &ox810se_pciea.hw,
+               [CLK_810_NAND]  = &ox810se_nand.hw,
+       },
+       .num = ARRAY_SIZE(ox810se_gates),
+};
+
+static struct clk_hw_onecell_data ox820_hw_onecell_data = {
+       .hws = {
+               [CLK_820_LEON]  = &ox820_leon.hw,
+               [CLK_820_DMA_SGDMA]     = &ox820_dma_sgdma.hw,
+               [CLK_820_CIPHER]        = &ox820_cipher.hw,
+               [CLK_820_SD]    = &ox820_sd.hw,
+               [CLK_820_SATA]  = &ox820_sata.hw,
+               [CLK_820_AUDIO] = &ox820_audio.hw,
+               [CLK_820_USBMPH]        = &ox820_usbmph.hw,
+               [CLK_820_ETHA]  = &ox820_etha.hw,
+               [CLK_820_PCIEA] = &ox820_pciea.hw,
+               [CLK_820_NAND]  = &ox820_nand.hw,
+               [CLK_820_ETHB]  = &ox820_ethb.hw,
+               [CLK_820_PCIEB] = &ox820_pcieb.hw,
+               [CLK_820_REF600]        = &ox820_ref600.hw,
+               [CLK_820_USBDEV]        = &ox820_usbdev.hw,
+       },
+       .num = ARRAY_SIZE(ox820_gates),
+};
 
-/* Hardware Bit - Clock association */
-struct clk_oxnas_init_data {
-       unsigned long bit;
-       const struct clk_init_data *clk_init;
+static struct oxnas_stdclk_data ox810se_stdclk_data = {
+       .onecell_data = &ox810se_hw_onecell_data,
+       .gates = ox810se_gates,
+       .ngates = ARRAY_SIZE(ox810se_gates),
 };
 
-/* Clk init data declaration */
-DECLARE_STD_CLK(leon);
-DECLARE_STD_CLK(dma_sgdma);
-DECLARE_STD_CLK(cipher);
-DECLARE_STD_CLK(sata);
-DECLARE_STD_CLK(audio);
-DECLARE_STD_CLK(usbmph);
-DECLARE_STD_CLKP(etha, eth_parents);
-DECLARE_STD_CLK(pciea);
-DECLARE_STD_CLK(nand);
-
-/* Table index is clock indice */
-static const struct clk_oxnas_init_data clk_oxnas_init[] = {
-       [0] = {0, &clk_leon_init},
-       [1] = {1, &clk_dma_sgdma_init},
-       [2] = {2, &clk_cipher_init},
-       /* Skip & Do not touch to DDR clock */
-       [3] = {4, &clk_sata_init},
-       [4] = {5, &clk_audio_init},
-       [5] = {6, &clk_usbmph_init},
-       [6] = {7, &clk_etha_init},
-       [7] = {8, &clk_pciea_init},
-       [8] = {9, &clk_nand_init},
+static struct oxnas_stdclk_data ox820_stdclk_data = {
+       .onecell_data = &ox820_hw_onecell_data,
+       .gates = ox820_gates,
+       .ngates = ARRAY_SIZE(ox820_gates),
 };
 
-struct clk_oxnas_data {
-       struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)];
-       struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)];
-       struct clk *clks[ARRAY_SIZE(clk_oxnas_init)];
+static const struct of_device_id oxnas_stdclk_dt_ids[] = {
+       { .compatible = "oxsemi,ox810se-stdclk", &ox810se_stdclk_data },
+       { .compatible = "oxsemi,ox820-stdclk", &ox820_stdclk_data },
+       { }
 };
 
 static int oxnas_stdclk_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       struct clk_oxnas_data *clk_oxnas;
+       const struct oxnas_stdclk_data *data;
+       const struct of_device_id *id;
        struct regmap *regmap;
+       int ret;
        int i;
 
-       clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL);
-       if (!clk_oxnas)
-               return -ENOMEM;
+       id = of_match_device(oxnas_stdclk_dt_ids, &pdev->dev);
+       if (!id)
+               return -ENODEV;
+       data = id->data;
 
        regmap = syscon_node_to_regmap(of_get_parent(np));
        if (IS_ERR(regmap)) {
@@ -149,32 +236,23 @@ static int oxnas_stdclk_probe(struct platform_device *pdev)
                return PTR_ERR(regmap);
        }
 
-       for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) {
-               struct clk_oxnas *_clk;
+       for (i = 0 ; i < data->ngates ; ++i)
+               data->gates[i]->regmap = regmap;
 
-               _clk = &clk_oxnas->clk_oxnas[i];
-               _clk->bit = clk_oxnas_init[i].bit;
-               _clk->hw.init = clk_oxnas_init[i].clk_init;
-               _clk->regmap = regmap;
+       for (i = 0; i < data->onecell_data->num; i++) {
+               if (!data->onecell_data->hws[i])
+                       continue;
 
-               clk_oxnas->clks[i] =
-                       devm_clk_register(&pdev->dev, &_clk->hw);
-               if (WARN_ON(IS_ERR(clk_oxnas->clks[i])))
-                       return PTR_ERR(clk_oxnas->clks[i]);
+               ret = devm_clk_hw_register(&pdev->dev,
+                                          data->onecell_data->hws[i]);
+               if (ret)
+                       return ret;
        }
 
-       clk_oxnas->onecell_data->clks = clk_oxnas->clks;
-       clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init);
-
-       return of_clk_add_provider(np, of_clk_src_onecell_get,
-                                  clk_oxnas->onecell_data);
+       return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
+                                     data->onecell_data);
 }
 
-static const struct of_device_id oxnas_stdclk_dt_ids[] = {
-       { .compatible = "oxsemi,ox810se-stdclk" },
-       { }
-};
-
 static struct platform_driver oxnas_stdclk_driver = {
        .probe = oxnas_stdclk_probe,
        .driver = {
index 80ae2a51452d7410c1edc856f8126d6451c75913..d0bf8b1c67de51ba27e756af870cea4ccfa67eec 100644 (file)
@@ -266,6 +266,39 @@ static const struct clockgen_muxinfo ls1043a_hwa2 = {
        },
 };
 
+static const struct clockgen_muxinfo ls1046a_hwa1 = {
+       {
+               {},
+               {},
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+               { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+       },
+};
+
+static const struct clockgen_muxinfo ls1046a_hwa2 = {
+       {
+               {},
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+               {},
+               {},
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+       },
+};
+
+static const struct clockgen_muxinfo ls1012a_cmux = {
+       {
+               [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+               {},
+               [2] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+       }
+};
+
 static const struct clockgen_muxinfo t1023_hwa1 = {
        {
                {},
@@ -488,6 +521,31 @@ static const struct clockgen_chipinfo chipinfo[] = {
                .pll_mask = 0x07,
                .flags = CG_PLL_8BIT,
        },
+       {
+               .compat = "fsl,ls1046a-clockgen",
+               .init_periph = t2080_init_periph,
+               .cmux_groups = {
+                       &t1040_cmux
+               },
+               .hwaccel = {
+                       &ls1046a_hwa1, &ls1046a_hwa2
+               },
+               .cmux_to_group = {
+                       0, -1
+               },
+               .pll_mask = 0x07,
+               .flags = CG_PLL_8BIT,
+       },
+       {
+               .compat = "fsl,ls1012a-clockgen",
+               .cmux_groups = {
+                       &ls1012a_cmux
+               },
+               .cmux_to_group = {
+                       0, -1
+               },
+               .pll_mask = 0x03,
+       },
        {
                .compat = "fsl,ls2080a-clockgen",
                .cmux_groups = {
@@ -1273,8 +1331,10 @@ err:
 
 CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
 
 /* Legacy nodes */
index 02d6810084017212c04cf83ae7b27b586fd74ca7..5eb05dbf59b84d27d79106adeb7405d15de1433a 100644 (file)
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
 
 #define STM32F4_RCC_PLLCFGR            0x04
 #define STM32F4_RCC_CFGR               0x08
@@ -31,6 +35,8 @@
 #define STM32F4_RCC_AHB3ENR            0x38
 #define STM32F4_RCC_APB1ENR            0x40
 #define STM32F4_RCC_APB2ENR            0x44
+#define STM32F4_RCC_BDCR               0x70
+#define STM32F4_RCC_CSR                        0x74
 
 struct stm32f4_gate_data {
        u8      offset;
@@ -40,7 +46,7 @@ struct stm32f4_gate_data {
        unsigned long flags;
 };
 
-static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
+static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
        { STM32F4_RCC_AHB1ENR,  0,      "gpioa",        "ahb_div" },
        { STM32F4_RCC_AHB1ENR,  1,      "gpiob",        "ahb_div" },
        { STM32F4_RCC_AHB1ENR,  2,      "gpioc",        "ahb_div" },
@@ -120,26 +126,113 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
        { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
 };
 
-/*
- * MAX_CLKS is the maximum value in the enumeration below plus the combined
- * hweight of stm32f42xx_gate_map (plus one).
- */
-#define MAX_CLKS 74
+static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
+       { STM32F4_RCC_AHB1ENR,  0,      "gpioa",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  1,      "gpiob",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  2,      "gpioc",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  3,      "gpiod",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  4,      "gpioe",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  5,      "gpiof",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  6,      "gpiog",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  7,      "gpioh",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  8,      "gpioi",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  9,      "gpioj",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 10,      "gpiok",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 12,      "crc",          "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 18,      "bkpsra",       "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 20,      "ccmdatam",     "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 21,      "dma1",         "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 22,      "dma2",         "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 23,      "dma2d",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 25,      "ethmac",       "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 26,      "ethmactx",     "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 27,      "ethmacrx",     "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 28,      "ethmacptp",    "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 29,      "otghs",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 30,      "otghsulpi",    "ahb_div" },
+
+       { STM32F4_RCC_AHB2ENR,  0,      "dcmi",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  4,      "cryp",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  5,      "hash",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  6,      "rng",          "pll48" },
+       { STM32F4_RCC_AHB2ENR,  7,      "otgfs",        "pll48" },
+
+       { STM32F4_RCC_AHB3ENR,  0,      "fmc",          "ahb_div",
+               CLK_IGNORE_UNUSED },
+       { STM32F4_RCC_AHB3ENR,  1,      "qspi",         "ahb_div",
+               CLK_IGNORE_UNUSED },
+
+       { STM32F4_RCC_APB1ENR,  0,      "tim2",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  1,      "tim3",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  2,      "tim4",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  3,      "tim5",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  4,      "tim6",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  5,      "tim7",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  6,      "tim12",        "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  7,      "tim13",        "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  8,      "tim14",        "apb1_mul" },
+       { STM32F4_RCC_APB1ENR, 11,      "wwdg",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 14,      "spi2",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 15,      "spi3",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 17,      "uart2",        "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 18,      "uart3",        "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 19,      "uart4",        "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 20,      "uart5",        "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 21,      "i2c1",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 22,      "i2c2",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 23,      "i2c3",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 25,      "can1",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 26,      "can2",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 28,      "pwr",          "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 29,      "dac",          "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 30,      "uart7",        "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 31,      "uart8",        "apb1_div" },
+
+       { STM32F4_RCC_APB2ENR,  0,      "tim1",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR,  1,      "tim8",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR,  4,      "usart1",       "apb2_div" },
+       { STM32F4_RCC_APB2ENR,  5,      "usart6",       "apb2_div" },
+       { STM32F4_RCC_APB2ENR,  8,      "adc1",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR,  9,      "adc2",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 10,      "adc3",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 11,      "sdio",         "pll48" },
+       { STM32F4_RCC_APB2ENR, 12,      "spi1",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 13,      "spi4",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 14,      "syscfg",       "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 16,      "tim9",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR, 17,      "tim10",        "apb2_mul" },
+       { STM32F4_RCC_APB2ENR, 18,      "tim11",        "apb2_mul" },
+       { STM32F4_RCC_APB2ENR, 20,      "spi5",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
+};
 
-enum { SYSTICK, FCLK };
+enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
 
 /*
  * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
  * have gate bits associated with them. Its combined hweight is 71.
  */
-static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
-                                          0x0000000000000001ull,
-                                          0x04777f33f6fec9ffull };
+#define MAX_GATE_MAP 3
+
+static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+                                                      0x0000000000000001ull,
+                                                      0x04777f33f6fec9ffull };
+
+static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+                                                      0x0000000000000003ull,
+                                                      0x0c777f33f6fec9ffull };
+
+static const u64 *stm32f4_gate_map;
+
+static struct clk_hw **clks;
 
-static struct clk_hw *clks[MAX_CLKS];
 static DEFINE_SPINLOCK(stm32f4_clk_lock);
 static void __iomem *base;
 
+static struct regmap *pdrm;
+
 /*
  * "Multiplier" device for APBx clocks.
  *
@@ -256,15 +349,15 @@ static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
  */
 static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
 {
-       u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
+       u64 table[MAX_GATE_MAP];
 
        if (primary == 1) {
-               if (WARN_ON(secondary > FCLK))
+               if (WARN_ON(secondary >= END_PRIMARY_CLK))
                        return -EINVAL;
                return secondary;
        }
 
-       memcpy(table, stm32f42xx_gate_map, sizeof(table));
+       memcpy(table, stm32f4_gate_map, sizeof(table));
 
        /* only bits set in table can be used as indices */
        if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
@@ -276,7 +369,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
        table[BIT_ULL_WORD(secondary)] &=
            GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
 
-       return FCLK + hweight64(table[0]) +
+       return END_PRIMARY_CLK - 1 + hweight64(table[0]) +
               (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
               (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
 }
@@ -292,6 +385,212 @@ stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
        return clks[i];
 }
 
+#define to_rgclk(_rgate) container_of(_rgate, struct stm32_rgate, gate)
+
+static inline void disable_power_domain_write_protection(void)
+{
+       if (pdrm)
+               regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
+}
+
+static inline void enable_power_domain_write_protection(void)
+{
+       if (pdrm)
+               regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
+}
+
+static inline void sofware_reset_backup_domain(void)
+{
+       unsigned long val;
+
+       val = readl(base + STM32F4_RCC_BDCR);
+       writel(val | BIT(16), base + STM32F4_RCC_BDCR);
+       writel(val & ~BIT(16), base + STM32F4_RCC_BDCR);
+}
+
+struct stm32_rgate {
+       struct  clk_gate gate;
+       u8      bit_rdy_idx;
+};
+
+#define RTC_TIMEOUT 1000000
+
+static int rgclk_enable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+       struct stm32_rgate *rgate = to_rgclk(gate);
+       u32 reg;
+       int ret;
+
+       disable_power_domain_write_protection();
+
+       clk_gate_ops.enable(hw);
+
+       ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg,
+                       reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT);
+
+       enable_power_domain_write_protection();
+       return ret;
+}
+
+static void rgclk_disable(struct clk_hw *hw)
+{
+       clk_gate_ops.disable(hw);
+}
+
+static int rgclk_is_enabled(struct clk_hw *hw)
+{
+       return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops rgclk_ops = {
+       .enable = rgclk_enable,
+       .disable = rgclk_disable,
+       .is_enabled = rgclk_is_enabled,
+};
+
+static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               void __iomem *reg, u8 bit_idx, u8 bit_rdy_idx,
+               u8 clk_gate_flags, spinlock_t *lock)
+{
+       struct stm32_rgate *rgate;
+       struct clk_init_data init = { NULL };
+       struct clk_hw *hw;
+       int ret;
+
+       rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
+       if (!rgate)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &rgclk_ops;
+       init.flags = flags;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       rgate->bit_rdy_idx = bit_rdy_idx;
+
+       rgate->gate.lock = lock;
+       rgate->gate.reg = reg;
+       rgate->gate.bit_idx = bit_idx;
+       rgate->gate.hw.init = &init;
+
+       hw = &rgate->gate.hw;
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
+               kfree(rgate);
+               hw = ERR_PTR(ret);
+       }
+
+       return hw;
+}
+
+static int cclk_gate_enable(struct clk_hw *hw)
+{
+       int ret;
+
+       disable_power_domain_write_protection();
+
+       ret = clk_gate_ops.enable(hw);
+
+       enable_power_domain_write_protection();
+
+       return ret;
+}
+
+static void cclk_gate_disable(struct clk_hw *hw)
+{
+       disable_power_domain_write_protection();
+
+       clk_gate_ops.disable(hw);
+
+       enable_power_domain_write_protection();
+}
+
+static int cclk_gate_is_enabled(struct clk_hw *hw)
+{
+       return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops cclk_gate_ops = {
+       .enable         = cclk_gate_enable,
+       .disable        = cclk_gate_disable,
+       .is_enabled     = cclk_gate_is_enabled,
+};
+
+static u8 cclk_mux_get_parent(struct clk_hw *hw)
+{
+       return clk_mux_ops.get_parent(hw);
+}
+
+static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       int ret;
+
+       disable_power_domain_write_protection();
+
+       sofware_reset_backup_domain();
+
+       ret = clk_mux_ops.set_parent(hw, index);
+
+       enable_power_domain_write_protection();
+
+       return ret;
+}
+
+static const struct clk_ops cclk_mux_ops = {
+       .get_parent = cclk_mux_get_parent,
+       .set_parent = cclk_mux_set_parent,
+};
+
+static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
+               const char * const *parent_names, int num_parents,
+               void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags,
+               spinlock_t *lock)
+{
+       struct clk_hw *hw;
+       struct clk_gate *gate;
+       struct clk_mux *mux;
+
+       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+       if (!gate) {
+               hw = ERR_PTR(-EINVAL);
+               goto fail;
+       }
+
+       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+       if (!mux) {
+               kfree(gate);
+               hw = ERR_PTR(-EINVAL);
+               goto fail;
+       }
+
+       gate->reg = reg;
+       gate->bit_idx = bit_idx;
+       gate->flags = 0;
+       gate->lock = lock;
+
+       mux->reg = reg;
+       mux->shift = shift;
+       mux->mask = 3;
+       mux->flags = 0;
+
+       hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
+                       &mux->hw, &cclk_mux_ops,
+                       NULL, NULL,
+                       &gate->hw, &cclk_gate_ops,
+                       flags);
+
+       if (IS_ERR(hw)) {
+               kfree(gate);
+               kfree(mux);
+       }
+
+fail:
+       return hw;
+}
+
 static const char *sys_parents[] __initdata =   { "hsi", NULL, "pll" };
 
 static const struct clk_div_table ahb_div_table[] = {
@@ -308,10 +607,46 @@ static const struct clk_div_table apb_div_table[] = {
        { 0 },
 };
 
+static const char *rtc_parents[4] = {
+       "no-clock", "lse", "lsi", "hse-rtc"
+};
+
+struct stm32f4_clk_data {
+       const struct stm32f4_gate_data *gates_data;
+       const u64 *gates_map;
+       int gates_num;
+};
+
+static const struct stm32f4_clk_data stm32f429_clk_data = {
+       .gates_data     = stm32f429_gates,
+       .gates_map      = stm32f42xx_gate_map,
+       .gates_num      = ARRAY_SIZE(stm32f429_gates),
+};
+
+static const struct stm32f4_clk_data stm32f469_clk_data = {
+       .gates_data     = stm32f469_gates,
+       .gates_map      = stm32f46xx_gate_map,
+       .gates_num      = ARRAY_SIZE(stm32f469_gates),
+};
+
+static const struct of_device_id stm32f4_of_match[] = {
+       {
+               .compatible = "st,stm32f42xx-rcc",
+               .data = &stm32f429_clk_data
+       },
+       {
+               .compatible = "st,stm32f469-rcc",
+               .data = &stm32f469_clk_data
+       },
+       {}
+};
+
 static void __init stm32f4_rcc_init(struct device_node *np)
 {
        const char *hse_clk;
        int n;
+       const struct of_device_id *match;
+       const struct stm32f4_clk_data *data;
 
        base = of_iomap(np, 0);
        if (!base) {
@@ -319,6 +654,25 @@ static void __init stm32f4_rcc_init(struct device_node *np)
                return;
        }
 
+       pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+       if (IS_ERR(pdrm)) {
+               pdrm = NULL;
+               pr_warn("%s: Unable to get syscfg\n", __func__);
+       }
+
+       match = of_match_node(stm32f4_of_match, np);
+       if (WARN_ON(!match))
+               return;
+
+       data = match->data;
+
+       clks = kmalloc_array(data->gates_num + END_PRIMARY_CLK,
+                       sizeof(*clks), GFP_KERNEL);
+       if (!clks)
+               goto fail;
+
+       stm32f4_gate_map = data->gates_map;
+
        hse_clk = of_clk_get_parent_name(np, 0);
 
        clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
@@ -351,11 +705,15 @@ static void __init stm32f4_rcc_init(struct device_node *np)
        clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
                                               0, 1, 1);
 
-       for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
-               const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
-               unsigned int secondary =
-                   8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
-               int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
+       for (n = 0; n < data->gates_num; n++) {
+               const struct stm32f4_gate_data *gd;
+               unsigned int secondary;
+               int idx;
+
+               gd = &data->gates_data[n];
+               secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
+                       gd->bit_idx;
+               idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
 
                if (idx < 0)
                        goto fail;
@@ -371,9 +729,44 @@ static void __init stm32f4_rcc_init(struct device_node *np)
                }
        }
 
+       clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
+                       base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock);
+
+       if (IS_ERR(clks[CLK_LSI])) {
+               pr_err("Unable to register lsi clock\n");
+               goto fail;
+       }
+
+       clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
+                       base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock);
+
+       if (IS_ERR(clks[CLK_LSE])) {
+               pr_err("Unable to register lse clock\n");
+               goto fail;
+       }
+
+       clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse",
+                       0, base + STM32F4_RCC_CFGR, 16, 5, 0,
+                       &stm32f4_clk_lock);
+
+       if (IS_ERR(clks[CLK_HSE_RTC])) {
+               pr_err("Unable to register hse-rtc clock\n");
+               goto fail;
+       }
+
+       clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4,
+                       base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock);
+
+       if (IS_ERR(clks[CLK_RTC])) {
+               pr_err("Unable to register rtc clock\n");
+               goto fail;
+       }
+
        of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
        return;
 fail:
+       kfree(clks);
        iounmap(base);
 }
-CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
index f4fdac55727c8017d0d8990b35ee19f6044be8fa..0621fbfb4bebfd548b21f62e7320f1bab2294b48 100644 (file)
@@ -243,7 +243,7 @@ static int wm831x_clkout_is_prepared(struct clk_hw *hw)
        if (ret < 0) {
                dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
                        ret);
-               return true;
+               return false;
        }
 
        return (ret & WM831X_CLKOUT_ENA) != 0;
index 3f537a04c6a633b10fb29e0cb390bcd3a54be976..cbed6602172be2f302db8d30698095a81a7f0463 100644 (file)
@@ -1,3 +1,11 @@
+config COMMON_CLK_HI3516CV300
+       tristate "HI3516CV300 Clock Driver"
+       depends on ARCH_HISI || COMPILE_TEST
+       select RESET_HISI
+       default ARCH_HISI
+       help
+         Build the clock driver for hi3516cv300.
+
 config COMMON_CLK_HI3519
        tristate "Hi3519 Clock Driver"
        depends on ARCH_HISI || COMPILE_TEST
@@ -6,6 +14,14 @@ config COMMON_CLK_HI3519
        help
          Build the clock driver for hi3519.
 
+config COMMON_CLK_HI3798CV200
+       tristate "Hi3798CV200 Clock Driver"
+       depends on ARCH_HISI || COMPILE_TEST
+       select RESET_HISI
+       default ARCH_HISI
+       help
+         Build the clock driver for hi3798cv200.
+
 config COMMON_CLK_HI6220
        bool "Hi6220 Clock Driver"
        depends on ARCH_HISI || COMPILE_TEST
@@ -23,5 +39,6 @@ config RESET_HISI
 config STUB_CLK_HI6220
        bool "Hi6220 Stub Clock Driver"
        depends on COMMON_CLK_HI6220 && MAILBOX
+       default ARCH_HISI
        help
          Build the Hisilicon Hi6220 stub clock driver.
index e169ec7da0239426c9f26455b479167b1d125642..4eec5e511e4c22c48f3e7f8e038c60f294cb1d75 100644 (file)
@@ -7,7 +7,9 @@ obj-y   += clk.o clkgate-separated.o clkdivider-hi6220.o
 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI3516CV300)   += crg-hi3516cv300.o
 obj-$(CONFIG_COMMON_CLK_HI3519)        += clk-hi3519.o
+obj-$(CONFIG_COMMON_CLK_HI3798CV200)   += crg-hi3798cv200.o
 obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
 obj-$(CONFIG_RESET_HISI)       += reset.o
 obj-$(CONFIG_STUB_CLK_HI6220)  += clk-hi6220-stub.o
diff --git a/drivers/clk/hisilicon/crg-hi3516cv300.c b/drivers/clk/hisilicon/crg-hi3516cv300.c
new file mode 100644 (file)
index 0000000..2007123
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Hi3516CV300 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * 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.
+ *
+ * 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 <dt-bindings/clock/hi3516cv300-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+#include "reset.h"
+
+/* hi3516CV300 core CRG */
+#define HI3516CV300_INNER_CLK_OFFSET   64
+#define HI3516CV300_FIXED_3M           65
+#define HI3516CV300_FIXED_6M           66
+#define HI3516CV300_FIXED_24M          67
+#define HI3516CV300_FIXED_49P5         68
+#define HI3516CV300_FIXED_50M          69
+#define HI3516CV300_FIXED_83P3M                70
+#define HI3516CV300_FIXED_99M          71
+#define HI3516CV300_FIXED_100M         72
+#define HI3516CV300_FIXED_148P5M       73
+#define HI3516CV300_FIXED_198M         74
+#define HI3516CV300_FIXED_297M         75
+#define HI3516CV300_UART_MUX           76
+#define HI3516CV300_FMC_MUX            77
+#define HI3516CV300_MMC0_MUX           78
+#define HI3516CV300_MMC1_MUX           79
+#define HI3516CV300_MMC2_MUX           80
+#define HI3516CV300_MMC3_MUX           81
+#define HI3516CV300_PWM_MUX            82
+#define HI3516CV300_CRG_NR_CLKS                128
+
+static const struct hisi_fixed_rate_clock hi3516cv300_fixed_rate_clks[] = {
+       { HI3516CV300_FIXED_3M, "3m", NULL, 0, 3000000, },
+       { HI3516CV300_FIXED_6M, "6m", NULL, 0, 6000000, },
+       { HI3516CV300_FIXED_24M, "24m", NULL, 0, 24000000, },
+       { HI3516CV300_FIXED_49P5, "49.5m", NULL, 0, 49500000, },
+       { HI3516CV300_FIXED_50M, "50m", NULL, 0, 50000000, },
+       { HI3516CV300_FIXED_83P3M, "83.3m", NULL, 0, 83300000, },
+       { HI3516CV300_FIXED_99M, "99m", NULL, 0, 99000000, },
+       { HI3516CV300_FIXED_100M, "100m", NULL, 0, 100000000, },
+       { HI3516CV300_FIXED_148P5M, "148.5m", NULL, 0, 148500000, },
+       { HI3516CV300_FIXED_198M, "198m", NULL, 0, 198000000, },
+       { HI3516CV300_FIXED_297M, "297m", NULL, 0, 297000000, },
+       { HI3516CV300_APB_CLK, "apb", NULL, 0, 50000000, },
+};
+
+static const char *const uart_mux_p[] = {"24m", "6m"};
+static const char *const fmc_mux_p[] = {
+       "24m", "83.3m", "148.5m", "198m", "297m"
+};
+static const char *const mmc_mux_p[] = {"49.5m"};
+static const char *const mmc2_mux_p[] = {"99m", "49.5m"};
+static const char *const pwm_mux_p[] = {"3m", "50m", "24m", "24m"};
+
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4};
+static u32 mmc_mux_table[] = {0};
+static u32 mmc2_mux_table[] = {0, 2};
+static u32 pwm_mux_table[] = {0, 1, 2, 3};
+
+static const struct hisi_mux_clock hi3516cv300_mux_clks[] = {
+       { HI3516CV300_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
+               CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, },
+       { HI3516CV300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+               CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, },
+       { HI3516CV300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+               CLK_SET_RATE_PARENT, 0xc4, 4, 2, 0, mmc_mux_table, },
+       { HI3516CV300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+               CLK_SET_RATE_PARENT, 0xc4, 12, 2, 0, mmc_mux_table, },
+       { HI3516CV300_MMC2_MUX, "mmc2_mux", mmc2_mux_p, ARRAY_SIZE(mmc2_mux_p),
+               CLK_SET_RATE_PARENT, 0xc4, 20, 2, 0, mmc2_mux_table, },
+       { HI3516CV300_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+               CLK_SET_RATE_PARENT, 0xc8, 4, 2, 0, mmc_mux_table, },
+       { HI3516CV300_PWM_MUX, "pwm_mux", pwm_mux_p, ARRAY_SIZE(pwm_mux_p),
+               CLK_SET_RATE_PARENT, 0x38, 2, 2, 0, pwm_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3516cv300_gate_clks[] = {
+
+       { HI3516CV300_UART0_CLK, "clk_uart0", "uart_mux", CLK_SET_RATE_PARENT,
+               0xe4, 15, 0, },
+       { HI3516CV300_UART1_CLK, "clk_uart1", "uart_mux", CLK_SET_RATE_PARENT,
+               0xe4, 16, 0, },
+       { HI3516CV300_UART2_CLK, "clk_uart2", "uart_mux", CLK_SET_RATE_PARENT,
+               0xe4, 17, 0, },
+
+       { HI3516CV300_SPI0_CLK, "clk_spi0", "100m", CLK_SET_RATE_PARENT,
+               0xe4, 13, 0, },
+       { HI3516CV300_SPI1_CLK, "clk_spi1", "100m", CLK_SET_RATE_PARENT,
+               0xe4, 14, 0, },
+
+       { HI3516CV300_FMC_CLK, "clk_fmc", "fmc_mux", CLK_SET_RATE_PARENT,
+               0xc0, 1, 0, },
+       { HI3516CV300_MMC0_CLK, "clk_mmc0", "mmc0_mux", CLK_SET_RATE_PARENT,
+               0xc4, 1, 0, },
+       { HI3516CV300_MMC1_CLK, "clk_mmc1", "mmc1_mux", CLK_SET_RATE_PARENT,
+               0xc4, 9, 0, },
+       { HI3516CV300_MMC2_CLK, "clk_mmc2", "mmc2_mux", CLK_SET_RATE_PARENT,
+               0xc4, 17, 0, },
+       { HI3516CV300_MMC3_CLK, "clk_mmc3", "mmc3_mux", CLK_SET_RATE_PARENT,
+               0xc8, 1, 0, },
+
+       { HI3516CV300_ETH_CLK, "clk_eth", NULL, 0, 0xec, 1, 0, },
+
+       { HI3516CV300_DMAC_CLK, "clk_dmac", NULL, 0, 0xd8, 5, 0, },
+       { HI3516CV300_PWM_CLK, "clk_pwm", "pwm_mux", CLK_SET_RATE_PARENT,
+               0x38, 1, 0, },
+
+       { HI3516CV300_USB2_BUS_CLK, "clk_usb2_bus", NULL, 0, 0xb8, 0, 0, },
+       { HI3516CV300_USB2_OHCI48M_CLK, "clk_usb2_ohci48m", NULL, 0,
+               0xb8, 1, 0, },
+       { HI3516CV300_USB2_OHCI12M_CLK, "clk_usb2_ohci12m", NULL, 0,
+               0xb8, 2, 0, },
+       { HI3516CV300_USB2_OTG_UTMI_CLK, "clk_usb2_otg_utmi", NULL, 0,
+               0xb8, 3, 0, },
+       { HI3516CV300_USB2_HST_PHY_CLK, "clk_usb2_hst_phy", NULL, 0,
+               0xb8, 4, 0, },
+       { HI3516CV300_USB2_UTMI0_CLK, "clk_usb2_utmi0", NULL, 0, 0xb8, 5, 0, },
+       { HI3516CV300_USB2_PHY_CLK, "clk_usb2_phy", NULL, 0, 0xb8, 7, 0, },
+};
+
+static struct hisi_clock_data *hi3516cv300_clk_register(
+               struct platform_device *pdev)
+{
+       struct hisi_clock_data *clk_data;
+       int ret;
+
+       clk_data = hisi_clk_alloc(pdev, HI3516CV300_CRG_NR_CLKS);
+       if (!clk_data)
+               return ERR_PTR(-ENOMEM);
+
+       ret = hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks,
+                       ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = hisi_clk_register_mux(hi3516cv300_mux_clks,
+                       ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
+       if (ret)
+               goto unregister_fixed_rate;
+
+       ret = hisi_clk_register_gate(hi3516cv300_gate_clks,
+                       ARRAY_SIZE(hi3516cv300_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_gate:
+       hisi_clk_unregister_gate(hi3516cv300_gate_clks,
+                               ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
+unregister_mux:
+       hisi_clk_unregister_mux(hi3516cv300_mux_clks,
+                       ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
+unregister_fixed_rate:
+       hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
+                       ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
+       return ERR_PTR(ret);
+}
+
+static void hi3516cv300_clk_unregister(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+       of_clk_del_provider(pdev->dev.of_node);
+
+       hisi_clk_unregister_gate(hi3516cv300_gate_clks,
+                       ARRAY_SIZE(hi3516cv300_gate_clks), crg->clk_data);
+       hisi_clk_unregister_mux(hi3516cv300_mux_clks,
+                       ARRAY_SIZE(hi3516cv300_mux_clks), crg->clk_data);
+       hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
+                       ARRAY_SIZE(hi3516cv300_fixed_rate_clks), crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
+       .register_clks = hi3516cv300_clk_register,
+       .unregister_clks = hi3516cv300_clk_unregister,
+};
+
+/* hi3516CV300 sysctrl CRG */
+#define HI3516CV300_SYSCTRL_NR_CLKS 16
+
+static const char *wdt_mux_p[] __initconst = { "3m", "apb" };
+static u32 wdt_mux_table[] = {0, 1};
+
+static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
+       { HI3516CV300_WDT_CLK, "wdt", wdt_mux_p, ARRAY_SIZE(wdt_mux_p),
+               CLK_SET_RATE_PARENT, 0x0, 23, 1, 0, wdt_mux_table, },
+};
+
+static struct hisi_clock_data *hi3516cv300_sysctrl_clk_register(
+               struct platform_device *pdev)
+{
+       struct hisi_clock_data *clk_data;
+       int ret;
+
+       clk_data = hisi_clk_alloc(pdev, HI3516CV300_SYSCTRL_NR_CLKS);
+       if (!clk_data)
+               return ERR_PTR(-ENOMEM);
+
+       ret = hisi_clk_register_mux(hi3516cv300_sysctrl_mux_clks,
+                       ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
+       if (ret)
+               return ERR_PTR(ret);
+
+
+       ret = of_clk_add_provider(pdev->dev.of_node,
+                       of_clk_src_onecell_get, &clk_data->clk_data);
+       if (ret)
+               goto unregister_mux;
+
+       return clk_data;
+
+unregister_mux:
+       hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
+                       ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
+       return ERR_PTR(ret);
+}
+
+static void hi3516cv300_sysctrl_clk_unregister(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+       of_clk_del_provider(pdev->dev.of_node);
+
+       hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
+                       ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
+                       crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3516cv300_sysctrl_funcs = {
+       .register_clks = hi3516cv300_sysctrl_clk_register,
+       .unregister_clks = hi3516cv300_sysctrl_clk_unregister,
+};
+
+static const struct of_device_id hi3516cv300_crg_match_table[] = {
+       {
+               .compatible = "hisilicon,hi3516cv300-crg",
+               .data = &hi3516cv300_crg_funcs
+       },
+       {
+               .compatible = "hisilicon,hi3516cv300-sysctrl",
+               .data = &hi3516cv300_sysctrl_funcs
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, hi3516cv300_crg_match_table);
+
+static int hi3516cv300_crg_probe(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg;
+
+       crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+       if (!crg)
+               return -ENOMEM;
+
+       crg->funcs = of_device_get_match_data(&pdev->dev);
+       if (!crg->funcs)
+               return -ENOENT;
+
+       crg->rstc = hisi_reset_init(pdev);
+       if (!crg->rstc)
+               return -ENOMEM;
+
+       crg->clk_data = crg->funcs->register_clks(pdev);
+       if (IS_ERR(crg->clk_data)) {
+               hisi_reset_exit(crg->rstc);
+               return PTR_ERR(crg->clk_data);
+       }
+
+       platform_set_drvdata(pdev, crg);
+       return 0;
+}
+
+static int hi3516cv300_crg_remove(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+       hisi_reset_exit(crg->rstc);
+       crg->funcs->unregister_clks(pdev);
+       return 0;
+}
+
+static struct platform_driver hi3516cv300_crg_driver = {
+       .probe          = hi3516cv300_crg_probe,
+       .remove         = hi3516cv300_crg_remove,
+       .driver         = {
+               .name   = "hi3516cv300-crg",
+               .of_match_table = hi3516cv300_crg_match_table,
+       },
+};
+
+static int __init hi3516cv300_crg_init(void)
+{
+       return platform_driver_register(&hi3516cv300_crg_driver);
+}
+core_initcall(hi3516cv300_crg_init);
+
+static void __exit hi3516cv300_crg_exit(void)
+{
+       platform_driver_unregister(&hi3516cv300_crg_driver);
+}
+module_exit(hi3516cv300_crg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3516CV300 CRG Driver");
diff --git a/drivers/clk/hisilicon/crg-hi3798cv200.c b/drivers/clk/hisilicon/crg-hi3798cv200.c
new file mode 100644 (file)
index 0000000..fc8b5bc
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * Hi3798CV200 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * 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.
+ *
+ * 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 <dt-bindings/clock/histb-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+#include "reset.h"
+
+/* hi3798CV200 core CRG */
+#define HI3798CV200_INNER_CLK_OFFSET   64
+#define HI3798CV200_FIXED_24M  65
+#define HI3798CV200_FIXED_25M  66
+#define HI3798CV200_FIXED_50M  67
+#define HI3798CV200_FIXED_75M  68
+#define HI3798CV200_FIXED_100M 69
+#define HI3798CV200_FIXED_150M 70
+#define HI3798CV200_FIXED_200M 71
+#define HI3798CV200_FIXED_250M 72
+#define HI3798CV200_FIXED_300M 73
+#define HI3798CV200_FIXED_400M 74
+#define HI3798CV200_MMC_MUX    75
+#define HI3798CV200_ETH_PUB_CLK        76
+#define HI3798CV200_ETH_BUS_CLK        77
+#define HI3798CV200_ETH_BUS0_CLK       78
+#define HI3798CV200_ETH_BUS1_CLK       79
+#define HI3798CV200_COMBPHY1_MUX       80
+
+#define HI3798CV200_CRG_NR_CLKS                128
+
+static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
+       { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
+       { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
+       { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
+       { HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
+       { HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
+       { HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
+       { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
+       { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
+       { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
+       { HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
+       { HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
+};
+
+static const char *const mmc_mux_p[] = {
+               "100m", "50m", "25m", "200m", "150m" };
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
+
+static const char *const comphy1_mux_p[] = {
+               "100m", "25m"};
+static u32 comphy1_mux_table[] = {2, 3};
+
+static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
+       { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+               CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
+       { HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
+               comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
+               CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
+       /* UART */
+       { HISTB_UART2_CLK, "clk_uart2", "75m",
+               CLK_SET_RATE_PARENT, 0x68, 4, 0, },
+       /* I2C */
+       { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
+               CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
+       { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
+               CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
+       { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
+               CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
+       { HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
+               CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
+       { HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
+               CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
+       /* SPI */
+       { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
+               CLK_SET_RATE_PARENT, 0x70, 0, 0, },
+       /* SDIO */
+       { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
+                       CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
+       { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux",
+               CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
+       /* EMMC */
+       { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
+               CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
+       { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
+               CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
+       /* PCIE*/
+       { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
+               CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
+       { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
+               CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
+       { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
+               CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
+       { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
+               CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
+       /* Ethernet */
+       { HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,
+               CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
+       { HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",
+               CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
+       { HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
+               CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
+       { HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
+               CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
+       { HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
+               CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
+       { HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
+               CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
+       { HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
+               CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
+       { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
+               CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
+       /* COMBPHY1 */
+       { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
+               CLK_SET_RATE_PARENT, 0x188, 8, 0, },
+};
+
+static struct hisi_clock_data *hi3798cv200_clk_register(
+                               struct platform_device *pdev)
+{
+       struct hisi_clock_data *clk_data;
+       int ret;
+
+       clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
+       if (!clk_data)
+               return ERR_PTR(-ENOMEM);
+
+       ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
+                                    ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+                                    clk_data);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
+                               ARRAY_SIZE(hi3798cv200_mux_clks),
+                               clk_data);
+       if (ret)
+               goto unregister_fixed_rate;
+
+       ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_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(hi3798cv200_fixed_rate_clks,
+                               ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+                               clk_data);
+
+unregister_mux:
+       hisi_clk_unregister_mux(hi3798cv200_mux_clks,
+                               ARRAY_SIZE(hi3798cv200_mux_clks),
+                               clk_data);
+unregister_gate:
+       hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_gate_clks),
+                               clk_data);
+       return ERR_PTR(ret);
+}
+
+static void hi3798cv200_clk_unregister(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+       of_clk_del_provider(pdev->dev.of_node);
+
+       hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_gate_clks),
+                               crg->clk_data);
+       hisi_clk_unregister_mux(hi3798cv200_mux_clks,
+                               ARRAY_SIZE(hi3798cv200_mux_clks),
+                               crg->clk_data);
+       hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
+                               ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+                               crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
+       .register_clks = hi3798cv200_clk_register,
+       .unregister_clks = hi3798cv200_clk_unregister,
+};
+
+/* hi3798CV200 sysctrl CRG */
+
+#define HI3798CV200_SYSCTRL_NR_CLKS 16
+
+static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
+       { HISTB_IR_CLK, "clk_ir", "100m",
+               CLK_SET_RATE_PARENT, 0x48, 4, 0, },
+       { HISTB_TIMER01_CLK, "clk_timer01", "24m",
+               CLK_SET_RATE_PARENT, 0x48, 6, 0, },
+       { HISTB_UART0_CLK, "clk_uart0", "75m",
+               CLK_SET_RATE_PARENT, 0x48, 10, 0, },
+};
+
+static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
+                                       struct platform_device *pdev)
+{
+       struct hisi_clock_data *clk_data;
+       int ret;
+
+       clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
+       if (!clk_data)
+               return ERR_PTR(-ENOMEM);
+
+       ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+                               clk_data);
+       if (ret)
+               return ERR_PTR(ret);
+
+       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_gate:
+       hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+                               clk_data);
+       return ERR_PTR(ret);
+}
+
+static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+       of_clk_del_provider(pdev->dev.of_node);
+
+       hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+                               crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
+       .register_clks = hi3798cv200_sysctrl_clk_register,
+       .unregister_clks = hi3798cv200_sysctrl_clk_unregister,
+};
+
+static const struct of_device_id hi3798cv200_crg_match_table[] = {
+       { .compatible = "hisilicon,hi3798cv200-crg",
+               .data = &hi3798cv200_crg_funcs },
+       { .compatible = "hisilicon,hi3798cv200-sysctrl",
+               .data = &hi3798cv200_sysctrl_funcs },
+       { }
+};
+MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);
+
+static int hi3798cv200_crg_probe(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg;
+
+       crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+       if (!crg)
+               return -ENOMEM;
+
+       crg->funcs = of_device_get_match_data(&pdev->dev);
+       if (!crg->funcs)
+               return -ENOENT;
+
+       crg->rstc = hisi_reset_init(pdev);
+       if (!crg->rstc)
+               return -ENOMEM;
+
+       crg->clk_data = crg->funcs->register_clks(pdev);
+       if (IS_ERR(crg->clk_data)) {
+               hisi_reset_exit(crg->rstc);
+               return PTR_ERR(crg->clk_data);
+       }
+
+       platform_set_drvdata(pdev, crg);
+       return 0;
+}
+
+static int hi3798cv200_crg_remove(struct platform_device *pdev)
+{
+       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+       hisi_reset_exit(crg->rstc);
+       crg->funcs->unregister_clks(pdev);
+       return 0;
+}
+
+static struct platform_driver hi3798cv200_crg_driver = {
+       .probe          = hi3798cv200_crg_probe,
+       .remove         = hi3798cv200_crg_remove,
+       .driver         = {
+               .name   = "hi3798cv200-crg",
+               .of_match_table = hi3798cv200_crg_match_table,
+       },
+};
+
+static int __init hi3798cv200_crg_init(void)
+{
+       return platform_driver_register(&hi3798cv200_crg_driver);
+}
+core_initcall(hi3798cv200_crg_init);
+
+static void __exit hi3798cv200_crg_exit(void)
+{
+       platform_driver_unregister(&hi3798cv200_crg_driver);
+}
+module_exit(hi3798cv200_crg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");
diff --git a/drivers/clk/hisilicon/crg.h b/drivers/clk/hisilicon/crg.h
new file mode 100644 (file)
index 0000000..e073971
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * HiSilicon Clock and Reset Driver Header
+ *
+ * Copyright (c) 2016 HiSilicon Limited.
+ *
+ * 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 __HISI_CRG_H
+#define __HISI_CRG_H
+
+struct hisi_clock_data;
+struct hisi_reset_controller;
+
+struct hisi_crg_funcs {
+       struct hisi_clock_data* (*register_clks)(struct platform_device *pdev);
+       void (*unregister_clks)(struct platform_device *pdev);
+};
+
+struct hisi_crg_dev {
+       struct hisi_clock_data *clk_data;
+       struct hisi_reset_controller *rstc;
+       const struct hisi_crg_funcs *funcs;
+};
+
+#endif /* __HISI_CRG_H */
index ce8ea10407e48647aed9fdcf8d98c30ab29bd514..42ffc1c92bab0ca95454eb4ebfff28c78aa19196 100644 (file)
@@ -156,10 +156,267 @@ static struct clk ** const uart_clks[] __initconst = {
        NULL
 };
 
+static int ldb_di_sel_by_clock_id(int clock_id)
+{
+       switch (clock_id) {
+       case IMX6QDL_CLK_PLL5_VIDEO_DIV:
+               if (clk_on_imx6q() &&
+                   imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
+                       return -ENOENT;
+               return 0;
+       case IMX6QDL_CLK_PLL2_PFD0_352M:
+               return 1;
+       case IMX6QDL_CLK_PLL2_PFD2_396M:
+               return 2;
+       case IMX6QDL_CLK_MMDC_CH1_AXI:
+               return 3;
+       case IMX6QDL_CLK_PLL3_USB_OTG:
+               return 4;
+       default:
+               return -ENOENT;
+       }
+}
+
+static void of_assigned_ldb_sels(struct device_node *node,
+                                unsigned int *ldb_di0_sel,
+                                unsigned int *ldb_di1_sel)
+{
+       struct of_phandle_args clkspec;
+       int index, rc, num_parents;
+       int parent, child, sel;
+
+       num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+                                                "#clock-cells");
+       for (index = 0; index < num_parents; index++) {
+               rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+                                       "#clock-cells", index, &clkspec);
+               if (rc < 0) {
+                       /* skip empty (null) phandles */
+                       if (rc == -ENOENT)
+                               continue;
+                       else
+                               return;
+               }
+               if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+                       pr_err("ccm: parent clock %d not in ccm\n", index);
+                       return;
+               }
+               parent = clkspec.args[0];
+
+               rc = of_parse_phandle_with_args(node, "assigned-clocks",
+                               "#clock-cells", index, &clkspec);
+               if (rc < 0)
+                       return;
+               if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+                       pr_err("ccm: child clock %d not in ccm\n", index);
+                       return;
+               }
+               child = clkspec.args[0];
+
+               if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
+                   child != IMX6QDL_CLK_LDB_DI1_SEL)
+                       continue;
+
+               sel = ldb_di_sel_by_clock_id(parent);
+               if (sel < 0) {
+                       pr_err("ccm: invalid ldb_di%d parent clock: %d\n",
+                              child == IMX6QDL_CLK_LDB_DI1_SEL, parent);
+                       continue;
+               }
+
+               if (child == IMX6QDL_CLK_LDB_DI0_SEL)
+                       *ldb_di0_sel = sel;
+               if (child == IMX6QDL_CLK_LDB_DI1_SEL)
+                       *ldb_di1_sel = sel;
+       }
+}
+
+#define CCM_CCDR               0x04
+#define CCM_CCSR               0x0c
+#define CCM_CS2CDR             0x2c
+
+#define CCDR_MMDC_CH1_MASK             BIT(16)
+#define CCSR_PLL3_SW_CLK_SEL           BIT(0)
+
+#define CS2CDR_LDB_DI0_CLK_SEL_SHIFT   9
+#define CS2CDR_LDB_DI1_CLK_SEL_SHIFT   12
+
+static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
+{
+       unsigned int reg;
+
+       reg = readl_relaxed(ccm_base + CCM_CCDR);
+       reg |= CCDR_MMDC_CH1_MASK;
+       writel_relaxed(reg, ccm_base + CCM_CCDR);
+}
+
+/*
+ * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk
+ * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the
+ * bypass clock source, since there is no CG bit for mmdc_ch1.
+ */
+static void mmdc_ch1_disable(void __iomem *ccm_base)
+{
+       unsigned int reg;
+
+       clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL],
+                      clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+
+       /*
+        * Handshake with mmdc_ch1 module must be masked when changing
+        * periph2_clk_sel.
+        */
+       clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]);
+
+       /* Disable pll3_sw_clk by selecting the bypass clock source */
+       reg = readl_relaxed(ccm_base + CCM_CCSR);
+       reg |= CCSR_PLL3_SW_CLK_SEL;
+       writel_relaxed(reg, ccm_base + CCM_CCSR);
+}
+
+static void mmdc_ch1_reenable(void __iomem *ccm_base)
+{
+       unsigned int reg;
+
+       /* Enable pll3_sw_clk by disabling the bypass */
+       reg = readl_relaxed(ccm_base + CCM_CCSR);
+       reg &= ~CCSR_PLL3_SW_CLK_SEL;
+       writel_relaxed(reg, ccm_base + CCM_CCSR);
+
+       clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]);
+}
+
+/*
+ * We have to follow a strict procedure when changing the LDB clock source,
+ * otherwise we risk introducing a glitch that can lock up the LDB divider.
+ * Things to keep in mind:
+ *
+ * 1. The current and new parent clock inputs to the mux must be disabled.
+ * 2. The default clock input for ldb_di0/1_clk_sel is mmdc_ch1_axi, which
+ *    has no CG bit.
+ * 3. pll2_pfd2_396m can not be gated if it is used as memory clock.
+ * 4. In the RTL implementation of the LDB_DI_CLK_SEL muxes the top four
+ *    options are in one mux and the PLL3 option along with three unused
+ *    inputs is in a second mux. There is a third mux with two inputs used
+ *    to decide between the first and second 4-port mux:
+ *
+ *    pll5_video_div 0 --|\
+ *    pll2_pfd0_352m 1 --| |_
+ *    pll2_pfd2_396m 2 --| | `-|\
+ *    mmdc_ch1_axi   3 --|/    | |
+ *                             | |--
+ *    pll3_usb_otg   4 --|\    | |
+ *                   5 --| |_,-|/
+ *                   6 --| |
+ *                   7 --|/
+ *
+ * The ldb_di0/1_clk_sel[1:0] bits control both 4-port muxes at the same time.
+ * The ldb_di0/1_clk_sel[2] bit controls the 2-port mux. The code below
+ * switches the parent to the bottom mux first and then manipulates the top
+ * mux to ensure that no glitch will enter the divider.
+ */
+static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
+{
+       unsigned int reg;
+       unsigned int sel[2][4];
+       int i;
+
+       reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+       sel[0][0] = (reg >> CS2CDR_LDB_DI0_CLK_SEL_SHIFT) & 7;
+       sel[1][0] = (reg >> CS2CDR_LDB_DI1_CLK_SEL_SHIFT) & 7;
+
+       sel[0][3] = sel[0][2] = sel[0][1] = sel[0][0];
+       sel[1][3] = sel[1][2] = sel[1][1] = sel[1][0];
+
+       of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
+
+       for (i = 0; i < 2; i++) {
+               /* Warn if a glitch might have been introduced already */
+               if (sel[i][0] != 3) {
+                       pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
+                               i, sel[i][0]);
+               }
+
+               if (sel[i][0] == sel[i][3])
+                       continue;
+
+               /* Only switch to or from pll2_pfd2_396m if it is disabled */
+               if ((sel[i][0] == 2 || sel[i][3] == 2) &&
+                   (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+                    clk[IMX6QDL_CLK_PLL2_PFD2_396M])) {
+                       pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n",
+                              i);
+                       sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0];
+                       continue;
+               }
+
+               /* First switch to the bottom mux */
+               sel[i][1] = sel[i][0] | 4;
+
+               /* Then configure the top mux before switching back to it */
+               sel[i][2] = sel[i][3] | 4;
+
+               pr_debug("ccm: switching ldb_di%d_sel: %d->%d->%d->%d\n", i,
+                        sel[i][0], sel[i][1], sel[i][2], sel[i][3]);
+       }
+
+       if (sel[0][0] == sel[0][3] && sel[1][0] == sel[1][3])
+               return;
+
+       mmdc_ch1_disable(ccm_base);
+
+       for (i = 1; i < 4; i++) {
+               reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+               reg &= ~((7 << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+                        (7 << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+               reg |= ((sel[0][i] << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+                       (sel[1][i] << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+               writel_relaxed(reg, ccm_base + CCM_CS2CDR);
+       }
+
+       mmdc_ch1_reenable(ccm_base);
+}
+
+#define CCM_ANALOG_PLL_VIDEO   0xa0
+#define CCM_ANALOG_PFD_480     0xf0
+#define CCM_ANALOG_PFD_528     0x100
+
+#define PLL_ENABLE             BIT(13)
+
+#define PFD0_CLKGATE           BIT(7)
+#define PFD1_CLKGATE           BIT(15)
+#define PFD2_CLKGATE           BIT(23)
+#define PFD3_CLKGATE           BIT(31)
+
+static void disable_anatop_clocks(void __iomem *anatop_base)
+{
+       unsigned int reg;
+
+       /* Make sure PLL2 PFDs 0-2 are gated */
+       reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528);
+       /* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */
+       if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+           clk[IMX6QDL_CLK_PLL2_PFD2_396M])
+               reg |= PFD0_CLKGATE | PFD1_CLKGATE;
+       else
+               reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE;
+       writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_528);
+
+       /* Make sure PLL3 PFDs 0-3 are gated */
+       reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_480);
+       reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE | PFD3_CLKGATE;
+       writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_480);
+
+       /* Make sure PLL5 is disabled */
+       reg = readl_relaxed(anatop_base + CCM_ANALOG_PLL_VIDEO);
+       reg &= ~PLL_ENABLE;
+       writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO);
+}
+
 static void __init imx6q_clocks_init(struct device_node *ccm_node)
 {
        struct device_node *np;
-       void __iomem *base;
+       void __iomem *anatop_base, *base;
        int i;
        int ret;
 
@@ -172,7 +429,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
-       base = of_iomap(np, 0);
+       anatop_base = base = of_iomap(np, 0);
        WARN_ON(!base);
 
        /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
@@ -330,8 +587,20 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
        clk[IMX6QDL_CLK_IPU1_SEL]         = imx_clk_mux("ipu1_sel",         base + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
        clk[IMX6QDL_CLK_IPU2_SEL]         = imx_clk_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
-       clk[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+
+       disable_anatop_clocks(anatop_base);
+
+       imx6q_mmdc_ch1_mask_handshake(base);
+
+       /*
+        * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware
+        * bug. Set the muxes to the requested values before registering the
+        * ldb_di_sel clocks.
+        */
+       init_ldb_clks(np, base);
+
+       clk[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
+       clk[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
        clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
        clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
        clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
@@ -582,12 +851,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 
        clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
 
-       if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
-           clk_on_imx6dl()) {
-               clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-               clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-       }
-
        clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
        if (clk_on_imx6dl())
                clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
index d1d7787ce2113f8854619e69217edda89598a55f..75c35fb12b608781e04a7a54c630b3509f68aecb 100644 (file)
@@ -64,6 +64,10 @@ static const char *perclk_sels[] = { "ipg", "osc", };
 static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
 static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
 static const char *sim_sels[] = { "sim_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+/* epdc_pre_sels, epdc_sels, esai_sels only exists on i.MX6ULL */
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *esai_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
 
 static struct clk *clks[IMX6UL_CLK_END];
 static struct clk_onecell_data clk_data;
@@ -102,6 +106,17 @@ static u32 share_count_audio;
 static u32 share_count_sai1;
 static u32 share_count_sai2;
 static u32 share_count_sai3;
+static u32 share_count_esai;
+
+static inline int clk_on_imx6ul(void)
+{
+       return of_machine_is_compatible("fsl,imx6ul");
+}
+
+static inline int clk_on_imx6ull(void)
+{
+       return of_machine_is_compatible("fsl,imx6ull");
+}
 
 static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 {
@@ -238,12 +253,19 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_QSPI1_SEL]        = imx_clk_mux("qspi1_sel",    base + 0x1c, 7,  3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
        clks[IMX6UL_CLK_PERCLK_SEL]       = imx_clk_mux("perclk_sel",   base + 0x1c, 6,  1, perclk_sels, ARRAY_SIZE(perclk_sels));
        clks[IMX6UL_CLK_CAN_SEL]          = imx_clk_mux("can_sel",      base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
+       if (clk_on_imx6ull())
+               clks[IMX6ULL_CLK_ESAI_SEL]        = imx_clk_mux("esai_sel",     base + 0x20, 19, 2, esai_sels, ARRAY_SIZE(esai_sels));
        clks[IMX6UL_CLK_UART_SEL]         = imx_clk_mux("uart_sel",     base + 0x24, 6,  1, uart_sels, ARRAY_SIZE(uart_sels));
        clks[IMX6UL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",     base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
        clks[IMX6UL_CLK_LDB_DI0_SEL]      = imx_clk_mux("ldb_di0_sel",  base + 0x2c, 9,  3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
        clks[IMX6UL_CLK_SPDIF_SEL]        = imx_clk_mux("spdif_sel",    base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
-       clks[IMX6UL_CLK_SIM_PRE_SEL]      = imx_clk_mux("sim_pre_sel",  base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
-       clks[IMX6UL_CLK_SIM_SEL]          = imx_clk_mux("sim_sel",      base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+       if (clk_on_imx6ul()) {
+               clks[IMX6UL_CLK_SIM_PRE_SEL]      = imx_clk_mux("sim_pre_sel",  base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+               clks[IMX6UL_CLK_SIM_SEL]          = imx_clk_mux("sim_sel",      base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+       } else if (clk_on_imx6ull()) {
+               clks[IMX6ULL_CLK_EPDC_PRE_SEL]    = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+               clks[IMX6ULL_CLK_EPDC_SEL]        = imx_clk_mux("epdc_sel",     base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+       }
        clks[IMX6UL_CLK_ECSPI_SEL]        = imx_clk_mux("ecspi_sel",    base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
        clks[IMX6UL_CLK_LCDIF_PRE_SEL]    = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
        clks[IMX6UL_CLK_LCDIF_SEL]        = imx_clk_mux("lcdif_sel",    base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
@@ -276,6 +298,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_SAI3_PODF]      = imx_clk_divider("sai3_podf",     "sai3_pred",         base + 0x28, 16, 6);
        clks[IMX6UL_CLK_SAI1_PRED]      = imx_clk_divider("sai1_pred",     "sai1_sel",          base + 0x28, 6,  3);
        clks[IMX6UL_CLK_SAI1_PODF]      = imx_clk_divider("sai1_podf",     "sai1_pred",         base + 0x28, 0,  6);
+       if (clk_on_imx6ull()) {
+               clks[IMX6ULL_CLK_ESAI_PRED]     = imx_clk_divider("esai_pred",     "esai_sel",          base + 0x28, 9,  3);
+               clks[IMX6ULL_CLK_ESAI_PODF]     = imx_clk_divider("esai_podf",     "esai_pred",         base + 0x28, 25, 3);
+       }
        clks[IMX6UL_CLK_ENFC_PRED]      = imx_clk_divider("enfc_pred",     "enfc_sel",          base + 0x2c, 18, 3);
        clks[IMX6UL_CLK_ENFC_PODF]      = imx_clk_divider("enfc_podf",     "enfc_pred",         base + 0x2c, 21, 6);
        clks[IMX6UL_CLK_SAI2_PRED]      = imx_clk_divider("sai2_pred",     "sai2_sel",          base + 0x2c, 6,  3);
@@ -298,9 +324,15 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_APBHDMA]        = imx_clk_gate2("apbh_dma",     "bch_podf",     base + 0x68,    4);
        clks[IMX6UL_CLK_ASRC_IPG]       = imx_clk_gate2_shared("asrc_ipg",      "ahb",  base + 0x68,    6, &share_count_asrc);
        clks[IMX6UL_CLK_ASRC_MEM]       = imx_clk_gate2_shared("asrc_mem",      "ahb",  base + 0x68,    6, &share_count_asrc);
-       clks[IMX6UL_CLK_CAAM_MEM]       = imx_clk_gate2("caam_mem",     "ahb",          base + 0x68,    8);
-       clks[IMX6UL_CLK_CAAM_ACLK]      = imx_clk_gate2("caam_aclk",    "ahb",          base + 0x68,    10);
-       clks[IMX6UL_CLK_CAAM_IPG]       = imx_clk_gate2("caam_ipg",     "ipg",          base + 0x68,    12);
+       if (clk_on_imx6ul()) {
+               clks[IMX6UL_CLK_CAAM_MEM]       = imx_clk_gate2("caam_mem",     "ahb",          base + 0x68,    8);
+               clks[IMX6UL_CLK_CAAM_ACLK]      = imx_clk_gate2("caam_aclk",    "ahb",          base + 0x68,    10);
+               clks[IMX6UL_CLK_CAAM_IPG]       = imx_clk_gate2("caam_ipg",     "ipg",          base + 0x68,    12);
+       } else if (clk_on_imx6ull()) {
+               clks[IMX6ULL_CLK_DCP_CLK]       = imx_clk_gate2("dcp",          "ahb",          base + 0x68,    10);
+               clks[IMX6UL_CLK_ENET]           = imx_clk_gate2("enet",         "ipg",          base + 0x68,    12);
+               clks[IMX6UL_CLK_ENET_AHB]       = imx_clk_gate2("enet_ahb",     "ahb",          base + 0x68,    12);
+       }
        clks[IMX6UL_CLK_CAN1_IPG]       = imx_clk_gate2("can1_ipg",     "ipg",          base + 0x68,    14);
        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);
@@ -309,7 +341,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        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);
+       if (clk_on_imx6ul())
+               clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",          base + 0x68,    30);
+       else if (clk_on_imx6ull())
+               clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",           base + 0x80,   18);
 
        /* CCGR1 */
        clks[IMX6UL_CLK_ECSPI1]         = imx_clk_gate2("ecspi1",       "ecspi_podf",   base + 0x6c,    0);
@@ -328,6 +363,11 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_UART4_SERIAL]   = imx_clk_gate2("uart4_serail", "uart_podf",    base + 0x6c,    24);
 
        /* CCGR2 */
+       if (clk_on_imx6ull()) {
+               clks[IMX6ULL_CLK_ESAI_EXTAL]    = imx_clk_gate2_shared("esai_extal",    "esai_podf",    base + 0x70,    0, &share_count_esai);
+               clks[IMX6ULL_CLK_ESAI_IPG]      = imx_clk_gate2_shared("esai_ipg",      "ahb",          base + 0x70,    0, &share_count_esai);
+               clks[IMX6ULL_CLK_ESAI_MEM]      = imx_clk_gate2_shared("esai_mem",      "ahb",          base + 0x70,    0, &share_count_esai);
+       }
        clks[IMX6UL_CLK_CSI]            = imx_clk_gate2("csi",          "csi_podf",             base + 0x70,    2);
        clks[IMX6UL_CLK_I2C1]           = imx_clk_gate2("i2c1",         "perclk",       base + 0x70,    6);
        clks[IMX6UL_CLK_I2C2]           = imx_clk_gate2("i2c2",         "perclk",       base + 0x70,    8);
@@ -340,8 +380,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        /* CCGR3 */
        clks[IMX6UL_CLK_UART5_IPG]      = imx_clk_gate2("uart5_ipg",    "ipg",          base + 0x74,    2);
        clks[IMX6UL_CLK_UART5_SERIAL]   = imx_clk_gate2("uart5_serial", "uart_podf",    base + 0x74,    2);
-       clks[IMX6UL_CLK_ENET]           = imx_clk_gate2("enet",         "ipg",          base + 0x74,    4);
-       clks[IMX6UL_CLK_ENET_AHB]       = imx_clk_gate2("enet_ahb",     "ahb",          base + 0x74,    4);
+       if (clk_on_imx6ul()) {
+               clks[IMX6UL_CLK_ENET]           = imx_clk_gate2("enet",         "ipg",          base + 0x74,    4);
+               clks[IMX6UL_CLK_ENET_AHB]       = imx_clk_gate2("enet_ahb",     "ahb",          base + 0x74,    4);
+       } else if (clk_on_imx6ull()) {
+               clks[IMX6ULL_CLK_EPDC_ACLK]     = imx_clk_gate2("epdc_aclk",    "axi",          base + 0x74,    4);
+               clks[IMX6ULL_CLK_EPDC_PIX]      = imx_clk_gate2("epdc_pix",     "epdc_podf",    base + 0x74,    4);
+       }
        clks[IMX6UL_CLK_UART6_IPG]      = imx_clk_gate2("uart6_ipg",    "ipg",          base + 0x74,    6);
        clks[IMX6UL_CLK_UART6_SERIAL]   = imx_clk_gate2("uart6_serial", "uart_podf",    base + 0x74,    6);
        clks[IMX6UL_CLK_LCDIF_PIX]      = imx_clk_gate2("lcdif_pix",    "lcdif_podf",   base + 0x74,    10);
@@ -385,8 +430,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_USBOH3]         = imx_clk_gate2("usboh3",       "ipg",           base + 0x80,   0);
        clks[IMX6UL_CLK_USDHC1]         = imx_clk_gate2("usdhc1",       "usdhc1_podf",   base + 0x80,   2);
        clks[IMX6UL_CLK_USDHC2]         = imx_clk_gate2("usdhc2",       "usdhc2_podf",   base + 0x80,   4);
-       clks[IMX6UL_CLK_SIM1]           = imx_clk_gate2("sim1",         "sim_sel",       base + 0x80,   6);
-       clks[IMX6UL_CLK_SIM2]           = imx_clk_gate2("sim2",         "sim_sel",       base + 0x80,   8);
+       if (clk_on_imx6ul()) {
+               clks[IMX6UL_CLK_SIM1]           = imx_clk_gate2("sim1",         "sim_sel",       base + 0x80,   6);
+               clks[IMX6UL_CLK_SIM2]           = imx_clk_gate2("sim2",         "sim_sel",       base + 0x80,   8);
+       }
        clks[IMX6UL_CLK_EIM]            = imx_clk_gate2("eim",          "eim_slow_podf", base + 0x80,   10);
        clks[IMX6UL_CLK_PWM8]           = imx_clk_gate2("pwm8",         "perclk",        base + 0x80,   16);
        clks[IMX6UL_CLK_UART8_IPG]      = imx_clk_gate2("uart8_ipg",    "ipg",           base + 0x80,   14);
@@ -441,7 +488,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        }
 
        clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
-       clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+       if (clk_on_imx6ul())
+               clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+       else if (clk_on_imx6ull())
+               clk_set_parent(clks[IMX6ULL_CLK_EPDC_PRE_SEL], clks[IMX6UL_CLK_PLL3_PFD2]);
 
        clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
 }
index 7a6acc3e4a927c1ae874bdb74bbe826284602c3a..ed3a2df536ea92e7960026f06db778585b75f2fb 100644 (file)
@@ -234,6 +234,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long max_rate = parent_rate * 54;
        u32 div;
        u32 mfn, mfd = 1000000;
+       u32 max_mfd = 0x3FFFFFFF;
        u64 temp64;
 
        if (rate > max_rate)
@@ -241,6 +242,9 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
        else if (rate < min_rate)
                rate = min_rate;
 
+       if (parent_rate <= max_mfd)
+               mfd = parent_rate;
+
        div = rate / parent_rate;
        temp64 = (u64) (rate - div * parent_rate);
        temp64 *= mfd;
@@ -262,11 +266,15 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long max_rate = parent_rate * 54;
        u32 val, div;
        u32 mfn, mfd = 1000000;
+       u32 max_mfd = 0x3FFFFFFF;
        u64 temp64;
 
        if (rate < min_rate || rate > max_rate)
                return -EINVAL;
 
+       if (parent_rate <= max_mfd)
+               mfd = parent_rate;
+
        div = rate / parent_rate;
        temp64 = (u64) (rate - div * parent_rate);
        temp64 *= mfd;
index 3799ff82a9b487e85358d2dc57c8dc8fe203ea6f..4afad3b96a61cdf1a7e4ddca6529884ba78e3b96 100644 (file)
@@ -75,6 +75,14 @@ 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_mux_ldb(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_SET_RATE_PARENT, reg,
+                       shift, width, CLK_MUX_READ_ONLY, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_fixed_factor(const char *name,
                const char *parent, unsigned int mult, unsigned int div)
 {
index a26ba2184454a8654eca7d7ca3185b472e7ff46e..e7e840fb74eaf7cf58da79d31fbf8d2dd9daeea2 100644 (file)
@@ -154,7 +154,7 @@ out:
 }
 
 /**
- * _of_clk_init - PLL initialisation via DT
+ * _of_pll_clk_init - PLL initialisation via DT
  * @node: device tree node for this clock
  * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
  *             pll controller, else it is in the control register0(bit 11-6)
@@ -235,7 +235,7 @@ CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock",
                                        of_keystone_pll_clk_init);
 
 /**
- * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper
+ * of_keystone_main_pll_clk_init - Main PLL initialisation DT wrapper
  * @node: device tree node for this clock
  */
 static void __init of_keystone_main_pll_clk_init(struct device_node *node)
@@ -267,25 +267,30 @@ static void __init of_pll_div_clk_init(struct device_node *node)
        parent_name = of_clk_get_parent_name(node, 0);
        if (!parent_name) {
                pr_err("%s: missing parent clock\n", __func__);
+               iounmap(reg);
                return;
        }
 
        if (of_property_read_u32(node, "bit-shift", &shift)) {
                pr_err("%s: missing 'shift' property\n", __func__);
+               iounmap(reg);
                return;
        }
 
        if (of_property_read_u32(node, "bit-mask", &mask)) {
                pr_err("%s: missing 'bit-mask' property\n", __func__);
+               iounmap(reg);
                return;
        }
 
        clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
                                 mask, 0, NULL);
-       if (clk)
+       if (clk) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
-       else
+       } else {
                pr_err("%s: error registering divider %s\n", __func__, clk_name);
+               iounmap(reg);
+       }
 }
 CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
 
index f042bd2a6a998651481e7ca594333c3856f6d8dc..0bd631a41f6a9287d3b1ed668bd604df595748a6 100644 (file)
@@ -6,6 +6,49 @@ config COMMON_CLK_MEDIATEK
        ---help---
          Mediatek SoCs' clock support.
 
+config COMMON_CLK_MT2701
+       bool "Clock driver for Mediatek MT2701"
+       select COMMON_CLK_MEDIATEK
+       default ARCH_MEDIATEK
+       ---help---
+         This driver supports Mediatek MT2701 basic clocks.
+
+config COMMON_CLK_MT2701_MMSYS
+       bool "Clock driver for Mediatek MT2701 mmsys"
+       select COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 mmsys clocks.
+
+config COMMON_CLK_MT2701_IMGSYS
+       bool "Clock driver for Mediatek MT2701 imgsys"
+       select COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 imgsys clocks.
+
+config COMMON_CLK_MT2701_VDECSYS
+       bool "Clock driver for Mediatek MT2701 vdecsys"
+       select COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 vdecsys clocks.
+
+config COMMON_CLK_MT2701_HIFSYS
+       bool "Clock driver for Mediatek MT2701 hifsys"
+       select COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 hifsys clocks.
+
+config COMMON_CLK_MT2701_ETHSYS
+       bool "Clock driver for Mediatek MT2701 ethsys"
+       select COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 ethsys clocks.
+
+config COMMON_CLK_MT2701_BDPSYS
+       bool "Clock driver for Mediatek MT2701 bdpsys"
+       select COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 bdpsys clocks.
+
 config COMMON_CLK_MT8135
        bool "Clock driver for Mediatek MT8135"
        depends on ARCH_MEDIATEK || COMPILE_TEST
index 32e7222e730567e7cbbdd19f8c23e1797e1e6a1e..19ae7ef79b5722ce4f63ba80832285a196c35231 100644 (file)
@@ -1,4 +1,11 @@
 obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
+obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
+obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
+obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
+obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
+obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
 obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
 obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
index d8787bf444eb5c92d5aa318cdf5415fb5fcb8863..934bf0e45e262afb265ea9ab4d644e7928fd4c8f 100644 (file)
@@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
        regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
 }
 
+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
+{
+       struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+       u32 cgbit = BIT(cg->bit);
+
+       regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
+}
+
+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
+{
+       struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+       u32 cgbit = BIT(cg->bit);
+
+       regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
+}
+
 static int mtk_cg_enable(struct clk_hw *hw)
 {
        mtk_cg_clr_bit(hw);
@@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
        mtk_cg_clr_bit(hw);
 }
 
+static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
+{
+       mtk_cg_clr_bit_no_setclr(hw);
+
+       return 0;
+}
+
+static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
+{
+       mtk_cg_set_bit_no_setclr(hw);
+}
+
+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
+{
+       mtk_cg_set_bit_no_setclr(hw);
+
+       return 0;
+}
+
+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
+{
+       mtk_cg_clr_bit_no_setclr(hw);
+}
+
 const struct clk_ops mtk_clk_gate_ops_setclr = {
        .is_enabled     = mtk_cg_bit_is_cleared,
        .enable         = mtk_cg_enable,
@@ -97,6 +137,18 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
        .disable        = mtk_cg_disable_inv,
 };
 
+const struct clk_ops mtk_clk_gate_ops_no_setclr = {
+       .is_enabled     = mtk_cg_bit_is_cleared,
+       .enable         = mtk_cg_enable_no_setclr,
+       .disable        = mtk_cg_disable_no_setclr,
+};
+
+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
+       .is_enabled     = mtk_cg_bit_is_set,
+       .enable         = mtk_cg_enable_inv_no_setclr,
+       .disable        = mtk_cg_disable_inv_no_setclr,
+};
+
 struct clk *mtk_clk_register_gate(
                const char *name,
                const char *parent_name,
index b1821603b887f2874f97c6fb1819ff0fddfcd619..72ef89b3ad7ba260a5c01f3cbc9fd6728c0cae81 100644 (file)
@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw)
 
 extern const struct clk_ops mtk_clk_gate_ops_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
 
 struct clk *mtk_clk_register_gate(
                const char *name,
diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
new file mode 100644 (file)
index 0000000..fe4964d
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs bdp0_cg_regs = {
+       .set_ofs = 0x0104,
+       .clr_ofs = 0x0108,
+       .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs bdp1_cg_regs = {
+       .set_ofs = 0x0114,
+       .clr_ofs = 0x0118,
+       .sta_ofs = 0x0110,
+};
+
+#define GATE_BDP0(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &bdp0_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+#define GATE_BDP1(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &bdp1_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+static const struct mtk_gate bdp_clks[] = {
+       GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+       GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+       GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+       GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
+       GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
+       GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
+       GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
+       GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
+       GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
+       GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
+       GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
+       GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
+       GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
+       GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
+       GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
+       GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
+       GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
+       GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
+       GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
+       GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
+       GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
+       GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
+       GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
+       GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
+       GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
+       GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
+       GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
+       GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
+       GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
+       GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
+       GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
+       GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
+       GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
+       GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
+       GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
+       GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
+       GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
+       GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
+       GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
+       GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
+       GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
+       GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
+       GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
+       GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
+       GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
+       GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
+       GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
+       GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
+       GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
+};
+
+static const struct of_device_id of_match_clk_mt2701_bdp[] = {
+       { .compatible = "mediatek,mt2701-bdpsys", },
+       {}
+};
+
+static int clk_mt2701_bdp_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+
+       mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt2701_bdp_drv = {
+       .probe = clk_mt2701_bdp_probe,
+       .driver = {
+               .name = "clk-mt2701-bdp",
+               .of_match_table = of_match_clk_mt2701_bdp,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_bdp_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c
new file mode 100644 (file)
index 0000000..877be87
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs eth_cg_regs = {
+       .sta_ofs = 0x0030,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) {                \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &eth_cg_regs,                   \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+       }
+
+static const struct mtk_gate eth_clks[] = {
+       GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
+       GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
+       GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
+       GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
+       GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
+       GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
+       GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
+       GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
+};
+
+static const struct of_device_id of_match_clk_mt2701_eth[] = {
+       { .compatible = "mediatek,mt2701-ethsys", },
+       {}
+};
+
+static int clk_mt2701_eth_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+
+       mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt2701_eth_drv = {
+       .probe = clk_mt2701_eth_probe,
+       .driver = {
+               .name = "clk-mt2701-eth",
+               .of_match_table = of_match_clk_mt2701_eth,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_eth_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
new file mode 100644 (file)
index 0000000..18f3723
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs hif_cg_regs = {
+       .sta_ofs = 0x0030,
+};
+
+#define GATE_HIF(_id, _name, _parent, _shift) {                \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &hif_cg_regs,                   \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+       }
+
+static const struct mtk_gate hif_clks[] = {
+       GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
+       GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
+       GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
+       GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
+       GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
+};
+
+static const struct of_device_id of_match_clk_mt2701_hif[] = {
+       { .compatible = "mediatek,mt2701-hifsys", },
+       {}
+};
+
+static int clk_mt2701_hif_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+
+       mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r) {
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+               return r;
+       }
+
+       mtk_register_reset_controller(node, 1, 0x34);
+
+       return 0;
+}
+
+static struct platform_driver clk_mt2701_hif_drv = {
+       .probe = clk_mt2701_hif_probe,
+       .driver = {
+               .name = "clk-mt2701-hif",
+               .of_match_table = of_match_clk_mt2701_hif,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_hif_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
new file mode 100644 (file)
index 0000000..b7441c9
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+       .set_ofs = 0x0004,
+       .clr_ofs = 0x0008,
+       .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) {                \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &img_cg_regs,                   \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+static const struct mtk_gate img_clks[] = {
+       GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+       GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+       GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+       GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
+       GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
+       GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
+};
+
+static const struct of_device_id of_match_clk_mt2701_img[] = {
+       { .compatible = "mediatek,mt2701-imgsys", },
+       {}
+};
+
+static int clk_mt2701_img_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+       mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt2701_img_drv = {
+       .probe = clk_mt2701_img_probe,
+       .driver = {
+               .name = "clk-mt2701-img",
+               .of_match_table = of_match_clk_mt2701_img,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c
new file mode 100644 (file)
index 0000000..fe1f850
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs disp0_cg_regs = {
+       .set_ofs = 0x0104,
+       .clr_ofs = 0x0108,
+       .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs disp1_cg_regs = {
+       .set_ofs = 0x0114,
+       .clr_ofs = 0x0118,
+       .sta_ofs = 0x0110,
+};
+
+#define GATE_DISP0(_id, _name, _parent, _shift) {      \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &disp0_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+#define GATE_DISP1(_id, _name, _parent, _shift) {      \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &disp1_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+static const struct mtk_gate mm_clks[] = {
+       GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
+       GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+       GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
+       GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
+       GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
+       GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
+       GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
+       GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
+       GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
+       GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+       GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
+       GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+       GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
+       GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
+       GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
+       GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
+       GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
+       GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
+       GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
+       GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+       GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
+       GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
+       GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
+       GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
+       GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
+       GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
+       GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
+       GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
+       GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
+       GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
+       GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
+       GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
+       GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
+       GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
+};
+
+static const struct of_device_id of_match_clk_mt2701_mm[] = {
+       { .compatible = "mediatek,mt2701-mmsys", },
+       {}
+};
+
+static int clk_mt2701_mm_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+       mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt2701_mm_drv = {
+       .probe = clk_mt2701_mm_probe,
+       .driver = {
+               .name = "clk-mt2701-mm",
+               .of_match_table = of_match_clk_mt2701_mm,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
new file mode 100644 (file)
index 0000000..d3c0fc9
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+       .set_ofs = 0x0000,
+       .clr_ofs = 0x0004,
+       .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+       .set_ofs = 0x0008,
+       .clr_ofs = 0x000c,
+       .sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) {      \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &vdec0_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) {      \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &vdec1_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+static const struct mtk_gate vdec_clks[] = {
+       GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+       GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+};
+
+static const struct of_device_id of_match_clk_mt2701_vdec[] = {
+       { .compatible = "mediatek,mt2701-vdecsys", },
+       {}
+};
+
+static int clk_mt2701_vdec_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+       mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt2701_vdec_drv = {
+       .probe = clk_mt2701_vdec_probe,
+       .driver = {
+               .name = "clk-mt2701-vdec",
+               .of_match_table = of_match_clk_mt2701_vdec,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
new file mode 100644 (file)
index 0000000..6f26e6a
--- /dev/null
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+#define DUMMY_RATE             0
+
+static DEFINE_SPINLOCK(mt2701_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+       FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m",
+               108 * MHZ),
+       FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m",
+               400 * MHZ),
+       FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m",
+               295750000),
+       FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m",
+               340 * MHZ),
+       FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m",
+               340 * MHZ),
+       FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m",
+               340 * MHZ),
+       FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m",
+               300 * MHZ),
+       FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m",
+               27 * MHZ),
+       FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m",
+               416 * MHZ),
+       FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m",
+               143 * MHZ),
+       FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m",
+               27 * MHZ),
+       FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m",
+               DUMMY_RATE),
+       FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m",
+               DUMMY_RATE),
+       FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m",
+               DUMMY_RATE),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+       FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+       FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+       FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+       FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+       FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+       FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+       FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+       FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+       FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+       FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+       FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+
+       FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1),
+       FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+       FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+       FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+       FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+       FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52),
+       FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108),
+       FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+       FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+       FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1),
+       FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
+       FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16),
+       FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+       FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+
+       FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+       FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+       FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+       FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+
+       FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+       FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+       FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2),
+       FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4),
+       FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1),
+
+       FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+       FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+       FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+
+       FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1),
+       FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1),
+       FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2),
+
+       FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1),
+       FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2),
+       FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4),
+
+       FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1),
+       FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2),
+       FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3),
+
+       FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1),
+
+       FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1),
+       FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4),
+       FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8),
+       FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16),
+       FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24),
+
+       FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3),
+       FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3),
+       FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3),
+       FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1),
+       FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1),
+       FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
+       FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
+       FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+};
+
+static const char * const axi_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "syspll_d5",
+       "syspll1_d4",
+       "univpll_d5",
+       "univpll2_d2",
+       "mmpll_d2",
+       "dmpll_d2"
+};
+
+static const char * const mem_parents[] = {
+       "clk26m",
+       "dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] = {
+       "clk26m",
+       "syspll1_d8"
+};
+
+static const char * const mm_parents[] = {
+       "clk26m",
+       "vencpll_ck",
+       "syspll1_d2",
+       "syspll1_d4",
+       "univpll_d5",
+       "univpll1_d2",
+       "univpll2_d2",
+       "dmpll_ck"
+};
+
+static const char * const pwm_parents[] = {
+       "clk26m",
+       "univpll2_d4",
+       "univpll3_d2",
+       "univpll1_d4",
+};
+
+static const char * const vdec_parents[] = {
+       "clk26m",
+       "vdecpll_ck",
+       "syspll_d5",
+       "syspll1_d4",
+       "univpll_d5",
+       "univpll2_d2",
+       "vencpll_ck",
+       "msdcpll_d2",
+       "mmpll_d2"
+};
+
+static const char * const mfg_parents[] = {
+       "clk26m",
+       "mmpll_ck",
+       "dmpll_x2_ck",
+       "msdcpll_ck",
+       "clk26m",
+       "syspll_d3",
+       "univpll_d3",
+       "univpll1_d2"
+};
+
+static const char * const camtg_parents[] = {
+       "clk26m",
+       "univpll_d26",
+       "univpll2_d2",
+       "syspll3_d2",
+       "syspll3_d4",
+       "msdcpll_d2",
+       "mmpll_d2"
+};
+
+static const char * const uart_parents[] = {
+       "clk26m",
+       "univpll2_d8"
+};
+
+static const char * const spi_parents[] = {
+       "clk26m",
+       "syspll3_d2",
+       "syspll4_d2",
+       "univpll2_d4",
+       "univpll1_d8"
+};
+
+static const char * const usb20_parents[] = {
+       "clk26m",
+       "univpll1_d8",
+       "univpll3_d4"
+};
+
+static const char * const msdc30_parents[] = {
+       "clk26m",
+       "msdcpll_d2",
+       "syspll2_d2",
+       "syspll1_d4",
+       "univpll1_d4",
+       "univpll2_d4"
+};
+
+static const char * const audio_parents[] = {
+       "clk26m",
+       "syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+       "clk26m",
+       "syspll1_d4",
+       "syspll3_d2",
+       "syspll4_d2",
+       "univpll3_d2",
+       "univpll2_d4"
+};
+
+static const char * const pmicspi_parents[] = {
+       "clk26m",
+       "syspll1_d8",
+       "syspll2_d4",
+       "syspll4_d2",
+       "syspll3_d4",
+       "syspll2_d8",
+       "syspll1_d16",
+       "univpll3_d4",
+       "univpll_d26",
+       "dmpll_d2",
+       "dmpll_d4"
+};
+
+static const char * const scp_parents[] = {
+       "clk26m",
+       "syspll1_d8",
+       "dmpll_d2",
+       "dmpll_d4"
+};
+
+static const char * const dpi0_parents[] = {
+       "clk26m",
+       "mipipll",
+       "mipipll_d2",
+       "mipipll_d4",
+       "clk26m",
+       "tvdpll_ck",
+       "tvdpll_d2",
+       "tvdpll_d4"
+};
+
+static const char * const dpi1_parents[] = {
+       "clk26m",
+       "tvdpll_ck",
+       "tvdpll_d2",
+       "tvdpll_d4"
+};
+
+static const char * const tve_parents[] = {
+       "clk26m",
+       "mipipll",
+       "mipipll_d2",
+       "mipipll_d4",
+       "clk26m",
+       "tvdpll_ck",
+       "tvdpll_d2",
+       "tvdpll_d4"
+};
+
+static const char * const hdmi_parents[] = {
+       "clk26m",
+       "hdmipll_ck",
+       "hdmipll_d2",
+       "hdmipll_d3"
+};
+
+static const char * const apll_parents[] = {
+       "clk26m",
+       "audpll",
+       "audpll_d4",
+       "audpll_d8",
+       "audpll_d16",
+       "audpll_d24",
+       "clk26m",
+       "clk26m"
+};
+
+static const char * const rtc_parents[] = {
+       "32k_internal",
+       "32k_external",
+       "clk26m",
+       "univpll3_d8"
+};
+
+static const char * const nfi2x_parents[] = {
+       "clk26m",
+       "syspll2_d2",
+       "syspll_d7",
+       "univpll3_d2",
+       "syspll2_d4",
+       "univpll3_d4",
+       "syspll4_d4",
+       "clk26m"
+};
+
+static const char * const emmc_hclk_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "syspll1_d4",
+       "syspll2_d2"
+};
+
+static const char * const flash_parents[] = {
+       "clk26m_d8",
+       "clk26m",
+       "syspll2_d8",
+       "syspll3_d4",
+       "univpll3_d4",
+       "syspll4_d2",
+       "syspll2_d4",
+       "univpll2_d4"
+};
+
+static const char * const di_parents[] = {
+       "clk26m",
+       "tvd2pll_ck",
+       "tvd2pll_d2",
+       "clk26m"
+};
+
+static const char * const nr_osd_parents[] = {
+       "clk26m",
+       "vencpll_ck",
+       "syspll1_d2",
+       "syspll1_d4",
+       "univpll_d5",
+       "univpll1_d2",
+       "univpll2_d2",
+       "dmpll_ck"
+};
+
+static const char * const hdmirx_bist_parents[] = {
+       "clk26m",
+       "syspll_d3",
+       "clk26m",
+       "syspll1_d16",
+       "syspll4_d2",
+       "syspll1_d4",
+       "vencpll_ck",
+       "clk26m"
+};
+
+static const char * const intdir_parents[] = {
+       "clk26m",
+       "mmpll_ck",
+       "syspll_d2",
+       "univpll_d2"
+};
+
+static const char * const asm_parents[] = {
+       "clk26m",
+       "univpll2_d4",
+       "univpll2_d2",
+       "syspll_d5"
+};
+
+static const char * const ms_card_parents[] = {
+       "clk26m",
+       "univpll3_d8",
+       "syspll4_d4"
+};
+
+static const char * const ethif_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "syspll_d5",
+       "syspll1_d4",
+       "univpll_d5",
+       "univpll1_d2",
+       "dmpll_ck",
+       "dmpll_d2"
+};
+
+static const char * const hdmirx_parents[] = {
+       "clk26m",
+       "univpll_d52"
+};
+
+static const char * const cmsys_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "univpll1_d2",
+       "univpll_d5",
+       "syspll_d5",
+       "syspll2_d2",
+       "syspll1_d4",
+       "syspll3_d2",
+       "syspll2_d4",
+       "syspll1_d8",
+       "clk26m",
+       "clk26m",
+       "clk26m",
+       "clk26m",
+       "clk26m"
+};
+
+static const char * const clk_8bdac_parents[] = {
+       "32k_internal",
+       "8bdac_ck",
+       "clk26m",
+       "clk26m"
+};
+
+static const char * const aud2dvd_parents[] = {
+       "a1sys_hp_ck",
+       "a2sys_hp_ck"
+};
+
+static const char * const padmclk_parents[] = {
+       "clk26m",
+       "univpll_d26",
+       "univpll_d52",
+       "univpll_d108",
+       "univpll2_d8",
+       "univpll2_d16",
+       "univpll2_d32"
+};
+
+static const char * const aud_mux_parents[] = {
+       "clk26m",
+       "aud1pll_98m_ck",
+       "aud2pll_90m_ck",
+       "hadds2pll_98m",
+       "audio_ext1_ck",
+       "audio_ext2_ck"
+};
+
+static const char * const aud_src_parents[] = {
+       "aud_mux1_sel",
+       "aud_mux2_sel"
+};
+
+static const char * const cpu_parents[] = {
+       "clk26m",
+       "armpll",
+       "mainpll",
+       "mmpll"
+};
+
+static const struct mtk_composite top_muxes[] = {
+       MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+               0x0040, 0, 3, 7, CLK_IS_CRITICAL),
+       MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+               0x0040, 8, 1, 15, CLK_IS_CRITICAL),
+       MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel",
+               ddrphycfg_parents, 0x0040, 16, 1, 23, CLK_IS_CRITICAL),
+       MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
+               0x0040, 24, 3, 31),
+
+       MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+               0x0050, 0, 2, 7),
+       MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents,
+               0x0050, 8, 4, 15),
+       MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents,
+               0x0050, 16, 3, 23),
+       MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents,
+               0x0050, 24, 3, 31),
+       MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+               0x0060, 0, 1, 7),
+
+       MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents,
+               0x0060, 8, 3, 15),
+       MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents,
+               0x0060, 16, 2, 23),
+       MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents,
+               0x0060, 24, 3, 31),
+
+       MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents,
+               0x0070, 0, 3, 7),
+       MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents,
+               0x0070, 8, 3, 15),
+       MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents,
+               0x0070, 16, 1, 23),
+       MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+               0x0070, 24, 3, 31),
+
+       MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+               0x0080, 0, 4, 7),
+       MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents,
+               0x0080, 8, 2, 15),
+       MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents,
+               0x0080, 16, 3, 23),
+       MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents,
+               0x0080, 24, 2, 31),
+
+       MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents,
+               0x0090, 0, 3, 7),
+       MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents,
+               0x0090, 8, 2, 15),
+       MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents,
+               0x0090, 16, 3, 23),
+
+       MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents,
+               0x00A0, 0, 2, 7, CLK_IS_CRITICAL),
+       MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents,
+               0x00A0, 8, 3, 15),
+       MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents,
+               0x00A0, 24, 2, 31),
+
+       MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
+               0x00B0, 0, 3, 7),
+       MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents,
+               0x00B0, 8, 2, 15),
+       MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents,
+               0x00B0, 16, 3, 23),
+       MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents,
+               0x00B0, 24, 3, 31),
+
+       MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel",
+               hdmirx_bist_parents, 0x00C0, 0, 3, 7),
+       MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
+               0x00C0, 8, 2, 15),
+       MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents,
+               0x00C0, 16, 2, 23),
+       MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents,
+               0x00C0, 24, 3, 31),
+
+       MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents,
+               0x00D0, 0, 2, 7),
+       MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents,
+               0x00D0, 16, 2, 23),
+       MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents,
+               0x00D0, 24, 3, 31),
+
+       MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents,
+               0x00E0, 0, 1, 7),
+       MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents,
+               0x00E0, 8, 3, 15),
+       MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents,
+               0x00E0, 16, 4, 23),
+
+       MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents,
+               0x00E0, 24, 3, 31),
+       MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents,
+               0x00F0, 0, 3, 7),
+       MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents,
+               0x00F0, 8, 2, 15),
+       MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents,
+               0x00F0, 16, 1, 23),
+
+       MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents,
+               0x0100, 0, 3),
+
+       MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents,
+               0x012c, 0, 3),
+       MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents,
+               0x012c, 3, 3),
+       MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents,
+               0x012c, 6, 3),
+       MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents,
+               0x012c, 15, 1, 23),
+       MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents,
+               0x012c, 16, 1, 24),
+       MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents,
+               0x012c, 17, 1, 25),
+       MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents,
+               0x012c, 18, 1, 26),
+       MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents,
+               0x012c, 19, 1, 27),
+       MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents,
+               0x012c, 20, 1, 28),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+       DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1",
+               0x0120, 0, 8),
+       DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2",
+               0x0120, 8, 8),
+       DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel",
+               0x0120, 16, 8),
+       DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel",
+               0x0120, 24, 8),
+       DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel",
+               0x0124, 0, 8),
+       DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel",
+               0x0124, 8, 8),
+       DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel",
+               0x0124, 16, 8),
+       DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel",
+               0x0124, 24, 8),
+       DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel",
+               0x0128, 0, 8),
+       DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel",
+               0x0128, 8, 8),
+};
+
+static const struct mtk_gate_regs top_aud_cg_regs = {
+       .sta_ofs = 0x012C,
+};
+
+#define GATE_TOP_AUD(_id, _name, _parent, _shift) {    \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top_aud_cg_regs,               \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr,     \
+       }
+
+static const struct mtk_gate top_clks[] = {
+       GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
+               21),
+       GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div",
+               22),
+       GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div",
+               23),
+       GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div",
+               24),
+       GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div",
+               25),
+       GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div",
+               26),
+       GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div",
+               27),
+       GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div",
+               28),
+};
+
+static int mtk_topckgen_init(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       void __iomem *base;
+       struct device_node *node = pdev->dev.of_node;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+       mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+                                                               clk_data);
+
+       mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+                                                               clk_data);
+
+       mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
+                               base, &mt2701_clk_lock, clk_data);
+
+       mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+                               base, &mt2701_clk_lock, clk_data);
+
+       mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+                                               clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct mtk_gate_regs infra_cg_regs = {
+       .set_ofs = 0x0040,
+       .clr_ofs = 0x0044,
+       .sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {                \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &infra_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+static const struct mtk_gate infra_clks[] = {
+       GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
+       GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1),
+       GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2),
+       GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4),
+       GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5),
+       GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6),
+       GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7),
+       GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+       GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12),
+       GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13),
+       GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14),
+       GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15),
+       GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+       GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18),
+       GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19),
+       GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+       GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23),
+       GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+       FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static struct clk_onecell_data *infra_clk_data;
+
+static void mtk_infrasys_init_early(struct device_node *node)
+{
+       int r, i;
+
+       if (!infra_clk_data) {
+               infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+               for (i = 0; i < CLK_INFRA_NR; i++)
+                       infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+       }
+
+       mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+                                               infra_clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+}
+CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt2701-infracfg",
+                       mtk_infrasys_init_early);
+
+static int mtk_infrasys_init(struct platform_device *pdev)
+{
+       int r, i;
+       struct device_node *node = pdev->dev.of_node;
+
+       if (!infra_clk_data) {
+               infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+       } else {
+               for (i = 0; i < CLK_INFRA_NR; i++) {
+                       if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+                               infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
+               }
+       }
+
+       mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+                                               infra_clk_data);
+       mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+                                               infra_clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+       if (r)
+               return r;
+
+       mtk_register_reset_controller(node, 2, 0x30);
+
+       return 0;
+}
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+       .set_ofs = 0x0008,
+       .clr_ofs = 0x0010,
+       .sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+       .set_ofs = 0x000c,
+       .clr_ofs = 0x0014,
+       .sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {      \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &peri0_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {      \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &peri1_cg_regs,                 \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+static const struct mtk_gate peri_clks[] = {
+       GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
+       GATE_PERI0(CLK_PERI_ETH, "eth_ck", "clk26m", 30),
+       GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29),
+       GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28),
+       GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27),
+       GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26),
+       GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25),
+       GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24),
+       GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23),
+       GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22),
+       GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21),
+       GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20),
+       GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19),
+       GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18),
+       GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17),
+       GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16),
+       GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15),
+       GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14),
+       GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13),
+       GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+       GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+       GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+       GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+       GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+       GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+       GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+       GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+       GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+       GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+       GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+       GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+       GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
+
+       GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11),
+       GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10),
+       GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9),
+       GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8),
+       GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7),
+       GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6),
+       GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5),
+       GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4),
+       GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3),
+       GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2),
+       GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1),
+       GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] = {
+       "clk26m",
+       "uart_sel",
+};
+
+static const struct mtk_composite peri_muxs[] = {
+       MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents,
+               0x40c, 0, 1),
+       MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents,
+               0x40c, 1, 1),
+       MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents,
+               0x40c, 2, 1),
+       MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents,
+               0x40c, 3, 1),
+};
+
+static int mtk_pericfg_init(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       void __iomem *base;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+
+       mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+                                               clk_data);
+
+       mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base,
+                       &mt2701_clk_lock, clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               return r;
+
+       mtk_register_reset_controller(node, 2, 0x0);
+
+       return 0;
+}
+
+#define MT8590_PLL_FMAX                (2000 * MHZ)
+#define CON0_MT8590_RST_BAR    BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
+                       _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) {  \
+               .id = _id,                                              \
+               .name = _name,                                          \
+               .reg = _reg,                                            \
+               .pwr_reg = _pwr_reg,                                    \
+               .en_mask = _en_mask,                                    \
+               .flags = _flags,                                        \
+               .rst_bar_mask = CON0_MT8590_RST_BAR,                    \
+               .fmax = MT8590_PLL_FMAX,                                \
+               .pcwbits = _pcwbits,                                    \
+               .pd_reg = _pd_reg,                                      \
+               .pd_shift = _pd_shift,                                  \
+               .tuner_reg = _tuner_reg,                                \
+               .pcw_reg = _pcw_reg,                                    \
+               .pcw_shift = _pcw_shift,                                \
+       }
+
+static const struct mtk_pll_data apmixed_plls[] = {
+       PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001,
+                       PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0),
+       PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001,
+                 HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0),
+       PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001,
+                 HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14),
+       PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0,
+                               21, 0x230, 4, 0x0, 0x234, 0),
+       PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0,
+                               21, 0x240, 4, 0x0, 0x244, 0),
+       PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0,
+                               21, 0x250, 4, 0x0, 0x254, 0),
+       PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0,
+                               31, 0x270, 4, 0x0, 0x274, 0),
+       PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0,
+                               31, 0x280, 4, 0x0, 0x284, 0),
+       PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0,
+                               31, 0x290, 4, 0x0, 0x294, 0),
+       PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0,
+                               31, 0x2a0, 4, 0x0, 0x2a4, 0),
+       PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0,
+                               31, 0x2b0, 4, 0x0, 0x2b4, 0),
+       PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0,
+                               31, 0x2c0, 4, 0x0, 0x2c4, 0),
+       PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0,
+                               21, 0x2d0, 4, 0x0, 0x2d4, 0),
+};
+
+static int mtk_apmixedsys_init(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+       if (!clk_data)
+               return -ENOMEM;
+
+       mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+                                                               clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt2701[] = {
+       {
+               .compatible = "mediatek,mt2701-topckgen",
+               .data = mtk_topckgen_init,
+       }, {
+               .compatible = "mediatek,mt2701-infracfg",
+               .data = mtk_infrasys_init,
+       }, {
+               .compatible = "mediatek,mt2701-pericfg",
+               .data = mtk_pericfg_init,
+       }, {
+               .compatible = "mediatek,mt2701-apmixedsys",
+               .data = mtk_apmixedsys_init,
+       }, {
+               /* sentinel */
+       }
+};
+
+static int clk_mt2701_probe(struct platform_device *pdev)
+{
+       int (*clk_init)(struct platform_device *);
+       int r;
+
+       clk_init = of_device_get_match_data(&pdev->dev);
+       if (!clk_init)
+               return -EINVAL;
+
+       r = clk_init(pdev);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt2701_drv = {
+       .probe = clk_mt2701_probe,
+       .driver = {
+               .name = "clk-mt2701",
+               .of_match_table = of_match_clk_mt2701,
+       },
+};
+
+static int __init clk_mt2701_init(void)
+{
+       return platform_driver_register(&clk_mt2701_drv);
+}
+
+arch_initcall(clk_mt2701_init);
index bb30f7063569d1c67a3dbc27c87744742a3b898f..0541df78141c7d8b0efe78d95d017a0a51263115 100644 (file)
@@ -58,6 +58,9 @@ void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
        for (i = 0; i < num; i++) {
                const struct mtk_fixed_clk *rc = &clks[i];
 
+               if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id]))
+                       continue;
+
                clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
                                              rc->rate);
 
@@ -81,6 +84,9 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
        for (i = 0; i < num; i++) {
                const struct mtk_fixed_factor *ff = &clks[i];
 
+               if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id]))
+                       continue;
+
                clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
                                CLK_SET_RATE_PARENT, ff->mult, ff->div);
 
@@ -116,6 +122,9 @@ int mtk_clk_register_gates(struct device_node *node,
        for (i = 0; i < num; i++) {
                const struct mtk_gate *gate = &clks[i];
 
+               if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
+                       continue;
+
                clk = mtk_clk_register_gate(gate->name, gate->parent_name,
                                regmap,
                                gate->regs->set_ofs,
@@ -232,6 +241,9 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
        for (i = 0; i < num; i++) {
                const struct mtk_composite *mc = &mcs[i];
 
+               if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id]))
+                       continue;
+
                clk = mtk_clk_register_composite(mc, base, lock);
 
                if (IS_ERR(clk)) {
@@ -244,3 +256,31 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
                        clk_data->clks[mc->id] = clk;
        }
 }
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+                       int num, void __iomem *base, spinlock_t *lock,
+                               struct clk_onecell_data *clk_data)
+{
+       struct clk *clk;
+       int i;
+
+       for (i = 0; i <  num; i++) {
+               const struct mtk_clk_divider *mcd = &mcds[i];
+
+               if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
+                       continue;
+
+               clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
+                       mcd->flags, base +  mcd->div_reg, mcd->div_shift,
+                       mcd->div_width, mcd->clk_divider_flags, lock);
+
+               if (IS_ERR(clk)) {
+                       pr_err("Failed to register clk %s: %ld\n",
+                               mcd->name, PTR_ERR(clk));
+                       continue;
+               }
+
+               if (clk_data)
+                       clk_data->clks[mcd->id] = clk;
+       }
+}
index 9f24fcfa304f9c975b63af33e6597722a403afbd..f5d6b70ce189372602f2c6f8aaa1d2694ba8e65e 100644 (file)
@@ -87,7 +87,8 @@ struct mtk_composite {
  * In case the rate change propagation to parent clocks is undesirable,
  * this macro allows to specify the clock flags manually.
  */
-#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) {    \
+#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,     \
+                       _gate, _flags) {                                \
                .id = _id,                                              \
                .name = _name,                                          \
                .mux_reg = _reg,                                        \
@@ -106,7 +107,8 @@ struct mtk_composite {
  * parent clock by default.
  */
 #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)    \
-       MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT)
+       MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,      \
+               _gate, CLK_SET_RATE_PARENT)
 
 #define MUX(_id, _name, _parents, _reg, _shift, _width) {              \
                .id = _id,                                              \
@@ -121,7 +123,8 @@ struct mtk_composite {
                .flags = CLK_SET_RATE_PARENT,                           \
        }
 
-#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {      \
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,        \
+                                       _div_width, _div_shift) {       \
                .id = _id,                                              \
                .parent = _parent,                                      \
                .name = _name,                                          \
@@ -156,12 +159,40 @@ struct mtk_gate {
        const struct clk_ops *ops;
 };
 
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
-               int num, struct clk_onecell_data *clk_data);
+int mtk_clk_register_gates(struct device_node *node,
+                       const struct mtk_gate *clks, int num,
+                       struct clk_onecell_data *clk_data);
+
+struct mtk_clk_divider {
+       int id;
+       const char *name;
+       const char *parent_name;
+       unsigned long flags;
+
+       u32 div_reg;
+       unsigned char div_shift;
+       unsigned char div_width;
+       unsigned char clk_divider_flags;
+       const struct clk_div_table *clk_div_table;
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {   \
+               .id = _id,                                      \
+               .name = _name,                                  \
+               .parent_name = _parent,                         \
+               .div_reg = _reg,                                \
+               .div_shift = _shift,                            \
+               .div_width = _width,                            \
+}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+                       int num, void __iomem *base, spinlock_t *lock,
+                               struct clk_onecell_data *clk_data);
 
 struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
 
 #define HAVE_RST_BAR   BIT(0)
+#define PLL_AO         BIT(1)
 
 struct mtk_pll_div_table {
        u32 div;
index 0c2deac17ce958fd415bf80a67944b12b5ca39c1..a409142e93462dd0eb7fc599f43479a26b2c695c 100644 (file)
@@ -301,6 +301,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
        pll->data = data;
 
        init.name = data->name;
+       init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
        init.ops = &mtk_pll_ops;
        init.parent_names = &parent_name;
        init.num_parents = 1;
index 9adaf48aea2317625a520bb42635fa8362946893..0fc75c39595708f0d5c6296fcbeea4e3d61f5731 100644 (file)
@@ -309,19 +309,19 @@ static void __init mmp2_clk_init(struct device_node *np)
        pxa_unit->mpmu_base = of_iomap(np, 0);
        if (!pxa_unit->mpmu_base) {
                pr_err("failed to map mpmu registers\n");
-               return;
+               goto free_memory;
        }
 
        pxa_unit->apmu_base = of_iomap(np, 1);
        if (!pxa_unit->apmu_base) {
                pr_err("failed to map apmu registers\n");
-               return;
+               goto unmap_mpmu_region;
        }
 
        pxa_unit->apbc_base = of_iomap(np, 2);
        if (!pxa_unit->apbc_base) {
                pr_err("failed to map apbc registers\n");
-               return;
+               goto unmap_apmu_region;
        }
 
        mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
@@ -333,6 +333,15 @@ static void __init mmp2_clk_init(struct device_node *np)
        mmp2_axi_periph_clk_init(pxa_unit);
 
        mmp2_clk_reset_init(np, pxa_unit);
+
+       return;
+
+unmap_apmu_region:
+       iounmap(pxa_unit->apmu_base);
+unmap_mpmu_region:
+       iounmap(pxa_unit->mpmu_base);
+free_memory:
+       kfree(pxa_unit);
 }
 
 CLK_OF_DECLARE(mmp2_clk, "marvell,mmp2-clock", mmp2_clk_init);
index e478ff44e170b4591430064fb9d4eba9592e8dbe..cede7b4ca3b918764fb5cf2f5e7e8a78978f1dd3 100644 (file)
@@ -216,6 +216,7 @@ static void __init pxa1928_mpmu_clk_init(struct device_node *np)
        pxa_unit->mpmu_base = of_iomap(np, 0);
        if (!pxa_unit->mpmu_base) {
                pr_err("failed to map mpmu registers\n");
+               kfree(pxa_unit);
                return;
        }
 
@@ -234,6 +235,7 @@ static void __init pxa1928_apmu_clk_init(struct device_node *np)
        pxa_unit->apmu_base = of_iomap(np, 0);
        if (!pxa_unit->apmu_base) {
                pr_err("failed to map apmu registers\n");
+               kfree(pxa_unit);
                return;
        }
 
@@ -254,6 +256,7 @@ static void __init pxa1928_apbc_clk_init(struct device_node *np)
        pxa_unit->apbc_base = of_iomap(np, 0);
        if (!pxa_unit->apbc_base) {
                pr_err("failed to map apbc registers\n");
+               kfree(pxa_unit);
                return;
        }
 
index 64d1ef49caebedd9d35226afcec9e0a624f0965f..1dcabe95cb67c048e8014f78cb1004bf2cd92de5 100644 (file)
@@ -278,25 +278,25 @@ static void __init pxa910_clk_init(struct device_node *np)
        pxa_unit->mpmu_base = of_iomap(np, 0);
        if (!pxa_unit->mpmu_base) {
                pr_err("failed to map mpmu registers\n");
-               return;
+               goto free_memory;
        }
 
        pxa_unit->apmu_base = of_iomap(np, 1);
        if (!pxa_unit->apmu_base) {
                pr_err("failed to map apmu registers\n");
-               return;
+               goto unmap_mpmu_region;
        }
 
        pxa_unit->apbc_base = of_iomap(np, 2);
        if (!pxa_unit->apbc_base) {
                pr_err("failed to map apbc registers\n");
-               return;
+               goto unmap_apmu_region;
        }
 
        pxa_unit->apbcp_base = of_iomap(np, 3);
        if (!pxa_unit->apbcp_base) {
                pr_err("failed to map apbcp registers\n");
-               return;
+               goto unmap_apbc_region;
        }
 
        mmp_clk_init(np, &pxa_unit->unit, PXA910_NR_CLKS);
@@ -308,6 +308,17 @@ static void __init pxa910_clk_init(struct device_node *np)
        pxa910_axi_periph_clk_init(pxa_unit);
 
        pxa910_clk_reset_init(np, pxa_unit);
+
+       return;
+
+unmap_apbc_region:
+       iounmap(pxa_unit->apbc_base);
+unmap_apmu_region:
+       iounmap(pxa_unit->apmu_base);
+unmap_mpmu_region:
+       iounmap(pxa_unit->mpmu_base);
+free_memory:
+       kfree(pxa_unit);
 }
 
 CLK_OF_DECLARE(pxa910_clk, "marvell,pxa910-clock", pxa910_clk_init);
index 02023baf86c930ec2f68cdc3e4cbe7e9fc170a47..8181b919f062c3b40ad51b6657840357b574baac 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -135,34 +135,17 @@ fail0:
        return ret;
 }
 
-static int ap806_syscon_clk_remove(struct platform_device *pdev)
-{
-       of_clk_del_provider(pdev->dev.of_node);
-       clk_unregister_fixed_factor(ap806_clks[3]);
-       clk_unregister_fixed_rate(ap806_clks[2]);
-       clk_unregister_fixed_rate(ap806_clks[1]);
-       clk_unregister_fixed_rate(ap806_clks[0]);
-
-       return 0;
-}
-
 static const struct of_device_id ap806_syscon_of_match[] = {
        { .compatible = "marvell,ap806-system-controller", },
        { }
 };
-MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
 
 static struct platform_driver ap806_syscon_driver = {
        .probe = ap806_syscon_clk_probe,
-       .remove = ap806_syscon_clk_remove,
        .driver         = {
                .name   = "marvell-ap806-system-controller",
                .of_match_table = ap806_syscon_of_match,
+               .suppress_bind_attrs = true,
        },
 };
-
-module_platform_driver(ap806_syscon_driver);
-
-MODULE_DESCRIPTION("Marvell AP806 System Controller driver");
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(ap806_syscon_driver);
index f2303da7fda7ccff76d2acaf459e3df8ff705b27..32e5b43c086f3c24c35550540d3ea3cca12675d9 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -87,7 +87,7 @@ struct cp110_gate_clk {
        u8 bit_idx;
 };
 
-#define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw)
+#define to_cp110_gate_clk(hw) container_of(hw, struct cp110_gate_clk, hw)
 
 static int cp110_gate_enable(struct clk_hw *hw)
 {
@@ -123,13 +123,14 @@ static const struct clk_ops cp110_gate_ops = {
        .is_enabled = cp110_gate_is_enabled,
 };
 
-static struct clk *cp110_register_gate(const char *name,
-                                      const char *parent_name,
-                                      struct regmap *regmap, u8 bit_idx)
+static struct clk_hw *cp110_register_gate(const char *name,
+                                         const char *parent_name,
+                                         struct regmap *regmap, u8 bit_idx)
 {
        struct cp110_gate_clk *gate;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
 
        gate = kzalloc(sizeof(*gate), GFP_KERNEL);
        if (!gate)
@@ -146,39 +147,37 @@ static struct clk *cp110_register_gate(const char *name,
        gate->bit_idx = bit_idx;
        gate->hw.init = &init;
 
-       clk = clk_register(NULL, &gate->hw);
-       if (IS_ERR(clk))
+       hw = &gate->hw;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(gate);
+               hw = ERR_PTR(ret);
+       }
 
-       return clk;
+       return hw;
 }
 
-static void cp110_unregister_gate(struct clk *clk)
+static void cp110_unregister_gate(struct clk_hw *hw)
 {
-       struct clk_hw *hw;
-
-       hw = __clk_get_hw(clk);
-       if (!hw)
-               return;
-
-       clk_unregister(clk);
+       clk_hw_unregister(hw);
        kfree(to_cp110_gate_clk(hw));
 }
 
-static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data)
+static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
+                                      void *data)
 {
-       struct clk_onecell_data *clk_data = data;
+       struct clk_hw_onecell_data *clk_data = data;
        unsigned int type = clkspec->args[0];
        unsigned int idx = clkspec->args[1];
 
        if (type == CP110_CLK_TYPE_CORE) {
                if (idx > CP110_MAX_CORE_CLOCKS)
                        return ERR_PTR(-EINVAL);
-               return clk_data->clks[idx];
+               return clk_data->hws[idx];
        } else if (type == CP110_CLK_TYPE_GATABLE) {
                if (idx > CP110_MAX_GATABLE_CLOCKS)
                        return ERR_PTR(-EINVAL);
-               return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx];
+               return clk_data->hws[CP110_MAX_CORE_CLOCKS + idx];
        }
 
        return ERR_PTR(-EINVAL);
@@ -189,8 +188,8 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
        struct regmap *regmap;
        struct device_node *np = pdev->dev.of_node;
        const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name;
-       struct clk_onecell_data *cp110_clk_data;
-       struct clk *clk, **cp110_clks;
+       struct clk_hw_onecell_data *cp110_clk_data;
+       struct clk_hw *hw, **cp110_clks;
        u32 nand_clk_ctrl;
        int i, ret;
 
@@ -203,80 +202,75 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       cp110_clks = devm_kcalloc(&pdev->dev, sizeof(struct clk *),
-                                 CP110_CLK_NUM, GFP_KERNEL);
-       if (!cp110_clks)
-               return -ENOMEM;
-
-       cp110_clk_data = devm_kzalloc(&pdev->dev,
-                                     sizeof(*cp110_clk_data),
+       cp110_clk_data = devm_kzalloc(&pdev->dev, sizeof(*cp110_clk_data) +
+                                     sizeof(struct clk_hw *) * CP110_CLK_NUM,
                                      GFP_KERNEL);
        if (!cp110_clk_data)
                return -ENOMEM;
 
-       cp110_clk_data->clks = cp110_clks;
-       cp110_clk_data->clk_num = CP110_CLK_NUM;
+       cp110_clks = cp110_clk_data->hws;
+       cp110_clk_data->num = CP110_CLK_NUM;
 
-       /* Register the APLL which is the root of the clk tree */
+       /* Register the APLL which is the root of the hw tree */
        of_property_read_string_index(np, "core-clock-output-names",
                                      CP110_CORE_APLL, &apll_name);
-       clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0,
-                                     1000 * 1000 * 1000);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
+       hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
+                                       1000 * 1000 * 1000);
+       if (IS_ERR(hw)) {
+               ret = PTR_ERR(hw);
                goto fail0;
        }
 
-       cp110_clks[CP110_CORE_APLL] = clk;
+       cp110_clks[CP110_CORE_APLL] = hw;
 
        /* PPv2 is APLL/3 */
        of_property_read_string_index(np, "core-clock-output-names",
                                      CP110_CORE_PPV2, &ppv2_name);
-       clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
+       hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
+       if (IS_ERR(hw)) {
+               ret = PTR_ERR(hw);
                goto fail1;
        }
 
-       cp110_clks[CP110_CORE_PPV2] = clk;
+       cp110_clks[CP110_CORE_PPV2] = hw;
 
        /* EIP clock is APLL/2 */
        of_property_read_string_index(np, "core-clock-output-names",
                                      CP110_CORE_EIP, &eip_name);
-       clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
+       hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
+       if (IS_ERR(hw)) {
+               ret = PTR_ERR(hw);
                goto fail2;
        }
 
-       cp110_clks[CP110_CORE_EIP] = clk;
+       cp110_clks[CP110_CORE_EIP] = hw;
 
        /* Core clock is EIP/2 */
        of_property_read_string_index(np, "core-clock-output-names",
                                      CP110_CORE_CORE, &core_name);
-       clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
+       hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
+       if (IS_ERR(hw)) {
+               ret = PTR_ERR(hw);
                goto fail3;
        }
 
-       cp110_clks[CP110_CORE_CORE] = clk;
+       cp110_clks[CP110_CORE_CORE] = hw;
 
        /* NAND can be either APLL/2.5 or core clock */
        of_property_read_string_index(np, "core-clock-output-names",
                                      CP110_CORE_NAND, &nand_name);
        if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
-               clk = clk_register_fixed_factor(NULL, nand_name,
-                                               apll_name, 0, 2, 5);
+               hw = clk_hw_register_fixed_factor(NULL, nand_name,
+                                                  apll_name, 0, 2, 5);
        else
-               clk = clk_register_fixed_factor(NULL, nand_name,
-                                               core_name, 0, 1, 1);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
+               hw = clk_hw_register_fixed_factor(NULL, nand_name,
+                                                  core_name, 0, 1, 1);
+       if (IS_ERR(hw)) {
+               ret = PTR_ERR(hw);
                goto fail4;
        }
 
-       cp110_clks[CP110_CORE_NAND] = clk;
+       cp110_clks[CP110_CORE_NAND] = hw;
 
        for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
                const char *parent, *name;
@@ -335,16 +329,16 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
                        break;
                }
 
-               clk = cp110_register_gate(name, parent, regmap, i);
-               if (IS_ERR(clk)) {
-                       ret = PTR_ERR(clk);
+               hw = cp110_register_gate(name, parent, regmap, i);
+               if (IS_ERR(hw)) {
+                       ret = PTR_ERR(hw);
                        goto fail_gate;
                }
 
-               cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk;
+               cp110_clks[CP110_MAX_CORE_CLOCKS + i] = hw;
        }
 
-       ret = of_clk_add_provider(np, cp110_of_clk_get, cp110_clk_data);
+       ret = of_clk_add_hw_provider(np, cp110_of_clk_get, cp110_clk_data);
        if (ret)
                goto fail_clk_add;
 
@@ -355,65 +349,36 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 fail_clk_add:
 fail_gate:
        for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
-               clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
+               hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
 
-               if (clk)
-                       cp110_unregister_gate(clk);
+               if (hw)
+                       cp110_unregister_gate(hw);
        }
 
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
+       clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
 fail4:
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
+       clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
 fail3:
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+       clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
 fail2:
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
+       clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
 fail1:
-       clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
+       clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
 fail0:
        return ret;
 }
 
-static int cp110_syscon_clk_remove(struct platform_device *pdev)
-{
-       struct clk **cp110_clks = platform_get_drvdata(pdev);
-       int i;
-
-       of_clk_del_provider(pdev->dev.of_node);
-
-       for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
-               struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
-
-               if (clk)
-                       cp110_unregister_gate(clk);
-       }
-
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
-       clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
-       clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
-
-       return 0;
-}
-
 static const struct of_device_id cp110_syscon_of_match[] = {
        { .compatible = "marvell,cp110-system-controller0", },
        { }
 };
-MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
 
 static struct platform_driver cp110_syscon_driver = {
        .probe = cp110_syscon_clk_probe,
-       .remove = cp110_syscon_clk_remove,
        .driver         = {
                .name   = "marvell-cp110-system-controller0",
                .of_match_table = cp110_syscon_of_match,
+               .suppress_bind_attrs = true,
        },
 };
-
-module_platform_driver(cp110_syscon_driver);
-
-MODULE_DESCRIPTION("Marvell CP110 System Controller 0 driver");
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(cp110_syscon_driver);
index f7136b94fd0ea51f8b877e6403f076a9463263da..27781b49eb8218f8c960d6999176467a545b4ae9 100644 (file)
@@ -277,12 +277,15 @@ static void __init lpc18xx_ccu_init(struct device_node *np)
        }
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
-       if (!clk_data)
+       if (!clk_data) {
+               iounmap(reg_base);
                return;
+       }
 
        clk_data->num = of_property_count_strings(np, "clock-names");
        clk_data->name = kcalloc(clk_data->num, sizeof(char *), GFP_KERNEL);
        if (!clk_data->name) {
+               iounmap(reg_base);
                kfree(clk_data);
                return;
        }
index 34c97353cdebe81f8edeef4baa941add66f61baf..5b98ff9076f34fcdbc58283bd7410e2e56b546a9 100644 (file)
@@ -1282,13 +1282,13 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
 
        LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0),
        LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
-                          CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+                          CLK_DIVIDER_ONE_BASED),
        LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0),
        LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE),
 
        LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0),
        LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
-                          CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+                          CLK_DIVIDER_ONE_BASED),
        LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0),
        LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE),
 
@@ -1335,8 +1335,7 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
        LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0),
        LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE),
 
-       LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL,
-                          CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+       LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED),
        LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9),
                           0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops),
        LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE),
@@ -1478,6 +1477,20 @@ static struct clk * __init lpc32xx_clk_register(u32 id)
        return clk;
 }
 
+static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate)
+{
+       u32 val;
+
+       regmap_read(clk_regmap, reg, &val);
+
+       if (!(val & div_mask)) {
+               val &= ~gate;
+               val |= BIT(__ffs(div_mask));
+       }
+
+       regmap_update_bits(clk_regmap, reg, gate | div_mask, val);
+}
+
 static void __init lpc32xx_clk_init(struct device_node *np)
 {
        unsigned int i;
@@ -1517,6 +1530,17 @@ static void __init lpc32xx_clk_init(struct device_node *np)
                return;
        }
 
+       /*
+        * Divider part of PWM and MS clocks requires a quirk to avoid
+        * a misinterpretation of formally valid zero value in register
+        * bitfield, which indicates another clock gate. Instead of
+        * adding complexity to a gate clock ensure that zero value in
+        * divider clock is never met in runtime.
+        */
+       lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0));
+       lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2));
+       lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9));
+
        for (i = 1; i < LPC32XX_CLK_MAX; i++) {
                clk[i] = lpc32xx_clk_register(i);
                if (IS_ERR(clk[i])) {
index 29cee9e8d4d91bf34312207b7016e2f05c7d2746..74f64c3c429098b832840b5082ab3eb15e5ef73f 100644 (file)
 #include <dt-bindings/clock/pxa-clock.h>
 #include "clk-pxa.h"
 
-DEFINE_SPINLOCK(lock);
+#define KHz 1000
+#define MHz (1000 * 1000)
+
+#define MDREFR_K0DB4   (1 << 29)       /* SDCLK0 Divide by 4 Control/Status */
+#define MDREFR_K2FREE  (1 << 25)       /* SDRAM Free-Running Control */
+#define MDREFR_K1FREE  (1 << 24)       /* SDRAM Free-Running Control */
+#define MDREFR_K0FREE  (1 << 23)       /* SDRAM Free-Running Control */
+#define MDREFR_SLFRSH  (1 << 22)       /* SDRAM Self-Refresh Control/Status */
+#define MDREFR_APD     (1 << 20)       /* SDRAM/SSRAM Auto-Power-Down Enable */
+#define MDREFR_K2DB2   (1 << 19)       /* SDCLK2 Divide by 2 Control/Status */
+#define MDREFR_K2RUN   (1 << 18)       /* SDCLK2 Run Control/Status */
+#define MDREFR_K1DB2   (1 << 17)       /* SDCLK1 Divide by 2 Control/Status */
+#define MDREFR_K1RUN   (1 << 16)       /* SDCLK1 Run Control/Status */
+#define MDREFR_E1PIN   (1 << 15)       /* SDCKE1 Level Control/Status */
+#define MDREFR_K0DB2   (1 << 14)       /* SDCLK0 Divide by 2 Control/Status */
+#define MDREFR_K0RUN   (1 << 13)       /* SDCLK0 Run Control/Status */
+#define MDREFR_E0PIN   (1 << 12)       /* SDCKE0 Level Control/Status */
+#define MDREFR_DB2_MASK        (MDREFR_K2DB2 | MDREFR_K1DB2)
+#define MDREFR_DRI_MASK        0xFFF
+
+static DEFINE_SPINLOCK(pxa_clk_lock);
 
 static struct clk *pxa_clocks[CLK_MAX];
 static struct clk_onecell_data onecell_data = {
@@ -89,7 +109,7 @@ int __init clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks)
                pxa_clk->lp = clks[i].lp;
                pxa_clk->hp = clks[i].hp;
                pxa_clk->gate = clks[i].gate;
-               pxa_clk->gate.lock = &lock;
+               pxa_clk->gate.lock = &pxa_clk_lock;
                clk = clk_register_composite(NULL, clks[i].name,
                                             clks[i].parent_names, 2,
                                             &pxa_clk->hw, &cken_mux_ops,
@@ -106,3 +126,124 @@ void __init clk_pxa_dt_common_init(struct device_node *np)
 {
        of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
 }
+
+void pxa2xx_core_turbo_switch(bool on)
+{
+       unsigned long flags;
+       unsigned int unused, clkcfg;
+
+       local_irq_save(flags);
+
+       asm("mrc p14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
+       clkcfg &= ~CLKCFG_TURBO & ~CLKCFG_HALFTURBO;
+       if (on)
+               clkcfg |= CLKCFG_TURBO;
+       clkcfg |= CLKCFG_FCS;
+
+       asm volatile(
+       "       b       2f\n"
+       "       .align  5\n"
+       "1:     mcr     p14, 0, %1, c6, c0, 0\n"
+       "       b       3f\n"
+       "2:     b       1b\n"
+       "3:     nop\n"
+               : "=&r" (unused)
+               : "r" (clkcfg)
+               : );
+
+       local_irq_restore(flags);
+}
+
+void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
+                       u32 (*mdrefr_dri)(unsigned int), void __iomem *mdrefr,
+                       void __iomem *cccr)
+{
+       unsigned int clkcfg = freq->clkcfg;
+       unsigned int unused, preset_mdrefr, postset_mdrefr;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       /* Calculate the next MDREFR.  If we're slowing down the SDRAM clock
+        * we need to preset the smaller DRI before the change.  If we're
+        * speeding up we need to set the larger DRI value after the change.
+        */
+       preset_mdrefr = postset_mdrefr = readl(mdrefr);
+       if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(freq->membus_khz)) {
+               preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
+               preset_mdrefr |= mdrefr_dri(freq->membus_khz);
+       }
+       postset_mdrefr =
+               (postset_mdrefr & ~MDREFR_DRI_MASK) |
+               mdrefr_dri(freq->membus_khz);
+
+       /* If we're dividing the memory clock by two for the SDRAM clock, this
+        * must be set prior to the change.  Clearing the divide must be done
+        * after the change.
+        */
+       if (freq->div2) {
+               preset_mdrefr  |= MDREFR_DB2_MASK;
+               postset_mdrefr |= MDREFR_DB2_MASK;
+       } else {
+               postset_mdrefr &= ~MDREFR_DB2_MASK;
+       }
+
+       /* Set new the CCCR and prepare CLKCFG */
+       writel(freq->cccr, cccr);
+
+       asm volatile(
+       "       ldr     r4, [%1]\n"
+       "       b       2f\n"
+       "       .align  5\n"
+       "1:     str     %3, [%1]                /* preset the MDREFR */\n"
+       "       mcr     p14, 0, %2, c6, c0, 0   /* set CLKCFG[FCS] */\n"
+       "       str     %4, [%1]                /* postset the MDREFR */\n"
+       "       b       3f\n"
+       "2:     b       1b\n"
+       "3:     nop\n"
+            : "=&r" (unused)
+            : "r" (mdrefr), "r" (clkcfg), "r" (preset_mdrefr),
+              "r" (postset_mdrefr)
+            : "r4", "r5");
+
+       local_irq_restore(flags);
+}
+
+int pxa2xx_determine_rate(struct clk_rate_request *req,
+                         struct pxa2xx_freq *freqs, int nb_freqs)
+{
+       int i, closest_below = -1, closest_above = -1;
+       unsigned long rate;
+
+       for (i = 0; i < nb_freqs; i++) {
+               rate = freqs[i].cpll;
+               if (rate == req->rate)
+                       break;
+               if (rate < req->min_rate)
+                       continue;
+               if (rate > req->max_rate)
+                       continue;
+               if (rate <= req->rate)
+                       closest_below = i;
+               if ((rate >= req->rate) && (closest_above == -1))
+                       closest_above = i;
+       }
+
+       req->best_parent_hw = NULL;
+
+       if (i < nb_freqs) {
+               rate = req->rate;
+       } else if (closest_below >= 0) {
+               rate = freqs[closest_below].cpll;
+       } else if (closest_above >= 0) {
+               rate = freqs[closest_above].cpll;
+       } else {
+               pr_debug("%s(rate=%lu) no match\n", __func__, req->rate);
+               return -EINVAL;
+       }
+
+       pr_debug("%s(rate=%lu) rate=%lu\n", __func__, req->rate, rate);
+       req->rate = rate;
+
+       return 0;
+}
index d1de805df86733bb2a4b69505f070bae72f23f3f..2b90c5917b32d5b2a682a6a4b28d0149d6341cc2 100644 (file)
 #ifndef _CLK_PXA_
 #define _CLK_PXA_
 
+#define CLKCFG_TURBO           0x1
+#define CLKCFG_FCS             0x2
+#define CLKCFG_HALFTURBO       0x4
+#define CLKCFG_FASTBUS         0x8
+
 #define PARENTS(name) \
        static const char *const name ## _parents[] __initconst
 #define MUX_RO_RATE_RO_OPS(name, clk_name)                     \
                        NULL, NULL, CLK_GET_RATE_NOCACHE);      \
        }
 
-#define RATE_RO_OPS(name, clk_name)                    \
+#define RATE_RO_OPS(name, clk_name)                            \
+       static struct clk_hw name ## _rate_hw;                  \
+       static const struct clk_ops name ## _rate_ops = {               \
+               .recalc_rate = name ## _get_rate,               \
+       };                                                      \
+       static struct clk * __init clk_register_ ## name(void)  \
+       {                                                       \
+               return clk_register_composite(NULL, clk_name,   \
+                       name ## _parents,                       \
+                       ARRAY_SIZE(name ## _parents),           \
+                       NULL, NULL,                             \
+                       &name ## _rate_hw, &name ## _rate_ops,  \
+                       NULL, NULL, CLK_GET_RATE_NOCACHE);      \
+       }
+
+#define RATE_OPS(name, clk_name)                               \
        static struct clk_hw name ## _rate_hw;                  \
        static struct clk_ops name ## _rate_ops = {             \
                .recalc_rate = name ## _get_rate,               \
+               .set_rate = name ## _set_rate,                  \
+               .determine_rate = name ## _determine_rate,      \
        };                                                      \
        static struct clk * __init clk_register_ ## name(void)  \
        {                                                       \
                        NULL, NULL, CLK_GET_RATE_NOCACHE);      \
        }
 
+#define MUX_OPS(name, clk_name, flags)                         \
+       static struct clk_hw name ## _mux_hw;                   \
+       static const struct clk_ops name ## _mux_ops = {        \
+               .get_parent = name ## _get_parent,              \
+               .set_parent = name ## _set_parent,              \
+               .determine_rate = name ## _determine_rate,      \
+       };                                                      \
+       static struct clk * __init clk_register_ ## name(void)  \
+       {                                                       \
+               return clk_register_composite(NULL, clk_name,   \
+                       name ## _parents,                       \
+                       ARRAY_SIZE(name ## _parents),           \
+                       &name ## _mux_hw, &name ## _mux_ops,    \
+                       NULL, NULL,                             \
+                       NULL, NULL,                             \
+                       CLK_GET_RATE_NOCACHE | flags); \
+       }
+
 /*
  * CKEN clock type
  * This clock takes it source from 2 possible parents :
@@ -95,7 +135,15 @@ struct desc_clk_cken {
        PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1,             \
                 NULL, cken_reg, cken_bit, flag)
 
-static int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
+struct pxa2xx_freq {
+       unsigned long cpll;
+       unsigned int membus_khz;
+       unsigned int cccr;
+       unsigned int div2;
+       unsigned int clkcfg;
+};
+
+static inline int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
 {
        return 0;
 }
@@ -105,4 +153,11 @@ extern void clkdev_pxa_register(int ckid, const char *con_id,
 extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks);
 void clk_pxa_dt_common_init(struct device_node *np);
 
+void pxa2xx_core_turbo_switch(bool on);
+void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
+                       u32 (*mdrefr_dri)(unsigned int), void __iomem *mdrefr,
+                       void __iomem *cccr);
+int pxa2xx_determine_rate(struct clk_rate_request *req,
+                         struct pxa2xx_freq *freqs,  int nb_freqs);
+
 #endif
index a98b98e2a9e4404047d5f965924a660464a13ec6..c53993b6bf87f8ddc113df1080bdd38cc20750ef 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <mach/pxa2xx-regs.h>
+#include <mach/smemc.h>
 
 #include <dt-bindings/clock/pxa-clock.h>
 #include "clk-pxa.h"
@@ -30,6 +31,17 @@ enum {
        PXA_CORE_TURBO,
 };
 
+#define PXA25x_CLKCFG(T)                       \
+       (CLKCFG_FCS |                           \
+        ((T) ? CLKCFG_TURBO : 0))
+#define PXA25x_CCCR(N2, M, L) (N2 << 7 | M << 5 | L)
+
+#define MDCNFG_DRAC2(mdcnfg)   (((mdcnfg) >> 21) & 0x3)
+#define MDCNFG_DRAC0(mdcnfg)   (((mdcnfg) >> 5) & 0x3)
+
+/* Define the refresh period in mSec for the SDRAM and the number of rows */
+#define SDRAM_TREF     64      /* standard 64ms SDRAM */
+
 /*
  * Various clock factors driven by the CCCR register.
  */
@@ -48,6 +60,34 @@ static const char * const get_freq_khz[] = {
        "core", "run", "cpll", "memory"
 };
 
+static int get_sdram_rows(void)
+{
+       static int sdram_rows;
+       unsigned int drac2 = 0, drac0 = 0;
+       u32 mdcnfg;
+
+       if (sdram_rows)
+               return sdram_rows;
+
+       mdcnfg = readl_relaxed(MDCNFG);
+
+       if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
+               drac2 = MDCNFG_DRAC2(mdcnfg);
+
+       if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
+               drac0 = MDCNFG_DRAC0(mdcnfg);
+
+       sdram_rows = 1 << (11 + max(drac0, drac2));
+       return sdram_rows;
+}
+
+static u32 mdrefr_dri(unsigned int freq_khz)
+{
+       u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
+
+       return interval / 32;
+}
+
 /*
  * Get the clock frequency as reflected by CCCR and the turbo flag.
  * We assume these values have been applied via a fcs.
@@ -139,6 +179,21 @@ static struct desc_clk_cken pxa25x_clocks[] __initdata = {
                             clk_pxa25x_memory_parents, 0),
 };
 
+/*
+ * In this table, PXA25x_CCCR(N2, M, L) has the following meaning, where :
+ *   - freq_cpll = n * m * L * 3.6864 MHz
+ *   - n = N2 / 2
+ *   - m = 2^(M - 1), where 1 <= M <= 3
+ *   - l = L_clk_mult[L], ie. { 0, 27, 32, 36, 40, 45, 0, }[L]
+ */
+static struct pxa2xx_freq pxa25x_freqs[] = {
+       /* CPU  MEMBUS  CCCR                  DIV2 CCLKCFG      */
+       { 99532800, 99500, PXA25x_CCCR(2,  1, 1),  1, PXA25x_CLKCFG(1)},
+       {199065600, 99500, PXA25x_CCCR(4,  1, 1),  0, PXA25x_CLKCFG(1)},
+       {298598400, 99500, PXA25x_CCCR(3,  2, 1),  0, PXA25x_CLKCFG(1)},
+       {398131200, 99500, PXA25x_CCCR(4,  2, 1),  0, PXA25x_CLKCFG(1)},
+};
+
 static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
 {
        unsigned long clkcfg;
@@ -151,13 +206,24 @@ static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
        return PXA_CORE_RUN;
 }
 
-static unsigned long clk_pxa25x_core_get_rate(struct clk_hw *hw,
-                                             unsigned long parent_rate)
+static int clk_pxa25x_core_set_parent(struct clk_hw *hw, u8 index)
 {
-       return parent_rate;
+       if (index > PXA_CORE_TURBO)
+               return -EINVAL;
+
+       pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
+
+       return 0;
+}
+
+static int clk_pxa25x_core_determine_rate(struct clk_hw *hw,
+                                         struct clk_rate_request *req)
+{
+       return __clk_mux_determine_rate(hw, req);
 }
+
 PARENTS(clk_pxa25x_core) = { "run", "cpll" };
-MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core");
+MUX_OPS(clk_pxa25x_core, "core", CLK_SET_RATE_PARENT);
 
 static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw,
                                             unsigned long parent_rate)
@@ -182,17 +248,42 @@ static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw,
        m = M_clk_mult[(cccr >> 5) & 0x03];
        n2 = N2_clk_mult[(cccr >> 7) & 0x07];
 
-       if (t)
-               return m * l * n2 * parent_rate / 2;
-       return m * l * parent_rate;
+       return m * l * n2 * parent_rate / 2;
+}
+
+static int clk_pxa25x_cpll_determine_rate(struct clk_hw *hw,
+                                         struct clk_rate_request *req)
+{
+       return pxa2xx_determine_rate(req, pxa25x_freqs,
+                                    ARRAY_SIZE(pxa25x_freqs));
+}
+
+static int clk_pxa25x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate)
+{
+       int i;
+
+       pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
+       for (i = 0; i < ARRAY_SIZE(pxa25x_freqs); i++)
+               if (pxa25x_freqs[i].cpll == rate)
+                       break;
+
+       if (i >= ARRAY_SIZE(pxa25x_freqs))
+               return -EINVAL;
+
+       pxa2xx_cpll_change(&pxa25x_freqs[i], mdrefr_dri, MDREFR, CCCR);
+
+       return 0;
 }
 PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" };
-RATE_RO_OPS(clk_pxa25x_cpll, "cpll");
+RATE_OPS(clk_pxa25x_cpll, "cpll");
 
 static void __init pxa25x_register_core(void)
 {
-       clk_register_clk_pxa25x_cpll();
-       clk_register_clk_pxa25x_run();
+       clkdev_pxa_register(CLK_NONE, "cpll", NULL,
+                           clk_register_clk_pxa25x_cpll());
+       clkdev_pxa_register(CLK_NONE, "run", NULL,
+                           clk_register_clk_pxa25x_run());
        clkdev_pxa_register(CLK_CORE, "core", NULL,
                            clk_register_clk_pxa25x_core());
 }
@@ -214,7 +305,8 @@ static void __init pxa25x_base_clocks_init(void)
 {
        pxa25x_register_plls();
        pxa25x_register_core();
-       clk_register_clk_pxa25x_memory();
+       clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
+                           clk_register_clk_pxa25x_memory());
 }
 
 #define DUMMY_CLK(_con_id, _dev_id, _parent) \
index c40b1804f58caf33f7b1bf6cac90cc22ea381248..25a30194d27a390a950667c41a9caff4f7ae16b0 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/clkdev.h>
 #include <linux/of.h>
 
+#include <mach/smemc.h>
+
 #include <dt-bindings/clock/pxa-clock.h>
 #include "clk-pxa.h"
 
@@ -45,11 +47,52 @@ enum {
        PXA_MEM_RUN,
 };
 
+#define PXA27x_CLKCFG(B, HT, T)                        \
+       (CLKCFG_FCS |                           \
+        ((B)  ? CLKCFG_FASTBUS : 0) |          \
+        ((HT) ? CLKCFG_HALFTURBO : 0) |        \
+        ((T)  ? CLKCFG_TURBO : 0))
+#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
+
+#define MDCNFG_DRAC2(mdcnfg)   (((mdcnfg) >> 21) & 0x3)
+#define MDCNFG_DRAC0(mdcnfg)   (((mdcnfg) >> 5) & 0x3)
+
+/* Define the refresh period in mSec for the SDRAM and the number of rows */
+#define SDRAM_TREF     64      /* standard 64ms SDRAM */
+
 static const char * const get_freq_khz[] = {
        "core", "run", "cpll", "memory",
        "system_bus"
 };
 
+static int get_sdram_rows(void)
+{
+       static int sdram_rows;
+       unsigned int drac2 = 0, drac0 = 0;
+       u32 mdcnfg;
+
+       if (sdram_rows)
+               return sdram_rows;
+
+       mdcnfg = readl_relaxed(MDCNFG);
+
+       if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
+               drac2 = MDCNFG_DRAC2(mdcnfg);
+
+       if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
+               drac0 = MDCNFG_DRAC0(mdcnfg);
+
+       sdram_rows = 1 << (11 + max(drac0, drac2));
+       return sdram_rows;
+}
+
+static u32 mdrefr_dri(unsigned int freq_khz)
+{
+       u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
+
+       return (interval - 31) / 32;
+}
+
 /*
  * Get the clock frequency as reflected by CCSR and the turbo flag.
  * We assume these values have been applied via a fcs.
@@ -145,6 +188,42 @@ static struct desc_clk_cken pxa27x_clocks[] __initdata = {
 
 };
 
+/*
+ * PXA270 definitions
+ *
+ * For the PXA27x:
+ * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
+ *
+ * A = 0 => memory controller clock from table 3-7,
+ * A = 1 => memory controller clock = system bus clock
+ * Run mode frequency  = 13 MHz * L
+ * Turbo mode frequency = 13 MHz * L * N
+ * System bus frequency = 13 MHz * L / (B + 1)
+ *
+ * In CCCR:
+ * A = 1
+ * L = 16        oscillator to run mode ratio
+ * 2N = 6        2 * (turbo mode to run mode ratio)
+ *
+ * In CCLKCFG:
+ * B = 1         Fast bus mode
+ * HT = 0        Half-Turbo mode
+ * T = 1         Turbo mode
+ *
+ * For now, just support some of the combinations in table 3-7 of
+ * PXA27x Processor Family Developer's Manual to simplify frequency
+ * change sequences.
+ */
+static struct pxa2xx_freq pxa27x_freqs[] = {
+       {104000000, 104000, PXA27x_CCCR(1,  8, 2), 0, PXA27x_CLKCFG(1, 0, 1) },
+       {156000000, 104000, PXA27x_CCCR(1,  8, 3), 0, PXA27x_CLKCFG(1, 0, 1) },
+       {208000000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CLKCFG(0, 0, 1) },
+       {312000000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CLKCFG(1, 0, 1) },
+       {416000000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CLKCFG(1, 0, 1) },
+       {520000000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CLKCFG(1, 0, 1) },
+       {624000000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CLKCFG(1, 0, 1) },
+};
+
 static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
        unsigned long parent_rate)
 {
@@ -162,10 +241,35 @@ static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
        L  = l * parent_rate;
        N  = (L * n2) / 2;
 
-       return t ? N : L;
+       return N;
+}
+
+static int clk_pxa27x_cpll_determine_rate(struct clk_hw *hw,
+                                         struct clk_rate_request *req)
+{
+       return pxa2xx_determine_rate(req, pxa27x_freqs,
+                                    ARRAY_SIZE(pxa27x_freqs));
+}
+
+static int clk_pxa27x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate)
+{
+       int i;
+
+       pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
+       for (i = 0; i < ARRAY_SIZE(pxa27x_freqs); i++)
+               if (pxa27x_freqs[i].cpll == rate)
+                       break;
+
+       if (i >= ARRAY_SIZE(pxa27x_freqs))
+               return -EINVAL;
+
+       pxa2xx_cpll_change(&pxa27x_freqs[i], mdrefr_dri, MDREFR, CCCR);
+       return 0;
 }
+
 PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
-RATE_RO_OPS(clk_pxa27x_cpll, "cpll");
+RATE_OPS(clk_pxa27x_cpll, "cpll");
 
 static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
                                                  unsigned long parent_rate)
@@ -217,31 +321,10 @@ static void __init pxa27x_register_plls(void)
        clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
 }
 
-static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw,
-                                             unsigned long parent_rate)
-{
-       unsigned long clkcfg;
-       unsigned int t, ht, b, osc_forced;
-       unsigned long ccsr = readl(CCSR);
-
-       osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
-       asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
-       t  = clkcfg & (1 << 0);
-       ht = clkcfg & (1 << 2);
-       b  = clkcfg & (1 << 3);
-
-       if (osc_forced)
-               return parent_rate;
-       if (ht)
-               return parent_rate / 2;
-       else
-               return parent_rate;
-}
-
 static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
 {
        unsigned long clkcfg;
-       unsigned int t, ht, b, osc_forced;
+       unsigned int t, ht, osc_forced;
        unsigned long ccsr = readl(CCSR);
 
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
@@ -251,14 +334,30 @@ static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
        asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
        t  = clkcfg & (1 << 0);
        ht = clkcfg & (1 << 2);
-       b  = clkcfg & (1 << 3);
 
        if (ht || t)
                return PXA_CORE_TURBO;
        return PXA_CORE_RUN;
 }
+
+static int clk_pxa27x_core_set_parent(struct clk_hw *hw, u8 index)
+{
+       if (index > PXA_CORE_TURBO)
+               return -EINVAL;
+
+       pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
+
+       return 0;
+}
+
+static int clk_pxa27x_core_determine_rate(struct clk_hw *hw,
+                                         struct clk_rate_request *req)
+{
+       return __clk_mux_determine_rate(hw, req);
+}
+
 PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
-MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core");
+MUX_OPS(clk_pxa27x_core, "core", CLK_SET_RATE_PARENT);
 
 static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
                                             unsigned long parent_rate)
@@ -273,9 +372,10 @@ RATE_RO_OPS(clk_pxa27x_run, "run");
 
 static void __init pxa27x_register_core(void)
 {
-       clk_register_clk_pxa27x_cpll();
-       clk_register_clk_pxa27x_run();
-
+       clkdev_pxa_register(CLK_NONE, "cpll", NULL,
+                           clk_register_clk_pxa27x_cpll());
+       clkdev_pxa_register(CLK_NONE, "run", NULL,
+                           clk_register_clk_pxa27x_run());
        clkdev_pxa_register(CLK_CORE, "core", NULL,
                            clk_register_clk_pxa27x_core());
 }
@@ -294,9 +394,9 @@ static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw,
        if (osc_forced)
                return parent_rate;
        if (b)
-               return parent_rate / 2;
-       else
                return parent_rate;
+       else
+               return parent_rate / 2;
 }
 
 static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
@@ -385,8 +485,10 @@ static void __init pxa27x_base_clocks_init(void)
 {
        pxa27x_register_plls();
        pxa27x_register_core();
-       clk_register_clk_pxa27x_system_bus();
-       clk_register_clk_pxa27x_memory();
+       clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
+                           clk_register_clk_pxa27x_system_bus());
+       clkdev_pxa_register(CLK_NONE, "memory", NULL,
+                           clk_register_clk_pxa27x_memory());
        clk_register_clk_pxa27x_lcd_base();
 }
 
index 0146d3c2547fbf8fda0bd5f7af53c73e30f9f195..5fb8d7430908414effcf6842e7ac7db042bddc81 100644 (file)
@@ -2,6 +2,9 @@ config QCOM_GDSC
        bool
        select PM_GENERIC_DOMAINS if PM
 
+config QCOM_RPMCC
+       bool
+
 config COMMON_CLK_QCOM
        tristate "Support for Qualcomm's clock controllers"
        depends on OF
@@ -9,6 +12,32 @@ config COMMON_CLK_QCOM
        select REGMAP_MMIO
        select RESET_CONTROLLER
 
+config QCOM_CLK_RPM
+       tristate "RPM based Clock Controller"
+       depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
+       select QCOM_RPMCC
+       help
+         The RPM (Resource Power Manager) is a dedicated hardware engine for
+         managing the shared SoC resources in order to keep the lowest power
+         profile. It communicates with other hardware subsystems via shared
+         memory and accepts clock requests, aggregates the requests and turns
+         the clocks on/off or scales them on demand.
+         Say Y if you want to support the clocks exposed by the RPM on
+         platforms such as apq8064, msm8660, msm8960 etc.
+
+config QCOM_CLK_SMD_RPM
+       tristate "RPM over SMD based Clock Controller"
+       depends on COMMON_CLK_QCOM && QCOM_SMD_RPM
+       select QCOM_RPMCC
+       help
+         The RPM (Resource Power Manager) is a dedicated hardware engine for
+         managing the shared SoC resources in order to keep the lowest power
+         profile. It communicates with other hardware subsystems via shared
+         memory and accepts clock requests, aggregates the requests and turns
+         the clocks on/off or scales them on demand.
+         Say Y if you want to support the clocks exposed by the RPM on
+         platforms such as apq8016, apq8084, msm8974 etc.
+
 config APQ_GCC_8084
        tristate "APQ8084 Global Clock Controller"
        select QCOM_GDSC
@@ -132,6 +161,14 @@ config MSM_MMCC_8974
          Say Y if you want to support multimedia devices such as display,
          graphics, video encode/decode, camera, etc.
 
+config MSM_GCC_8994
+       tristate "MSM8994 Global Clock Controller"
+       depends on COMMON_CLK_QCOM
+       help
+         Support for the global clock controller on msm8994 devices.
+         Say Y if you want to use peripheral devices such as UART, SPI,
+         i2c, USB, UFS, SD/eMMC, PCIe, etc.
+
 config MSM_GCC_8996
        tristate "MSM8996 Global Clock Controller"
        select QCOM_GDSC
index 1fb1f5476cb076a7e861b5df41bed383a29cba85..1c3e222b917be0695b562a15b797e2bdff9006fe 100644 (file)
@@ -24,8 +24,11 @@ obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
 obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
+obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
 obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
 obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
+obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
+obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
index e6a03eaf7a9340cad7a6e49392e8830c0a688809..47a1da3739ce98eb06dbd4939b0a218d63afe613 100644 (file)
 #include <linux/delay.h>
 
 #include "clk-alpha-pll.h"
+#include "common.h"
 
 #define PLL_MODE               0x00
 # define PLL_OUTCTRL           BIT(0)
 # define PLL_BYPASSNL          BIT(1)
 # define PLL_RESET_N           BIT(2)
+# define PLL_OFFLINE_REQ       BIT(7)
 # define PLL_LOCK_COUNT_SHIFT  8
 # define PLL_LOCK_COUNT_MASK   0x3f
 # define PLL_BIAS_COUNT_SHIFT  14
 # define PLL_BIAS_COUNT_MASK   0x3f
 # define PLL_VOTE_FSM_ENA      BIT(20)
+# define PLL_FSM_ENA           BIT(20)
 # define PLL_VOTE_FSM_RESET    BIT(21)
+# define PLL_OFFLINE_ACK       BIT(28)
 # define PLL_ACTIVE_FLAG       BIT(30)
 # define PLL_LOCK_DET          BIT(31)
 
@@ -46,6 +50,7 @@
 #define PLL_USER_CTL_U         0x14
 
 #define PLL_CONFIG_CTL         0x18
+#define PLL_CONFIG_CTL_U       0x20
 #define PLL_TEST_CTL           0x1c
 #define PLL_TEST_CTL_U         0x20
 #define PLL_STATUS             0x24
@@ -55,6 +60,7 @@
  */
 #define ALPHA_REG_BITWIDTH     40
 #define ALPHA_BITWIDTH         32
+#define ALPHA_16BIT_MASK       0xffff
 
 #define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
                                           struct clk_alpha_pll, clkr)
 #define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
                                           struct clk_alpha_pll_postdiv, clkr)
 
-static int wait_for_pll(struct clk_alpha_pll *pll)
+static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
+                       const char *action)
 {
-       u32 val, mask, off;
+       u32 val, off;
        int count;
        int ret;
        const char *name = clk_hw_get_name(&pll->clkr.hw);
@@ -74,26 +81,148 @@ static int wait_for_pll(struct clk_alpha_pll *pll)
        if (ret)
                return ret;
 
-       if (val & PLL_VOTE_FSM_ENA)
-               mask = PLL_ACTIVE_FLAG;
-       else
-               mask = PLL_LOCK_DET;
-
-       /* Wait for pll to enable. */
        for (count = 100; count > 0; count--) {
                ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
                if (ret)
                        return ret;
-               if ((val & mask) == mask)
+               if (inverse && !(val & mask))
+                       return 0;
+               else if ((val & mask) == mask)
                        return 0;
 
                udelay(1);
        }
 
-       WARN(1, "%s didn't enable after voting for it!\n", name);
+       WARN(1, "%s failed to %s!\n", name, action);
        return -ETIMEDOUT;
 }
 
+#define wait_for_pll_enable_active(pll) \
+       wait_for_pll(pll, PLL_ACTIVE_FLAG, 0, "enable")
+
+#define wait_for_pll_enable_lock(pll) \
+       wait_for_pll(pll, PLL_LOCK_DET, 0, "enable")
+
+#define wait_for_pll_disable(pll) \
+       wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable")
+
+#define wait_for_pll_offline(pll) \
+       wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline")
+
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+                            const struct alpha_pll_config *config)
+{
+       u32 val, mask;
+       u32 off = pll->offset;
+
+       regmap_write(regmap, off + PLL_L_VAL, config->l);
+       regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
+       regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
+       regmap_write(regmap, off + PLL_CONFIG_CTL_U, config->config_ctl_hi_val);
+
+       val = config->main_output_mask;
+       val |= config->aux_output_mask;
+       val |= config->aux2_output_mask;
+       val |= config->early_output_mask;
+       val |= config->pre_div_val;
+       val |= config->post_div_val;
+       val |= config->vco_val;
+
+       mask = config->main_output_mask;
+       mask |= config->aux_output_mask;
+       mask |= config->aux2_output_mask;
+       mask |= config->early_output_mask;
+       mask |= config->pre_div_mask;
+       mask |= config->post_div_mask;
+       mask |= config->vco_mask;
+
+       regmap_update_bits(regmap, off + PLL_USER_CTL, mask, val);
+
+       if (pll->flags & SUPPORTS_FSM_MODE)
+               qcom_pll_set_fsm_mode(regmap, off + PLL_MODE, 6, 0);
+}
+
+static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
+{
+       int ret;
+       u32 val, off;
+       struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+       off = pll->offset;
+       ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+       if (ret)
+               return ret;
+
+       val |= PLL_FSM_ENA;
+
+       if (pll->flags & SUPPORTS_OFFLINE_REQ)
+               val &= ~PLL_OFFLINE_REQ;
+
+       ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val);
+       if (ret)
+               return ret;
+
+       /* Make sure enable request goes through before waiting for update */
+       mb();
+
+       return wait_for_pll_enable_active(pll);
+}
+
+static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
+{
+       int ret;
+       u32 val, off;
+       struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+       off = pll->offset;
+       ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+       if (ret)
+               return;
+
+       if (pll->flags & SUPPORTS_OFFLINE_REQ) {
+               ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+                                        PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
+               if (ret)
+                       return;
+
+               ret = wait_for_pll_offline(pll);
+               if (ret)
+                       return;
+       }
+
+       /* Disable hwfsm */
+       ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+                                PLL_FSM_ENA, 0);
+       if (ret)
+               return;
+
+       wait_for_pll_disable(pll);
+}
+
+static int pll_is_enabled(struct clk_hw *hw, u32 mask)
+{
+       int ret;
+       u32 val, off;
+       struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+       off = pll->offset;
+       ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+       if (ret)
+               return ret;
+
+       return !!(val & mask);
+}
+
+static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
+{
+       return pll_is_enabled(hw, PLL_ACTIVE_FLAG);
+}
+
+static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
+{
+       return pll_is_enabled(hw, PLL_LOCK_DET);
+}
+
 static int clk_alpha_pll_enable(struct clk_hw *hw)
 {
        int ret;
@@ -112,7 +241,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
                ret = clk_enable_regmap(hw);
                if (ret)
                        return ret;
-               return wait_for_pll(pll);
+               return wait_for_pll_enable_active(pll);
        }
 
        /* Skip if already enabled */
@@ -136,7 +265,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
        if (ret)
                return ret;
 
-       ret = wait_for_pll(pll);
+       ret = wait_for_pll_enable_lock(pll);
        if (ret)
                return ret;
 
@@ -234,9 +363,14 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
        if (ctl & PLL_ALPHA_EN) {
                regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
-               regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high);
-               a = (u64)high << 32 | low;
-               a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+               if (pll->flags & SUPPORTS_16BIT_ALPHA) {
+                       a = low & ALPHA_16BIT_MASK;
+               } else {
+                       regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U,
+                                   &high);
+                       a = (u64)high << 32 | low;
+                       a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+               }
        }
 
        return alpha_pll_calc_rate(prate, l, a);
@@ -257,11 +391,15 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                return -EINVAL;
        }
 
-       a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
-
        regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
-       regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a);
-       regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+
+       if (pll->flags & SUPPORTS_16BIT_ALPHA) {
+               regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL,
+                            a & ALPHA_16BIT_MASK);
+       } else {
+               a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+               regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+       }
 
        regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
                           PLL_VCO_MASK << PLL_VCO_SHIFT,
@@ -294,12 +432,23 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 const struct clk_ops clk_alpha_pll_ops = {
        .enable = clk_alpha_pll_enable,
        .disable = clk_alpha_pll_disable,
+       .is_enabled = clk_alpha_pll_is_enabled,
        .recalc_rate = clk_alpha_pll_recalc_rate,
        .round_rate = clk_alpha_pll_round_rate,
        .set_rate = clk_alpha_pll_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
 
+const struct clk_ops clk_alpha_pll_hwfsm_ops = {
+       .enable = clk_alpha_pll_hwfsm_enable,
+       .disable = clk_alpha_pll_hwfsm_disable,
+       .is_enabled = clk_alpha_pll_hwfsm_is_enabled,
+       .recalc_rate = clk_alpha_pll_recalc_rate,
+       .round_rate = clk_alpha_pll_round_rate,
+       .set_rate = clk_alpha_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
+
 static unsigned long
 clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 {
index 90ce2016e1a0e5d03553264866cff61d2c400860..d6e1ee2c7348e617447c9fc785990e24559df09a 100644 (file)
@@ -34,6 +34,10 @@ struct clk_alpha_pll {
 
        const struct pll_vco *vco_table;
        size_t num_vco;
+#define SUPPORTS_OFFLINE_REQ   BIT(0)
+#define SUPPORTS_16BIT_ALPHA   BIT(1)
+#define SUPPORTS_FSM_MODE      BIT(2)
+       u8 flags;
 
        struct clk_regmap clkr;
 };
@@ -51,7 +55,28 @@ struct clk_alpha_pll_postdiv {
        struct clk_regmap clkr;
 };
 
+struct alpha_pll_config {
+       u32 l;
+       u32 alpha;
+       u32 config_ctl_val;
+       u32 config_ctl_hi_val;
+       u32 main_output_mask;
+       u32 aux_output_mask;
+       u32 aux2_output_mask;
+       u32 early_output_mask;
+       u32 pre_div_val;
+       u32 pre_div_mask;
+       u32 post_div_val;
+       u32 post_div_mask;
+       u32 vco_val;
+       u32 vco_mask;
+};
+
 extern const struct clk_ops clk_alpha_pll_ops;
+extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
 extern const struct clk_ops clk_alpha_pll_postdiv_ops;
 
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+                            const struct alpha_pll_config *config);
+
 #endif
index 5b940d629045fe706707f1d6a8c92a3ef12098b5..cb6cb8710daf11c0936e525fd1698caa440b884d 100644 (file)
 #include <asm/div64.h>
 
 #include "clk-pll.h"
+#include "common.h"
 
 #define PLL_OUTCTRL            BIT(0)
 #define PLL_BYPASSNL           BIT(1)
 #define PLL_RESET_N            BIT(2)
-#define PLL_LOCK_COUNT_SHIFT   8
-#define PLL_LOCK_COUNT_MASK    0x3f
-#define PLL_BIAS_COUNT_SHIFT   14
-#define PLL_BIAS_COUNT_MASK    0x3f
-#define PLL_VOTE_FSM_ENA       BIT(20)
-#define PLL_VOTE_FSM_RESET     BIT(21)
 
 static int clk_pll_enable(struct clk_hw *hw)
 {
@@ -228,26 +223,6 @@ const struct clk_ops clk_pll_vote_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
 
-static void
-clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
-{
-       u32 val;
-       u32 mask;
-
-       /* De-assert reset to FSM */
-       regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
-
-       /* Program bias count and lock count */
-       val = 1 << PLL_BIAS_COUNT_SHIFT | lock_count << PLL_LOCK_COUNT_SHIFT;
-       mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
-       mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
-       regmap_update_bits(regmap, pll->mode_reg, mask, val);
-
-       /* Enable PLL FSM voting */
-       regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_ENA,
-               PLL_VOTE_FSM_ENA);
-}
-
 static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
        const struct pll_config *config)
 {
@@ -280,7 +255,7 @@ void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
 {
        clk_pll_configure(pll, regmap, config);
        if (fsm_mode)
-               clk_pll_set_fsm_mode(pll, regmap, 8);
+               qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 8);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
 
@@ -289,7 +264,7 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
 {
        clk_pll_configure(pll, regmap, config);
        if (fsm_mode)
-               clk_pll_set_fsm_mode(pll, regmap, 0);
+               qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 0);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
 
index b904c335cda4275945351e3c772aa171a3c11d32..1b3e8d265bdb02c08c96c7cfecfb3ce8e401de60 100644 (file)
@@ -173,6 +173,7 @@ struct clk_rcg2 {
 #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
 
 extern const struct clk_ops clk_rcg2_ops;
+extern const struct clk_ops clk_rcg2_floor_ops;
 extern const struct clk_ops clk_rcg2_shared_ops;
 extern const struct clk_ops clk_edp_pixel_ops;
 extern const struct clk_ops clk_byte_ops;
index a071bba8018c40424d4d7f02ea80c9622c4d1b26..1a0985ae20d2e34a2f4588784bfd70ba2f66050f 100644 (file)
 #define N_REG                  0xc
 #define D_REG                  0x10
 
+enum freq_policy {
+       FLOOR,
+       CEIL,
+};
+
 static int clk_rcg2_is_enabled(struct clk_hw *hw)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -176,15 +181,26 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        return calc_rate(parent_rate, m, n, mode, hid_div);
 }
 
-static int _freq_tbl_determine_rate(struct clk_hw *hw,
-               const struct freq_tbl *f, struct clk_rate_request *req)
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+                                   struct clk_rate_request *req,
+                                   enum freq_policy policy)
 {
        unsigned long clk_flags, rate = req->rate;
        struct clk_hw *p;
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        int index;
 
-       f = qcom_find_freq(f, rate);
+       switch (policy) {
+       case FLOOR:
+               f = qcom_find_freq_floor(f, rate);
+               break;
+       case CEIL:
+               f = qcom_find_freq(f, rate);
+               break;
+       default:
+               return -EINVAL;
+       };
+
        if (!f)
                return -EINVAL;
 
@@ -221,7 +237,15 @@ static int clk_rcg2_determine_rate(struct clk_hw *hw,
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 
-       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, CEIL);
+}
+
+static int clk_rcg2_determine_floor_rate(struct clk_hw *hw,
+                                        struct clk_rate_request *req)
+{
+       struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR);
 }
 
 static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
@@ -265,12 +289,23 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
        return update_config(rcg);
 }
 
-static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
+static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
+                              enum freq_policy policy)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        const struct freq_tbl *f;
 
-       f = qcom_find_freq(rcg->freq_tbl, rate);
+       switch (policy) {
+       case FLOOR:
+               f = qcom_find_freq_floor(rcg->freq_tbl, rate);
+               break;
+       case CEIL:
+               f = qcom_find_freq(rcg->freq_tbl, rate);
+               break;
+       default:
+               return -EINVAL;
+       };
+
        if (!f)
                return -EINVAL;
 
@@ -280,13 +315,25 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
 static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
                            unsigned long parent_rate)
 {
-       return __clk_rcg2_set_rate(hw, rate);
+       return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+{
+       return __clk_rcg2_set_rate(hw, rate, FLOOR);
 }
 
 static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
                unsigned long rate, unsigned long parent_rate, u8 index)
 {
-       return __clk_rcg2_set_rate(hw, rate);
+       return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw,
+               unsigned long rate, unsigned long parent_rate, u8 index)
+{
+       return __clk_rcg2_set_rate(hw, rate, FLOOR);
 }
 
 const struct clk_ops clk_rcg2_ops = {
@@ -300,6 +347,17 @@ const struct clk_ops clk_rcg2_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg2_ops);
 
+const struct clk_ops clk_rcg2_floor_ops = {
+       .is_enabled = clk_rcg2_is_enabled,
+       .get_parent = clk_rcg2_get_parent,
+       .set_parent = clk_rcg2_set_parent,
+       .recalc_rate = clk_rcg2_recalc_rate,
+       .determine_rate = clk_rcg2_determine_floor_rate,
+       .set_rate = clk_rcg2_set_floor_rate,
+       .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
+
 static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -323,7 +381,7 @@ static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
                pr_err("%s: RCG did not turn on\n", name);
 
        /* set clock rate */
-       ret = __clk_rcg2_set_rate(hw, rate);
+       ret = __clk_rcg2_set_rate(hw, rate, CEIL);
        if (ret)
                return ret;
 
diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c
new file mode 100644 (file)
index 0000000..df3e5fe
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mfd/qcom_rpm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/mfd/qcom-rpm.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+
+#define QCOM_RPM_MISC_CLK_TYPE                         0x306b6c63
+#define QCOM_RPM_SCALING_ENABLE_ID                     0x2
+
+#define DEFINE_CLK_RPM(_platform, _name, _active, r_id)                              \
+       static struct clk_rpm _platform##_##_active;                          \
+       static struct clk_rpm _platform##_##_name = {                         \
+               .rpm_clk_id = (r_id),                                         \
+               .peer = &_platform##_##_active,                               \
+               .rate = INT_MAX,                                              \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_ops,                                  \
+                       .name = #_name,                                       \
+                       .parent_names = (const char *[]){ "pxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       };                                                                    \
+       static struct clk_rpm _platform##_##_active = {                       \
+               .rpm_clk_id = (r_id),                                         \
+               .peer = &_platform##_##_name,                                 \
+               .active_only = true,                                          \
+               .rate = INT_MAX,                                              \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_ops,                                  \
+                       .name = #_active,                                     \
+                       .parent_names = (const char *[]){ "pxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       }
+
+#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r)        \
+       static struct clk_rpm _platform##_##_active;                          \
+       static struct clk_rpm _platform##_##_name = {                         \
+               .rpm_clk_id = (r_id),                                         \
+               .active_only = true,                                          \
+               .peer = &_platform##_##_active,                               \
+               .rate = (r),                                                  \
+               .branch = true,                                               \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_branch_ops,                           \
+                       .name = #_name,                                       \
+                       .parent_names = (const char *[]){ "pxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       };                                                                    \
+       static struct clk_rpm _platform##_##_active = {                       \
+               .rpm_clk_id = (r_id),                                         \
+               .peer = &_platform##_##_name,                                 \
+               .rate = (r),                                                  \
+               .branch = true,                                               \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_branch_ops,                           \
+                       .name = #_active,                                     \
+                       .parent_names = (const char *[]){ "pxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       }
+
+#define DEFINE_CLK_RPM_CXO_BRANCH(_platform, _name, _active, r_id, r)        \
+       static struct clk_rpm _platform##_##_active;                          \
+       static struct clk_rpm _platform##_##_name = {                         \
+               .rpm_clk_id = (r_id),                                         \
+               .peer = &_platform##_##_active,                               \
+               .rate = (r),                                                  \
+               .branch = true,                                               \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_branch_ops,                           \
+                       .name = #_name,                                       \
+                       .parent_names = (const char *[]){ "cxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       };                                                                    \
+       static struct clk_rpm _platform##_##_active = {                       \
+               .rpm_clk_id = (r_id),                                         \
+               .active_only = true,                                          \
+               .peer = &_platform##_##_name,                                 \
+               .rate = (r),                                                  \
+               .branch = true,                                               \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_branch_ops,                           \
+                       .name = #_active,                                     \
+                       .parent_names = (const char *[]){ "cxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       }
+
+#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
+
+struct clk_rpm {
+       const int rpm_clk_id;
+       const bool active_only;
+       unsigned long rate;
+       bool enabled;
+       bool branch;
+       struct clk_rpm *peer;
+       struct clk_hw hw;
+       struct qcom_rpm *rpm;
+};
+
+struct rpm_cc {
+       struct qcom_rpm *rpm;
+       struct clk_rpm **clks;
+       size_t num_clks;
+};
+
+struct rpm_clk_desc {
+       struct clk_rpm **clks;
+       size_t num_clks;
+};
+
+static DEFINE_MUTEX(rpm_clk_lock);
+
+static int clk_rpm_handoff(struct clk_rpm *r)
+{
+       int ret;
+       u32 value = INT_MAX;
+
+       ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
+                            r->rpm_clk_id, &value, 1);
+       if (ret)
+               return ret;
+       ret = qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,
+                            r->rpm_clk_id, &value, 1);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int clk_rpm_set_rate_active(struct clk_rpm *r, unsigned long rate)
+{
+       u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */
+
+       return qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
+                             r->rpm_clk_id, &value, 1);
+}
+
+static int clk_rpm_set_rate_sleep(struct clk_rpm *r, unsigned long rate)
+{
+       u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */
+
+       return qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,
+                             r->rpm_clk_id, &value, 1);
+}
+
+static void to_active_sleep(struct clk_rpm *r, unsigned long rate,
+                           unsigned long *active, unsigned long *sleep)
+{
+       *active = rate;
+
+       /*
+        * Active-only clocks don't care what the rate is during sleep. So,
+        * they vote for zero.
+        */
+       if (r->active_only)
+               *sleep = 0;
+       else
+               *sleep = *active;
+}
+
+static int clk_rpm_prepare(struct clk_hw *hw)
+{
+       struct clk_rpm *r = to_clk_rpm(hw);
+       struct clk_rpm *peer = r->peer;
+       unsigned long this_rate = 0, this_sleep_rate = 0;
+       unsigned long peer_rate = 0, peer_sleep_rate = 0;
+       unsigned long active_rate, sleep_rate;
+       int ret = 0;
+
+       mutex_lock(&rpm_clk_lock);
+
+       /* Don't send requests to the RPM if the rate has not been set. */
+       if (!r->rate)
+               goto out;
+
+       to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);
+
+       /* Take peer clock's rate into account only if it's enabled. */
+       if (peer->enabled)
+               to_active_sleep(peer, peer->rate,
+                               &peer_rate, &peer_sleep_rate);
+
+       active_rate = max(this_rate, peer_rate);
+
+       if (r->branch)
+               active_rate = !!active_rate;
+
+       ret = clk_rpm_set_rate_active(r, active_rate);
+       if (ret)
+               goto out;
+
+       sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+       if (r->branch)
+               sleep_rate = !!sleep_rate;
+
+       ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+       if (ret)
+               /* Undo the active set vote and restore it */
+               ret = clk_rpm_set_rate_active(r, peer_rate);
+
+out:
+       if (!ret)
+               r->enabled = true;
+
+       mutex_unlock(&rpm_clk_lock);
+
+       return ret;
+}
+
+static void clk_rpm_unprepare(struct clk_hw *hw)
+{
+       struct clk_rpm *r = to_clk_rpm(hw);
+       struct clk_rpm *peer = r->peer;
+       unsigned long peer_rate = 0, peer_sleep_rate = 0;
+       unsigned long active_rate, sleep_rate;
+       int ret;
+
+       mutex_lock(&rpm_clk_lock);
+
+       if (!r->rate)
+               goto out;
+
+       /* Take peer clock's rate into account only if it's enabled. */
+       if (peer->enabled)
+               to_active_sleep(peer, peer->rate, &peer_rate,
+                               &peer_sleep_rate);
+
+       active_rate = r->branch ? !!peer_rate : peer_rate;
+       ret = clk_rpm_set_rate_active(r, active_rate);
+       if (ret)
+               goto out;
+
+       sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;
+       ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+       if (ret)
+               goto out;
+
+       r->enabled = false;
+
+out:
+       mutex_unlock(&rpm_clk_lock);
+}
+
+static int clk_rpm_set_rate(struct clk_hw *hw,
+                           unsigned long rate, unsigned long parent_rate)
+{
+       struct clk_rpm *r = to_clk_rpm(hw);
+       struct clk_rpm *peer = r->peer;
+       unsigned long active_rate, sleep_rate;
+       unsigned long this_rate = 0, this_sleep_rate = 0;
+       unsigned long peer_rate = 0, peer_sleep_rate = 0;
+       int ret = 0;
+
+       mutex_lock(&rpm_clk_lock);
+
+       if (!r->enabled)
+               goto out;
+
+       to_active_sleep(r, rate, &this_rate, &this_sleep_rate);
+
+       /* Take peer clock's rate into account only if it's enabled. */
+       if (peer->enabled)
+               to_active_sleep(peer, peer->rate,
+                               &peer_rate, &peer_sleep_rate);
+
+       active_rate = max(this_rate, peer_rate);
+       ret = clk_rpm_set_rate_active(r, active_rate);
+       if (ret)
+               goto out;
+
+       sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+       ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+       if (ret)
+               goto out;
+
+       r->rate = rate;
+
+out:
+       mutex_unlock(&rpm_clk_lock);
+
+       return ret;
+}
+
+static long clk_rpm_round_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long *parent_rate)
+{
+       /*
+        * RPM handles rate rounding and we don't have a way to
+        * know what the rate will be, so just return whatever
+        * rate is requested.
+        */
+       return rate;
+}
+
+static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct clk_rpm *r = to_clk_rpm(hw);
+
+       /*
+        * RPM handles rate rounding and we don't have a way to
+        * know what the rate will be, so just return whatever
+        * rate was set.
+        */
+       return r->rate;
+}
+
+static const struct clk_ops clk_rpm_ops = {
+       .prepare        = clk_rpm_prepare,
+       .unprepare      = clk_rpm_unprepare,
+       .set_rate       = clk_rpm_set_rate,
+       .round_rate     = clk_rpm_round_rate,
+       .recalc_rate    = clk_rpm_recalc_rate,
+};
+
+static const struct clk_ops clk_rpm_branch_ops = {
+       .prepare        = clk_rpm_prepare,
+       .unprepare      = clk_rpm_unprepare,
+       .round_rate     = clk_rpm_round_rate,
+       .recalc_rate    = clk_rpm_recalc_rate,
+};
+
+/* apq8064 */
+DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
+DEFINE_CLK_RPM(apq8064, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
+DEFINE_CLK_RPM(apq8064, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
+DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
+DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
+
+static struct clk_rpm *apq8064_clks[] = {
+       [RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
+       [RPM_APPS_FABRIC_A_CLK] = &apq8064_afab_a_clk,
+       [RPM_CFPB_CLK] = &apq8064_cfpb_clk,
+       [RPM_CFPB_A_CLK] = &apq8064_cfpb_a_clk,
+       [RPM_DAYTONA_FABRIC_CLK] = &apq8064_daytona_clk,
+       [RPM_DAYTONA_FABRIC_A_CLK] = &apq8064_daytona_a_clk,
+       [RPM_EBI1_CLK] = &apq8064_ebi1_clk,
+       [RPM_EBI1_A_CLK] = &apq8064_ebi1_a_clk,
+       [RPM_MM_FABRIC_CLK] = &apq8064_mmfab_clk,
+       [RPM_MM_FABRIC_A_CLK] = &apq8064_mmfab_a_clk,
+       [RPM_MMFPB_CLK] = &apq8064_mmfpb_clk,
+       [RPM_MMFPB_A_CLK] = &apq8064_mmfpb_a_clk,
+       [RPM_SYS_FABRIC_CLK] = &apq8064_sfab_clk,
+       [RPM_SYS_FABRIC_A_CLK] = &apq8064_sfab_a_clk,
+       [RPM_SFPB_CLK] = &apq8064_sfpb_clk,
+       [RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
+       [RPM_QDSS_CLK] = &apq8064_qdss_clk,
+       [RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
+};
+
+static const struct rpm_clk_desc rpm_clk_apq8064 = {
+       .clks = apq8064_clks,
+       .num_clks = ARRAY_SIZE(apq8064_clks),
+};
+
+static const struct of_device_id rpm_clk_match_table[] = {
+       { .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rpm_clk_match_table);
+
+static struct clk_hw *qcom_rpm_clk_hw_get(struct of_phandle_args *clkspec,
+                                         void *data)
+{
+       struct rpm_cc *rcc = data;
+       unsigned int idx = clkspec->args[0];
+
+       if (idx >= rcc->num_clks) {
+               pr_err("%s: invalid index %u\n", __func__, idx);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
+}
+
+static int rpm_clk_probe(struct platform_device *pdev)
+{
+       struct rpm_cc *rcc;
+       int ret;
+       size_t num_clks, i;
+       struct qcom_rpm *rpm;
+       struct clk_rpm **rpm_clks;
+       const struct rpm_clk_desc *desc;
+
+       rpm = dev_get_drvdata(pdev->dev.parent);
+       if (!rpm) {
+               dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+               return -ENODEV;
+       }
+
+       desc = of_device_get_match_data(&pdev->dev);
+       if (!desc)
+               return -EINVAL;
+
+       rpm_clks = desc->clks;
+       num_clks = desc->num_clks;
+
+       rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
+       if (!rcc)
+               return -ENOMEM;
+
+       rcc->clks = rpm_clks;
+       rcc->num_clks = num_clks;
+
+       for (i = 0; i < num_clks; i++) {
+               if (!rpm_clks[i])
+                       continue;
+
+               rpm_clks[i]->rpm = rpm;
+
+               ret = clk_rpm_handoff(rpm_clks[i]);
+               if (ret)
+                       goto err;
+       }
+
+       for (i = 0; i < num_clks; i++) {
+               if (!rpm_clks[i])
+                       continue;
+
+               ret = devm_clk_hw_register(&pdev->dev, &rpm_clks[i]->hw);
+               if (ret)
+                       goto err;
+       }
+
+       ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_rpm_clk_hw_get,
+                                    rcc);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       dev_err(&pdev->dev, "Error registering RPM Clock driver (%d)\n", ret);
+       return ret;
+}
+
+static int rpm_clk_remove(struct platform_device *pdev)
+{
+       of_clk_del_provider(pdev->dev.of_node);
+       return 0;
+}
+
+static struct platform_driver rpm_clk_driver = {
+       .driver = {
+               .name = "qcom-clk-rpm",
+               .of_match_table = rpm_clk_match_table,
+       },
+       .probe = rpm_clk_probe,
+       .remove = rpm_clk_remove,
+};
+
+static int __init rpm_clk_init(void)
+{
+       return platform_driver_register(&rpm_clk_driver);
+}
+core_initcall(rpm_clk_init);
+
+static void __exit rpm_clk_exit(void)
+{
+       platform_driver_unregister(&rpm_clk_driver);
+}
+module_exit(rpm_clk_exit);
+
+MODULE_DESCRIPTION("Qualcomm RPM Clock Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-clk-rpm");
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
new file mode 100644 (file)
index 0000000..07e2cc6
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/mfd/qcom-rpm.h>
+
+#define QCOM_RPM_KEY_SOFTWARE_ENABLE                   0x6e657773
+#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY    0x62636370
+#define QCOM_RPM_SMD_KEY_RATE                          0x007a484b
+#define QCOM_RPM_SMD_KEY_ENABLE                                0x62616e45
+#define QCOM_RPM_SMD_KEY_STATE                         0x54415453
+#define QCOM_RPM_SCALING_ENABLE_ID                     0x2
+
+#define __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, stat_id,  \
+                            key)                                             \
+       static struct clk_smd_rpm _platform##_##_active;                      \
+       static struct clk_smd_rpm _platform##_##_name = {                     \
+               .rpm_res_type = (type),                                       \
+               .rpm_clk_id = (r_id),                                         \
+               .rpm_status_id = (stat_id),                                   \
+               .rpm_key = (key),                                             \
+               .peer = &_platform##_##_active,                               \
+               .rate = INT_MAX,                                              \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_smd_rpm_ops,                              \
+                       .name = #_name,                                       \
+                       .parent_names = (const char *[]){ "xo_board" },       \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       };                                                                    \
+       static struct clk_smd_rpm _platform##_##_active = {                   \
+               .rpm_res_type = (type),                                       \
+               .rpm_clk_id = (r_id),                                         \
+               .rpm_status_id = (stat_id),                                   \
+               .active_only = true,                                          \
+               .rpm_key = (key),                                             \
+               .peer = &_platform##_##_name,                                 \
+               .rate = INT_MAX,                                              \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_smd_rpm_ops,                              \
+                       .name = #_active,                                     \
+                       .parent_names = (const char *[]){ "xo_board" },       \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       }
+
+#define __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id,    \
+                                   stat_id, r, key)                          \
+       static struct clk_smd_rpm _platform##_##_active;                      \
+       static struct clk_smd_rpm _platform##_##_name = {                     \
+               .rpm_res_type = (type),                                       \
+               .rpm_clk_id = (r_id),                                         \
+               .rpm_status_id = (stat_id),                                   \
+               .rpm_key = (key),                                             \
+               .branch = true,                                               \
+               .peer = &_platform##_##_active,                               \
+               .rate = (r),                                                  \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_smd_rpm_branch_ops,                       \
+                       .name = #_name,                                       \
+                       .parent_names = (const char *[]){ "xo_board" },       \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       };                                                                    \
+       static struct clk_smd_rpm _platform##_##_active = {                   \
+               .rpm_res_type = (type),                                       \
+               .rpm_clk_id = (r_id),                                         \
+               .rpm_status_id = (stat_id),                                   \
+               .active_only = true,                                          \
+               .rpm_key = (key),                                             \
+               .branch = true,                                               \
+               .peer = &_platform##_##_name,                                 \
+               .rate = (r),                                                  \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_smd_rpm_branch_ops,                       \
+                       .name = #_active,                                     \
+                       .parent_names = (const char *[]){ "xo_board" },       \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       }
+
+#define DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id)            \
+               __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id,   \
+               0, QCOM_RPM_SMD_KEY_RATE)
+
+#define DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, r)   \
+               __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type,  \
+               r_id, 0, r, QCOM_RPM_SMD_KEY_ENABLE)
+
+#define DEFINE_CLK_SMD_RPM_QDSS(_platform, _name, _active, type, r_id)       \
+               __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id,   \
+               0, QCOM_RPM_SMD_KEY_STATE)
+
+#define DEFINE_CLK_SMD_RPM_XO_BUFFER(_platform, _name, _active, r_id)        \
+               __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active,        \
+               QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000,                        \
+               QCOM_RPM_KEY_SOFTWARE_ENABLE)
+
+#define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_platform, _name, _active, r_id) \
+               __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active,        \
+               QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000,                        \
+               QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY)
+
+#define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw)
+
+struct clk_smd_rpm {
+       const int rpm_res_type;
+       const int rpm_key;
+       const int rpm_clk_id;
+       const int rpm_status_id;
+       const bool active_only;
+       bool enabled;
+       bool branch;
+       struct clk_smd_rpm *peer;
+       struct clk_hw hw;
+       unsigned long rate;
+       struct qcom_smd_rpm *rpm;
+};
+
+struct clk_smd_rpm_req {
+       __le32 key;
+       __le32 nbytes;
+       __le32 value;
+};
+
+struct rpm_cc {
+       struct qcom_rpm *rpm;
+       struct clk_smd_rpm **clks;
+       size_t num_clks;
+};
+
+struct rpm_smd_clk_desc {
+       struct clk_smd_rpm **clks;
+       size_t num_clks;
+};
+
+static DEFINE_MUTEX(rpm_smd_clk_lock);
+
+static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)
+{
+       int ret;
+       struct clk_smd_rpm_req req = {
+               .key = cpu_to_le32(r->rpm_key),
+               .nbytes = cpu_to_le32(sizeof(u32)),
+               .value = cpu_to_le32(INT_MAX),
+       };
+
+       ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+                                r->rpm_res_type, r->rpm_clk_id, &req,
+                                sizeof(req));
+       if (ret)
+               return ret;
+       ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+                                r->rpm_res_type, r->rpm_clk_id, &req,
+                                sizeof(req));
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,
+                                      unsigned long rate)
+{
+       struct clk_smd_rpm_req req = {
+               .key = cpu_to_le32(r->rpm_key),
+               .nbytes = cpu_to_le32(sizeof(u32)),
+               .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
+       };
+
+       return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+                                 r->rpm_res_type, r->rpm_clk_id, &req,
+                                 sizeof(req));
+}
+
+static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,
+                                     unsigned long rate)
+{
+       struct clk_smd_rpm_req req = {
+               .key = cpu_to_le32(r->rpm_key),
+               .nbytes = cpu_to_le32(sizeof(u32)),
+               .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
+       };
+
+       return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+                                 r->rpm_res_type, r->rpm_clk_id, &req,
+                                 sizeof(req));
+}
+
+static void to_active_sleep(struct clk_smd_rpm *r, unsigned long rate,
+                           unsigned long *active, unsigned long *sleep)
+{
+       *active = rate;
+
+       /*
+        * Active-only clocks don't care what the rate is during sleep. So,
+        * they vote for zero.
+        */
+       if (r->active_only)
+               *sleep = 0;
+       else
+               *sleep = *active;
+}
+
+static int clk_smd_rpm_prepare(struct clk_hw *hw)
+{
+       struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+       struct clk_smd_rpm *peer = r->peer;
+       unsigned long this_rate = 0, this_sleep_rate = 0;
+       unsigned long peer_rate = 0, peer_sleep_rate = 0;
+       unsigned long active_rate, sleep_rate;
+       int ret = 0;
+
+       mutex_lock(&rpm_smd_clk_lock);
+
+       /* Don't send requests to the RPM if the rate has not been set. */
+       if (!r->rate)
+               goto out;
+
+       to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);
+
+       /* Take peer clock's rate into account only if it's enabled. */
+       if (peer->enabled)
+               to_active_sleep(peer, peer->rate,
+                               &peer_rate, &peer_sleep_rate);
+
+       active_rate = max(this_rate, peer_rate);
+
+       if (r->branch)
+               active_rate = !!active_rate;
+
+       ret = clk_smd_rpm_set_rate_active(r, active_rate);
+       if (ret)
+               goto out;
+
+       sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+       if (r->branch)
+               sleep_rate = !!sleep_rate;
+
+       ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+       if (ret)
+               /* Undo the active set vote and restore it */
+               ret = clk_smd_rpm_set_rate_active(r, peer_rate);
+
+out:
+       if (!ret)
+               r->enabled = true;
+
+       mutex_unlock(&rpm_smd_clk_lock);
+
+       return ret;
+}
+
+static void clk_smd_rpm_unprepare(struct clk_hw *hw)
+{
+       struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+       struct clk_smd_rpm *peer = r->peer;
+       unsigned long peer_rate = 0, peer_sleep_rate = 0;
+       unsigned long active_rate, sleep_rate;
+       int ret;
+
+       mutex_lock(&rpm_smd_clk_lock);
+
+       if (!r->rate)
+               goto out;
+
+       /* Take peer clock's rate into account only if it's enabled. */
+       if (peer->enabled)
+               to_active_sleep(peer, peer->rate, &peer_rate,
+                               &peer_sleep_rate);
+
+       active_rate = r->branch ? !!peer_rate : peer_rate;
+       ret = clk_smd_rpm_set_rate_active(r, active_rate);
+       if (ret)
+               goto out;
+
+       sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;
+       ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+       if (ret)
+               goto out;
+
+       r->enabled = false;
+
+out:
+       mutex_unlock(&rpm_smd_clk_lock);
+}
+
+static int clk_smd_rpm_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+       struct clk_smd_rpm *peer = r->peer;
+       unsigned long active_rate, sleep_rate;
+       unsigned long this_rate = 0, this_sleep_rate = 0;
+       unsigned long peer_rate = 0, peer_sleep_rate = 0;
+       int ret = 0;
+
+       mutex_lock(&rpm_smd_clk_lock);
+
+       if (!r->enabled)
+               goto out;
+
+       to_active_sleep(r, rate, &this_rate, &this_sleep_rate);
+
+       /* Take peer clock's rate into account only if it's enabled. */
+       if (peer->enabled)
+               to_active_sleep(peer, peer->rate,
+                               &peer_rate, &peer_sleep_rate);
+
+       active_rate = max(this_rate, peer_rate);
+       ret = clk_smd_rpm_set_rate_active(r, active_rate);
+       if (ret)
+               goto out;
+
+       sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+       ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+       if (ret)
+               goto out;
+
+       r->rate = rate;
+
+out:
+       mutex_unlock(&rpm_smd_clk_lock);
+
+       return ret;
+}
+
+static long clk_smd_rpm_round_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long *parent_rate)
+{
+       /*
+        * RPM handles rate rounding and we don't have a way to
+        * know what the rate will be, so just return whatever
+        * rate is requested.
+        */
+       return rate;
+}
+
+static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+
+       /*
+        * RPM handles rate rounding and we don't have a way to
+        * know what the rate will be, so just return whatever
+        * rate was set.
+        */
+       return r->rate;
+}
+
+static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)
+{
+       int ret;
+       struct clk_smd_rpm_req req = {
+               .key = cpu_to_le32(QCOM_RPM_SMD_KEY_ENABLE),
+               .nbytes = cpu_to_le32(sizeof(u32)),
+               .value = cpu_to_le32(1),
+       };
+
+       ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE,
+                                QCOM_SMD_RPM_MISC_CLK,
+                                QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
+       if (ret) {
+               pr_err("RPM clock scaling (sleep set) not enabled!\n");
+               return ret;
+       }
+
+       ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+                                QCOM_SMD_RPM_MISC_CLK,
+                                QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
+       if (ret) {
+               pr_err("RPM clock scaling (active set) not enabled!\n");
+               return ret;
+       }
+
+       pr_debug("%s: RPM clock scaling is enabled\n", __func__);
+       return 0;
+}
+
+static const struct clk_ops clk_smd_rpm_ops = {
+       .prepare        = clk_smd_rpm_prepare,
+       .unprepare      = clk_smd_rpm_unprepare,
+       .set_rate       = clk_smd_rpm_set_rate,
+       .round_rate     = clk_smd_rpm_round_rate,
+       .recalc_rate    = clk_smd_rpm_recalc_rate,
+};
+
+static const struct clk_ops clk_smd_rpm_branch_ops = {
+       .prepare        = clk_smd_rpm_prepare,
+       .unprepare      = clk_smd_rpm_unprepare,
+       .round_rate     = clk_smd_rpm_round_rate,
+       .recalc_rate    = clk_smd_rpm_recalc_rate,
+};
+
+/* msm8916 */
+DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
+DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
+DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
+DEFINE_CLK_SMD_RPM_QDSS(msm8916, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk1, bb_clk1_a, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk2, bb_clk2_a, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk1, rf_clk1_a, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk2, rf_clk2_a, 5);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk1_pin, bb_clk1_a_pin, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk2_pin, bb_clk2_a_pin, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk1_pin, rf_clk1_a_pin, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk2_pin, rf_clk2_a_pin, 5);
+
+static struct clk_smd_rpm *msm8916_clks[] = {
+       [RPM_SMD_PCNOC_CLK]             = &msm8916_pcnoc_clk,
+       [RPM_SMD_PCNOC_A_CLK]           = &msm8916_pcnoc_a_clk,
+       [RPM_SMD_SNOC_CLK]              = &msm8916_snoc_clk,
+       [RPM_SMD_SNOC_A_CLK]            = &msm8916_snoc_a_clk,
+       [RPM_SMD_BIMC_CLK]              = &msm8916_bimc_clk,
+       [RPM_SMD_BIMC_A_CLK]            = &msm8916_bimc_a_clk,
+       [RPM_SMD_QDSS_CLK]              = &msm8916_qdss_clk,
+       [RPM_SMD_QDSS_A_CLK]            = &msm8916_qdss_a_clk,
+       [RPM_SMD_BB_CLK1]               = &msm8916_bb_clk1,
+       [RPM_SMD_BB_CLK1_A]             = &msm8916_bb_clk1_a,
+       [RPM_SMD_BB_CLK2]               = &msm8916_bb_clk2,
+       [RPM_SMD_BB_CLK2_A]             = &msm8916_bb_clk2_a,
+       [RPM_SMD_RF_CLK1]               = &msm8916_rf_clk1,
+       [RPM_SMD_RF_CLK1_A]             = &msm8916_rf_clk1_a,
+       [RPM_SMD_RF_CLK2]               = &msm8916_rf_clk2,
+       [RPM_SMD_RF_CLK2_A]             = &msm8916_rf_clk2_a,
+       [RPM_SMD_BB_CLK1_PIN]           = &msm8916_bb_clk1_pin,
+       [RPM_SMD_BB_CLK1_A_PIN]         = &msm8916_bb_clk1_a_pin,
+       [RPM_SMD_BB_CLK2_PIN]           = &msm8916_bb_clk2_pin,
+       [RPM_SMD_BB_CLK2_A_PIN]         = &msm8916_bb_clk2_a_pin,
+       [RPM_SMD_RF_CLK1_PIN]           = &msm8916_rf_clk1_pin,
+       [RPM_SMD_RF_CLK1_A_PIN]         = &msm8916_rf_clk1_a_pin,
+       [RPM_SMD_RF_CLK2_PIN]           = &msm8916_rf_clk2_pin,
+       [RPM_SMD_RF_CLK2_A_PIN]         = &msm8916_rf_clk2_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_msm8916 = {
+       .clks = msm8916_clks,
+       .num_clks = ARRAY_SIZE(msm8916_clks),
+};
+
+static const struct of_device_id rpm_smd_clk_match_table[] = {
+       { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
+
+static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec,
+                                            void *data)
+{
+       struct rpm_cc *rcc = data;
+       unsigned int idx = clkspec->args[0];
+
+       if (idx >= rcc->num_clks) {
+               pr_err("%s: invalid index %u\n", __func__, idx);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
+}
+
+static int rpm_smd_clk_probe(struct platform_device *pdev)
+{
+       struct rpm_cc *rcc;
+       int ret;
+       size_t num_clks, i;
+       struct qcom_smd_rpm *rpm;
+       struct clk_smd_rpm **rpm_smd_clks;
+       const struct rpm_smd_clk_desc *desc;
+
+       rpm = dev_get_drvdata(pdev->dev.parent);
+       if (!rpm) {
+               dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+               return -ENODEV;
+       }
+
+       desc = of_device_get_match_data(&pdev->dev);
+       if (!desc)
+               return -EINVAL;
+
+       rpm_smd_clks = desc->clks;
+       num_clks = desc->num_clks;
+
+       rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
+       if (!rcc)
+               return -ENOMEM;
+
+       rcc->clks = rpm_smd_clks;
+       rcc->num_clks = num_clks;
+
+       for (i = 0; i < num_clks; i++) {
+               if (!rpm_smd_clks[i])
+                       continue;
+
+               rpm_smd_clks[i]->rpm = rpm;
+
+               ret = clk_smd_rpm_handoff(rpm_smd_clks[i]);
+               if (ret)
+                       goto err;
+       }
+
+       ret = clk_smd_rpm_enable_scaling(rpm);
+       if (ret)
+               goto err;
+
+       for (i = 0; i < num_clks; i++) {
+               if (!rpm_smd_clks[i])
+                       continue;
+
+               ret = devm_clk_hw_register(&pdev->dev, &rpm_smd_clks[i]->hw);
+               if (ret)
+                       goto err;
+       }
+
+       ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get,
+                                    rcc);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       dev_err(&pdev->dev, "Error registering SMD clock driver (%d)\n", ret);
+       return ret;
+}
+
+static int rpm_smd_clk_remove(struct platform_device *pdev)
+{
+       of_clk_del_provider(pdev->dev.of_node);
+       return 0;
+}
+
+static struct platform_driver rpm_smd_clk_driver = {
+       .driver = {
+               .name = "qcom-clk-smd-rpm",
+               .of_match_table = rpm_smd_clk_match_table,
+       },
+       .probe = rpm_smd_clk_probe,
+       .remove = rpm_smd_clk_remove,
+};
+
+static int __init rpm_smd_clk_init(void)
+{
+       return platform_driver_register(&rpm_smd_clk_driver);
+}
+core_initcall(rpm_smd_clk_init);
+
+static void __exit rpm_smd_clk_exit(void)
+{
+       platform_driver_unregister(&rpm_smd_clk_driver);
+}
+module_exit(rpm_smd_clk_exit);
+
+MODULE_DESCRIPTION("Qualcomm RPM over SMD Clock Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-clk-smd-rpm");
index fffcbaf0fba74b3fad90ea48c25761aa7873ab43..cfab7b400381ad467f39d9628930745f6345cce4 100644 (file)
@@ -46,6 +46,22 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
 }
 EXPORT_SYMBOL_GPL(qcom_find_freq);
 
+const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+                                           unsigned long rate)
+{
+       const struct freq_tbl *best = NULL;
+
+       for ( ; f->freq; f++) {
+               if (rate >= f->freq)
+                       best = f;
+               else
+                       break;
+       }
+
+       return best;
+}
+EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
+
 int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
 {
        int i, num_parents = clk_hw_get_num_parents(hw);
@@ -74,6 +90,27 @@ qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
 }
 EXPORT_SYMBOL_GPL(qcom_cc_map);
 
+void
+qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count)
+{
+       u32 val;
+       u32 mask;
+
+       /* De-assert reset to FSM */
+       regmap_update_bits(map, reg, PLL_VOTE_FSM_RESET, 0);
+
+       /* Program bias count and lock count */
+       val = bias_count << PLL_BIAS_COUNT_SHIFT |
+               lock_count << PLL_LOCK_COUNT_SHIFT;
+       mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
+       mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
+       regmap_update_bits(map, reg, mask, val);
+
+       /* Enable PLL FSM voting */
+       regmap_update_bits(map, reg, PLL_VOTE_FSM_ENA, PLL_VOTE_FSM_ENA);
+}
+EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode);
+
 static void qcom_cc_del_clk_provider(void *data)
 {
        of_clk_del_provider(data);
@@ -153,15 +190,12 @@ int qcom_cc_register_board_clk(struct device *dev, const char *path,
                               const char *name, unsigned long rate)
 {
        bool add_factor = true;
-       struct device_node *node;
-
-       /* The RPM clock driver will add the factor clock if present */
-       if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {
-               node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");
-               if (of_device_is_available(node))
-                       add_factor = false;
-               of_node_put(node);
-       }
+
+       /*
+        * TODO: The RPM clock driver currently does not support the xo clock.
+        * When xo is added to the RPM clock driver, we should change this
+        * function to skip registration of xo factor clocks.
+        */
 
        return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);
 }
index ae9bdeb21f295a0e9a3f14b3230d37636324a5a8..23c1927669bac89273c39ee1b698ddc31890e5e7 100644 (file)
@@ -22,6 +22,13 @@ struct freq_tbl;
 struct clk_hw;
 struct parent_map;
 
+#define PLL_LOCK_COUNT_SHIFT   8
+#define PLL_LOCK_COUNT_MASK    0x3f
+#define PLL_BIAS_COUNT_SHIFT   14
+#define PLL_BIAS_COUNT_MASK    0x3f
+#define PLL_VOTE_FSM_ENA       BIT(20)
+#define PLL_VOTE_FSM_RESET     BIT(21)
+
 struct qcom_cc_desc {
        const struct regmap_config *config;
        struct clk_regmap **clks;
@@ -34,6 +41,10 @@ struct qcom_cc_desc {
 
 extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
                                             unsigned long rate);
+extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+                                                  unsigned long rate);
+extern void
+qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count);
 extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
                               u8 src);
 
index 070037a29ea5842ba6cd332563570fc1ffd8689c..486d9610355c653eb034e99833beacb6d63baf33 100644 (file)
@@ -1142,7 +1142,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
                .name = "sdcc1_apps_clk_src",
                .parent_names = gcc_xo_gpll0_gpll4,
                .num_parents = 3,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -1156,7 +1156,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
                .name = "sdcc2_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -1170,7 +1170,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
                .name = "sdcc3_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -1184,7 +1184,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
                .name = "sdcc4_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
index b593065de8db6fdb860548c556c989c1531964cf..33d09138f5e5b3b3c553a5e7d4f4787feb0b5507 100644 (file)
@@ -185,8 +185,7 @@ static struct clk_branch gcc_audio_pwm_clk = {
 };
 
 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = {
-       F(19200000, P_XO, 1, 2, 5),
-       F(24000000, P_XO, 1, 1, 2),
+       F(19050000, P_FEPLL200, 10.5, 1, 1),
        { }
 };
 
index 52a7d3959875b2eee15bc75fc8398764849e8c63..28eb200d0f1ee008989e5a253811a316c6951ee9 100644 (file)
@@ -2990,11 +2990,11 @@ static int gcc_ipq806x_probe(struct platform_device *pdev)
        struct regmap *regmap;
        int ret;
 
-       ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
+       ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 25000000);
        if (ret)
                return ret;
 
-       ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
+       ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 25000000);
        if (ret)
                return ret;
 
index 5c4e193164d4d7b9d3ec729ef724b2b1293e560d..628e6ca276ec827c865b0d53dfa9281cc57db43c 100644 (file)
@@ -1107,7 +1107,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
                .name = "sdcc1_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -1132,7 +1132,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
                .name = "sdcc2_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
index 00915209e7c547f080b389be9f9478d4b70658f9..348e30da4f18db105945d4baed75bee3d97da328 100644 (file)
@@ -872,7 +872,7 @@ static struct clk_init_data sdcc1_apps_clk_src_init = {
        .name = "sdcc1_apps_clk_src",
        .parent_names = gcc_xo_gpll0,
        .num_parents = 2,
-       .ops = &clk_rcg2_ops,
+       .ops = &clk_rcg2_floor_ops,
 };
 
 static struct clk_rcg2 sdcc1_apps_clk_src = {
@@ -894,7 +894,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
                .name = "sdcc2_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -908,7 +908,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
                .name = "sdcc3_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -922,7 +922,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
                .name = "sdcc4_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
diff --git a/drivers/clk/qcom/gcc-msm8994.c b/drivers/clk/qcom/gcc-msm8994.c
new file mode 100644 (file)
index 0000000..8afd830
--- /dev/null
@@ -0,0 +1,2300 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8994.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+enum {
+       P_XO,
+       P_GPLL0,
+       P_GPLL4,
+};
+
+static const struct parent_map gcc_xo_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+};
+
+static const char * const gcc_xo_gpll0[] = {
+       "xo",
+       "gpll0",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_GPLL4, 5 },
+};
+
+static const char * const gcc_xo_gpll0_gpll4[] = {
+       "xo",
+       "gpll0",
+       "gpll4",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_fixed_factor xo = {
+       .mult = 1,
+       .div = 1,
+       .hw.init = &(struct clk_init_data)
+       {
+               .name = "xo",
+               .parent_names = (const char *[]) { "xo_board" },
+               .num_parents = 1,
+               .ops = &clk_fixed_factor_ops,
+       },
+};
+
+static struct clk_alpha_pll gpll0_early = {
+       .offset = 0x00000,
+       .clkr = {
+               .enable_reg = 0x1480,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gpll0_early",
+                       .parent_names = (const char *[]) { "xo" },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_ops,
+               },
+       },
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+       .offset = 0x00000,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "gpll0",
+               .parent_names = (const char *[]) { "gpll0_early" },
+               .num_parents = 1,
+               .ops = &clk_alpha_pll_postdiv_ops,
+       },
+};
+
+static struct clk_alpha_pll gpll4_early = {
+       .offset = 0x1dc0,
+       .clkr = {
+               .enable_reg = 0x1480,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gpll4_early",
+                       .parent_names = (const char *[]) { "xo" },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_ops,
+               },
+       },
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+       .offset = 0x1dc0,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "gpll4",
+               .parent_names = (const char *[]) { "gpll4_early" },
+               .num_parents = 1,
+               .ops = &clk_alpha_pll_postdiv_ops,
+       },
+};
+
+static struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+       F(50000000, P_GPLL0, 12, 0, 0),
+       F(100000000, P_GPLL0, 6, 0, 0),
+       F(150000000, P_GPLL0, 4, 0, 0),
+       F(171430000, P_GPLL0, 3.5, 0, 0),
+       F(200000000, P_GPLL0, 3, 0, 0),
+       F(240000000, P_GPLL0, 2.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+       .cmd_rcgr = 0x1d68,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_ufs_axi_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "ufs_axi_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_usb30_master_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(125000000, P_GPLL0, 1, 5, 24),
+       { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+       .cmd_rcgr = 0x03d4,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_usb30_master_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "usb30_master_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_blsp_i2c_apps_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(50000000, P_GPLL0, 12, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0660,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup1_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_blspqup_spi_apps_clk_src[] = {
+       F(960000, P_XO, 10, 1, 2),
+       F(4800000, P_XO, 4, 0, 0),
+       F(9600000, P_XO, 2, 0, 0),
+       F(15000000, P_GPLL0, 10, 1, 4),
+       F(19200000, P_XO, 1, 0, 0),
+       F(24000000, P_GPLL0, 12.5, 1, 2),
+       F(25000000, P_GPLL0, 12, 1, 2),
+       F(48000000, P_GPLL0, 12.5, 0, 0),
+       F(50000000, P_GPLL0, 12, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+       .cmd_rcgr = 0x064c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup1_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x06e0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup2_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+       .cmd_rcgr = 0x06cc,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup2_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0760,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup3_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+       .cmd_rcgr = 0x074c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup3_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x07e0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup4_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+       .cmd_rcgr = 0x07cc,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup4_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0860,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup5_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+       .cmd_rcgr = 0x084c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup5_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x08e0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup6_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+       .cmd_rcgr = 0x08cc,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_qup6_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_blsp_uart_apps_clk_src[] = {
+       F(3686400, P_GPLL0, 1, 96, 15625),
+       F(7372800, P_GPLL0, 1, 192, 15625),
+       F(14745600, P_GPLL0, 1, 384, 15625),
+       F(16000000, P_GPLL0, 5, 2, 15),
+       F(19200000, P_XO, 1, 0, 0),
+       F(24000000, P_GPLL0, 5, 1, 5),
+       F(32000000, P_GPLL0, 1, 4, 75),
+       F(40000000, P_GPLL0, 15, 0, 0),
+       F(46400000, P_GPLL0, 1, 29, 375),
+       F(48000000, P_GPLL0, 12.5, 0, 0),
+       F(51200000, P_GPLL0, 1, 32, 375),
+       F(56000000, P_GPLL0, 1, 7, 75),
+       F(58982400, P_GPLL0, 1, 1536, 15625),
+       F(60000000, P_GPLL0, 10, 0, 0),
+       F(63160000, P_GPLL0, 9.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+       .cmd_rcgr = 0x068c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_uart1_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+       .cmd_rcgr = 0x070c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_uart2_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+       .cmd_rcgr = 0x078c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_uart3_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+       .cmd_rcgr = 0x080c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_uart4_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+       .cmd_rcgr = 0x088c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_uart5_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+       .cmd_rcgr = 0x090c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp1_uart6_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x09a0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup1_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+       .cmd_rcgr = 0x098c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup1_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0a20,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup2_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+       .cmd_rcgr = 0x0a0c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup2_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0aa0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup3_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+       .cmd_rcgr = 0x0a8c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup3_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0b20,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup4_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+       .cmd_rcgr = 0x0b0c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup4_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0ba0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup5_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+       .cmd_rcgr = 0x0b8c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup5_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0c20,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup6_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+       .cmd_rcgr = 0x0c0c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_qup6_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+       .cmd_rcgr = 0x09cc,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_uart1_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+       .cmd_rcgr = 0x0a4c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_uart2_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+       .cmd_rcgr = 0x0acc,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_uart3_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+       .cmd_rcgr = 0x0b4c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_uart4_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+       .cmd_rcgr = 0x0bcc,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_uart5_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+       .cmd_rcgr = 0x0c4c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "blsp2_uart6_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_gp1_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(100000000, P_GPLL0, 6, 0, 0),
+       F(200000000, P_GPLL0, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+       .cmd_rcgr = 0x1904,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gp1_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "gp1_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_gp2_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(100000000, P_GPLL0, 6, 0, 0),
+       F(200000000, P_GPLL0, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+       .cmd_rcgr = 0x1944,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gp2_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "gp2_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_gp3_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(100000000, P_GPLL0, 6, 0, 0),
+       F(200000000, P_GPLL0, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+       .cmd_rcgr = 0x1984,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gp3_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "gp3_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_pcie_0_aux_clk_src[] = {
+       F(1011000, P_XO, 1, 1, 19),
+       { }
+};
+
+static struct clk_rcg2 pcie_0_aux_clk_src = {
+       .cmd_rcgr = 0x1b00,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .freq_tbl = ftbl_pcie_0_aux_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "pcie_0_aux_clk_src",
+               .parent_names = (const char *[]) { "xo" },
+               .num_parents = 1,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_pcie_pipe_clk_src[] = {
+       F(125000000, P_XO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 pcie_0_pipe_clk_src = {
+       .cmd_rcgr = 0x1adc,
+       .hid_width = 5,
+       .freq_tbl = ftbl_pcie_pipe_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "pcie_0_pipe_clk_src",
+               .parent_names = (const char *[]) { "xo" },
+               .num_parents = 1,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_pcie_1_aux_clk_src[] = {
+       F(1011000, P_XO, 1, 1, 19),
+       { }
+};
+
+static struct clk_rcg2 pcie_1_aux_clk_src = {
+       .cmd_rcgr = 0x1b80,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .freq_tbl = ftbl_pcie_1_aux_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "pcie_1_aux_clk_src",
+               .parent_names = (const char *[]) { "xo" },
+               .num_parents = 1,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 pcie_1_pipe_clk_src = {
+       .cmd_rcgr = 0x1b5c,
+       .hid_width = 5,
+       .freq_tbl = ftbl_pcie_pipe_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "pcie_1_pipe_clk_src",
+               .parent_names = (const char *[]) { "xo" },
+               .num_parents = 1,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_pdm2_clk_src[] = {
+       F(60000000, P_GPLL0, 10, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+       .cmd_rcgr = 0x0cd0,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_pdm2_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "pdm2_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+       F(144000, P_XO, 16, 3, 25),
+       F(400000, P_XO, 12, 1, 4),
+       F(20000000, P_GPLL0, 15, 1, 2),
+       F(25000000, P_GPLL0, 12, 1, 2),
+       F(50000000, P_GPLL0, 12, 0, 0),
+       F(100000000, P_GPLL0, 6, 0, 0),
+       F(192000000, P_GPLL4, 2, 0, 0),
+       F(384000000, P_GPLL4, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+       .cmd_rcgr = 0x04d0,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll4_map,
+       .freq_tbl = ftbl_sdcc1_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "sdcc1_apps_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll4,
+               .num_parents = 3,
+               .ops = &clk_rcg2_floor_ops,
+       },
+};
+
+static struct freq_tbl ftbl_sdcc2_4_apps_clk_src[] = {
+       F(144000, P_XO, 16, 3, 25),
+       F(400000, P_XO, 12, 1, 4),
+       F(20000000, P_GPLL0, 15, 1, 2),
+       F(25000000, P_GPLL0, 12, 1, 2),
+       F(50000000, P_GPLL0, 12, 0, 0),
+       F(100000000, P_GPLL0, 6, 0, 0),
+       F(200000000, P_GPLL0, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+       .cmd_rcgr = 0x0510,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "sdcc2_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_floor_ops,
+       },
+};
+
+static struct clk_rcg2 sdcc3_apps_clk_src = {
+       .cmd_rcgr = 0x0550,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "sdcc3_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_floor_ops,
+       },
+};
+
+static struct clk_rcg2 sdcc4_apps_clk_src = {
+       .cmd_rcgr = 0x0590,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "sdcc4_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_floor_ops,
+       },
+};
+
+static struct freq_tbl ftbl_tsif_ref_clk_src[] = {
+       F(105500, P_XO, 1, 1, 182),
+       { }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+       .cmd_rcgr = 0x0d90,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .freq_tbl = ftbl_tsif_ref_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "tsif_ref_clk_src",
+               .parent_names = (const char *[]) { "xo" },
+               .num_parents = 1,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(60000000, P_GPLL0, 10, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+       .cmd_rcgr = 0x03e8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "usb30_mock_utmi_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+       F(1200000, P_XO, 16, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+       .cmd_rcgr = 0x1414,
+       .hid_width = 5,
+       .freq_tbl = ftbl_usb3_phy_aux_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "usb3_phy_aux_clk_src",
+               .parent_names = (const char *[]) { "xo" },
+               .num_parents = 1,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_usb_hs_system_clk_src[] = {
+       F(75000000, P_GPLL0, 8, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 usb_hs_system_clk_src = {
+       .cmd_rcgr = 0x0490,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_usb_hs_system_clk_src,
+       .clkr.hw.init = &(struct clk_init_data)
+       {
+               .name = "usb_hs_system_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+       .halt_reg = 0x05c4,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x1484,
+               .enable_mask = BIT(17),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+       .halt_reg = 0x0648,
+       .clkr = {
+               .enable_reg = 0x0648,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup1_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup1_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+       .halt_reg = 0x0644,
+       .clkr = {
+               .enable_reg = 0x0644,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup1_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup1_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+       .halt_reg = 0x06c8,
+       .clkr = {
+               .enable_reg = 0x06c8,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup2_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup2_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+       .halt_reg = 0x06c4,
+       .clkr = {
+               .enable_reg = 0x06c4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup2_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup2_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+       .halt_reg = 0x0748,
+       .clkr = {
+               .enable_reg = 0x0748,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup3_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup3_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+       .halt_reg = 0x0744,
+       .clkr = {
+               .enable_reg = 0x0744,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup3_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup3_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+       .halt_reg = 0x07c8,
+       .clkr = {
+               .enable_reg = 0x07c8,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup4_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup4_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+       .halt_reg = 0x07c4,
+       .clkr = {
+               .enable_reg = 0x07c4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup4_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup4_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+       .halt_reg = 0x0848,
+       .clkr = {
+               .enable_reg = 0x0848,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup5_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup5_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+       .halt_reg = 0x0844,
+       .clkr = {
+               .enable_reg = 0x0844,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup5_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup5_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+       .halt_reg = 0x08c8,
+       .clkr = {
+               .enable_reg = 0x08c8,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup6_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup6_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+       .halt_reg = 0x08c4,
+       .clkr = {
+               .enable_reg = 0x08c4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_qup6_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_qup6_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+       .halt_reg = 0x0684,
+       .clkr = {
+               .enable_reg = 0x0684,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_uart1_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_uart1_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+       .halt_reg = 0x0704,
+       .clkr = {
+               .enable_reg = 0x0704,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_uart2_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_uart2_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+       .halt_reg = 0x0784,
+       .clkr = {
+               .enable_reg = 0x0784,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_uart3_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_uart3_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+       .halt_reg = 0x0804,
+       .clkr = {
+               .enable_reg = 0x0804,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_uart4_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_uart4_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+       .halt_reg = 0x0884,
+       .clkr = {
+               .enable_reg = 0x0884,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_uart5_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_uart5_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+       .halt_reg = 0x0904,
+       .clkr = {
+               .enable_reg = 0x0904,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp1_uart6_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp1_uart6_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+       .halt_reg = 0x0944,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x1484,
+               .enable_mask = BIT(15),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+       .halt_reg = 0x0988,
+       .clkr = {
+               .enable_reg = 0x0988,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup1_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup1_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+       .halt_reg = 0x0984,
+       .clkr = {
+               .enable_reg = 0x0984,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup1_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup1_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+       .halt_reg = 0x0a08,
+       .clkr = {
+               .enable_reg = 0x0a08,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup2_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup2_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+       .halt_reg = 0x0a04,
+       .clkr = {
+               .enable_reg = 0x0a04,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup2_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup2_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+       .halt_reg = 0x0a88,
+       .clkr = {
+               .enable_reg = 0x0a88,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup3_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup3_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+       .halt_reg = 0x0a84,
+       .clkr = {
+               .enable_reg = 0x0a84,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup3_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup3_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+       .halt_reg = 0x0b08,
+       .clkr = {
+               .enable_reg = 0x0b08,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup4_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup4_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+       .halt_reg = 0x0b04,
+       .clkr = {
+               .enable_reg = 0x0b04,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup4_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup4_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+       .halt_reg = 0x0b88,
+       .clkr = {
+               .enable_reg = 0x0b88,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup5_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup5_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+       .halt_reg = 0x0b84,
+       .clkr = {
+               .enable_reg = 0x0b84,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup5_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup5_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+       .halt_reg = 0x0c08,
+       .clkr = {
+               .enable_reg = 0x0c08,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup6_i2c_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup6_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+       .halt_reg = 0x0c04,
+       .clkr = {
+               .enable_reg = 0x0c04,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_qup6_spi_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_qup6_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+       .halt_reg = 0x09c4,
+       .clkr = {
+               .enable_reg = 0x09c4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_uart1_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_uart1_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+       .halt_reg = 0x0a44,
+       .clkr = {
+               .enable_reg = 0x0a44,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_uart2_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_uart2_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+       .halt_reg = 0x0ac4,
+       .clkr = {
+               .enable_reg = 0x0ac4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_uart3_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_uart3_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+       .halt_reg = 0x0b44,
+       .clkr = {
+               .enable_reg = 0x0b44,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_uart4_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_uart4_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+       .halt_reg = 0x0bc4,
+       .clkr = {
+               .enable_reg = 0x0bc4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_uart5_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_uart5_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+       .halt_reg = 0x0c44,
+       .clkr = {
+               .enable_reg = 0x0c44,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_blsp2_uart6_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "blsp2_uart6_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+       .halt_reg = 0x1900,
+       .clkr = {
+               .enable_reg = 0x1900,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_gp1_clk",
+                       .parent_names = (const char *[]) {
+                               "gp1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+       .halt_reg = 0x1940,
+       .clkr = {
+               .enable_reg = 0x1940,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_gp2_clk",
+                       .parent_names = (const char *[]) {
+                               "gp2_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+       .halt_reg = 0x1980,
+       .clkr = {
+               .enable_reg = 0x1980,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_gp3_clk",
+                       .parent_names = (const char *[]) {
+                               "gp3_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+       .halt_reg = 0x1ad4,
+       .clkr = {
+               .enable_reg = 0x1ad4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_pcie_0_aux_clk",
+                       .parent_names = (const char *[]) {
+                               "pcie_0_aux_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+       .halt_reg = 0x1ad8,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0x1ad8,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_pcie_0_pipe_clk",
+                       .parent_names = (const char *[]) {
+                               "pcie_0_pipe_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+       .halt_reg = 0x1b54,
+       .clkr = {
+               .enable_reg = 0x1b54,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_pcie_1_aux_clk",
+                       .parent_names = (const char *[]) {
+                               "pcie_1_aux_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+       .halt_reg = 0x1b58,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0x1b58,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_pcie_1_pipe_clk",
+                       .parent_names = (const char *[]) {
+                               "pcie_1_pipe_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+       .halt_reg = 0x0ccc,
+       .clkr = {
+               .enable_reg = 0x0ccc,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_pdm2_clk",
+                       .parent_names = (const char *[]) {
+                               "pdm2_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+       .halt_reg = 0x04c4,
+       .clkr = {
+               .enable_reg = 0x04c4,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_sdcc1_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "sdcc1_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+       .halt_reg = 0x0504,
+       .clkr = {
+               .enable_reg = 0x0504,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_sdcc2_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "sdcc2_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc3_apps_clk = {
+       .halt_reg = 0x0544,
+       .clkr = {
+               .enable_reg = 0x0544,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_sdcc3_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "sdcc3_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+       .halt_reg = 0x0584,
+       .clkr = {
+               .enable_reg = 0x0584,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_sdcc4_apps_clk",
+                       .parent_names = (const char *[]) {
+                               "sdcc4_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sys_noc_ufs_axi_clk = {
+       .halt_reg = 0x1d7c,
+       .clkr = {
+               .enable_reg = 0x1d7c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_sys_noc_ufs_axi_clk",
+                       .parent_names = (const char *[]) {
+                               "ufs_axi_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+       .halt_reg = 0x03fc,
+       .clkr = {
+               .enable_reg = 0x03fc,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_sys_noc_usb3_axi_clk",
+                       .parent_names = (const char *[]) {
+                               "usb30_master_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_tsif_ref_clk = {
+       .halt_reg = 0x0d88,
+       .clkr = {
+               .enable_reg = 0x0d88,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_tsif_ref_clk",
+                       .parent_names = (const char *[]) {
+                               "tsif_ref_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+       .halt_reg = 0x1d48,
+       .clkr = {
+               .enable_reg = 0x1d48,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_ufs_axi_clk",
+                       .parent_names = (const char *[]) {
+                               "ufs_axi_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_ufs_rx_cfg_clk = {
+       .halt_reg = 0x1d54,
+       .clkr = {
+               .enable_reg = 0x1d54,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_ufs_rx_cfg_clk",
+                       .parent_names = (const char *[]) {
+                               "ufs_axi_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_ufs_tx_cfg_clk = {
+       .halt_reg = 0x1d50,
+       .clkr = {
+               .enable_reg = 0x1d50,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_ufs_tx_cfg_clk",
+                       .parent_names = (const char *[]) {
+                               "ufs_axi_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+       .halt_reg = 0x03c8,
+       .clkr = {
+               .enable_reg = 0x03c8,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_usb30_master_clk",
+                       .parent_names = (const char *[]) {
+                               "usb30_master_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+       .halt_reg = 0x03d0,
+       .clkr = {
+               .enable_reg = 0x03d0,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_usb30_mock_utmi_clk",
+                       .parent_names = (const char *[]) {
+                               "usb30_mock_utmi_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+       .halt_reg = 0x1408,
+       .clkr = {
+               .enable_reg = 0x1408,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_usb3_phy_aux_clk",
+                       .parent_names = (const char *[]) {
+                               "usb3_phy_aux_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb_hs_system_clk = {
+       .halt_reg = 0x0484,
+       .clkr = {
+               .enable_reg = 0x0484,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data)
+               {
+                       .name = "gcc_usb_hs_system_clk",
+                       .parent_names = (const char *[]) {
+                               "usb_hs_system_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_regmap *gcc_msm8994_clocks[] = {
+       [GPLL0_EARLY] = &gpll0_early.clkr,
+       [GPLL0] = &gpll0.clkr,
+       [GPLL4_EARLY] = &gpll4_early.clkr,
+       [GPLL4] = &gpll4.clkr,
+       [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+       [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+       [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+       [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+       [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+       [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+       [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+       [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+       [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+       [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+       [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr,
+       [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr,
+       [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr,
+       [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr,
+       [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+       [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+       [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+       [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+       [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+       [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+       [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+       [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+       [BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.clkr,
+       [BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.clkr,
+       [BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.clkr,
+       [BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.clkr,
+       [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+       [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+       [BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.clkr,
+       [BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.clkr,
+       [BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.clkr,
+       [BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr,
+       [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+       [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+       [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+       [PCIE_0_AUX_CLK_SRC] = &pcie_0_aux_clk_src.clkr,
+       [PCIE_0_PIPE_CLK_SRC] = &pcie_0_pipe_clk_src.clkr,
+       [PCIE_1_AUX_CLK_SRC] = &pcie_1_aux_clk_src.clkr,
+       [PCIE_1_PIPE_CLK_SRC] = &pcie_1_pipe_clk_src.clkr,
+       [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+       [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+       [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+       [SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr,
+       [SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
+       [TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
+       [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+       [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+       [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
+       [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+       [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+       [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+       [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+       [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+       [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+       [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
+       [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+       [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+       [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+       [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+       [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+       [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+       [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+       [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+       [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+       [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+       [GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.clkr,
+       [GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.clkr,
+       [GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.clkr,
+       [GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.clkr,
+       [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+       [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+       [GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.clkr,
+       [GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.clkr,
+       [GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.clkr,
+       [GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.clkr,
+       [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+       [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+       [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+       [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+       [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+       [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+       [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+       [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+       [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+       [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+       [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
+       [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+       [GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
+       [GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
+       [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
+       [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+       [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
+       [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
+       [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+       [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+       [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+       [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
+};
+
+static const struct regmap_config gcc_msm8994_regmap_config = {
+       .reg_bits       = 32,
+       .reg_stride     = 4,
+       .val_bits       = 32,
+       .max_register   = 0x2000,
+       .fast_io        = true,
+};
+
+static const struct qcom_cc_desc gcc_msm8994_desc = {
+       .config = &gcc_msm8994_regmap_config,
+       .clks = gcc_msm8994_clocks,
+       .num_clks = ARRAY_SIZE(gcc_msm8994_clocks),
+};
+
+static const struct of_device_id gcc_msm8994_match_table[] = {
+       { .compatible = "qcom,gcc-msm8994" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8994_match_table);
+
+static int gcc_msm8994_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct clk *clk;
+
+       clk = devm_clk_register(dev, &xo.hw);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       return qcom_cc_probe(pdev, &gcc_msm8994_desc);
+}
+
+static struct platform_driver gcc_msm8994_driver = {
+       .probe          = gcc_msm8994_probe,
+       .driver         = {
+               .name   = "gcc-msm8994",
+               .of_match_table = gcc_msm8994_match_table,
+       },
+};
+
+static int __init gcc_msm8994_init(void)
+{
+       return platform_driver_register(&gcc_msm8994_driver);
+}
+core_initcall(gcc_msm8994_init);
+
+static void __exit gcc_msm8994_exit(void)
+{
+       platform_driver_unregister(&gcc_msm8994_driver);
+}
+module_exit(gcc_msm8994_exit);
+
+MODULE_DESCRIPTION("Qualcomm GCC MSM8994 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8994");
index fe03e6fbc7df590d9d354891a5aa05d686d59fd7..4b1fc1730d295f0b843cb5cd50de223371dbbb4c 100644 (file)
@@ -460,14 +460,22 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
                .name = "sdcc1_apps_clk_src",
                .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
                .num_parents = 4,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
+static struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(150000000, P_GPLL0, 4, 0, 0),
+       F(300000000, P_GPLL0, 2, 0, 0),
+       { }
+};
+
 static struct clk_rcg2 sdcc1_ice_core_clk_src = {
        .cmd_rcgr = 0x13024,
        .hid_width = 5,
        .parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map,
+       .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "sdcc1_ice_core_clk_src",
                .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
@@ -497,7 +505,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
                .name = "sdcc2_apps_clk_src",
                .parent_names = gcc_xo_gpll0_gpll4,
                .num_parents = 3,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -511,7 +519,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
                .name = "sdcc3_apps_clk_src",
                .parent_names = gcc_xo_gpll0_gpll4,
                .num_parents = 3,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -535,7 +543,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
                .name = "sdcc4_apps_clk_src",
                .parent_names = gcc_xo_gpll0,
                .num_parents = 2,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -1230,10 +1238,18 @@ static struct clk_rcg2 ufs_axi_clk_src = {
        },
 };
 
+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(150000000, P_GPLL0, 4, 0, 0),
+       F(300000000, P_GPLL0, 2, 0, 0),
+       { }
+};
+
 static struct clk_rcg2 ufs_ice_core_clk_src = {
        .cmd_rcgr = 0x76014,
        .hid_width = 5,
        .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_ufs_ice_core_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "ufs_ice_core_clk_src",
                .parent_names = gcc_xo_gpll0,
@@ -1242,10 +1258,19 @@ static struct clk_rcg2 ufs_ice_core_clk_src = {
        },
 };
 
+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+       F(75000000, P_GPLL0, 8, 0, 0),
+       F(150000000, P_GPLL0, 4, 0, 0),
+       F(256000000, P_GPLL4, 1.5, 0, 0),
+       F(300000000, P_GPLL0, 2, 0, 0),
+       { }
+};
+
 static struct clk_rcg2 qspi_ser_clk_src = {
        .cmd_rcgr = 0x8b00c,
        .hid_width = 5,
        .parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map,
+       .freq_tbl = ftbl_qspi_ser_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "qspi_ser_clk_src",
                .parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div,
index f12d7b2bddd7061495bcd04a12f76245ed2721d1..288186cce0ae420d499cf995636320bb0a9203d5 100644 (file)
@@ -30,6 +30,7 @@
 #define SW_OVERRIDE_MASK       BIT(2)
 #define HW_CONTROL_MASK                BIT(1)
 #define SW_COLLAPSE_MASK       BIT(0)
+#define GMEM_CLAMP_IO_MASK     BIT(0)
 
 /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
 #define EN_REST_WAIT_VAL       (0x2 << 20)
@@ -55,6 +56,13 @@ static int gdsc_is_enabled(struct gdsc *sc, unsigned int reg)
        return !!(val & PWR_ON_MASK);
 }
 
+static int gdsc_hwctrl(struct gdsc *sc, bool en)
+{
+       u32 val = en ? HW_CONTROL_MASK : 0;
+
+       return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
+}
+
 static int gdsc_toggle_logic(struct gdsc *sc, bool en)
 {
        int ret;
@@ -140,6 +148,18 @@ static inline void gdsc_clear_mem_on(struct gdsc *sc)
                regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
 }
 
+static inline void gdsc_deassert_clamp_io(struct gdsc *sc)
+{
+       regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
+                          GMEM_CLAMP_IO_MASK, 0);
+}
+
+static inline void gdsc_assert_clamp_io(struct gdsc *sc)
+{
+       regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
+                          GMEM_CLAMP_IO_MASK, 1);
+}
+
 static int gdsc_enable(struct generic_pm_domain *domain)
 {
        struct gdsc *sc = domain_to_gdsc(domain);
@@ -148,6 +168,9 @@ static int gdsc_enable(struct generic_pm_domain *domain)
        if (sc->pwrsts == PWRSTS_ON)
                return gdsc_deassert_reset(sc);
 
+       if (sc->flags & CLAMP_IO)
+               gdsc_deassert_clamp_io(sc);
+
        ret = gdsc_toggle_logic(sc, true);
        if (ret)
                return ret;
@@ -164,20 +187,39 @@ static int gdsc_enable(struct generic_pm_domain *domain)
         */
        udelay(1);
 
+       /* Turn on HW trigger mode if supported */
+       if (sc->flags & HW_CTRL)
+               return gdsc_hwctrl(sc, true);
+
        return 0;
 }
 
 static int gdsc_disable(struct generic_pm_domain *domain)
 {
        struct gdsc *sc = domain_to_gdsc(domain);
+       int ret;
 
        if (sc->pwrsts == PWRSTS_ON)
                return gdsc_assert_reset(sc);
 
+       /* Turn off HW trigger mode if supported */
+       if (sc->flags & HW_CTRL) {
+               ret = gdsc_hwctrl(sc, false);
+               if (ret < 0)
+                       return ret;
+       }
+
        if (sc->pwrsts & PWRSTS_OFF)
                gdsc_clear_mem_on(sc);
 
-       return gdsc_toggle_logic(sc, false);
+       ret = gdsc_toggle_logic(sc, false);
+       if (ret)
+               return ret;
+
+       if (sc->flags & CLAMP_IO)
+               gdsc_assert_clamp_io(sc);
+
+       return 0;
 }
 
 static int gdsc_init(struct gdsc *sc)
index 3bf497c36bdf83b205733fb0201e33e7b103f61d..39648348e5ec9afa02501e3e1f1c32d2802a78b8 100644 (file)
@@ -39,6 +39,7 @@ struct gdsc {
        struct regmap                   *regmap;
        unsigned int                    gdscr;
        unsigned int                    gds_hw_ctrl;
+       unsigned int                    clamp_io_ctrl;
        unsigned int                    *cxcs;
        unsigned int                    cxc_count;
        const u8                        pwrsts;
@@ -50,6 +51,8 @@ struct gdsc {
 #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
        const u8                        flags;
 #define VOTABLE                BIT(0)
+#define CLAMP_IO       BIT(1)
+#define HW_CTRL                BIT(2)
        struct reset_controller_dev     *rcdev;
        unsigned int                    *resets;
        unsigned int                    reset_count;
index db3998e5e2d83d77a5b07f8d1e29490b2e532f6d..977e98eadbeb1293a412a75f930fd9887232ea8f 100644 (file)
@@ -443,7 +443,7 @@ static int lcc_ipq806x_probe(struct platform_device *pdev)
                return PTR_ERR(regmap);
 
        /* Configure the rate of PLL4 if the bootloader hasn't already */
-       val = regmap_read(regmap, 0x0, &val);
+       regmap_read(regmap, 0x0, &val);
        if (!val)
                clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
        /* Enable PLL4 source on the LPASS Primary PLL Mux */
index ca97e11517976cbe81e895f8586d540283441591..9b97246287a7305f6b54ff9e4809fda1e748abc7 100644 (file)
@@ -2945,6 +2945,7 @@ static struct gdsc venus_core0_gdsc = {
                .name = "venus_core0",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = HW_CTRL,
 };
 
 static struct gdsc venus_core1_gdsc = {
@@ -2955,6 +2956,7 @@ static struct gdsc venus_core1_gdsc = {
                .name = "venus_core1",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = HW_CTRL,
 };
 
 static struct gdsc camss_gdsc = {
@@ -3034,6 +3036,28 @@ static struct gdsc mdss_gdsc = {
        .pwrsts = PWRSTS_OFF_ON,
 };
 
+static struct gdsc gpu_gdsc = {
+       .gdscr = 0x4034,
+       .gds_hw_ctrl = 0x4038,
+       .pd = {
+               .name = "gpu",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
+};
+
+static struct gdsc gpu_gx_gdsc = {
+       .gdscr = 0x4024,
+       .clamp_io_ctrl = 0x4300,
+       .cxcs = (unsigned int []){ 0x4028 },
+       .cxc_count = 1,
+       .pd = {
+               .name = "gpu_gx",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = CLAMP_IO,
+};
+
 static struct clk_regmap *mmcc_msm8996_clocks[] = {
        [MMPLL0_EARLY] = &mmpll0_early.clkr,
        [MMPLL0_PLL] = &mmpll0.clkr,
@@ -3223,6 +3247,8 @@ static struct gdsc *mmcc_msm8996_gdscs[] = {
        [CPP_GDSC] = &cpp_gdsc,
        [FD_GDSC] = &fd_gdsc,
        [MDSS_GDSC] = &mdss_gdsc,
+       [GPU_GDSC] = &gpu_gdsc,
+       [GPU_GX_GDSC] = &gpu_gx_gdsc,
 };
 
 static const struct qcom_reset_map mmcc_msm8996_resets[] = {
index 41a12d376799ae8c4b358f5f0cc3e5846b98cfcf..2586dfa0026bb015a1a0e81d3b60a1eff7e5a785 100644 (file)
@@ -1,5 +1,7 @@
 config CLK_RENESAS_CPG_MSSR
        bool
+       default y if ARCH_R8A7743
+       default y if ARCH_R8A7745
        default y if ARCH_R8A7795
        default y if ARCH_R8A7796
 
index 90dd0db7d9c6ef7c328c1ff981872d7e24623d84..1072f7653c0c5e701b15c678b8a7dd550b40dba1 100644 (file)
@@ -2,6 +2,8 @@ obj-$(CONFIG_ARCH_EMEV2)                += clk-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)            += clk-rz.o
 obj-$(CONFIG_ARCH_R8A73A4)             += clk-r8a73a4.o clk-div6.o
 obj-$(CONFIG_ARCH_R8A7740)             += clk-r8a7740.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7743)             += r8a7743-cpg-mssr.o rcar-gen2-cpg.o
+obj-$(CONFIG_ARCH_R8A7745)             += r8a7745-cpg-mssr.o rcar-gen2-cpg.o
 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
index 40e3a501a50e200ff68e41710ad9fcecaf695327..886a8380e91247a199f2852177b9fda5cff8f0ad 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/clk/renesas.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 struct r8a7778_cpg {
        struct clk_onecell_data data;
@@ -83,6 +84,18 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
        struct clk **clks;
        unsigned int i;
        int num_clks;
+       u32 mode;
+
+       if (rcar_rst_read_mode_pins(&mode))
+               return;
+
+       BUG_ON(!(mode & BIT(19)));
+
+       cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
+                        (!!(mode & BIT(12)) << 1) |
+                        (!!(mode & BIT(11)));
+       cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
+                       (!!(mode & BIT(1)));
 
        num_clks = of_property_count_strings(np, "clock-output-names");
        if (num_clks < 0) {
@@ -130,16 +143,3 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
 
 CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
               r8a7778_cpg_clocks_init);
-
-void __init r8a7778_clocks_init(u32 mode)
-{
-       BUG_ON(!(mode & BIT(19)));
-
-       cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
-                        (!!(mode & BIT(12)) << 1) |
-                        (!!(mode & BIT(11)));
-       cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
-                       (!!(mode & BIT(1)));
-
-       of_clk_init(NULL);
-}
index cf2a37df03b15e60ee70e44ce21fcc8f5341680c..27fbfafaf2cd035327ed50ea86479fae0f4a4c23 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a7779-clock.h>
 
@@ -88,8 +89,6 @@ static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 };
  * Initialization
  */
 
-static u32 cpg_mode __initdata;
-
 static struct clk * __init
 r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg,
                           const struct cpg_clk_config *config,
@@ -127,6 +126,10 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
        struct clk **clks;
        unsigned int i, plla_mult;
        int num_clks;
+       u32 mode;
+
+       if (rcar_rst_read_mode_pins(&mode))
+               return;
 
        num_clks = of_property_count_strings(np, "clock-output-names");
        if (num_clks < 0) {
@@ -148,8 +151,8 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
        cpg->data.clks = clks;
        cpg->data.clk_num = num_clks;
 
-       config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)];
-       plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)];
+       config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(mode)];
+       plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(mode)];
 
        for (i = 0; i < num_clks; ++i) {
                const char *name;
@@ -173,10 +176,3 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
 }
 CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
               r8a7779_cpg_clocks_init);
-
-void __init r8a7779_clocks_init(u32 mode)
-{
-       cpg_mode = mode;
-
-       of_clk_init(NULL);
-}
index 00e6aba4b9c095960e7bd635d62eefdd33033da5..f39519edc645ca87887f30a259aab9b9de6d5991 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 struct rcar_gen2_cpg {
        struct clk_onecell_data data;
@@ -364,6 +365,23 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
                                                 4, 0, table, &cpg->lock);
 }
 
+/*
+ * Reset register definitions.
+ */
+#define MODEMR 0xe6160060
+
+static u32 __init rcar_gen2_read_mode_pins(void)
+{
+       void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+       u32 mode;
+
+       BUG_ON(!modemr);
+       mode = ioread32(modemr);
+       iounmap(modemr);
+
+       return mode;
+}
+
 static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
 {
        const struct cpg_pll_config *config;
@@ -372,6 +390,13 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
        unsigned int i;
        int num_clks;
 
+       if (rcar_rst_read_mode_pins(&cpg_mode)) {
+               /* Backward-compatibility with old DT */
+               pr_warn("%s: failed to obtain mode pins from RST\n",
+                       np->full_name);
+               cpg_mode = rcar_gen2_read_mode_pins();
+       }
+
        num_clks = of_property_count_strings(np, "clock-output-names");
        if (num_clks < 0) {
                pr_err("%s: failed to count clocks\n", __func__);
@@ -420,10 +445,3 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
 }
 CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks",
               rcar_gen2_cpg_clocks_init);
-
-void __init rcar_gen2_clocks_init(u32 mode)
-{
-       cpg_mode = mode;
-
-       of_clk_init(NULL);
-}
diff --git a/drivers/clk/renesas/r8a7743-cpg-mssr.c b/drivers/clk/renesas/r8a7743-cpg-mssr.c
new file mode 100644 (file)
index 0000000..6dc0b30
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * r8a7743 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7743-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A7743_CLK_OSC,
+
+       /* External Input Clocks */
+       CLK_EXTAL,
+       CLK_USB_EXTAL,
+
+       /* Internal Core Clocks */
+       CLK_MAIN,
+       CLK_PLL0,
+       CLK_PLL1,
+       CLK_PLL3,
+       CLK_PLL1_DIV2,
+
+       /* Module Clocks */
+       MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7743_core_clks[] __initconst = {
+       /* External Clock Inputs */
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("usb_extal",  CLK_USB_EXTAL),
+
+       /* Internal Core Clocks */
+       DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+       DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+       DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+       DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+       /* Core Clock Outputs */
+       DEF_BASE("z",    R8A7743_CLK_Z,    CLK_TYPE_GEN2_Z,     CLK_PLL0),
+       DEF_BASE("lb",   R8A7743_CLK_LB,   CLK_TYPE_GEN2_LB,    CLK_PLL1),
+       DEF_BASE("sdh",  R8A7743_CLK_SDH,  CLK_TYPE_GEN2_SDH,   CLK_PLL1),
+       DEF_BASE("sd0",  R8A7743_CLK_SD0,  CLK_TYPE_GEN2_SD0,   CLK_PLL1),
+       DEF_BASE("qspi", R8A7743_CLK_QSPI, CLK_TYPE_GEN2_QSPI,  CLK_PLL1_DIV2),
+       DEF_BASE("rcan", R8A7743_CLK_RCAN, CLK_TYPE_GEN2_RCAN,  CLK_USB_EXTAL),
+
+       DEF_FIXED("zg",    R8A7743_CLK_ZG,      CLK_PLL1,           3, 1),
+       DEF_FIXED("zx",    R8A7743_CLK_ZX,      CLK_PLL1,           3, 1),
+       DEF_FIXED("zs",    R8A7743_CLK_ZS,      CLK_PLL1,           6, 1),
+       DEF_FIXED("hp",    R8A7743_CLK_HP,      CLK_PLL1,          12, 1),
+       DEF_FIXED("b",     R8A7743_CLK_B,       CLK_PLL1,          12, 1),
+       DEF_FIXED("p",     R8A7743_CLK_P,       CLK_PLL1,          24, 1),
+       DEF_FIXED("cl",    R8A7743_CLK_CL,      CLK_PLL1,          48, 1),
+       DEF_FIXED("m2",    R8A7743_CLK_M2,      CLK_PLL1,           8, 1),
+       DEF_FIXED("zb3",   R8A7743_CLK_ZB3,     CLK_PLL3,           4, 1),
+       DEF_FIXED("zb3d2", R8A7743_CLK_ZB3D2,   CLK_PLL3,           8, 1),
+       DEF_FIXED("ddr",   R8A7743_CLK_DDR,     CLK_PLL3,           8, 1),
+       DEF_FIXED("mp",    R8A7743_CLK_MP,      CLK_PLL1_DIV2,     15, 1),
+       DEF_FIXED("cp",    R8A7743_CLK_CP,      CLK_EXTAL,          2, 1),
+       DEF_FIXED("r",     R8A7743_CLK_R,       CLK_PLL1,       49152, 1),
+       DEF_FIXED("osc",   R8A7743_CLK_OSC,     CLK_PLL1,       12288, 1),
+
+       DEF_DIV6P1("sd2",  R8A7743_CLK_SD2,     CLK_PLL1_DIV2,  0x078),
+       DEF_DIV6P1("sd3",  R8A7743_CLK_SD3,     CLK_PLL1_DIV2,  0x26c),
+       DEF_DIV6P1("mmc0", R8A7743_CLK_MMC0,    CLK_PLL1_DIV2,  0x240),
+};
+
+static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
+       DEF_MOD("msiof0",                  0,   R8A7743_CLK_MP),
+       DEF_MOD("vcp0",                  101,   R8A7743_CLK_ZS),
+       DEF_MOD("vpc0",                  103,   R8A7743_CLK_ZS),
+       DEF_MOD("tmu1",                  111,   R8A7743_CLK_P),
+       DEF_MOD("3dg",                   112,   R8A7743_CLK_ZG),
+       DEF_MOD("2d-dmac",               115,   R8A7743_CLK_ZS),
+       DEF_MOD("fdp1-1",                118,   R8A7743_CLK_ZS),
+       DEF_MOD("fdp1-0",                119,   R8A7743_CLK_ZS),
+       DEF_MOD("tmu3",                  121,   R8A7743_CLK_P),
+       DEF_MOD("tmu2",                  122,   R8A7743_CLK_P),
+       DEF_MOD("cmt0",                  124,   R8A7743_CLK_R),
+       DEF_MOD("tmu0",                  125,   R8A7743_CLK_CP),
+       DEF_MOD("vsp1du1",               127,   R8A7743_CLK_ZS),
+       DEF_MOD("vsp1du0",               128,   R8A7743_CLK_ZS),
+       DEF_MOD("vsp1-sy",               131,   R8A7743_CLK_ZS),
+       DEF_MOD("scifa2",                202,   R8A7743_CLK_MP),
+       DEF_MOD("scifa1",                203,   R8A7743_CLK_MP),
+       DEF_MOD("scifa0",                204,   R8A7743_CLK_MP),
+       DEF_MOD("msiof2",                205,   R8A7743_CLK_MP),
+       DEF_MOD("scifb0",                206,   R8A7743_CLK_MP),
+       DEF_MOD("scifb1",                207,   R8A7743_CLK_MP),
+       DEF_MOD("msiof1",                208,   R8A7743_CLK_MP),
+       DEF_MOD("scifb2",                216,   R8A7743_CLK_MP),
+       DEF_MOD("sys-dmac1",             218,   R8A7743_CLK_ZS),
+       DEF_MOD("sys-dmac0",             219,   R8A7743_CLK_ZS),
+       DEF_MOD("tpu0",                  304,   R8A7743_CLK_CP),
+       DEF_MOD("sdhi3",                 311,   R8A7743_CLK_SD3),
+       DEF_MOD("sdhi2",                 312,   R8A7743_CLK_SD2),
+       DEF_MOD("sdhi0",                 314,   R8A7743_CLK_SD0),
+       DEF_MOD("mmcif0",                315,   R8A7743_CLK_MMC0),
+       DEF_MOD("iic0",                  318,   R8A7743_CLK_HP),
+       DEF_MOD("pciec",                 319,   R8A7743_CLK_MP),
+       DEF_MOD("iic1",                  323,   R8A7743_CLK_HP),
+       DEF_MOD("usb3.0",                328,   R8A7743_CLK_MP),
+       DEF_MOD("cmt1",                  329,   R8A7743_CLK_R),
+       DEF_MOD("usbhs-dmac0",           330,   R8A7743_CLK_HP),
+       DEF_MOD("usbhs-dmac1",           331,   R8A7743_CLK_HP),
+       DEF_MOD("irqc",                  407,   R8A7743_CLK_CP),
+       DEF_MOD("intc-sys",              408,   R8A7743_CLK_ZS),
+       DEF_MOD("audio-dmac1",           501,   R8A7743_CLK_HP),
+       DEF_MOD("audio-dmac0",           502,   R8A7743_CLK_HP),
+       DEF_MOD("thermal",               522,   CLK_EXTAL),
+       DEF_MOD("pwm",                   523,   R8A7743_CLK_P),
+       DEF_MOD("usb-ehci",              703,   R8A7743_CLK_MP),
+       DEF_MOD("usbhs",                 704,   R8A7743_CLK_HP),
+       DEF_MOD("hscif2",                713,   R8A7743_CLK_ZS),
+       DEF_MOD("scif5",                 714,   R8A7743_CLK_P),
+       DEF_MOD("scif4",                 715,   R8A7743_CLK_P),
+       DEF_MOD("hscif1",                716,   R8A7743_CLK_ZS),
+       DEF_MOD("hscif0",                717,   R8A7743_CLK_ZS),
+       DEF_MOD("scif3",                 718,   R8A7743_CLK_P),
+       DEF_MOD("scif2",                 719,   R8A7743_CLK_P),
+       DEF_MOD("scif1",                 720,   R8A7743_CLK_P),
+       DEF_MOD("scif0",                 721,   R8A7743_CLK_P),
+       DEF_MOD("du1",                   723,   R8A7743_CLK_ZX),
+       DEF_MOD("du0",                   724,   R8A7743_CLK_ZX),
+       DEF_MOD("lvds0",                 726,   R8A7743_CLK_ZX),
+       DEF_MOD("ipmmu-sgx",             800,   R8A7743_CLK_ZX),
+       DEF_MOD("vin2",                  809,   R8A7743_CLK_ZG),
+       DEF_MOD("vin1",                  810,   R8A7743_CLK_ZG),
+       DEF_MOD("vin0",                  811,   R8A7743_CLK_ZG),
+       DEF_MOD("etheravb",              812,   R8A7743_CLK_HP),
+       DEF_MOD("ether",                 813,   R8A7743_CLK_P),
+       DEF_MOD("sata1",                 814,   R8A7743_CLK_ZS),
+       DEF_MOD("sata0",                 815,   R8A7743_CLK_ZS),
+       DEF_MOD("gpio7",                 904,   R8A7743_CLK_CP),
+       DEF_MOD("gpio6",                 905,   R8A7743_CLK_CP),
+       DEF_MOD("gpio5",                 907,   R8A7743_CLK_CP),
+       DEF_MOD("gpio4",                 908,   R8A7743_CLK_CP),
+       DEF_MOD("gpio3",                 909,   R8A7743_CLK_CP),
+       DEF_MOD("gpio2",                 910,   R8A7743_CLK_CP),
+       DEF_MOD("gpio1",                 911,   R8A7743_CLK_CP),
+       DEF_MOD("gpio0",                 912,   R8A7743_CLK_CP),
+       DEF_MOD("can1",                  915,   R8A7743_CLK_P),
+       DEF_MOD("can0",                  916,   R8A7743_CLK_P),
+       DEF_MOD("qspi_mod",              917,   R8A7743_CLK_QSPI),
+       DEF_MOD("i2c5",                  925,   R8A7743_CLK_HP),
+       DEF_MOD("iicdvfs",               926,   R8A7743_CLK_CP),
+       DEF_MOD("i2c4",                  927,   R8A7743_CLK_HP),
+       DEF_MOD("i2c3",                  928,   R8A7743_CLK_HP),
+       DEF_MOD("i2c2",                  929,   R8A7743_CLK_HP),
+       DEF_MOD("i2c1",                  930,   R8A7743_CLK_HP),
+       DEF_MOD("i2c0",                  931,   R8A7743_CLK_HP),
+       DEF_MOD("ssi-all",              1005,   R8A7743_CLK_P),
+       DEF_MOD("ssi9",                 1006,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi8",                 1007,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi7",                 1008,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi6",                 1009,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi5",                 1010,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi4",                 1011,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi3",                 1012,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi2",                 1013,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi1",                 1014,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi0",                 1015,   MOD_CLK_ID(1005)),
+       DEF_MOD("scu-all",              1017,   R8A7743_CLK_P),
+       DEF_MOD("scu-dvc1",             1018,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-dvc0",             1019,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-ctu1-mix1",        1020,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-ctu0-mix0",        1021,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src9",             1022,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src8",             1023,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src7",             1024,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src6",             1025,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src5",             1026,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src4",             1027,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src3",             1028,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src2",             1029,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src1",             1030,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src0",             1031,   MOD_CLK_ID(1017)),
+       DEF_MOD("scifa3",               1106,   R8A7743_CLK_MP),
+       DEF_MOD("scifa4",               1107,   R8A7743_CLK_MP),
+       DEF_MOD("scifa5",               1108,   R8A7743_CLK_MP),
+};
+
+static const unsigned int r8a7743_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *    MD       EXTAL           PLL0    PLL1    PLL3
+ * 14 13 19    (MHz)           *1      *1
+ *---------------------------------------------------
+ * 0  0  0     15              x172/2  x208/2  x106
+ * 0  0  1     15              x172/2  x208/2  x88
+ * 0  1  0     20              x130/2  x156/2  x80
+ * 0  1  1     20              x130/2  x156/2  x66
+ * 1  0  0     26 / 2          x200/2  x240/2  x122
+ * 1  0  1     26 / 2          x200/2  x240/2  x102
+ * 1  1  0     30 / 2          x172/2  x208/2  x106
+ * 1  1  1     30 / 2          x172/2  x208/2  x88
+ *
+ * *1 :        Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 12) | \
+                                        (((md) & BIT(13)) >> 12) | \
+                                        (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+       /* EXTAL div    PLL1 mult       PLL3 mult */
+       { 1,            208,            106,    },
+       { 1,            208,            88,     },
+       { 1,            156,            80,     },
+       { 1,            156,            66,     },
+       { 2,            240,            122,    },
+       { 2,            240,            102,    },
+       { 2,            208,            106,    },
+       { 2,            208,            88,     },
+};
+
+static int __init r8a7743_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
+
+       cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+       return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7743_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks = r8a7743_core_clks,
+       .num_core_clks = ARRAY_SIZE(r8a7743_core_clks),
+       .last_dt_core_clk = LAST_DT_CORE_CLK,
+       .num_total_core_clks = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks = r8a7743_mod_clks,
+       .num_mod_clks = ARRAY_SIZE(r8a7743_mod_clks),
+       .num_hw_mod_clks = 12 * 32,
+
+       /* Critical Module Clocks */
+       .crit_mod_clks = r8a7743_crit_mod_clks,
+       .num_crit_mod_clks = ARRAY_SIZE(r8a7743_crit_mod_clks),
+
+       /* Callbacks */
+       .init = r8a7743_cpg_mssr_init,
+       .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c
new file mode 100644 (file)
index 0000000..2f15ba7
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * r8a7745 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7745-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A7745_CLK_OSC,
+
+       /* External Input Clocks */
+       CLK_EXTAL,
+       CLK_USB_EXTAL,
+
+       /* Internal Core Clocks */
+       CLK_MAIN,
+       CLK_PLL0,
+       CLK_PLL1,
+       CLK_PLL3,
+       CLK_PLL1_DIV2,
+
+       /* Module Clocks */
+       MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7745_core_clks[] __initconst = {
+       /* External Clock Inputs */
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("usb_extal",  CLK_USB_EXTAL),
+
+       /* Internal Core Clocks */
+       DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+       DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+       DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+       DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+       /* Core Clock Outputs */
+       DEF_BASE("lb",   R8A7745_CLK_LB,   CLK_TYPE_GEN2_LB,    CLK_PLL1),
+       DEF_BASE("sdh",  R8A7745_CLK_SDH,  CLK_TYPE_GEN2_SDH,   CLK_PLL1),
+       DEF_BASE("sd0",  R8A7745_CLK_SD0,  CLK_TYPE_GEN2_SD0,   CLK_PLL1),
+       DEF_BASE("qspi", R8A7745_CLK_QSPI, CLK_TYPE_GEN2_QSPI,  CLK_PLL1_DIV2),
+       DEF_BASE("rcan", R8A7745_CLK_RCAN, CLK_TYPE_GEN2_RCAN,  CLK_USB_EXTAL),
+
+       DEF_FIXED("z2",    R8A7745_CLK_Z2,      CLK_PLL0,           1, 1),
+       DEF_FIXED("zg",    R8A7745_CLK_ZG,      CLK_PLL1,           6, 1),
+       DEF_FIXED("zx",    R8A7745_CLK_ZX,      CLK_PLL1,           3, 1),
+       DEF_FIXED("zs",    R8A7745_CLK_ZS,      CLK_PLL1,           6, 1),
+       DEF_FIXED("hp",    R8A7745_CLK_HP,      CLK_PLL1,          12, 1),
+       DEF_FIXED("b",     R8A7745_CLK_B,       CLK_PLL1,          12, 1),
+       DEF_FIXED("p",     R8A7745_CLK_P,       CLK_PLL1,          24, 1),
+       DEF_FIXED("cl",    R8A7745_CLK_CL,      CLK_PLL1,          48, 1),
+       DEF_FIXED("cp",    R8A7745_CLK_CP,      CLK_PLL1,          48, 1),
+       DEF_FIXED("m2",    R8A7745_CLK_M2,      CLK_PLL1,           8, 1),
+       DEF_FIXED("zb3",   R8A7745_CLK_ZB3,     CLK_PLL3,           4, 1),
+       DEF_FIXED("zb3d2", R8A7745_CLK_ZB3D2,   CLK_PLL3,           8, 1),
+       DEF_FIXED("ddr",   R8A7745_CLK_DDR,     CLK_PLL3,           8, 1),
+       DEF_FIXED("mp",    R8A7745_CLK_MP,      CLK_PLL1_DIV2,     15, 1),
+       DEF_FIXED("cpex",  R8A7745_CLK_CPEX,    CLK_EXTAL,          2, 1),
+       DEF_FIXED("r",     R8A7745_CLK_R,       CLK_PLL1,       49152, 1),
+       DEF_FIXED("osc",   R8A7745_CLK_OSC,     CLK_PLL1,       12288, 1),
+
+       DEF_DIV6P1("sd2",  R8A7745_CLK_SD2,     CLK_PLL1_DIV2,  0x078),
+       DEF_DIV6P1("sd3",  R8A7745_CLK_SD3,     CLK_PLL1_DIV2,  0x26c),
+       DEF_DIV6P1("mmc0", R8A7745_CLK_MMC0,    CLK_PLL1_DIV2,  0x240),
+};
+
+static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
+       DEF_MOD("msiof0",                  0,   R8A7745_CLK_MP),
+       DEF_MOD("vcp0",                  101,   R8A7745_CLK_ZS),
+       DEF_MOD("vpc0",                  103,   R8A7745_CLK_ZS),
+       DEF_MOD("tmu1",                  111,   R8A7745_CLK_P),
+       DEF_MOD("3dg",                   112,   R8A7745_CLK_ZG),
+       DEF_MOD("2d-dmac",               115,   R8A7745_CLK_ZS),
+       DEF_MOD("fdp1-0",                119,   R8A7745_CLK_ZS),
+       DEF_MOD("tmu3",                  121,   R8A7745_CLK_P),
+       DEF_MOD("tmu2",                  122,   R8A7745_CLK_P),
+       DEF_MOD("cmt0",                  124,   R8A7745_CLK_R),
+       DEF_MOD("tmu0",                  125,   R8A7745_CLK_CP),
+       DEF_MOD("vsp1du0",               128,   R8A7745_CLK_ZS),
+       DEF_MOD("vsp1-sy",               131,   R8A7745_CLK_ZS),
+       DEF_MOD("scifa2",                202,   R8A7745_CLK_MP),
+       DEF_MOD("scifa1",                203,   R8A7745_CLK_MP),
+       DEF_MOD("scifa0",                204,   R8A7745_CLK_MP),
+       DEF_MOD("msiof2",                205,   R8A7745_CLK_MP),
+       DEF_MOD("scifb0",                206,   R8A7745_CLK_MP),
+       DEF_MOD("scifb1",                207,   R8A7745_CLK_MP),
+       DEF_MOD("msiof1",                208,   R8A7745_CLK_MP),
+       DEF_MOD("scifb2",                216,   R8A7745_CLK_MP),
+       DEF_MOD("sys-dmac1",             218,   R8A7745_CLK_ZS),
+       DEF_MOD("sys-dmac0",             219,   R8A7745_CLK_ZS),
+       DEF_MOD("tpu0",                  304,   R8A7745_CLK_CP),
+       DEF_MOD("sdhi3",                 311,   R8A7745_CLK_SD3),
+       DEF_MOD("sdhi2",                 312,   R8A7745_CLK_SD2),
+       DEF_MOD("sdhi0",                 314,   R8A7745_CLK_SD0),
+       DEF_MOD("mmcif0",                315,   R8A7745_CLK_MMC0),
+       DEF_MOD("iic0",                  318,   R8A7745_CLK_HP),
+       DEF_MOD("iic1",                  323,   R8A7745_CLK_HP),
+       DEF_MOD("cmt1",                  329,   R8A7745_CLK_R),
+       DEF_MOD("usbhs-dmac0",           330,   R8A7745_CLK_HP),
+       DEF_MOD("usbhs-dmac1",           331,   R8A7745_CLK_HP),
+       DEF_MOD("irqc",                  407,   R8A7745_CLK_CP),
+       DEF_MOD("intc-sys",              408,   R8A7745_CLK_ZS),
+       DEF_MOD("audio-dmac0",           502,   R8A7745_CLK_HP),
+       DEF_MOD("pwm",                   523,   R8A7745_CLK_P),
+       DEF_MOD("usb-ehci",              703,   R8A7745_CLK_MP),
+       DEF_MOD("usbhs",                 704,   R8A7745_CLK_HP),
+       DEF_MOD("hscif2",                713,   R8A7745_CLK_ZS),
+       DEF_MOD("scif5",                 714,   R8A7745_CLK_P),
+       DEF_MOD("scif4",                 715,   R8A7745_CLK_P),
+       DEF_MOD("hscif1",                716,   R8A7745_CLK_ZS),
+       DEF_MOD("hscif0",                717,   R8A7745_CLK_ZS),
+       DEF_MOD("scif3",                 718,   R8A7745_CLK_P),
+       DEF_MOD("scif2",                 719,   R8A7745_CLK_P),
+       DEF_MOD("scif1",                 720,   R8A7745_CLK_P),
+       DEF_MOD("scif0",                 721,   R8A7745_CLK_P),
+       DEF_MOD("du0",                   724,   R8A7745_CLK_ZX),
+       DEF_MOD("ipmmu-sgx",             800,   R8A7745_CLK_ZX),
+       DEF_MOD("vin1",                  810,   R8A7745_CLK_ZG),
+       DEF_MOD("vin0",                  811,   R8A7745_CLK_ZG),
+       DEF_MOD("etheravb",              812,   R8A7745_CLK_HP),
+       DEF_MOD("ether",                 813,   R8A7745_CLK_P),
+       DEF_MOD("gpio6",                 905,   R8A7745_CLK_CP),
+       DEF_MOD("gpio5",                 907,   R8A7745_CLK_CP),
+       DEF_MOD("gpio4",                 908,   R8A7745_CLK_CP),
+       DEF_MOD("gpio3",                 909,   R8A7745_CLK_CP),
+       DEF_MOD("gpio2",                 910,   R8A7745_CLK_CP),
+       DEF_MOD("gpio1",                 911,   R8A7745_CLK_CP),
+       DEF_MOD("gpio0",                 912,   R8A7745_CLK_CP),
+       DEF_MOD("can1",                  915,   R8A7745_CLK_P),
+       DEF_MOD("can0",                  916,   R8A7745_CLK_P),
+       DEF_MOD("qspi_mod",              917,   R8A7745_CLK_QSPI),
+       DEF_MOD("i2c5",                  925,   R8A7745_CLK_HP),
+       DEF_MOD("i2c4",                  927,   R8A7745_CLK_HP),
+       DEF_MOD("i2c3",                  928,   R8A7745_CLK_HP),
+       DEF_MOD("i2c2",                  929,   R8A7745_CLK_HP),
+       DEF_MOD("i2c1",                  930,   R8A7745_CLK_HP),
+       DEF_MOD("i2c0",                  931,   R8A7745_CLK_HP),
+       DEF_MOD("ssi-all",              1005,   R8A7745_CLK_P),
+       DEF_MOD("ssi9",                 1006,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi8",                 1007,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi7",                 1008,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi6",                 1009,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi5",                 1010,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi4",                 1011,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi3",                 1012,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi2",                 1013,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi1",                 1014,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi0",                 1015,   MOD_CLK_ID(1005)),
+       DEF_MOD("scu-all",              1017,   R8A7745_CLK_P),
+       DEF_MOD("scu-dvc1",             1018,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-dvc0",             1019,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-ctu1-mix1",        1020,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-ctu0-mix0",        1021,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src9",             1022,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src8",             1023,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src7",             1024,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src6",             1025,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src5",             1026,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src4",             1027,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src3",             1028,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src2",             1029,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src1",             1030,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src0",             1031,   MOD_CLK_ID(1017)),
+       DEF_MOD("scifa3",               1106,   R8A7745_CLK_MP),
+       DEF_MOD("scifa4",               1107,   R8A7745_CLK_MP),
+       DEF_MOD("scifa5",               1108,   R8A7745_CLK_MP),
+};
+
+static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *    MD       EXTAL           PLL0    PLL1    PLL3
+ * 14 13 19    (MHz)           *1      *2
+ *---------------------------------------------------
+ * 0  0  0     15              x200/3  x208/2  x106
+ * 0  0  1     15              x200/3  x208/2  x88
+ * 0  1  0     20              x150/3  x156/2  x80
+ * 0  1  1     20              x150/3  x156/2  x66
+ * 1  0  0     26 / 2          x230/3  x240/2  x122
+ * 1  0  1     26 / 2          x230/3  x240/2  x102
+ * 1  1  0     30 / 2          x200/3  x208/2  x106
+ * 1  1  1     30 / 2          x200/3  x208/2  x88
+ *
+ * *1 :        Table 7.5b indicates VCO output (PLL0 = VCO/3)
+ * *2 :        Table 7.5b indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 12) | \
+                                        (((md) & BIT(13)) >> 12) | \
+                                        (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+       /* EXTAL div    PLL1 mult       PLL3 mult       PLL0 mult */
+       { 1,            208,            106,            200     },
+       { 1,            208,            88,             200     },
+       { 1,            156,            80,             150     },
+       { 1,            156,            66,             150     },
+       { 2,            240,            122,            230     },
+       { 2,            240,            102,            230     },
+       { 2,            208,            106,            200     },
+       { 2,            208,            88,             200     },
+};
+
+static int __init r8a7745_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
+
+       cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+       return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7745_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks = r8a7745_core_clks,
+       .num_core_clks = ARRAY_SIZE(r8a7745_core_clks),
+       .last_dt_core_clk = LAST_DT_CORE_CLK,
+       .num_total_core_clks = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks = r8a7745_mod_clks,
+       .num_mod_clks = ARRAY_SIZE(r8a7745_mod_clks),
+       .num_hw_mod_clks = 12 * 32,
+
+       /* Critical Module Clocks */
+       .crit_mod_clks = r8a7745_crit_mod_clks,
+       .num_crit_mod_clks = ARRAY_SIZE(r8a7745_crit_mod_clks),
+
+       /* Callbacks */
+       .init = r8a7745_cpg_mssr_init,
+       .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
index f255e451e8cafbbf573ee4d447151f91177c1118..50698a7d90745447576a4ad3afd9e0893911201b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 
@@ -97,7 +98,7 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
        DEF_FIXED("cp",         R8A7795_CLK_CP,    CLK_EXTAL,      2, 1),
 
        DEF_DIV6P1("mso",       R8A7795_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
-       DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV2, 0x250),
+       DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
        DEF_DIV6P1("canfd",     R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
        DEF_DIV6P1("csi0",      R8A7795_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
 
@@ -311,7 +312,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
 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();
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
 
        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
        if (!cpg_pll_config->extal_div) {
index eb347ed265f2adfa7f051f8d15493c45870589b3..7d298c57a3e060b6ea9a7ff8af36602706293e79 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
 
@@ -102,6 +103,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        DEF_FIXED("cl",         R8A7796_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A7796_CLK_CP,    CLK_EXTAL,      2, 1),
 
+       DEF_DIV6P1("csi0",      R8A7796_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
+
        DEF_DIV6_RO("osc",      R8A7796_CLK_OSC,   CLK_EXTAL, CPG_RCKCR,  8),
        DEF_DIV6_RO("r_int",    CLK_RINT,          CLK_EXTAL, CPG_RCKCR, 32),
 
@@ -109,6 +112,14 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
 };
 
 static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
+       DEF_MOD("scif5",                 202,   R8A7796_CLK_S3D4),
+       DEF_MOD("scif4",                 203,   R8A7796_CLK_S3D4),
+       DEF_MOD("scif3",                 204,   R8A7796_CLK_S3D4),
+       DEF_MOD("scif1",                 206,   R8A7796_CLK_S3D4),
+       DEF_MOD("scif0",                 207,   R8A7796_CLK_S3D4),
+       DEF_MOD("sys-dmac2",             217,   R8A7796_CLK_S0D3),
+       DEF_MOD("sys-dmac1",             218,   R8A7796_CLK_S0D3),
+       DEF_MOD("sys-dmac0",             219,   R8A7796_CLK_S0D3),
        DEF_MOD("cmt3",                  300,   R8A7796_CLK_R),
        DEF_MOD("cmt2",                  301,   R8A7796_CLK_R),
        DEF_MOD("cmt1",                  302,   R8A7796_CLK_R),
@@ -120,7 +131,47 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("sdif0",                 314,   R8A7796_CLK_SD0),
        DEF_MOD("rwdt0",                 402,   R8A7796_CLK_R),
        DEF_MOD("intc-ap",               408,   R8A7796_CLK_S3D1),
+       DEF_MOD("drif7",                 508,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif6",                 509,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif5",                 510,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif4",                 511,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif3",                 512,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif2",                 513,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif1",                 514,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif0",                 515,   R8A7796_CLK_S3D2),
+       DEF_MOD("hscif4",                516,   R8A7796_CLK_S3D1),
+       DEF_MOD("hscif3",                517,   R8A7796_CLK_S3D1),
+       DEF_MOD("hscif2",                518,   R8A7796_CLK_S3D1),
+       DEF_MOD("hscif1",                519,   R8A7796_CLK_S3D1),
+       DEF_MOD("hscif0",                520,   R8A7796_CLK_S3D1),
        DEF_MOD("thermal",               522,   R8A7796_CLK_CP),
+       DEF_MOD("fcpvd2",                601,   R8A7796_CLK_S0D2),
+       DEF_MOD("fcpvd1",                602,   R8A7796_CLK_S0D2),
+       DEF_MOD("fcpvd0",                603,   R8A7796_CLK_S0D2),
+       DEF_MOD("fcpvb0",                607,   R8A7796_CLK_S0D1),
+       DEF_MOD("fcpvi0",                611,   R8A7796_CLK_S0D1),
+       DEF_MOD("fcpf0",                 615,   R8A7796_CLK_S0D1),
+       DEF_MOD("fcpci0",                617,   R8A7796_CLK_S0D2),
+       DEF_MOD("fcpcs",                 619,   R8A7796_CLK_S0D2),
+       DEF_MOD("vspd2",                 621,   R8A7796_CLK_S0D2),
+       DEF_MOD("vspd1",                 622,   R8A7796_CLK_S0D2),
+       DEF_MOD("vspd0",                 623,   R8A7796_CLK_S0D2),
+       DEF_MOD("vspb",                  626,   R8A7796_CLK_S0D1),
+       DEF_MOD("vspi0",                 631,   R8A7796_CLK_S0D1),
+       DEF_MOD("csi20",                 714,   R8A7796_CLK_CSI0),
+       DEF_MOD("csi40",                 716,   R8A7796_CLK_CSI0),
+       DEF_MOD("du2",                   722,   R8A7796_CLK_S2D1),
+       DEF_MOD("du1",                   723,   R8A7796_CLK_S2D1),
+       DEF_MOD("du0",                   724,   R8A7796_CLK_S2D1),
+       DEF_MOD("lvds",                  727,   R8A7796_CLK_S2D1),
+       DEF_MOD("vin7",                  804,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin6",                  805,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin5",                  806,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin4",                  807,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin3",                  808,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin2",                  809,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin1",                  810,   R8A7796_CLK_S0D2),
+       DEF_MOD("vin0",                  811,   R8A7796_CLK_S0D2),
        DEF_MOD("etheravb",              812,   R8A7796_CLK_S0D6),
        DEF_MOD("gpio7",                 905,   R8A7796_CLK_S3D4),
        DEF_MOD("gpio6",                 906,   R8A7796_CLK_S3D4),
@@ -130,6 +181,13 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("gpio2",                 910,   R8A7796_CLK_S3D4),
        DEF_MOD("gpio1",                 911,   R8A7796_CLK_S3D4),
        DEF_MOD("gpio0",                 912,   R8A7796_CLK_S3D4),
+       DEF_MOD("i2c6",                  918,   R8A7796_CLK_S0D6),
+       DEF_MOD("i2c5",                  919,   R8A7796_CLK_S0D6),
+       DEF_MOD("i2c4",                  927,   R8A7796_CLK_S0D6),
+       DEF_MOD("i2c3",                  928,   R8A7796_CLK_S0D6),
+       DEF_MOD("i2c2",                  929,   R8A7796_CLK_S3D2),
+       DEF_MOD("i2c1",                  930,   R8A7796_CLK_S3D2),
+       DEF_MOD("i2c0",                  931,   R8A7796_CLK_S3D2),
 };
 
 static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
@@ -190,7 +248,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
 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();
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
 
        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
        if (!cpg_pll_config->extal_div) {
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.c b/drivers/clk/renesas/rcar-gen2-cpg.c
new file mode 100644 (file)
index 0000000..123b1e6
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#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-gen2-cpg.h"
+
+#define CPG_FRQCRB             0x0004
+#define CPG_FRQCRB_KICK                BIT(31)
+#define CPG_SDCKCR             0x0074
+#define CPG_PLL0CR             0x00d8
+#define CPG_PLL0CR_STC_SHIFT   24
+#define CPG_PLL0CR_STC_MASK    (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC             0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT   8
+#define CPG_FRQCRC_ZFC_MASK    (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR           0x025c
+#define CPG_RCANCKCR           0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.  clk->rate = parent->rate * mult / 32
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+       struct clk_hw hw;
+       void __iomem *reg;
+       void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       unsigned int val;
+
+       val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+       mult = 32 - val;
+
+       return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long *parent_rate)
+{
+       unsigned long prate  = *parent_rate;
+       unsigned int mult;
+
+       if (!prate)
+               prate = 1;
+
+       mult = div_u64((u64)rate * 32, prate);
+       mult = clamp(mult, 1U, 32U);
+
+       return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       u32 val, kick;
+       unsigned int i;
+
+       mult = div_u64((u64)rate * 32, parent_rate);
+       mult = clamp(mult, 1U, 32U);
+
+       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+               return -EBUSY;
+
+       val = readl(zclk->reg);
+       val &= ~CPG_FRQCRC_ZFC_MASK;
+       val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+       writel(val, zclk->reg);
+
+       /*
+        * Set KICK bit in FRQCRB to update hardware setting and wait for
+        * clock change completion.
+        */
+       kick = readl(zclk->kick_reg);
+       kick |= CPG_FRQCRB_KICK;
+       writel(kick, zclk->kick_reg);
+
+       /*
+        * Note: There is no HW information about the worst case latency.
+        *
+        * Using experimental measurements, it seems that no more than
+        * ~10 iterations are needed, independently of the CPU rate.
+        * Since this value might be dependent on external xtal rate, pll1
+        * rate or even the other emulation clocks rate, use 1000 as a
+        * "super" safe value.
+        */
+       for (i = 1000; i; i--) {
+               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+                       return 0;
+
+               cpu_relax();
+       }
+
+       return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+       .recalc_rate = cpg_z_clk_recalc_rate,
+       .round_rate = cpg_z_clk_round_rate,
+       .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+                                             const char *parent_name,
+                                             void __iomem *base)
+{
+       struct clk_init_data init;
+       struct cpg_z_clk *zclk;
+       struct clk *clk;
+
+       zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+       if (!zclk)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &cpg_z_clk_ops;
+       init.flags = 0;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       zclk->reg = base + CPG_FRQCRC;
+       zclk->kick_reg = base + CPG_FRQCRB;
+       zclk->hw.init = &init;
+
+       clk = clk_register(NULL, &zclk->hw);
+       if (IS_ERR(clk))
+               kfree(zclk);
+
+       return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+                                                const char *parent_name,
+                                                void __iomem *base)
+{
+       struct clk_fixed_factor *fixed;
+       struct clk_gate *gate;
+       struct clk *clk;
+
+       fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+       if (!fixed)
+               return ERR_PTR(-ENOMEM);
+
+       fixed->mult = 1;
+       fixed->div = 6;
+
+       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+       if (!gate) {
+               kfree(fixed);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       gate->reg = base + CPG_RCANCKCR;
+       gate->bit_idx = 8;
+       gate->flags = CLK_GATE_SET_TO_DISABLE;
+       gate->lock = &cpg_lock;
+
+       clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+                                    &fixed->hw, &clk_fixed_factor_ops,
+                                    &gate->hw, &clk_gate_ops, 0);
+       if (IS_ERR(clk)) {
+               kfree(gate);
+               kfree(fixed);
+       }
+
+       return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+       {  1,  3 }, {  2,  4 }, {  3,  6 }, {  4,  8 },
+       {  5, 12 }, {  6, 16 }, {  7, 18 }, {  8, 24 },
+       { 10, 36 }, { 11, 48 }, {  0,  0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+                                                const char *parent_name,
+                                                void __iomem *base)
+{
+       struct clk_divider *div;
+       struct clk_gate *gate;
+       struct clk *clk;
+
+       div = kzalloc(sizeof(*div), GFP_KERNEL);
+       if (!div)
+               return ERR_PTR(-ENOMEM);
+
+       div->reg = base + CPG_ADSPCKCR;
+       div->width = 4;
+       div->table = cpg_adsp_div_table;
+       div->lock = &cpg_lock;
+
+       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+       if (!gate) {
+               kfree(div);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       gate->reg = base + CPG_ADSPCKCR;
+       gate->bit_idx = 8;
+       gate->flags = CLK_GATE_SET_TO_DISABLE;
+       gate->lock = &cpg_lock;
+
+       clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+                                    &div->hw, &clk_divider_ops,
+                                    &gate->hw, &clk_gate_ops, 0);
+       if (IS_ERR(clk)) {
+               kfree(gate);
+               kfree(div);
+       }
+
+       return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+       {  0,  2 }, {  1,  3 }, {  2,  4 }, {  3,  6 },
+       {  4,  8 }, {  5, 12 }, {  6, 16 }, {  7, 18 },
+       {  8, 24 }, { 10, 36 }, { 11, 48 }, {  0,  0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+       {  4,  8 }, {  5, 12 }, {  6, 16 }, {  7, 18 },
+       {  8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+       {  0,  0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_pll0_div __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_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_div_table *table = NULL;
+       const struct clk *parent;
+       const char *parent_name;
+       unsigned int mult = 1;
+       unsigned int div = 1;
+       unsigned int shift;
+
+       parent = clks[core->parent];
+       if (IS_ERR(parent))
+               return ERR_CAST(parent);
+
+       parent_name = __clk_get_name(parent);
+
+       switch (core->type) {
+       /* R-Car Gen2 */
+       case CLK_TYPE_GEN2_MAIN:
+               div = cpg_pll_config->extal_div;
+               break;
+
+       case CLK_TYPE_GEN2_PLL0:
+               /*
+                * PLL0 is a  configurable multiplier clock except on R-Car
+                * V2H/E2. Register the PLL0 clock 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.
+                */
+               mult = cpg_pll_config->pll0_mult;
+               div  = cpg_pll0_div;
+               if (!mult) {
+                       u32 pll0cr = readl(base + CPG_PLL0CR);
+
+                       mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+                                CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+               }
+               break;
+
+       case CLK_TYPE_GEN2_PLL1:
+               mult = cpg_pll_config->pll1_mult / 2;
+               break;
+
+       case CLK_TYPE_GEN2_PLL3:
+               mult = cpg_pll_config->pll3_mult;
+               break;
+
+       case CLK_TYPE_GEN2_Z:
+               return cpg_z_clk_register(core->name, parent_name, base);
+
+       case CLK_TYPE_GEN2_LB:
+               div = cpg_mode & BIT(18) ? 36 : 24;
+               break;
+
+       case CLK_TYPE_GEN2_ADSP:
+               return cpg_adsp_clk_register(core->name, parent_name, base);
+
+       case CLK_TYPE_GEN2_SDH:
+               table = cpg_sdh_div_table;
+               shift = 8;
+               break;
+
+       case CLK_TYPE_GEN2_SD0:
+               table = cpg_sd01_div_table;
+               shift = 4;
+               break;
+
+       case CLK_TYPE_GEN2_SD1:
+               table = cpg_sd01_div_table;
+               shift = 0;
+               break;
+
+       case CLK_TYPE_GEN2_QSPI:
+               div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+                     8 : 10;
+               break;
+
+       case CLK_TYPE_GEN2_RCAN:
+               return cpg_rcan_clk_register(core->name, parent_name, base);
+
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!table)
+               return clk_register_fixed_factor(NULL, core->name, parent_name,
+                                                0, mult, div);
+       else
+               return clk_register_divider_table(NULL, core->name,
+                                                 parent_name, 0,
+                                                 base + CPG_SDCKCR, shift, 4,
+                                                 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+                             unsigned int pll0_div, u32 mode)
+{
+       cpg_pll_config = config;
+       cpg_pll0_div = pll0_div;
+       cpg_mode = mode;
+
+       spin_lock_init(&cpg_lock);
+
+       return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.h b/drivers/clk/renesas/rcar-gen2-cpg.h
new file mode 100644 (file)
index 0000000..9eba07f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+       CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+       CLK_TYPE_GEN2_PLL0,
+       CLK_TYPE_GEN2_PLL1,
+       CLK_TYPE_GEN2_PLL3,
+       CLK_TYPE_GEN2_Z,
+       CLK_TYPE_GEN2_LB,
+       CLK_TYPE_GEN2_ADSP,
+       CLK_TYPE_GEN2_SDH,
+       CLK_TYPE_GEN2_SD0,
+       CLK_TYPE_GEN2_SD1,
+       CLK_TYPE_GEN2_QSPI,
+       CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+       unsigned int extal_div;
+       unsigned int pll1_mult;
+       unsigned int pll3_mult;
+       unsigned int pll0_mult;         /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_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_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+                      unsigned int pll0_div, u32 mode);
+
+#endif
index bb4f2f9a8c2f5ba8d126ed33b6e1273454aaaa7a..742f6dc7c15653ef5b51bc9d4f3da9b1ebe75c47 100644 (file)
@@ -98,7 +98,7 @@ static int cpg_sd_clock_enable(struct clk_hw *hw)
        u32 val, sd_fc;
        unsigned int i;
 
-       val = clk_readl(clock->reg);
+       val = readl(clock->reg);
 
        sd_fc = val & CPG_SD_FC_MASK;
        for (i = 0; i < clock->div_num; i++)
@@ -111,7 +111,7 @@ static int cpg_sd_clock_enable(struct clk_hw *hw)
        val &= ~(CPG_SD_STP_MASK);
        val |= clock->div_table[i].val & CPG_SD_STP_MASK;
 
-       clk_writel(val, clock->reg);
+       writel(val, clock->reg);
 
        return 0;
 }
@@ -120,14 +120,14 @@ 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);
+       writel(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);
+       return !(readl(clock->reg) & CPG_SD_STP_MASK);
 }
 
 static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
@@ -138,7 +138,7 @@ static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
        u32 val, sd_fc;
        unsigned int i;
 
-       val = clk_readl(clock->reg);
+       val = readl(clock->reg);
 
        sd_fc = val & CPG_SD_FC_MASK;
        for (i = 0; i < clock->div_num; i++)
@@ -189,10 +189,10 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
        if (i >= clock->div_num)
                return -EINVAL;
 
-       val = clk_readl(clock->reg);
+       val = 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);
+       writel(val, clock->reg);
 
        return 0;
 }
@@ -333,23 +333,6 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                                         __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)
 {
index f699085147d1aece3bfa67da225a01839b898a81..f788f481dd42cdf65ddfac1d4067836e87093f59 100644 (file)
@@ -33,7 +33,6 @@ struct rcar_gen3_cpg_pll_config {
 
 #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);
index e1365e7491ae02a0519ec94aaea92baa5f58d55e..8359ce75db7aa4fb6e4bfb7f0f1ede36d90e1349 100644 (file)
@@ -33,9 +33,9 @@
 #include "clk-div6.h"
 
 #ifdef DEBUG
-#define WARN_DEBUG(x)  do { } while (0)
-#else
 #define WARN_DEBUG(x)  WARN_ON(x)
+#else
+#define WARN_DEBUG(x)  do { } while (0)
 #endif
 
 
@@ -146,12 +146,12 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
                enable ? "ON" : "OFF");
        spin_lock_irqsave(&priv->mstp_lock, flags);
 
-       value = clk_readl(priv->base + SMSTPCR(reg));
+       value = readl(priv->base + SMSTPCR(reg));
        if (enable)
                value &= ~bitmask;
        else
                value |= bitmask;
-       clk_writel(value, priv->base + SMSTPCR(reg));
+       writel(value, priv->base + SMSTPCR(reg));
 
        spin_unlock_irqrestore(&priv->mstp_lock, flags);
 
@@ -159,8 +159,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
                return 0;
 
        for (i = 1000; i > 0; --i) {
-               if (!(clk_readl(priv->base + MSTPSR(reg)) &
-                     bitmask))
+               if (!(readl(priv->base + MSTPSR(reg)) & bitmask))
                        break;
                cpu_relax();
        }
@@ -190,7 +189,7 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
        struct cpg_mssr_priv *priv = clock->priv;
        u32 value;
 
-       value = clk_readl(priv->base + MSTPSR(clock->index / 32));
+       value = readl(priv->base + MSTPSR(clock->index / 32));
 
        return !(value & BIT(clock->index % 32));
 }
@@ -309,7 +308,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
        return;
 
 fail:
-       dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,",
+       dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
                core->name, PTR_ERR(clk));
 }
 
@@ -377,7 +376,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
        return;
 
 fail:
-       dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,",
+       dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
                mod->name, PTR_ERR(clk));
        kfree(clock);
 }
@@ -503,6 +502,18 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
 }
 
 static const struct of_device_id cpg_mssr_match[] = {
+#ifdef CONFIG_ARCH_R8A7743
+       {
+               .compatible = "renesas,r8a7743-cpg-mssr",
+               .data = &r8a7743_cpg_mssr_info,
+       },
+#endif
+#ifdef CONFIG_ARCH_R8A7745
+       {
+               .compatible = "renesas,r8a7745-cpg-mssr",
+               .data = &r8a7745_cpg_mssr_info,
+       },
+#endif
 #ifdef CONFIG_ARCH_R8A7795
        {
                .compatible = "renesas,r8a7795-cpg-mssr",
index ee7edfaf14089cefbd5949a484334c8de7d181dc..4bb7a80c6469e12eebed9f0dee0916657bad3477 100644 (file)
@@ -130,6 +130,8 @@ struct cpg_mssr_info {
                                        struct clk **clks, void __iomem *base);
 };
 
+extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7745_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 b5f2c8ed12e17641f810b0e941102cad2cf34b7f..16e098c36f903f542abf80bc05107fab8538eeec 100644 (file)
@@ -11,6 +11,7 @@ obj-y += clk-mmc-phase.o
 obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
 
+obj-y  += clk-rk1108.o
 obj-y  += clk-rk3036.o
 obj-y  += clk-rk3188.o
 obj-y  += clk-rk3228.o
index 05b3d73bfefaacdd54c6123609165d6d2d8481d8..0e09684d43a5b15cf441f06fa12145abeb0234a2 100644 (file)
@@ -124,9 +124,18 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
                                           struct clk_notifier_data *ndata)
 {
        const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
+       const struct rockchip_cpuclk_rate_table *rate;
        unsigned long alt_prate, alt_div;
        unsigned long flags;
 
+       /* check validity of the new rate */
+       rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
+       if (!rate) {
+               pr_err("%s: Invalid rate : %lu for cpuclk\n",
+                      __func__, ndata->new_rate);
+               return -EINVAL;
+       }
+
        alt_prate = clk_get_rate(cpuclk->alt_parent);
 
        spin_lock_irqsave(cpuclk->lock, flags);
index 9c1373e81683bebec4c0968b30036c5b175e8028..6ed605776abd1cbf5002cca73248e6b300e5f33c 100644 (file)
@@ -319,7 +319,8 @@ static void rockchip_rk3036_pll_init(struct clk_hw *hw)
 
        if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
                rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
-               rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+               rate->dsmpd != cur.dsmpd ||
+               (!cur.dsmpd && (rate->frac != cur.frac))) {
                struct clk *parent = clk_get_parent(hw->clk);
 
                if (!parent) {
@@ -795,7 +796,8 @@ static void rockchip_rk3399_pll_init(struct clk_hw *hw)
 
        if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
                rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
-               rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+               rate->dsmpd != cur.dsmpd ||
+               (!cur.dsmpd && (rate->frac != cur.frac))) {
                struct clk *parent = clk_get_parent(hw->clk);
 
                if (!parent) {
diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c
new file mode 100644 (file)
index 0000000..92750d7
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ *         Andy Yan <andy.yan@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk1108-cru.h>
+#include "clk.h"
+
+#define RK1108_GRF_SOC_STATUS0 0x480
+
+enum rk1108_plls {
+       apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
+       /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+       RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+       RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+       RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+       RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+       RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+       RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+       RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+       { /* sentinel */ },
+};
+
+#define RK1108_DIV_CORE_MASK           0xf
+#define RK1108_DIV_CORE_SHIFT          4
+
+#define RK1108_CLKSEL0(_core_peri_div) \
+       {                               \
+               .reg = RK1108_CLKSEL_CON(1),    \
+               .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
+                               RK1108_DIV_CORE_SHIFT)  \
+       }
+
+#define RK1108_CPUCLK_RATE(_prate, _core_peri_div)                     \
+       {                                                               \
+               .prate = _prate,                                        \
+               .divs = {                                               \
+                       RK1108_CLKSEL0(_core_peri_div),         \
+               },                                                      \
+       }
+
+static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
+       RK1108_CPUCLK_RATE(816000000, 4),
+       RK1108_CPUCLK_RATE(600000000, 4),
+       RK1108_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
+       .core_reg = RK1108_CLKSEL_CON(0),
+       .div_core_shift = 0,
+       .div_core_mask = 0x1f,
+       .mux_core_alt = 1,
+       .mux_core_main = 0,
+       .mux_core_shift = 8,
+       .mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p)               = { "xin24m", "xin24m"};
+PNAME(mux_ddrphy_p)            = { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_armclk_p)            = { "apll_core", "gpll_core", "dpll_core" };
+PNAME(mux_usb480m_pre_p)       = { "usbphy", "xin24m" };
+PNAME(mux_hdmiphy_phy_p)       = { "hdmiphy", "xin24m" };
+PNAME(mux_dclk_hdmiphy_pre_p)  = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" };
+PNAME(mux_pll_src_4plls_p)     = { "dpll", "hdmiphy", "gpll", "usb480m" };
+PNAME(mux_pll_src_3plls_p)     = { "apll", "gpll", "dpll" };
+PNAME(mux_pll_src_2plls_p)     = { "dpll", "gpll" };
+PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" };
+PNAME(mux_aclk_peri_src_p)     = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
+PNAME(mux_aclk_bus_src_p)      = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
+PNAME(mux_mmc_src_p)           = { "dpll", "gpll", "xin24m", "usb480m" };
+PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" };
+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_p)       = { "sclk_macphy_pre", "ext_gmac" };
+PNAME(mux_i2s0_pre_p)          = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p)           = { "i2s0_pre", "xin12m" };
+PNAME(mux_i2s1_p)              = { "i2s1_src", "i2s1_frac", "xin12m" };
+PNAME(mux_i2s2_p)              = { "i2s2_src", "i2s2_frac", "xin12m" };
+
+static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
+       [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
+                    RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
+       [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
+                    RK1108_PLL_CON(11), 8, 31, 0, NULL),
+       [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
+                    RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
+       MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
+       MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
+       MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
+       MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
+       MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
+       MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
+       MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
+                       RK1108_MISC_CON, 13, 2, MFLAGS),
+       MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
+                       RK1108_MISC_CON, 15, 2, MFLAGS),
+       /*
+        * Clock-Architecture Diagram 2
+        */
+
+       /* PD_CORE */
+       GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 1, GFLAGS),
+       GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 0, GFLAGS),
+       GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 2, GFLAGS),
+       COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+                       RK1108_CLKGATE_CON(0), 5, GFLAGS),
+       COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+                       RK1108_CLKGATE_CON(0), 4, GFLAGS),
+       GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(11), 0, GFLAGS),
+       GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(11), 1, GFLAGS),
+
+       /* PD_RKVENC */
+
+       /* PD_RKVDEC */
+
+       /* PD_PMU_wrapper */
+       COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(8), 12, GFLAGS),
+       GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 0, GFLAGS),
+       GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 1, GFLAGS),
+       GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 2, GFLAGS),
+       GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 3, GFLAGS),
+       GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 4, GFLAGS),
+       GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 5, GFLAGS),
+       GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(10), 6, GFLAGS),
+       COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(8), 15, GFLAGS),
+       COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(8), 14, GFLAGS),
+       GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(8), 13, GFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 4
+        */
+       COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(6), 0, GFLAGS),
+       GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(17), 0, GFLAGS),
+       COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
+                       RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(7), 2, GFLAGS),
+       COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
+                       RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(7), 3, GFLAGS),
+
+       INVERTER(0, "pclk_vip", "ext_vip",
+                       RK1108_CLKSEL_CON(31), 8, IFLAGS),
+       GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(7), 6, GFLAGS),
+       GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(18), 10, GFLAGS),
+       GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(6), 5, GFLAGS),
+       GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(6), 4, GFLAGS),
+       COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
+                       RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 5
+        */
+
+       FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+       COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
+                       RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(2), 0, GFLAGS),
+       COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(8), 0,
+                       RK1108_CLKGATE_CON(2), 1, GFLAGS,
+                       &rk1108_i2s0_fracmux),
+       GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+                       RK1108_CLKGATE_CON(2), 2, GFLAGS),
+       COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
+                       RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
+                       RK1108_CLKGATE_CON(2), 3, GFLAGS),
+
+       COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
+                       RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(2), 4, GFLAGS),
+       COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+                       RK2928_CLKSEL_CON(9), 0,
+                       RK2928_CLKGATE_CON(2), 5, GFLAGS,
+                       &rk1108_i2s1_fracmux),
+       GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+                       RK1108_CLKGATE_CON(2), 6, GFLAGS),
+
+       COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
+                       RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 8, GFLAGS),
+       COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(10), 0,
+                       RK1108_CLKGATE_CON(2), 9, GFLAGS,
+                       &rk1108_i2s2_fracmux),
+       GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
+                       RK1108_CLKGATE_CON(2), 10, GFLAGS),
+
+       /* PD_BUS */
+       GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 0, GFLAGS),
+       GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 1, GFLAGS),
+       GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 2, GFLAGS),
+       COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
+                       RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
+       COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
+                       RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(1), 4, GFLAGS),
+       COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
+                       RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(1), 5, GFLAGS),
+       GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 6, GFLAGS),
+       GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 7, GFLAGS),
+       GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 8, GFLAGS),
+       GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 9, GFLAGS),
+       GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(1), 10, GFLAGS),
+       GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 4, GFLAGS),
+
+       COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 1, GFLAGS),
+       COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 3, GFLAGS),
+       COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 5, GFLAGS),
+
+       COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(16), 0,
+                       RK1108_CLKGATE_CON(3), 2, GFLAGS,
+                       &rk1108_uart0_fracmux),
+       COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(17), 0,
+                       RK1108_CLKGATE_CON(3), 4, GFLAGS,
+                       &rk1108_uart1_fracmux),
+       COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(18), 0,
+                       RK1108_CLKGATE_CON(3), 6, GFLAGS,
+                       &rk1108_uart2_fracmux),
+       GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 10, GFLAGS),
+       GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 11, GFLAGS),
+       GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 12, GFLAGS),
+
+       COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 7, GFLAGS),
+       COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 8, GFLAGS),
+       COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 9, GFLAGS),
+       GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 0, GFLAGS),
+       GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 1, GFLAGS),
+       GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 2, GFLAGS),
+       COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(3), 10, GFLAGS),
+       GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 6, GFLAGS),
+       GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 3, GFLAGS),
+       GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 7, GFLAGS),
+       GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 8, GFLAGS),
+       GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(13), 9, GFLAGS),
+
+       GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(14), 0, GFLAGS),
+
+       GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
+            RK1108_CLKGATE_CON(12), 2, GFLAGS),
+       GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(12), 3, GFLAGS),
+       GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(12), 1, GFLAGS),
+
+       /* PD_DDR */
+       GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 8, GFLAGS),
+       GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 9, GFLAGS),
+       GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 10, GFLAGS),
+       COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
+                       DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+                       RK1108_CLKGATE_CON(10), 9, GFLAGS),
+       GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(12), 4, GFLAGS),
+       GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(12), 5, GFLAGS),
+       GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(12), 6, GFLAGS),
+       GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(0), 11, GFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 6
+        */
+
+       /* PD_PERI */
+       COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
+                       RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(4), 5, GFLAGS),
+       GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(15), 13, GFLAGS),
+       COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
+                       RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(4), 4, GFLAGS),
+       GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(15), 12, GFLAGS),
+
+       GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(4), 1, GFLAGS),
+       GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+                       RK1108_CLKGATE_CON(4), 2, GFLAGS),
+       COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
+                       RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(15), 11, GFLAGS),
+
+       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+                       RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
+                       RK1108_CLKGATE_CON(5), 0, GFLAGS),
+
+       COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+                       RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
+                       RK1108_CLKGATE_CON(5), 2, GFLAGS),
+       DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+                       RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
+
+       COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+                       RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
+                       RK1108_CLKGATE_CON(5), 1, GFLAGS),
+       DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
+                       RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
+       GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
+       GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
+       GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
+
+       COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
+                       RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(5), 3, GFLAGS),
+       GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
+
+       COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
+                       RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK1108_CLKGATE_CON(5), 4, GFLAGS),
+       GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
+
+       COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
+                       RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK1108_CLKGATE_CON(4), 10, GFLAGS),
+       MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
+                       RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
+       GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
+       GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
+       GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
+
+       MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
+       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
+
+       MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK1108_SDIO_CON0,  1),
+       MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK1108_SDIO_CON1,  1),
+
+       MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK1108_EMMC_CON0,  1),
+       MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK1108_EMMC_CON1,  1),
+};
+
+static const char *const rk1108_critical_clocks[] __initconst = {
+       "aclk_core",
+       "aclk_bus_src_gpll",
+       "aclk_periph",
+       "hclk_periph",
+       "pclk_periph",
+};
+
+static void __init rk1108_clk_init(struct device_node *np)
+{
+       struct rockchip_clk_provider *ctx;
+       void __iomem *reg_base;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("%s: could not map cru region\n", __func__);
+               return;
+       }
+
+       ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+       if (IS_ERR(ctx)) {
+               pr_err("%s: rockchip clk init failed\n", __func__);
+               iounmap(reg_base);
+               return;
+       }
+
+       rockchip_clk_register_plls(ctx, rk1108_pll_clks,
+                                  ARRAY_SIZE(rk1108_pll_clks),
+                                  RK1108_GRF_SOC_STATUS0);
+       rockchip_clk_register_branches(ctx, rk1108_clk_branches,
+                                 ARRAY_SIZE(rk1108_clk_branches));
+       rockchip_clk_protect_critical(rk1108_critical_clocks,
+                                     ARRAY_SIZE(rk1108_critical_clocks));
+
+       rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+                       mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+                       &rk1108_cpuclk_data, rk1108_cpuclk_rates,
+                       ARRAY_SIZE(rk1108_cpuclk_rates));
+
+       rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
+                                 ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+       rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
+
+       rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
index d0e722a0e8cff9afb79f7c22535042fe2332ce61..062ef4960244a54ba1f8c85a45d4bc3449111f39 100644 (file)
@@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
        RK3066_PLL_RATE( 504000000, 1, 84, 4),
        RK3066_PLL_RATE( 456000000, 1, 76, 4),
        RK3066_PLL_RATE( 408000000, 1, 68, 4),
+       RK3066_PLL_RATE( 400000000, 3, 100, 2),
        RK3066_PLL_RATE( 384000000, 2, 128, 4),
        RK3066_PLL_RATE( 360000000, 1, 60, 4),
        RK3066_PLL_RATE( 312000000, 1, 52, 4),
@@ -306,14 +307,14 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
                        RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
                        RK2928_CLKGATE_CON(0), 2, GFLAGS),
 
-       GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+       GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0,
                        RK2928_CLKGATE_CON(0), 3, GFLAGS),
 
        GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
                        RK2928_CLKGATE_CON(0), 6, GFLAGS),
-       GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
+       GATE(PCLK_CPU, "pclk_cpu", "pclk_cpu_pre", 0,
                        RK2928_CLKGATE_CON(0), 5, GFLAGS),
-       GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
+       GATE(HCLK_CPU, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
                        RK2928_CLKGATE_CON(0), 4, GFLAGS),
 
        COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
@@ -323,12 +324,12 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
                        RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS,
                        RK2928_CLKGATE_CON(1), 4, GFLAGS),
 
-       GATE(0, "aclk_peri", "aclk_peri_pre", 0,
+       GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0,
                        RK2928_CLKGATE_CON(2), 1, GFLAGS),
-       COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0,
+       COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre", 0,
                        RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
                        RK2928_CLKGATE_CON(2), 2, GFLAGS),
-       COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0,
+       COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre", 0,
                        RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
                        RK2928_CLKGATE_CON(2), 3, GFLAGS),
 
index 8387c7a40bda86e106ba4301c406d0a6b0a16a37..3490887b05799390522e7fd867698fe12bfa72cf 100644 (file)
@@ -77,7 +77,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
        RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
        RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
        RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
-       RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+       RK3036_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0),
        RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
        RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
        RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
@@ -87,12 +87,13 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
        RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
        RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
        RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
-       RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+       RK3036_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0),
        RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
        RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
        RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0),
        RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
        RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0),
+       RK3036_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0),
        RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
        RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
        RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
@@ -410,11 +411,11 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
        GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED,
                        RK3399_CLKGATE_CON(6), 6, GFLAGS),
 
-       GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED,
+       GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", 0,
                        RK3399_CLKGATE_CON(13), 12, GFLAGS),
-       GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED,
+       GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", 0,
                        RK3399_CLKGATE_CON(13), 12, GFLAGS),
-       MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED,
+       MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, 0,
                        RK3399_CLKSEL_CON(14), 6, 1, MFLAGS),
 
        MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0,
@@ -498,7 +499,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
                        RK3399_CLKGATE_CON(14), 10, GFLAGS),
        GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED,
                        RK3399_CLKGATE_CON(14), 11, GFLAGS),
-       GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED,
+       GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", 0,
                        RK3399_CLKGATE_CON(0), 7, GFLAGS),
 
        /* big core */
@@ -539,7 +540,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
        GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
                        RK3399_CLKGATE_CON(14), 2, GFLAGS),
 
-       GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED,
+       GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", 0,
                        RK3399_CLKGATE_CON(1), 7, GFLAGS),
 
        /* gmac */
@@ -675,18 +676,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 
        GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED,
                        RK3399_CLKGATE_CON(18), 10, GFLAGS),
-       GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED,
+       GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", 0,
                        RK3399_CLKGATE_CON(18), 12, GFLAGS),
        GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED,
                        RK3399_CLKGATE_CON(18), 15, GFLAGS),
        GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED,
                        RK3399_CLKGATE_CON(19), 2, GFLAGS),
 
-       GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED,
+       GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", 0,
                        RK3399_CLKGATE_CON(4), 11, GFLAGS),
-       GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED,
+       GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", 0,
                        RK3399_CLKGATE_CON(3), 5, GFLAGS),
-       GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED,
+       GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", 0,
                        RK3399_CLKGATE_CON(3), 6, GFLAGS),
 
        /* cci */
@@ -966,7 +967,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
        GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS),
        GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS),
        GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS),
-       GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS),
+       GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", 0, RK3399_CLKGATE_CON(23), 8, GFLAGS),
        GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS),
        GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS),
        GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS),
@@ -980,7 +981,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
        GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS),
 
        /* pclk_perilp0 gates */
-       GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS),
+       GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", 0, RK3399_CLKGATE_CON(23), 9, GFLAGS),
 
        /* crypto */
        COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0,
@@ -1382,8 +1383,8 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
        /* clk_test */
        /* clk_test_pre is controlled by CRU_MISC_CON[3] */
        COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
-                       RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
-                       RK3368_CLKGATE_CON(13), 11, GFLAGS),
+                       RK3399_CLKSEL_CON(58), 0, 5, DFLAGS,
+                       RK3399_CLKGATE_CON(13), 11, GFLAGS),
 
        /* ddrc */
        GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
index 1653edd792a5ebb66c5007afcce6d262e028078e..d67eecc4ade9bbafbca358eb42c2202f5f4db4af 100644 (file)
@@ -34,6 +34,21 @@ struct clk;
 #define HIWORD_UPDATE(val, mask, shift) \
                ((val) << (shift) | (mask) << ((shift) + 16))
 
+/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define RK1108_PLL_CON(x)              ((x) * 0x4)
+#define RK1108_CLKSEL_CON(x)           ((x) * 0x4 + 0x60)
+#define RK1108_CLKGATE_CON(x)          ((x) * 0x4 + 0x120)
+#define RK1108_SOFTRST_CON(x)          ((x) * 0x4 + 0x180)
+#define RK1108_GLB_SRST_FST            0x1c0
+#define RK1108_GLB_SRST_SND            0x1c4
+#define RK1108_MISC_CON                        0x1cc
+#define RK1108_SDMMC_CON0              0x1d8
+#define RK1108_SDMMC_CON1              0x1dc
+#define RK1108_SDIO_CON0               0x1e0
+#define RK1108_SDIO_CON1               0x1e4
+#define RK1108_EMMC_CON0               0x1e8
+#define RK1108_EMMC_CON1               0x1ec
+
 #define RK2928_PLL_CON(x)              ((x) * 0x4)
 #define RK2928_MODE_CON                0x40
 #define RK2928_CLKSEL_CON(x)   ((x) * 0x4 + 0x44)
index ea1608682d7fe90b3b20ede863386d82c4f23e7b..f096bd7df40c13d6af2ee8f000b7a38f41a47d25 100644 (file)
@@ -543,7 +543,7 @@ static const struct samsung_div_clock top_div_clks[] __initconst = {
 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),
+                       ENABLE_ACLK_TOP, 30, CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_IMEM_SSX_266, "aclk_imem_ssx_266",
                        "div_aclk_imem_sssx_266", ENABLE_ACLK_TOP,
                        29, CLK_IGNORE_UNUSED, 0),
@@ -555,25 +555,25 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
                        ENABLE_ACLK_TOP, 24,
-                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+                       CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_200",
                        ENABLE_ACLK_TOP, 23,
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_PERIC_66, "aclk_peric_66", "div_aclk_peric_66_b",
                        ENABLE_ACLK_TOP, 22,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_PERIS_66, "aclk_peris_66", "div_aclk_peris_66_b",
                        ENABLE_ACLK_TOP, 21,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_MSCL_400, "aclk_mscl_400", "div_aclk_mscl_400",
                        ENABLE_ACLK_TOP, 19,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_FSYS_200, "aclk_fsys_200", "div_aclk_fsys_200",
                        ENABLE_ACLK_TOP, 18,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_GSCL_111, "aclk_gscl_111", "div_aclk_gscl_111",
                        ENABLE_ACLK_TOP, 15,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_GSCL_333, "aclk_gscl_333", "div_aclk_gscl_333",
                        ENABLE_ACLK_TOP, 14,
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -582,7 +582,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_CAM1_400, "aclk_cam1_400", "div_aclk_cam1_400",
                        ENABLE_ACLK_TOP, 12,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_CAM1_552, "aclk_cam1_552", "div_aclk_cam1_552",
                        ENABLE_ACLK_TOP, 11,
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -591,7 +591,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_CAM0_400, "aclk_cam0_400", "div_aclk_cam0_400",
                        ENABLE_ACLK_TOP, 9,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_CAM0_552, "aclk_cam0_552", "div_aclk_cam0_552",
                        ENABLE_ACLK_TOP, 8,
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -600,19 +600,19 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_ISP_400, "aclk_isp_400", "div_aclk_isp_400",
                        ENABLE_ACLK_TOP, 6,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_HEVC_400, "aclk_hevc_400", "div_aclk_hevc_400",
                        ENABLE_ACLK_TOP, 5,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_MFC_400, "aclk_mfc_400", "div_aclk_mfc_400",
                        ENABLE_ACLK_TOP, 3,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
        GATE(CLK_ACLK_G2D_266, "aclk_g2d_266", "div_aclk_g2d_266",
                        ENABLE_ACLK_TOP, 2,
                        CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_G2D_400, "aclk_g2d_400", "div_aclk_g2d_400",
                        ENABLE_ACLK_TOP, 0,
-                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+                       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 
        /* ENABLE_SCLK_TOP_MSCL */
        GATE(CLK_SCLK_JPEG_MSCL, "sclk_jpeg_mscl", "div_sclk_jpeg",
@@ -1385,7 +1385,7 @@ static const struct samsung_gate_clock mif_gate_clks[] __initconst = {
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_DISP_333, "aclk_disp_333", "div_aclk_disp_333",
                        ENABLE_ACLK_MIF3, 1,
-                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+                       CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_CPIF_200, "aclk_cpif_200", "div_aclk_cpif_200",
                        ENABLE_ACLK_MIF3, 0,
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
@@ -1929,7 +1929,7 @@ CLK_OF_DECLARE(exynos5433_cmu_peris, "samsung,exynos5433-cmu-peris",
 
 /* list of all parent clock list */
 PNAME(mout_sclk_ufs_mphy_user_p)       = { "oscclk", "sclk_ufs_mphy", };
-PNAME(mout_aclk_fsys_200_user_p)       = { "oscclk", "div_aclk_fsys_200", };
+PNAME(mout_aclk_fsys_200_user_p)       = { "oscclk", "aclk_fsys_200", };
 PNAME(mout_sclk_pcie_100_user_p)       = { "oscclk", "sclk_pcie_100_fsys",};
 PNAME(mout_sclk_ufsunipro_user_p)      = { "oscclk", "sclk_ufsunipro_fsys",};
 PNAME(mout_sclk_mmc2_user_p)           = { "oscclk", "sclk_mmc2_fsys", };
index a485f3b284b9f5825fb206966197489df8594746..918ba3164da94c9dcf02927b17940f7e76165551 100644 (file)
@@ -329,8 +329,10 @@ static void __init st_of_flexgen_setup(struct device_node *np)
                return;
 
        parents = flexgen_get_parents(np, &num_parents);
-       if (!parents)
+       if (!parents) {
+               iounmap(reg);
                return;
+       }
 
        match = of_match_node(flexgen_of_match, np);
        if (match) {
@@ -394,6 +396,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
        return;
 
 err:
+       iounmap(reg);
        if (clk_data)
                kfree(clk_data->clks);
        kfree(clk_data);
index 254d9526c018c044d4c8d4c639d4d9089e011e04..8454c6e3dd65f229a5a51fbd3966d380e2926cb7 100644 (file)
@@ -35,17 +35,14 @@ config SUNXI_CCU_NK
 
 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
 
@@ -56,6 +53,17 @@ config SUNXI_CCU_MP
 
 # SoC Drivers
 
+config SUN50I_A64_CCU
+       bool "Support for the Allwinner A64 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 ARM64 && ARCH_SUNXI
+
 config SUN6I_A31_CCU
        bool "Support for the Allwinner A31/A31s CCU"
        select SUNXI_CCU_DIV
index 106cba27c3316b2d54047a6c94b0e96f449fce14..24fbc6e5deb81e1c62de1fcf06652f19493a0f26 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_SUNXI_CCU_NM)    += ccu_nm.o
 obj-$(CONFIG_SUNXI_CCU_MP)     += ccu_mp.o
 
 # SoC support
+obj-$(CONFIG_SUN50I_A64_CCU)   += ccu-sun50i-a64.o
 obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
 obj-$(CONFIG_SUN8I_A23_CCU)    += ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)    += ccu-sun8i-a33.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
new file mode 100644 (file)
index 0000000..e3c084c
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * 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 <linux/platform_device.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-sun50i-a64.h"
+
+static struct ccu_nkmp pll_cpux_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT(8, 5),
+       .k              = _SUNXI_CCU_MULT(4, 2),
+       .m              = _SUNXI_CCU_DIV(0, 2),
+       .p              = _SUNXI_CCU_DIV_MAX(16, 2, 4),
+       .common         = {
+               .reg            = 0x000,
+               .hw.init        = CLK_HW_INIT("pll-cpux",
+                                             "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+/*
+ * 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 SUN50I_A64_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 */
+                                  CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0",
+                                       "osc24M", 0x010,
+                                       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 */
+                                       CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
+                                       "osc24M", 0x018,
+                                       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 */
+                                       CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0",
+                                   "osc24M", 0x020,
+                                   8, 5,       /* N */
+                                   4, 2,       /* K */
+                                   0, 2,       /* M */
+                                   BIT(31),    /* gate */
+                                   BIT(28),    /* lock */
+                                   CLK_SET_RATE_UNGATE);
+
+static struct ccu_nk pll_periph0_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT(8, 5),
+       .k              = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+       .fixed_post_div = 2,
+       .common         = {
+               .reg            = 0x028,
+               .features       = CCU_FEATURE_FIXED_POSTDIV,
+               .hw.init        = CLK_HW_INIT("pll-periph0", "osc24M",
+                                             &ccu_nk_ops, CLK_SET_RATE_UNGATE),
+       },
+};
+
+static struct ccu_nk pll_periph1_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT(8, 5),
+       .k              = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+       .fixed_post_div = 2,
+       .common         = {
+               .reg            = 0x02c,
+               .features       = CCU_FEATURE_FIXED_POSTDIV,
+               .hw.init        = CLK_HW_INIT("pll-periph1", "osc24M",
+                                             &ccu_nk_ops, CLK_SET_RATE_UNGATE),
+       },
+};
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1",
+                                       "osc24M", 0x030,
+                                       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 */
+                                       CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
+                                       "osc24M", 0x038,
+                                       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 */
+                                       CLK_SET_RATE_UNGATE);
+
+/*
+ * The output function can be changed to something more complex that
+ * we do not handle yet.
+ *
+ * Hardcode the mode so that we don't fall in that case.
+ */
+#define SUN50I_A64_PLL_MIPI_REG                0x040
+
+static struct ccu_nkm pll_mipi_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT(8, 4),
+       .k              = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+       .m              = _SUNXI_CCU_DIV(0, 4),
+       .common         = {
+               .reg            = 0x040,
+               .hw.init        = CLK_HW_INIT("pll-mipi", "pll-video0",
+                                             &ccu_nkm_ops, CLK_SET_RATE_UNGATE),
+       },
+};
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_hsic_clk, "pll-hsic",
+                                       "osc24M", 0x044,
+                                       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 */
+                                       CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
+                                       "osc24M", 0x048,
+                                       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 */
+                                       CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
+                                  "osc24M", 0x04c,
+                                  8, 7,        /* N */
+                                  0, 2,        /* M */
+                                  BIT(31),     /* gate */
+                                  BIT(28),     /* lock */
+                                  CLK_SET_RATE_UNGATE);
+
+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_SET_RATE_PARENT | 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-2x",
+                                            "pll-periph0-2x" };
+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 const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = {
+       { .index = 1, .div = 2 },
+};
+static struct ccu_mux ahb2_clk = {
+       .mux            = {
+               .shift  = 0,
+               .width  = 1,
+               .fixed_predivs  = ahb2_fixed_predivs,
+               .n_predivs      = ARRAY_SIZE(ahb2_fixed_predivs),
+       },
+
+       .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_mipi_dsi_clk,        "bus-mipi-dsi", "ahb1",
+                     0x060, BIT(1), 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_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_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_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_scr_clk,     "bus-scr",      "apb2",
+                     0x06c, BIT(5), 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_uart4_clk,   "bus-uart4",    "apb2",
+                     0x06c, BIT(20), 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 const char * const ths_parents[] = { "osc24M" };
+static struct ccu_div ths_clk = {
+       .enable = BIT(31),
+       .div    = _SUNXI_CCU_DIV_TABLE(0, 2, ths_div_table),
+       .mux    = _SUNXI_CCU_MUX(24, 2),
+       .common = {
+               .reg            = 0x074,
+               .hw.init        = CLK_HW_INIT_PARENTS("ths",
+                                                     ths_parents,
+                                                     &ccu_div_ops,
+                                                     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 const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x",
+                                                   "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 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, 4,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mmc_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), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
+                              0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
+                              0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
+                            0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+
+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_hsic_clk,    "usb-hsic",     "pll-hsic",
+                     0x0cc, BIT(10), 0);
+static SUNXI_CCU_GATE(usb_hsic_12m_clk,        "usb-hsic-12M", "osc12M",
+                     0x0cc, BIT(11), 0);
+static SUNXI_CCU_GATE(usb_ohci0_clk,   "usb-ohci0",    "osc12M",
+                     0x0cc, BIT(16), 0);
+static SUNXI_CCU_GATE(usb_ohci1_clk,   "usb-ohci1",    "usb-ohci0",
+                     0x0cc, BIT(17), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
+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 tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
+static const u8 tcon0_table[] = { 0, 2, };
+static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
+                                    tcon0_table, 0x118, 24, 3, BIT(31),
+                                    CLK_SET_RATE_PARENT);
+
+static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
+static const u8 tcon1_table[] = { 0, 2, };
+static struct ccu_div tcon1_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV(0, 4),
+       .mux            = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table),
+       .common         = {
+               .reg            = 0x11c,
+               .hw.init        = CLK_HW_INIT_PARENTS("tcon1",
+                                                     tcon1_parents,
+                                                     &ccu_div_ops,
+                                                     CLK_SET_RATE_PARENT),
+       },
+};
+
+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-video1", "pll-periph1" };
+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), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(ac_dig_4x_clk,   "ac-dig-4x",    "pll-audio-4x",
+                     0x140, BIT(30), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(avs_clk,         "avs",          "osc24M",
+                     0x144, BIT(31), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
+                                0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+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-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+                                0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
+
+static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
+static const u8 dsi_dphy_table[] = { 0, 2, };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy",
+                                      dsi_dphy_parents, dsi_dphy_table,
+                                      0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
+                            0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+/* Fixed Factor clocks */
+static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0);
+
+/* 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 CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
+                       "pll-periph1", 1, 2, 0);
+static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
+                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_a64_ccu_clks[] = {
+       &pll_cpux_clk.common,
+       &pll_audio_base_clk.common,
+       &pll_video0_clk.common,
+       &pll_ve_clk.common,
+       &pll_ddr0_clk.common,
+       &pll_periph0_clk.common,
+       &pll_periph1_clk.common,
+       &pll_video1_clk.common,
+       &pll_gpu_clk.common,
+       &pll_mipi_clk.common,
+       &pll_hsic_clk.common,
+       &pll_de_clk.common,
+       &pll_ddr1_clk.common,
+       &cpux_clk.common,
+       &axi_clk.common,
+       &ahb1_clk.common,
+       &apb1_clk.common,
+       &apb2_clk.common,
+       &ahb2_clk.common,
+       &bus_mipi_dsi_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_ohci0_clk.common,
+       &bus_ohci1_clk.common,
+       &bus_ve_clk.common,
+       &bus_tcon0_clk.common,
+       &bus_tcon1_clk.common,
+       &bus_deinterlace_clk.common,
+       &bus_csi_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_scr_clk.common,
+       &bus_uart0_clk.common,
+       &bus_uart1_clk.common,
+       &bus_uart2_clk.common,
+       &bus_uart3_clk.common,
+       &bus_uart4_clk.common,
+       &bus_dbg_clk.common,
+       &ths_clk.common,
+       &nand_clk.common,
+       &mmc0_clk.common,
+       &mmc1_clk.common,
+       &mmc2_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_hsic_clk.common,
+       &usb_hsic_12m_clk.common,
+       &usb_ohci0_clk.common,
+       &usb_ohci1_clk.common,
+       &dram_clk.common,
+       &dram_ve_clk.common,
+       &dram_csi_clk.common,
+       &dram_deinterlace_clk.common,
+       &dram_ts_clk.common,
+       &de_clk.common,
+       &tcon0_clk.common,
+       &tcon1_clk.common,
+       &deinterlace_clk.common,
+       &csi_misc_clk.common,
+       &csi_sclk_clk.common,
+       &csi_mclk_clk.common,
+       &ve_clk.common,
+       &ac_dig_clk.common,
+       &ac_dig_4x_clk.common,
+       &avs_clk.common,
+       &hdmi_clk.common,
+       &hdmi_ddc_clk.common,
+       &mbus_clk.common,
+       &dsi_dphy_clk.common,
+       &gpu_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_a64_hw_clks = {
+       .hws    = {
+               [CLK_OSC_12M]           = &osc12M_clk.hw,
+               [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_VIDEO0]        = &pll_video0_clk.common.hw,
+               [CLK_PLL_VIDEO0_2X]     = &pll_video0_2x_clk.hw,
+               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
+               [CLK_PLL_DDR0]          = &pll_ddr0_clk.common.hw,
+               [CLK_PLL_PERIPH0]       = &pll_periph0_clk.common.hw,
+               [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
+               [CLK_PLL_PERIPH1]       = &pll_periph1_clk.common.hw,
+               [CLK_PLL_PERIPH1_2X]    = &pll_periph1_2x_clk.hw,
+               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
+               [CLK_PLL_GPU]           = &pll_gpu_clk.common.hw,
+               [CLK_PLL_MIPI]          = &pll_mipi_clk.common.hw,
+               [CLK_PLL_HSIC]          = &pll_hsic_clk.common.hw,
+               [CLK_PLL_DE]            = &pll_de_clk.common.hw,
+               [CLK_PLL_DDR1]          = &pll_ddr1_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_MIPI_DSI]      = &bus_mipi_dsi_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_OHCI0]         = &bus_ohci0_clk.common.hw,
+               [CLK_BUS_OHCI1]         = &bus_ohci1_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_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_UART4]         = &bus_uart4_clk.common.hw,
+               [CLK_BUS_SCR]           = &bus_scr_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_MMC1]              = &mmc1_clk.common.hw,
+               [CLK_MMC2]              = &mmc2_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_HSIC]          = &usb_hsic_clk.common.hw,
+               [CLK_USB_HSIC_12M]      = &usb_hsic_12m_clk.common.hw,
+               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
+               [CLK_USB_OHCI1]         = &usb_ohci1_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]             = &tcon0_clk.common.hw,
+               [CLK_TCON1]             = &tcon1_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_AC_DIG_4X]         = &ac_dig_4x_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_DSI_DPHY]          = &dsi_dphy_clk.common.hw,
+               [CLK_GPU]               = &gpu_clk.common.hw,
+       },
+       .num    = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_a64_ccu_resets[] = {
+       [RST_USB_PHY0]          =  { 0x0cc, BIT(0) },
+       [RST_USB_PHY1]          =  { 0x0cc, BIT(1) },
+       [RST_USB_HSIC]          =  { 0x0cc, BIT(2) },
+
+       [RST_DRAM]              =  { 0x0f4, BIT(31) },
+       [RST_MBUS]              =  { 0x0fc, BIT(31) },
+
+       [RST_BUS_MIPI_DSI]      =  { 0x2c0, BIT(1) },
+       [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_OHCI0]         =  { 0x2c0, BIT(28) },
+       [RST_BUS_OHCI1]         =  { 0x2c0, BIT(29) },
+
+       [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_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_LVDS]          =  { 0x2c8, BIT(0) },
+
+       [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]          =  { 0x2d8, BIT(0) },
+       [RST_BUS_I2C1]          =  { 0x2d8, BIT(1) },
+       [RST_BUS_I2C2]          =  { 0x2d8, BIT(2) },
+       [RST_BUS_SCR]           =  { 0x2d8, BIT(5) },
+       [RST_BUS_UART0]         =  { 0x2d8, BIT(16) },
+       [RST_BUS_UART1]         =  { 0x2d8, BIT(17) },
+       [RST_BUS_UART2]         =  { 0x2d8, BIT(18) },
+       [RST_BUS_UART3]         =  { 0x2d8, BIT(19) },
+       [RST_BUS_UART4]         =  { 0x2d8, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = {
+       .ccu_clks       = sun50i_a64_ccu_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun50i_a64_ccu_clks),
+
+       .hw_clks        = &sun50i_a64_hw_clks,
+
+       .resets         = sun50i_a64_ccu_resets,
+       .num_resets     = ARRAY_SIZE(sun50i_a64_ccu_resets),
+};
+
+static int sun50i_a64_ccu_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       void __iomem *reg;
+       u32 val;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       /* Force the PLL-Audio-1x divider to 4 */
+       val = readl(reg + SUN50I_A64_PLL_AUDIO_REG);
+       val &= ~GENMASK(19, 16);
+       writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG);
+
+       writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
+
+       return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+}
+
+static const struct of_device_id sun50i_a64_ccu_ids[] = {
+       { .compatible = "allwinner,sun50i-a64-ccu" },
+       { }
+};
+
+static struct platform_driver sun50i_a64_ccu_driver = {
+       .probe  = sun50i_a64_ccu_probe,
+       .driver = {
+               .name   = "sun50i-a64-ccu",
+               .of_match_table = sun50i_a64_ccu_ids,
+       },
+};
+builtin_platform_driver(sun50i_a64_ccu_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
new file mode 100644 (file)
index 0000000..9b3cd24
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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_SUN50I_A64_H_
+#define _CCU_SUN50I_A64_H_
+
+#include <dt-bindings/clock/sun50i-a64-ccu.h>
+#include <dt-bindings/reset/sun50i-a64-ccu.h>
+
+#define CLK_OSC_12M                    0
+#define CLK_PLL_CPUX                   1
+#define CLK_PLL_AUDIO_BASE             2
+#define CLK_PLL_AUDIO                  3
+#define CLK_PLL_AUDIO_2X               4
+#define CLK_PLL_AUDIO_4X               5
+#define CLK_PLL_AUDIO_8X               6
+#define CLK_PLL_VIDEO0                 7
+#define CLK_PLL_VIDEO0_2X              8
+#define CLK_PLL_VE                     9
+#define CLK_PLL_DDR0                   10
+#define CLK_PLL_PERIPH0                        11
+#define CLK_PLL_PERIPH0_2X             12
+#define CLK_PLL_PERIPH1                        13
+#define CLK_PLL_PERIPH1_2X             14
+#define CLK_PLL_VIDEO1                 15
+#define CLK_PLL_GPU                    16
+#define CLK_PLL_MIPI                   17
+#define CLK_PLL_HSIC                   18
+#define CLK_PLL_DE                     19
+#define CLK_PLL_DDR1                   20
+#define CLK_CPUX                       21
+#define CLK_AXI                                22
+#define CLK_APB                                23
+#define CLK_AHB1                       24
+#define CLK_APB1                       25
+#define CLK_APB2                       26
+#define CLK_AHB2                       27
+
+/* All the bus gates are exported */
+
+/* The first bunch of module clocks are exported */
+
+#define CLK_USB_OHCI0_12M              90
+
+#define CLK_USB_OHCI1_12M              92
+
+#define CLK_DRAM                       94
+
+/* All the DRAM gates are exported */
+
+/* Some more module clocks are exported */
+
+#define CLK_MBUS                       112
+
+/* And the DSI and GPU module clock is exported */
+
+#define CLK_NUMBER                     (CLK_GPU + 1)
+
+#endif /* _CCU_SUN50I_A64_H_ */
index 2646d980087bf3011205156a068f48b97a9b81bf..5c6d37bdf247cfef1b4da1bcf185d1b56082f036 100644 (file)
@@ -344,10 +344,10 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
 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);
+                              0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
-                              0x0b4, 16, 2, BIT(31), 0);
+                              0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 /* TODO: the parent for most of the USB clocks is not known */
 static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",     "osc24M",
@@ -415,7 +415,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
                             0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(ac_dig_clk,      "ac-dig",       "pll-audio",
-                     0x140, BIT(31), 0);
+                     0x140, BIT(31), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(avs_clk,         "avs",          "osc24M",
                      0x144, BIT(31), 0);
 
index 4d70590f05e36efe4171a93dc46db0884d3d68a2..21c427d86f289b2a588cc41190525c408e2be3bf 100644 (file)
@@ -394,16 +394,16 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
 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);
+                              0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
-                              0x0b4, 16, 2, BIT(31), 0);
+                              0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
-                              0x0b8, 16, 2, BIT(31), 0);
+                              0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
-                            0x0c0, 0, 4, BIT(31), 0);
+                            0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",     "osc24M",
                      0x0cc, BIT(8), 0);
@@ -466,7 +466,7 @@ 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);
+                     0x140, BIT(31), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(avs_clk,         "avs",          "osc24M",
                      0x144, BIT(31), 0);
 
index 34c338832c0da6f5e9635bc08781f5f78626283b..06540f7cf41cba1deea274ef30a0a06003160c37 100644 (file)
@@ -20,7 +20,7 @@
 #include "ccu_mux.h"
 
 /**
- * struct _ccu_div - Internal divider description
+ * struct ccu_div_internal - Internal divider description
  * @shift: Bit offset of the divider in its register
  * @width: Width of the divider field in its register
  * @max: Maximum value allowed for that divider. This is the
@@ -36,7 +36,7 @@
  * It is basically a wrapper around the clk_divider functions
  * arguments.
  */
-struct _ccu_div {
+struct ccu_div_internal {
        u8                      shift;
        u8                      width;
 
@@ -78,7 +78,7 @@ struct _ccu_div {
 struct ccu_div {
        u32                     enable;
 
-       struct _ccu_div         div;
+       struct ccu_div_internal         div;
        struct ccu_mux_internal mux;
        struct ccu_common       common;
 };
index 5c4b10cd15b5e96d663326f35343968555805365..8b5eb7756bf7dca2cf72543c40ac331c91d323fa 100644 (file)
@@ -14,7 +14,7 @@
 #include "ccu_frac.h"
 
 bool ccu_frac_helper_is_enabled(struct ccu_common *common,
-                               struct _ccu_frac *cf)
+                               struct ccu_frac_internal *cf)
 {
        if (!(common->features & CCU_FEATURE_FRACTIONAL))
                return false;
@@ -23,7 +23,7 @@ bool ccu_frac_helper_is_enabled(struct ccu_common *common,
 }
 
 void ccu_frac_helper_enable(struct ccu_common *common,
-                           struct _ccu_frac *cf)
+                           struct ccu_frac_internal *cf)
 {
        unsigned long flags;
        u32 reg;
@@ -38,7 +38,7 @@ void ccu_frac_helper_enable(struct ccu_common *common,
 }
 
 void ccu_frac_helper_disable(struct ccu_common *common,
-                            struct _ccu_frac *cf)
+                            struct ccu_frac_internal *cf)
 {
        unsigned long flags;
        u32 reg;
@@ -53,7 +53,7 @@ void ccu_frac_helper_disable(struct ccu_common *common,
 }
 
 bool ccu_frac_helper_has_rate(struct ccu_common *common,
-                             struct _ccu_frac *cf,
+                             struct ccu_frac_internal *cf,
                              unsigned long rate)
 {
        if (!(common->features & CCU_FEATURE_FRACTIONAL))
@@ -63,7 +63,7 @@ bool ccu_frac_helper_has_rate(struct ccu_common *common,
 }
 
 unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
-                                       struct _ccu_frac *cf)
+                                       struct ccu_frac_internal *cf)
 {
        u32 reg;
 
@@ -84,7 +84,7 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
 }
 
 int ccu_frac_helper_set_rate(struct ccu_common *common,
-                            struct _ccu_frac *cf,
+                            struct ccu_frac_internal *cf,
                             unsigned long rate)
 {
        unsigned long flags;
index e4c670b1cdfea628e9ebcbc9b2f2030b26545040..7b1ee380156fa253b92bfbda098fe0f15b3050b5 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "ccu_common.h"
 
-struct _ccu_frac {
+struct ccu_frac_internal {
        u32             enable;
        u32             select;
 
@@ -33,21 +33,21 @@ struct _ccu_frac {
        }
 
 bool ccu_frac_helper_is_enabled(struct ccu_common *common,
-                               struct _ccu_frac *cf);
+                               struct ccu_frac_internal *cf);
 void ccu_frac_helper_enable(struct ccu_common *common,
-                           struct _ccu_frac *cf);
+                           struct ccu_frac_internal *cf);
 void ccu_frac_helper_disable(struct ccu_common *common,
-                            struct _ccu_frac *cf);
+                            struct ccu_frac_internal *cf);
 
 bool ccu_frac_helper_has_rate(struct ccu_common *common,
-                             struct _ccu_frac *cf,
+                             struct ccu_frac_internal *cf,
                              unsigned long rate);
 
 unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
-                                       struct _ccu_frac *cf);
+                                       struct ccu_frac_internal *cf);
 
 int ccu_frac_helper_set_rate(struct ccu_common *common,
-                            struct _ccu_frac *cf,
+                            struct ccu_frac_internal *cf,
                             unsigned long rate);
 
 #endif /* _CCU_FRAC_H_ */
index edf9215ea8ccdfacab996ac8117b635dfa379b4e..915625e97d98b6ab72753486207dedf0b61fe310 100644 (file)
@@ -29,8 +29,8 @@
 struct ccu_mp {
        u32                     enable;
 
-       struct _ccu_div         m;
-       struct _ccu_div         p;
+       struct ccu_div_internal         m;
+       struct ccu_div_internal         p;
        struct ccu_mux_internal mux;
        struct ccu_common       common;
 };
index 010e9424691dee4aff6c80a858554948afcf556f..678b6cb49f01b7b176ca84f425ee5a91d6486728 100644 (file)
 #include "ccu_gate.h"
 #include "ccu_mult.h"
 
+struct _ccu_mult {
+       unsigned long   mult, min, max;
+};
+
 static void ccu_mult_find_best(unsigned long parent, unsigned long rate,
-                              unsigned int max_n, unsigned int *n)
+                              struct _ccu_mult *mult)
 {
-       *n = rate / parent;
+       int _mult;
+
+       _mult = rate / parent;
+       if (_mult < mult->min)
+               _mult = mult->min;
+
+       if (_mult > mult->max)
+               _mult = mult->max;
+
+       mult->mult = _mult;
 }
 
 static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
@@ -25,11 +38,13 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
                                        void *data)
 {
        struct ccu_mult *cm = data;
-       unsigned int n;
+       struct _ccu_mult _cm;
 
-       ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n);
+       _cm.min = 1;
+       _cm.max = 1 << cm->mult.width;
+       ccu_mult_find_best(parent_rate, rate, &_cm);
 
-       return parent_rate * n;
+       return parent_rate * _cm.mult;
 }
 
 static void ccu_mult_disable(struct clk_hw *hw)
@@ -83,21 +98,23 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
                           unsigned long parent_rate)
 {
        struct ccu_mult *cm = hw_to_ccu_mult(hw);
+       struct _ccu_mult _cm;
        unsigned long flags;
-       unsigned int n;
        u32 reg;
 
        ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
                                                &parent_rate);
 
-       ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n);
+       _cm.min = cm->mult.min;
+       _cm.max = 1 << cm->mult.width;
+       ccu_mult_find_best(parent_rate, rate, &_cm);
 
        spin_lock_irqsave(cm->common.lock, flags);
 
        reg = readl(cm->common.base + cm->common.reg);
        reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift);
 
-       writel(reg | ((n - 1) << cm->mult.shift),
+       writel(reg | ((_cm.mult - 1) << cm->mult.shift),
               cm->common.base + cm->common.reg);
 
        spin_unlock_irqrestore(cm->common.lock, flags);
index 5d2c8dc14073337a3573f61df8cefdfd1a09c694..c1a2134bdc711367d239b237f5dae01f1e6af07b 100644 (file)
@@ -4,21 +4,26 @@
 #include "ccu_common.h"
 #include "ccu_mux.h"
 
-struct _ccu_mult {
+struct ccu_mult_internal {
        u8      shift;
        u8      width;
+       u8      min;
 };
 
-#define _SUNXI_CCU_MULT(_shift, _width)                \
-       {                                       \
-               .shift  = _shift,               \
-               .width  = _width,               \
+#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min)      \
+       {                                               \
+               .shift  = _shift,                       \
+               .width  = _width,                       \
+               .min    = _min,                         \
        }
 
+#define _SUNXI_CCU_MULT(_shift, _width)                \
+       _SUNXI_CCU_MULT_MIN(_shift, _width, 1)
+
 struct ccu_mult {
        u32                     enable;
 
-       struct _ccu_mult        mult;
+       struct ccu_mult_internal        mult;
        struct ccu_mux_internal mux;
        struct ccu_common       common;
 };
index d6fafb397489caaebee47a7c086bdccda7c1244f..eaf0fdf78d2ba278299c8eb93c4b40eb20ce4201 100644 (file)
@@ -9,21 +9,24 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/rational.h>
 
 #include "ccu_gate.h"
 #include "ccu_nk.h"
 
+struct _ccu_nk {
+       unsigned long   n, min_n, max_n;
+       unsigned long   k, min_k, max_k;
+};
+
 static 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)
+                            struct _ccu_nk *nk)
 {
        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++) {
+       for (_k = nk->min_k; _k <= nk->max_k; _k++) {
+               for (_n = nk->min_n; _n <= nk->max_n; _n++) {
                        unsigned long tmp_rate = parent * _n * _k;
 
                        if (tmp_rate > rate)
@@ -37,8 +40,8 @@ static void ccu_nk_find_best(unsigned long parent, unsigned long rate,
                }
        }
 
-       *k = best_k;
-       *n = best_n;
+       nk->k = best_k;
+       nk->n = best_n;
 }
 
 static void ccu_nk_disable(struct clk_hw *hw)
@@ -89,16 +92,19 @@ 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;
+       struct _ccu_nk _nk;
 
        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);
+       _nk.min_n = nk->n.min;
+       _nk.max_n = 1 << nk->n.width;
+       _nk.min_k = nk->k.min;
+       _nk.max_k = 1 << nk->k.width;
+
+       ccu_nk_find_best(*parent_rate, rate, &_nk);
+       rate = *parent_rate * _nk.n * _nk.k;
 
-       rate = *parent_rate * n * k;
        if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
                rate = rate / nk->fixed_post_div;
 
@@ -110,15 +116,18 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct ccu_nk *nk = hw_to_ccu_nk(hw);
        unsigned long flags;
-       unsigned int n, k;
+       struct _ccu_nk _nk;
        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);
+       _nk.min_n = nk->n.min;
+       _nk.max_n = 1 << nk->n.width;
+       _nk.min_k = nk->k.min;
+       _nk.max_k = 1 << nk->k.width;
+
+       ccu_nk_find_best(parent_rate, rate, &_nk);
 
        spin_lock_irqsave(nk->common.lock, flags);
 
@@ -126,7 +135,7 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
        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),
+       writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift),
               nk->common.base + nk->common.reg);
 
        spin_unlock_irqrestore(nk->common.lock, flags);
index 4b52da0c29fee5e544242d2e765d472eb1634ed1..437836b806961a3d65be2e20b5c5115a3a43a588 100644 (file)
@@ -30,8 +30,8 @@ struct ccu_nk {
        u32                     enable;
        u32                     lock;
 
-       struct _ccu_mult        n;
-       struct _ccu_mult        k;
+       struct ccu_mult_internal        n;
+       struct ccu_mult_internal        k;
 
        unsigned int            fixed_post_div;
 
index 059fdc3b4f96397d8de0c7457677e30cd8858210..9b840a47a94d8774aef65388058dfc7f0d589c5d 100644 (file)
@@ -9,15 +9,14 @@
  */
 
 #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;
+       unsigned long   n, min_n, max_n;
+       unsigned long   k, min_k, max_k;
+       unsigned long   m, min_m, max_m;
 };
 
 static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
@@ -27,22 +26,22 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
        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;
+       for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
+               for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
+                       for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+                               unsigned long tmp_rate;
+
+                               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;
+                               }
+                       }
                }
        }
 
@@ -101,8 +100,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
        struct ccu_nkm *nkm = data;
        struct _ccu_nkm _nkm;
 
+       _nkm.min_n = nkm->n.min;
        _nkm.max_n = 1 << nkm->n.width;
+       _nkm.min_k = nkm->k.min;
        _nkm.max_k = 1 << nkm->k.width;
+       _nkm.min_m = 1;
        _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
 
        ccu_nkm_find_best(parent_rate, rate, &_nkm);
@@ -127,8 +129,11 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long flags;
        u32 reg;
 
+       _nkm.min_n = nkm->n.min;
        _nkm.max_n = 1 << nkm->n.width;
+       _nkm.min_k = nkm->k.min;
        _nkm.max_k = 1 << nkm->k.width;
+       _nkm.min_m = 1;
        _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
 
        ccu_nkm_find_best(parent_rate, rate, &_nkm);
index 35493fddd8ab3f07a30388e5bd74eb3d70026395..34580894f4d1cd7b3f7df76a780735d58d72173e 100644 (file)
@@ -29,9 +29,9 @@ struct ccu_nkm {
        u32                     enable;
        u32                     lock;
 
-       struct _ccu_mult        n;
-       struct _ccu_mult        k;
-       struct _ccu_div         m;
+       struct ccu_mult_internal        n;
+       struct ccu_mult_internal        k;
+       struct ccu_div_internal         m;
        struct ccu_mux_internal mux;
 
        struct ccu_common       common;
index 9769dee99511abeb3bab68106572ad56a0a9e0c5..684c42da3ebbf91ac46ab1e06f7ea378b454760d 100644 (file)
@@ -9,16 +9,15 @@
  */
 
 #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;
+       unsigned long   n, min_n, max_n;
+       unsigned long   k, min_k, max_k;
+       unsigned long   m, min_m, max_m;
+       unsigned long   p, min_p, max_p;
 };
 
 static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
@@ -28,25 +27,25 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
        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 = 1; _p <= nkmp->max_p; _p <<= 1) {
-                       unsigned long tmp_rate;
-
-                       rational_best_approximation(rate / _k, parent / _p,
-                                                   nkmp->max_n, nkmp->max_m,
-                                                   &_n, &_m);
-
-                       tmp_rate = parent * _n * _k / (_m * _p);
-
-                       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;
+       for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) {
+               for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) {
+                       for (_m = nkmp->min_m; _m <= nkmp->max_m; _m++) {
+                               for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) {
+                                       unsigned long tmp_rate;
+
+                                       tmp_rate = parent * _n * _k / (_m * _p);
+
+                                       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;
+                                       }
+                               }
                        }
                }
        }
@@ -108,9 +107,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
        struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
        struct _ccu_nkmp _nkmp;
 
+       _nkmp.min_n = nkmp->n.min;
        _nkmp.max_n = 1 << nkmp->n.width;
+       _nkmp.min_k = nkmp->k.min;
        _nkmp.max_k = 1 << nkmp->k.width;
+       _nkmp.min_m = 1;
        _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+       _nkmp.min_p = 1;
        _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
 
        ccu_nkmp_find_best(*parent_rate, rate, &_nkmp);
@@ -126,9 +129,13 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long flags;
        u32 reg;
 
+       _nkmp.min_n = 1;
        _nkmp.max_n = 1 << nkmp->n.width;
+       _nkmp.min_k = 1;
        _nkmp.max_k = 1 << nkmp->k.width;
+       _nkmp.min_m = 1;
        _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+       _nkmp.min_p = 1;
        _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
 
        ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
index 5adb0c92a6145fbfbf2034ad7b52c6f39a4d0380..a82facbc61446d6c0cc36f4771c70aaf17090574 100644 (file)
@@ -29,10 +29,10 @@ 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_mult_internal        n;
+       struct ccu_mult_internal        k;
+       struct ccu_div_internal         m;
+       struct ccu_div_internal         p;
 
        struct ccu_common       common;
 };
index b61bdd8c7a7fea1a9cdcaf084c15be62309415c8..c9f3b6c982f02e4fd2cacea8ddd516b7344cc239 100644 (file)
@@ -9,12 +9,42 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/rational.h>
 
 #include "ccu_frac.h"
 #include "ccu_gate.h"
 #include "ccu_nm.h"
 
+struct _ccu_nm {
+       unsigned long   n, min_n, max_n;
+       unsigned long   m, min_m, max_m;
+};
+
+static void ccu_nm_find_best(unsigned long parent, unsigned long rate,
+                            struct _ccu_nm *nm)
+{
+       unsigned long best_rate = 0;
+       unsigned long best_n = 0, best_m = 0;
+       unsigned long _n, _m;
+
+       for (_n = nm->min_n; _n <= nm->max_n; _n++) {
+               for (_m = nm->min_m; _m <= nm->max_m; _m++) {
+                       unsigned long tmp_rate = parent * _n  / _m;
+
+                       if (tmp_rate > rate)
+                               continue;
+
+                       if ((rate - tmp_rate) < (rate - best_rate)) {
+                               best_rate = tmp_rate;
+                               best_n = _n;
+                               best_m = _m;
+                       }
+               }
+       }
+
+       nm->n = best_n;
+       nm->m = best_m;
+}
+
 static void ccu_nm_disable(struct clk_hw *hw)
 {
        struct ccu_nm *nm = hw_to_ccu_nm(hw);
@@ -61,24 +91,24 @@ 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 max_n, max_m;
-       unsigned long n, m;
+       struct _ccu_nm _nm;
 
-       max_n = 1 << nm->n.width;
-       max_m = nm->m.max ?: 1 << nm->m.width;
+       _nm.min_n = nm->n.min;
+       _nm.max_n = 1 << nm->n.width;
+       _nm.min_m = 1;
+       _nm.max_m = nm->m.max ?: 1 << nm->m.width;
 
-       rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m);
+       ccu_nm_find_best(*parent_rate, rate, &_nm);
 
-       return *parent_rate * n / m;
+       return *parent_rate * _nm.n / _nm.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);
+       struct _ccu_nm _nm;
        unsigned long flags;
-       unsigned long max_n, max_m;
-       unsigned long n, m;
        u32 reg;
 
        if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
@@ -86,10 +116,12 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
        else
                ccu_frac_helper_disable(&nm->common, &nm->frac);
 
-       max_n = 1 << nm->n.width;
-       max_m = nm->m.max ?: 1 << nm->m.width;
+       _nm.min_n = 1;
+       _nm.max_n = 1 << nm->n.width;
+       _nm.min_m = 1;
+       _nm.max_m = nm->m.max ?: 1 << nm->m.width;
 
-       rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m);
+       ccu_nm_find_best(parent_rate, rate, &_nm);
 
        spin_lock_irqsave(nm->common.lock, flags);
 
@@ -97,7 +129,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
        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),
+       writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift),
               nm->common.base + nm->common.reg);
 
        spin_unlock_irqrestore(nm->common.lock, flags);
index 0b7bcd33a2df7ccd36d7718bde5f961f70a57333..e87fd186da7830cf4d79bfb5c8b621154735487c 100644 (file)
@@ -30,9 +30,9 @@ struct ccu_nm {
        u32                     enable;
        u32                     lock;
 
-       struct _ccu_mult        n;
-       struct _ccu_div         m;
-       struct _ccu_frac        frac;
+       struct ccu_mult_internal        n;
+       struct ccu_div_internal         m;
+       struct ccu_frac_internal        frac;
 
        struct ccu_common       common;
 };
index e54266cc1c51f36321627e0a196244305a1e20eb..4417ae129ac7c95dc6ca280f8c0ed2ac999e725b 100644 (file)
@@ -24,7 +24,7 @@
 #include "clk-factors.h"
 
 /**
- * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
  * MOD0 rate is calculated as follows
  * rate = (parent_rate >> p) / (m + 1);
  */
index c205809ba58065aaf88d488dfc8112f149bb4e90..ad1c1cc829cba46591ba458e3b637441b20f3638 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <soc/tegra/fuse.h>
 
@@ -148,7 +148,6 @@ static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
        { .compatible = "nvidia,tegra124-dfll", },
        { },
 };
-MODULE_DEVICE_TABLE(of, tegra124_dfll_fcpu_of_match);
 
 static const struct dev_pm_ops tegra124_dfll_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
@@ -164,20 +163,4 @@ static struct platform_driver tegra124_dfll_fcpu_driver = {
                .pm = &tegra124_dfll_pm_ops,
        },
 };
-
-static int __init tegra124_dfll_fcpu_init(void)
-{
-       return platform_driver_register(&tegra124_dfll_fcpu_driver);
-}
-module_init(tegra124_dfll_fcpu_init);
-
-static void __exit tegra124_dfll_fcpu_exit(void)
-{
-       platform_driver_unregister(&tegra124_dfll_fcpu_driver);
-}
-module_exit(tegra124_dfll_fcpu_exit);
-
-MODULE_DESCRIPTION("Tegra124 DFLL clock source driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Aleksandr Frid <afrid@nvidia.com>");
-MODULE_AUTHOR("Paul Walmsley <pwalmsley@nvidia.com>");
+builtin_platform_driver(tegra124_dfll_fcpu_driver);
index 624115e82ff92a6c982db5e65aa6e73c95732d5a..da9e8e7b5ce5c967daf791372be66f07e4ebdb82 100644 (file)
@@ -92,19 +92,19 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
 
 /**
  * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables
- * @cvb_tables: array of CVB tables
- * @sz: size of the previously mentioned array
+ * @dev: the struct device * for which the OPP table is built
+ * @tables: array of CVB tables
+ * @count: size of the previously mentioned array
  * @process_id: process id of the HW module
  * @speedo_id: speedo id of the HW module
  * @speedo_value: speedo value of the HW module
- * @max_rate: highest safe clock rate
- * @opp_dev: the struct device * for which the OPP table is built
+ * @max_freq: highest safe clock rate
  *
  * On Tegra, a CVB table encodes the relationship between operating voltage
  * and safe maximal frequency for a given module (e.g. GPU or CPU). This
  * function calculates the optimal voltage-frequency operating points
  * for the given arguments and exports them via the OPP library for the
- * given @opp_dev. Returns a pointer to the struct cvb_table that matched
+ * given @dev. Returns a pointer to the struct cvb_table that matched
  * or an ERR_PTR on failure.
  */
 const struct cvb_table *
index 8831e1a05367ad9c7473e3ee723adc3f29dc9936..11d8aa3ec18604a7ce5c04ddded50ff660f554c1 100644 (file)
 
 #include "clock.h"
 
-/*
- * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
- * that are sourced by DPLL5, and both of these require this clock
- * to be at 120 MHz for proper operation.
- */
-#define DPLL5_FREQ_FOR_USBHOST         120000000
-
 #define OMAP3430ES2_ST_DSS_IDLE_SHIFT                  1
 #define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT             5
 #define OMAP3430ES2_ST_SSI_IDLE_SHIFT                  8
@@ -546,14 +539,21 @@ void __init omap3_clk_lock_dpll5(void)
        struct clk *dpll5_clk;
        struct clk *dpll5_m2_clk;
 
+       /*
+        * Errata sprz319f advisory 2.1 documents a USB host clock drift issue
+        * that can be worked around using specially crafted dpll5 settings
+        * with a dpll5_m2 divider set to 8. Set the dpll5 rate to 8x the USB
+        * host clock rate, its .set_rate handler() will detect that frequency
+        * and use the errata settings.
+        */
        dpll5_clk = clk_get(NULL, "dpll5_ck");
-       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_set_rate(dpll5_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST * 8);
        clk_prepare_enable(dpll5_clk);
 
-       /* Program dpll5_m2_clk divider for no division */
+       /* Program dpll5_m2_clk divider */
        dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
        clk_prepare_enable(dpll5_m2_clk);
-       clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_set_rate(dpll5_m2_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST);
 
        clk_disable_unprepare(dpll5_m2_clk);
        clk_disable_unprepare(dpll5_clk);
index bfa17d33ef3b948e8c679e7ef6609fb0ed4ab1c1..9fd6043314eb3968815750b084664d593e9cde51 100644 (file)
@@ -201,7 +201,6 @@ static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK(NULL, "atl_dpll_clk_mux", "atl_dpll_clk_mux"),
        DT_CLK(NULL, "atl_gfclk_mux", "atl_gfclk_mux"),
        DT_CLK(NULL, "dcan1_sys_clk_mux", "dcan1_sys_clk_mux"),
-       DT_CLK(NULL, "gmac_gmii_ref_clk_div", "gmac_gmii_ref_clk_div"),
        DT_CLK(NULL, "gmac_rft_clk_mux", "gmac_rft_clk_mux"),
        DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"),
        DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"),
index c77333230bdf22d20dac90611aa4461a28c86321..45d05339d583fad8c3beee9755534eb4ebe4f0cd 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
@@ -295,31 +295,17 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int of_dra7_atl_clk_remove(struct platform_device *pdev)
-{
-       pm_runtime_disable(&pdev->dev);
-
-       return 0;
-}
-
 static const struct of_device_id of_dra7_atl_clk_match_tbl[] = {
        { .compatible = "ti,dra7-atl", },
        {},
 };
-MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
 
 static struct platform_driver dra7_atl_clk_driver = {
        .driver = {
                .name = "dra7-atl",
+               .suppress_bind_attrs = true,
                .of_match_table = of_dra7_atl_clk_match_tbl,
        },
        .probe = of_dra7_atl_clk_probe,
-       .remove = of_dra7_atl_clk_remove,
 };
-
-module_platform_driver(dra7_atl_clk_driver);
-
-MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic");
-MODULE_ALIAS("platform:dra7-atl-clock");
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(dra7_atl_clk_driver);
index 90f3f472ae1c4c70e537c69a7a58e2d1168abddd..13c37f48d9d69d6f4b950671cc735b1ed49fefba 100644 (file)
@@ -257,11 +257,20 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
 
+/*
+ * OMAP3_DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define OMAP3_DPLL5_FREQ_FOR_USBHOST   120000000
+
 unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
                         unsigned long parent_rate);
 int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
                                    unsigned long parent_rate, u8 index);
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+                        unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
 
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
index 9fc8754a6e6160081c067a5a96b364b8bf0ec40a..4b9a419d8e14133d04bb405b84d79da9b6bc5be5 100644 (file)
@@ -114,6 +114,18 @@ static const struct clk_ops omap3_dpll_ck_ops = {
        .round_rate     = &omap2_dpll_round_rate,
 };
 
+static const struct clk_ops omap3_dpll5_ck_ops = {
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .set_rate       = &omap3_dpll5_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+
 static const struct clk_ops omap3_dpll_per_ck_ops = {
        .enable         = &omap3_noncore_dpll_enable,
        .disable        = &omap3_noncore_dpll_disable,
@@ -474,7 +486,12 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
+       if ((of_machine_is_compatible("ti,omap3630") ||
+            of_machine_is_compatible("ti,omap36xx")) &&
+           !strcmp(node->name, "dpll5_ck"))
+               of_ti_dpll_setup(node, &omap3_dpll5_ck_ops, &dd);
+       else
+               of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
               of_ti_omap3_dpll_setup);
index 88f2ce81ba55988164c9e77657b78b65ac65a3a8..4cdd28a25584424f5d5bc9730abf5e7a1d8b6bb7 100644 (file)
@@ -838,3 +838,70 @@ int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
        return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
                                                      index);
 }
+
+/* Apply DM3730 errata sprz319 advisory 2.1. */
+static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
+                                    unsigned long parent_rate)
+{
+       struct omap3_dpll5_settings {
+               unsigned int rate, m, n;
+       };
+
+       static const struct omap3_dpll5_settings precomputed[] = {
+               /*
+                * From DM3730 errata advisory 2.1, table 35 and 36.
+                * The N value is increased by 1 compared to the tables as the
+                * errata lists register values while last_rounded_field is the
+                * real divider value.
+                */
+               { 12000000,  80,  0 + 1 },
+               { 13000000, 443,  5 + 1 },
+               { 19200000,  50,  0 + 1 },
+               { 26000000, 443, 11 + 1 },
+               { 38400000,  25,  0 + 1 }
+       };
+
+       const struct omap3_dpll5_settings *d;
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *dd;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
+               if (parent_rate == precomputed[i].rate)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(precomputed))
+               return false;
+
+       d = &precomputed[i];
+
+       /* Update the M, N and rounded rate values and program the DPLL. */
+       dd = clk->dpll_data;
+       dd->last_rounded_m = d->m;
+       dd->last_rounded_n = d->n;
+       dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
+       omap3_noncore_dpll_program(clk, 0);
+
+       return true;
+}
+
+/**
+ * omap3_dpll5_set_rate - set rate for omap3 dpll5
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
+ * the DPLL is used for USB host (detected through the requested rate).
+ */
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+                        unsigned long parent_rate)
+{
+       if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
+               if (omap3_dpll5_apply_errata(hw, parent_rate))
+                       return 0;
+       }
+
+       return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
index f27b360329caa8053cce244e26872c1241fd04b6..665d1d65a90e5a39084b2ec79eab717e9aa0fe95 100644 (file)
@@ -1,8 +1,11 @@
 obj-y  += clk-uniphier-core.o
+
+obj-y  += clk-uniphier-cpugear.o
 obj-y  += clk-uniphier-fixed-factor.o
 obj-y  += clk-uniphier-fixed-rate.o
 obj-y  += clk-uniphier-gate.o
 obj-y  += clk-uniphier-mux.o
+
 obj-y  += clk-uniphier-sys.o
 obj-y  += clk-uniphier-mio.o
 obj-y  += clk-uniphier-peri.o
index 26c53f7963a438dcaaac252229cea31419ab44ea..0007218ce6a08d8f5874ec7aa1f312d06c87be1d 100644 (file)
@@ -27,6 +27,9 @@ static struct clk_hw *uniphier_clk_register(struct device *dev,
                                        const struct uniphier_clk_data *data)
 {
        switch (data->type) {
+       case UNIPHIER_CLK_TYPE_CPUGEAR:
+               return uniphier_clk_register_cpugear(dev, regmap, data->name,
+                                                    &data->data.cpugear);
        case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
                return uniphier_clk_register_fixed_factor(dev, data->name,
                                                          &data->data.factor);
diff --git a/drivers/clk/uniphier/clk-uniphier-cpugear.c b/drivers/clk/uniphier/clk-uniphier-cpugear.c
new file mode 100644 (file)
index 0000000..9bff26e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.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/delay.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_CLK_CPUGEAR_STAT      0       /* status */
+#define UNIPHIER_CLK_CPUGEAR_SET       4       /* set */
+#define UNIPHIER_CLK_CPUGEAR_UPD       8       /* update */
+#define   UNIPHIER_CLK_CPUGEAR_UPD_BIT BIT(0)
+
+struct uniphier_clk_cpugear {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       unsigned int regbase;
+       unsigned int mask;
+};
+
+#define to_uniphier_clk_cpugear(_hw) \
+                       container_of(_hw, struct uniphier_clk_cpugear, hw)
+
+static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+       int ret;
+       unsigned int val;
+
+       ret = regmap_write_bits(gear->regmap,
+                               gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+                               gear->mask, index);
+       if (ret)
+               return ret;
+
+       ret = regmap_write_bits(gear->regmap,
+                               gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+                               UNIPHIER_CLK_CPUGEAR_UPD_BIT,
+                               UNIPHIER_CLK_CPUGEAR_UPD_BIT);
+       if (ret)
+               return ret;
+
+       return regmap_read_poll_timeout(gear->regmap,
+                               gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
+                               val, !(val & UNIPHIER_CLK_CPUGEAR_UPD_BIT),
+                               0, 1);
+}
+
+static u8 uniphier_clk_cpugear_get_parent(struct clk_hw *hw)
+{
+       struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+       int num_parents = clk_hw_get_num_parents(hw);
+       int ret;
+       unsigned int val;
+
+       ret = regmap_read(gear->regmap,
+                         gear->regbase + UNIPHIER_CLK_CPUGEAR_STAT, &val);
+       if (ret)
+               return ret;
+
+       val &= gear->mask;
+
+       return val < num_parents ? val : -EINVAL;
+}
+
+static const struct clk_ops uniphier_clk_cpugear_ops = {
+       .determine_rate = __clk_mux_determine_rate,
+       .set_parent = uniphier_clk_cpugear_set_parent,
+       .get_parent = uniphier_clk_cpugear_get_parent,
+};
+
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+                                        struct regmap *regmap,
+                                        const char *name,
+                               const struct uniphier_clk_cpugear_data *data)
+{
+       struct uniphier_clk_cpugear *gear;
+       struct clk_init_data init;
+       int ret;
+
+       gear = devm_kzalloc(dev, sizeof(*gear), GFP_KERNEL);
+       if (!gear)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &uniphier_clk_cpugear_ops;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.parent_names = data->parent_names;
+       init.num_parents = data->num_parents,
+
+       gear->regmap = regmap;
+       gear->regbase = data->regbase;
+       gear->mask = data->mask;
+       gear->hw.init = &init;
+
+       ret = devm_clk_hw_register(dev, &gear->hw);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return &gear->hw;
+}
index 5d029991047ddb7fdda7807d11d2d3dc99978279..d049316c1c0f20442065f92ce7c2156236edcb73 100644 (file)
@@ -125,16 +125,35 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
 };
 
 const struct uniphier_clk_data uniphier_ld11_sys_clk_data[] = {
+       UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 392, 5),         /* 1960 MHz */
+       UNIPHIER_CLK_FACTOR("mpll", -1, "ref", 64, 1),          /* 1600 MHz */
        UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1),          /* 2000 MHz */
+       UNIPHIER_CLK_FACTOR("vspll", -1, "ref", 80, 1),         /* 2000 MHz */
        UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34),
        UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40),
        UNIPHIER_LD11_SYS_CLK_STDMAC(8),                        /* HSC, MIO */
        UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25),
+       /* CPU gears */
+       UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
+       UNIPHIER_CLK_DIV4("mpll", 2, 3, 4, 8),
+       UNIPHIER_CLK_DIV3("spll", 3, 4, 8),
+       /* Note: both gear1 and gear4 are spll/4.  This is not a bug. */
+       UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8,
+                            "cpll/2", "spll/4", "cpll/3", "spll/3",
+                            "spll/4", "spll/8", "cpll/4", "cpll/8"),
+       UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8,
+                            "mpll/2", "spll/4", "mpll/3", "spll/3",
+                            "spll/4", "spll/8", "mpll/4", "mpll/8"),
        { /* sentinel */ }
 };
 
 const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
+       UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 88, 1),          /* ARM: 2200 MHz */
+       UNIPHIER_CLK_FACTOR("gppll", -1, "ref", 52, 1),         /* Mali: 1300 MHz */
+       UNIPHIER_CLK_FACTOR("mpll", -1, "ref", 64, 1),          /* Codec: 1600 MHz */
        UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1),          /* 2000 MHz */
+       UNIPHIER_CLK_FACTOR("s2pll", -1, "ref", 88, 1),         /* IPP: 2200 MHz */
+       UNIPHIER_CLK_FACTOR("vppll", -1, "ref", 504, 5),        /* 2520 MHz */
        UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34),
        UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40),
        UNIPHIER_LD20_SYS_CLK_SD,
@@ -147,5 +166,18 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
        UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14),
        UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12),
        UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13),
+       /* CPU gears */
+       UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
+       UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8),
+       UNIPHIER_CLK_DIV4("s2pll", 2, 3, 4, 8),
+       UNIPHIER_CLK_CPUGEAR("cpu-ca72", 32, 0x8000, 0xf, 8,
+                            "cpll/2", "spll/2", "cpll/3", "spll/3",
+                            "spll/4", "spll/8", "cpll/4", "cpll/8"),
+       UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8,
+                            "cpll/2", "spll/2", "cpll/3", "spll/3",
+                            "spll/4", "spll/8", "cpll/4", "cpll/8"),
+       UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8,
+                            "s2pll/2", "spll/2", "s2pll/3", "spll/3",
+                            "spll/4", "spll/8", "s2pll/4", "s2pll/8"),
        { /* sentinel */ }
 };
index 0244dba1f4cf554567c37bd15978bd8813fc3be9..01c16ecec48f79608f446ff41bf6caf5a6432c69 100644 (file)
@@ -20,15 +20,24 @@ struct clk_hw;
 struct device;
 struct regmap;
 
-#define UNIPHIER_CLK_MUX_MAX_PARENTS   8
+#define UNIPHIER_CLK_CPUGEAR_MAX_PARENTS       16
+#define UNIPHIER_CLK_MUX_MAX_PARENTS           8
 
 enum uniphier_clk_type {
+       UNIPHIER_CLK_TYPE_CPUGEAR,
        UNIPHIER_CLK_TYPE_FIXED_FACTOR,
        UNIPHIER_CLK_TYPE_FIXED_RATE,
        UNIPHIER_CLK_TYPE_GATE,
        UNIPHIER_CLK_TYPE_MUX,
 };
 
+struct uniphier_clk_cpugear_data {
+       const char *parent_names[UNIPHIER_CLK_CPUGEAR_MAX_PARENTS];
+       unsigned int num_parents;
+       unsigned int regbase;
+       unsigned int mask;
+};
+
 struct uniphier_clk_fixed_factor_data {
        const char *parent_name;
        unsigned int mult;
@@ -58,6 +67,7 @@ struct uniphier_clk_data {
        enum uniphier_clk_type type;
        int idx;
        union {
+               struct uniphier_clk_cpugear_data cpugear;
                struct uniphier_clk_fixed_factor_data factor;
                struct uniphier_clk_fixed_rate_data rate;
                struct uniphier_clk_gate_data gate;
@@ -65,6 +75,20 @@ struct uniphier_clk_data {
        } data;
 };
 
+#define UNIPHIER_CLK_CPUGEAR(_name, _idx, _regbase, _mask,     \
+                            _num_parents, ...)                 \
+       {                                                       \
+               .name = (_name),                                \
+               .type = UNIPHIER_CLK_TYPE_CPUGEAR,              \
+               .idx = (_idx),                                  \
+               .data.cpugear = {                               \
+                       .parent_names = { __VA_ARGS__ },        \
+                       .num_parents = (_num_parents),          \
+                       .regbase = (_regbase),                  \
+                       .mask = (_mask)                         \
+                },                                             \
+       }
+
 #define UNIPHIER_CLK_FACTOR(_name, _idx, _parent, _mult, _div) \
        {                                                       \
                .name = (_name),                                \
@@ -77,7 +101,6 @@ struct uniphier_clk_data {
                },                                              \
        }
 
-
 #define UNIPHIER_CLK_GATE(_name, _idx, _parent, _reg, _bit)    \
        {                                                       \
                .name = (_name),                                \
@@ -90,7 +113,25 @@ struct uniphier_clk_data {
                },                                              \
        }
 
+#define UNIPHIER_CLK_DIV(parent, div)                          \
+       UNIPHIER_CLK_FACTOR(parent "/" #div, -1, parent, 1, div)
+
+#define UNIPHIER_CLK_DIV2(parent, div0, div1)                  \
+       UNIPHIER_CLK_DIV(parent, div0),                         \
+       UNIPHIER_CLK_DIV(parent, div1)
+
+#define UNIPHIER_CLK_DIV3(parent, div0, div1, div2)            \
+       UNIPHIER_CLK_DIV2(parent, div0, div1),                  \
+       UNIPHIER_CLK_DIV(parent, div2)
+
+#define UNIPHIER_CLK_DIV4(parent, div0, div1, div2, div3)      \
+       UNIPHIER_CLK_DIV2(parent, div0, div1),                  \
+       UNIPHIER_CLK_DIV2(parent, div2, div3)
 
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+                                            struct regmap *regmap,
+                                            const char *name,
+                               const struct uniphier_clk_cpugear_data *data);
 struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
                                                  const char *name,
                        const struct uniphier_clk_fixed_factor_data *data);
index 623039c3514cdc347d77f4d6ab7a3d5d0af469c5..86cc78cd1962701aca7c8d8cd838d17659254674 100644 (file)
@@ -1,3 +1,8 @@
+obj-$(CONFIG_ARCH_RCAR_GEN1)   += rcar-rst.o
+obj-$(CONFIG_ARCH_RCAR_GEN2)   += rcar-rst.o
+obj-$(CONFIG_ARCH_R8A7795)     += rcar-rst.o
+obj-$(CONFIG_ARCH_R8A7796)     += rcar-rst.o
+
 obj-$(CONFIG_ARCH_R8A7779)     += rcar-sysc.o r8a7779-sysc.o
 obj-$(CONFIG_ARCH_R8A7790)     += rcar-sysc.o r8a7790-sysc.o
 obj-$(CONFIG_ARCH_R8A7791)     += rcar-sysc.o r8a7791-sysc.o
diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
new file mode 100644 (file)
index 0000000..a6d1c26
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver
+ *
+ * Copyright (C) 2016 Glider bvba
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+struct rst_config {
+       unsigned int modemr;    /* Mode Monitoring Register Offset */
+};
+
+static const struct rst_config rcar_rst_gen1 __initconst = {
+       .modemr = 0x20,
+};
+
+static const struct rst_config rcar_rst_gen2 __initconst = {
+       .modemr = 0x60,
+};
+
+static const struct of_device_id rcar_rst_matches[] __initconst = {
+       /* RZ/G is handled like R-Car Gen2 */
+       { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 },
+       { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 },
+       /* R-Car Gen1 */
+       { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
+       { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
+       /* R-Car Gen2 */
+       { .compatible = "renesas,r8a7790-rst", .data = &rcar_rst_gen2 },
+       { .compatible = "renesas,r8a7791-rst", .data = &rcar_rst_gen2 },
+       { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 },
+       { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 },
+       { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 },
+       /* R-Car Gen3 is handled like R-Car Gen2 */
+       { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 },
+       { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 },
+       { /* sentinel */ }
+};
+
+static void __iomem *rcar_rst_base __initdata;
+static u32 saved_mode __initdata;
+
+static int __init rcar_rst_init(void)
+{
+       const struct of_device_id *match;
+       const struct rst_config *cfg;
+       struct device_node *np;
+       void __iomem *base;
+       int error = 0;
+
+       np = of_find_matching_node_and_match(NULL, rcar_rst_matches, &match);
+       if (!np)
+               return -ENODEV;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_warn("%s: Cannot map regs\n", np->full_name);
+               error = -ENOMEM;
+               goto out_put;
+       }
+
+       rcar_rst_base = base;
+       cfg = match->data;
+       saved_mode = ioread32(base + cfg->modemr);
+
+       pr_debug("%s: MODE = 0x%08x\n", np->full_name, saved_mode);
+
+out_put:
+       of_node_put(np);
+       return error;
+}
+
+int __init rcar_rst_read_mode_pins(u32 *mode)
+{
+       int error;
+
+       if (!rcar_rst_base) {
+               error = rcar_rst_init();
+               if (error)
+                       return error;
+       }
+
+       *mode = saved_mode;
+       return 0;
+}
diff --git a/include/dt-bindings/clock/hi3516cv300-clock.h b/include/dt-bindings/clock/hi3516cv300-clock.h
new file mode 100644 (file)
index 0000000..5ba51b8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DTS_HI3516CV300_CLOCK_H
+#define __DTS_HI3516CV300_CLOCK_H
+
+/* hi3516CV300 core CRG */
+#define HI3516CV300_APB_CLK            0
+#define HI3516CV300_UART0_CLK          1
+#define HI3516CV300_UART1_CLK          2
+#define HI3516CV300_UART2_CLK          3
+#define HI3516CV300_SPI0_CLK           4
+#define HI3516CV300_SPI1_CLK           5
+#define HI3516CV300_FMC_CLK            6
+#define HI3516CV300_MMC0_CLK           7
+#define HI3516CV300_MMC1_CLK           8
+#define HI3516CV300_MMC2_CLK           9
+#define HI3516CV300_MMC3_CLK           10
+#define HI3516CV300_ETH_CLK            11
+#define HI3516CV300_ETH_MACIF_CLK      12
+#define HI3516CV300_DMAC_CLK           13
+#define HI3516CV300_PWM_CLK            14
+#define HI3516CV300_USB2_BUS_CLK       15
+#define HI3516CV300_USB2_OHCI48M_CLK   16
+#define HI3516CV300_USB2_OHCI12M_CLK   17
+#define HI3516CV300_USB2_OTG_UTMI_CLK  18
+#define HI3516CV300_USB2_HST_PHY_CLK   19
+#define HI3516CV300_USB2_UTMI0_CLK     20
+#define HI3516CV300_USB2_PHY_CLK       21
+
+/* hi3516CV300 sysctrl CRG */
+#define HI3516CV300_WDT_CLK            1
+
+#endif /* __DTS_HI3516CV300_CLOCK_H */
diff --git a/include/dt-bindings/clock/histb-clock.h b/include/dt-bindings/clock/histb-clock.h
new file mode 100644 (file)
index 0000000..181c0f0
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DTS_HISTB_CLOCK_H
+#define __DTS_HISTB_CLOCK_H
+
+/* clocks provided by core CRG */
+#define HISTB_OSC_CLK                  0
+#define HISTB_APB_CLK                  1
+#define HISTB_AHB_CLK                  2
+#define HISTB_UART1_CLK                3
+#define HISTB_UART2_CLK                4
+#define HISTB_UART3_CLK                5
+#define HISTB_I2C0_CLK         6
+#define HISTB_I2C1_CLK         7
+#define HISTB_I2C2_CLK         8
+#define HISTB_I2C3_CLK         9
+#define HISTB_I2C4_CLK         10
+#define HISTB_I2C5_CLK         11
+#define HISTB_SPI0_CLK         12
+#define HISTB_SPI1_CLK         13
+#define HISTB_SPI2_CLK         14
+#define HISTB_SCI_CLK                  15
+#define HISTB_FMC_CLK                  16
+#define HISTB_MMC_BIU_CLK              17
+#define HISTB_MMC_CIU_CLK              18
+#define HISTB_MMC_DRV_CLK              19
+#define HISTB_MMC_SAMPLE_CLK           20
+#define HISTB_SDIO0_BIU_CLK            21
+#define HISTB_SDIO0_CIU_CLK            22
+#define HISTB_SDIO0_DRV_CLK            23
+#define HISTB_SDIO0_SAMPLE_CLK 24
+#define HISTB_PCIE_AUX_CLK             25
+#define HISTB_PCIE_PIPE_CLK            26
+#define HISTB_PCIE_SYS_CLK             27
+#define HISTB_PCIE_BUS_CLK             28
+#define HISTB_ETH0_MAC_CLK             29
+#define HISTB_ETH0_MACIF_CLK           30
+#define HISTB_ETH1_MAC_CLK             31
+#define HISTB_ETH1_MACIF_CLK           32
+#define HISTB_COMBPHY1_CLK             33
+
+
+/* clocks provided by mcu CRG */
+#define HISTB_MCE_CLK  1
+#define HISTB_IR_CLK   2
+#define HISTB_TIMER01_CLK      3
+#define HISTB_LEDC_CLK 4
+#define HISTB_UART0_CLK        5
+#define HISTB_LSADC_CLK        6
+
+#endif /* __DTS_HISTB_CLOCK_H */
index fd8aee8f64aeb68fdd84918215295d52ff021996..ee9f1a508d2f7fdabae06088b901be47cac23400 100644 (file)
 #define IMX6UL_CLK_PLL3_120M           223
 #define IMX6UL_CLK_KPP                 224
 
-#define IMX6UL_CLK_END                 225
+/* For i.MX6ULL */
+#define IMX6ULL_CLK_ESAI_PRED          225
+#define IMX6ULL_CLK_ESAI_PODF          226
+#define IMX6ULL_CLK_ESAI_EXTAL         227
+#define IMX6ULL_CLK_ESAI_MEM           228
+#define IMX6ULL_CLK_ESAI_IPG           229
+#define IMX6ULL_CLK_DCP_CLK            230
+#define IMX6ULL_CLK_EPDC_PRE_SEL       231
+#define IMX6ULL_CLK_EPDC_SEL           232
+#define IMX6ULL_CLK_EPDC_PODF          233
+#define IMX6ULL_CLK_EPDC_ACLK          234
+#define IMX6ULL_CLK_EPDC_PIX           235
+#define IMX6ULL_CLK_ESAI_SEL           236
+#define IMX6UL_CLK_END                 237
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
diff --git a/include/dt-bindings/clock/oxsemi,ox810se.h b/include/dt-bindings/clock/oxsemi,ox810se.h
new file mode 100644 (file)
index 0000000..d5facb5
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@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/>.
+ */
+
+#ifndef DT_CLOCK_OXSEMI_OX810SE_H
+#define DT_CLOCK_OXSEMI_OX810SE_H
+
+#define CLK_810_LEON           0
+#define CLK_810_DMA_SGDMA      1
+#define CLK_810_CIPHER         2
+#define CLK_810_SATA           3
+#define CLK_810_AUDIO          4
+#define CLK_810_USBMPH         5
+#define CLK_810_ETHA           6
+#define CLK_810_PCIEA          7
+#define CLK_810_NAND           8
+
+#endif /* DT_CLOCK_OXSEMI_OX810SE_H */
diff --git a/include/dt-bindings/clock/oxsemi,ox820.h b/include/dt-bindings/clock/oxsemi,ox820.h
new file mode 100644 (file)
index 0000000..f661ecc
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@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/>.
+ */
+
+#ifndef DT_CLOCK_OXSEMI_OX820_H
+#define DT_CLOCK_OXSEMI_OX820_H
+
+/* PLLs */
+#define CLK_820_PLLA           0
+#define CLK_820_PLLB           1
+
+/* Gate Clocks */
+#define CLK_820_LEON           2
+#define CLK_820_DMA_SGDMA      3
+#define CLK_820_CIPHER         4
+#define CLK_820_SD             5
+#define CLK_820_SATA           6
+#define CLK_820_AUDIO          7
+#define CLK_820_USBMPH         8
+#define CLK_820_ETHA           9
+#define CLK_820_PCIEA          10
+#define CLK_820_NAND           11
+#define CLK_820_PCIEB          12
+#define CLK_820_ETHB           13
+#define CLK_820_REF600         14
+#define CLK_820_USBDEV         15
+
+#endif /* DT_CLOCK_OXSEMI_OX820_H */
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8994.h b/include/dt-bindings/clock/qcom,gcc-msm8994.h
new file mode 100644 (file)
index 0000000..8fa535b
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_8994_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8994_H
+
+#define GPLL0_EARLY                            0
+#define GPLL0                                  1
+#define GPLL4_EARLY                            2
+#define GPLL4                                  3
+#define UFS_AXI_CLK_SRC                                4
+#define USB30_MASTER_CLK_SRC                   5
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC            6
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC            7
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC            8
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC            9
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC            10
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC            11
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC            12
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC            13
+#define BLSP1_QUP5_I2C_APPS_CLK_SRC            14
+#define BLSP1_QUP5_SPI_APPS_CLK_SRC            15
+#define BLSP1_QUP6_I2C_APPS_CLK_SRC            16
+#define BLSP1_QUP6_SPI_APPS_CLK_SRC            17
+#define BLSP1_UART1_APPS_CLK_SRC               18
+#define BLSP1_UART2_APPS_CLK_SRC               19
+#define BLSP1_UART3_APPS_CLK_SRC               20
+#define BLSP1_UART4_APPS_CLK_SRC               21
+#define BLSP1_UART5_APPS_CLK_SRC               22
+#define BLSP1_UART6_APPS_CLK_SRC               23
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC            24
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC            25
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC            26
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC            27
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC            28
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC            29
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC            30
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC            31
+#define BLSP2_QUP5_I2C_APPS_CLK_SRC            32
+#define BLSP2_QUP5_SPI_APPS_CLK_SRC            33
+#define BLSP2_QUP6_I2C_APPS_CLK_SRC            34
+#define BLSP2_QUP6_SPI_APPS_CLK_SRC            35
+#define BLSP2_UART1_APPS_CLK_SRC               36
+#define BLSP2_UART2_APPS_CLK_SRC               37
+#define BLSP2_UART3_APPS_CLK_SRC               38
+#define BLSP2_UART4_APPS_CLK_SRC               39
+#define BLSP2_UART5_APPS_CLK_SRC               40
+#define BLSP2_UART6_APPS_CLK_SRC               41
+#define GP1_CLK_SRC                            42
+#define GP2_CLK_SRC                            43
+#define GP3_CLK_SRC                            44
+#define PCIE_0_AUX_CLK_SRC                     45
+#define PCIE_0_PIPE_CLK_SRC                    46
+#define PCIE_1_AUX_CLK_SRC                     47
+#define PCIE_1_PIPE_CLK_SRC                    48
+#define PDM2_CLK_SRC                           49
+#define SDCC1_APPS_CLK_SRC                     50
+#define SDCC2_APPS_CLK_SRC                     51
+#define SDCC3_APPS_CLK_SRC                     52
+#define SDCC4_APPS_CLK_SRC                     53
+#define TSIF_REF_CLK_SRC                       54
+#define USB30_MOCK_UTMI_CLK_SRC                        55
+#define USB3_PHY_AUX_CLK_SRC                   56
+#define USB_HS_SYSTEM_CLK_SRC                  57
+#define GCC_BLSP1_AHB_CLK                      58
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK            59
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK            60
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK            61
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK            62
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK            63
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK            64
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK            65
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK            66
+#define GCC_BLSP1_QUP5_I2C_APPS_CLK            67
+#define GCC_BLSP1_QUP5_SPI_APPS_CLK            68
+#define GCC_BLSP1_QUP6_I2C_APPS_CLK            69
+#define GCC_BLSP1_QUP6_SPI_APPS_CLK            70
+#define GCC_BLSP1_UART1_APPS_CLK               71
+#define GCC_BLSP1_UART2_APPS_CLK               72
+#define GCC_BLSP1_UART3_APPS_CLK               73
+#define GCC_BLSP1_UART4_APPS_CLK               74
+#define GCC_BLSP1_UART5_APPS_CLK               75
+#define GCC_BLSP1_UART6_APPS_CLK               76
+#define GCC_BLSP2_AHB_CLK                      77
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK            78
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK            79
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK            80
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK            81
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK            82
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK            83
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK            84
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK            85
+#define GCC_BLSP2_QUP5_I2C_APPS_CLK            86
+#define GCC_BLSP2_QUP5_SPI_APPS_CLK            87
+#define GCC_BLSP2_QUP6_I2C_APPS_CLK            88
+#define GCC_BLSP2_QUP6_SPI_APPS_CLK            89
+#define GCC_BLSP2_UART1_APPS_CLK               90
+#define GCC_BLSP2_UART2_APPS_CLK               91
+#define GCC_BLSP2_UART3_APPS_CLK               92
+#define GCC_BLSP2_UART4_APPS_CLK               93
+#define GCC_BLSP2_UART5_APPS_CLK               94
+#define GCC_BLSP2_UART6_APPS_CLK               95
+#define GCC_GP1_CLK                            96
+#define GCC_GP2_CLK                            97
+#define GCC_GP3_CLK                            98
+#define GCC_PCIE_0_AUX_CLK                     99
+#define GCC_PCIE_0_PIPE_CLK                    100
+#define GCC_PCIE_1_AUX_CLK                     101
+#define GCC_PCIE_1_PIPE_CLK                    102
+#define GCC_PDM2_CLK                           103
+#define GCC_SDCC1_APPS_CLK                     104
+#define GCC_SDCC2_APPS_CLK                     105
+#define GCC_SDCC3_APPS_CLK                     106
+#define GCC_SDCC4_APPS_CLK                     107
+#define GCC_SYS_NOC_UFS_AXI_CLK                        108
+#define GCC_SYS_NOC_USB3_AXI_CLK               109
+#define GCC_TSIF_REF_CLK                       110
+#define GCC_UFS_AXI_CLK                                111
+#define GCC_UFS_RX_CFG_CLK                     112
+#define GCC_UFS_TX_CFG_CLK                     113
+#define GCC_USB30_MASTER_CLK                   114
+#define GCC_USB30_MOCK_UTMI_CLK                        115
+#define GCC_USB3_PHY_AUX_CLK                   116
+#define GCC_USB_HS_SYSTEM_CLK                  117
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h
new file mode 100644 (file)
index 0000000..5924cdb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015 Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_RPMCC_H
+#define _DT_BINDINGS_CLK_MSM_RPMCC_H
+
+/* apq8064 */
+#define RPM_PXO_CLK                            0
+#define RPM_PXO_A_CLK                          1
+#define RPM_CXO_CLK                            2
+#define RPM_CXO_A_CLK                          3
+#define RPM_APPS_FABRIC_CLK                    4
+#define RPM_APPS_FABRIC_A_CLK                  5
+#define RPM_CFPB_CLK                           6
+#define RPM_CFPB_A_CLK                         7
+#define RPM_QDSS_CLK                           8
+#define RPM_QDSS_A_CLK                         9
+#define RPM_DAYTONA_FABRIC_CLK                 10
+#define RPM_DAYTONA_FABRIC_A_CLK               11
+#define RPM_EBI1_CLK                           12
+#define RPM_EBI1_A_CLK                         13
+#define RPM_MM_FABRIC_CLK                      14
+#define RPM_MM_FABRIC_A_CLK                    15
+#define RPM_MMFPB_CLK                          16
+#define RPM_MMFPB_A_CLK                                17
+#define RPM_SYS_FABRIC_CLK                     18
+#define RPM_SYS_FABRIC_A_CLK                   19
+#define RPM_SFPB_CLK                           20
+#define RPM_SFPB_A_CLK                         21
+
+/* msm8916 */
+#define RPM_SMD_XO_CLK_SRC                             0
+#define RPM_SMD_XO_A_CLK_SRC                   1
+#define RPM_SMD_PCNOC_CLK                              2
+#define RPM_SMD_PCNOC_A_CLK                            3
+#define RPM_SMD_SNOC_CLK                               4
+#define RPM_SMD_SNOC_A_CLK                             5
+#define RPM_SMD_BIMC_CLK                               6
+#define RPM_SMD_BIMC_A_CLK                             7
+#define RPM_SMD_QDSS_CLK                               8
+#define RPM_SMD_QDSS_A_CLK                             9
+#define RPM_SMD_BB_CLK1                                10
+#define RPM_SMD_BB_CLK1_A                              11
+#define RPM_SMD_BB_CLK2                                12
+#define RPM_SMD_BB_CLK2_A                              13
+#define RPM_SMD_RF_CLK1                                14
+#define RPM_SMD_RF_CLK1_A                              15
+#define RPM_SMD_RF_CLK2                                16
+#define RPM_SMD_RF_CLK2_A                              17
+#define RPM_SMD_BB_CLK1_PIN                            18
+#define RPM_SMD_BB_CLK1_A_PIN                  19
+#define RPM_SMD_BB_CLK2_PIN                            20
+#define RPM_SMD_BB_CLK2_A_PIN                  21
+#define RPM_SMD_RF_CLK1_PIN                            22
+#define RPM_SMD_RF_CLK1_A_PIN                  23
+#define RPM_SMD_RF_CLK2_PIN                            24
+#define RPM_SMD_RF_CLK2_A_PIN                  25
+
+#endif
diff --git a/include/dt-bindings/clock/r8a7743-cpg-mssr.h b/include/dt-bindings/clock/r8a7743-cpg-mssr.h
new file mode 100644 (file)
index 0000000..e1d1f3c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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_R8A7743_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a7743 CPG Core Clocks */
+#define R8A7743_CLK_Z          0
+#define R8A7743_CLK_ZG         1
+#define R8A7743_CLK_ZTR                2
+#define R8A7743_CLK_ZTRD2      3
+#define R8A7743_CLK_ZT         4
+#define R8A7743_CLK_ZX         5
+#define R8A7743_CLK_ZS         6
+#define R8A7743_CLK_HP         7
+#define R8A7743_CLK_B          9
+#define R8A7743_CLK_LB         10
+#define R8A7743_CLK_P          11
+#define R8A7743_CLK_CL         12
+#define R8A7743_CLK_M2         13
+#define R8A7743_CLK_ZB3                15
+#define R8A7743_CLK_ZB3D2      16
+#define R8A7743_CLK_DDR                17
+#define R8A7743_CLK_SDH                18
+#define R8A7743_CLK_SD0                19
+#define R8A7743_CLK_SD2                20
+#define R8A7743_CLK_SD3                21
+#define R8A7743_CLK_MMC0       22
+#define R8A7743_CLK_MP         23
+#define R8A7743_CLK_QSPI       26
+#define R8A7743_CLK_CP         27
+#define R8A7743_CLK_RCAN       28
+#define R8A7743_CLK_R          29
+#define R8A7743_CLK_OSC                30
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/clock/r8a7745-cpg-mssr.h b/include/dt-bindings/clock/r8a7745-cpg-mssr.h
new file mode 100644 (file)
index 0000000..56ad6f0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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_R8A7745_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A7745_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a7745 CPG Core Clocks */
+#define R8A7745_CLK_Z2         0
+#define R8A7745_CLK_ZG         1
+#define R8A7745_CLK_ZTR                2
+#define R8A7745_CLK_ZTRD2      3
+#define R8A7745_CLK_ZT         4
+#define R8A7745_CLK_ZX         5
+#define R8A7745_CLK_ZS         6
+#define R8A7745_CLK_HP         7
+#define R8A7745_CLK_B          9
+#define R8A7745_CLK_LB         10
+#define R8A7745_CLK_P          11
+#define R8A7745_CLK_CL         12
+#define R8A7745_CLK_CP         13
+#define R8A7745_CLK_M2         14
+#define R8A7745_CLK_ZB3                16
+#define R8A7745_CLK_ZB3D2      17
+#define R8A7745_CLK_DDR                18
+#define R8A7745_CLK_SDH                19
+#define R8A7745_CLK_SD0                20
+#define R8A7745_CLK_SD2                21
+#define R8A7745_CLK_SD3                22
+#define R8A7745_CLK_MMC0       23
+#define R8A7745_CLK_MP         24
+#define R8A7745_CLK_QSPI       25
+#define R8A7745_CLK_CPEX       26
+#define R8A7745_CLK_RCAN       27
+#define R8A7745_CLK_R          28
+#define R8A7745_CLK_OSC                29
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7745_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/clock/rk1108-cru.h b/include/dt-bindings/clock/rk1108-cru.h
new file mode 100644 (file)
index 0000000..9350a55
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+
+/* pll id */
+#define PLL_APLL                       0
+#define PLL_DPLL                       1
+#define PLL_GPLL                       2
+#define ARMCLK                         3
+
+/* sclk gates (special clocks) */
+#define SCLK_SPI0                      65
+#define SCLK_NANDC                     67
+#define SCLK_SDMMC                     68
+#define SCLK_SDIO                      69
+#define SCLK_EMMC                      71
+#define SCLK_UART0                     72
+#define SCLK_UART1                     73
+#define SCLK_UART2                     74
+#define SCLK_I2S0                      75
+#define SCLK_I2S1                      76
+#define SCLK_I2S2                      77
+#define SCLK_TIMER0                    78
+#define SCLK_TIMER1                    79
+#define SCLK_SFC                       80
+#define SCLK_SDMMC_DRV                 81
+#define SCLK_SDIO_DRV                  82
+#define SCLK_EMMC_DRV                  83
+#define SCLK_SDMMC_SAMPLE              84
+#define SCLK_SDIO_SAMPLE               85
+#define SCLK_EMMC_SAMPLE               86
+
+/* aclk gates */
+#define ACLK_DMAC                      192
+#define ACLK_PRE                       193
+#define ACLK_CORE                      194
+#define ACLK_ENMCORE                   195
+
+/* pclk gates */
+#define PCLK_GPIO1                     256
+#define PCLK_GPIO2                     257
+#define PCLK_GPIO3                     258
+#define PCLK_GRF                       259
+#define PCLK_I2C1                      260
+#define PCLK_I2C2                      261
+#define PCLK_I2C3                      262
+#define PCLK_SPI                       263
+#define PCLK_SFC                       264
+#define PCLK_UART0                     265
+#define PCLK_UART1                     266
+#define PCLK_UART2                     267
+#define PCLK_TSADC                     268
+#define PCLK_PWM                       269
+#define PCLK_TIMER                     270
+#define PCLK_PERI                      271
+
+/* hclk gates */
+#define HCLK_I2S0_8CH                  320
+#define HCLK_I2S1_8CH                  321
+#define HCLK_I2S2_2CH                  322
+#define HCLK_NANDC                     323
+#define HCLK_SDMMC                     324
+#define HCLK_SDIO                      325
+#define HCLK_EMMC                      326
+#define HCLK_PERI                      327
+#define HCLK_SFC                       328
+
+#define CLK_NR_CLKS                    (HCLK_SFC + 1)
+
+/* reset id */
+#define SRST_CORE_PO_AD                0
+#define SRST_CORE_AD                   1
+#define SRST_L2_AD                     2
+#define SRST_CPU_NIU_AD                3
+#define SRST_CORE_PO                   4
+#define SRST_CORE                      5
+#define SRST_L2                        6
+#define SRST_CORE_DBG                  8
+#define PRST_DBG                       9
+#define RST_DAP                        10
+#define PRST_DBG_NIU                   11
+#define ARST_STRC_SYS_AD               15
+
+#define SRST_DDRPHY_CLKDIV             16
+#define SRST_DDRPHY                    17
+#define PRST_DDRPHY                    18
+#define PRST_HDMIPHY                   19
+#define PRST_VDACPHY                   20
+#define PRST_VADCPHY                   21
+#define PRST_MIPI_CSI_PHY              22
+#define PRST_MIPI_DSI_PHY              23
+#define PRST_ACODEC                    24
+#define ARST_BUS_NIU                   25
+#define PRST_TOP_NIU                   26
+#define ARST_INTMEM                    27
+#define HRST_ROM                       28
+#define ARST_DMAC                      29
+#define SRST_MSCH_NIU                  30
+#define PRST_MSCH_NIU                  31
+
+#define PRST_DDRUPCTL                  32
+#define NRST_DDRUPCTL                  33
+#define PRST_DDRMON                    34
+#define HRST_I2S0_8CH                  35
+#define MRST_I2S0_8CH                  36
+#define HRST_I2S1_2CH                  37
+#define MRST_IS21_2CH                  38
+#define HRST_I2S2_2CH                  39
+#define MRST_I2S2_2CH                  40
+#define HRST_CRYPTO                    41
+#define SRST_CRYPTO                    42
+#define PRST_SPI                       43
+#define SRST_SPI                       44
+#define PRST_UART0                     45
+#define PRST_UART1                     46
+#define PRST_UART2                     47
+
+#define SRST_UART0                     48
+#define SRST_UART1                     49
+#define SRST_UART2                     50
+#define PRST_I2C1                      51
+#define PRST_I2C2                      52
+#define PRST_I2C3                      53
+#define SRST_I2C1                      54
+#define SRST_I2C2                      55
+#define SRST_I2C3                      56
+#define PRST_PWM1                      58
+#define SRST_PWM1                      60
+#define PRST_WDT                       61
+#define PRST_GPIO1                     62
+#define PRST_GPIO2                     63
+
+#define PRST_GPIO3                     64
+#define PRST_GRF                       65
+#define PRST_EFUSE                     66
+#define PRST_EFUSE512                  67
+#define PRST_TIMER0                    68
+#define SRST_TIMER0                    69
+#define SRST_TIMER1                    70
+#define PRST_TSADC                     71
+#define SRST_TSADC                     72
+#define PRST_SARADC                    73
+#define SRST_SARADC                    74
+#define HRST_SYSBUS                    75
+#define PRST_USBGRF                    76
+
+#define ARST_PERIPH_NIU                80
+#define HRST_PERIPH_NIU                81
+#define PRST_PERIPH_NIU                82
+#define HRST_PERIPH                    83
+#define HRST_SDMMC                     84
+#define HRST_SDIO                      85
+#define HRST_EMMC                      86
+#define HRST_NANDC                     87
+#define NRST_NANDC                     88
+#define HRST_SFC                       89
+#define SRST_SFC                       90
+#define ARST_GMAC                      91
+#define HRST_OTG                       92
+#define SRST_OTG                       93
+#define SRST_OTG_ADP                   94
+#define HRST_HOST0                     95
+
+#define HRST_HOST0_AUX                 96
+#define HRST_HOST0_ARB                 97
+#define SRST_HOST0_EHCIPHY             98
+#define SRST_HOST0_UTMI                99
+#define SRST_USBPOR                    100
+#define SRST_UTMI0                     101
+#define SRST_UTMI1                     102
+
+#define ARST_VIO0_NIU                  102
+#define ARST_VIO1_NIU                  103
+#define HRST_VIO_NIU                   104
+#define PRST_VIO_NIU                   105
+#define ARST_VOP                       106
+#define HRST_VOP                       107
+#define DRST_VOP                       108
+#define ARST_IEP                       109
+#define HRST_IEP                       110
+#define ARST_RGA                       111
+#define HRST_RGA                       112
+#define SRST_RGA                       113
+#define PRST_CVBS                      114
+#define PRST_HDMI                      115
+#define SRST_HDMI                      116
+#define PRST_MIPI_DSI                  117
+
+#define ARST_ISP_NIU                   118
+#define HRST_ISP_NIU                   119
+#define HRST_ISP                       120
+#define SRST_ISP                       121
+#define ARST_VIP0                      122
+#define HRST_VIP0                      123
+#define PRST_VIP0                      124
+#define ARST_VIP1                      125
+#define HRST_VIP1                      126
+#define PRST_VIP1                      127
+#define ARST_VIP2                      128
+#define HRST_VIP2                      129
+#define PRST_VIP2                      120
+#define ARST_VIP3                      121
+#define HRST_VIP3                      122
+#define PRST_VIP4                      123
+
+#define PRST_CIF1TO4                   124
+#define SRST_CVBS_CLK                  125
+#define HRST_CVBS                      126
+
+#define ARST_VPU_NIU                   140
+#define HRST_VPU_NIU                   141
+#define ARST_VPU                       142
+#define HRST_VPU                       143
+#define ARST_RKVDEC_NIU                144
+#define HRST_RKVDEC_NIU                145
+#define ARST_RKVDEC                    146
+#define HRST_RKVDEC                    147
+#define SRST_RKVDEC_CABAC              148
+#define SRST_RKVDEC_CORE               149
+#define ARST_RKVENC_NIU                150
+#define HRST_RKVENC_NIU                151
+#define ARST_RKVENC                    152
+#define HRST_RKVENC                    153
+#define SRST_RKVENC_CORE               154
+
+#define SRST_DSP_CORE                  156
+#define SRST_DSP_SYS                   157
+#define SRST_DSP_GLOBAL                158
+#define SRST_DSP_OECM                  159
+#define PRST_DSP_IOP_NIU               160
+#define ARST_DSP_EPP_NIU               161
+#define ARST_DSP_EDP_NIU               162
+#define PRST_DSP_DBG_NIU               163
+#define PRST_DSP_CFG_NIU               164
+#define PRST_DSP_GRF                   165
+#define PRST_DSP_MAILBOX               166
+#define PRST_DSP_INTC                  167
+#define PRST_DSP_PFM_MON               169
+#define SRST_DSP_PFM_MON               170
+#define ARST_DSP_EDAP_NIU              171
+
+#define SRST_PMU                       172
+#define SRST_PMU_I2C0                  173
+#define PRST_PMU_I2C0                  174
+#define PRST_PMU_GPIO0                 175
+#define PRST_PMU_INTMEM                176
+#define PRST_PMU_PWM0                  177
+#define SRST_PMU_PWM0                  178
+#define PRST_PMU_GRF                   179
+#define SRST_PMU_NIU                   180
+#define SRST_PMU_PVTM                  181
+#define ARST_DSP_EDP_PERF              184
+#define ARST_DSP_EPP_PERF              185
+
+#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */
index 4f53e70f68ee5b32ee69cd825e370ba3f65d9ce8..d141c1f0c77824e0ee4d42be87785b171b1457d9 100644 (file)
@@ -72,6 +72,8 @@
 #define ACLK_IPP               200
 #define ACLK_RGA               201
 #define ACLK_CIF0              202
+#define ACLK_CPU               203
+#define ACLK_PERI              204
 
 /* pclk gates */
 #define PCLK_GRF               320
 #define PCLK_EFUSE             347
 #define PCLK_TZPC              348
 #define PCLK_TSADC             349
+#define PCLK_CPU               350
+#define PCLK_PERI              351
 
 /* hclk gates */
 #define HCLK_SDMMC             448
 #define HCLK_IPP               465
 #define HCLK_RGA               466
 #define HCLK_NANDC0            467
+#define HCLK_CPU               468
+#define HCLK_PERI              469
 
-#define CLK_NR_CLKS            (HCLK_NANDC0 + 1)
+#define CLK_NR_CLKS            (HCLK_PERI + 1)
 
 /* soft-reset indices */
 #define SRST_MCORE             2
diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h
new file mode 100644 (file)
index 0000000..370c0a0
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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_SUN50I_A64_H_
+#define _DT_BINDINGS_CLK_SUN50I_A64_H_
+
+#define CLK_BUS_MIPI_DSI       28
+#define CLK_BUS_CE             29
+#define CLK_BUS_DMA            30
+#define CLK_BUS_MMC0           31
+#define CLK_BUS_MMC1           32
+#define CLK_BUS_MMC2           33
+#define CLK_BUS_NAND           34
+#define CLK_BUS_DRAM           35
+#define CLK_BUS_EMAC           36
+#define CLK_BUS_TS             37
+#define CLK_BUS_HSTIMER                38
+#define CLK_BUS_SPI0           39
+#define CLK_BUS_SPI1           40
+#define CLK_BUS_OTG            41
+#define CLK_BUS_EHCI0          42
+#define CLK_BUS_EHCI1          43
+#define CLK_BUS_OHCI0          44
+#define CLK_BUS_OHCI1          45
+#define CLK_BUS_VE             46
+#define CLK_BUS_TCON0          47
+#define CLK_BUS_TCON1          48
+#define CLK_BUS_DEINTERLACE    49
+#define CLK_BUS_CSI            50
+#define CLK_BUS_HDMI           51
+#define CLK_BUS_DE             52
+#define CLK_BUS_GPU            53
+#define CLK_BUS_MSGBOX         54
+#define CLK_BUS_SPINLOCK       55
+#define CLK_BUS_CODEC          56
+#define CLK_BUS_SPDIF          57
+#define CLK_BUS_PIO            58
+#define CLK_BUS_THS            59
+#define CLK_BUS_I2S0           60
+#define CLK_BUS_I2S1           61
+#define CLK_BUS_I2S2           62
+#define CLK_BUS_I2C0           63
+#define CLK_BUS_I2C1           64
+#define CLK_BUS_I2C2           65
+#define CLK_BUS_SCR            66
+#define CLK_BUS_UART0          67
+#define CLK_BUS_UART1          68
+#define CLK_BUS_UART2          69
+#define CLK_BUS_UART3          70
+#define CLK_BUS_UART4          71
+#define CLK_BUS_DBG            72
+#define CLK_THS                        73
+#define CLK_NAND               74
+#define CLK_MMC0               75
+#define CLK_MMC1               76
+#define CLK_MMC2               77
+#define CLK_TS                 78
+#define CLK_CE                 79
+#define CLK_SPI0               80
+#define CLK_SPI1               81
+#define CLK_I2S0               82
+#define CLK_I2S1               83
+#define CLK_I2S2               84
+#define CLK_SPDIF              85
+#define CLK_USB_PHY0           86
+#define CLK_USB_PHY1           87
+#define CLK_USB_HSIC           88
+#define CLK_USB_HSIC_12M       89
+
+#define CLK_USB_OHCI0          91
+
+#define CLK_USB_OHCI1          93
+
+#define CLK_DRAM_VE            95
+#define CLK_DRAM_CSI           96
+#define CLK_DRAM_DEINTERLACE   97
+#define CLK_DRAM_TS            98
+#define CLK_DE                 99
+#define CLK_TCON0              100
+#define CLK_TCON1              101
+#define CLK_DEINTERLACE                102
+#define CLK_CSI_MISC           103
+#define CLK_CSI_SCLK           104
+#define CLK_CSI_MCLK           105
+#define CLK_VE                 106
+#define CLK_AC_DIG             107
+#define CLK_AC_DIG_4X          108
+#define CLK_AVS                        109
+#define CLK_HDMI               110
+#define CLK_HDMI_DDC           111
+
+#define CLK_DSI_DPHY           113
+#define CLK_GPU                        114
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H_ */
diff --git a/include/dt-bindings/reset/sun50i-a64-ccu.h b/include/dt-bindings/reset/sun50i-a64-ccu.h
new file mode 100644 (file)
index 0000000..db60b29
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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_SUN50I_A64_H_
+#define _DT_BINDINGS_RST_SUN50I_A64_H_
+
+#define RST_USB_PHY0           0
+#define RST_USB_PHY1           1
+#define RST_USB_HSIC           2
+#define RST_DRAM               3
+#define RST_MBUS               4
+#define RST_BUS_MIPI_DSI       5
+#define RST_BUS_CE             6
+#define RST_BUS_DMA            7
+#define RST_BUS_MMC0           8
+#define RST_BUS_MMC1           9
+#define RST_BUS_MMC2           10
+#define RST_BUS_NAND           11
+#define RST_BUS_DRAM           12
+#define RST_BUS_EMAC           13
+#define RST_BUS_TS             14
+#define RST_BUS_HSTIMER                15
+#define RST_BUS_SPI0           16
+#define RST_BUS_SPI1           17
+#define RST_BUS_OTG            18
+#define RST_BUS_EHCI0          19
+#define RST_BUS_EHCI1          20
+#define RST_BUS_OHCI0          21
+#define RST_BUS_OHCI1          22
+#define RST_BUS_VE             23
+#define RST_BUS_TCON0          24
+#define RST_BUS_TCON1          25
+#define RST_BUS_DEINTERLACE    26
+#define RST_BUS_CSI            27
+#define RST_BUS_HDMI0          28
+#define RST_BUS_HDMI1          29
+#define RST_BUS_DE             30
+#define RST_BUS_GPU            31
+#define RST_BUS_MSGBOX         32
+#define RST_BUS_SPINLOCK       33
+#define RST_BUS_DBG            34
+#define RST_BUS_LVDS           35
+#define RST_BUS_CODEC          36
+#define RST_BUS_SPDIF          37
+#define RST_BUS_THS            38
+#define RST_BUS_I2S0           39
+#define RST_BUS_I2S1           40
+#define RST_BUS_I2S2           41
+#define RST_BUS_I2C0           42
+#define RST_BUS_I2C1           43
+#define RST_BUS_I2C2           44
+#define RST_BUS_SCR            45
+#define RST_BUS_UART0          46
+#define RST_BUS_UART1          47
+#define RST_BUS_UART2          48
+#define RST_BUS_UART3          49
+#define RST_BUS_UART4          50
+
+#endif /* _DT_BINDINGS_RST_SUN50I_A64_H_ */
index 123c02788807f553feeeca0d2ea9c39cddab537f..e9d36b3e49de5b1bfa0f01277c093222e1ae2a6d 100644 (file)
@@ -17,8 +17,9 @@
 #include <linux/notifier.h>
 
 struct device;
-
 struct clk;
+struct device_node;
+struct of_phandle_args;
 
 /**
  * DOC: clk notifier callback types
@@ -248,6 +249,23 @@ struct clk *clk_get(struct device *dev, const char *id);
  */
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
+/**
+ * devm_get_clk_from_child - lookup and obtain a managed reference to a
+ *                          clock producer from child node.
+ * @dev: device for clock "consumer"
+ * @np: pointer to clock consumer node
+ * @con_id: clock consumer ID
+ *
+ * This function parses the clocks, and uses them to look up the
+ * struct clk from the registered list of clock providers by using
+ * @np and @con_id
+ *
+ * The clock will automatically be freed when the device is unbound
+ * from the bus.
+ */
+struct clk *devm_get_clk_from_child(struct device *dev,
+                                   struct device_node *np, const char *con_id);
+
 /**
  * clk_enable - inform the system when the clock source should be running.
  * @clk: clock source
@@ -432,6 +450,12 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
        return NULL;
 }
 
+static inline struct clk *devm_get_clk_from_child(struct device *dev,
+                               struct device_node *np, const char *con_id)
+{
+       return NULL;
+}
+
 static inline void clk_put(struct clk *clk) {}
 
 static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
@@ -501,9 +525,6 @@ static inline void clk_disable_unprepare(struct clk *clk)
        clk_unprepare(clk);
 }
 
-struct device_node;
-struct of_phandle_args;
-
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
index ba6fa4148515e5c9959c21767820fe7363bd9713..9ebf1f8243bb57af54b0d5adc3b22408c858d103 100644 (file)
@@ -20,10 +20,6 @@ struct device;
 struct device_node;
 struct generic_pm_domain;
 
-void r8a7778_clocks_init(u32 mode);
-void r8a7779_clocks_init(u32 mode);
-void rcar_gen2_clocks_init(u32 mode);
-
 void cpg_mstp_add_clk_domain(struct device_node *np);
 #ifdef CONFIG_CLK_RENESAS_CPG_MSTP
 int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev);
diff --git a/include/linux/soc/renesas/rcar-rst.h b/include/linux/soc/renesas/rcar-rst.h
new file mode 100644 (file)
index 0000000..a18e078
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __LINUX_SOC_RENESAS_RCAR_RST_H__
+#define __LINUX_SOC_RENESAS_RCAR_RST_H__
+
+int rcar_rst_read_mode_pins(u32 *mode);
+
+#endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */