]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'clk-for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/clk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2015 00:26:48 +0000 (17:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2015 00:26:48 +0000 (17:26 -0700)
Pull clk updates from Michael Turquette:
 "The clk framework changes for 4.3 are mostly updates to existing
  drivers and the addition of new clock drivers.  Stephen Boyd has also
  done a lot of subsystem-wide driver clean-ups (thanks!).  There are
  also fixes to the framework core and changes to better split clock
  provider drivers from clock consumer drivers"

* tag 'clk-for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (227 commits)
  clk: s5pv210: add missing call to samsung_clk_of_add_provider()
  clk: pistachio: correct critical clock list
  clk: pistachio: Fix PLL rate calculation in integer mode
  clk: pistachio: Fix override of clk-pll settings from boot loader
  clk: pistachio: Fix 32bit integer overflows
  clk: tegra: Fix some static checker problems
  clk: qcom: Fix MSM8916 prng clock enable bit
  clk: Add missing header for 'bool' definition to clk-conf.h
  drivers/clk: appropriate __init annotation for const data
  clk: rockchip: register pll mux before pll itself
  clk: add bindings for the Ux500 clocks
  clk/ARM: move Ux500 PRCC bases to the device tree
  clk: remove duplicated code with __clk_set_parent_after
  clk: Convert __clk_get_name(hw->clk) to clk_hw_get_name(hw)
  clk: Constify clk_hw argument to provider APIs
  clk: Hi6220: add stub clock driver
  dt-bindings: clk: Hi6220: Document stub clock driver
  dt-bindings: arm: Hi6220: add doc for SRAM controller
  clk: atlas7: fix pll missed divide NR in fraction mode
  clk: atlas7: fix bit field and its root clk for coresight_tpiu
  ...

320 files changed:
Documentation/clk.txt
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
Documentation/devicetree/bindings/arm/sp810.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/gpio-mux-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/hi6220-clock.txt
Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ux500.txt [new file with mode: 0644]
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun9i-a80.dtsi
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-hisi/hisilicon.c
arch/arm/mach-keystone/pm_domain.c
arch/arm/mach-mvebu/board-v7.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clkt34xx_dpll3m2.c
arch/arm/mach-omap2/clkt_clksel.c [deleted file]
arch/arm/mach-omap2/clkt_iclk.c [deleted file]
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2430.c [deleted file]
arch/arm/mach-omap2/clock2xxx.c [deleted file]
arch/arm/mach-omap2/clock34xx.c [deleted file]
arch/arm/mach-omap2/clock34xx.h [deleted file]
arch/arm/mach-omap2/clock3517.c [deleted file]
arch/arm/mach-omap2/clock3517.h [deleted file]
arch/arm/mach-omap2/clock36xx.c [deleted file]
arch/arm/mach-omap2/clock36xx.h [deleted file]
arch/arm/mach-omap2/clock3xxx.c [deleted file]
arch/arm/mach-omap2/clock44xx.h [deleted file]
arch/arm/mach-omap2/clock_common_data.c [deleted file]
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-orion5x/board-dt.c
arch/arm/mach-s3c64xx/common.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-ux500/cpu.c
arch/arm64/kernel/setup.c
arch/mips/alchemy/common/clock.c
arch/powerpc/platforms/512x/clock-commonclk.c
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_lpss.c
drivers/clk/Makefile
drivers/clk/at91/clk-main.c
drivers/clk/at91/clk-master.c
drivers/clk/at91/clk-peripheral.c
drivers/clk/at91/clk-programmable.c
drivers/clk/at91/clk-slow.c
drivers/clk/at91/clk-smd.c
drivers/clk/at91/clk-usb.c
drivers/clk/at91/pmc.c
drivers/clk/at91/pmc.h
drivers/clk/bcm/clk-kona.c
drivers/clk/berlin/berlin2-pll.c
drivers/clk/clk-axi-clkgen.c
drivers/clk/clk-bcm2835.c
drivers/clk/clk-cdce706.c
drivers/clk/clk-cdce925.c
drivers/clk/clk-clps711x.c
drivers/clk/clk-composite.c
drivers/clk/clk-divider.c
drivers/clk/clk-efm32gg.c
drivers/clk/clk-fixed-factor.c
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-gate.c
drivers/clk/clk-gpio-gate.c [deleted file]
drivers/clk/clk-gpio.c [new file with mode: 0644]
drivers/clk/clk-highbank.c
drivers/clk/clk-moxart.c
drivers/clk/clk-mux.c
drivers/clk/clk-nomadik.c
drivers/clk/clk-palmas.c
drivers/clk/clk-rk808.c
drivers/clk/clk-s2mps11.c
drivers/clk/clk-si5351.c
drivers/clk/clk-si570.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-twl6040.c
drivers/clk/clk-u300.c
drivers/clk/clk-wm831x.c
drivers/clk/clk-xgene.c
drivers/clk/clk.c
drivers/clk/h8300/clk-div.c
drivers/clk/h8300/clk-h8s2678.c
drivers/clk/hisilicon/Kconfig
drivers/clk/hisilicon/Makefile
drivers/clk/hisilicon/clk-hi3620.c
drivers/clk/hisilicon/clk-hi6220-stub.c [new file with mode: 0644]
drivers/clk/hisilicon/clk-hip04.c
drivers/clk/hisilicon/clk.c
drivers/clk/hisilicon/clkgate-separated.c
drivers/clk/imx/Makefile
drivers/clk/imx/clk-imx1.c
drivers/clk/imx/clk-imx21.c
drivers/clk/imx/clk-imx31.c
drivers/clk/imx/clk-imx35.c
drivers/clk/imx/clk-imx6q.c
drivers/clk/imx/clk-imx6ul.c [new file with mode: 0644]
drivers/clk/imx/clk-pfd.c
drivers/clk/imx/clk-pllv1.c
drivers/clk/imx/clk-pllv3.c
drivers/clk/ingenic/cgu.c
drivers/clk/keystone/gate.c
drivers/clk/keystone/pll.c
drivers/clk/mediatek/clk-gate.h
drivers/clk/mediatek/clk-mt8135.c
drivers/clk/mediatek/clk-mt8173.c
drivers/clk/mediatek/clk-mtk.h
drivers/clk/mediatek/clk-pll.c
drivers/clk/meson/clk-cpu.c
drivers/clk/meson/clkc.c
drivers/clk/mmp/clk-apbc.c
drivers/clk/mmp/clk-apmu.c
drivers/clk/mmp/clk-gate.c
drivers/clk/mmp/clk-mix.c
drivers/clk/mmp/clk.c
drivers/clk/mvebu/clk-cpu.c
drivers/clk/mvebu/common.c
drivers/clk/mxs/clk-div.c
drivers/clk/mxs/clk-frac.c
drivers/clk/mxs/clk-imx23.c
drivers/clk/mxs/clk-imx28.c
drivers/clk/mxs/clk-pll.c
drivers/clk/mxs/clk-ref.c
drivers/clk/mxs/clk.h
drivers/clk/nxp/clk-lpc18xx-cgu.c
drivers/clk/pistachio/clk-pistachio.c
drivers/clk/pistachio/clk-pll.c
drivers/clk/pistachio/clk.c
drivers/clk/pistachio/clk.h
drivers/clk/pxa/clk-pxa25x.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/pxa/clk-pxa3xx.c
drivers/clk/qcom/clk-branch.c
drivers/clk/qcom/clk-pll.c
drivers/clk/qcom/clk-pll.h
drivers/clk/qcom/clk-rcg.c
drivers/clk/qcom/clk-rcg2.c
drivers/clk/qcom/common.c
drivers/clk/qcom/gcc-apq8084.c
drivers/clk/qcom/gcc-ipq806x.c
drivers/clk/qcom/gcc-msm8660.c
drivers/clk/qcom/gcc-msm8916.c
drivers/clk/qcom/gcc-msm8960.c
drivers/clk/qcom/gcc-msm8974.c
drivers/clk/qcom/lcc-ipq806x.c
drivers/clk/qcom/lcc-msm8960.c
drivers/clk/qcom/mmcc-apq8084.c
drivers/clk/qcom/mmcc-msm8960.c
drivers/clk/qcom/mmcc-msm8974.c
drivers/clk/rockchip/Makefile
drivers/clk/rockchip/clk-cpu.c
drivers/clk/rockchip/clk-inverter.c [new file with mode: 0644]
drivers/clk/rockchip/clk-mmc-phase.c
drivers/clk/rockchip/clk-pll.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3368.c [new file with mode: 0644]
drivers/clk/rockchip/clk.c
drivers/clk/rockchip/clk.h
drivers/clk/samsung/clk-cpu.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos4415.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5260.c
drivers/clk/samsung/clk-exynos5410.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/samsung/clk-exynos5440.c
drivers/clk/samsung/clk-exynos7.c
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-s3c2410-dclk.c
drivers/clk/samsung/clk-s3c2410.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clk/samsung/clk-s5pv210-audss.c
drivers/clk/samsung/clk-s5pv210.c
drivers/clk/samsung/clk.c
drivers/clk/samsung/clk.h
drivers/clk/shmobile/clk-div6.c
drivers/clk/shmobile/clk-r8a73a4.c
drivers/clk/shmobile/clk-r8a7740.c
drivers/clk/shmobile/clk-r8a7778.c
drivers/clk/shmobile/clk-r8a7779.c
drivers/clk/shmobile/clk-rcar-gen2.c
drivers/clk/shmobile/clk-sh73a0.c
drivers/clk/sirf/clk-atlas6.c
drivers/clk/sirf/clk-atlas7.c
drivers/clk/sirf/clk-common.c
drivers/clk/sirf/clk-prima2.c
drivers/clk/socfpga/clk-gate-a10.c
drivers/clk/socfpga/clk-gate.c
drivers/clk/socfpga/clk-periph-a10.c
drivers/clk/socfpga/clk-periph.c
drivers/clk/socfpga/clk-pll-a10.c
drivers/clk/socfpga/clk-pll.c
drivers/clk/socfpga/clk.h
drivers/clk/spear/clk-vco-pll.c
drivers/clk/spear/spear1310_clock.c
drivers/clk/spear/spear1340_clock.c
drivers/clk/spear/spear6xx_clock.c
drivers/clk/st/clk-flexgen.c
drivers/clk/st/clkgen-fsyn.c
drivers/clk/st/clkgen-mux.c
drivers/clk/st/clkgen-pll.c
drivers/clk/sunxi/Makefile
drivers/clk/sunxi/clk-a20-gmac.c
drivers/clk/sunxi/clk-factors.c
drivers/clk/sunxi/clk-mod0.c
drivers/clk/sunxi/clk-simple-gates.c [new file with mode: 0644]
drivers/clk/sunxi/clk-sun6i-ar100.c
drivers/clk/sunxi/clk-sun8i-mbus.c
drivers/clk/sunxi/clk-sun9i-core.c
drivers/clk/sunxi/clk-sun9i-mmc.c
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/sunxi/clk-usb.c
drivers/clk/tegra/Makefile
drivers/clk/tegra/clk-dfll.c [new file with mode: 0644]
drivers/clk/tegra/clk-dfll.h [new file with mode: 0644]
drivers/clk/tegra/clk-divider.c
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-periph-gate.c
drivers/clk/tegra/clk-periph.c
drivers/clk/tegra/clk-pll-out.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-super.c
drivers/clk/tegra/clk-tegra-audio.c
drivers/clk/tegra/clk-tegra-fixed.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-pmc.c
drivers/clk/tegra/clk-tegra-super-gen4.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124-dfll-fcpu.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h
drivers/clk/tegra/cvb.c [new file with mode: 0644]
drivers/clk/tegra/cvb.h [new file with mode: 0644]
drivers/clk/ti/Makefile
drivers/clk/ti/apll.c
drivers/clk/ti/autoidle.c
drivers/clk/ti/clk-2xxx.c
drivers/clk/ti/clk-33xx.c
drivers/clk/ti/clk-3xxx-legacy.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-43xx.c
drivers/clk/ti/clk-44xx.c
drivers/clk/ti/clk-54xx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clk-816x.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clk.c
drivers/clk/ti/clkt_dflt.c [new file with mode: 0644]
drivers/clk/ti/clkt_dpll.c [moved from arch/arm/mach-omap2/clkt_dpll.c with 92% similarity]
drivers/clk/ti/clkt_iclk.c [new file with mode: 0644]
drivers/clk/ti/clock.h
drivers/clk/ti/clockdomain.c
drivers/clk/ti/composite.c
drivers/clk/ti/divider.c
drivers/clk/ti/dpll.c
drivers/clk/ti/dpll3xxx.c [moved from arch/arm/mach-omap2/dpll3xxx.c with 79% similarity]
drivers/clk/ti/dpll44xx.c [moved from arch/arm/mach-omap2/dpll44xx.c with 79% similarity]
drivers/clk/ti/fapll.c
drivers/clk/ti/fixed-factor.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/clk/ti/mux.c
drivers/clk/ux500/Makefile
drivers/clk/ux500/abx500-clk.c
drivers/clk/ux500/clk-prcmu.c
drivers/clk/ux500/clk-sysctrl.c
drivers/clk/ux500/clk.h
drivers/clk/ux500/u8500_clk.c [deleted file]
drivers/clk/ux500/u8500_of_clk.c
drivers/clk/ux500/u8540_clk.c
drivers/clk/ux500/u9540_clk.c
drivers/clk/versatile/clk-icst.c
drivers/clk/versatile/clk-impd1.c
drivers/clk/versatile/clk-realview.c
drivers/clk/versatile/clk-sp810.c
drivers/clk/versatile/clk-versatile.c
drivers/clk/zte/Makefile
drivers/clk/zte/clk-zx296702.c
drivers/clk/zte/clk.c [moved from drivers/clk/zte/clk-pll.c with 55% similarity]
drivers/clk/zte/clk.h
drivers/clk/zynq/clkc.c
drivers/clocksource/cadence_ttc_timer.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
drivers/video/fbdev/simplefb.c
include/dt-bindings/clock/exynos3250.h
include/dt-bindings/clock/exynos5250.h
include/dt-bindings/clock/imx6ul-clock.h [new file with mode: 0644]
include/dt-bindings/clock/rk3066a-cru.h
include/dt-bindings/clock/rk3188-cru-common.h
include/dt-bindings/clock/rk3188-cru.h
include/dt-bindings/clock/rk3288-cru.h
include/dt-bindings/clock/rk3368-cru.h [new file with mode: 0644]
include/dt-bindings/clock/zx296702-clock.h
include/dt-bindings/reset/tegra124-car.h [new file with mode: 0644]
include/linux/clk-provider.h
include/linux/clk/clk-conf.h
include/linux/clk/tegra.h
include/linux/clk/ti.h
include/linux/platform_data/clk-ux500.h
lib/vsprintf.c

index f463bdc37f885c80d4614d6c9ab729c739e298d5..5c4bc4d01d0c32939af28b3c0044f1700231d4a1 100644 (file)
@@ -71,12 +71,8 @@ the operations defined in clk.h:
                long            (*round_rate)(struct clk_hw *hw,
                                                unsigned long rate,
                                                unsigned long *parent_rate);
-               long            (*determine_rate)(struct clk_hw *hw,
-                                               unsigned long rate,
-                                               unsigned long min_rate,
-                                               unsigned long max_rate,
-                                               unsigned long *best_parent_rate,
-                                               struct clk_hw **best_parent_clk);
+               int             (*determine_rate)(struct clk_hw *hw,
+                                                 struct clk_rate_request *req);
                int             (*set_parent)(struct clk_hw *hw, u8 index);
                u8              (*get_parent)(struct clk_hw *hw);
                int             (*set_rate)(struct clk_hw *hw,
index c431c67524d610bed3103dcce5434aff78b78e91..c733e28e18e5896cb6fa5ba4ff988a82c225780c 100644 (file)
@@ -127,6 +127,24 @@ Example:
                #clock-cells = <1>;
        };
 
+
+Hisilicon Hi6220 SRAM controller
+
+Required properties:
+- compatible : "hisilicon,hi6220-sramctrl", "syscon"
+- reg : Register address and size
+
+Hisilicon's SoCs use sram for multiple purpose; on Hi6220 there have several
+SRAM banks for power management, modem, security, etc. Further, use "syscon"
+managing the common sram which can be shared by multiple modules.
+
+Example:
+       /*for Hi6220*/
+       sram: sram@fff80000 {
+               compatible = "hisilicon,hi6220-sramctrl", "syscon";
+               reg = <0x0 0xfff80000 0x0 0x12000>;
+       };
+
 -----------------------------------------------------------------------
 Hisilicon HiP01 system controller
 
diff --git a/Documentation/devicetree/bindings/arm/sp810.txt b/Documentation/devicetree/bindings/arm/sp810.txt
new file mode 100644 (file)
index 0000000..6808fb5
--- /dev/null
@@ -0,0 +1,46 @@
+SP810 System Controller
+-----------------------
+
+Required properties:
+
+- compatible:  standard compatible string for a Primecell peripheral,
+               see Documentation/devicetree/bindings/arm/primecell.txt
+               for more details
+               should be: "arm,sp810", "arm,primecell"
+
+- reg:         standard registers property, physical address and size
+               of the control registers
+
+- clock-names: from the common clock bindings, for more details see
+               Documentation/devicetree/bindings/clock/clock-bindings.txt;
+               should be: "refclk", "timclk", "apb_pclk"
+
+- clocks:      from the common clock bindings, phandle and clock
+               specifier pairs for the entries of clock-names property
+
+- #clock-cells: from the common clock bindings;
+               should be: <1>
+
+- clock-output-names: from the common clock bindings;
+               should be: "timerclken0", "timerclken1", "timerclken2", "timerclken3"
+
+- assigned-clocks: from the common clock binding;
+               should be: clock specifier for each output clock of this
+               provider node
+
+- assigned-clock-parents: from the common clock binding;
+               should be: phandle of input clock listed in clocks
+               property with the highest frequency
+
+Example:
+       v2m_sysctl: sysctl@020000 {
+               compatible = "arm,sp810", "arm,primecell";
+               reg = <0x020000 0x1000>;
+               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+               clock-names = "refclk", "timclk", "apb_pclk";
+               #clock-cells = <1>;
+               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+               assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
+               assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
+
+       };
diff --git a/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt b/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt
new file mode 100644 (file)
index 0000000..2be1e03
--- /dev/null
@@ -0,0 +1,19 @@
+Binding for simple gpio clock multiplexer.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "gpio-mux-clock".
+- clocks: list of two references to parent clocks.
+- #clock-cells : from common clock binding; shall be set to 0.
+- select-gpios : GPIO reference for selecting the parent clock.
+
+Example:
+       clock {
+               compatible = "gpio-mux-clock";
+               clocks = <&parentclk1>, <&parentclk2>;
+               #clock-cells = <0>;
+               select-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
+       };
index 259e30af959768cbbedaeca27648589a9746871d..e4d5feaebc292c7944f32fe5484c2839444f7658 100644 (file)
@@ -15,19 +15,36 @@ Required Properties:
        - "hisilicon,hi6220-sysctrl"
        - "hisilicon,hi6220-mediactrl"
        - "hisilicon,hi6220-pmctrl"
+       - "hisilicon,hi6220-stub-clk"
 
 - reg: physical base address of the controller and length of memory mapped
   region.
 
 - #clock-cells: should be 1.
 
-For example:
+Optional Properties:
+
+- hisilicon,hi6220-clk-sram: phandle to the syscon managing the SoC internal sram;
+  the driver need use the sram to pass parameters for frequency change.
+
+- mboxes: use the label reference for the mailbox as the first parameter, the
+  second parameter is the channel number.
+
+Example 1:
        sys_ctrl: sys_ctrl@f7030000 {
                compatible = "hisilicon,hi6220-sysctrl", "syscon";
                reg = <0x0 0xf7030000 0x0 0x2000>;
                #clock-cells = <1>;
        };
 
+Example 2:
+       stub_clock: stub_clock {
+               compatible = "hisilicon,hi6220-stub-clk";
+               hisilicon,hi6220-clk-sram = <&sram>;
+               #clock-cells = <1>;
+               mboxes = <&mailbox 1>;
+       };
+
 Each clock is assigned an identifier and client nodes use this identifier
 to specify the clock which they consume.
 
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
new file mode 100644 (file)
index 0000000..ee7e5fd
--- /dev/null
@@ -0,0 +1,79 @@
+NVIDIA Tegra124 DFLL FCPU clocksource
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The DFLL IP block on Tegra is a root clocksource designed for clocking
+the fast CPU cluster. It consists of a free-running voltage controlled
+oscillator connected to the CPU voltage rail (VDD_CPU), and a closed loop
+control module that will automatically adjust the VDD_CPU voltage by
+communicating with an off-chip PMIC either via an I2C bus or via PWM signals.
+Currently only the I2C mode is supported by these bindings.
+
+Required properties:
+- compatible : should be "nvidia,tegra124-dfll"
+- reg : Defines the following set of registers, in the order listed:
+        - registers for the DFLL control logic.
+        - registers for the I2C output logic.
+        - registers for the integrated I2C master controller.
+        - look-up table RAM for voltage register values.
+- interrupts: Should contain the DFLL block interrupt.
+- clocks: Must contain an entry for each entry in clock-names.
+  See clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - soc: Clock source for the DFLL control logic.
+  - ref: The closed loop reference clock
+  - i2c: Clock source for the integrated I2C master.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - dvco: Reset control for the DFLL DVCO.
+- #clock-cells: Must be 0.
+- clock-output-names: Name of the clock output.
+- vdd-cpu-supply: Regulator for the CPU voltage rail that the DFLL
+  hardware will start controlling. The regulator will be queried for
+  the I2C register, control values and supported voltages.
+
+Required properties for the control loop parameters:
+- nvidia,sample-rate: Sample rate of the DFLL control loop.
+- nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM.
+- nvidia,force-mode: See the field DFLL_PARAMS_FORCE_MODE in the TRM.
+- nvidia,cf: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM.
+- nvidia,ci: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM.
+- nvidia,cg: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM.
+
+Optional properties for the control loop parameters:
+- nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM.
+
+Required properties for I2C mode:
+- nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode.
+
+Example:
+
+clock@0,70110000 {
+        compatible = "nvidia,tegra124-dfll";
+        reg = <0 0x70110000 0 0x100>, /* DFLL control */
+              <0 0x70110000 0 0x100>, /* I2C output control */
+              <0 0x70110100 0 0x100>, /* Integrated I2C controller */
+              <0 0x70110200 0 0x100>; /* Look-up table RAM */
+        interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>,
+                 <&tegra_car TEGRA124_CLK_DFLL_REF>,
+                 <&tegra_car TEGRA124_CLK_I2C5>;
+        clock-names = "soc", "ref", "i2c";
+        resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
+        reset-names = "dvco";
+        #clock-cells = <0>;
+        clock-output-names = "dfllCPU_out";
+        vdd-cpu-supply = <&vdd_cpu>;
+        status = "okay";
+
+        nvidia,sample-rate = <12500>;
+        nvidia,droop-ctrl = <0x00000f00>;
+        nvidia,force-mode = <1>;
+        nvidia,cf = <10>;
+        nvidia,ci = <0>;
+        nvidia,cg = <2>;
+
+        nvidia,i2c-fs-rate = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
new file mode 100644 (file)
index 0000000..7c8bbcf
--- /dev/null
@@ -0,0 +1,61 @@
+* Rockchip RK3368 Clock and Reset Unit
+
+The RK3368 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,rk3368-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/rk3368-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,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_gmac" - external GMAC clock - optional
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+ - "ext_vip" - external VIP clock - optional,
+ - "usbotg_out" - output clock of the pll in the otg phy
+
+Example: Clock controller node:
+
+       cru: clock-controller@ff760000 {
+               compatible = "rockchip,rk3368-cru";
+               reg = <0x0 0xff760000 0x0 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@10124000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x10124000 0x400>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <1>;
+               clocks = <&cru SCLK_UART0>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ux500.txt b/Documentation/devicetree/bindings/clock/ux500.txt
new file mode 100644 (file)
index 0000000..e52bd4b
--- /dev/null
@@ -0,0 +1,64 @@
+Clock bindings for ST-Ericsson Ux500 clocks
+
+Required properties :
+- compatible : shall contain only one of the following:
+  "stericsson,u8500-clks"
+  "stericsson,u8540-clks"
+  "stericsson,u9540-clks"
+- reg : shall contain base register location and length for
+  CLKRST1, 2, 3, 5, and 6 in an array. Note the absence of
+  CLKRST4, which does not exist.
+
+Required subnodes:
+- prcmu-clock: a subnode with one clock cell for PRCMU (power,
+  reset, control unit) clocks. The cell indicates which PRCMU
+  clock in the prcmu-clock node the consumer wants to use.
+- prcc-periph-clock: a subnode with two clock cells for
+  PRCC (programmable reset- and clock controller) peripheral clocks.
+  The first cell indicates which PRCC block the consumer
+  wants to use, possible values are 1, 2, 3, 5, 6. The second
+  cell indicates which clock inside the PRCC block it wants,
+  possible values are 0 thru 31.
+- prcc-kernel-clock: a subnode with two clock cells for
+  PRCC (programmable reset- and clock controller) kernel clocks
+  The first cell indicates which PRCC block the consumer
+  wants to use, possible values are 1, 2, 3, 5, 6. The second
+  cell indicates which clock inside the PRCC block it wants,
+  possible values are 0 thru 31.
+- rtc32k-clock: a subnode with zero clock cells for the 32kHz
+  RTC clock.
+- smp-twd-clock: a subnode for the ARM SMP Timer Watchdog cluster
+  with zero clock cells.
+
+Example:
+
+clocks {
+       compatible = "stericsson,u8500-clks";
+       /*
+        * Registers for the CLKRST block on peripheral
+        * groups 1, 2, 3, 5, 6,
+        */
+       reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
+           <0x8000f000 0x1000>, <0xa03ff000 0x1000>,
+           <0xa03cf000 0x1000>;
+
+       prcmu_clk: prcmu-clock {
+               #clock-cells = <1>;
+       };
+
+       prcc_pclk: prcc-periph-clock {
+               #clock-cells = <2>;
+       };
+
+       prcc_kclk: prcc-kernel-clock {
+               #clock-cells = <2>;
+       };
+
+       rtc_clk: rtc32k-clock {
+               #clock-cells = <0>;
+       };
+
+       smp_twd_clk: smp-twd-clock {
+               #clock-cells = <0>;
+       };
+};
index b8f81fb418ce60039ad4e8e04f2892ca34d26bc8..c5fbde3afcf6fc482aa4d1f521b3c138c20608e1 100644 (file)
 
                clocks {
                        compatible = "stericsson,u8500-clks";
+                       /*
+                        * Registers for the CLKRST block on peripheral
+                        * groups 1, 2, 3, 5, 6,
+                        */
+                       reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
+                           <0x8000f000 0x1000>, <0xa03ff000 0x1000>,
+                           <0xa03cf000 0x1000>;
 
                        prcmu_clk: prcmu-clock {
                                #clock-cells = <1>;
index 61c03d1fe5303301a7ee44f1069c3865da958313..ab0e131587bb2dccdfff15c189bbb07771388129 100644 (file)
                        compatible = "allwinner,sun4i-a10-axi-gates-clk";
                        reg = <0x01c2005c 0x4>;
                        clocks = <&axi>;
+                       clock-indices = <0>;
                        clock-output-names = "axi_dram";
                };
 
                        compatible = "allwinner,sun4i-a10-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>,
+                                       <4>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <11>, <12>,
+                                       <13>, <14>, <16>,
+                                       <17>, <18>, <20>,
+                                       <21>, <22>, <23>,
+                                       <24>, <25>, <26>,
+                                       <32>, <33>, <34>,
+                                       <35>, <36>, <37>,
+                                       <40>, <41>, <43>,
+                                       <44>, <45>,
+                                       <46>, <47>,
+                                       <50>, <52>;
                        clock-output-names = "ahb_usb0", "ahb_ehci0",
-                               "ahb_ohci0", "ahb_ehci1", "ahb_ohci1", "ahb_ss",
-                               "ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1",
-                               "ahb_mmc2", "ahb_mmc3", "ahb_ms", "ahb_nand",
-                               "ahb_sdram", "ahb_ace", "ahb_emac", "ahb_ts",
-                               "ahb_spi0", "ahb_spi1", "ahb_spi2", "ahb_spi3",
-                               "ahb_pata", "ahb_sata", "ahb_gps", "ahb_ve",
-                               "ahb_tvd", "ahb_tve0", "ahb_tve1", "ahb_lcd0",
-                               "ahb_lcd1", "ahb_csi0", "ahb_csi1", "ahb_hdmi",
-                               "ahb_de_be0", "ahb_de_be1", "ahb_de_fe0",
-                               "ahb_de_fe1", "ahb_mp", "ahb_mali400";
+                                            "ahb_ohci0", "ahb_ehci1",
+                                            "ahb_ohci1", "ahb_ss", "ahb_dma",
+                                            "ahb_bist", "ahb_mmc0", "ahb_mmc1",
+                                            "ahb_mmc2", "ahb_mmc3", "ahb_ms",
+                                            "ahb_nand", "ahb_sdram", "ahb_ace",
+                                            "ahb_emac", "ahb_ts", "ahb_spi0",
+                                            "ahb_spi1", "ahb_spi2", "ahb_spi3",
+                                            "ahb_pata", "ahb_sata", "ahb_gps",
+                                            "ahb_ve", "ahb_tvd", "ahb_tve0",
+                                            "ahb_tve1", "ahb_lcd0", "ahb_lcd1",
+                                            "ahb_csi0", "ahb_csi1", "ahb_hdmi",
+                                            "ahb_de_be0", "ahb_de_be1",
+                                            "ahb_de_fe0", "ahb_de_fe1",
+                                            "ahb_mp", "ahb_mali400";
                };
 
                apb0: apb0@01c20054 {
                        compatible = "allwinner,sun4i-a10-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>,
+                                       <5>, <6>,
+                                       <7>, <10>;
                        clock-output-names = "apb0_codec", "apb0_spdif",
-                               "apb0_ac97", "apb0_iis", "apb0_pio", "apb0_ir0",
-                               "apb0_ir1", "apb0_keypad";
+                                            "apb0_ac97", "apb0_iis",
+                                            "apb0_pio", "apb0_ir0",
+                                            "apb0_ir1", "apb0_keypad";
                };
 
                apb1: clk@01c20058 {
                        compatible = "allwinner,sun4i-a10-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <4>,
+                                       <5>, <6>,
+                                       <7>, <16>,
+                                       <17>, <18>,
+                                       <19>, <20>,
+                                       <21>, <22>,
+                                       <23>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
-                               "apb1_i2c2", "apb1_can", "apb1_scr",
-                               "apb1_ps20", "apb1_ps21", "apb1_uart0",
-                               "apb1_uart1", "apb1_uart2", "apb1_uart3",
-                               "apb1_uart4", "apb1_uart5", "apb1_uart6",
-                               "apb1_uart7";
+                                            "apb1_i2c2", "apb1_can",
+                                            "apb1_scr", "apb1_ps20",
+                                            "apb1_ps21", "apb1_uart0",
+                                            "apb1_uart1", "apb1_uart2",
+                                            "apb1_uart3", "apb1_uart4",
+                                            "apb1_uart5", "apb1_uart6",
+                                            "apb1_uart7";
                };
 
                nand_clk: clk@01c20080 {
index f11efb722bbb025cc7f0d5b7b22524e3bc060c45..a513b416a80773c970105920cecd8878d46a2dfc 100644 (file)
                        compatible = "allwinner,sun5i-a10s-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <13>,
+                                       <14>, <17>, <18>,
+                                       <20>, <21>, <22>,
+                                       <26>, <28>, <32>,
+                                       <34>, <36>, <40>,
+                                       <43>, <44>,
+                                       <46>, <51>,
+                                       <52>;
                        clock-output-names = "ahb_usbotg", "ahb_ehci",
                                             "ahb_ohci", "ahb_ss", "ahb_dma",
                                             "ahb_bist", "ahb_mmc0", "ahb_mmc1",
                        compatible = "allwinner,sun5i-a10s-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <3>,
+                                       <5>, <6>,
+                                       <10>;
                        clock-output-names = "apb0_codec", "apb0_iis",
                                             "apb0_pio", "apb0_ir",
                                             "apb0_keypad";
                        compatible = "allwinner,sun5i-a10s-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <16>,
+                                       <17>, <18>,
+                                       <19>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
-                               "apb1_i2c2", "apb1_uart0", "apb1_uart1",
-                               "apb1_uart2", "apb1_uart3";
+                                            "apb1_i2c2", "apb1_uart0",
+                                            "apb1_uart1", "apb1_uart2",
+                                            "apb1_uart3";
                };
        };
 
index 976d4faa2179ace0c60d6adc269deb226c314e15..f3631c9c6fa2616e8b5ef209df59ca9ac9ee0ad3 100644 (file)
                        compatible = "allwinner,sun5i-a13-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <13>,
+                                       <14>, <20>,
+                                       <21>, <22>,
+                                       <28>, <32>, <36>,
+                                       <40>, <44>,
+                                       <46>, <51>,
+                                       <52>;
                        clock-output-names = "ahb_usbotg", "ahb_ehci",
                                             "ahb_ohci", "ahb_ss", "ahb_dma",
                                             "ahb_bist", "ahb_mmc0", "ahb_mmc1",
                        compatible = "allwinner,sun5i-a13-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <5>,
+                                       <6>;
                        clock-output-names = "apb0_codec", "apb0_pio",
                                             "apb0_ir";
                };
                        compatible = "allwinner,sun5i-a13-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <17>,
+                                       <19>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
-                               "apb1_i2c2", "apb1_uart1", "apb1_uart3";
+                                            "apb1_i2c2", "apb1_uart1",
+                                            "apb1_uart3";
                };
        };
 };
index 54b0978304344104d94d7d4e79a3117986563204..427c0e7289fa3d44d05c281d8c5f0860501f7a77 100644 (file)
                        compatible = "allwinner,sun4i-a10-axi-gates-clk";
                        reg = <0x01c2005c 0x4>;
                        clocks = <&axi>;
+                       clock-indices = <0>;
                        clock-output-names = "axi_dram";
                };
 
index 008047a018cf2b645cc85136c194be665376c5ef..3ec456fa03a4f84c2a1ea6566c9ddf5337a8e3b1 100644 (file)
                        compatible = "allwinner,sun6i-a31-ahb1-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb1>;
+                       clock-indices = <1>, <5>,
+                                       <6>, <8>, <9>,
+                                       <10>, <11>, <12>,
+                                       <13>, <14>,
+                                       <17>, <18>, <19>,
+                                       <20>, <21>, <22>,
+                                       <23>, <24>, <26>,
+                                       <27>, <29>,
+                                       <30>, <31>, <32>,
+                                       <36>, <37>, <40>,
+                                       <43>, <44>, <45>,
+                                       <46>, <47>, <50>,
+                                       <52>, <55>, <56>,
+                                       <57>, <58>;
                        clock-output-names = "ahb1_mipidsi", "ahb1_ss",
                                        "ahb1_dma", "ahb1_mmc0", "ahb1_mmc1",
                                        "ahb1_mmc2", "ahb1_mmc3", "ahb1_nand1",
                        compatible = "allwinner,sun6i-a31-apb1-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <4>,
+                                       <5>, <12>,
+                                       <13>;
                        clock-output-names = "apb1_codec", "apb1_digital_mic",
                                        "apb1_pio", "apb1_daudio0",
                                        "apb1_daudio1";
                        compatible = "allwinner,sun6i-a31-apb2-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb2>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <16>,
+                                       <17>, <18>, <19>,
+                                       <20>, <21>;
                        clock-output-names = "apb2_i2c0", "apb2_i2c1",
                                             "apb2_i2c2", "apb2_i2c3",
                                             "apb2_uart0", "apb2_uart1",
                        compatible = "allwinner,sun6i-a31-usb-clk";
                        reg = <0x01c200cc 0x4>;
                        clocks = <&osc24M>;
+                       clock-indices = <8>, <9>, <10>,
+                                       <16>, <17>,
+                                       <18>;
                        clock-output-names = "usb_phy0", "usb_phy1", "usb_phy2",
                                             "usb_ohci0", "usb_ohci1",
                                             "usb_ohci2";
index 6a63f30c9a699d0e4620aac31f64247ad9c1f95b..ca0b01a96c52b5762f9c97a411bc75c107c491a7 100644 (file)
                        compatible = "allwinner,sun7i-a20-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <5>, <6>, <7>, <8>,
+                                       <9>, <10>, <11>, <12>,
+                                       <13>, <14>, <16>,
+                                       <17>, <18>, <20>, <21>,
+                                       <22>, <23>, <25>,
+                                       <28>, <32>, <33>, <34>,
+                                       <35>, <36>, <37>, <40>,
+                                       <41>, <42>, <43>,
+                                       <44>, <45>, <46>,
+                                       <47>, <49>, <50>,
+                                       <52>;
                        clock-output-names = "ahb_usb0", "ahb_ehci0",
                                "ahb_ohci0", "ahb_ehci1", "ahb_ohci1",
                                "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0",
                        compatible = "allwinner,sun7i-a20-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <5>, <6>, <7>,
+                                       <8>, <10>;
                        clock-output-names = "apb0_codec", "apb0_spdif",
                                "apb0_ac97", "apb0_iis0", "apb0_iis1",
                                "apb0_pio", "apb0_ir0", "apb0_ir1",
                        compatible = "allwinner,sun7i-a20-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <5>, <6>, <7>,
+                                       <15>, <16>, <17>,
+                                       <18>, <19>, <20>,
+                                       <21>, <22>, <23>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
                                "apb1_i2c2", "apb1_i2c3", "apb1_can",
                                "apb1_scr", "apb1_ps20", "apb1_ps21",
index 7abd0ae3143d74e1f9ba9b2638fc55353a306d7c..c318c770b6c1533b0afe7de02747c05153bbe68a 100644 (file)
                        compatible = "allwinner,sun8i-a23-ahb1-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb1>;
+                       clock-indices = <1>, <6>,
+                                       <8>, <9>, <10>,
+                                       <13>, <14>,
+                                       <19>, <20>,
+                                       <21>, <24>, <26>,
+                                       <29>, <32>, <36>,
+                                       <40>, <44>, <46>,
+                                       <52>, <54>,
+                                       <57>;
                        clock-output-names = "ahb1_mipidsi", "ahb1_dma",
                                        "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2",
                                        "ahb1_nand", "ahb1_sdram",
                        compatible = "allwinner,sun8i-a23-apb1-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <5>,
+                                       <12>, <13>;
                        clock-output-names = "apb1_codec", "apb1_pio",
                                        "apb1_daudio0", "apb1_daudio1";
                };
                        compatible = "allwinner,sun8i-a23-apb2-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb2>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <16>,
+                                       <17>, <18>,
+                                       <19>, <20>;
                        clock-output-names = "apb2_i2c0", "apb2_i2c1",
                                        "apb2_i2c2", "apb2_uart0",
                                        "apb2_uart1", "apb2_uart2",
index a43ad779ee2f68546a26da570f19ba601c2dc15b..5908e3dcf9658544e1f45b38d0fcd46a6c3a58a6 100644 (file)
                        compatible = "allwinner,sun9i-a80-ahb0-gates-clk";
                        reg = <0x06000580 0x4>;
                        clocks = <&ahb0>;
-                       clock-indices = <0>, <1>, <3>, <5>, <8>, <12>, <13>,
-                                       <14>, <15>, <16>, <18>, <20>, <21>,
-                                       <22>, <23>;
+                       clock-indices = <0>, <1>, <3>,
+                                       <5>, <8>, <12>,
+                                       <13>, <14>,
+                                       <15>, <16>, <18>,
+                                       <20>, <21>, <22>,
+                                       <23>;
                        clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu",
                                        "ahb0_ss", "ahb0_sd", "ahb0_nand1",
                                        "ahb0_nand0", "ahb0_sdram",
                        compatible = "allwinner,sun9i-a80-ahb1-gates-clk";
                        reg = <0x06000584 0x4>;
                        clocks = <&ahb1>;
-                       clock-indices = <0>, <1>, <17>, <21>, <22>, <23>, <24>;
+                       clock-indices = <0>, <1>,
+                                       <17>, <21>,
+                                       <22>, <23>,
+                                       <24>;
                        clock-output-names = "ahb1_usbotg", "ahb1_usbhci",
                                        "ahb1_gmac", "ahb1_msgbox",
                                        "ahb1_spinlock", "ahb1_hstimer",
                        compatible = "allwinner,sun9i-a80-ahb2-gates-clk";
                        reg = <0x06000588 0x4>;
                        clocks = <&ahb2>;
-                       clock-indices = <0>, <1>, <2>, <4>, <5>, <7>, <8>,
-                                       <11>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <4>, <5>,
+                                       <7>, <8>, <11>;
                        clock-output-names = "ahb2_lcd0", "ahb2_lcd1",
                                        "ahb2_edp", "ahb2_csi", "ahb2_hdmi",
                                        "ahb2_de", "ahb2_mp", "ahb2_mipi_dsi";
                        compatible = "allwinner,sun9i-a80-apb0-gates-clk";
                        reg = <0x06000590 0x4>;
                        clocks = <&apb0>;
-                       clock-indices = <1>, <5>, <11>, <12>, <13>, <15>,
-                                       <17>, <18>, <19>;
+                       clock-indices = <1>, <5>,
+                                       <11>, <12>, <13>,
+                                       <15>, <17>, <18>,
+                                       <19>;
                        clock-output-names = "apb0_spdif", "apb0_pio",
                                        "apb0_ac97", "apb0_i2s0", "apb0_i2s1",
                                        "apb0_lradc", "apb0_gpadc", "apb0_twd",
                        compatible = "allwinner,sun9i-a80-apb1-gates-clk";
                        reg = <0x06000594 0x4>;
                        clocks = <&apb1>;
-                       clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                       <16>, <17>, <18>, <19>, <20>, <21>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <16>, <17>,
+                                       <18>, <19>,
+                                       <20>, <21>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
                                        "apb1_i2c2", "apb1_i2c3", "apb1_i2c4",
                                        "apb1_uart0", "apb1_uart1",
index eaf58f88ef5dcd262a862e96b0656b03a31cf8b3..685826c4a710b16e11f21a400480b516ed8c09d9 100644 (file)
@@ -8,7 +8,6 @@
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
index c6bd7c7bd4aa4949203505247f0fd9db21ea0c5b..8cc62150116a779b48e15b71b4937af154075415 100644 (file)
@@ -11,7 +11,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
 
index edea697e8253d601ce2323a0a99c1083d1e9ff93..e283939a216fb188c0fa9ccaaa08b70eb18ff7ef 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_clock.h>
 #include <linux/platform_device.h>
-#include <linux/clk-provider.h>
 #include <linux/of.h>
 
 static struct dev_pm_domain keystone_pm_domain = {
index afee9083ad92bc6d16bb7b29ef5f86f811351847..9f739f3cad4c7e584391c0e8f79ec27376d5fa4c 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
index 903c85be28972e6e7d28aaf9459f5bc87b4ac87c..7892c7d3b6f4b005c9416dbcd108bfab6ead2b3c 100644 (file)
@@ -12,8 +12,7 @@ obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \
 
 hwmod-common                           = omap_hwmod.o omap_hwmod_reset.o \
                                          omap_hwmod_common_data.o
-clock-common                           = clock.o clock_common_data.o \
-                                         clkt_dpll.o clkt_clksel.o
+clock-common                           = clock.o
 secure-common                          = omap-smc.o omap-secure.o
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
@@ -182,24 +181,17 @@ obj-$(CONFIG_SOC_DRA7XX)          += $(clockdomain-common)
 obj-$(CONFIG_SOC_DRA7XX)               += clockdomains7xx_data.o
 
 # Clock framework
-obj-$(CONFIG_ARCH_OMAP2)               += $(clock-common) clock2xxx.o
+obj-$(CONFIG_ARCH_OMAP2)               += $(clock-common)
 obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_dpllcore.o
 obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_virt_prcm_set.o
-obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_dpll.o clkt_iclk.o
-obj-$(CONFIG_SOC_OMAP2430)             += clock2430.o
-obj-$(CONFIG_ARCH_OMAP3)               += $(clock-common) clock3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)               += clock34xx.o clkt34xx_dpll3m2.o
-obj-$(CONFIG_ARCH_OMAP3)               += clock3517.o clock36xx.o
-obj-$(CONFIG_ARCH_OMAP3)               += dpll3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)               += clkt_iclk.o
+obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_dpll.o
+obj-$(CONFIG_ARCH_OMAP3)               += $(clock-common)
+obj-$(CONFIG_ARCH_OMAP3)               += clkt34xx_dpll3m2.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(clock-common)
-obj-$(CONFIG_ARCH_OMAP4)               += dpll3xxx.o dpll44xx.o
-obj-$(CONFIG_SOC_AM33XX)               += $(clock-common) dpll3xxx.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clock-common)
 obj-$(CONFIG_SOC_OMAP5)                        += $(clock-common)
-obj-$(CONFIG_SOC_OMAP5)                        += dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_DRA7XX)               += $(clock-common)
-obj-$(CONFIG_SOC_DRA7XX)               += dpll3xxx.o dpll44xx.o
-obj-$(CONFIG_SOC_AM43XX)               += $(clock-common) dpll3xxx.o
+obj-$(CONFIG_SOC_AM43XX)               += $(clock-common)
 
 # OMAP2 clock rate set data (old "OPP" data)
 obj-$(CONFIG_SOC_OMAP2420)             += opp2420_data.o
index eb69acf21014e023184baac01b8821c528b7ed56..3f6521313c93337a791963003339218d9adf3f10 100644 (file)
 
 #include "clock.h"
 #include "clock3xxx.h"
-#include "clock34xx.h"
 #include "sdrc.h"
 #include "sram.h"
 
 #define CYCLES_PER_MHZ                 1000000
 
+struct clk *sdrc_ick_p, *arm_fck_p;
+
 /*
  * CORE DPLL (DPLL3) M2 divider rate programming functions
  *
@@ -60,12 +61,14 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!clk || !rate)
                return -EINVAL;
 
-       validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
+       new_div = DIV_ROUND_UP(parent_rate, rate);
+       validrate = parent_rate / new_div;
+
        if (validrate != rate)
                return -EINVAL;
 
-       sdrcrate = __clk_get_rate(sdrc_ick_p);
-       clkrate = __clk_get_rate(hw->clk);
+       sdrcrate = clk_get_rate(sdrc_ick_p);
+       clkrate = clk_hw_get_rate(hw);
        if (rate > clkrate)
                sdrcrate <<= ((rate / clkrate) >> 1);
        else
@@ -83,7 +86,7 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
        /*
         * XXX This only needs to be done when the CPU frequency changes
         */
-       _mpurate = __clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
+       _mpurate = clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
        c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
        c += 1;  /* for safety */
        c *= SDRC_MPURATE_LOOPS;
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
deleted file mode 100644 (file)
index 7ee2610..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * clkt_clksel.c - OMAP2/3/4 clksel clock functions
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * 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.
- *
- *
- * clksel clocks are clocks that do not have a fixed parent, or that
- * can divide their parent's rate, or possibly both at the same time, based
- * on the contents of a hardware register bitfield.
- *
- * All of the various mux and divider settings can be encoded into
- * struct clksel* data structures, and then these can be autogenerated
- * from some hardware database for each new chip generation.  This
- * should avoid the need to write, review, and validate a lot of new
- * clock code for each new chip, since it can be exported from the SoC
- * design flow.  This is now done on OMAP4.
- *
- * The fusion of mux and divider clocks is a software creation.  In
- * hardware reality, the multiplexer (parent selection) and the
- * divider exist separately.  XXX At some point these clksel clocks
- * should be split into "divider" clocks and "mux" clocks to better
- * match the hardware.
- *
- * (The name "clksel" comes from the name of the corresponding
- * register field in the OMAP2/3 family of SoCs.)
- *
- * XXX Currently these clocks are only used in the OMAP2/3/4 code, but
- * many of the OMAP1 clocks should be convertible to use this
- * mechanism.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/bug.h>
-
-#include "clock.h"
-
-/* Private functions */
-
-/**
- * _get_clksel_by_parent() - return clksel struct for a given clk & parent
- * @clk: OMAP struct clk ptr to inspect
- * @src_clk: OMAP struct clk ptr of the parent clk to search for
- *
- * Scan the struct clksel array associated with the clock to find
- * the element associated with the supplied parent clock address.
- * Returns a pointer to the struct clksel on success or NULL on error.
- */
-static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
-                                                 struct clk *src_clk)
-{
-       const struct clksel *clks;
-
-       if (!src_clk)
-               return NULL;
-
-       for (clks = clk->clksel; clks->parent; clks++)
-               if (clks->parent == src_clk)
-                       break; /* Found the requested parent */
-
-       if (!clks->parent) {
-               /* This indicates a data problem */
-               WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
-                    __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
-               return NULL;
-       }
-
-       return clks;
-}
-
-/**
- * _write_clksel_reg() - program a clock's clksel register in hardware
- * @clk: struct clk * to program
- * @v: clksel bitfield value to program (with LSB at bit 0)
- *
- * Shift the clksel register bitfield value @v to its appropriate
- * location in the clksel register and write it in.  This function
- * will ensure that the write to the clksel_reg reaches its
- * destination before returning -- important since PRM and CM register
- * accesses can be quite slow compared to ARM cycles -- but does not
- * take into account any time the hardware might take to switch the
- * clock source.
- */
-static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
-{
-       u32 v;
-
-       v = omap2_clk_readl(clk, clk->clksel_reg);
-       v &= ~clk->clksel_mask;
-       v |= field_val << __ffs(clk->clksel_mask);
-       omap2_clk_writel(v, clk, clk->clksel_reg);
-
-       v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */
-}
-
-/**
- * _clksel_to_divisor() - turn clksel field value into integer divider
- * @clk: OMAP struct clk to use
- * @field_val: register field value to find
- *
- * Given a struct clk of a rate-selectable clksel clock, and a register field
- * value to search for, find the corresponding clock divisor.  The register
- * field value should be pre-masked and shifted down so the LSB is at bit 0
- * before calling.  Returns 0 on error or returns the actual integer divisor
- * upon success.
- */
-static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
-{
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       struct clk *parent;
-
-       parent = __clk_get_parent(clk->hw.clk);
-
-       clks = _get_clksel_by_parent(clk, parent);
-       if (!clks)
-               return 0;
-
-       for (clkr = clks->rates; clkr->div; clkr++) {
-               if (!(clkr->flags & cpu_mask))
-                       continue;
-
-               if (clkr->val == field_val)
-                       break;
-       }
-
-       if (!clkr->div) {
-               /* This indicates a data error */
-               WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
-                    __clk_get_name(clk->hw.clk), field_val,
-                    __clk_get_name(parent));
-               return 0;
-       }
-
-       return clkr->div;
-}
-
-/**
- * _divisor_to_clksel() - turn clksel integer divisor into a field value
- * @clk: OMAP struct clk to use
- * @div: integer divisor to search for
- *
- * Given a struct clk of a rate-selectable clksel clock, and a clock
- * divisor, find the corresponding register field value.  Returns the
- * register field value _before_ left-shifting (i.e., LSB is at bit
- * 0); or returns 0xFFFFFFFF (~0) upon error.
- */
-static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
-{
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       struct clk *parent;
-
-       /* should never happen */
-       WARN_ON(div == 0);
-
-       parent = __clk_get_parent(clk->hw.clk);
-       clks = _get_clksel_by_parent(clk, parent);
-       if (!clks)
-               return ~0;
-
-       for (clkr = clks->rates; clkr->div; clkr++) {
-               if (!(clkr->flags & cpu_mask))
-                       continue;
-
-               if (clkr->div == div)
-                       break;
-       }
-
-       if (!clkr->div) {
-               pr_err("clock: %s: could not find divisor %d for parent %s\n",
-                      __clk_get_name(clk->hw.clk), div,
-                      __clk_get_name(parent));
-               return ~0;
-       }
-
-       return clkr->val;
-}
-
-/**
- * _read_divisor() - get current divisor applied to parent clock (from hdwr)
- * @clk: OMAP struct clk to use.
- *
- * Read the current divisor register value for @clk that is programmed
- * into the hardware, convert it into the actual divisor value, and
- * return it; or return 0 on error.
- */
-static u32 _read_divisor(struct clk_hw_omap *clk)
-{
-       u32 v;
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return 0;
-
-       v = omap2_clk_readl(clk, clk->clksel_reg);
-       v &= clk->clksel_mask;
-       v >>= __ffs(clk->clksel_mask);
-
-       return _clksel_to_divisor(clk, v);
-}
-
-/* Public functions */
-
-/**
- * omap2_clksel_round_rate_div() - find divisor for the given clock and rate
- * @clk: OMAP struct clk to use
- * @target_rate: desired clock rate
- * @new_div: ptr to where we should store the divisor
- *
- * Finds 'best' divider value in an array based on the source and target
- * rates.  The divider array must be sorted with smallest divider first.
- * This function is also used by the DPLL3 M2 divider code.
- *
- * Returns the rounded clock rate or returns 0xffffffff on error.
- */
-u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
-                                                unsigned long target_rate,
-                               u32 *new_div)
-{
-       unsigned long test_rate;
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       u32 last_div = 0;
-       struct clk *parent;
-       unsigned long parent_rate;
-       const char *clk_name;
-
-       parent = __clk_get_parent(clk->hw.clk);
-       clk_name = __clk_get_name(clk->hw.clk);
-       parent_rate = __clk_get_rate(parent);
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return ~0;
-
-       pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
-                clk_name, target_rate);
-
-       *new_div = 1;
-
-       clks = _get_clksel_by_parent(clk, parent);
-       if (!clks)
-               return ~0;
-
-       for (clkr = clks->rates; clkr->div; clkr++) {
-               if (!(clkr->flags & cpu_mask))
-                       continue;
-
-               /* Sanity check */
-               if (clkr->div <= last_div)
-                       pr_err("clock: %s: clksel_rate table not sorted\n",
-                              clk_name);
-
-               last_div = clkr->div;
-
-               test_rate = parent_rate / clkr->div;
-
-               if (test_rate <= target_rate)
-                       break; /* found it */
-       }
-
-       if (!clkr->div) {
-               pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
-                      clk_name, target_rate, __clk_get_name(parent));
-               return ~0;
-       }
-
-       *new_div = clkr->div;
-
-       pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
-                (parent_rate / clkr->div));
-
-       return parent_rate / clkr->div;
-}
-
-/*
- * Clocktype interface functions to the OMAP clock code
- * (i.e., those used in struct clk field function pointers, etc.)
- */
-
-/**
- * omap2_clksel_find_parent_index() - return the array index of the current
- * hardware parent of @hw
- * @hw: struct clk_hw * to find the current hardware parent of
- *
- * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
- * clk_hw_omap record representing a source-selectable hardware clock,
- * read the hardware register and determine what its parent is
- * currently set to.  Intended to be called only by the common clock
- * framework struct clk_hw_ops.get_parent function pointer.  Return
- * the array index of this parent clock upon success -- there is no
- * way to return an error, so if we encounter an error, just WARN()
- * and pretend that we know that we're doing.
- */
-u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       u32 r, found = 0;
-       struct clk *parent;
-       const char *clk_name;
-       int ret = 0, f = 0;
-
-       parent = __clk_get_parent(hw->clk);
-       clk_name = __clk_get_name(hw->clk);
-
-       /* XXX should be able to return an error */
-       WARN((!clk->clksel || !clk->clksel_mask),
-            "clock: %s: attempt to call on a non-clksel clock", clk_name);
-
-       r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask;
-       r >>= __ffs(clk->clksel_mask);
-
-       for (clks = clk->clksel; clks->parent && !found; clks++) {
-               for (clkr = clks->rates; clkr->div && !found; clkr++) {
-                       if (!(clkr->flags & cpu_mask))
-                               continue;
-
-                       if (clkr->val == r) {
-                               found = 1;
-                               ret = f;
-                       }
-               }
-               f++;
-       }
-
-       /* This indicates a data error */
-       WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
-            clk_name, r);
-
-       return ret;
-}
-
-
-/**
- * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
- * @clk: struct clk *
- *
- * This function is intended to be called only by the clock framework.
- * Each clksel clock should have its struct clk .recalc field set to this
- * function.  Returns the clock's current rate, based on its parent's rate
- * and its current divisor setting in the hardware.
- */
-unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
-{
-       unsigned long rate;
-       u32 div = 0;
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-
-       if (!parent_rate)
-               return 0;
-
-       div = _read_divisor(clk);
-       if (!div)
-               rate = parent_rate;
-       else
-               rate = parent_rate / div;
-
-       pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
-                __clk_get_name(hw->clk), rate, div);
-
-       return rate;
-}
-
-/**
- * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
- * @clk: OMAP struct clk to use
- * @target_rate: desired clock rate
- *
- * This function is intended to be called only by the clock framework.
- * Finds best target rate based on the source clock and possible dividers.
- * rates. The divider array must be sorted with smallest divider first.
- *
- * Returns the rounded clock rate or returns 0xffffffff on error.
- */
-long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                       unsigned long *parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 new_div;
-
-       return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
-}
-
-/**
- * omap2_clksel_set_rate() - program clock rate in hardware
- * @clk: struct clk * to program rate
- * @rate: target rate to program
- *
- * This function is intended to be called only by the clock framework.
- * Program @clk's rate to @rate in the hardware.  The clock can be
- * either enabled or disabled when this happens, although if the clock
- * is enabled, some downstream devices may glitch or behave
- * unpredictably when the clock rate is changed - this depends on the
- * hardware. This function does not currently check the usecount of
- * the clock, so if multiple drivers are using the clock, and the rate
- * is changed, they will all be affected without any notification.
- * Returns -EINVAL upon error, or 0 upon success.
- */
-int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 field_val, validrate, new_div = 0;
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return -EINVAL;
-
-       validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
-       if (validrate != rate)
-               return -EINVAL;
-
-       field_val = _divisor_to_clksel(clk, new_div);
-       if (field_val == ~0)
-               return -EINVAL;
-
-       _write_clksel_reg(clk, field_val);
-
-       pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
-                __clk_get_rate(hw->clk));
-
-       return 0;
-}
-
-/*
- * Clksel parent setting function - not passed in struct clk function
- * pointer - instead, the OMAP clock code currently assumes that any
- * parent-setting clock is a clksel clock, and calls
- * omap2_clksel_set_parent() by default
- */
-
-/**
- * omap2_clksel_set_parent() - change a clock's parent clock
- * @clk: struct clk * of the child clock
- * @new_parent: struct clk * of the new parent clock
- *
- * This function is intended to be called only by the clock framework.
- * Change the parent clock of clock @clk to @new_parent.  This is
- * intended to be used while @clk is disabled.  This function does not
- * currently check the usecount of the clock, so if multiple drivers
- * are using the clock, and the parent is changed, they will all be
- * affected without any notification.  Returns -EINVAL upon error, or
- * 0 upon success.
- */
-int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return -EINVAL;
-
-       _write_clksel_reg(clk, field_val);
-       return 0;
-}
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
deleted file mode 100644 (file)
index 55eb579..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * OMAP2/3 interface clock control
- *
- * Copyright (C) 2011 Nokia Corporation
- * Paul Walmsley
- *
- * 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-
-#include "clock.h"
-
-/* Register offsets */
-#define CM_AUTOIDLE                    0x30
-#define CM_ICLKEN                      0x10
-
-/* Private functions */
-
-/* XXX */
-void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
-{
-       u32 v;
-       void __iomem *r;
-
-       r = (__force void __iomem *)
-               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
-
-       v = omap2_clk_readl(clk, r);
-       v |= (1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, r);
-}
-
-/* XXX */
-void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
-{
-       u32 v;
-       void __iomem *r;
-
-       r = (__force void __iomem *)
-               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
-
-       v = omap2_clk_readl(clk, r);
-       v &= ~(1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, r);
-}
-
-/* Public data */
-
-const struct clk_hw_omap_ops clkhwops_iclk = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-};
-
-const struct clk_hw_omap_ops clkhwops_iclk_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap2_clk_dflt_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-
-
index a699d716930746d4f37bd603be865b248d5986bc..acb60ed172730a12b06f36a02c3175d848d7369c 100644 (file)
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
-#include <linux/regmap.h>
 #include <linux/of_address.h>
-#include <linux/bootmem.h>
 #include <asm/cpu.h>
 
 #include <trace/events/power.h>
 #include "cm-regbits-34xx.h"
 #include "common.h"
 
-/*
- * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
- * for a module to indicate that it is no longer in idle
- */
-#define MAX_MODULE_ENABLE_WAIT         100000
-
 u16 cpu_mask;
 
-/*
- * Clock features setup. Used instead of CPU type checks.
- */
-struct ti_clk_features ti_clk_features;
-
 /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
 #define OMAP3430_DPLL_FINT_BAND1_MIN   750000
 #define OMAP3430_DPLL_FINT_BAND1_MAX   2100000
@@ -66,119 +54,24 @@ struct ti_clk_features ti_clk_features;
 #define OMAP3PLUS_DPLL_FINT_MIN                32000
 #define OMAP3PLUS_DPLL_FINT_MAX                52000000
 
-/*
- * clkdm_control: if true, then when a clock is enabled in the
- * hardware, its clockdomain will first be enabled; and when a clock
- * is disabled in the hardware, its clockdomain will be disabled
- * afterwards.
- */
-static bool clkdm_control = true;
-
-static LIST_HEAD(clk_hw_omap_clocks);
-
-struct clk_iomap {
-       struct regmap *regmap;
-       void __iomem *mem;
-};
-
-static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
-
-static void clk_memmap_writel(u32 val, void __iomem *reg)
-{
-       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-       struct clk_iomap *io = clk_memmaps[r->index];
-
-       if (io->regmap)
-               regmap_write(io->regmap, r->offset, val);
-       else
-               writel_relaxed(val, io->mem + r->offset);
-}
-
-static u32 clk_memmap_readl(void __iomem *reg)
-{
-       u32 val;
-       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-       struct clk_iomap *io = clk_memmaps[r->index];
-
-       if (io->regmap)
-               regmap_read(io->regmap, r->offset, &val);
-       else
-               val = readl_relaxed(io->mem + r->offset);
-
-       return val;
-}
-
-void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
-{
-       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
-               writel_relaxed(val, reg);
-       else
-               clk_memmap_writel(val, reg);
-}
-
-u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
-{
-       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
-               return readl_relaxed(reg);
-       else
-               return clk_memmap_readl(reg);
-}
-
 static struct ti_clk_ll_ops omap_clk_ll_ops = {
-       .clk_readl = clk_memmap_readl,
-       .clk_writel = clk_memmap_writel,
+       .clkdm_clk_enable = clkdm_clk_enable,
+       .clkdm_clk_disable = clkdm_clk_disable,
+       .cm_wait_module_ready = omap_cm_wait_module_ready,
+       .cm_split_idlest_reg = cm_split_idlest_reg,
 };
 
 /**
- * omap2_clk_provider_init - initialize a clock provider
- * @match_table: DT device table to match for devices to init
- * @np: device node pointer for the this clock provider
- * @index: index for the clock provider
- + @syscon: syscon regmap pointer
- * @mem: iomem pointer for the clock provider memory area, only used if
- *      syscon is not provided
+ * omap2_clk_setup_ll_ops - setup clock driver low-level ops
  *
- * Initializes a clock provider module (CM/PRM etc.), registering
- * the memory mapping at specified index and initializing the
- * low level driver infrastructure. Returns 0 in success.
+ * Sets up clock driver low-level platform ops. These are needed
+ * for register accesses and various other misc platform operations.
+ * Returns 0 on success, -EBUSY if low level ops have been registered
+ * already.
  */
-int __init omap2_clk_provider_init(struct device_node *np, int index,
-                                  struct regmap *syscon, void __iomem *mem)
+int __init omap2_clk_setup_ll_ops(void)
 {
-       struct clk_iomap *io;
-
-       ti_clk_ll_ops = &omap_clk_ll_ops;
-
-       io = kzalloc(sizeof(*io), GFP_KERNEL);
-
-       io->regmap = syscon;
-       io->mem = mem;
-
-       clk_memmaps[index] = io;
-
-       ti_dt_clk_init_provider(np, index);
-
-       return 0;
-}
-
-/**
- * omap2_clk_legacy_provider_init - initialize a legacy clock provider
- * @index: index for the clock provider
- * @mem: iomem pointer for the clock provider memory area
- *
- * Initializes a legacy clock provider memory mapping.
- */
-void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
-{
-       struct clk_iomap *io;
-
-       ti_clk_ll_ops = &omap_clk_ll_ops;
-
-       io = memblock_virt_alloc(sizeof(*io), 0);
-
-       io->mem = mem;
-
-       clk_memmaps[index] = io;
+       return ti_clk_setup_ll_ops(&omap_clk_ll_ops);
 }
 
 /*
@@ -187,77 +80,6 @@ void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
 
 /* Private functions */
 
-
-/**
- * _wait_idlest_generic - wait for a module to leave the idle state
- * @clk: module clock to wait for (needed for register offsets)
- * @reg: virtual address of module IDLEST register
- * @mask: value to mask against to determine if the module is active
- * @idlest: idle state indicator (0 or 1) for the clock
- * @name: name of the clock (for printk)
- *
- * Wait for a module to leave idle, where its idle-status register is
- * not inside the CM module.  Returns 1 if the module left idle
- * promptly, or 0 if the module did not leave idle before the timeout
- * elapsed.  XXX Deprecated - should be moved into drivers for the
- * individual IP block that the IDLEST register exists in.
- */
-static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
-                               u32 mask, u8 idlest, const char *name)
-{
-       int i = 0, ena = 0;
-
-       ena = (idlest) ? 0 : mask;
-
-       omap_test_timeout(((omap2_clk_readl(clk, reg) & mask) == ena),
-                         MAX_MODULE_ENABLE_WAIT, i);
-
-       if (i < MAX_MODULE_ENABLE_WAIT)
-               pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
-                        name, i);
-       else
-               pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
-                      name, MAX_MODULE_ENABLE_WAIT);
-
-       return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
-};
-
-/**
- * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
- * @clk: struct clk * belonging to the module
- *
- * If the necessary clocks for the OMAP hardware IP block that
- * corresponds to clock @clk are enabled, then wait for the module to
- * indicate readiness (i.e., to leave IDLE).  This code does not
- * belong in the clock code and will be moved in the medium term to
- * module-dependent code.  No return value.
- */
-static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
-{
-       void __iomem *companion_reg, *idlest_reg;
-       u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
-       s16 prcm_mod;
-       int r;
-
-       /* Not all modules have multiple clocks that their IDLEST depends on */
-       if (clk->ops->find_companion) {
-               clk->ops->find_companion(clk, &companion_reg, &other_bit);
-               if (!(omap2_clk_readl(clk, companion_reg) & (1 << other_bit)))
-                       return;
-       }
-
-       clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
-       r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
-       if (r) {
-               /* IDLEST register not in the CM module */
-               _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
-                                    idlest_val, __clk_get_name(clk->hw.clk));
-       } else {
-               omap_cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
-                                         idlest_bit);
-       };
-}
-
 /* Public functions */
 
 /**
@@ -290,279 +112,6 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
        }
 }
 
-/**
- * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
- *
- * Prevent the OMAP clock code from calling into the clockdomain code
- * when a hardware clock in that clockdomain is enabled or disabled.
- * Intended to be called at init time from omap*_clk_init().  No
- * return value.
- */
-void __init omap2_clk_disable_clkdm_control(void)
-{
-       clkdm_control = false;
-}
-
-/**
- * omap2_clk_dflt_find_companion - find companion clock to @clk
- * @clk: struct clk * to find the companion clock of
- * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
- * @other_bit: u8 ** to return the companion clock bit shift in
- *
- * Note: We don't need special code here for INVERT_ENABLE for the
- * time being since INVERT_ENABLE only applies to clocks enabled by
- * CM_CLKEN_PLL
- *
- * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
- * just a matter of XORing the bits.
- *
- * Some clocks don't have companion clocks.  For example, modules with
- * only an interface clock (such as MAILBOXES) don't have a companion
- * clock.  Right now, this code relies on the hardware exporting a bit
- * in the correct companion register that indicates that the
- * nonexistent 'companion clock' is active.  Future patches will
- * associate this type of code with per-module data structures to
- * avoid this issue, and remove the casts.  No return value.
- */
-void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
-                       void __iomem **other_reg, u8 *other_bit)
-{
-       u32 r;
-
-       /*
-        * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
-        * it's just a matter of XORing the bits.
-        */
-       r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
-
-       *other_reg = (__force void __iomem *)r;
-       *other_bit = clk->enable_bit;
-}
-
-/**
- * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
- * @clk: struct clk * to find IDLEST info for
- * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
- * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
- * @idlest_val: u8 * to return the idle status indicator
- *
- * Return the CM_IDLEST register address and bit shift corresponding
- * to the module that "owns" this clock.  This default code assumes
- * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
- * the IDLEST register address ID corresponds to the CM_*CLKEN
- * register address ID (e.g., that CM_FCLKEN2 corresponds to
- * CM_IDLEST2).  This is not true for all modules.  No return value.
- */
-void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
-               void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = clk->enable_bit;
-
-       /*
-        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
-        * 34xx reverses this, just to keep us on our toes
-        * AM35xx uses both, depending on the module.
-        */
-       *idlest_val = ti_clk_features.cm_idlest_val;
-}
-
-/**
- * omap2_dflt_clk_enable - enable a clock in the hardware
- * @hw: struct clk_hw * of the clock to enable
- *
- * Enable the clock @hw in the hardware.  We first call into the OMAP
- * clockdomain code to "enable" the corresponding clockdomain if this
- * is the first enabled user of the clockdomain.  Then program the
- * hardware to enable the clock.  Then wait for the IP block that uses
- * this clock to leave idle (if applicable).  Returns the error value
- * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
- * if @hw has a null clock enable_reg, or zero upon success.
- */
-int omap2_dflt_clk_enable(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-       u32 v;
-       int ret = 0;
-
-       clk = to_clk_hw_omap(hw);
-
-       if (clkdm_control && clk->clkdm) {
-               ret = clkdm_clk_enable(clk->clkdm, hw->clk);
-               if (ret) {
-                       WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
-                            __func__, __clk_get_name(hw->clk),
-                            clk->clkdm->name, ret);
-                       return ret;
-               }
-       }
-
-       if (unlikely(clk->enable_reg == NULL)) {
-               pr_err("%s: %s missing enable_reg\n", __func__,
-                      __clk_get_name(hw->clk));
-               ret = -EINVAL;
-               goto err;
-       }
-
-       /* FIXME should not have INVERT_ENABLE bit here */
-       v = omap2_clk_readl(clk, clk->enable_reg);
-       if (clk->flags & INVERT_ENABLE)
-               v &= ~(1 << clk->enable_bit);
-       else
-               v |= (1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, clk->enable_reg);
-       v = omap2_clk_readl(clk, clk->enable_reg); /* OCP barrier */
-
-       if (clk->ops && clk->ops->find_idlest)
-               _omap2_module_wait_ready(clk);
-
-       return 0;
-
-err:
-       if (clkdm_control && clk->clkdm)
-               clkdm_clk_disable(clk->clkdm, hw->clk);
-       return ret;
-}
-
-/**
- * omap2_dflt_clk_disable - disable a clock in the hardware
- * @hw: struct clk_hw * of the clock to disable
- *
- * Disable the clock @hw in the hardware, and call into the OMAP
- * clockdomain code to "disable" the corresponding clockdomain if all
- * clocks/hwmods in that clockdomain are now disabled.  No return
- * value.
- */
-void omap2_dflt_clk_disable(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-       u32 v;
-
-       clk = to_clk_hw_omap(hw);
-       if (!clk->enable_reg) {
-               /*
-                * 'independent' here refers to a clock which is not
-                * controlled by its parent.
-                */
-               pr_err("%s: independent clock %s has no enable_reg\n",
-                      __func__, __clk_get_name(hw->clk));
-               return;
-       }
-
-       v = omap2_clk_readl(clk, clk->enable_reg);
-       if (clk->flags & INVERT_ENABLE)
-               v |= (1 << clk->enable_bit);
-       else
-               v &= ~(1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, clk->enable_reg);
-       /* No OCP barrier needed here since it is a disable operation */
-
-       if (clkdm_control && clk->clkdm)
-               clkdm_clk_disable(clk->clkdm, hw->clk);
-}
-
-/**
- * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
- * @hw: struct clk_hw * of the clock being enabled
- *
- * Increment the usecount of the clockdomain of the clock pointed to
- * by @hw; if the usecount is 1, the clockdomain will be "enabled."
- * Only needed for clocks that don't use omap2_dflt_clk_enable() as
- * their enable function pointer.  Passes along the return value of
- * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
- * clockdomain, or 0 if clock framework-based clockdomain control is
- * not implemented.
- */
-int omap2_clkops_enable_clkdm(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-       int ret = 0;
-
-       clk = to_clk_hw_omap(hw);
-
-       if (unlikely(!clk->clkdm)) {
-               pr_err("%s: %s: no clkdm set ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-               return -EINVAL;
-       }
-
-       if (unlikely(clk->enable_reg))
-               pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-
-       if (!clkdm_control) {
-               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
-                      __func__, __clk_get_name(hw->clk));
-               return 0;
-       }
-
-       ret = clkdm_clk_enable(clk->clkdm, hw->clk);
-       WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
-            __func__, __clk_get_name(hw->clk), clk->clkdm->name, ret);
-
-       return ret;
-}
-
-/**
- * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
- * @hw: struct clk_hw * of the clock being disabled
- *
- * Decrement the usecount of the clockdomain of the clock pointed to
- * by @hw; if the usecount is 0, the clockdomain will be "disabled."
- * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
- * disable function pointer.  No return value.
- */
-void omap2_clkops_disable_clkdm(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-
-       clk = to_clk_hw_omap(hw);
-
-       if (unlikely(!clk->clkdm)) {
-               pr_err("%s: %s: no clkdm set ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-               return;
-       }
-
-       if (unlikely(clk->enable_reg))
-               pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-
-       if (!clkdm_control) {
-               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
-                      __func__, __clk_get_name(hw->clk));
-               return;
-       }
-
-       clkdm_clk_disable(clk->clkdm, hw->clk);
-}
-
-/**
- * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
- * @hw: struct clk_hw * to check
- *
- * Return 1 if the clock represented by @hw is enabled in the
- * hardware, or 0 otherwise.  Intended for use in the struct
- * clk_ops.is_enabled function pointer.
- */
-int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 v;
-
-       v = omap2_clk_readl(clk, clk->enable_reg);
-
-       if (clk->flags & INVERT_ENABLE)
-               v ^= BIT(clk->enable_bit);
-
-       v &= BIT(clk->enable_bit);
-
-       return v ? 1 : 0;
-}
-
 static int __initdata mpurate;
 
 /*
@@ -583,178 +132,6 @@ static int __init omap_clk_setup(char *str)
 }
 __setup("mpurate=", omap_clk_setup);
 
-/**
- * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
- * @clk: struct clk * to initialize
- *
- * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
- * temporarily for autoidle handling, until this support can be
- * integrated into the common clock framework code in some way.  No
- * return value.
- */
-void omap2_init_clk_hw_omap_clocks(struct clk *clk)
-{
-       struct clk_hw_omap *c;
-
-       if (__clk_get_flags(clk) & CLK_IS_BASIC)
-               return;
-
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       list_add(&c->node, &clk_hw_omap_clocks);
-}
-
-/**
- * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
- * support it
- *
- * Enable clock autoidle on all OMAP clocks that have allow_idle
- * function pointers associated with them.  This function is intended
- * to be temporary until support for this is added to the common clock
- * code.  Returns 0.
- */
-int omap2_clk_enable_autoidle_all(void)
-{
-       struct clk_hw_omap *c;
-
-       list_for_each_entry(c, &clk_hw_omap_clocks, node)
-               if (c->ops && c->ops->allow_idle)
-                       c->ops->allow_idle(c);
-
-       of_ti_clk_allow_autoidle_all();
-
-       return 0;
-}
-
-/**
- * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
- * support it
- *
- * Disable clock autoidle on all OMAP clocks that have allow_idle
- * function pointers associated with them.  This function is intended
- * to be temporary until support for this is added to the common clock
- * code.  Returns 0.
- */
-int omap2_clk_disable_autoidle_all(void)
-{
-       struct clk_hw_omap *c;
-
-       list_for_each_entry(c, &clk_hw_omap_clocks, node)
-               if (c->ops && c->ops->deny_idle)
-                       c->ops->deny_idle(c);
-
-       of_ti_clk_deny_autoidle_all();
-
-       return 0;
-}
-
-/**
- * omap2_clk_deny_idle - disable autoidle on an OMAP clock
- * @clk: struct clk * to disable autoidle for
- *
- * Disable autoidle on an OMAP clock.
- */
-int omap2_clk_deny_idle(struct clk *clk)
-{
-       struct clk_hw_omap *c;
-
-       if (__clk_get_flags(clk) & CLK_IS_BASIC)
-               return -EINVAL;
-
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       if (c->ops && c->ops->deny_idle)
-               c->ops->deny_idle(c);
-       return 0;
-}
-
-/**
- * omap2_clk_allow_idle - enable autoidle on an OMAP clock
- * @clk: struct clk * to enable autoidle for
- *
- * Enable autoidle on an OMAP clock.
- */
-int omap2_clk_allow_idle(struct clk *clk)
-{
-       struct clk_hw_omap *c;
-
-       if (__clk_get_flags(clk) & CLK_IS_BASIC)
-               return -EINVAL;
-
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       if (c->ops && c->ops->allow_idle)
-               c->ops->allow_idle(c);
-       return 0;
-}
-
-/**
- * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
- * @clk_names: ptr to an array of strings of clock names to enable
- * @num_clocks: number of clock names in @clk_names
- *
- * Prepare and enable a list of clocks, named by @clk_names.  No
- * return value. XXX Deprecated; only needed until these clocks are
- * properly claimed and enabled by the drivers or core code that uses
- * them.  XXX What code disables & calls clk_put on these clocks?
- */
-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
-{
-       struct clk *init_clk;
-       int i;
-
-       for (i = 0; i < num_clocks; i++) {
-               init_clk = clk_get(NULL, clk_names[i]);
-               if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
-                               clk_names[i]))
-                       continue;
-               clk_prepare_enable(init_clk);
-       }
-}
-
-const struct clk_hw_omap_ops clkhwops_wait = {
-       .find_idlest    = omap2_clk_dflt_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-/**
- * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
- * @mpurate_ck_name: clk name of the clock to change rate
- *
- * Change the ARM MPU clock rate to the rate specified on the command
- * line, if one was specified.  @mpurate_ck_name should be
- * "virt_prcm_set" on OMAP2xxx and "dpll1_ck" on OMAP34xx/OMAP36xx.
- * XXX Does not handle voltage scaling - on OMAP2xxx this is currently
- * handled by the virt_prcm_set clock, but this should be handled by
- * the OPP layer.  XXX This is intended to be handled by the OPP layer
- * code in the near future and should be removed from the clock code.
- * Returns -EINVAL if 'mpurate' is zero or if clk_set_rate() rejects
- * the rate, -ENOENT if the struct clk referred to by @mpurate_ck_name
- * cannot be found, or 0 upon success.
- */
-int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
-{
-       struct clk *mpurate_ck;
-       int r;
-
-       if (!mpurate)
-               return -EINVAL;
-
-       mpurate_ck = clk_get(NULL, mpurate_ck_name);
-       if (WARN(IS_ERR(mpurate_ck), "Failed to get %s.\n", mpurate_ck_name))
-               return -ENOENT;
-
-       r = clk_set_rate(mpurate_ck, mpurate);
-       if (r < 0) {
-               WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
-                    mpurate_ck_name, mpurate, r);
-               clk_put(mpurate_ck);
-               return -EINVAL;
-       }
-
-       calibrate_delay();
-       clk_put(mpurate_ck);
-
-       return 0;
-}
-
 /**
  * omap2_clk_print_new_rates - print summary of current clock tree rates
  * @hfclkin_ck_name: clk name for the off-chip HF oscillator
@@ -801,29 +178,30 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
  */
 void __init ti_clk_init_features(void)
 {
+       struct ti_clk_features features = { 0 };
        /* Fint setup for DPLLs */
        if (cpu_is_omap3430()) {
-               ti_clk_features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
-               ti_clk_features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
-               ti_clk_features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
-               ti_clk_features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
+               features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+               features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+               features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
+               features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
        } else {
-               ti_clk_features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
-               ti_clk_features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+               features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+               features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
        }
 
        /* Bypass value setup for DPLLs */
        if (cpu_is_omap24xx()) {
-               ti_clk_features.dpll_bypass_vals |=
+               features.dpll_bypass_vals |=
                        (1 << OMAP2XXX_EN_DPLL_LPBYPASS) |
                        (1 << OMAP2XXX_EN_DPLL_FRBYPASS);
        } else if (cpu_is_omap34xx()) {
-               ti_clk_features.dpll_bypass_vals |=
+               features.dpll_bypass_vals |=
                        (1 << OMAP3XXX_EN_DPLL_LPBYPASS) |
                        (1 << OMAP3XXX_EN_DPLL_FRBYPASS);
        } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() ||
                   soc_is_omap54xx() || soc_is_dra7xx()) {
-               ti_clk_features.dpll_bypass_vals |=
+               features.dpll_bypass_vals |=
                        (1 << OMAP4XXX_EN_DPLL_LPBYPASS) |
                        (1 << OMAP4XXX_EN_DPLL_FRBYPASS) |
                        (1 << OMAP4XXX_EN_DPLL_MNBYPASS);
@@ -831,7 +209,7 @@ void __init ti_clk_init_features(void)
 
        /* Jitter correction only available on OMAP343X */
        if (cpu_is_omap343x())
-               ti_clk_features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
+               features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
 
        /* Idlest value for interface clocks.
         * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
@@ -839,11 +217,13 @@ void __init ti_clk_init_features(void)
         * AM35xx uses both, depending on the module.
         */
        if (cpu_is_omap24xx())
-               ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
+               features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
        else if (cpu_is_omap34xx())
-               ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
+               features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
 
        /* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
        if (omap_rev() == OMAP3430_REV_ES1_0)
-               ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
+               features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
+
+       ti_clk_setup_features(&features);
 }
index 652ed0ab86ec022cffdb55271e3c1e9fb6a78e0c..67da640ba1c747a57bc5e3da47603c275ae068a2 100644 (file)
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
-struct omap_clk {
-       u16                             cpu;
-       struct clk_lookup               lk;
-};
-
-#define CLK(dev, con, ck)              \
-       {                               \
-               .lk = {                 \
-                       .dev_id = dev,  \
-                       .con_id = con,  \
-                       .clk = ck,      \
-               },                      \
-       }
-
-struct clockdomain;
-
-#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)     \
-       static struct clk_core _name##_core = {                 \
-               .name = #_name,                                 \
-               .hw = &_name##_hw.hw,                           \
-               .parent_names = _parent_array_name,             \
-               .num_parents = ARRAY_SIZE(_parent_array_name),  \
-               .ops = &_clkops_name,                           \
-       };                                                      \
-       static struct clk _name = {                             \
-               .core = &_name##_core,                          \
-       };
-
-#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name,     \
-                               _clkops_name, _flags)           \
-       static struct clk_core _name##_core = {                 \
-               .name = #_name,                                 \
-               .hw = &_name##_hw.hw,                           \
-               .parent_names = _parent_array_name,             \
-               .num_parents = ARRAY_SIZE(_parent_array_name),  \
-               .ops = &_clkops_name,                           \
-               .flags = _flags,                                \
-       };                                                      \
-       static struct clk _name = {                             \
-               .core = &_name##_core,                          \
-       };
-
-#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name)          \
-       static struct clk_hw_omap _name##_hw = {                \
-               .hw = {                                         \
-                       .clk = &_name,                          \
-               },                                              \
-               .clkdm_name = _clkdm_name,                      \
-       };
-
-#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel,       \
-                           _clksel_reg, _clksel_mask,          \
-                           _parent_names, _ops)                \
-       static struct clk _name;                                \
-       static struct clk_hw_omap _name##_hw = {                \
-               .hw = {                                         \
-                       .clk = &_name,                          \
-               },                                              \
-               .clksel         = _clksel,                      \
-               .clksel_reg     = _clksel_reg,                  \
-               .clksel_mask    = _clksel_mask,                 \
-               .clkdm_name     = _clkdm_name,                  \
-       };                                                      \
-       DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
-
-#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel,  \
-                                _clksel_reg, _clksel_mask,     \
-                                _enable_reg, _enable_bit,      \
-                                _hwops, _parent_names, _ops)   \
-       static struct clk _name;                                \
-       static struct clk_hw_omap _name##_hw = {                \
-               .hw = {                                         \
-                       .clk = &_name,                          \
-               },                                              \
-               .ops            = _hwops,                       \
-               .enable_reg     = _enable_reg,                  \
-               .enable_bit     = _enable_bit,                  \
-               .clksel         = _clksel,                      \
-               .clksel_reg     = _clksel_reg,                  \
-               .clksel_mask    = _clksel_mask,                 \
-               .clkdm_name     = _clkdm_name,                  \
-       };                                                      \
-       DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
-
 /* struct clksel_rate.flags possibilities */
 #define RATE_IN_242X           (1 << 0)
 #define RATE_IN_243X           (1 << 1)
@@ -127,38 +43,6 @@ struct clockdomain;
 /* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
 #define RATE_IN_3430ES2PLUS_36XX       (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
 
-
-/**
- * struct clksel_rate - register bitfield values corresponding to clk divisors
- * @val: register bitfield value (shifted to bit 0)
- * @div: clock divisor corresponding to @val
- * @flags: (see "struct clksel_rate.flags possibilities" above)
- *
- * @val should match the value of a read from struct clk.clksel_reg
- * AND'ed with struct clk.clksel_mask, shifted right to bit 0.
- *
- * @div is the divisor that should be applied to the parent clock's rate
- * to produce the current clock's rate.
- */
-struct clksel_rate {
-       u32                     val;
-       u8                      div;
-       u16                     flags;
-};
-
-/**
- * struct clksel - available parent clocks, and a pointer to their divisors
- * @parent: struct clk * to a possible parent clock
- * @rates: available divisors for this parent clock
- *
- * A struct clksel is always associated with one or more struct clks
- * and one or more struct clksel_rates.
- */
-struct clksel {
-       struct clk               *parent;
-       const struct clksel_rate *rates;
-};
-
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K               0x0
 #define CORE_CLK_SRC_DPLL              0x1
@@ -180,105 +64,18 @@ struct clksel {
 #define OMAP4XXX_EN_DPLL_FRBYPASS              0x6
 #define OMAP4XXX_EN_DPLL_LOCKED                        0x7
 
-u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
-void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
-void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
-void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
-void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
-
-void __init omap2_clk_disable_clkdm_control(void);
-
-/* clkt_clksel.c public functions */
-u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
-                               unsigned long target_rate,
-                               u32 *new_div);
-u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
-unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
-long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                               unsigned long *parent_rate);
-int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate);
-int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
-
-/* clkt_iclk.c public functions */
-extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
-extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
-
-unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
-
-void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
-                                  void __iomem **other_reg,
-                                  u8 *other_bit);
-void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
-                               void __iomem **idlest_reg,
-                               u8 *idlest_bit, u8 *idlest_val);
-int omap2_clk_enable_autoidle_all(void);
-int omap2_clk_allow_idle(struct clk *clk);
-int omap2_clk_deny_idle(struct clk *clk);
-int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
                               const char *core_ck_name,
                               const char *mpu_ck_name);
 
-u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg);
-void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
-
 extern u16 cpu_mask;
 
-/*
- * Clock features setup. Used instead of CPU type checks.
- */
-struct ti_clk_features {
-       u32 flags;
-       long fint_min;
-       long fint_max;
-       long fint_band1_max;
-       long fint_band2_min;
-       u8 dpll_bypass_vals;
-       u8 cm_idlest_val;
-};
-
-#define TI_CLK_DPLL_HAS_FREQSEL                (1 << 0)
-#define TI_CLK_DPLL4_DENY_REPROGRAM    (1 << 1)
-
-extern struct ti_clk_features ti_clk_features;
-
 extern const struct clkops clkops_omap2_dflt_wait;
 extern const struct clkops clkops_omap2_dflt;
 
 extern struct clk_functions omap2_clk_functions;
 
-extern const struct clksel_rate gpt_32k_rates[];
-extern const struct clksel_rate gpt_sys_rates[];
-extern const struct clksel_rate gfx_l3_rates[];
-extern const struct clksel_rate dsp_ick_rates[];
-
-extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
-extern const struct clk_hw_omap_ops clkhwops_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
-extern const struct clk_hw_omap_ops clkhwops_apll54;
-extern const struct clk_hw_omap_ops clkhwops_apll96;
-
-/* clksel_rate blocks shared between OMAP44xx and AM33xx */
-extern const struct clksel_rate div_1_0_rates[];
-extern const struct clksel_rate div3_1to4_rates[];
-extern const struct clksel_rate div_1_1_rates[];
-extern const struct clksel_rate div_1_2_rates[];
-extern const struct clksel_rate div_1_3_rates[];
-extern const struct clksel_rate div_1_4_rates[];
-extern const struct clksel_rate div31_1to31_rates[];
-
-extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
-extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
-
-struct regmap;
-
-int __init omap2_clk_provider_init(struct device_node *np, int index,
-                                  struct regmap *syscon, void __iomem *mem);
-void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem);
+int __init omap2_clk_setup_ll_ops(void);
 
 void __init ti_clk_init_features(void);
 #endif
diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
deleted file mode 100644 (file)
index cef0c8d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * clock2430.c - OMAP2430-specific clock integration code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "cm2xxx.h"
-#include "cm-regbits-24xx.h"
-
-/**
- * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
- * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
- * passes back the correct CM_IDLEST register address for I2CHS
- * modules.  No return value.
- */
-static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
-                                          void __iomem **idlest_reg,
-                                          u8 *idlest_bit,
-                                          u8 *idlest_val)
-{
-       *idlest_reg = OMAP2430_CM_REGADDR(CORE_MOD, CM_IDLEST);
-       *idlest_bit = clk->enable_bit;
-       *idlest_val = OMAP24XX_CM_IDLEST_VAL;
-}
-
-/* 2430 I2CHS has non-standard IDLEST register */
-const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
-       .find_idlest    = omap2430_clk_i2chs_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c
deleted file mode 100644 (file)
index b870f6a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * clock2xxx.c - OMAP2xxx-specific clock integration code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "cm.h"
-#include "cm-regbits-24xx.h"
-
-struct clk_hw *dclk_hw;
-/*
- * Omap24xx specific clock functions
- */
-
-/*
- * Switch the MPU rate if specified on cmdline.  We cannot do this
- * early until cmdline is parsed.  XXX This should be removed from the
- * clock code and handled by the OPP layer code in the near future.
- */
-static int __init omap2xxx_clk_arch_init(void)
-{
-       int ret;
-
-       if (!cpu_is_omap24xx())
-               return 0;
-
-       ret = omap2_clk_switch_mpurate_at_boot("virt_prcm_set");
-       if (!ret)
-               omap2_clk_print_new_rates("sys_ck", "dpll_ck", "mpu_ck");
-
-       return ret;
-}
-
-omap_arch_initcall(omap2xxx_clk_arch_init);
-
-
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
deleted file mode 100644 (file)
index 4596468..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * OMAP3-specific clock framework functions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- *
- * Paul Walmsley
- * Jouni Högander
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
- * Russell King
- *
- * 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock34xx.h"
-#include "cm3xxx.h"
-#include "cm-regbits-34xx.h"
-
-/**
- * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
- * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
- * @idlest_reg and @idlest_bit.  No return value.
- */
-static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
-                                           u8 *idlest_bit,
-                                           u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
-       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-/**
- * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
- * target IDLEST bits.  For our purposes, we are concerned with the
- * target IDLEST bits, which exist at a different bit position than
- * the *CLKEN bit position for these modules (DSS and USBHOST) (The
- * default find_idlest code assumes that they are at the same
- * position.)  No return value.
- */
-static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
-                                                   void __iomem **idlest_reg,
-                                                   u8 *idlest_bit,
-                                                   u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       /* USBHOST_IDLE has same shift */
-       *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
-       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-/**
- * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
- * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
- * @idlest_reg and @idlest_bit.  No return value.
- */
-static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
-                                                void __iomem **idlest_reg,
-                                                u8 *idlest_bit,
-                                                u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
-       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
deleted file mode 100644 (file)
index 084ba71..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * OMAP34xx clock function prototypes and macros
- *
- * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
-
-extern const struct clkops clkops_omap3430es2_ssi_wait;
-extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
-extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
-extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
-extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
-extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
-
-#endif
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
deleted file mode 100644 (file)
index 4d79ae2..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * OMAP3517/3505-specific clock framework functions
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2011 Nokia Corporation
- *
- * Ranjith Lohithakshan
- * Paul Walmsley
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
- * Russell King
- *
- * 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock3517.h"
-#include "cm3xxx.h"
-#include "cm-regbits-34xx.h"
-
-/*
- * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
- * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
- * at an offset of 4 from ICK enable bit.
- */
-#define AM35XX_IPSS_ICK_MASK                   0xF
-#define AM35XX_IPSS_ICK_EN_ACK_OFFSET          0x4
-#define AM35XX_IPSS_ICK_FCK_OFFSET             0x8
-#define AM35XX_IPSS_CLK_IDLEST_VAL             0
-
-/**
- * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The interface clocks on AM35xx IPSS reflects the clock idle status
- * in the enable register itsel at a bit offset of 4 from the enable
- * bit. A value of 1 indicates that clock is enabled.
- */
-static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
-                                           u8 *idlest_bit,
-                                           u8 *idlest_val)
-{
-       *idlest_reg = (__force void __iomem *)(clk->enable_reg);
-       *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
-       *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
-}
-
-/**
- * am35xx_clk_find_companion - find companion clock to @clk
- * @clk: struct clk * to find the companion clock of
- * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
- * @other_bit: u8 ** to return the companion clock bit shift in
- *
- * Some clocks don't have companion clocks.  For example, modules with
- * only an interface clock (such as HECC) don't have a companion
- * clock.  Right now, this code relies on the hardware exporting a bit
- * in the correct companion register that indicates that the
- * nonexistent 'companion clock' is active.  Future patches will
- * associate this type of code with per-module data structures to
- * avoid this issue, and remove the casts.  No return value.
- */
-static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
-                                     void __iomem **other_reg,
-                                     u8 *other_bit)
-{
-       *other_reg = (__force void __iomem *)(clk->enable_reg);
-       if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
-               *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
-       else
-               *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
-}
-const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
-       .find_idlest    = am35xx_clk_find_idlest,
-       .find_companion = am35xx_clk_find_companion,
-};
-
-/**
- * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The IPSS target CM_IDLEST bit is at a different shift from the
- * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
- * and @idlest_bit.  No return value.
- */
-static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
-                                           u8 *idlest_bit,
-                                           u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = AM35XX_ST_IPSS_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-
-const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = am35xx_clk_ipss_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
diff --git a/arch/arm/mach-omap2/clock3517.h b/arch/arm/mach-omap2/clock3517.h
deleted file mode 100644 (file)
index ca5e5a6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * OMAP3517/3505 clock function prototypes and macros
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
-
-extern const struct clkops clkops_am35xx_ipss_module_wait;
-extern const struct clkops clkops_am35xx_ipss_wait;
-
-#endif
diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c
deleted file mode 100644 (file)
index 91ccb96..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * OMAP36xx-specific clkops
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- *
- * Mike Turquette
- * Vijaykumar GN
- * Paul Walmsley
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
- * Russell King
- *
- * 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock36xx.h"
-#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
-
-/**
- * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering
- *         from HSDivider PWRDN problem Implements Errata ID: i556.
- * @clk: DPLL output struct clk
- *
- * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
- * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
- * valueafter their respective PWRDN bits are set.  Any dummy write
- * (Any other value different from the Read value) to the
- * corresponding CM_CLKSEL register will refresh the dividers.
- */
-int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
-{
-       struct clk_divider *parent;
-       struct clk_hw *parent_hw;
-       u32 dummy_v, orig_v;
-       struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
-       int ret;
-
-       /* Clear PWRDN bit of HSDIVIDER */
-       ret = omap2_dflt_clk_enable(clk);
-
-       parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
-       parent = to_clk_divider(parent_hw);
-
-       /* Restore the dividers */
-       if (!ret) {
-               orig_v = omap2_clk_readl(omap_clk, parent->reg);
-               dummy_v = orig_v;
-
-               /* Write any other value different from the Read value */
-               dummy_v ^= (1 << parent->shift);
-               omap2_clk_writel(dummy_v, omap_clk, parent->reg);
-
-               /* Write the original divider */
-               omap2_clk_writel(orig_v, omap_clk, parent->reg);
-       }
-
-       return ret;
-}
diff --git a/arch/arm/mach-omap2/clock36xx.h b/arch/arm/mach-omap2/clock36xx.h
deleted file mode 100644 (file)
index 945bb7f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * OMAP36xx clock function prototypes and macros
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
-
-extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
-
-#endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
deleted file mode 100644 (file)
index a9e86db..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * OMAP3-specific clock framework functions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
- *
- * Paul Walmsley
- * Jouni Högander
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
- *
- * 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "clock.h"
-#include "clock3xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-34xx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-34xx.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
-
-/* needed by omap3_core_dpll_m2_set_rate() */
-struct clk *sdrc_ick_p, *arm_fck_p;
-
-/**
- * omap3_dpll4_set_rate - set rate for omap3 per-dpll
- * @hw: clock to change
- * @rate: target rate for clock
- * @parent_rate: rate of the parent clock
- *
- * Check if the current SoC supports the per-dpll reprogram operation
- * or not, and then do the rate change if supported. Returns -EINVAL
- * if not supported, 0 for success, and potential error codes from the
- * clock rate change.
- */
-int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       /*
-        * According to the 12-5 CDP code from TI, "Limitation 2.5"
-        * on 3430ES1 prevents us from changing DPLL multipliers or dividers
-        * on DPLL4.
-        */
-       if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
-               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
-               return -EINVAL;
-       }
-
-       return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
-}
-
-/**
- * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
- * @hw: clock to change
- * @rate: target rate for clock
- * @parent_rate: rate of the parent clock
- * @index: parent index, 0 - reference clock, 1 - bypass clock
- *
- * Check if the current SoC support the per-dpll reprogram operation
- * or not, and then do the rate + parent change if supported. Returns
- * -EINVAL if not supported, 0 for success, and potential error codes
- * from the clock rate change.
- */
-int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
-                                   unsigned long parent_rate, u8 index)
-{
-       if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
-               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
-               return -EINVAL;
-       }
-
-       return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
-                                                     index);
-}
-
-void __init omap3_clk_lock_dpll5(void)
-{
-       struct clk *dpll5_clk;
-       struct clk *dpll5_m2_clk;
-
-       dpll5_clk = clk_get(NULL, "dpll5_ck");
-       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
-       clk_prepare_enable(dpll5_clk);
-
-       /* Program dpll5_m2_clk divider for no division */
-       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_disable_unprepare(dpll5_m2_clk);
-       clk_disable_unprepare(dpll5_clk);
-       return;
-}
-
-/* Common clock code */
-
-/*
- * Switch the MPU rate if specified on cmdline.  We cannot do this
- * early until cmdline is parsed.  XXX This should be removed from the
- * clock code and handled by the OPP layer code in the near future.
- */
-static int __init omap3xxx_clk_arch_init(void)
-{
-       int ret;
-
-       if (!cpu_is_omap34xx())
-               return 0;
-
-       ret = omap2_clk_switch_mpurate_at_boot("dpll1_ck");
-       if (!ret)
-               omap2_clk_print_new_rates("osc_sys_ck", "core_ck", "arm_fck");
-
-       return ret;
-}
-
-omap_arch_initcall(omap3xxx_clk_arch_init);
-
-
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
deleted file mode 100644 (file)
index 287a46f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * OMAP4 clock function prototypes and macros
- *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
-
-/*
- * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
- *    set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
- *    vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
- */
-#define OMAP4430_REGM4XEN_MULT 4
-
-int omap4xxx_clk_init(void);
-
-#endif
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
deleted file mode 100644 (file)
index 61b60df..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *  linux/arch/arm/mach-omap2/clock_common_data.c
- *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2009 Nokia Corporation
- *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
- *
- * 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 file contains clock data that is common to both the OMAP2xxx and
- * OMAP3xxx clock definition files.
- */
-
-#include "clock.h"
-
-/* clksel_rate data common to 24xx/343x */
-const struct clksel_rate gpt_32k_rates[] = {
-        { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-        { .div = 0 }
-};
-
-const struct clksel_rate gpt_sys_rates[] = {
-        { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-        { .div = 0 }
-};
-
-const struct clksel_rate gfx_l3_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-       { .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-       { .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_3XXX },
-       { .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_3XXX },
-       { .div = 0 }
-};
-
-const struct clksel_rate dsp_ick_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_24XX },
-       { .div = 2, .val = 2, .flags = RATE_IN_24XX },
-       { .div = 3, .val = 3, .flags = RATE_IN_243X },
-       { .div = 0 },
-};
-
-
-/* clksel_rate blocks shared between OMAP44xx and AM33xx */
-
-const struct clksel_rate div_1_0_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div3_1to4_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
-       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 4, .val = 2, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_1_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_2_rates[] = {
-       { .div = 1, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_3_rates[] = {
-       { .div = 1, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_4_rates[] = {
-       { .div = 1, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div31_1to31_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 2, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 3, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 4, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 5, .val = 5, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 6, .val = 6, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 7, .val = 7, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 8, .val = 8, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 9, .val = 9, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 10, .val = 10, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 11, .val = 11, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 12, .val = 12, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 13, .val = 13, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 14, .val = 14, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 15, .val = 15, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 16, .val = 16, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 17, .val = 17, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 18, .val = 18, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 19, .val = 19, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 20, .val = 20, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 21, .val = 21, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 22, .val = 22, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 23, .val = 23, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 24, .val = 24, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 25, .val = 25, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 26, .val = 26, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 27, .val = 27, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 28, .val = 28, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 29, .val = 29, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 30, .val = 30, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
index 820dde8b5b0453f96a6a3c53a4db8e4c3c9abca6..a253aafbb9a29fe3a7350ca959095e3e78b836d4 100644 (file)
@@ -37,7 +37,6 @@
 #include "clock.h"
 #include "clock2xxx.h"
 #include "clock3xxx.h"
-#include "clock44xx.h"
 #include "omap-pm.h"
 #include "sdrc.h"
 #include "control.h"
@@ -723,6 +722,8 @@ int __init omap_clk_init(void)
 
        ti_clk_init_features();
 
+       omap2_clk_setup_ll_ops();
+
        if (of_have_populated_dt()) {
                ret = omap_control_init();
                if (ret)
index 486cc4ded1906670c053f110bb09aeee34ea7fa3..6ef9e6341d96ba13e31c6a3cd0e1b3fc54cf1db9 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
index b1aad7e1426c62e9a394b72a09dfc48ab361f348..2a1a4180d5d0f5901e8fdbaab5d25339b581be01 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/sysfs.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/irq.h>
 #include <linux/time.h>
index 79f033b1ddff2f24c96327c5822a19951983855d..d0871786dd8ac7ebebc93a1b71a2410b4483d9a4 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/of_platform.h>
 #include <linux/cpu.h>
 #include <linux/mbus.h>
-#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <asm/system_misc.h>
 #include <asm/mach/arch.h>
index 16547f2641a32d343bb8ea44adfdf106ad781f49..25d6676f8d6e80d1e75cea63b662de8a7e8ef61c 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
index 5d1a318f1302c53b37b6fa896f24c03ac247404b..0fa4c5f8b1beb31abfa6f26745143a1693a8725c 100644 (file)
@@ -8,6 +8,7 @@ menuconfig ARCH_TEGRA
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
        select PINCTRL
+       select PM_OPP
        select ARCH_HAS_RESET_CONTROLLER
        select RESET_CONTROLLER
        select SOC_BUS
index e31d3d61c9988a645bf081f7462fffaee3db67dd..b316e18a76aa1d14ba5d7ce5bc7a77f9fc8bb930 100644 (file)
@@ -72,21 +72,12 @@ void __init ux500_init_irq(void)
         * Init clocks here so that they are available for system timer
         * initialization.
         */
-       if (cpu_is_u8500_family()) {
-               u8500_of_clk_init(U8500_CLKRST1_BASE,
-                                 U8500_CLKRST2_BASE,
-                                 U8500_CLKRST3_BASE,
-                                 U8500_CLKRST5_BASE,
-                                 U8500_CLKRST6_BASE);
-       } else if (cpu_is_u9540()) {
-               u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
-                              U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
-                              U8500_CLKRST6_BASE);
-       } else if (cpu_is_u8540()) {
-               u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
-                              U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
-                              U8500_CLKRST6_BASE);
-       }
+       if (cpu_is_u8500_family())
+               u8500_clk_init();
+       else if (cpu_is_u9540())
+               u9540_clk_init();
+       else if (cpu_is_u8540())
+               u8540_clk_init();
 }
 
 static const char * __init ux500_get_machine(void)
index f3067d4d4e35711680376372395667efdc45ad07..926ae8d9abc5f7ff66449d1eec168b8973da6118 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/kexec.h>
 #include <linux/crash_dump.h>
 #include <linux/root_dev.h>
-#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
index 6e46abe0dac6a9cb054bc690f8fee4c9fed60ed3..bd34f4093cd9f7d565be85dd3950849ebaa264a0 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/slab.h>
@@ -389,12 +390,11 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
        return div1;
 }
 
-static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk,
-                                       int scale, int maxdiv)
+static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req,
+                                int scale, int maxdiv)
 {
-       struct clk *pc, *bpc, *free;
+       struct clk_hw *pc, *bpc, *free;
        long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
        int j;
 
@@ -408,7 +408,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
         * the one that gets closest to but not over the requested rate.
         */
        for (j = 0; j < 7; j++) {
-               pc = clk_get_parent_by_index(hw->clk, j);
+               pc = clk_hw_get_parent_by_index(hw, j);
                if (!pc)
                        break;
 
@@ -416,20 +416,20 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
                 * XXX: we would actually want clk_has_active_children()
                 * but this is a good-enough approximation for now.
                 */
-               if (!__clk_is_prepared(pc)) {
+               if (!clk_hw_is_prepared(pc)) {
                        if (!free)
                                free = pc;
                }
 
-               pr = clk_get_rate(pc);
-               if (pr < rate)
+               pr = clk_hw_get_rate(pc);
+               if (pr < req->rate)
                        continue;
 
                /* what can hardware actually provide */
-               tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+               tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
                nr = pr / tdv;
-               diff = rate - nr;
-               if (nr > rate)
+               diff = req->rate - nr;
+               if (nr > req->rate)
                        continue;
 
                if (diff < lastdiff) {
@@ -448,15 +448,16 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
         */
        if (lastdiff && free) {
                for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
-                       tpr = rate * j;
+                       tpr = req->rate * j;
                        if (tpr < 0)
                                break;
-                       pr = clk_round_rate(free, tpr);
+                       pr = clk_hw_round_rate(free, tpr);
 
-                       tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+                       tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
+                                              NULL);
                        nr = pr / tdv;
-                       diff = rate - nr;
-                       if (nr > rate)
+                       diff = req->rate - nr;
+                       if (nr > req->rate)
                                continue;
                        if (diff < lastdiff) {
                                lastdiff = diff;
@@ -469,9 +470,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
                }
        }
 
-       *best_parent_rate = bpr;
-       *best_parent_clk = __clk_get_hw(bpc);
-       return br;
+       if (br < 0)
+               return br;
+
+       req->best_parent_rate = bpr;
+       req->best_parent_hw = bpc;
+       req->rate = br;
+
+       return 0;
 }
 
 static int alchemy_clk_fgv1_en(struct clk_hw *hw)
@@ -562,14 +568,10 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
        return parent_rate / v;
 }
 
-static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req)
 {
-       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
-                                    best_parent_clk, 2, 512);
+       return alchemy_clk_fgcs_detr(hw, req, 2, 512);
 }
 
 /* Au1000, Au1100, Au15x0, Au12x0 */
@@ -696,11 +698,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
        return t;
 }
 
-static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req)
 {
        struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
        int scale, maxdiv;
@@ -713,8 +712,7 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
                maxdiv = 512;
        }
 
-       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
-                                    best_parent_clk, scale, maxdiv);
+       return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
 }
 
 /* Au1300 larger input mux, no separate disable bit, flexible divider */
@@ -917,17 +915,13 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
-static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int alchemy_clk_csrc_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req)
 {
        struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
        int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
 
-       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
-                                    best_parent_clk, scale, 4);
+       return alchemy_clk_fgcs_detr(hw, req, scale, 4);
 }
 
 static struct clk_ops alchemy_clkops_csrc = {
index f691bcabd71013e23a09a07bfec61a592e1cd237..c50ea76ba66ceb95c99555f7391b75c0744a1b96 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/device.h>
index 3984ea96e5f762de82fe5e4fb140999d9b434f48..a450e7af877c337aec3aff21f0676299b3699f73 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/clkdev.h>
 #include <linux/acpi.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/pm.h>
 
 #include "internal.h"
index 46b58abb08c5e05efb9111f76e788a3601f6046c..502454c24e69708dbc6a3164142e2131b74008d6 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
index c4cf075a2320f7ae33327fd79e9d9525c15921c0..d08b3e5985bed4d2254c24aec6a9acb9645ff280 100644 (file)
@@ -9,7 +9,7 @@ obj-$(CONFIG_COMMON_CLK)        += clk-gate.o
 obj-$(CONFIG_COMMON_CLK)       += clk-mux.o
 obj-$(CONFIG_COMMON_CLK)       += clk-composite.o
 obj-$(CONFIG_COMMON_CLK)       += clk-fractional-divider.o
-obj-$(CONFIG_COMMON_CLK)       += clk-gpio-gate.o
+obj-$(CONFIG_COMMON_CLK)       += clk-gpio.o
 ifeq ($(CONFIG_OF), y)
 obj-$(CONFIG_COMMON_CLK)       += clk-conf.o
 endif
index 27dfa965cfedb020ebf66b635e0053ca58cefc1c..fd7247deabdc3de9cdf8ab0e4fb67d0c6775ef3e 100644 (file)
@@ -614,17 +614,12 @@ void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
        int num_parents;
        unsigned int irq;
        const char *name = np->name;
-       int i;
 
        num_parents = of_clk_get_parent_count(np);
        if (num_parents <= 0 || num_parents > 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index 5b3ded5205a29177dde69509bd72032f7fff61aa..620ea323356b62145c4f7ef7f1d19511c5832015 100644 (file)
@@ -222,7 +222,6 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
 {
        struct clk *clk;
        int num_parents;
-       int i;
        unsigned int irq;
        const char *parent_names[MASTER_SOURCE_MAX];
        const char *name = np->name;
@@ -232,11 +231,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
        if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index df2c1afa52b4acaa6204d5595a76c65f7dc0cb70..e4d7b574f1ea33a198a454e0223818c9e539ebb9 100644 (file)
@@ -134,7 +134,7 @@ at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name,
 
 static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
 {
-       struct clk *parent;
+       struct clk_hw *parent;
        unsigned long parent_rate;
        int shift = 0;
 
@@ -142,8 +142,8 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
                return;
 
        if (periph->range.max) {
-               parent = clk_get_parent_by_index(periph->hw.clk, 0);
-               parent_rate = __clk_get_rate(parent);
+               parent = clk_hw_get_parent_by_index(&periph->hw, 0);
+               parent_rate = clk_hw_get_rate(parent);
                if (!parent_rate)
                        return;
 
index 8c86c0f7847a55a0cdc257289c49c67777216d73..14b270b85fec277a6fdea1ad0df260eeee95f27b 100644 (file)
@@ -54,46 +54,47 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
        return parent_rate >> pres;
 }
 
-static long clk_programmable_determine_rate(struct clk_hw *hw,
-                                           unsigned long rate,
-                                           unsigned long min_rate,
-                                           unsigned long max_rate,
-                                           unsigned long *best_parent_rate,
-                                           struct clk_hw **best_parent_hw)
+static int clk_programmable_determine_rate(struct clk_hw *hw,
+                                          struct clk_rate_request *req)
 {
-       struct clk *parent = NULL;
+       struct clk_hw *parent;
        long best_rate = -EINVAL;
        unsigned long parent_rate;
        unsigned long tmp_rate;
        int shift;
        int i;
 
-       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
-               parent = clk_get_parent_by_index(hw->clk, i);
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
 
-               parent_rate = __clk_get_rate(parent);
+               parent_rate = clk_hw_get_rate(parent);
                for (shift = 0; shift < PROG_PRES_MASK; shift++) {
                        tmp_rate = parent_rate >> shift;
-                       if (tmp_rate <= rate)
+                       if (tmp_rate <= req->rate)
                                break;
                }
 
-               if (tmp_rate > rate)
+               if (tmp_rate > req->rate)
                        continue;
 
-               if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
+               if (best_rate < 0 ||
+                   (req->rate - tmp_rate) < (req->rate - best_rate)) {
                        best_rate = tmp_rate;
-                       *best_parent_rate = parent_rate;
-                       *best_parent_hw = __clk_get_hw(parent);
+                       req->best_parent_rate = parent_rate;
+                       req->best_parent_hw = parent;
                }
 
                if (!best_rate)
                        break;
        }
 
-       return best_rate;
+       if (best_rate < 0)
+               return best_rate;
+
+       req->rate = best_rate;
+       return 0;
 }
 
 static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
@@ -230,7 +231,6 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
 {
        int num;
        u32 id;
-       int i;
        struct clk *clk;
        int num_parents;
        const char *parent_names[PROG_SOURCE_MAX];
@@ -241,11 +241,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
        if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        num = of_get_child_count(np);
        if (!num || num > (PROG_ID_MAX + 1))
index 98a84a865fe1cf1b13a437741631b83804e32bf6..d0d5076a9b94b078f1d78a0c8c4d598c56e8c00a 100644 (file)
  *
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk/at91_pmc.h>
 #include <linux/delay.h>
 #include <linux/of.h>
@@ -371,17 +373,12 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
        const char *parent_names[2];
        int num_parents;
        const char *name = np->name;
-       int i;
 
        num_parents = of_clk_get_parent_count(np);
        if (num_parents <= 0 || num_parents > 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
@@ -449,17 +446,12 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
        const char *parent_names[2];
        int num_parents;
        const char *name = np->name;
-       int i;
 
        num_parents = of_clk_get_parent_count(np);
        if (num_parents != 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index 3817ea865ca258ecb8675f6e35c39be4f53fd424..a7f8501cfa056222a103c1e0f05a442521f68eae 100644 (file)
@@ -145,7 +145,6 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
                                        struct at91_pmc *pmc)
 {
        struct clk *clk;
-       int i;
        int num_parents;
        const char *parent_names[SMD_SOURCE_MAX];
        const char *name = np->name;
@@ -154,11 +153,7 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
        if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; i++) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index b0cbd2b1ff5957027a5643963d45038435e8b1ce..8ab8502778a282bac38b56ce9ecb7cd92c8962e2 100644 (file)
@@ -56,47 +56,43 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
        return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
 }
 
-static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
-                                             unsigned long rate,
-                                             unsigned long min_rate,
-                                             unsigned long max_rate,
-                                             unsigned long *best_parent_rate,
-                                             struct clk_hw **best_parent_hw)
+static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
+                                            struct clk_rate_request *req)
 {
-       struct clk *parent = NULL;
+       struct clk_hw *parent;
        long best_rate = -EINVAL;
        unsigned long tmp_rate;
        int best_diff = -1;
        int tmp_diff;
        int i;
 
-       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
                int div;
 
-               parent = clk_get_parent_by_index(hw->clk, i);
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
 
                for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
                        unsigned long tmp_parent_rate;
 
-                       tmp_parent_rate = rate * div;
-                       tmp_parent_rate = __clk_round_rate(parent,
+                       tmp_parent_rate = req->rate * div;
+                       tmp_parent_rate = clk_hw_round_rate(parent,
                                                           tmp_parent_rate);
                        tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
-                       if (tmp_rate < rate)
-                               tmp_diff = rate - tmp_rate;
+                       if (tmp_rate < req->rate)
+                               tmp_diff = req->rate - tmp_rate;
                        else
-                               tmp_diff = tmp_rate - rate;
+                               tmp_diff = tmp_rate - req->rate;
 
                        if (best_diff < 0 || best_diff > tmp_diff) {
                                best_rate = tmp_rate;
                                best_diff = tmp_diff;
-                               *best_parent_rate = tmp_parent_rate;
-                               *best_parent_hw = __clk_get_hw(parent);
+                               req->best_parent_rate = tmp_parent_rate;
+                               req->best_parent_hw = parent;
                        }
 
-                       if (!best_diff || tmp_rate < rate)
+                       if (!best_diff || tmp_rate < req->rate)
                                break;
                }
 
@@ -104,7 +100,11 @@ static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
                        break;
        }
 
-       return best_rate;
+       if (best_rate < 0)
+               return best_rate;
+
+       req->rate = best_rate;
+       return 0;
 }
 
 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
@@ -273,7 +273,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
                                          unsigned long *parent_rate)
 {
        struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
-       struct clk *parent = __clk_get_parent(hw->clk);
+       struct clk_hw *parent = clk_hw_get_parent(hw);
        unsigned long bestrate = 0;
        int bestdiff = -1;
        unsigned long tmprate;
@@ -287,7 +287,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
                        continue;
 
                tmp_parent_rate = rate * usb->divisors[i];
-               tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
+               tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
                tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
                if (tmprate < rate)
                        tmpdiff = rate - tmprate;
@@ -373,7 +373,6 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
                                        struct at91_pmc *pmc)
 {
        struct clk *clk;
-       int i;
        int num_parents;
        const char *parent_names[USB_SOURCE_MAX];
        const char *name = np->name;
@@ -382,11 +381,7 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
        if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; i++) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index 39be2be82b0a04b730258b4a7154aa5be103cc73..d1844f1f37292a79bac681d9037141586b4ba203 100644 (file)
@@ -125,7 +125,6 @@ static int pmc_irq_map(struct irq_domain *h, unsigned int virq,
 
        irq_set_chip_and_handler(virq, &pmc_irq,
                                 handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID);
        irq_set_chip_data(virq, pmc);
 
        return 0;
index eb8e5dc9076d46f07901a98db214fbeec0b0a3dc..8b87771c69b2c4211597c879e01c6256655c4bc0 100644 (file)
@@ -59,71 +59,63 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
 int of_at91_get_clk_range(struct device_node *np, const char *propname,
                          struct clk_range *range);
 
-extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
-                                                struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
-                                                   struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
-                                                      struct at91_pmc *pmc);
-extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np,
-                                                struct at91_pmc *pmc);
-extern void __init of_sama5d3_clk_pll_setup(struct device_node *np,
-                                           struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_master_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np,
-                                                struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-
-#if defined(CONFIG_HAVE_AT91_UTMI)
-extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-#endif
-
-#if defined(CONFIG_HAVE_AT91_USB_CLK)
-extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-#endif
-
-#if defined(CONFIG_HAVE_AT91_SMD)
-extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-#endif
-
-#if defined(CONFIG_HAVE_AT91_H32MX)
-extern void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
-                                             struct at91_pmc *pmc);
-#endif
+void of_at91sam9260_clk_slow_setup(struct device_node *np,
+                                  struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_main_osc_setup(struct device_node *np,
+                                     struct at91_pmc *pmc);
+void of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
+                                        struct at91_pmc *pmc);
+void of_at91rm9200_clk_main_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+void of_at91sam9x5_clk_main_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_pll_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+void of_at91sam9g45_clk_pll_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+void of_at91sam9g20_clk_pllb_setup(struct device_node *np,
+                                  struct at91_pmc *pmc);
+void of_sama5d3_clk_pll_setup(struct device_node *np,
+                             struct at91_pmc *pmc);
+void of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_master_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+void of_at91sam9x5_clk_master_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_sys_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_periph_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+void of_at91sam9x5_clk_periph_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_prog_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+void of_at91sam9g45_clk_prog_setup(struct device_node *np,
+                                  struct at91_pmc *pmc);
+void of_at91sam9x5_clk_prog_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91sam9x5_clk_utmi_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_usb_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+void of_at91sam9x5_clk_usb_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+void of_at91sam9n12_clk_usb_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91sam9x5_clk_smd_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+
+void of_sama5d4_clk_h32mx_setup(struct device_node *np,
+                               struct at91_pmc *pmc);
 
 #endif /* __PMC_H_ */
index 79a98506c433bbbbc12bd50d0f7cf82a029d3b8b..3a15347b423348b83a70613ad5e6b880d05f8875 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/clk.h>
 
 /*
  * "Policies" affect the frequencies of bus clocks provided by a
@@ -1010,25 +1011,23 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
        struct bcm_clk_div *div = &bcm_clk->u.peri->div;
 
        if (!divider_exists(div))
-               return __clk_get_rate(hw->clk);
+               return clk_hw_get_rate(hw);
 
        /* Quietly avoid a zero rate */
        return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
                                rate ? rate : 1, *parent_rate, NULL);
 }
 
-static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate,
-               unsigned long max_rate,
-               unsigned long *best_parent_rate, struct clk_hw **best_parent)
+static int kona_peri_clk_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct clk *clk = hw->clk;
-       struct clk *current_parent;
+       struct clk_hw *current_parent;
        unsigned long parent_rate;
        unsigned long best_delta;
        unsigned long best_rate;
        u32 parent_count;
+       long rate;
        u32 which;
 
        /*
@@ -1037,18 +1036,25 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
         */
        WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
        parent_count = (u32)bcm_clk->init_data.num_parents;
-       if (parent_count < 2)
-               return kona_peri_clk_round_rate(hw, rate, best_parent_rate);
+       if (parent_count < 2) {
+               rate = kona_peri_clk_round_rate(hw, req->rate,
+                                               &req->best_parent_rate);
+               if (rate < 0)
+                       return rate;
+
+               req->rate = rate;
+               return 0;
+       }
 
        /* Unless we can do better, stick with current parent */
-       current_parent = clk_get_parent(clk);
-       parent_rate = __clk_get_rate(current_parent);
-       best_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
-       best_delta = abs(best_rate - rate);
+       current_parent = clk_hw_get_parent(hw);
+       parent_rate = clk_hw_get_rate(current_parent);
+       best_rate = kona_peri_clk_round_rate(hw, req->rate, &parent_rate);
+       best_delta = abs(best_rate - req->rate);
 
        /* Check whether any other parent clock can produce a better result */
        for (which = 0; which < parent_count; which++) {
-               struct clk *parent = clk_get_parent_by_index(clk, which);
+               struct clk_hw *parent = clk_hw_get_parent_by_index(hw, which);
                unsigned long delta;
                unsigned long other_rate;
 
@@ -1057,18 +1063,20 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
                        continue;
 
                /* We don't support CLK_SET_RATE_PARENT */
-               parent_rate = __clk_get_rate(parent);
-               other_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
-               delta = abs(other_rate - rate);
+               parent_rate = clk_hw_get_rate(parent);
+               other_rate = kona_peri_clk_round_rate(hw, req->rate,
+                                                     &parent_rate);
+               delta = abs(other_rate - req->rate);
                if (delta < best_delta) {
                        best_delta = delta;
                        best_rate = other_rate;
-                       *best_parent = __clk_get_hw(parent);
-                       *best_parent_rate = parent_rate;
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = parent_rate;
                }
        }
 
-       return best_rate;
+       req->rate = best_rate;
+       return 0;
 }
 
 static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
@@ -1130,7 +1138,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        if (parent_rate > (unsigned long)LONG_MAX)
                return -EINVAL;
 
-       if (rate == __clk_get_rate(hw->clk))
+       if (rate == clk_hw_get_rate(hw))
                return 0;
 
        if (!divider_exists(div))
@@ -1249,6 +1257,7 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
        unsigned long flags;
        unsigned int which;
        struct clk **clks = ccu->clk_data.clks;
+       struct kona_clk *kona_clks = ccu->kona_clks;
        bool success = true;
 
        flags = ccu_lock(ccu);
@@ -1259,7 +1268,7 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
 
                if (!clks[which])
                        continue;
-               bcm_clk = to_kona_clk(__clk_get_hw(clks[which]));
+               bcm_clk = &kona_clks[which];
                success &= __kona_clk_init(bcm_clk);
        }
 
index f4b8d324b083dfda89d3766cc6958b533b7802d4..1c2294d3ba85a449a7415c034a287045d703dc83 100644 (file)
@@ -61,7 +61,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        fbdiv = (val >> map->fbdiv_shift) & FBDIV_MASK;
        rfdiv = (val >> map->rfdiv_shift) & RFDIV_MASK;
        if (rfdiv == 0) {
-               pr_warn("%s has zero rfdiv\n", __clk_get_name(hw->clk));
+               pr_warn("%s has zero rfdiv\n", clk_hw_get_name(hw));
                rfdiv = 1;
        }
 
@@ -70,7 +70,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        vcodiv = map->vcodiv[vcodivsel];
        if (vcodiv == 0) {
                pr_warn("%s has zero vcodiv (index %d)\n",
-                       __clk_get_name(hw->clk), vcodivsel);
+                       clk_hw_get_name(hw), vcodivsel);
                vcodiv = 1;
        }
 
index e619285c6defddc731ce4eac34c3b5527bf5e47b..3bcd42fbb55e3fbbcdb401f707aef3879fe5d001 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 6b950ca8b71108fdf3f32dd5ea6503eb1e5dc7ed..dd295e498309b9e60f2903910a67563626a883f7 100644 (file)
@@ -32,11 +32,6 @@ void __init bcm2835_init_clocks(void)
        struct clk *clk;
        int ret;
 
-       clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
-                                       250000000);
-       if (IS_ERR(clk))
-               pr_err("sys_pclk not registered\n");
-
        clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
                                        126000000);
        if (IS_ERR(clk))
index f01164fada5dafd4e80d0eac8f5f0242847399dd..01877f64eff6a764ec2fcc2e5e3ff1f88d8f3514 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -309,7 +310,7 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
        if (!mul)
                div = CDCE706_DIVIDER_DIVIDER_MAX;
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                unsigned long best_diff = rate;
                unsigned long best_div = 0;
                struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
index 85fafb41e6ca3a8edbab5f1a1d8adc88c4ec7f4d..089bf88ffa8d677547b1a6f18c6ace50322793c6 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright (C) 2014, Topic Embedded Products
  * Licenced under GPL
  */
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index 715eec1a99022cc0461fa6a26f81e53c0a8dd33f..ff4ef4f1df622a5529402acf3127ada88941491c 100644 (file)
@@ -9,7 +9,6 @@
  * (at your option) any later version.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/io.h>
index 616f5aef3c26c7ad24334b1291d7d8178ef76ede..4735de0660cc912f1bafea1e31388bcf9843543d 100644 (file)
@@ -55,78 +55,77 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
        return rate_ops->recalc_rate(rate_hw, parent_rate);
 }
 
-static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_p)
+static int clk_composite_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req)
 {
        struct clk_composite *composite = to_clk_composite(hw);
        const struct clk_ops *rate_ops = composite->rate_ops;
        const struct clk_ops *mux_ops = composite->mux_ops;
        struct clk_hw *rate_hw = composite->rate_hw;
        struct clk_hw *mux_hw = composite->mux_hw;
-       struct clk *parent;
+       struct clk_hw *parent;
        unsigned long parent_rate;
        long tmp_rate, best_rate = 0;
        unsigned long rate_diff;
        unsigned long best_rate_diff = ULONG_MAX;
+       long rate;
        int i;
 
        if (rate_hw && rate_ops && rate_ops->determine_rate) {
                __clk_hw_set_clk(rate_hw, hw);
-               return rate_ops->determine_rate(rate_hw, rate, min_rate,
-                                               max_rate,
-                                               best_parent_rate,
-                                               best_parent_p);
+               return rate_ops->determine_rate(rate_hw, req);
        } else if (rate_hw && rate_ops && rate_ops->round_rate &&
                   mux_hw && mux_ops && mux_ops->set_parent) {
-               *best_parent_p = NULL;
+               req->best_parent_hw = NULL;
 
-               if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
-                       parent = clk_get_parent(mux_hw->clk);
-                       *best_parent_p = __clk_get_hw(parent);
-                       *best_parent_rate = __clk_get_rate(parent);
+               if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
+                       parent = clk_hw_get_parent(mux_hw);
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = clk_hw_get_rate(parent);
 
-                       return rate_ops->round_rate(rate_hw, rate,
-                                                   best_parent_rate);
+                       rate = rate_ops->round_rate(rate_hw, req->rate,
+                                                   &req->best_parent_rate);
+                       if (rate < 0)
+                               return rate;
+
+                       req->rate = rate;
+                       return 0;
                }
 
-               for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
-                       parent = clk_get_parent_by_index(mux_hw->clk, i);
+               for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) {
+                       parent = clk_hw_get_parent_by_index(mux_hw, i);
                        if (!parent)
                                continue;
 
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
 
-                       tmp_rate = rate_ops->round_rate(rate_hw, rate,
+                       tmp_rate = rate_ops->round_rate(rate_hw, req->rate,
                                                        &parent_rate);
                        if (tmp_rate < 0)
                                continue;
 
-                       rate_diff = abs(rate - tmp_rate);
+                       rate_diff = abs(req->rate - tmp_rate);
 
-                       if (!rate_diff || !*best_parent_p
+                       if (!rate_diff || !req->best_parent_hw
                                       || best_rate_diff > rate_diff) {
-                               *best_parent_p = __clk_get_hw(parent);
-                               *best_parent_rate = parent_rate;
+                               req->best_parent_hw = parent;
+                               req->best_parent_rate = parent_rate;
                                best_rate_diff = rate_diff;
                                best_rate = tmp_rate;
                        }
 
                        if (!rate_diff)
-                               return rate;
+                               return 0;
                }
 
-               return best_rate;
+               req->rate = best_rate;
+               return 0;
        } else if (mux_hw && mux_ops && mux_ops->determine_rate) {
                __clk_hw_set_clk(mux_hw, hw);
-               return mux_ops->determine_rate(mux_hw, rate, min_rate,
-                                              max_rate, best_parent_rate,
-                                              best_parent_p);
+               return mux_ops->determine_rate(mux_hw, req);
        } else {
                pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
-               return 0;
+               return -EINVAL;
        }
 }
 
index 706b5783c360dfc5ba60c6f7054374f5f06ff4f8..f24d0a19ae70aa8cc2a1210ab03da617d048aff0 100644 (file)
@@ -78,12 +78,14 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
 }
 
 static unsigned int _get_div(const struct clk_div_table *table,
-                            unsigned int val, unsigned long flags)
+                            unsigned int val, unsigned long flags, u8 width)
 {
        if (flags & CLK_DIVIDER_ONE_BASED)
                return val;
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
                return 1 << val;
+       if (flags & CLK_DIVIDER_MAX_AT_ZERO)
+               return val ? val : div_mask(width) + 1;
        if (table)
                return _get_table_div(table, val);
        return val + 1;
@@ -101,12 +103,14 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
 }
 
 static unsigned int _get_val(const struct clk_div_table *table,
-                            unsigned int div, unsigned long flags)
+                            unsigned int div, unsigned long flags, u8 width)
 {
        if (flags & CLK_DIVIDER_ONE_BASED)
                return div;
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
                return __ffs(div);
+       if (flags & CLK_DIVIDER_MAX_AT_ZERO)
+               return (div == div_mask(width) + 1) ? 0 : div;
        if (table)
                return  _get_table_val(table, div);
        return div - 1;
@@ -117,13 +121,14 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
                                  const struct clk_div_table *table,
                                  unsigned long flags)
 {
+       struct clk_divider *divider = to_clk_divider(hw);
        unsigned int div;
 
-       div = _get_div(table, val, flags);
+       div = _get_div(table, val, flags, divider->width);
        if (!div) {
                WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
                        "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return parent_rate;
        }
 
@@ -285,7 +290,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        maxdiv = _get_maxdiv(table, width, flags);
 
-       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
                parent_rate = *best_parent_rate;
                bestdiv = _div_round(table, parent_rate, rate, flags);
                bestdiv = bestdiv == 0 ? 1 : bestdiv;
@@ -311,7 +316,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
                        *best_parent_rate = parent_rate_saved;
                        return i;
                }
-               parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+               parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
                                               rate * i);
                now = DIV_ROUND_UP(parent_rate, i);
                if (_is_best_div(rate, now, best, flags)) {
@@ -323,7 +328,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        if (!bestdiv) {
                bestdiv = _get_maxdiv(table, width, flags);
-               *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
+               *best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
        }
 
        return bestdiv;
@@ -351,7 +356,8 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
        if (divider->flags & CLK_DIVIDER_READ_ONLY) {
                bestdiv = readl(divider->reg) >> divider->shift;
                bestdiv &= div_mask(divider->width);
-               bestdiv = _get_div(divider->table, bestdiv, divider->flags);
+               bestdiv = _get_div(divider->table, bestdiv, divider->flags,
+                       divider->width);
                return DIV_ROUND_UP(*prate, bestdiv);
        }
 
@@ -370,7 +376,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
        if (!_is_valid_div(table, div, flags))
                return -EINVAL;
 
-       value = _get_val(table, div, flags);
+       value = _get_val(table, div, flags, width);
 
        return min_t(unsigned int, value, div_mask(width));
 }
@@ -389,6 +395,8 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (divider->lock)
                spin_lock_irqsave(divider->lock, flags);
+       else
+               __acquire(divider->lock);
 
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
                val = div_mask(divider->width) << (divider->shift + 16);
@@ -401,6 +409,8 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (divider->lock)
                spin_unlock_irqrestore(divider->lock, flags);
+       else
+               __release(divider->lock);
 
        return 0;
 }
index 73a8d0ff530c022b3ccdbe0fc96fe3f4a1fc2f67..bac4553f04b854d96f3269a5b624a3723e2e9259 100644 (file)
@@ -6,7 +6,6 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
index fccabe497f6e5db42f6585acd9ecb1c4440bcb4e..83de57aeceea514dfaf53fc5a0271b1ca7d3b13d 100644 (file)
@@ -41,12 +41,11 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                unsigned long best_parent;
 
                best_parent = (rate / fix->mult) * fix->div;
-               *prate = __clk_round_rate(__clk_get_parent(hw->clk),
-                               best_parent);
+               *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
        }
 
        return (*prate / fix->div) * fix->mult;
index 140eb5844dc4b86d1fb6b7034b5c375117dee0f8..e85f856b859219b1987dda9a403e07f4ded45769 100644 (file)
@@ -27,11 +27,15 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
 
        if (fd->lock)
                spin_lock_irqsave(fd->lock, flags);
+       else
+               __acquire(fd->lock);
 
        val = clk_readl(fd->reg);
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
+       else
+               __release(fd->lock);
 
        m = (val & fd->mmask) >> fd->mshift;
        n = (val & fd->nmask) >> fd->nshift;
@@ -80,6 +84,8 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (fd->lock)
                spin_lock_irqsave(fd->lock, flags);
+       else
+               __acquire(fd->lock);
 
        val = clk_readl(fd->reg);
        val &= ~(fd->mmask | fd->nmask);
@@ -88,6 +94,8 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
+       else
+               __release(fd->lock);
 
        return 0;
 }
index 551dd067279402abbd45685315ee9df1c5f7c5d5..de0b322f5f58d4a57677455e6a5a2a78dcf0687d 100644 (file)
@@ -52,6 +52,8 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 
        if (gate->lock)
                spin_lock_irqsave(gate->lock, flags);
+       else
+               __acquire(gate->lock);
 
        if (gate->flags & CLK_GATE_HIWORD_MASK) {
                reg = BIT(gate->bit_idx + 16);
@@ -70,6 +72,8 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 
        if (gate->lock)
                spin_unlock_irqrestore(gate->lock, flags);
+       else
+               __release(gate->lock);
 }
 
 static int clk_gate_enable(struct clk_hw *hw)
diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
deleted file mode 100644 (file)
index f564e62..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
- * Author: Jyri Sarha <jsarha@ti.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.
- *
- * Gpio gated clock implementation
- */
-
-#include <linux/clk-provider.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of_gpio.h>
-#include <linux/err.h>
-#include <linux/device.h>
-
-/**
- * DOC: basic gpio gated clock which can be enabled and disabled
- *      with gpio output
- * Traits of this clock:
- * prepare - clk_(un)prepare only ensures parent is (un)prepared
- * enable - clk_enable and clk_disable are functional & control gpio
- * rate - inherits rate from parent.  No clk_set_rate support
- * parent - fixed parent.  No clk_set_parent support
- */
-
-#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
-
-static int clk_gpio_gate_enable(struct clk_hw *hw)
-{
-       struct clk_gpio *clk = to_clk_gpio(hw);
-
-       gpiod_set_value(clk->gpiod, 1);
-
-       return 0;
-}
-
-static void clk_gpio_gate_disable(struct clk_hw *hw)
-{
-       struct clk_gpio *clk = to_clk_gpio(hw);
-
-       gpiod_set_value(clk->gpiod, 0);
-}
-
-static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
-{
-       struct clk_gpio *clk = to_clk_gpio(hw);
-
-       return gpiod_get_value(clk->gpiod);
-}
-
-const struct clk_ops clk_gpio_gate_ops = {
-       .enable = clk_gpio_gate_enable,
-       .disable = clk_gpio_gate_disable,
-       .is_enabled = clk_gpio_gate_is_enabled,
-};
-EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
-
-/**
- * clk_register_gpio - register a gpip clock with the clock framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_name: name of this clock's parent
- * @gpio: gpio number to gate this clock
- * @active_low: true if gpio should be set to 0 to enable clock
- * @flags: clock flags
- */
-struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, unsigned gpio, bool active_low,
-               unsigned long flags)
-{
-       struct clk_gpio *clk_gpio = NULL;
-       struct clk *clk = ERR_PTR(-EINVAL);
-       struct clk_init_data init = { NULL };
-       unsigned long gpio_flags;
-       int err;
-
-       if (active_low)
-               gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
-       else
-               gpio_flags = GPIOF_OUT_INIT_LOW;
-
-       if (dev)
-               err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
-       else
-               err = gpio_request_one(gpio, gpio_flags, name);
-
-       if (err) {
-               pr_err("%s: %s: Error requesting clock control gpio %u\n",
-                      __func__, name, gpio);
-               return ERR_PTR(err);
-       }
-
-       if (dev)
-               clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio),
-                                       GFP_KERNEL);
-       else
-               clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL);
-
-       if (!clk_gpio) {
-               clk = ERR_PTR(-ENOMEM);
-               goto clk_register_gpio_gate_err;
-       }
-
-       init.name = name;
-       init.ops = &clk_gpio_gate_ops;
-       init.flags = flags | CLK_IS_BASIC;
-       init.parent_names = (parent_name ? &parent_name : NULL);
-       init.num_parents = (parent_name ? 1 : 0);
-
-       clk_gpio->gpiod = gpio_to_desc(gpio);
-       clk_gpio->hw.init = &init;
-
-       clk = clk_register(dev, &clk_gpio->hw);
-
-       if (!IS_ERR(clk))
-               return clk;
-
-       if (!dev)
-               kfree(clk_gpio);
-
-clk_register_gpio_gate_err:
-       if (!dev)
-               gpio_free(gpio);
-
-       return clk;
-}
-EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
-
-#ifdef CONFIG_OF
-/**
- * The clk_register_gpio_gate has to be delayed, because the EPROBE_DEFER
- * can not be handled properly at of_clk_init() call time.
- */
-
-struct clk_gpio_gate_delayed_register_data {
-       struct device_node *node;
-       struct mutex lock;
-       struct clk *clk;
-};
-
-static struct clk *of_clk_gpio_gate_delayed_register_get(
-               struct of_phandle_args *clkspec,
-               void *_data)
-{
-       struct clk_gpio_gate_delayed_register_data *data = _data;
-       struct clk *clk;
-       const char *clk_name = data->node->name;
-       const char *parent_name;
-       int gpio;
-       enum of_gpio_flags of_flags;
-
-       mutex_lock(&data->lock);
-
-       if (data->clk) {
-               mutex_unlock(&data->lock);
-               return data->clk;
-       }
-
-       gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0,
-                                               &of_flags);
-       if (gpio < 0) {
-               mutex_unlock(&data->lock);
-               if (gpio != -EPROBE_DEFER)
-                       pr_err("%s: %s: Can't get 'enable-gpios' DT property\n",
-                              __func__, clk_name);
-               return ERR_PTR(gpio);
-       }
-
-       parent_name = of_clk_get_parent_name(data->node, 0);
-
-       clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpio,
-                                       of_flags & OF_GPIO_ACTIVE_LOW, 0);
-       if (IS_ERR(clk)) {
-               mutex_unlock(&data->lock);
-               return clk;
-       }
-
-       data->clk = clk;
-       mutex_unlock(&data->lock);
-
-       return clk;
-}
-
-/**
- * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
- */
-static void __init of_gpio_gate_clk_setup(struct device_node *node)
-{
-       struct clk_gpio_gate_delayed_register_data *data;
-
-       data = kzalloc(sizeof(struct clk_gpio_gate_delayed_register_data),
-                      GFP_KERNEL);
-       if (!data)
-               return;
-
-       data->node = node;
-       mutex_init(&data->lock);
-
-       of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
-}
-CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
-#endif
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
new file mode 100644 (file)
index 0000000..10819e2
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Authors:
+ *    Jyri Sarha <jsarha@ti.com>
+ *    Sergej Sawazki <ce3a@gmx.de>
+ *
+ * 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.
+ *
+ * Gpio controlled clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_gpio.h>
+#include <linux/err.h>
+#include <linux/device.h>
+
+/**
+ * DOC: basic gpio gated clock which can be enabled and disabled
+ *      with gpio output
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gpio
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
+
+static int clk_gpio_gate_enable(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value(clk->gpiod, 1);
+
+       return 0;
+}
+
+static void clk_gpio_gate_disable(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value(clk->gpiod, 0);
+}
+
+static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       return gpiod_get_value(clk->gpiod);
+}
+
+const struct clk_ops clk_gpio_gate_ops = {
+       .enable = clk_gpio_gate_enable,
+       .disable = clk_gpio_gate_disable,
+       .is_enabled = clk_gpio_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
+
+/**
+ * DOC: basic clock multiplexer which can be controlled with a gpio output
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * rate - rate is only affected by parent switching.  No clk_set_rate support
+ * parent - parent is adjustable through clk_set_parent
+ */
+
+static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       return gpiod_get_value(clk->gpiod);
+}
+
+static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value(clk->gpiod, index);
+
+       return 0;
+}
+
+const struct clk_ops clk_gpio_mux_ops = {
+       .get_parent = clk_gpio_mux_get_parent,
+       .set_parent = clk_gpio_mux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
+
+static struct clk *clk_register_gpio(struct device *dev, const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low, unsigned long flags,
+               const struct clk_ops *clk_gpio_ops)
+{
+       struct clk_gpio *clk_gpio;
+       struct clk *clk;
+       struct clk_init_data init = {};
+       unsigned long gpio_flags;
+       int err;
+
+       if (dev)
+               clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
+       else
+               clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL);
+
+       if (!clk_gpio)
+               return ERR_PTR(-ENOMEM);
+
+       if (active_low)
+               gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
+       else
+               gpio_flags = GPIOF_OUT_INIT_LOW;
+
+       if (dev)
+               err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
+       else
+               err = gpio_request_one(gpio, gpio_flags, name);
+       if (err) {
+               if (err != -EPROBE_DEFER)
+                       pr_err("%s: %s: Error requesting clock control gpio %u\n",
+                                       __func__, name, gpio);
+               if (!dev)
+                       kfree(clk_gpio);
+
+               return ERR_PTR(err);
+       }
+
+       init.name = name;
+       init.ops = clk_gpio_ops;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+
+       clk_gpio->gpiod = gpio_to_desc(gpio);
+       clk_gpio->hw.init = &init;
+
+       if (dev)
+               clk = devm_clk_register(dev, &clk_gpio->hw);
+       else
+               clk = clk_register(NULL, &clk_gpio->hw);
+
+       if (!IS_ERR(clk))
+               return clk;
+
+       if (!dev) {
+               gpiod_put(clk_gpio->gpiod);
+               kfree(clk_gpio);
+       }
+
+       return clk;
+}
+
+/**
+ * clk_register_gpio_gate - register a gpio clock gate with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of this clock's parent
+ * @gpio: gpio number to gate this clock
+ * @active_low: true if gpio should be set to 0 to enable clock
+ * @flags: clock flags
+ */
+struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
+               const char *parent_name, unsigned gpio, bool active_low,
+               unsigned long flags)
+{
+       return clk_register_gpio(dev, name,
+                       (parent_name ? &parent_name : NULL),
+                       (parent_name ? 1 : 0), gpio, active_low, flags,
+                       &clk_gpio_gate_ops);
+}
+EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
+
+/**
+ * clk_register_gpio_mux - register a gpio clock mux with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_names: names of this clock's parents
+ * @num_parents: number of parents listed in @parent_names
+ * @gpio: gpio number to gate this clock
+ * @active_low: true if gpio should be set to 0 to enable clock
+ * @flags: clock flags
+ */
+struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low, unsigned long flags)
+{
+       if (num_parents != 2) {
+               pr_err("mux-clock %s must have 2 parents\n", name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return clk_register_gpio(dev, name, parent_names, num_parents,
+                       gpio, active_low, flags, &clk_gpio_mux_ops);
+}
+EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
+
+#ifdef CONFIG_OF
+/**
+ * clk_register_get() has to be delayed, because -EPROBE_DEFER
+ * can not be handled properly at of_clk_init() call time.
+ */
+
+struct clk_gpio_delayed_register_data {
+       const char *gpio_name;
+       struct device_node *node;
+       struct mutex lock;
+       struct clk *clk;
+       struct clk *(*clk_register_get)(const char *name,
+                       const char * const *parent_names, u8 num_parents,
+                       unsigned gpio, bool active_low);
+};
+
+static struct clk *of_clk_gpio_delayed_register_get(
+               struct of_phandle_args *clkspec, void *_data)
+{
+       struct clk_gpio_delayed_register_data *data = _data;
+       struct clk *clk;
+       const char **parent_names;
+       int i, num_parents;
+       int gpio;
+       enum of_gpio_flags of_flags;
+
+       mutex_lock(&data->lock);
+
+       if (data->clk) {
+               mutex_unlock(&data->lock);
+               return data->clk;
+       }
+
+       gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0,
+                       &of_flags);
+       if (gpio < 0) {
+               mutex_unlock(&data->lock);
+               if (gpio == -EPROBE_DEFER)
+                       pr_debug("%s: %s: GPIOs not yet available, retry later\n",
+                                       data->node->name, __func__);
+               else
+                       pr_err("%s: %s: Can't get '%s' DT property\n",
+                                       data->node->name, __func__,
+                                       data->gpio_name);
+               return ERR_PTR(gpio);
+       }
+
+       num_parents = of_clk_get_parent_count(data->node);
+
+       parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+       if (!parent_names) {
+               clk = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
+       for (i = 0; i < num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(data->node, i);
+
+       clk = data->clk_register_get(data->node->name, parent_names,
+                       num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
+       if (IS_ERR(clk))
+               goto out;
+
+       data->clk = clk;
+out:
+       mutex_unlock(&data->lock);
+       kfree(parent_names);
+
+       return clk;
+}
+
+static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name,
+               const char * const *parent_names, u8 num_parents,
+               unsigned gpio, bool active_low)
+{
+       return clk_register_gpio_gate(NULL, name, parent_names[0],
+                       gpio, active_low, 0);
+}
+
+static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low)
+{
+       return clk_register_gpio_mux(NULL, name, parent_names, num_parents,
+                       gpio, active_low, 0);
+}
+
+static void __init of_gpio_clk_setup(struct device_node *node,
+               const char *gpio_name,
+               struct clk *(*clk_register_get)(const char *name,
+                               const char * const *parent_names,
+                               u8 num_parents,
+                               unsigned gpio, bool active_low))
+{
+       struct clk_gpio_delayed_register_data *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return;
+
+       data->node = node;
+       data->gpio_name = gpio_name;
+       data->clk_register_get = clk_register_get;
+       mutex_init(&data->lock);
+
+       of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data);
+}
+
+static void __init of_gpio_gate_clk_setup(struct device_node *node)
+{
+       of_gpio_clk_setup(node, "enable-gpios",
+               of_clk_gpio_gate_delayed_register_get);
+}
+CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
+
+void __init of_gpio_mux_clk_setup(struct device_node *node)
+{
+       of_gpio_clk_setup(node, "select-gpios",
+               of_clk_gpio_mux_delayed_register_get);
+}
+CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup);
+#endif
index 2e7e9d9798cb20901cc2dd234c33ef6d306dc966..be3a21abb185a188e207d8dd35cb8146293779a0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 5181b89c3cb2f18de2047a70a0bc43c562be4326..f37f719643ec0633552c16f310be264fae97c124 100644 (file)
@@ -10,6 +10,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
index 6066a01b20ea8d0e304dca2ff27bc34da9e0bf1c..7129c86a79dbfa679fa6dd707dab70aad9821324 100644 (file)
@@ -10,7 +10,6 @@
  * Simple multiplexer clock implementation
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -32,7 +31,7 @@
 static u8 clk_mux_get_parent(struct clk_hw *hw)
 {
        struct clk_mux *mux = to_clk_mux(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
        /*
@@ -85,6 +84,8 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 
        if (mux->lock)
                spin_lock_irqsave(mux->lock, flags);
+       else
+               __acquire(mux->lock);
 
        if (mux->flags & CLK_MUX_HIWORD_MASK) {
                val = mux->mask << (mux->shift + 16);
@@ -97,6 +98,8 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 
        if (mux->lock)
                spin_unlock_irqrestore(mux->lock, flags);
+       else
+               __release(mux->lock);
 
        return 0;
 }
index c9487179f25f46d79e511ace153e3a3e7078e49e..e4d8a991c58fa3972d414810e634ec5c72fb0c9a 100644 (file)
@@ -8,8 +8,7 @@
 #define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
 
 #include <linux/bitops.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk-provider.h>
index 45a535ab48aaa1cf443d4467f42734b7949b1b47..8e3039f0c3f9544de39bc8c06be41a2337b8492a 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/palmas.h>
 #include <linux/module.h>
index 83902b9cd49ef0a5772e807806999a1d16786195..0fee2f4ca258365bfa48a183c5712e7696e3b306 100644 (file)
@@ -15,7 +15,6 @@
  * more details.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 9b13a303d3f81e432f6ddac4ffe85dd27d4c8f82..d266299dfdb1a26e22477f78a2c389d5dc858f4f 100644 (file)
@@ -58,21 +58,17 @@ static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
 static int s2mps11_clk_prepare(struct clk_hw *hw)
 {
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
-       int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
+       return regmap_update_bits(s2mps11->iodev->regmap_pmic,
                                 s2mps11->reg,
                                 s2mps11->mask, s2mps11->mask);
-
-       return ret;
 }
 
 static void s2mps11_clk_unprepare(struct clk_hw *hw)
 {
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
-       int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
+       regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
                           s2mps11->mask, ~s2mps11->mask);
 }
 
@@ -186,15 +182,15 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
        struct clk_init_data *clks_init;
        int i, ret = 0;
 
-       s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
-                                       S2MPS11_CLKS_NUM, GFP_KERNEL);
+       s2mps11_clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
+                               sizeof(*s2mps11_clk), GFP_KERNEL);
        if (!s2mps11_clks)
                return -ENOMEM;
 
        s2mps11_clk = s2mps11_clks;
 
-       clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
-                                S2MPS11_CLKS_NUM, GFP_KERNEL);
+       clk_table = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
+                               sizeof(struct clk *), GFP_KERNEL);
        if (!clk_table)
                return -ENOMEM;
 
@@ -246,7 +242,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                                        s2mps11_name(s2mps11_clk), NULL);
                if (!s2mps11_clk->lookup) {
                        ret = -ENOMEM;
-                       goto err_lup;
+                       goto err_reg;
                }
        }
 
@@ -265,16 +261,10 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, s2mps11_clks);
 
        return ret;
-err_lup:
-       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
+
 err_reg:
-       while (s2mps11_clk > s2mps11_clks) {
-               if (s2mps11_clk->lookup) {
-                       clkdev_drop(s2mps11_clk->lookup);
-                       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
-               }
-               s2mps11_clk--;
-       }
+       while (--i >= 0)
+               clkdev_drop(s2mps11_clks[i].lookup);
 
        return ret;
 }
@@ -322,7 +312,7 @@ static int __init s2mps11_clk_init(void)
 }
 subsys_initcall(s2mps11_clk_init);
 
-static void __init s2mps11_clk_cleanup(void)
+static void __exit s2mps11_clk_cleanup(void)
 {
        platform_driver_unregister(&s2mps11_clk_driver);
 }
index e39e1e680b3c6c09b117e7a32a35b7d1a808bf37..5596c0aac22f8f4f1a639d6e3cf01ad92c7e0df4 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/clkdev.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -439,7 +439,7 @@ static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                parent_rate, (unsigned long)rate);
 
@@ -497,7 +497,7 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), a, b, c,
+               __func__, clk_hw_get_name(hw), a, b, c,
                *parent_rate, rate);
 
        return rate;
@@ -521,7 +521,7 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                parent_rate, rate);
 
@@ -632,7 +632,7 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, m = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                m, parent_rate, (unsigned long)rate);
 
@@ -663,7 +663,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
                divby4 = 1;
 
        /* multisync can set pll */
-       if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                /*
                 * find largest integer divider for max
                 * vco frequency and given target rate
@@ -745,7 +745,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), a, b, c, divby4,
+               __func__, clk_hw_get_name(hw), a, b, c, divby4,
                *parent_rate, rate);
 
        return rate;
@@ -777,7 +777,7 @@ static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                divby4, parent_rate, rate);
 
@@ -1013,7 +1013,7 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
                rate = SI5351_CLKOUT_MIN_FREQ;
 
        /* request frequency if multisync master */
-       if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                /* use r divider for frequencies below 1MHz */
                rdiv = SI5351_OUTPUT_CLK_DIV_1;
                while (rate < SI5351_MULTISYNTH_MIN_FREQ &&
@@ -1042,7 +1042,7 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
+               __func__, clk_hw_get_name(hw), (1 << rdiv),
                *parent_rate, rate);
 
        return rate;
@@ -1093,7 +1093,7 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
+               __func__, clk_hw_get_name(hw), (1 << rdiv),
                parent_rate, rate);
 
        return 0;
index 20a5aec98b1a2ca1b88560ccd0336d75073c4bed..cf478aa9fa5d9e9b791d6fc9cd32ffaa1864d10a 100644 (file)
@@ -19,6 +19,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index 3f6f7ad39490458a6e9cdcf4d944665abd34df86..fd89e771107eadfcb3b319f67f65eb16773bb654 100644 (file)
@@ -175,11 +175,10 @@ static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
        if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
                mult = 2;
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                unsigned long best_parent = rate / mult;
 
-               *prate =
-                   __clk_round_rate(__clk_get_parent(hw->clk), best_parent);
+               *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
        }
 
        return *prate * mult;
index 4a755135bcd388433696ee4c651a5bbb03302f5b..8e5ed649a0986721a1fcad1a9038ccb5b0c1e73d 100644 (file)
@@ -20,7 +20,6 @@
 *
 */
 
-#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
@@ -91,7 +90,7 @@ static int twl6040_clk_probe(struct platform_device *pdev)
        clkdata->twl6040 = twl6040;
 
        clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
-       clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+       clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
        if (IS_ERR(clkdata->clk))
                return PTR_ERR(clkdata->clk);
 
@@ -100,21 +99,11 @@ static int twl6040_clk_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int twl6040_clk_remove(struct platform_device *pdev)
-{
-       struct twl6040_clk *clkdata = platform_get_drvdata(pdev);
-
-       clk_unregister(clkdata->clk);
-
-       return 0;
-}
-
 static struct platform_driver twl6040_clk_driver = {
        .driver = {
                .name = "twl6040-clk",
        },
        .probe = twl6040_clk_probe,
-       .remove = twl6040_clk_remove,
 };
 
 module_platform_driver(twl6040_clk_driver);
index 18bf5e576b9390c680b4e9a08637104cb07cdde4..95d1742dac309fe43036b0d926e3b516a23a7822 100644 (file)
@@ -5,8 +5,8 @@
  * Author: Linus Walleij <linus.walleij@stericsson.com>
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  */
-#include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk-provider.h>
index ef67719f4e52c23cd977844662e3a202be4963bc..43f9d15255f4fd3a902b9ead2ccdc67d6e61fac4 100644 (file)
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index f26b3ac36b27a1aa06fd7db2b3352420f96c7768..96a6190acac230844d7c3588754d4280dc6d8f0e 100644 (file)
@@ -60,7 +60,6 @@ enum xgene_pll_type {
 
 struct xgene_clk_pll {
        struct clk_hw   hw;
-       const char      *name;
        void __iomem    *reg;
        spinlock_t      *lock;
        u32             pll_offset;
@@ -75,7 +74,7 @@ static int xgene_clk_pll_is_enabled(struct clk_hw *hw)
        u32 data;
 
        data = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
-       pr_debug("%s pll %s\n", pllclk->name,
+       pr_debug("%s pll %s\n", clk_hw_get_name(hw),
                data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled");
 
        return data & REGSPEC_RESET_F1_MASK ? 0 : 1;
@@ -113,7 +112,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
                fref = parent_rate / nref;
                fvco = fref * nfb;
        }
-       pr_debug("%s pll recalc rate %ld parent %ld\n", pllclk->name,
+       pr_debug("%s pll recalc rate %ld parent %ld\n", clk_hw_get_name(hw),
                fvco / nout, parent_rate);
 
        return fvco / nout;
@@ -146,7 +145,6 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
 
-       apmclk->name = name;
        apmclk->reg = reg;
        apmclk->lock = lock;
        apmclk->pll_offset = pll_offset;
@@ -210,7 +208,6 @@ struct xgene_dev_parameters {
 
 struct xgene_clk {
        struct clk_hw   hw;
-       const char      *name;
        spinlock_t      *lock;
        struct xgene_dev_parameters     param;
 };
@@ -228,7 +225,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
                spin_lock_irqsave(pclk->lock, flags);
 
        if (pclk->param.csr_reg != NULL) {
-               pr_debug("%s clock enabled\n", pclk->name);
+               pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
                reg = __pa(pclk->param.csr_reg);
                /* First enable the clock */
                data = xgene_clk_read(pclk->param.csr_reg +
@@ -237,7 +234,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
                xgene_clk_write(data, pclk->param.csr_reg +
                                        pclk->param.reg_clk_offset);
                pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
-                       pclk->name, &reg,
+                       clk_hw_get_name(hw), &reg,
                        pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
                        data);
 
@@ -248,7 +245,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
                xgene_clk_write(data, pclk->param.csr_reg +
                                        pclk->param.reg_csr_offset);
                pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
-                       pclk->name, &reg,
+                       clk_hw_get_name(hw), &reg,
                        pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
                        data);
        }
@@ -269,7 +266,7 @@ static void xgene_clk_disable(struct clk_hw *hw)
                spin_lock_irqsave(pclk->lock, flags);
 
        if (pclk->param.csr_reg != NULL) {
-               pr_debug("%s clock disabled\n", pclk->name);
+               pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
                /* First put the CSR in reset */
                data = xgene_clk_read(pclk->param.csr_reg +
                                        pclk->param.reg_csr_offset);
@@ -295,10 +292,10 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
        u32 data = 0;
 
        if (pclk->param.csr_reg != NULL) {
-               pr_debug("%s clock checking\n", pclk->name);
+               pr_debug("%s clock checking\n", clk_hw_get_name(hw));
                data = xgene_clk_read(pclk->param.csr_reg +
                                        pclk->param.reg_clk_offset);
-               pr_debug("%s clock is %s\n", pclk->name,
+               pr_debug("%s clock is %s\n", clk_hw_get_name(hw),
                        data & pclk->param.reg_clk_mask ? "enabled" :
                                                        "disabled");
        }
@@ -321,11 +318,13 @@ static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw,
                data &= (1 << pclk->param.reg_divider_width) - 1;
 
                pr_debug("%s clock recalc rate %ld parent %ld\n",
-                       pclk->name, parent_rate / data, parent_rate);
+                       clk_hw_get_name(hw),
+                       parent_rate / data, parent_rate);
+
                return parent_rate / data;
        } else {
                pr_debug("%s clock recalc rate %ld parent %ld\n",
-                       pclk->name, parent_rate, parent_rate);
+                       clk_hw_get_name(hw), parent_rate, parent_rate);
                return parent_rate;
        }
 }
@@ -357,7 +356,7 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
                data |= divider;
                xgene_clk_write(data, pclk->param.divider_reg +
                                        pclk->param.reg_divider_offset);
-               pr_debug("%s clock set rate %ld\n", pclk->name,
+               pr_debug("%s clock set rate %ld\n", clk_hw_get_name(hw),
                        parent_rate / divider_save);
        } else {
                divider_save = 1;
@@ -419,7 +418,6 @@ static struct clk *xgene_register_clk(struct device *dev,
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
 
-       apmclk->name = name;
        apmclk->lock = lock;
        apmclk->hw.init = &init;
        apmclk->param = *parameters;
index ddb4b541016fe986860a95a4a482d2f6c6713a3e..43e2c3ad6c3111ae6d0a83f027b75344c087f5f2 100644 (file)
@@ -9,6 +9,7 @@
  * Standard functionality for the common clock API.  See Documentation/clk.txt
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/module.h>
@@ -56,8 +57,11 @@ struct clk_core {
        struct clk_core         *new_parent;
        struct clk_core         *new_child;
        unsigned long           flags;
+       bool                    orphan;
        unsigned int            enable_count;
        unsigned int            prepare_count;
+       unsigned long           min_rate;
+       unsigned long           max_rate;
        unsigned long           accuracy;
        int                     phase;
        struct hlist_head       children;
@@ -111,12 +115,14 @@ static void clk_prepare_unlock(void)
 }
 
 static unsigned long clk_enable_lock(void)
+       __acquires(enable_lock)
 {
        unsigned long flags;
 
        if (!spin_trylock_irqsave(&enable_lock, flags)) {
                if (enable_owner == current) {
                        enable_refcnt++;
+                       __acquire(enable_lock);
                        return flags;
                }
                spin_lock_irqsave(&enable_lock, flags);
@@ -129,12 +135,15 @@ static unsigned long clk_enable_lock(void)
 }
 
 static void clk_enable_unlock(unsigned long flags)
+       __releases(enable_lock)
 {
        WARN_ON_ONCE(enable_owner != current);
        WARN_ON_ONCE(enable_refcnt == 0);
 
-       if (--enable_refcnt)
+       if (--enable_refcnt) {
+               __release(enable_lock);
                return;
+       }
        enable_owner = NULL;
        spin_unlock_irqrestore(&enable_lock, flags);
 }
@@ -269,27 +278,29 @@ const char *__clk_get_name(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_name);
 
+const char *clk_hw_get_name(const struct clk_hw *hw)
+{
+       return hw->core->name;
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_name);
+
 struct clk_hw *__clk_get_hw(struct clk *clk)
 {
        return !clk ? NULL : clk->core->hw;
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
-u8 __clk_get_num_parents(struct clk *clk)
+unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
 {
-       return !clk ? 0 : clk->core->num_parents;
+       return hw->core->num_parents;
 }
-EXPORT_SYMBOL_GPL(__clk_get_num_parents);
+EXPORT_SYMBOL_GPL(clk_hw_get_num_parents);
 
-struct clk *__clk_get_parent(struct clk *clk)
+struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw)
 {
-       if (!clk)
-               return NULL;
-
-       /* TODO: Create a per-user clk and change callers to call clk_put */
-       return !clk->core->parent ? NULL : clk->core->parent->hw->clk;
+       return hw->core->parent ? hw->core->parent->hw : NULL;
 }
-EXPORT_SYMBOL_GPL(__clk_get_parent);
+EXPORT_SYMBOL_GPL(clk_hw_get_parent);
 
 static struct clk_core *__clk_lookup_subtree(const char *name,
                                             struct clk_core *core)
@@ -348,18 +359,16 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
                return core->parents[index];
 }
 
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+struct clk_hw *
+clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
 {
        struct clk_core *parent;
 
-       if (!clk)
-               return NULL;
-
-       parent = clk_core_get_parent_by_index(clk->core, index);
+       parent = clk_core_get_parent_by_index(hw->core, index);
 
-       return !parent ? NULL : parent->hw->clk;
+       return !parent ? NULL : parent->hw;
 }
-EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
+EXPORT_SYMBOL_GPL(clk_hw_get_parent_by_index);
 
 unsigned int __clk_get_enable_count(struct clk *clk)
 {
@@ -387,14 +396,11 @@ out:
        return ret;
 }
 
-unsigned long __clk_get_rate(struct clk *clk)
+unsigned long clk_hw_get_rate(const struct clk_hw *hw)
 {
-       if (!clk)
-               return 0;
-
-       return clk_core_get_rate_nolock(clk->core);
+       return clk_core_get_rate_nolock(hw->core);
 }
-EXPORT_SYMBOL_GPL(__clk_get_rate);
+EXPORT_SYMBOL_GPL(clk_hw_get_rate);
 
 static unsigned long __clk_get_accuracy(struct clk_core *core)
 {
@@ -410,12 +416,15 @@ unsigned long __clk_get_flags(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-bool __clk_is_prepared(struct clk *clk)
+unsigned long clk_hw_get_flags(const struct clk_hw *hw)
 {
-       if (!clk)
-               return false;
+       return hw->core->flags;
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_flags);
 
-       return clk_core_is_prepared(clk->core);
+bool clk_hw_is_prepared(const struct clk_hw *hw)
+{
+       return clk_core_is_prepared(hw->core);
 }
 
 bool __clk_is_enabled(struct clk *clk)
@@ -436,28 +445,31 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
        return now <= rate && now > best;
 }
 
-static long
-clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
-                            unsigned long min_rate,
-                            unsigned long max_rate,
-                            unsigned long *best_parent_rate,
-                            struct clk_hw **best_parent_p,
+static int
+clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req,
                             unsigned long flags)
 {
        struct clk_core *core = hw->core, *parent, *best_parent = NULL;
-       int i, num_parents;
-       unsigned long parent_rate, best = 0;
+       int i, num_parents, ret;
+       unsigned long best = 0;
+       struct clk_rate_request parent_req = *req;
 
        /* if NO_REPARENT flag set, pass through to current parent */
        if (core->flags & CLK_SET_RATE_NO_REPARENT) {
                parent = core->parent;
-               if (core->flags & CLK_SET_RATE_PARENT)
-                       best = __clk_determine_rate(parent ? parent->hw : NULL,
-                                                   rate, min_rate, max_rate);
-               else if (parent)
+               if (core->flags & CLK_SET_RATE_PARENT) {
+                       ret = __clk_determine_rate(parent ? parent->hw : NULL,
+                                                  &parent_req);
+                       if (ret)
+                               return ret;
+
+                       best = parent_req.rate;
+               } else if (parent) {
                        best = clk_core_get_rate_nolock(parent);
-               else
+               } else {
                        best = clk_core_get_rate_nolock(core);
+               }
+
                goto out;
        }
 
@@ -467,24 +479,33 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
                parent = clk_core_get_parent_by_index(core, i);
                if (!parent)
                        continue;
-               if (core->flags & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_determine_rate(parent->hw, rate,
-                                                          min_rate,
-                                                          max_rate);
-               else
-                       parent_rate = clk_core_get_rate_nolock(parent);
-               if (mux_is_better_rate(rate, parent_rate, best, flags)) {
+
+               if (core->flags & CLK_SET_RATE_PARENT) {
+                       parent_req = *req;
+                       ret = __clk_determine_rate(parent->hw, &parent_req);
+                       if (ret)
+                               continue;
+               } else {
+                       parent_req.rate = clk_core_get_rate_nolock(parent);
+               }
+
+               if (mux_is_better_rate(req->rate, parent_req.rate,
+                                      best, flags)) {
                        best_parent = parent;
-                       best = parent_rate;
+                       best = parent_req.rate;
                }
        }
 
+       if (!best_parent)
+               return -EINVAL;
+
 out:
        if (best_parent)
-               *best_parent_p = best_parent->hw;
-       *best_parent_rate = best;
+               req->best_parent_hw = best_parent->hw;
+       req->best_parent_rate = best;
+       req->rate = best;
 
-       return best;
+       return 0;
 }
 
 struct clk *__clk_lookup(const char *name)
@@ -500,8 +521,8 @@ static void clk_core_get_boundaries(struct clk_core *core,
 {
        struct clk *clk_user;
 
-       *min_rate = 0;
-       *max_rate = ULONG_MAX;
+       *min_rate = core->min_rate;
+       *max_rate = core->max_rate;
 
        hlist_for_each_entry(clk_user, &core->clks, clks_node)
                *min_rate = max(*min_rate, clk_user->min_rate);
@@ -510,33 +531,30 @@ static void clk_core_get_boundaries(struct clk_core *core,
                *max_rate = min(*max_rate, clk_user->max_rate);
 }
 
+void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
+                          unsigned long max_rate)
+{
+       hw->core->min_rate = min_rate;
+       hw->core->max_rate = max_rate;
+}
+EXPORT_SYMBOL_GPL(clk_hw_set_rate_range);
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
  * complex clock that may combine a mux with other operations.
  */
-long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p)
+int __clk_mux_determine_rate(struct clk_hw *hw,
+                            struct clk_rate_request *req)
 {
-       return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
-                                           best_parent_rate,
-                                           best_parent_p, 0);
+       return clk_mux_determine_rate_flags(hw, req, 0);
 }
 EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
 
-long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p)
+int __clk_mux_determine_rate_closest(struct clk_hw *hw,
+                                    struct clk_rate_request *req)
 {
-       return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
-                                           best_parent_rate,
-                                           best_parent_p,
-                                           CLK_MUX_ROUND_CLOSEST);
+       return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
 }
 EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
 
@@ -759,14 +777,11 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
-static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
-                                               unsigned long rate,
-                                               unsigned long min_rate,
-                                               unsigned long max_rate)
+static int clk_core_round_rate_nolock(struct clk_core *core,
+                                     struct clk_rate_request *req)
 {
-       unsigned long parent_rate = 0;
        struct clk_core *parent;
-       struct clk_hw *parent_hw;
+       long rate;
 
        lockdep_assert_held(&prepare_lock);
 
@@ -774,21 +789,30 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
                return 0;
 
        parent = core->parent;
-       if (parent)
-               parent_rate = parent->rate;
+       if (parent) {
+               req->best_parent_hw = parent->hw;
+               req->best_parent_rate = parent->rate;
+       } else {
+               req->best_parent_hw = NULL;
+               req->best_parent_rate = 0;
+       }
 
        if (core->ops->determine_rate) {
-               parent_hw = parent ? parent->hw : NULL;
-               return core->ops->determine_rate(core->hw, rate,
-                                               min_rate, max_rate,
-                                               &parent_rate, &parent_hw);
-       } else if (core->ops->round_rate)
-               return core->ops->round_rate(core->hw, rate, &parent_rate);
-       else if (core->flags & CLK_SET_RATE_PARENT)
-               return clk_core_round_rate_nolock(core->parent, rate, min_rate,
-                                                 max_rate);
-       else
-               return core->rate;
+               return core->ops->determine_rate(core->hw, req);
+       } else if (core->ops->round_rate) {
+               rate = core->ops->round_rate(core->hw, req->rate,
+                                            &req->best_parent_rate);
+               if (rate < 0)
+                       return rate;
+
+               req->rate = rate;
+       } else if (core->flags & CLK_SET_RATE_PARENT) {
+               return clk_core_round_rate_nolock(parent, req);
+       } else {
+               req->rate = core->rate;
+       }
+
+       return 0;
 }
 
 /**
@@ -800,38 +824,32 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
  *
  * Useful for clk_ops such as .set_rate and .determine_rate.
  */
-unsigned long __clk_determine_rate(struct clk_hw *hw,
-                                  unsigned long rate,
-                                  unsigned long min_rate,
-                                  unsigned long max_rate)
+int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
-       if (!hw)
+       if (!hw) {
+               req->rate = 0;
                return 0;
+       }
 
-       return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+       return clk_core_round_rate_nolock(hw->core, req);
 }
 EXPORT_SYMBOL_GPL(__clk_determine_rate);
 
-/**
- * __clk_round_rate - round the given rate for a clk
- * @clk: round the rate of this clock
- * @rate: the rate which is to be rounded
- *
- * Useful for clk_ops such as .set_rate
- */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
 {
-       unsigned long min_rate;
-       unsigned long max_rate;
+       int ret;
+       struct clk_rate_request req;
 
-       if (!clk)
-               return 0;
+       clk_core_get_boundaries(hw->core, &req.min_rate, &req.max_rate);
+       req.rate = rate;
 
-       clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+       ret = clk_core_round_rate_nolock(hw->core, &req);
+       if (ret)
+               return 0;
 
-       return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
+       return req.rate;
 }
-EXPORT_SYMBOL_GPL(__clk_round_rate);
+EXPORT_SYMBOL_GPL(clk_hw_round_rate);
 
 /**
  * clk_round_rate - round the given rate for a clk
@@ -844,16 +862,24 @@ EXPORT_SYMBOL_GPL(__clk_round_rate);
  */
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       unsigned long ret;
+       struct clk_rate_request req;
+       int ret;
 
        if (!clk)
                return 0;
 
        clk_prepare_lock();
-       ret = __clk_round_rate(clk, rate);
+
+       clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
+       req.rate = rate;
+
+       ret = clk_core_round_rate_nolock(clk->core, &req);
        clk_prepare_unlock();
 
-       return ret;
+       if (ret)
+               return ret;
+
+       return req.rate;
 }
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
@@ -1064,18 +1090,40 @@ static int clk_fetch_parent_index(struct clk_core *core,
        return -EINVAL;
 }
 
+/*
+ * Update the orphan status of @core and all its children.
+ */
+static void clk_core_update_orphan_status(struct clk_core *core, bool is_orphan)
+{
+       struct clk_core *child;
+
+       core->orphan = is_orphan;
+
+       hlist_for_each_entry(child, &core->children, child_node)
+               clk_core_update_orphan_status(child, is_orphan);
+}
+
 static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
 {
+       bool was_orphan = core->orphan;
+
        hlist_del(&core->child_node);
 
        if (new_parent) {
+               bool becomes_orphan = new_parent->orphan;
+
                /* avoid duplicate POST_RATE_CHANGE notifications */
                if (new_parent->new_child == core)
                        new_parent->new_child = NULL;
 
                hlist_add_head(&core->child_node, &new_parent->children);
+
+               if (was_orphan != becomes_orphan)
+                       clk_core_update_orphan_status(core, becomes_orphan);
        } else {
                hlist_add_head(&core->child_node, &clk_orphan_list);
+               if (!was_orphan)
+                       clk_core_update_orphan_status(core, true);
        }
 
        core->parent = new_parent;
@@ -1160,14 +1208,8 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
                flags = clk_enable_lock();
                clk_reparent(core, old_parent);
                clk_enable_unlock(flags);
+               __clk_set_parent_after(core, old_parent, parent);
 
-               if (core->prepare_count) {
-                       flags = clk_enable_lock();
-                       clk_core_disable(core);
-                       clk_core_disable(parent);
-                       clk_enable_unlock(flags);
-                       clk_core_unprepare(parent);
-               }
                return ret;
        }
 
@@ -1249,7 +1291,6 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 {
        struct clk_core *top = core;
        struct clk_core *old_parent, *parent;
-       struct clk_hw *parent_hw;
        unsigned long best_parent_rate = 0;
        unsigned long new_rate;
        unsigned long min_rate;
@@ -1270,20 +1311,29 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 
        /* find the closest rate and parent clk/rate */
        if (core->ops->determine_rate) {
-               parent_hw = parent ? parent->hw : NULL;
-               ret = core->ops->determine_rate(core->hw, rate,
-                                              min_rate,
-                                              max_rate,
-                                              &best_parent_rate,
-                                              &parent_hw);
+               struct clk_rate_request req;
+
+               req.rate = rate;
+               req.min_rate = min_rate;
+               req.max_rate = max_rate;
+               if (parent) {
+                       req.best_parent_hw = parent->hw;
+                       req.best_parent_rate = parent->rate;
+               } else {
+                       req.best_parent_hw = NULL;
+                       req.best_parent_rate = 0;
+               }
+
+               ret = core->ops->determine_rate(core->hw, &req);
                if (ret < 0)
                        return NULL;
 
-               new_rate = ret;
-               parent = parent_hw ? parent_hw->core : NULL;
+               best_parent_rate = req.best_parent_rate;
+               new_rate = req.rate;
+               parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;
        } else if (core->ops->round_rate) {
                ret = core->ops->round_rate(core->hw, rate,
-                                          &best_parent_rate);
+                                           &best_parent_rate);
                if (ret < 0)
                        return NULL;
 
@@ -1592,8 +1642,12 @@ struct clk *clk_get_parent(struct clk *clk)
 {
        struct clk *parent;
 
+       if (!clk)
+               return NULL;
+
        clk_prepare_lock();
-       parent = __clk_get_parent(clk);
+       /* TODO: Create a per-user clk and change callers to call clk_put */
+       parent = !clk->core->parent ? NULL : clk->core->parent->hw->clk;
        clk_prepare_unlock();
 
        return parent;
@@ -2324,13 +2378,17 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
         * clocks and re-parent any that are children of the clock currently
         * being clk_init'd.
         */
-       if (core->parent)
+       if (core->parent) {
                hlist_add_head(&core->child_node,
                                &core->parent->children);
-       else if (core->flags & CLK_IS_ROOT)
+               core->orphan = core->parent->orphan;
+       } else if (core->flags & CLK_IS_ROOT) {
                hlist_add_head(&core->child_node, &clk_root_list);
-       else
+               core->orphan = false;
+       } else {
                hlist_add_head(&core->child_node, &clk_orphan_list);
+               core->orphan = true;
+       }
 
        /*
         * Set clk's accuracy.  The preferred method is to use
@@ -2479,6 +2537,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
        core->hw = hw;
        core->flags = hw->init->flags;
        core->num_parents = hw->init->num_parents;
+       core->min_rate = 0;
+       core->max_rate = ULONG_MAX;
        hw->core = core;
 
        /* allocate local copy in case parent_names is __initdata */
@@ -3054,8 +3114,6 @@ struct clock_provider {
        struct list_head node;
 };
 
-static LIST_HEAD(clk_provider_list);
-
 /*
  * This function looks for a parent clock. If there is one, then it
  * checks that the provider for this parent clock was initialized, in
@@ -3106,14 +3164,24 @@ void __init of_clk_init(const struct of_device_id *matches)
        struct clock_provider *clk_provider, *next;
        bool is_init_done;
        bool force = false;
+       LIST_HEAD(clk_provider_list);
 
        if (!matches)
                matches = &__clk_of_table;
 
        /* First prepare the list of the clocks providers */
        for_each_matching_node_and_match(np, matches, &match) {
-               struct clock_provider *parent =
-                       kzalloc(sizeof(struct clock_provider),  GFP_KERNEL);
+               struct clock_provider *parent;
+
+               parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+               if (!parent) {
+                       list_for_each_entry_safe(clk_provider, next,
+                                                &clk_provider_list, node) {
+                               list_del(&clk_provider->node);
+                               kfree(clk_provider);
+                       }
+                       return;
+               }
 
                parent->clk_init_cb = match->data;
                parent->np = np;
index 56f9eba91b838d3b855678f70e6a2249cd8d67c6..1dd5d14d5dbe0f4cc6092ba535ef950440d323be 100644 (file)
@@ -4,8 +4,6 @@
  * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/of.h>
@@ -15,7 +13,7 @@ static DEFINE_SPINLOCK(clklock);
 
 static void __init h8300_div_clk_setup(struct device_node *node)
 {
-       unsigned int num_parents;
+       int num_parents;
        struct clk *clk;
        const char *clk_name = node->name;
        const char *parent_name;
index 4701b093e497f6dac1c718674423ded21b40caee..2a38eb4a25527604ec0cbd867ab5d6fbfbc4b648 100644 (file)
@@ -4,8 +4,6 @@
  * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/device.h>
@@ -28,7 +26,7 @@ static unsigned long pll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
        struct pll_clock *pll_clock = to_pll_clock(hw);
-       int mul = 1 << (ctrl_inb((unsigned long)pll_clock->pllcr) & 3);
+       int mul = 1 << (readb(pll_clock->pllcr) & 3);
 
        return parent_rate * mul;
 }
@@ -65,13 +63,13 @@ static int pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        pll = ((rate / parent_rate) / 2) & 0x03;
        spin_lock_irqsave(&clklock, flags);
-       val = ctrl_inb((unsigned long)pll_clock->sckcr);
+       val = readb(pll_clock->sckcr);
        val |= 0x08;
-       ctrl_outb(val, (unsigned long)pll_clock->sckcr);
-       val = ctrl_inb((unsigned long)pll_clock->pllcr);
+       writeb(val, pll_clock->sckcr);
+       val = readb(pll_clock->pllcr);
        val &= ~0x03;
        val |= pll;
-       ctrl_outb(val, (unsigned long)pll_clock->pllcr);
+       writeb(val, pll_clock->pllcr);
        spin_unlock_irqrestore(&clklock, flags);
        return 0;
 }
@@ -84,7 +82,7 @@ static const struct clk_ops pll_ops = {
 
 static void __init h8s2678_pll_clk_setup(struct device_node *node)
 {
-       unsigned int num_parents;
+       int num_parents;
        struct clk *clk;
        const char *clk_name = node->name;
        const char *parent_name;
@@ -98,11 +96,9 @@ static void __init h8s2678_pll_clk_setup(struct device_node *node)
        }
 
 
-       pll_clock = kzalloc(sizeof(struct pll_clock), GFP_KERNEL);
-       if (!pll_clock) {
-               pr_err("%s: failed to alloc memory", clk_name);
+       pll_clock = kzalloc(sizeof(*pll_clock), GFP_KERNEL);
+       if (!pll_clock)
                return;
-       }
 
        pll_clock->sckcr = of_iomap(node, 0);
        if (pll_clock->sckcr == NULL) {
index b4165ba75d9f8b57157647aeca04ab04cfbb3678..2c16807341dce86b386cb662aa1a52418d311665 100644 (file)
@@ -1,6 +1,6 @@
 config COMMON_CLK_HI6220
        bool "Hi6220 Clock Driver"
-       depends on ARCH_HISI || COMPILE_TEST
+       depends on (ARCH_HISI || COMPILE_TEST) && MAILBOX
        default ARCH_HISI
        help
          Build the Hisilicon Hi6220 clock driver based on the common clock framework.
index 48f0116a032a4e0b9606107e4dec92c90ff11bd0..4a1001a11f04502d1b0b003ec5a7b3785946f313 100644 (file)
@@ -7,4 +7,4 @@ obj-y   += clk.o clkgate-separated.o clkdivider-hi6220.o
 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
-obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
+obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o clk-hi6220-stub.o
index 715d34a5ef9bc766b330726493445ffb02cfbb4d..7d03fe17d66f567cae3b69ec11b9e93279ca9dc5 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include <dt-bindings/clock/hi3620-clock.h>
 
@@ -294,34 +292,29 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
        }
 }
 
-static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p)
+static int mmc_clk_determine_rate(struct clk_hw *hw,
+                                 struct clk_rate_request *req)
 {
        struct clk_mmc *mclk = to_mmc(hw);
-       unsigned long best = 0;
 
-       if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
-               rate = 13000000;
-               best = 26000000;
-       } else if (rate <= 26000000) {
-               rate = 25000000;
-               best = 180000000;
-       } else if (rate <= 52000000) {
-               rate = 50000000;
-               best = 360000000;
-       } else if (rate <= 100000000) {
-               rate = 100000000;
-               best = 720000000;
+       if ((req->rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+               req->rate = 13000000;
+               req->best_parent_rate = 26000000;
+       } else if (req->rate <= 26000000) {
+               req->rate = 25000000;
+               req->best_parent_rate = 180000000;
+       } else if (req->rate <= 52000000) {
+               req->rate = 50000000;
+               req->best_parent_rate = 360000000;
+       } else if (req->rate <= 100000000) {
+               req->rate = 100000000;
+               req->best_parent_rate = 720000000;
        } else {
                /* max is 180M */
-               rate = 180000000;
-               best = 1440000000;
+               req->rate = 180000000;
+               req->best_parent_rate = 1440000000;
        }
-       *best_parent_rate = best;
-       return rate;
+       return -EINVAL;
 }
 
 static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
diff --git a/drivers/clk/hisilicon/clk-hi6220-stub.c b/drivers/clk/hisilicon/clk-hi6220-stub.c
new file mode 100644 (file)
index 0000000..2c4add1
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Hi6220 stub clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Author: Leo Yan <leo.yan@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mailbox_client.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+/* Stub clocks id */
+#define HI6220_STUB_ACPU0              0
+#define HI6220_STUB_ACPU1              1
+#define HI6220_STUB_GPU                        2
+#define HI6220_STUB_DDR                        5
+
+/* Mailbox message */
+#define HI6220_MBOX_MSG_LEN            8
+
+#define HI6220_MBOX_FREQ               0xA
+#define HI6220_MBOX_CMD_SET            0x3
+#define HI6220_MBOX_OBJ_AP             0x0
+
+/* CPU dynamic frequency scaling */
+#define ACPU_DFS_FREQ_MAX              0x1724
+#define ACPU_DFS_CUR_FREQ              0x17CC
+#define ACPU_DFS_FLAG                  0x1B30
+#define ACPU_DFS_FREQ_REQ              0x1B34
+#define ACPU_DFS_FREQ_LMT              0x1B38
+#define ACPU_DFS_LOCK_FLAG             0xAEAEAEAE
+
+#define to_stub_clk(hw) container_of(hw, struct hi6220_stub_clk, hw)
+
+struct hi6220_stub_clk {
+       u32 id;
+
+       struct device *dev;
+       struct clk_hw hw;
+
+       struct regmap *dfs_map;
+       struct mbox_client cl;
+       struct mbox_chan *mbox;
+};
+
+struct hi6220_mbox_msg {
+       unsigned char type;
+       unsigned char cmd;
+       unsigned char obj;
+       unsigned char src;
+       unsigned char para[4];
+};
+
+union hi6220_mbox_data {
+       unsigned int data[HI6220_MBOX_MSG_LEN];
+       struct hi6220_mbox_msg msg;
+};
+
+static unsigned int hi6220_acpu_get_freq(struct hi6220_stub_clk *stub_clk)
+{
+       unsigned int freq;
+
+       regmap_read(stub_clk->dfs_map, ACPU_DFS_CUR_FREQ, &freq);
+       return freq;
+}
+
+static int hi6220_acpu_set_freq(struct hi6220_stub_clk *stub_clk,
+                               unsigned int freq)
+{
+       union hi6220_mbox_data data;
+
+       /* set the frequency in sram */
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FREQ_REQ, freq);
+
+       /* compound mailbox message */
+       data.msg.type = HI6220_MBOX_FREQ;
+       data.msg.cmd  = HI6220_MBOX_CMD_SET;
+       data.msg.obj  = HI6220_MBOX_OBJ_AP;
+       data.msg.src  = HI6220_MBOX_OBJ_AP;
+
+       mbox_send_message(stub_clk->mbox, &data);
+       return 0;
+}
+
+static int hi6220_acpu_round_freq(struct hi6220_stub_clk *stub_clk,
+                                 unsigned int freq)
+{
+       unsigned int limit_flag, limit_freq = UINT_MAX;
+       unsigned int max_freq;
+
+       /* check the constrained frequency */
+       regmap_read(stub_clk->dfs_map, ACPU_DFS_FLAG, &limit_flag);
+       if (limit_flag == ACPU_DFS_LOCK_FLAG)
+               regmap_read(stub_clk->dfs_map, ACPU_DFS_FREQ_LMT, &limit_freq);
+
+       /* check the supported maximum frequency */
+       regmap_read(stub_clk->dfs_map, ACPU_DFS_FREQ_MAX, &max_freq);
+
+       /* calculate the real maximum frequency */
+       max_freq = min(max_freq, limit_freq);
+
+       if (WARN_ON(freq > max_freq))
+               freq = max_freq;
+
+       return freq;
+}
+
+static unsigned long hi6220_stub_clk_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       u32 rate = 0;
+       struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
+
+       switch (stub_clk->id) {
+       case HI6220_STUB_ACPU0:
+               rate = hi6220_acpu_get_freq(stub_clk);
+
+               /* convert from kHz to Hz */
+               rate *= 1000;
+               break;
+
+       default:
+               dev_err(stub_clk->dev, "%s: un-supported clock id %d\n",
+                       __func__, stub_clk->id);
+               break;
+       }
+
+       return rate;
+}
+
+static int hi6220_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
+       unsigned long new_rate = rate / 1000;  /* kHz */
+       int ret = 0;
+
+       switch (stub_clk->id) {
+       case HI6220_STUB_ACPU0:
+               ret = hi6220_acpu_set_freq(stub_clk, new_rate);
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       default:
+               dev_err(stub_clk->dev, "%s: un-supported clock id %d\n",
+                       __func__, stub_clk->id);
+               break;
+       }
+
+       pr_debug("%s: set rate=%ldkHz\n", __func__, new_rate);
+       return ret;
+}
+
+static long hi6220_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *parent_rate)
+{
+       struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
+       unsigned long new_rate = rate / 1000;  /* kHz */
+
+       switch (stub_clk->id) {
+       case HI6220_STUB_ACPU0:
+               new_rate = hi6220_acpu_round_freq(stub_clk, new_rate);
+
+               /* convert from kHz to Hz */
+               new_rate *= 1000;
+               break;
+
+       default:
+               dev_err(stub_clk->dev, "%s: un-supported clock id %d\n",
+                       __func__, stub_clk->id);
+               break;
+       }
+
+       return new_rate;
+}
+
+static const struct clk_ops hi6220_stub_clk_ops = {
+       .recalc_rate    = hi6220_stub_clk_recalc_rate,
+       .round_rate     = hi6220_stub_clk_round_rate,
+       .set_rate       = hi6220_stub_clk_set_rate,
+};
+
+static int hi6220_stub_clk_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct clk_init_data init;
+       struct hi6220_stub_clk *stub_clk;
+       struct clk *clk;
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+
+       stub_clk = devm_kzalloc(dev, sizeof(*stub_clk), GFP_KERNEL);
+       if (!stub_clk)
+               return -ENOMEM;
+
+       stub_clk->dfs_map = syscon_regmap_lookup_by_phandle(np,
+                               "hisilicon,hi6220-clk-sram");
+       if (IS_ERR(stub_clk->dfs_map)) {
+               dev_err(dev, "failed to get sram regmap\n");
+               return PTR_ERR(stub_clk->dfs_map);
+       }
+
+       stub_clk->hw.init = &init;
+       stub_clk->dev = dev;
+       stub_clk->id = HI6220_STUB_ACPU0;
+
+       /* Use mailbox client with blocking mode */
+       stub_clk->cl.dev = dev;
+       stub_clk->cl.tx_done = NULL;
+       stub_clk->cl.tx_block = true;
+       stub_clk->cl.tx_tout = 500;
+       stub_clk->cl.knows_txdone = false;
+
+       /* Allocate mailbox channel */
+       stub_clk->mbox = mbox_request_channel(&stub_clk->cl, 0);
+       if (IS_ERR(stub_clk->mbox)) {
+               dev_err(dev, "failed get mailbox channel\n");
+               return PTR_ERR(stub_clk->mbox);
+       };
+
+       init.name = "acpu0";
+       init.ops = &hi6220_stub_clk_ops;
+       init.num_parents = 0;
+       init.flags = CLK_IS_ROOT;
+
+       clk = devm_clk_register(dev, &stub_clk->hw);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       if (ret) {
+               dev_err(dev, "failed to register OF clock provider\n");
+               return ret;
+       }
+
+       /* initialize buffer to zero */
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FLAG, 0x0);
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FREQ_REQ, 0x0);
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FREQ_LMT, 0x0);
+
+       dev_dbg(dev, "Registered clock '%s'\n", init.name);
+       return 0;
+}
+
+static const struct of_device_id hi6220_stub_clk_of_match[] = {
+       { .compatible = "hisilicon,hi6220-stub-clk", },
+       {}
+};
+
+static struct platform_driver hi6220_stub_clk_driver = {
+       .driver = {
+               .name = "hi6220-stub-clk",
+               .of_match_table = hi6220_stub_clk_of_match,
+       },
+       .probe = hi6220_stub_clk_probe,
+};
+
+static int __init hi6220_stub_clk_init(void)
+{
+       return platform_driver_register(&hi6220_stub_clk_driver);
+}
+subsys_initcall(hi6220_stub_clk_init);
index 132b57a0ce09473d124e4ded7c20b3626640b3a0..8ca9673083431e5229844749f4131dd8b2008c5e 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include <dt-bindings/clock/hip04-clock.h>
 
index c90a89739b033480253641db138c99afde08be6c..9f8e76676553894ee08f4718b039c6dcaac4cfc5 100644 (file)
  */
 
 #include <linux/kernel.h>
-#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
@@ -45,14 +44,9 @@ struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
        struct clk **clk_table;
        void __iomem *base;
 
-       if (np) {
-               base = of_iomap(np, 0);
-               if (!base) {
-                       pr_err("failed to map Hisilicon clock registers\n");
-                       goto err;
-               }
-       } else {
-               pr_err("failed to find Hisilicon clock node in DTS\n");
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_err("%s: failed to map clock registers\n", __func__);
                goto err;
        }
 
index b03d5a7246f9f0806b370703a8335f816915bdff..a47812f56a17bb97d5a98521b67f1ace784ad9a4 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 75fae169ce8fa6ae9e91cf0b8b0c69d14e02cc67..1ada68abb158a08a4769d31919a83f84265ef655 100644 (file)
@@ -22,5 +22,6 @@ obj-$(CONFIG_SOC_IMX5)   += clk-imx51-imx53.o
 obj-$(CONFIG_SOC_IMX6Q)  += clk-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
+obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
index c2647fa19f281eb74f65d08553bcbe823aa59979..99cf802fa51fa28d6dba3a20a7aaf48836c75da4 100644 (file)
@@ -15,7 +15,6 @@
  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
index dba987e3b89f687c6b48488b385dd781e4122b37..e63188eb08ac9d1a0794850d8766d01fd7285f2a 100644 (file)
@@ -9,7 +9,6 @@
  * of the License, or (at your option) any later version.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index fe66c40b7be2d205af090bc42cc0346ca7c5d667..1f8383475bb369cebaf431772781fb2baf692524 100644 (file)
@@ -147,7 +147,8 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
        clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[rtc_gate], NULL, "imx21-rtc");
+       clk_register_clkdev(clk[ckil], "ref", "imx21-rtc");
+       clk_register_clkdev(clk[rtc_gate], "ipg", "imx21-rtc");
        clk_register_clkdev(clk[epit1_gate], "epit", NULL);
        clk_register_clkdev(clk[epit2_gate], "epit", NULL);
        clk_register_clkdev(clk[nfc], NULL, "imx27-nand.0");
index 69138ba3dec7056cbba6e32156fa99df1b3e2690..8623cd4e49fd5b444e2be3aff9e88fe2ade83432 100644 (file)
@@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll", "arm"};
 static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"};
 
 enum mx35_clks {
-       ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
+       ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
        arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel,
        esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre,
        spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre,
@@ -107,6 +107,7 @@ int __init mx35_clocks_init(void)
        }
 
        clk[ckih] = imx_clk_fixed("ckih", 24000000);
+       clk[ckil] = imx_clk_fixed("ckih", 32768);
        clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "mpll", "ckih", base + MX35_CCM_MPCTL);
        clk[ppll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "ppll", "ckih", base + MX35_CCM_PPCTL);
 
@@ -258,6 +259,9 @@ int __init mx35_clocks_init(void)
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.1");
        clk_register_clkdev(clk[uart3_gate], "per", "imx21-uart.2");
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.2");
+       /* i.mx35 has the i.mx21 type rtc */
+       clk_register_clkdev(clk[ckil], "ref", "imx21-rtc");
+       clk_register_clkdev(clk[rtc_gate], "ipg", "imx21-rtc");
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
        clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.0");
index d046f8e43de8d056d1af2cb1ae4bd790019d2d9a..c507bcad2c37ee4d1af6e9214f0c36769defd1a5 100644 (file)
@@ -494,6 +494,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                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]);
+
        clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
        clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
        clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
new file mode 100644 (file)
index 0000000..aaa3665
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/clock/imx6ul-clock.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+#define BM_CCM_CCDR_MMDC_CH0_MASK      (0x2 << 16)
+#define CCDR   0x4
+
+static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *ca7_secondary_sels[] = { "pll2_pfd2_396m", "pll2_bus", };
+static const char *step_sels[] = { "osc", "ca7_secondary_sel", };
+static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = {"periph", "axi_alt_sel", };
+static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
+static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", };
+static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
+static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
+static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
+static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *bch_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *gpmi_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *eim_slow_sels[] =  { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd0_720m", };
+static const char *spdif_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *sai_sels[] = { "pll3_pfd2_508m", "pll5_video_div", "pll4_audio_div", };
+static const char *lcdif_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", };
+static const char *sim_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
+static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd3_454m", "dummy", "dummy", "dummy", };
+static const char *can_sels[] = { "pll3_60m", "osc", "pll3_80m", "dummy", };
+static const char *ecspi_sels[] = { "pll3_60m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "osc", };
+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", };
+
+static struct clk *clks[IMX6UL_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int const clks_init_on[] __initconst = {
+       IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AIPSTZ3,
+       IMX6UL_CLK_AXI, IMX6UL_CLK_ARM, IMX6UL_CLK_ROM,
+       IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG,
+};
+
+static struct clk_div_table clk_enet_ref_table[] = {
+       { .val = 0, .div = 20, },
+       { .val = 1, .div = 10, },
+       { .val = 2, .div = 5, },
+       { .val = 3, .div = 4, },
+       { }
+};
+
+static struct clk_div_table post_div_table[] = {
+       { .val = 2, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 0, .div = 4, },
+       { }
+};
+
+static struct clk_div_table video_div_table[] = {
+       { .val = 0, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 2, .div = 1, },
+       { .val = 3, .div = 4, },
+       { }
+};
+
+static u32 share_count_asrc;
+static u32 share_count_audio;
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+
+static void __init imx6ul_clocks_init(struct device_node *ccm_node)
+{
+       struct device_node *np;
+       void __iomem *base;
+       int i;
+
+       clks[IMX6UL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+
+       clks[IMX6UL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+       clks[IMX6UL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+
+       /* ipp_di clock is external input */
+       clks[IMX6UL_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
+       clks[IMX6UL_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop");
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+       clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
+       clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
+       clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", base + 0x10, 0x3);
+       clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
+       clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
+       clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
+       clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+
+       clks[IMX6UL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_CLK_CSI_SEL] = imx_clk_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
+
+       /* Do not bypass PLLs initially */
+       clk_set_parent(clks[IMX6UL_PLL1_BYPASS], clks[IMX6UL_CLK_PLL1]);
+       clk_set_parent(clks[IMX6UL_PLL2_BYPASS], clks[IMX6UL_CLK_PLL2]);
+       clk_set_parent(clks[IMX6UL_PLL3_BYPASS], clks[IMX6UL_CLK_PLL3]);
+       clk_set_parent(clks[IMX6UL_PLL4_BYPASS], clks[IMX6UL_CLK_PLL4]);
+       clk_set_parent(clks[IMX6UL_PLL5_BYPASS], clks[IMX6UL_CLK_PLL5]);
+       clk_set_parent(clks[IMX6UL_PLL6_BYPASS], clks[IMX6UL_CLK_PLL6]);
+       clk_set_parent(clks[IMX6UL_PLL7_BYPASS], clks[IMX6UL_CLK_PLL7]);
+
+       clks[IMX6UL_CLK_PLL1_SYS]       = imx_clk_fixed_factor("pll1_sys",      "pll1_bypass", 1, 1);
+       clks[IMX6UL_CLK_PLL2_BUS]       = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
+       clks[IMX6UL_CLK_PLL3_USB_OTG]   = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
+       clks[IMX6UL_CLK_PLL4_AUDIO]     = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
+       clks[IMX6UL_CLK_PLL5_VIDEO]     = imx_clk_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
+       clks[IMX6UL_CLK_PLL6_ENET]      = imx_clk_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
+       clks[IMX6UL_CLK_PLL7_USB_HOST]  = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+
+       /*
+        * Bit 20 is the reserved and read-only bit, we do this only for:
+        * - Do nothing for usbphy clk_enable/disable
+        * - Keep refcount when do usbphy clk_enable/disable, in that case,
+        * the clk framework many need to enable/disable usbphy's parent
+        */
+       clks[IMX6UL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
+       clks[IMX6UL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+
+       /*
+        * usbphy*_gate needs to be on after system boots up, and software
+        * never needs to control it anymore.
+        */
+       clks[IMX6UL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+       clks[IMX6UL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+
+       /*                                      name               parent_name     reg          idx */
+       clks[IMX6UL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
+       clks[IMX6UL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
+       clks[IMX6UL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
+       clks[IMX6UL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus",     base + 0x100, 3);
+       clks[IMX6UL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
+       clks[IMX6UL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
+       clks[IMX6UL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
+       clks[IMX6UL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
+
+       clks[IMX6UL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+                       base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
+       clks[IMX6UL_CLK_ENET2_REF] = clk_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
+                       base + 0xe0, 2, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
+
+       clks[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_gate("enet_ref_125m", "enet2_ref", base + 0xe0, 20);
+       clks[IMX6UL_CLK_ENET_PTP_REF]   = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
+       clks[IMX6UL_CLK_ENET_PTP]       = imx_clk_gate("enet_ptp", "enet_ptp_ref", base + 0xe0, 21);
+
+       clks[IMX6UL_CLK_PLL4_POST_DIV]  = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX6UL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+       clks[IMX6UL_CLK_PLL5_POST_DIV]  = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX6UL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+
+       /*                                                 name         parent_name      mult  div */
+       clks[IMX6UL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1,     2);
+       clks[IMX6UL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1,     6);
+       clks[IMX6UL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1,     8);
+       clks[IMX6UL_CLK_GPT_3M]    = imx_clk_fixed_factor("gpt_3m",     "osc",           1,     8);
+
+       np = ccm_node;
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX6UL_CA7_SECONDARY_SEL]    = imx_clk_mux("ca7_secondary_sel", base + 0xc, 3, 1, ca7_secondary_sels, ARRAY_SIZE(ca7_secondary_sels));
+       clks[IMX6UL_CLK_STEP]             = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+       clks[IMX6UL_CLK_PLL1_SW]          = imx_clk_mux_flags("pll1_sw",   base + 0x0c, 2,  1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
+       clks[IMX6UL_CLK_AXI_ALT_SEL]      = imx_clk_mux("axi_alt_sel",          base + 0x14, 7,  1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+       clks[IMX6UL_CLK_AXI_SEL]          = imx_clk_mux_flags("axi_sel",        base + 0x14, 6,  1, axi_sels, ARRAY_SIZE(axi_sels), 0);
+       clks[IMX6UL_CLK_PERIPH_PRE]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+       clks[IMX6UL_CLK_PERIPH2_PRE]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+       clks[IMX6UL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+       clks[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       clks[IMX6UL_CLK_EIM_SLOW_SEL]     = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels));
+       clks[IMX6UL_CLK_GPMI_SEL]         = imx_clk_mux("gpmi_sel",     base + 0x1c, 19, 1, gpmi_sels, ARRAY_SIZE(gpmi_sels));
+       clks[IMX6UL_CLK_BCH_SEL]          = imx_clk_mux("bch_sel",      base + 0x1c, 18, 1, bch_sels, ARRAY_SIZE(bch_sels));
+       clks[IMX6UL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel",   base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6UL_CLK_USDHC1_SEL]       = imx_clk_mux("usdhc1_sel",   base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6UL_CLK_SAI3_SEL]         = imx_clk_mux("sai3_sel",     base + 0x1c, 14, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       clks[IMX6UL_CLK_SAI2_SEL]         = imx_clk_mux("sai2_sel",     base + 0x1c, 12, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       clks[IMX6UL_CLK_SAI1_SEL]         = imx_clk_mux("sai1_sel",     base + 0x1c, 10, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       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));
+       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));
+       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));
+
+       clks[IMX6UL_CLK_LDB_DI0_DIV_SEL]  = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+       clks[IMX6UL_CLK_LDB_DI1_DIV_SEL]  = imx_clk_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+
+       clks[IMX6UL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       clks[IMX6UL_CLK_LDB_DI0_DIV_7]   = imx_clk_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
+       clks[IMX6UL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "qspi1_sel", 2, 7);
+       clks[IMX6UL_CLK_LDB_DI1_DIV_7]   = imx_clk_fixed_factor("ldb_di1_div_7",   "qspi1_sel", 1, 7);
+
+       clks[IMX6UL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+       clks[IMX6UL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+       clks[IMX6UL_CLK_PERIPH_CLK2]    = imx_clk_divider("periph_clk2",   "periph_clk2_sel",   base + 0x14, 27, 3);
+       clks[IMX6UL_CLK_PERIPH2_CLK2]   = imx_clk_divider("periph2_clk2",  "periph2_clk2_sel",  base + 0x14, 0,  3);
+       clks[IMX6UL_CLK_IPG]            = imx_clk_divider("ipg",           "ahb",               base + 0x14, 8,  2);
+       clks[IMX6UL_CLK_LCDIF_PODF]     = imx_clk_divider("lcdif_podf",    "lcdif_pred",        base + 0x18, 23, 3);
+       clks[IMX6UL_CLK_QSPI1_PDOF]     = imx_clk_divider("qspi1_podf",    "qspi1_sel",         base + 0x1c, 26, 3);
+       clks[IMX6UL_CLK_EIM_SLOW_PODF]  = imx_clk_divider("eim_slow_podf", "eim_slow_sel",      base + 0x1c, 23, 3);
+       clks[IMX6UL_CLK_PERCLK]         = imx_clk_divider("perclk",        "perclk_sel",        base + 0x1c, 0,  6);
+       clks[IMX6UL_CLK_CAN_PODF]       = imx_clk_divider("can_podf",      "can_sel",           base + 0x20, 2,  6);
+       clks[IMX6UL_CLK_GPMI_PODF]      = imx_clk_divider("gpmi_podf",     "gpmi_sel",          base + 0x24, 22, 3);
+       clks[IMX6UL_CLK_BCH_PODF]       = imx_clk_divider("bch_podf",      "bch_sel",           base + 0x24, 19, 3);
+       clks[IMX6UL_CLK_USDHC2_PODF]    = imx_clk_divider("usdhc2_podf",   "usdhc2_sel",        base + 0x24, 16, 3);
+       clks[IMX6UL_CLK_USDHC1_PODF]    = imx_clk_divider("usdhc1_podf",   "usdhc1_sel",        base + 0x24, 11, 3);
+       clks[IMX6UL_CLK_UART_PODF]      = imx_clk_divider("uart_podf",     "uart_sel",          base + 0x24, 0,  6);
+       clks[IMX6UL_CLK_SAI3_PRED]      = imx_clk_divider("sai3_pred",     "sai3_sel",          base + 0x28, 22, 3);
+       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);
+       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);
+       clks[IMX6UL_CLK_SAI2_PODF]      = imx_clk_divider("sai2_podf",     "sai2_pred",         base + 0x2c, 0,  6);
+       clks[IMX6UL_CLK_SPDIF_PRED]     = imx_clk_divider("spdif_pred",    "spdif_sel",         base + 0x30, 25, 3);
+       clks[IMX6UL_CLK_SPDIF_PODF]     = imx_clk_divider("spdif_podf",    "spdif_pred",        base + 0x30, 22, 3);
+       clks[IMX6UL_CLK_SIM_PODF]       = imx_clk_divider("sim_podf",      "sim_pre_sel",       base + 0x34, 12, 3);
+       clks[IMX6UL_CLK_ECSPI_PODF]     = imx_clk_divider("ecspi_podf",    "ecspi_sel",         base + 0x38, 19, 6);
+       clks[IMX6UL_CLK_LCDIF_PRED]     = imx_clk_divider("lcdif_pred",    "lcdif_pre_sel",     base + 0x38, 12, 3);
+       clks[IMX6UL_CLK_CSI_PODF]       = imx_clk_divider("csi_podf",      "csi_sel",           base + 0x3c, 11, 3);
+
+       clks[IMX6UL_CLK_ARM]            = imx_clk_busy_divider("arm",       "pll1_sw",  base +  0x10, 0,  3,  base + 0x48, 16);
+       clks[IMX6UL_CLK_MMDC_PODF]      = imx_clk_busy_divider("mmdc_podf", "periph2",  base +  0x14, 3,  3,  base + 0x48, 2);
+       clks[IMX6UL_CLK_AXI_PODF]       = imx_clk_busy_divider("axi_podf",  "axi_sel",  base +  0x14, 16, 3,  base + 0x48, 0);
+       clks[IMX6UL_CLK_AHB]            = imx_clk_busy_divider("ahb",       "periph",   base +  0x14, 10, 3,  base + 0x48, 1);
+
+       /* CCGR0 */
+       clks[IMX6UL_CLK_AIPSTZ1]        = imx_clk_gate2("aips_tz1",     "ahb",          base + 0x68,    0);
+       clks[IMX6UL_CLK_AIPSTZ2]        = imx_clk_gate2("aips_tz2",     "ahb",          base + 0x68,    2);
+       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);
+       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);
+       clks[IMX6UL_CLK_CAN2_SERIAL]    = imx_clk_gate2("can2_serial",  "can_podf",     base + 0x68,    20);
+       clks[IMX6UL_CLK_GPT2_BUS]       = imx_clk_gate2("gpt_bus",      "perclk",       base + 0x68,    24);
+       clks[IMX6UL_CLK_GPT2_SERIAL]    = imx_clk_gate2("gpt_serial",   "perclk",       base + 0x68,    26);
+       clks[IMX6UL_CLK_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);
+
+       /* CCGR1 */
+       clks[IMX6UL_CLK_ECSPI1]         = imx_clk_gate2("ecspi1",       "ecspi_podf",   base + 0x6c,    0);
+       clks[IMX6UL_CLK_ECSPI2]         = imx_clk_gate2("ecspi2",       "ecspi_podf",   base + 0x6c,    2);
+       clks[IMX6UL_CLK_ECSPI3]         = imx_clk_gate2("ecspi3",       "ecspi_podf",   base + 0x6c,    4);
+       clks[IMX6UL_CLK_ECSPI4]         = imx_clk_gate2("ecspi4",       "ecspi_podf",   base + 0x6c,    6);
+       clks[IMX6UL_CLK_ADC2]           = imx_clk_gate2("adc2",         "ipg",          base + 0x6c,    8);
+       clks[IMX6UL_CLK_UART3_IPG]      = imx_clk_gate2("uart3_ipg",    "ipg",          base + 0x6c,    10);
+       clks[IMX6UL_CLK_UART3_SERIAL]   = imx_clk_gate2("uart3_serial", "uart_podf",    base + 0x6c,    10);
+       clks[IMX6UL_CLK_EPIT1]          = imx_clk_gate2("epit1",        "perclk",       base + 0x6c,    12);
+       clks[IMX6UL_CLK_EPIT2]          = imx_clk_gate2("epit2",        "perclk",       base + 0x6c,    14);
+       clks[IMX6UL_CLK_ADC1]           = imx_clk_gate2("adc1",         "ipg",          base + 0x6c,    16);
+       clks[IMX6UL_CLK_GPT1_BUS]       = imx_clk_gate2("gpt1_bus",     "perclk",       base + 0x6c,    20);
+       clks[IMX6UL_CLK_GPT1_SERIAL]    = imx_clk_gate2("gpt1_serial",  "perclk",       base + 0x6c,    22);
+       clks[IMX6UL_CLK_UART4_IPG]      = imx_clk_gate2("uart4_ipg",    "ipg",          base + 0x6c,    24);
+       clks[IMX6UL_CLK_UART4_SERIAL]   = imx_clk_gate2("uart4_serail", "uart_podf",    base + 0x6c,    24);
+
+       /* CCGR2 */
+       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);
+       clks[IMX6UL_CLK_I2C3]           = imx_clk_gate2("i2c3",         "perclk",       base + 0x70,    10);
+       clks[IMX6UL_CLK_OCOTP]          = imx_clk_gate2("ocotp",        "ipg",          base + 0x70,    12);
+       clks[IMX6UL_CLK_IOMUXC]         = imx_clk_gate2("iomuxc",       "lcdif_podf",   base + 0x70,    14);
+       clks[IMX6UL_CLK_LCDIF_APB]      = imx_clk_gate2("lcdif_apb",    "axi",          base + 0x70,    28);
+       clks[IMX6UL_CLK_PXP]            = imx_clk_gate2("pxp",          "axi",          base + 0x70,    30);
+
+       /* 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);
+       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);
+       clks[IMX6UL_CLK_QSPI]           = imx_clk_gate2("qspi1",        "qspi1_podf",   base + 0x74,    14);
+       clks[IMX6UL_CLK_WDOG1]          = imx_clk_gate2("wdog1",        "ipg",          base + 0x74,    16);
+       clks[IMX6UL_CLK_MMDC_P0_FAST]   = imx_clk_gate("mmdc_p0_fast", "mmdc_podf", base + 0x74,        20);
+       clks[IMX6UL_CLK_MMDC_P0_IPG]    = imx_clk_gate2("mmdc_p0_ipg",  "ipg",          base + 0x74,    24);
+       clks[IMX6UL_CLK_AXI]            = imx_clk_gate("axi",   "axi_podf",     base + 0x74,    28);
+
+       /* CCGR4 */
+       clks[IMX6UL_CLK_PER_BCH]        = imx_clk_gate2("per_bch",      "bch_podf",     base + 0x78,    12);
+       clks[IMX6UL_CLK_PWM1]           = imx_clk_gate2("pwm1",         "perclk",       base + 0x78,    16);
+       clks[IMX6UL_CLK_PWM2]           = imx_clk_gate2("pwm2",         "perclk",       base + 0x78,    18);
+       clks[IMX6UL_CLK_PWM3]           = imx_clk_gate2("pwm3",         "perclk",       base + 0x78,    20);
+       clks[IMX6UL_CLK_PWM4]           = imx_clk_gate2("pwm4",         "perclk",       base + 0x78,    22);
+       clks[IMX6UL_CLK_GPMI_BCH_APB]   = imx_clk_gate2("gpmi_bch_apb", "bch_podf",     base + 0x78,    24);
+       clks[IMX6UL_CLK_GPMI_BCH]       = imx_clk_gate2("gpmi_bch",     "gpmi_podf",    base + 0x78,    26);
+       clks[IMX6UL_CLK_GPMI_IO]        = imx_clk_gate2("gpmi_io",      "enfc_podf",    base + 0x78,    28);
+       clks[IMX6UL_CLK_GPMI_APB]       = imx_clk_gate2("gpmi_apb",     "bch_podf",     base + 0x78,    30);
+
+       /* CCGR5 */
+       clks[IMX6UL_CLK_ROM]            = imx_clk_gate2("rom",          "ahb",          base + 0x7c,    0);
+       clks[IMX6UL_CLK_SDMA]           = imx_clk_gate2("sdma",         "ahb",          base + 0x7c,    6);
+       clks[IMX6UL_CLK_WDOG2]          = imx_clk_gate2("wdog2",        "ipg",          base + 0x7c,    10);
+       clks[IMX6UL_CLK_SPBA]           = imx_clk_gate2("spba",         "ipg",          base + 0x7c,    12);
+       clks[IMX6UL_CLK_SPDIF]          = imx_clk_gate2_shared("spdif",         "spdif_podf",   base + 0x7c,    14, &share_count_audio);
+       clks[IMX6UL_CLK_SPDIF_GCLK]     = imx_clk_gate2_shared("spdif_gclk",    "ipg",          base + 0x7c,    14, &share_count_audio);
+       clks[IMX6UL_CLK_SAI3]           = imx_clk_gate2_shared("sai3",          "sai3_podf",    base + 0x7c,    22, &share_count_sai3);
+       clks[IMX6UL_CLK_SAI3_IPG]       = imx_clk_gate2_shared("sai3_ipg",      "ipg",          base + 0x7c,    22, &share_count_sai3);
+       clks[IMX6UL_CLK_UART1_IPG]      = imx_clk_gate2("uart1_ipg",    "ipg",          base + 0x7c,    24);
+       clks[IMX6UL_CLK_UART1_SERIAL]   = imx_clk_gate2("uart1_serial", "uart_podf",    base + 0x7c,    24);
+       clks[IMX6UL_CLK_UART7_IPG]      = imx_clk_gate2("uart7_ipg",    "ipg",          base + 0x7c,    26);
+       clks[IMX6UL_CLK_UART7_SERIAL]   = imx_clk_gate2("uart7_serial", "uart_podf",    base + 0x7c,    26);
+       clks[IMX6UL_CLK_SAI1]           = imx_clk_gate2_shared("sai1",          "sai1_podf",    base + 0x7c,    28, &share_count_sai1);
+       clks[IMX6UL_CLK_SAI1_IPG]       = imx_clk_gate2_shared("sai1_ipg",      "ipg",          base + 0x7c,    28, &share_count_sai1);
+       clks[IMX6UL_CLK_SAI2]           = imx_clk_gate2_shared("sai2",          "sai2_podf",    base + 0x7c,    30, &share_count_sai2);
+       clks[IMX6UL_CLK_SAI2_IPG]       = imx_clk_gate2_shared("sai2_ipg",      "ipg",          base + 0x7c,    30, &share_count_sai2);
+
+       /* CCGR6 */
+       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);
+       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);
+       clks[IMX6UL_CLK_UART8_SERIAL]   = imx_clk_gate2("uart8_serial", "uart_podf",     base + 0x80,   14);
+       clks[IMX6UL_CLK_WDOG3]          = imx_clk_gate2("wdog3",        "ipg",           base + 0x80,   20);
+       clks[IMX6UL_CLK_I2C4]           = imx_clk_gate2("i2c4",         "perclk",        base + 0x80,   24);
+       clks[IMX6UL_CLK_PWM5]           = imx_clk_gate2("pwm5",         "perclk",        base + 0x80,   26);
+       clks[IMX6UL_CLK_PWM6]           = imx_clk_gate2("pwm6",         "perclk",        base + 0x80,   28);
+       clks[IMX6UL_CLK_PWM7]           = imx_clk_gate2("Pwm7",         "perclk",        base + 0x80,   30);
+
+       /* mask handshake of mmdc */
+       writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               if (IS_ERR(clks[i]))
+                       pr_err("i.MX6UL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+
+       clk_data.clks = clks;
+       clk_data.clk_num = ARRAY_SIZE(clks);
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+       /* set perclk to from OSC */
+       clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
+
+       clk_set_rate(clks[IMX6UL_CLK_ENET_REF], 50000000);
+       clk_set_rate(clks[IMX6UL_CLK_ENET2_REF], 50000000);
+       clk_set_rate(clks[IMX6UL_CLK_CSI], 24000000);
+
+       /* keep all the clks on just for bringup */
+       for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+               clk_prepare_enable(clks[clks_init_on[i]]);
+
+       if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+               clk_prepare_enable(clks[IMX6UL_CLK_USBPHY1_GATE]);
+               clk_prepare_enable(clks[IMX6UL_CLK_USBPHY2_GATE]);
+       }
+
+       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]);
+
+       clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
+}
+
+CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
index 0b0f6f66ec56b680219bdcad3e550670e7130131..04a3e78ea1bc3254b6cd00ef429c00d234f50fd2 100644 (file)
@@ -10,7 +10,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/slab.h>
index c34ad8a611dd53e6f1465a82e8ad1c1f783b93f7..8564e4342c7d1fa115c1b5f9043bf6bbb8d6e70d 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/slab.h>
index f0d15fb9d7836d7de34338d31b1edb4fe69923cd..6addf8f58b975d9696f91e003b4775afa0da4397 100644 (file)
@@ -10,7 +10,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/io.h>
index b936cdd1a13c2d0254a6f5ef166caa49fe687113..7cfb7b2a2ed65bc9bb0e40abab245e12d3398ba1 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/delay.h>
index 86f1e362eafb8e29c02fae393620d39d32278529..aed5af23895be786db801a2d11360fa3e4a63f2b 100644 (file)
@@ -10,7 +10,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 4a375ead70e9f2c58c1eb6aaced07ea39e579b7b..3f553d0ae0b5f885d3cee60c9f673870684f83fc 100644 (file)
@@ -10,7 +10,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -309,8 +308,7 @@ static void __init of_pll_mux_clk_init(struct device_node *node)
                return;
        }
 
-       parents[0] = of_clk_get_parent_name(node, 0);
-       parents[1] = of_clk_get_parent_name(node, 1);
+       of_clk_parent_fill(node, parents, 2);
        if (!parents[0] || !parents[1]) {
                pr_err("%s: missing parent clocks\n", __func__);
                return;
index 6b6780b1e9c5b55a15524a720eb2af57af225792..11e25c992948fdcc7ea00c5cfa31f0274e6dfb53 100644 (file)
 #define __DRV_CLK_GATE_H
 
 #include <linux/regmap.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
+struct clk;
+
 struct mtk_clk_gate {
        struct clk_hw   hw;
        struct regmap   *regmap;
index 08b4b849b49197973ad5f4d0c491fc0540ac5a62..07c21e44b4b3e6811753525dde3b1ba1f127bacd 100644 (file)
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index 8b6523d15fb85984f5fb73304fa21803c40b730f..90eff85f4285ec10415509ba8013b63d623f94cb 100644 (file)
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
@@ -795,8 +796,9 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
 
 #define CON0_MT8173_RST_BAR    BIT(24)
 
-#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
-                       _tuner_reg, _pcw_reg, _pcw_shift) { \
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,  \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift, _div_table) {                       \
                .id = _id,                                              \
                .name = _name,                                          \
                .reg = _reg,                                            \
@@ -811,14 +813,31 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
                .tuner_reg = _tuner_reg,                                \
                .pcw_reg = _pcw_reg,                                    \
                .pcw_shift = _pcw_shift,                                \
+               .div_table = _div_table,                                \
        }
 
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,    \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift)                                     \
+               PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
+                       NULL)
+
+static const struct mtk_pll_div_table mmpll_div_table[] = {
+       { .div = 0, .freq = MT8173_PLL_FMAX },
+       { .div = 1, .freq = 1000000000 },
+       { .div = 2, .freq = 702000000 },
+       { .div = 3, .freq = 253500000 },
+       { .div = 4, .freq = 126750000 },
+       { } /* sentinel */
+};
+
 static const struct mtk_pll_data plls[] = {
        PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
        PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
        PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
        PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
-       PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+       PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0, mmpll_div_table),
        PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
        PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
        PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
index 9dda9d8ad10b0164bc5e15611659f6eda6f06ab8..c5cbecb3d218c3d33e116db2d814819987067e8d 100644 (file)
 
 #include <linux/regmap.h>
 #include <linux/bitops.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
+struct clk;
+
 #define MAX_MUX_GATE_BIT       31
 #define INVALID_MUX_GATE_BIT   (MAX_MUX_GATE_BIT + 1)
 
@@ -134,6 +135,11 @@ struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
 
 #define HAVE_RST_BAR   BIT(0)
 
+struct mtk_pll_div_table {
+       u32 div;
+       unsigned long freq;
+};
+
 struct mtk_pll_data {
        int id;
        const char *name;
@@ -150,6 +156,7 @@ struct mtk_pll_data {
        int pcwbits;
        uint32_t pcw_reg;
        int pcw_shift;
+       const struct mtk_pll_div_table *div_table;
 };
 
 void __init mtk_clk_register_plls(struct device_node *node,
index 44409e98c52f5b112889a6458189cad87a5f2898..622e7b6c62b42893f1c4c98574a492eed361130e 100644 (file)
@@ -90,20 +90,23 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
 static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
                int postdiv)
 {
-       u32 con1, pd, val;
+       u32 con1, val;
        int pll_en;
 
-       /* set postdiv */
-       pd = readl(pll->pd_addr);
-       pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
-       pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
-       writel(pd, pll->pd_addr);
-
        pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
 
-       /* set pcw */
-       val = readl(pll->pcw_addr);
+       /* set postdiv */
+       val = readl(pll->pd_addr);
+       val &= ~(POSTDIV_MASK << pll->data->pd_shift);
+       val |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+
+       /* postdiv and pcw need to set at the same time if on same register */
+       if (pll->pd_addr != pll->pcw_addr) {
+               writel(val, pll->pd_addr);
+               val = readl(pll->pcw_addr);
+       }
 
+       /* set pcw */
        val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
                        pll->data->pcw_shift);
        val |= pcw << pll->data->pcw_shift;
@@ -135,16 +138,28 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
                u32 freq, u32 fin)
 {
        unsigned long fmin = 1000 * MHZ;
+       const struct mtk_pll_div_table *div_table = pll->data->div_table;
        u64 _pcw;
        u32 val;
 
        if (freq > pll->data->fmax)
                freq = pll->data->fmax;
 
-       for (val = 0; val < 4; val++) {
+       if (div_table) {
+               if (freq > div_table[0].freq)
+                       freq = div_table[0].freq;
+
+               for (val = 0; div_table[val + 1].freq != 0; val++) {
+                       if (freq > div_table[val + 1].freq)
+                               break;
+               }
                *postdiv = 1 << val;
-               if (freq * *postdiv >= fmin)
-                       break;
+       } else {
+               for (val = 0; val < 5; val++) {
+                       *postdiv = 1 << val;
+                       if ((u64)freq * *postdiv >= fmin)
+                               break;
+               }
        }
 
        /* _pcw = freq * postdiv / fin * 2^pcwfbits */
index 71ad493b94df0cbb344b9e259c0c77304074f143..f7c30ea54ca8d85625b8bc33c5c772dd2700e0dd 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #define MESON_CPU_CLK_CNTL1            0x00
index b8c511c5e7a7e4c4aa2d04b94777ec907dd49b2a..c83ae1367abc1791618b858fe3544211c12dfaaf 100644 (file)
@@ -15,7 +15,6 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/syscon.h>
 #include <linux/slab.h>
index 09d41c717c52830efd22849100deb01e9f9252fb..4c717db05f2deb61a4519c7b112d3c75199371fe 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
index cdcf2d7f321e0d5becfaa90b199d9839bcc9d81a..47b5542ce50f3ec8c356eeb4bdbf9c580f207bfd 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
index adbd9d64ded2b149f5b7411cf788de0459ed6542..d20cd3431ac27547121d8bc6412c460a45b1ff10 100644 (file)
@@ -27,7 +27,6 @@
 static int mmp_clk_gate_enable(struct clk_hw *hw)
 {
        struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
-       struct clk *clk = hw->clk;
        unsigned long flags = 0;
        unsigned long rate;
        u32 tmp;
@@ -44,7 +43,7 @@ static int mmp_clk_gate_enable(struct clk_hw *hw)
                spin_unlock_irqrestore(gate->lock, flags);
 
        if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
-               rate = __clk_get_rate(clk);
+               rate = clk_hw_get_rate(hw);
                /* Need delay 2 cycles. */
                udelay(2000000/rate);
        }
index de6a873175d2b833f64d95f8e2bf5729da6fd1b4..c554833cffc509a8d2e120c4af5873b8100e3018 100644 (file)
@@ -63,7 +63,7 @@ static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
 
 static unsigned int _get_mux(struct mmp_clk_mix *mix, unsigned int val)
 {
-       int num_parents = __clk_get_num_parents(mix->hw.clk);
+       int num_parents = clk_hw_get_num_parents(&mix->hw);
        int i;
 
        if (mix->mux_flags & CLK_MUX_INDEX_BIT)
@@ -113,15 +113,15 @@ static void _filter_clk_table(struct mmp_clk_mix *mix,
 {
        int i;
        struct mmp_clk_mix_clk_table *item;
-       struct clk *parent, *clk;
+       struct clk_hw *parent, *hw;
        unsigned long parent_rate;
 
-       clk = mix->hw.clk;
+       hw = &mix->hw;
 
        for (i = 0; i < table_size; i++) {
                item = &table[i];
-               parent = clk_get_parent_by_index(clk, item->parent_index);
-               parent_rate = __clk_get_rate(parent);
+               parent = clk_hw_get_parent_by_index(hw, item->parent_index);
+               parent_rate = clk_hw_get_rate(parent);
                if (parent_rate % item->rate) {
                        item->valid = 0;
                } else {
@@ -181,7 +181,7 @@ static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val,
 
                if (timeout == 0) {
                        pr_err("%s:%s cannot do frequency change\n",
-                               __func__, __clk_get_name(mix->hw.clk));
+                               __func__, clk_hw_get_name(&mix->hw));
                        ret = -EBUSY;
                        goto error;
                }
@@ -201,27 +201,22 @@ error:
        return ret;
 }
 
-static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
        struct mmp_clk_mix *mix = to_clk_mix(hw);
        struct mmp_clk_mix_clk_table *item;
-       struct clk *parent, *parent_best, *mix_clk;
+       struct clk_hw *parent, *parent_best;
        unsigned long parent_rate, mix_rate, mix_rate_best, parent_rate_best;
        unsigned long gap, gap_best;
        u32 div_val_max;
        unsigned int div;
        int i, j;
 
-       mix_clk = hw->clk;
 
-       parent = NULL;
        mix_rate_best = 0;
        parent_rate_best = 0;
-       gap_best = rate;
+       gap_best = ULONG_MAX;
        parent_best = NULL;
 
        if (mix->table) {
@@ -229,11 +224,11 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
                        item = &mix->table[i];
                        if (item->valid == 0)
                                continue;
-                       parent = clk_get_parent_by_index(mix_clk,
+                       parent = clk_hw_get_parent_by_index(hw,
                                                        item->parent_index);
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
                        mix_rate = parent_rate / item->divisor;
-                       gap = abs(mix_rate - rate);
+                       gap = abs(mix_rate - req->rate);
                        if (parent_best == NULL || gap < gap_best) {
                                parent_best = parent;
                                parent_rate_best = parent_rate;
@@ -244,14 +239,14 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
                        }
                }
        } else {
-               for (i = 0; i < __clk_get_num_parents(mix_clk); i++) {
-                       parent = clk_get_parent_by_index(mix_clk, i);
-                       parent_rate = __clk_get_rate(parent);
+               for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+                       parent = clk_hw_get_parent_by_index(hw, i);
+                       parent_rate = clk_hw_get_rate(parent);
                        div_val_max = _get_maxdiv(mix);
                        for (j = 0; j < div_val_max; j++) {
                                div = _get_div(mix, j);
                                mix_rate = parent_rate / div;
-                               gap = abs(mix_rate - rate);
+                               gap = abs(mix_rate - req->rate);
                                if (parent_best == NULL || gap < gap_best) {
                                        parent_best = parent;
                                        parent_rate_best = parent_rate;
@@ -265,10 +260,14 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
        }
 
 found:
-       *best_parent_rate = parent_rate_best;
-       *best_parent_clk = __clk_get_hw(parent_best);
+       if (!parent_best)
+               return -EINVAL;
+
+       req->best_parent_rate = parent_rate_best;
+       req->best_parent_hw = parent_best;
+       req->rate = mix_rate_best;
 
-       return mix_rate_best;
+       return 0;
 }
 
 static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
@@ -381,20 +380,19 @@ static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        struct mmp_clk_mix_clk_table *item;
        unsigned long parent_rate;
        unsigned int best_divisor;
-       struct clk *mix_clk, *parent;
+       struct clk_hw *parent;
        int i;
 
        best_divisor = best_parent_rate / rate;
 
-       mix_clk = hw->clk;
        if (mix->table) {
                for (i = 0; i < mix->table_size; i++) {
                        item = &mix->table[i];
                        if (item->valid == 0)
                                continue;
-                       parent = clk_get_parent_by_index(mix_clk,
+                       parent = clk_hw_get_parent_by_index(hw,
                                                        item->parent_index);
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
                        if (parent_rate == best_parent_rate
                                && item->divisor == best_divisor)
                                break;
@@ -407,13 +405,13 @@ static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
                else
                        return -EINVAL;
        } else {
-               for (i = 0; i < __clk_get_num_parents(mix_clk); i++) {
-                       parent = clk_get_parent_by_index(mix_clk, i);
-                       parent_rate = __clk_get_rate(parent);
+               for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+                       parent = clk_hw_get_parent_by_index(hw, i);
+                       parent_rate = clk_hw_get_rate(parent);
                        if (parent_rate == best_parent_rate)
                                break;
                }
-               if (i < __clk_get_num_parents(mix_clk))
+               if (i < clk_hw_get_num_parents(hw))
                        return _set_rate(mix, _get_mux_val(mix, i),
                                        _get_div_val(mix, best_divisor), 1, 1);
                else
@@ -468,20 +466,20 @@ struct clk *mmp_clk_register_mix(struct device *dev,
        memcpy(&mix->reg_info, &config->reg_info, sizeof(config->reg_info));
        if (config->table) {
                table_bytes = sizeof(*config->table) * config->table_size;
-               mix->table = kzalloc(table_bytes, GFP_KERNEL);
+               mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL);
                if (!mix->table) {
                        pr_err("%s:%s: could not allocate mmp mix table\n",
                                __func__, name);
                        kfree(mix);
                        return ERR_PTR(-ENOMEM);
                }
-               memcpy(mix->table, config->table, table_bytes);
                mix->table_size = config->table_size;
        }
 
        if (config->mux_table) {
                table_bytes = sizeof(u32) * num_parents;
-               mix->mux_table = kzalloc(table_bytes, GFP_KERNEL);
+               mix->mux_table = kmemdup(config->mux_table, table_bytes,
+                                        GFP_KERNEL);
                if (!mix->mux_table) {
                        pr_err("%s:%s: could not allocate mmp mix mux-table\n",
                                __func__, name);
@@ -489,7 +487,6 @@ struct clk *mmp_clk_register_mix(struct device *dev,
                        kfree(mix);
                        return ERR_PTR(-ENOMEM);
                }
-               memcpy(mix->mux_table, config->mux_table, table_bytes);
        }
 
        mix->div_flags = config->div_flags;
index cf038ef54c5961f9764f1540eca0f717c14a172a..61893fe73251b41048ed1aebee177ca605c91cdc 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 3821a88077eaf5489f4d6e3be3d293fd6f0ca5f8..5837eb8a212fbdcd8446ff9da77f393cc05c128a 100644 (file)
@@ -10,7 +10,8 @@
  * warranty of any kind, whether express or implied.
  */
 #include <linux/kernel.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/io.h>
@@ -120,7 +121,7 @@ static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
        if (!cpuclk->pmu_dfs)
                return -ENODEV;
 
-       cur_rate = __clk_get_rate(hwclk->clk);
+       cur_rate = clk_hw_get_rate(hwclk);
 
        reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET);
        fabric_div = (reg >> SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT) &
@@ -196,7 +197,6 @@ static void __init of_cpu_clk_setup(struct device_node *node)
        for_each_node_by_type(dn, "cpu") {
                struct clk_init_data init;
                struct clk *clk;
-               struct clk *parent_clk;
                char *clk_name = kzalloc(5, GFP_KERNEL);
                int cpu, err;
 
@@ -208,9 +208,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
                        goto bail_out;
 
                sprintf(clk_name, "cpu%d", cpu);
-               parent_clk = of_clk_get(node, 0);
 
-               cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
+               cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0);
                cpuclk[cpu].clk_name = clk_name;
                cpuclk[cpu].cpu = cpu;
                cpuclk[cpu].reg_base = clock_complex_base;
index 15b370ff37481a61e4351377793d5619e14a6cd8..4a22429cd7a23b4171f825062ac96abc0f34d311 100644 (file)
@@ -13,8 +13,8 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 90e1da93877e6286fca36ab99ac5959ca6b0e75c..049ee27d5a22e680fad65c689a69813086d157e8 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/slab.h>
index e6aa6b567d6803295976a6d9f6a5206898a2189a..73f0240569ac0733d0312a3627d891d454f98ec5 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 32216f9b7f03e9b5540106d29c842cd68cf9b60a..f01876af6bb8b317bfcbcf53e3aef39d81bb0876 100644 (file)
@@ -9,9 +9,8 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk/mxs.h>
-#include <linux/clkdev.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/init.h>
index a68670868baacd42686b4ce61471838b02ee4905..6b572b759f9a38c71469faf1e09da19c9a964ac1 100644 (file)
@@ -9,9 +9,9 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/init.h>
index fadae41833ec0acef838ce55e671f7675c42f586..d4ca79a868e060da71c19a7e89d8531ac47b1990 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
index 4adeed6c2f9461a7012742fef335370d11322bd1..495f99b7965ea3a589eb7c2b3103cdb2f39d9ed4 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
index f07d821dd75d5d4a9318d5976c6c84938e3420f9..a4590956d2a28863565549b7e4b4ed0a40d7a66e 100644 (file)
@@ -12,7 +12,8 @@
 #ifndef __MXS_CLK_H
 #define __MXS_CLK_H
 
-#include <linux/clk.h>
+struct clk;
+
 #include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 
index 81e9e1c788f41f70fbd5b99bbbbf8489bd59d8a4..e0a3cb8970ab5b68e24dbb2fbcbb45f13d0ae0b3 100644 (file)
@@ -8,7 +8,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
index 8c0fe8828f9938d8e6491e430c33154cdcda3565..c4ceb5eaf46c16d281f8ce1c3e6334262a2db083 100644 (file)
@@ -159,9 +159,15 @@ PNAME(mux_debug) = { "mips_pll_mux", "rpu_v_pll_mux",
                     "wifi_pll_mux", "bt_pll_mux" };
 static u32 mux_debug_idx[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10 };
 
-static unsigned int pistachio_critical_clks[] __initdata = {
-       CLK_MIPS,
-       CLK_PERIPH_SYS,
+static unsigned int pistachio_critical_clks_core[] __initdata = {
+       CLK_MIPS
+};
+
+static unsigned int pistachio_critical_clks_sys[] __initdata = {
+       PERIPH_CLK_SYS,
+       PERIPH_CLK_SYS_BUS,
+       PERIPH_CLK_DDR,
+       PERIPH_CLK_ROM,
 };
 
 static void __init pistachio_clk_init(struct device_node *np)
@@ -193,8 +199,8 @@ static void __init pistachio_clk_init(struct device_node *np)
 
        pistachio_clk_register_provider(p);
 
-       pistachio_clk_force_enable(p, pistachio_critical_clks,
-                                  ARRAY_SIZE(pistachio_critical_clks));
+       pistachio_clk_force_enable(p, pistachio_critical_clks_core,
+                                  ARRAY_SIZE(pistachio_critical_clks_core));
 }
 CLK_OF_DECLARE(pistachio_clk, "img,pistachio-clk", pistachio_clk_init);
 
@@ -261,6 +267,9 @@ static void __init pistachio_clk_periph_init(struct device_node *np)
                                    ARRAY_SIZE(pistachio_periph_gates));
 
        pistachio_clk_register_provider(p);
+
+       pistachio_clk_force_enable(p, pistachio_critical_clks_sys,
+                                  ARRAY_SIZE(pistachio_critical_clks_sys));
 }
 CLK_OF_DECLARE(pistachio_clk_periph, "img,pistachio-clk-periph",
               pistachio_clk_periph_init);
index e17dada0dd21ab88fe1282b6dcc662e5e775988a..7e8daab9025bd326cc74d686d5e8f166ac775312 100644 (file)
 #define MIN_OUTPUT_FRAC                        12000000UL
 #define MAX_OUTPUT_FRAC                        1600000000UL
 
+/* Fractional PLL operating modes */
+enum pll_mode {
+       PLL_MODE_FRAC,
+       PLL_MODE_INT,
+};
+
 struct pistachio_clk_pll {
        struct clk_hw hw;
        void __iomem *base;
@@ -88,12 +94,10 @@ static inline void pll_lock(struct pistachio_clk_pll *pll)
                cpu_relax();
 }
 
-static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
+static inline u64 do_div_round_closest(u64 dividend, u64 divisor)
 {
        dividend += divisor / 2;
-       do_div(dividend, divisor);
-
-       return dividend;
+       return div64_u64(dividend, divisor);
 }
 
 static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
@@ -101,6 +105,29 @@ static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
        return container_of(hw, struct pistachio_clk_pll, hw);
 }
 
+static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw)
+{
+       struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
+       u32 val;
+
+       val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD;
+       return val ? PLL_MODE_INT : PLL_MODE_FRAC;
+}
+
+static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode)
+{
+       struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
+       u32 val;
+
+       val = pll_readl(pll, PLL_CTRL3);
+       if (mode == PLL_MODE_INT)
+               val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD;
+       else
+               val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD);
+
+       pll_writel(pll, val, PLL_CTRL3);
+}
+
 static struct pistachio_pll_rate_table *
 pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
               unsigned long fout)
@@ -136,8 +163,7 @@ static int pll_gf40lp_frac_enable(struct clk_hw *hw)
        u32 val;
 
        val = pll_readl(pll, PLL_CTRL3);
-       val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_DACPD |
-                PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
+       val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
                 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD);
        pll_writel(pll, val, PLL_CTRL3);
 
@@ -173,8 +199,8 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
        struct pistachio_pll_rate_table *params;
        int enabled = pll_gf40lp_frac_is_enabled(hw);
-       u32 val, vco, old_postdiv1, old_postdiv2;
-       const char *name = __clk_get_name(hw->clk);
+       u64 val, vco, old_postdiv1, old_postdiv2;
+       const char *name = clk_hw_get_name(hw);
 
        if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
                return -EINVAL;
@@ -183,17 +209,21 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!params || !params->refdiv)
                return -EINVAL;
 
-       vco = params->fref * params->fbdiv / params->refdiv;
+       /* calculate vco */
+       vco = params->fref;
+       vco *= (params->fbdiv << 24) + params->frac;
+       vco = div64_u64(vco, params->refdiv << 24);
+
        if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
-               pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+               pr_warn("%s: VCO %llu is out of range %lu..%lu\n", name, vco,
                        MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
 
-       val = params->fref / params->refdiv;
+       val = div64_u64(params->fref, params->refdiv);
        if (val < MIN_PFD)
-               pr_warn("%s: PFD %u is too low (min %lu)\n",
+               pr_warn("%s: PFD %llu is too low (min %lu)\n",
                        name, val, MIN_PFD);
        if (val > vco / 16)
-               pr_warn("%s: PFD %u is too high (max %u)\n",
+               pr_warn("%s: PFD %llu is too high (max %llu)\n",
                        name, val, vco / 16);
 
        val = pll_readl(pll, PLL_CTRL1);
@@ -227,6 +257,12 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
                (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
        pll_writel(pll, val, PLL_CTRL2);
 
+       /* set operating mode */
+       if (params->frac)
+               pll_frac_set_mode(hw, PLL_MODE_FRAC);
+       else
+               pll_frac_set_mode(hw, PLL_MODE_INT);
+
        if (enabled)
                pll_lock(pll);
 
@@ -237,8 +273,7 @@ static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
                                                 unsigned long parent_rate)
 {
        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
-       u32 val, prediv, fbdiv, frac, postdiv1, postdiv2;
-       u64 rate = parent_rate;
+       u64 val, prediv, fbdiv, frac, postdiv1, postdiv2, rate;
 
        val = pll_readl(pll, PLL_CTRL1);
        prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
@@ -251,7 +286,13 @@ static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
                PLL_FRAC_CTRL2_POSTDIV2_MASK;
        frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK;
 
-       rate *= (fbdiv << 24) + frac;
+       /* get operating mode (int/frac) and calculate rate accordingly */
+       rate = parent_rate;
+       if (pll_frac_get_mode(hw) == PLL_MODE_FRAC)
+               rate *= (fbdiv << 24) + frac;
+       else
+               rate *= (fbdiv << 24);
+
        rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24);
 
        return rate;
@@ -279,7 +320,7 @@ static int pll_gf40lp_laint_enable(struct clk_hw *hw)
        u32 val;
 
        val = pll_readl(pll, PLL_CTRL1);
-       val &= ~(PLL_INT_CTRL1_PD | PLL_INT_CTRL1_DSMPD |
+       val &= ~(PLL_INT_CTRL1_PD |
                 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD);
        pll_writel(pll, val, PLL_CTRL1);
 
@@ -316,7 +357,7 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
        struct pistachio_pll_rate_table *params;
        int enabled = pll_gf40lp_laint_is_enabled(hw);
        u32 val, vco, old_postdiv1, old_postdiv2;
-       const char *name = __clk_get_name(hw->clk);
+       const char *name = clk_hw_get_name(hw);
 
        if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
                return -EINVAL;
@@ -325,12 +366,12 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!params || !params->refdiv)
                return -EINVAL;
 
-       vco = params->fref * params->fbdiv / params->refdiv;
+       vco = div_u64(params->fref * params->fbdiv, params->refdiv);
        if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
                pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
                        MIN_VCO_LA, MAX_VCO_LA);
 
-       val = params->fref / params->refdiv;
+       val = div_u64(params->fref, params->refdiv);
        if (val < MIN_PFD)
                pr_warn("%s: PFD %u is too low (min %lu)\n",
                        name, val, MIN_PFD);
index 85faa83e1bd7a94fa8e4f98881a9d4add3ab4f6d..698cad4f509e70303aa17bf337fb8ea51b8a41e6 100644 (file)
@@ -6,6 +6,7 @@
  * version 2, as published by the Free Software Foundation.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
index 52fabbc24624bc5490442b10e381e752eae49887..8d45178dbde3e183e0806594e0fd1800f04076d5 100644 (file)
@@ -95,13 +95,13 @@ struct pistachio_fixed_factor {
        }
 
 struct pistachio_pll_rate_table {
-       unsigned long fref;
-       unsigned long fout;
-       unsigned int refdiv;
-       unsigned int fbdiv;
-       unsigned int postdiv1;
-       unsigned int postdiv2;
-       unsigned int frac;
+       unsigned long long fref;
+       unsigned long long fout;
+       unsigned long long refdiv;
+       unsigned long long fbdiv;
+       unsigned long long postdiv1;
+       unsigned long long postdiv2;
+       unsigned long long frac;
 };
 
 enum pistachio_pll_type {
index 6cd88d963a7ffbaa531b84f0a919b5aeef8f989d..542e45ef5087b5736e2111cfca08eb42ed7b24a3 100644 (file)
@@ -79,7 +79,7 @@ unsigned int pxa25x_get_clk_frequency_khz(int info)
                        clks[3] / 1000000, (clks[3] % 1000000) / 10000);
        }
 
-       return (unsigned int)clks[0];
+       return (unsigned int)clks[0] / KHz;
 }
 
 static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw,
index 9a31b77eed23511545f453022d9263db08b7add8..5b82d30baf9f36e9506544e554f1e79cf2b1b511 100644 (file)
@@ -80,7 +80,7 @@ unsigned int pxa27x_get_clk_frequency_khz(int info)
                pr_info("System bus clock: %ld.%02ldMHz\n",
                        clks[4] / 1000000, (clks[4] % 1000000) / 10000);
        }
-       return (unsigned int)clks[0];
+       return (unsigned int)clks[0] / KHz;
 }
 
 bool pxa27x_is_ppll_disabled(void)
index ac03ba49e9d1952dff14e9383ed86874690a7176..4af4eed5f89f03bb8affd1104de702b677326249 100644 (file)
@@ -78,7 +78,7 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info)
                pr_info("System bus clock: %ld.%02ldMHz\n",
                        clks[4] / 1000000, (clks[4] % 1000000) / 10000);
        }
-       return (unsigned int)clks[0];
+       return (unsigned int)clks[0] / KHz;
 }
 
 static unsigned long clk_pxa3xx_ac97_get_rate(struct clk_hw *hw,
index 6b4d2bcb1a53e9830cd3059abc7dcee04f2d6e58..26f7af315066f2381d10396d6d8e5b350f370032 100644 (file)
@@ -75,7 +75,7 @@ static int clk_branch_wait(const struct clk_branch *br, bool enabling,
                bool (check_halt)(const struct clk_branch *, bool))
 {
        bool voted = br->halt_check & BRANCH_VOTED;
-       const char *name = __clk_get_name(br->clkr.hw.clk);
+       const char *name = clk_hw_get_name(&br->clkr.hw);
 
        /* Skip checking halt bit if the clock is in hardware gated mode */
        if (clk_branch_in_hwcg_mode(br))
index 245d5063a385968a5081050b7ef679f86a71b124..5b940d629045fe706707f1d6a8c92a3ef12098b5 100644 (file)
@@ -135,19 +135,19 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
        return NULL;
 }
 
-static long
-clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
-                      unsigned long min_rate, unsigned long max_rate,
-                      unsigned long *p_rate, struct clk_hw **p)
+static int
+clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
        struct clk_pll *pll = to_clk_pll(hw);
        const struct pll_freq_tbl *f;
 
-       f = find_freq(pll->freq_tbl, rate);
+       f = find_freq(pll->freq_tbl, req->rate);
        if (!f)
-               return clk_pll_recalc_rate(hw, *p_rate);
+               req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate);
+       else
+               req->rate = f->freq;
 
-       return f->freq;
+       return 0;
 }
 
 static int
@@ -194,7 +194,7 @@ static int wait_for_pll(struct clk_pll *pll)
        u32 val;
        int count;
        int ret;
-       const char *name = __clk_get_name(pll->clkr.hw.clk);
+       const char *name = clk_hw_get_name(&pll->clkr.hw);
 
        /* Wait for pll to enable. */
        for (count = 200; count > 0; count--) {
@@ -213,7 +213,7 @@ static int wait_for_pll(struct clk_pll *pll)
 static int clk_pll_vote_enable(struct clk_hw *hw)
 {
        int ret;
-       struct clk_pll *p = to_clk_pll(__clk_get_hw(__clk_get_parent(hw->clk)));
+       struct clk_pll *p = to_clk_pll(clk_hw_get_parent(hw));
 
        ret = clk_enable_regmap(hw);
        if (ret)
@@ -292,3 +292,78 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
                clk_pll_set_fsm_mode(pll, regmap, 0);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
+
+static int clk_pll_sr2_enable(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       int ret;
+       u32 mode;
+
+       ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
+       if (ret)
+               return ret;
+
+       /* Disable PLL bypass mode. */
+       ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
+                                PLL_BYPASSNL);
+       if (ret)
+               return ret;
+
+       /*
+        * H/W requires a 5us delay between disabling the bypass and
+        * de-asserting the reset. Delay 10us just to be safe.
+        */
+       udelay(10);
+
+       /* De-assert active-low PLL reset. */
+       ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
+                                PLL_RESET_N);
+       if (ret)
+               return ret;
+
+       ret = wait_for_pll(pll);
+       if (ret)
+               return ret;
+
+       /* Enable PLL output. */
+       return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
+                                PLL_OUTCTRL);
+}
+
+static int
+clk_pll_sr2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       const struct pll_freq_tbl *f;
+       bool enabled;
+       u32 mode;
+       u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
+
+       f = find_freq(pll->freq_tbl, rate);
+       if (!f)
+               return -EINVAL;
+
+       regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
+       enabled = (mode & enable_mask) == enable_mask;
+
+       if (enabled)
+               clk_pll_disable(hw);
+
+       regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
+       regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
+       regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
+
+       if (enabled)
+               clk_pll_sr2_enable(hw);
+
+       return 0;
+}
+
+const struct clk_ops clk_pll_sr2_ops = {
+       .enable = clk_pll_sr2_enable,
+       .disable = clk_pll_disable,
+       .set_rate = clk_pll_sr2_set_rate,
+       .recalc_rate = clk_pll_recalc_rate,
+       .determine_rate = clk_pll_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);
index c9c0cda306d04e45548daa0d5b50f802ab2c04a9..ffd0c63bddbc41d78e65509bd4091826a3ab5408 100644 (file)
@@ -62,6 +62,7 @@ struct clk_pll {
 
 extern const struct clk_ops clk_pll_ops;
 extern const struct clk_ops clk_pll_vote_ops;
+extern const struct clk_ops clk_pll_sr2_ops;
 
 #define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr)
 
index 7b3d62674203e4238cba23ff2eb6530f9bdac23b..bccedc4b57568bda6edafa516933fc45f8cfa439 100644 (file)
@@ -45,7 +45,7 @@ static u32 src_to_ns(struct src_sel *s, u8 src, u32 ns)
 static u8 clk_rcg_get_parent(struct clk_hw *hw)
 {
        struct clk_rcg *rcg = to_clk_rcg(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 ns;
        int i, ret;
 
@@ -59,7 +59,7 @@ static u8 clk_rcg_get_parent(struct clk_hw *hw)
 
 err:
        pr_debug("%s: Clock %s has invalid parent, using default.\n",
-                __func__, __clk_get_name(hw->clk));
+                __func__, clk_hw_get_name(hw));
        return 0;
 }
 
@@ -72,7 +72,7 @@ static int reg_to_bank(struct clk_dyn_rcg *rcg, u32 bank)
 static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
 {
        struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 ns, reg;
        int bank;
        int i, ret;
@@ -95,7 +95,7 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
 
 err:
        pr_debug("%s: Clock %s has invalid parent, using default.\n",
-                __func__, __clk_get_name(hw->clk));
+                __func__, clk_hw_get_name(hw));
        return 0;
 }
 
@@ -404,14 +404,12 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        return calc_rate(parent_rate, m, n, mode, pre_div);
 }
 
-static long _freq_tbl_determine_rate(struct clk_hw *hw,
-               const struct freq_tbl *f, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p_hw,
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+               struct clk_rate_request *req,
                const struct parent_map *parent_map)
 {
-       unsigned long clk_flags;
-       struct clk *p;
+       unsigned long clk_flags, rate = req->rate;
+       struct clk_hw *p;
        int index;
 
        f = qcom_find_freq(f, rate);
@@ -422,8 +420,8 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
        if (index < 0)
                return index;
 
-       clk_flags = __clk_get_flags(hw->clk);
-       p = clk_get_parent_by_index(hw->clk, index);
+       clk_flags = clk_hw_get_flags(hw);
+       p = clk_hw_get_parent_by_index(hw, index);
        if (clk_flags & CLK_SET_RATE_PARENT) {
                rate = rate * f->pre_div;
                if (f->n) {
@@ -433,27 +431,26 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
                        rate = tmp;
                }
        } else {
-               rate =  __clk_get_rate(p);
+               rate =  clk_hw_get_rate(p);
        }
-       *p_hw = __clk_get_hw(p);
-       *p_rate = rate;
+       req->best_parent_hw = p;
+       req->best_parent_rate = rate;
+       req->rate = f->freq;
 
-       return f->freq;
+       return 0;
 }
 
-static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p)
+static int clk_rcg_determine_rate(struct clk_hw *hw,
+                                 struct clk_rate_request *req)
 {
        struct clk_rcg *rcg = to_clk_rcg(hw);
 
-       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
-                       max_rate, p_rate, p, rcg->s.parent_map);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req,
+                                       rcg->s.parent_map);
 }
 
-static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p)
+static int clk_dyn_rcg_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
        struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
        u32 reg;
@@ -464,24 +461,22 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
        bank = reg_to_bank(rcg, reg);
        s = &rcg->s[bank];
 
-       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
-                       max_rate, p_rate, p, s->parent_map);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, s->parent_map);
 }
 
-static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p_hw)
+static int clk_rcg_bypass_determine_rate(struct clk_hw *hw,
+                                        struct clk_rate_request *req)
 {
        struct clk_rcg *rcg = to_clk_rcg(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
-       struct clk *p;
+       struct clk_hw *p;
        int index = qcom_find_src_index(hw, rcg->s.parent_map, f->src);
 
-       p = clk_get_parent_by_index(hw->clk, index);
-       *p_hw = __clk_get_hw(p);
-       *p_rate = __clk_round_rate(p, rate);
+       req->best_parent_hw = p = clk_hw_get_parent_by_index(hw, index);
+       req->best_parent_rate = clk_hw_round_rate(p, req->rate);
+       req->rate = req->best_parent_rate;
 
-       return *p_rate;
+       return 0;
 }
 
 static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
index 92936f0912d2f86622d5ae1372cf03a046b83979..9aec1761fd29e26c4c2ad0fbd7979e609c880db3 100644 (file)
@@ -63,7 +63,7 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw)
 static u8 clk_rcg2_get_parent(struct clk_hw *hw)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 cfg;
        int i, ret;
 
@@ -80,7 +80,7 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw)
 
 err:
        pr_debug("%s: Clock %s has invalid parent, using default.\n",
-                __func__, __clk_get_name(hw->clk));
+                __func__, clk_hw_get_name(hw));
        return 0;
 }
 
@@ -89,7 +89,7 @@ static int update_config(struct clk_rcg2 *rcg)
        int count, ret;
        u32 cmd;
        struct clk_hw *hw = &rcg->clkr.hw;
-       const char *name = __clk_get_name(hw->clk);
+       const char *name = clk_hw_get_name(hw);
 
        ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
                                 CMD_UPDATE, CMD_UPDATE);
@@ -176,12 +176,11 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        return calc_rate(parent_rate, m, n, mode, hid_div);
 }
 
-static long _freq_tbl_determine_rate(struct clk_hw *hw,
-               const struct freq_tbl *f, unsigned long rate,
-               unsigned long *p_rate, struct clk_hw **p_hw)
+static int _freq_tbl_determine_rate(struct clk_hw *hw,
+               const struct freq_tbl *f, struct clk_rate_request *req)
 {
-       unsigned long clk_flags;
-       struct clk *p;
+       unsigned long clk_flags, rate = req->rate;
+       struct clk_hw *p;
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        int index;
 
@@ -193,8 +192,8 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
        if (index < 0)
                return index;
 
-       clk_flags = __clk_get_flags(hw->clk);
-       p = clk_get_parent_by_index(hw->clk, index);
+       clk_flags = clk_hw_get_flags(hw);
+       p = clk_hw_get_parent_by_index(hw, index);
        if (clk_flags & CLK_SET_RATE_PARENT) {
                if (f->pre_div) {
                        rate /= 2;
@@ -208,21 +207,21 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
                        rate = tmp;
                }
        } else {
-               rate =  __clk_get_rate(p);
+               rate =  clk_hw_get_rate(p);
        }
-       *p_hw = __clk_get_hw(p);
-       *p_rate = rate;
+       req->best_parent_hw = p;
+       req->best_parent_rate = rate;
+       req->rate = f->freq;
 
-       return f->freq;
+       return 0;
 }
 
-static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p)
+static int clk_rcg2_determine_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, rate, p_rate, p);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
 }
 
 static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
@@ -374,35 +373,33 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
        return clk_edp_pixel_set_rate(hw, rate, parent_rate);
 }
 
-static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long min_rate,
-                                unsigned long max_rate,
-                                unsigned long *p_rate, struct clk_hw **p)
+static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
        const struct frac_entry *frac;
        int delta = 100000;
-       s64 src_rate = *p_rate;
        s64 request;
        u32 mask = BIT(rcg->hid_width) - 1;
        u32 hid_div;
        int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
        /* Force the correct parent */
-       *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, index));
+       req->best_parent_hw = clk_hw_get_parent_by_index(hw, index);
+       req->best_parent_rate = clk_hw_get_rate(req->best_parent_hw);
 
-       if (src_rate == 810000000)
+       if (req->best_parent_rate == 810000000)
                frac = frac_table_810m;
        else
                frac = frac_table_675m;
 
        for (; frac->num; frac++) {
-               request = rate;
+               request = req->rate;
                request *= frac->den;
                request = div_s64(request, frac->num);
-               if ((src_rate < (request - delta)) ||
-                   (src_rate > (request + delta)))
+               if ((req->best_parent_rate < (request - delta)) ||
+                   (req->best_parent_rate > (request + delta)))
                        continue;
 
                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
@@ -410,8 +407,10 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
                hid_div >>= CFG_SRC_DIV_SHIFT;
                hid_div &= mask;
 
-               return calc_rate(src_rate, frac->num, frac->den, !!frac->den,
-                                hid_div);
+               req->rate = calc_rate(req->best_parent_rate,
+                                     frac->num, frac->den,
+                                     !!frac->den, hid_div);
+               return 0;
        }
 
        return -EINVAL;
@@ -428,28 +427,28 @@ const struct clk_ops clk_edp_pixel_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
 
-static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
-                        unsigned long min_rate, unsigned long max_rate,
-                        unsigned long *p_rate, struct clk_hw **p_hw)
+static int clk_byte_determine_rate(struct clk_hw *hw,
+                                  struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
        int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
        unsigned long parent_rate, div;
        u32 mask = BIT(rcg->hid_width) - 1;
-       struct clk *p;
+       struct clk_hw *p;
 
-       if (rate == 0)
+       if (req->rate == 0)
                return -EINVAL;
 
-       p = clk_get_parent_by_index(hw->clk, index);
-       *p_hw = __clk_get_hw(p);
-       *p_rate = parent_rate = __clk_round_rate(p, rate);
+       req->best_parent_hw = p = clk_hw_get_parent_by_index(hw, index);
+       req->best_parent_rate = parent_rate = clk_hw_round_rate(p, req->rate);
 
-       div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
+       div = DIV_ROUND_UP((2 * parent_rate), req->rate) - 1;
        div = min_t(u32, div, mask);
 
-       return calc_rate(parent_rate, 0, 0, 0, div);
+       req->rate = calc_rate(parent_rate, 0, 0, 0, div);
+
+       return 0;
 }
 
 static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -494,10 +493,8 @@ static const struct frac_entry frac_table_pixel[] = {
        { }
 };
 
-static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long min_rate,
-                                unsigned long max_rate,
-                                unsigned long *p_rate, struct clk_hw **p)
+static int clk_pixel_determine_rate(struct clk_hw *hw,
+                                   struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        unsigned long request, src_rate;
@@ -505,20 +502,20 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
        const struct freq_tbl *f = rcg->freq_tbl;
        const struct frac_entry *frac = frac_table_pixel;
        int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
-       struct clk *parent = clk_get_parent_by_index(hw->clk, index);
 
-       *p = __clk_get_hw(parent);
+       req->best_parent_hw = clk_hw_get_parent_by_index(hw, index);
 
        for (; frac->num; frac++) {
-               request = (rate * frac->den) / frac->num;
+               request = (req->rate * frac->den) / frac->num;
 
-               src_rate = __clk_round_rate(parent, request);
+               src_rate = clk_hw_round_rate(req->best_parent_hw, request);
                if ((src_rate < (request - delta)) ||
                        (src_rate > (request + delta)))
                        continue;
 
-               *p_rate = src_rate;
-               return (src_rate * frac->num) / frac->den;
+               req->best_parent_rate = src_rate;
+               req->rate = (src_rate * frac->num) / frac->den;
+               return 0;
        }
 
        return -EINVAL;
index f7101e330b1dd5d1ef182155282275abc1b51405..2dedceefd21d84464f4733bdfa36fda1f3489a2b 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/export.h>
+#include <linux/module.h>
 #include <linux/regmap.h>
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
@@ -45,7 +46,7 @@ EXPORT_SYMBOL_GPL(qcom_find_freq);
 
 int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
 {
-       int i, num_parents = __clk_get_num_parents(hw->clk);
+       int i, num_parents = clk_hw_get_num_parents(hw);
 
        for (i = 0; i < num_parents; i++)
                if (src == map[i].src)
@@ -144,3 +145,5 @@ void qcom_cc_remove(struct platform_device *pdev)
        reset_controller_unregister(platform_get_drvdata(pdev));
 }
 EXPORT_SYMBOL_GPL(qcom_cc_remove);
+
+MODULE_LICENSE("GPL v2");
index 54a756b90a3742342b5babcd5f38a26dfc4df48c..3563019b8e3cefe1ac8347464297a2183ce69c34 100644 (file)
@@ -48,7 +48,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
        { P_GPLL0, 1 }
 };
 
-static const char *gcc_xo_gpll0[] = {
+static const char * const gcc_xo_gpll0[] = {
        "xo",
        "gpll0_vote",
 };
@@ -59,7 +59,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
        { P_GPLL4, 5 }
 };
 
-static const char *gcc_xo_gpll0_gpll4[] = {
+static const char * const gcc_xo_gpll0_gpll4[] = {
        "xo",
        "gpll0_vote",
        "gpll4_vote",
@@ -70,7 +70,7 @@ static const struct parent_map gcc_xo_sata_asic0_map[] = {
        { P_SATA_ASIC0_CLK, 2 }
 };
 
-static const char *gcc_xo_sata_asic0[] = {
+static const char * const gcc_xo_sata_asic0[] = {
        "xo",
        "sata_asic0_clk",
 };
@@ -80,7 +80,7 @@ static const struct parent_map gcc_xo_sata_rx_map[] = {
        { P_SATA_RX_CLK, 2}
 };
 
-static const char *gcc_xo_sata_rx[] = {
+static const char * const gcc_xo_sata_rx[] = {
        "xo",
        "sata_rx_clk",
 };
@@ -90,7 +90,7 @@ static const struct parent_map gcc_xo_pcie_map[] = {
        { P_PCIE_0_1_PIPE_CLK, 2 }
 };
 
-static const char *gcc_xo_pcie[] = {
+static const char * const gcc_xo_pcie[] = {
        "xo",
        "pcie_pipe",
 };
@@ -100,7 +100,7 @@ static const struct parent_map gcc_xo_pcie_sleep_map[] = {
        { P_SLEEP_CLK, 6 }
 };
 
-static const char *gcc_xo_pcie_sleep[] = {
+static const char * const gcc_xo_pcie_sleep[] = {
        "xo",
        "sleep_clk_src",
 };
@@ -2105,6 +2105,7 @@ static struct clk_branch gcc_ce1_clk = {
                                "ce1_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
index 563969942a1df2bee95ef9164b7f4fce509a2229..40e480220cd3fb60206a5d8f5bbbf5aba10c3ac9 100644 (file)
@@ -188,7 +188,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = {
        { P_PLL8, 3 }
 };
 
-static const char *gcc_pxo_pll8[] = {
+static const char * const gcc_pxo_pll8[] = {
        "pxo",
        "pll8_vote",
 };
@@ -199,7 +199,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
        { P_CXO, 5 }
 };
 
-static const char *gcc_pxo_pll8_cxo[] = {
+static const char * const gcc_pxo_pll8_cxo[] = {
        "pxo",
        "pll8_vote",
        "cxo",
@@ -215,7 +215,7 @@ static const struct parent_map gcc_pxo_pll3_sata_map[] = {
        { P_PLL3, 6 }
 };
 
-static const char *gcc_pxo_pll3[] = {
+static const char * const gcc_pxo_pll3[] = {
        "pxo",
        "pll3",
 };
@@ -226,7 +226,7 @@ static const struct parent_map gcc_pxo_pll8_pll0[] = {
        { P_PLL0, 2 }
 };
 
-static const char *gcc_pxo_pll8_pll0_map[] = {
+static const char * const gcc_pxo_pll8_pll0_map[] = {
        "pxo",
        "pll8_vote",
        "pll0_vote",
@@ -240,7 +240,7 @@ static const struct parent_map gcc_pxo_pll8_pll14_pll18_pll0_map[] = {
        { P_PLL18, 1 }
 };
 
-static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = {
+static const char * const gcc_pxo_pll8_pll14_pll18_pll0[] = {
        "pxo",
        "pll8_vote",
        "pll0_vote",
index fc6b12da5b306916b771583334ebaf39b9a0336c..b02826ed770a25f474e37922133c7e0ead56c8d0 100644 (file)
@@ -70,7 +70,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = {
        { P_PLL8, 3 }
 };
 
-static const char *gcc_pxo_pll8[] = {
+static const char * const gcc_pxo_pll8[] = {
        "pxo",
        "pll8_vote",
 };
@@ -81,7 +81,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
        { P_CXO, 5 }
 };
 
-static const char *gcc_pxo_pll8_cxo[] = {
+static const char * const gcc_pxo_pll8_cxo[] = {
        "pxo",
        "pll8_vote",
        "cxo",
@@ -1917,7 +1917,7 @@ static struct clk_rcg usb_fs1_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
+static const char * const usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
 
 static struct clk_branch usb_fs1_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
@@ -1984,7 +1984,7 @@ static struct clk_rcg usb_fs2_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
+static const char * const usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
 
 static struct clk_branch usb_fs2_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
index c66f7bc2ae87cde429121af226970c2c7fd973c4..22a4e1e732c0a3cddc38bb20f1beeb97052ce733 100644 (file)
@@ -51,7 +51,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
        { P_GPLL0, 1 },
 };
 
-static const char *gcc_xo_gpll0[] = {
+static const char * const gcc_xo_gpll0[] = {
        "xo",
        "gpll0_vote",
 };
@@ -62,7 +62,7 @@ static const struct parent_map gcc_xo_gpll0_bimc_map[] = {
        { P_BIMC, 2 },
 };
 
-static const char *gcc_xo_gpll0_bimc[] = {
+static const char * const gcc_xo_gpll0_bimc[] = {
        "xo",
        "gpll0_vote",
        "bimc_pll_vote",
@@ -75,7 +75,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2a_map[] = {
        { P_GPLL2_AUX, 2 },
 };
 
-static const char *gcc_xo_gpll0a_gpll1_gpll2a[] = {
+static const char * const gcc_xo_gpll0a_gpll1_gpll2a[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -88,7 +88,7 @@ static const struct parent_map gcc_xo_gpll0_gpll2_map[] = {
        { P_GPLL2, 2 },
 };
 
-static const char *gcc_xo_gpll0_gpll2[] = {
+static const char * const gcc_xo_gpll0_gpll2[] = {
        "xo",
        "gpll0_vote",
        "gpll2_vote",
@@ -99,7 +99,7 @@ static const struct parent_map gcc_xo_gpll0a_map[] = {
        { P_GPLL0_AUX, 2 },
 };
 
-static const char *gcc_xo_gpll0a[] = {
+static const char * const gcc_xo_gpll0a[] = {
        "xo",
        "gpll0_vote",
 };
@@ -111,7 +111,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_sleep_map[] = {
        { P_SLEEP_CLK, 6 },
 };
 
-static const char *gcc_xo_gpll0_gpll1a_sleep[] = {
+static const char * const gcc_xo_gpll0_gpll1a_sleep[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -124,7 +124,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_map[] = {
        { P_GPLL1_AUX, 2 },
 };
 
-static const char *gcc_xo_gpll0_gpll1a[] = {
+static const char * const gcc_xo_gpll0_gpll1a[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -135,7 +135,7 @@ static const struct parent_map gcc_xo_dsibyte_map[] = {
        { P_DSI0_PHYPLL_BYTE, 2 },
 };
 
-static const char *gcc_xo_dsibyte[] = {
+static const char * const gcc_xo_dsibyte[] = {
        "xo",
        "dsi0pllbyte",
 };
@@ -146,7 +146,7 @@ static const struct parent_map gcc_xo_gpll0a_dsibyte_map[] = {
        { P_DSI0_PHYPLL_BYTE, 1 },
 };
 
-static const char *gcc_xo_gpll0a_dsibyte[] = {
+static const char * const gcc_xo_gpll0a_dsibyte[] = {
        "xo",
        "gpll0_vote",
        "dsi0pllbyte",
@@ -158,7 +158,7 @@ static const struct parent_map gcc_xo_gpll0_dsiphy_map[] = {
        { P_DSI0_PHYPLL_DSI, 2 },
 };
 
-static const char *gcc_xo_gpll0_dsiphy[] = {
+static const char * const gcc_xo_gpll0_dsiphy[] = {
        "xo",
        "gpll0_vote",
        "dsi0pll",
@@ -170,7 +170,7 @@ static const struct parent_map gcc_xo_gpll0a_dsiphy_map[] = {
        { P_DSI0_PHYPLL_DSI, 1 },
 };
 
-static const char *gcc_xo_gpll0a_dsiphy[] = {
+static const char * const gcc_xo_gpll0a_dsiphy[] = {
        "xo",
        "gpll0_vote",
        "dsi0pll",
@@ -183,7 +183,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2_map[] = {
        { P_GPLL2, 2 },
 };
 
-static const char *gcc_xo_gpll0a_gpll1_gpll2[] = {
+static const char * const gcc_xo_gpll0a_gpll1_gpll2[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -2278,7 +2278,7 @@ static struct clk_branch gcc_prng_ahb_clk = {
        .halt_check = BRANCH_HALT_VOTED,
        .clkr = {
                .enable_reg = 0x45004,
-               .enable_mask = BIT(0),
+               .enable_mask = BIT(8),
                .hw.init = &(struct clk_init_data){
                        .name = "gcc_prng_ahb_clk",
                        .parent_names = (const char *[]){
index eb6a4f9fa107e9af98ab1991f50e22d4c8b503c5..aa294b1bad343ccbef5b4daef38cda33fd6513f1 100644 (file)
@@ -125,7 +125,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = {
        { P_PLL8, 3 }
 };
 
-static const char *gcc_pxo_pll8[] = {
+static const char * const gcc_pxo_pll8[] = {
        "pxo",
        "pll8_vote",
 };
@@ -136,7 +136,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
        { P_CXO, 5 }
 };
 
-static const char *gcc_pxo_pll8_cxo[] = {
+static const char * const gcc_pxo_pll8_cxo[] = {
        "pxo",
        "pll8_vote",
        "cxo",
@@ -148,7 +148,7 @@ static const struct parent_map gcc_pxo_pll8_pll3_map[] = {
        { P_PLL3, 6 }
 };
 
-static const char *gcc_pxo_pll8_pll3[] = {
+static const char * const gcc_pxo_pll8_pll3[] = {
        "pxo",
        "pll8_vote",
        "pll3",
@@ -2085,7 +2085,7 @@ static struct clk_rcg usb_hsic_xcvr_fs_src = {
        }
 };
 
-static const char *usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" };
+static const char * const usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" };
 
 static struct clk_branch usb_hsic_xcvr_fs_clk = {
        .halt_reg = 0x2fc8,
@@ -2181,7 +2181,7 @@ static struct clk_rcg usb_fs1_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
+static const char * const usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
 
 static struct clk_branch usb_fs1_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
@@ -2248,7 +2248,7 @@ static struct clk_rcg usb_fs2_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
+static const char * const usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
 
 static struct clk_branch usb_fs2_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
index c39d09874e74d5d05a7f59e437ce5bb1f0ef8199..2bcf87538f9d7e34700d1a2e21b366e1618d4a5e 100644 (file)
@@ -44,7 +44,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
        { P_GPLL0, 1 }
 };
 
-static const char *gcc_xo_gpll0[] = {
+static const char * const gcc_xo_gpll0[] = {
        "xo",
        "gpll0_vote",
 };
@@ -55,7 +55,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
        { P_GPLL4, 5 }
 };
 
-static const char *gcc_xo_gpll0_gpll4[] = {
+static const char * const gcc_xo_gpll0_gpll4[] = {
        "xo",
        "gpll0_vote",
        "gpll4_vote",
@@ -1783,6 +1783,7 @@ static struct clk_branch gcc_ce1_clk = {
                                "ce1_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
index 47f0ac16d149c811d9f9ceca241e0d0468d09935..93ad42b1436604be66fcbb8081932879929fd823 100644 (file)
@@ -71,7 +71,7 @@ static const struct parent_map lcc_pxo_pll4_map[] = {
        { P_PLL4, 2 }
 };
 
-static const char *lcc_pxo_pll4[] = {
+static const char * const lcc_pxo_pll4[] = {
        "pxo",
        "pll4_vote",
 };
@@ -146,7 +146,7 @@ static struct clk_rcg mi2s_osr_src = {
        },
 };
 
-static const char *lcc_mi2s_parents[] = {
+static const char * const lcc_mi2s_parents[] = {
        "mi2s_osr_src",
 };
 
@@ -340,7 +340,7 @@ static struct clk_rcg spdif_src = {
        },
 };
 
-static const char *lcc_spdif_parents[] = {
+static const char * const lcc_spdif_parents[] = {
        "spdif_src",
 };
 
index d0df9d5fc3af0a8eda7349bff0a6179a841bfa09..ecb96c2846756e78185ad9b3be6b9d8d75218edc 100644 (file)
@@ -57,7 +57,7 @@ static const struct parent_map lcc_pxo_pll4_map[] = {
        { P_PLL4, 2 }
 };
 
-static const char *lcc_pxo_pll4[] = {
+static const char * const lcc_pxo_pll4[] = {
        "pxo",
        "pll4_vote",
 };
@@ -127,7 +127,7 @@ static struct clk_rcg mi2s_osr_src = {
        },
 };
 
-static const char *lcc_mi2s_parents[] = {
+static const char * const lcc_mi2s_parents[] = {
        "mi2s_osr_src",
 };
 
@@ -233,7 +233,7 @@ static struct clk_rcg prefix##_osr_src = {                  \
        },                                                      \
 };                                                             \
                                                                \
-static const char *lcc_##prefix##_parents[] = {                        \
+static const char * const lcc_##prefix##_parents[] = {         \
        #prefix "_osr_src",                                     \
 };                                                             \
                                                                \
@@ -445,7 +445,7 @@ static struct clk_rcg slimbus_src = {
        },
 };
 
-static const char *lcc_slimbus_parents[] = {
+static const char * const lcc_slimbus_parents[] = {
        "slimbus_src",
 };
 
index 1b17df2cb0afdd9350283fddbce43f048fb8acf3..f0ee6bde11af3b4e31d4566329c07004657414c1 100644 (file)
@@ -53,7 +53,7 @@ static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
        { P_GPLL0, 5 }
 };
 
-static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -69,7 +69,7 @@ static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
        { P_DSI1PLL, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "hdmipll",
@@ -86,7 +86,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = {
        { P_MMPLL2, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_2_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -102,7 +102,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
        { P_MMPLL3, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -119,7 +119,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -137,7 +137,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -155,7 +155,7 @@ static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL_BYTE, 2 }
 };
 
-static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -172,7 +172,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll0_map[] = {
        { P_MMPLL4, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_4_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_4_gpll0[] = {
        "xo",
        "mmpll0",
        "mmpll1",
@@ -189,7 +189,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_map[] = {
        { P_GPLL1, 4 }
 };
 
-static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = {
+static const char * const mmcc_xo_mmpll0_1_4_gpll1_0[] = {
        "xo",
        "mmpll0",
        "mmpll1",
@@ -208,7 +208,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = {
        { P_MMSLEEP, 6 }
 };
 
-static const char *mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
+static const char * const mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
        "xo",
        "mmpll0",
        "mmpll1",
index 9711bca9cc06aaf270ed2fb1c4195fa23eade8c2..bad02aebf959b6caed9b1941d8b9decf4152f7dd 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 #include <linux/reset-controller.h>
@@ -50,7 +51,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_map[] = {
        { P_PLL2, 1 }
 };
 
-static const char *mmcc_pxo_pll8_pll2[] = {
+static const char * const mmcc_pxo_pll8_pll2[] = {
        "pxo",
        "pll8_vote",
        "pll2",
@@ -63,7 +64,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_pll3_map[] = {
        { P_PLL3, 3 }
 };
 
-static const char *mmcc_pxo_pll8_pll2_pll15[] = {
+static const char * const mmcc_pxo_pll8_pll2_pll15[] = {
        "pxo",
        "pll8_vote",
        "pll2",
@@ -77,7 +78,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_pll15_map[] = {
        { P_PLL15, 3 }
 };
 
-static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+static const char * const mmcc_pxo_pll8_pll2_pll3[] = {
        "pxo",
        "pll8_vote",
        "pll2",
@@ -508,8 +509,7 @@ static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
        int ret = 0;
        u32 val;
        struct clk_pix_rdi *rdi = to_clk_pix_rdi(hw);
-       struct clk *clk = hw->clk;
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
 
        /*
         * These clocks select three inputs via two muxes. One mux selects
@@ -520,7 +520,8 @@ static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
         * needs to be on at what time.
         */
        for (i = 0; i < num_parents; i++) {
-               ret = clk_prepare_enable(clk_get_parent_by_index(clk, i));
+               struct clk_hw *p = clk_hw_get_parent_by_index(hw, i);
+               ret = clk_prepare_enable(p->clk);
                if (ret)
                        goto err;
        }
@@ -548,8 +549,10 @@ static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
        udelay(1);
 
 err:
-       for (i--; i >= 0; i--)
-               clk_disable_unprepare(clk_get_parent_by_index(clk, i));
+       for (i--; i >= 0; i--) {
+               struct clk_hw *p = clk_hw_get_parent_by_index(hw, i);
+               clk_disable_unprepare(p->clk);
+       }
 
        return ret;
 }
@@ -579,7 +582,7 @@ static const struct clk_ops clk_ops_pix_rdi = {
        .determine_rate = __clk_mux_determine_rate,
 };
 
-static const char *pix_rdi_parents[] = {
+static const char * const pix_rdi_parents[] = {
        "csi0_clk",
        "csi1_clk",
        "csi2_clk",
@@ -709,7 +712,7 @@ static struct clk_rcg csiphytimer_src = {
        },
 };
 
-static const char *csixphy_timer_src[] = { "csiphytimer_src" };
+static const char * const csixphy_timer_src[] = { "csiphytimer_src" };
 
 static struct clk_branch csiphy0_timer_clk = {
        .halt_reg = 0x01e8,
@@ -1385,7 +1388,7 @@ static const struct parent_map mmcc_pxo_hdmi_map[] = {
        { P_HDMI_PLL, 3 }
 };
 
-static const char *mmcc_pxo_hdmi[] = {
+static const char * const mmcc_pxo_hdmi[] = {
        "pxo",
        "hdmi_pll",
 };
@@ -1428,7 +1431,7 @@ static struct clk_rcg tv_src = {
        },
 };
 
-static const char *tv_src_name[] = { "tv_src" };
+static const char * const tv_src_name[] = { "tv_src" };
 
 static struct clk_branch tv_enc_clk = {
        .halt_reg = 0x01d4,
index 07f4cc159ad3103e79a955d26e085b596e34756c..0987bf443e1f3f57d6a0c36ff0702505abe10041 100644 (file)
@@ -56,7 +56,7 @@ static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
        { P_GPLL0, 5 }
 };
 
-static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -72,7 +72,7 @@ static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
        { P_DSI1PLL, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "hdmipll",
@@ -89,7 +89,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = {
        { P_MMPLL2, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_2_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -105,7 +105,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
        { P_MMPLL3, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -121,7 +121,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_gpll1_0_map[] = {
        { P_GPLL1, 4 }
 };
 
-static const char *mmcc_xo_mmpll0_1_gpll1_0[] = {
+static const char * const mmcc_xo_mmpll0_1_gpll1_0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -138,7 +138,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -156,7 +156,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -174,7 +174,7 @@ static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL_BYTE, 2 }
 };
 
-static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
index 2714097f90db1138b1f71771461b15932b826cce..b27edd6c8183378c8899d2dee22e42c913c4a46f 100644 (file)
@@ -6,8 +6,10 @@ obj-y  += clk-rockchip.o
 obj-y  += clk.o
 obj-y  += clk-pll.o
 obj-y  += clk-cpu.o
+obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
 
 obj-y  += clk-rk3188.o
 obj-y  += clk-rk3288.o
+obj-y  += clk-rk3368.o
index fb7721bd37e6a9595f70cbd8125fdab52fd2265e..330870a6d8bfa9163405398ff3de7e1eb0d8a864 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include "clk.h"
 
diff --git a/drivers/clk/rockchip/clk-inverter.c b/drivers/clk/rockchip/clk-inverter.c
new file mode 100644 (file)
index 0000000..7cbf43b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2015 Heiko Stuebner <heiko@sntech.de>
+ *
+ * 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/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include "clk.h"
+
+struct rockchip_inv_clock {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       int             shift;
+       int             flags;
+       spinlock_t      *lock;
+};
+
+#define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
+
+#define INVERTER_MASK 0x1
+
+static int rockchip_inv_get_phase(struct clk_hw *hw)
+{
+       struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+       u32 val;
+
+       val = readl(inv_clock->reg) >> inv_clock->shift;
+       val &= INVERTER_MASK;
+       return val ? 180 : 0;
+}
+
+static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
+{
+       struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+       u32 val;
+
+       if (degrees % 180 == 0) {
+               val = !!degrees;
+       } else {
+               pr_err("%s: unsupported phase %d for %s\n",
+                      __func__, degrees, clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
+               writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
+                      inv_clock->reg);
+       } else {
+               unsigned long flags;
+               u32 reg;
+
+               spin_lock_irqsave(inv_clock->lock, flags);
+
+               reg = readl(inv_clock->reg);
+               reg &= ~BIT(inv_clock->shift);
+               reg |= val;
+               writel(reg, inv_clock->reg);
+
+               spin_unlock_irqrestore(inv_clock->lock, flags);
+       }
+
+       return 0;
+}
+
+static const struct clk_ops rockchip_inv_clk_ops = {
+       .get_phase      = rockchip_inv_get_phase,
+       .set_phase      = rockchip_inv_set_phase,
+};
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+                               const char *const *parent_names, u8 num_parents,
+                               void __iomem *reg, int shift, int flags,
+                               spinlock_t *lock)
+{
+       struct clk_init_data init;
+       struct rockchip_inv_clock *inv_clock;
+       struct clk *clk;
+
+       inv_clock = kmalloc(sizeof(*inv_clock), GFP_KERNEL);
+       if (!inv_clock)
+               return NULL;
+
+       init.name = name;
+       init.num_parents = num_parents;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.parent_names = parent_names;
+       init.ops = &rockchip_inv_clk_ops;
+
+       inv_clock->hw.init = &init;
+       inv_clock->reg = reg;
+       inv_clock->shift = shift;
+       inv_clock->flags = flags;
+       inv_clock->lock = lock;
+
+       clk = clk_register(NULL, &inv_clock->hw);
+       if (IS_ERR(clk))
+               goto err_free;
+
+       return clk;
+
+err_free:
+       kfree(inv_clock);
+       return NULL;
+}
index e9f8df324e7ccecad7730998d8210c8ea11a2276..9b613426e968ab6a0e36fdcb52b7c87ac076253b 100644 (file)
  */
 
 #include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include "clk.h"
 
 struct rockchip_mmc_clock {
@@ -105,7 +108,7 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
        writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg);
 
        pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
-               __clk_get_name(hw->clk), degrees, delay_num,
+               clk_hw_get_name(hw), degrees, delay_num,
                mmc_clock->reg, raw_value>>(mmc_clock->shift),
                rockchip_mmc_get_phase(hw)
        );
@@ -131,6 +134,7 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        if (!mmc_clock)
                return NULL;
 
+       init.name = name;
        init.num_parents = num_parents;
        init.parent_names = parent_names;
        init.ops = &rockchip_mmc_clk_ops;
@@ -139,9 +143,6 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        mmc_clock->reg = reg;
        mmc_clock->shift = shift;
 
-       if (name)
-               init.name = name;
-
        clk = clk_register(NULL, &mmc_clock->hw);
        if (IS_ERR(clk))
                goto err_free;
index 76027261f7ed999971f0b46ca10a4b4774d55bc3..7737a1df1e4ba09e9d0fb0ccf420be7219d780b4 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 #include "clk.h"
@@ -121,8 +120,8 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
 #define RK3066_PLLCON0_NR_SHIFT                8
 #define RK3066_PLLCON1_NF_MASK         0x1fff
 #define RK3066_PLLCON1_NF_SHIFT                0
-#define RK3066_PLLCON2_BWADJ_MASK      0xfff
-#define RK3066_PLLCON2_BWADJ_SHIFT     0
+#define RK3066_PLLCON2_NB_MASK         0xfff
+#define RK3066_PLLCON2_NB_SHIFT                0
 #define RK3066_PLLCON3_RESET           (1 << 5)
 #define RK3066_PLLCON3_PWRDOWN         (1 << 1)
 #define RK3066_PLLCON3_BYPASS          (1 << 0)
@@ -137,7 +136,7 @@ static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
        pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
        if (pllcon & RK3066_PLLCON3_BYPASS) {
                pr_debug("%s: pll %s is bypassed\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return prate;
        }
 
@@ -175,13 +174,13 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        }
 
        pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
-                __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+                __func__, clk_hw_get_name(hw), old_rate, drate, prate);
 
        /* Get required rate settings from table */
        rate = rockchip_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -208,8 +207,8 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,
                                                   RK3066_PLLCON1_NF_SHIFT),
                       pll->reg_base + RK3066_PLLCON(1));
-       writel_relaxed(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK,
-                                                 RK3066_PLLCON2_BWADJ_SHIFT),
+       writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK,
+                                                  RK3066_PLLCON2_NB_SHIFT),
                       pll->reg_base + RK3066_PLLCON(2));
 
        /* leave reset and wait the reset_delay */
@@ -262,14 +261,14 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
 {
        struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
        const struct rockchip_pll_rate_table *rate;
-       unsigned int nf, nr, no, bwadj;
+       unsigned int nf, nr, no, nb;
        unsigned long drate;
        u32 pllcon;
 
        if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
                return;
 
-       drate = __clk_get_rate(hw->clk);
+       drate = clk_hw_get_rate(hw);
        rate = rockchip_get_pll_settings(pll, drate);
 
        /* when no rate setting for the current rate, rely on clk_set_rate */
@@ -284,25 +283,25 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
        nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
 
        pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
-       bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK;
+       nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1;
 
-       pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n",
-                __func__, __clk_get_name(hw->clk), drate, rate->nr, nr,
-               rate->no, no, rate->nf, nf, rate->bwadj, bwadj);
+       pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
+                __func__, clk_hw_get_name(hw), drate, rate->nr, nr,
+               rate->no, no, rate->nf, nf, rate->nb, nb);
        if (rate->nr != nr || rate->no != no || rate->nf != nf
-                                            || rate->bwadj != bwadj) {
-               struct clk *parent = __clk_get_parent(hw->clk);
+                                            || rate->nb != nb) {
+               struct clk_hw *parent = clk_hw_get_parent(hw);
                unsigned long prate;
 
                if (!parent) {
                        pr_warn("%s: parent of %s not available\n",
-                               __func__, __clk_get_name(hw->clk));
+                               __func__, clk_hw_get_name(hw));
                        return;
                }
 
                pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
-                        __func__, __clk_get_name(hw->clk));
-               prate = __clk_get_rate(parent);
+                        __func__, clk_hw_get_name(hw));
+               prate = clk_hw_get_rate(parent);
                rockchip_rk3066_pll_set_rate(hw, drate, prate);
        }
 }
@@ -354,6 +353,35 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
        if (!pll)
                return ERR_PTR(-ENOMEM);
 
+       /* create the mux on top of the real pll */
+       pll->pll_mux_ops = &clk_mux_ops;
+       pll_mux = &pll->pll_mux;
+       pll_mux->reg = base + mode_offset;
+       pll_mux->shift = mode_shift;
+       pll_mux->mask = PLL_MODE_MASK;
+       pll_mux->flags = 0;
+       pll_mux->lock = lock;
+       pll_mux->hw.init = &init;
+
+       if (pll_type == pll_rk3066)
+               pll_mux->flags |= CLK_MUX_HIWORD_MASK;
+
+       /* the actual muxing is xin24m, pll-output, xin32k */
+       pll_parents[0] = parent_names[0];
+       pll_parents[1] = pll_name;
+       pll_parents[2] = parent_names[1];
+
+       init.name = name;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.ops = pll->pll_mux_ops;
+       init.parent_names = pll_parents;
+       init.num_parents = ARRAY_SIZE(pll_parents);
+
+       mux_clk = clk_register(NULL, &pll_mux->hw);
+       if (IS_ERR(mux_clk))
+               goto err_mux;
+
+       /* now create the actual pll */
        init.name = pll_name;
 
        /* keep all plls untouched for now */
@@ -399,47 +427,19 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
        pll->flags = clk_pll_flags;
        pll->lock = lock;
 
-       /* create the mux on top of the real pll */
-       pll->pll_mux_ops = &clk_mux_ops;
-       pll_mux = &pll->pll_mux;
-       pll_mux->reg = base + mode_offset;
-       pll_mux->shift = mode_shift;
-       pll_mux->mask = PLL_MODE_MASK;
-       pll_mux->flags = 0;
-       pll_mux->lock = lock;
-       pll_mux->hw.init = &init;
-
-       if (pll_type == pll_rk3066)
-               pll_mux->flags |= CLK_MUX_HIWORD_MASK;
-
        pll_clk = clk_register(NULL, &pll->hw);
        if (IS_ERR(pll_clk)) {
                pr_err("%s: failed to register pll clock %s : %ld\n",
                        __func__, name, PTR_ERR(pll_clk));
-               mux_clk = pll_clk;
                goto err_pll;
        }
 
-       /* the actual muxing is xin24m, pll-output, xin32k */
-       pll_parents[0] = parent_names[0];
-       pll_parents[1] = pll_name;
-       pll_parents[2] = parent_names[1];
-
-       init.name = name;
-       init.flags = CLK_SET_RATE_PARENT;
-       init.ops = pll->pll_mux_ops;
-       init.parent_names = pll_parents;
-       init.num_parents = ARRAY_SIZE(pll_parents);
-
-       mux_clk = clk_register(NULL, &pll_mux->hw);
-       if (IS_ERR(mux_clk))
-               goto err_mux;
-
        return mux_clk;
 
-err_mux:
-       clk_unregister(pll_clk);
 err_pll:
+       clk_unregister(mux_clk);
+       mux_clk = pll_clk;
+err_mux:
        kfree(pll);
        return mux_clk;
 }
index e4f9d472f1ffb52f7ffb5f5061b39d56d519fb89..ed02bbc7b11f303a3d265003074ef022e545ddcf 100644 (file)
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -201,7 +202,7 @@ PNAME(mux_pll_src_cpll_gpll_p)      = { "cpll", "gpll" };
 PNAME(mux_aclk_cpu_p)          = { "apll", "gpll" };
 PNAME(mux_sclk_cif0_p)         = { "cif0_pre", "xin24m" };
 PNAME(mux_sclk_i2s0_p)         = { "i2s0_pre", "i2s0_frac", "xin12m" };
-PNAME(mux_sclk_spdif_p)                = { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_sclk_spdif_p)                = { "spdif_pre", "spdif_frac", "xin12m" };
 PNAME(mux_sclk_uart0_p)                = { "uart0_pre", "uart0_frac", "xin24m" };
 PNAME(mux_sclk_uart1_p)                = { "uart1_pre", "uart1_frac", "xin24m" };
 PNAME(mux_sclk_uart2_p)                = { "uart2_pre", "uart2_frac", "xin24m" };
@@ -235,6 +236,7 @@ static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
 #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
 
 /* 2 ^ (val + 1) */
 static struct clk_div_table div_core_peri_t[] = {
@@ -310,6 +312,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 
        GATE(0, "pclkin_cif0", "ext_cif0", 0,
                        RK2928_CLKGATE_CON(3), 3, GFLAGS),
+       INVERTER(0, "pclk_cif0", "pclkin_cif0",
+                       RK2928_CLKSEL_CON(30), 8, IFLAGS),
 
        /*
         * the 480m are generated inside the usb block from these clocks,
@@ -334,8 +338,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
                        RK2928_CLKSEL_CON(23), 0,
                        RK2928_CLKGATE_CON(2), 7, GFLAGS),
-       MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
+       MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
                        RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+       INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+                       RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
        COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
                        RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
@@ -344,10 +350,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
                        RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(0), 13, GFLAGS),
-       COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+       COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(9), 0,
                        RK2928_CLKGATE_CON(0), 14, GFLAGS),
-       MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+       MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
 
        /*
@@ -557,6 +563,8 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 
        GATE(0, "pclkin_cif1", "ext_cif1", 0,
                        RK2928_CLKGATE_CON(3), 4, GFLAGS),
+       INVERTER(0, "pclk_cif1", "pclkin_cif1",
+                       RK2928_CLKSEL_CON(30), 12, IFLAGS),
 
        COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
                        RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
@@ -809,7 +817,7 @@ static void __init rk3188_clk_init(struct device_node *np)
 
                rate = pll->rate_table;
                while (rate->rate > 0) {
-                       rate->bwadj = 0;
+                       rate->nb = 1;
                        rate++;
                }
        }
index 4f817ed9e6eedc432d0e6fd05adcb365e03e0f6b..0df5bae9ddbf062a0b3199ba7173eaedb2ab3fa1 100644 (file)
@@ -84,7 +84,7 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
        RK3066_PLL_RATE( 742500000, 8, 495, 2),
        RK3066_PLL_RATE( 696000000, 1, 58, 2),
        RK3066_PLL_RATE( 600000000, 1, 50, 2),
-       RK3066_PLL_RATE_BWADJ(594000000, 1, 198, 8, 1),
+       RK3066_PLL_RATE_NB(594000000, 1, 198, 8, 1),
        RK3066_PLL_RATE( 552000000, 1, 46, 2),
        RK3066_PLL_RATE( 504000000, 1, 84, 4),
        RK3066_PLL_RATE( 500000000, 3, 125, 2),
@@ -189,7 +189,7 @@ PNAME(mux_uart1_p)  = { "uart1_src", "uart1_frac", "xin24m" };
 PNAME(mux_uart2_p)     = { "uart2_src", "uart2_frac", "xin24m" };
 PNAME(mux_uart3_p)     = { "uart3_src", "uart3_frac", "xin24m" };
 PNAME(mux_uart4_p)     = { "uart4_src", "uart4_frac", "xin24m" };
-PNAME(mux_cif_out_p)   = { "cif_src", "xin24m" };
+PNAME(mux_vip_out_p)   = { "vip_src", "xin24m" };
 PNAME(mux_mac_p)       = { "mac_pll_src", "ext_gmac" };
 PNAME(mux_hsadcout_p)  = { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)   = { "ext_edp_24m", "xin24m" };
@@ -223,6 +223,7 @@ static struct clk_div_table div_hclk_cpu_t[] = {
 #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 rk3288_clk_branches[] __initdata = {
        /*
@@ -434,7 +435,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
                        RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
                        RK3288_CLKGATE_CON(3), 7, GFLAGS),
-       COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0,
+       COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
                        RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
 
        DIV(0, "pclk_pd_alive", "gpll", 0,
@@ -578,7 +579,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
                        RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
                        RK3288_CLKGATE_CON(2), 5, GFLAGS),
-       MUX(SCLK_MAC, "mac_clk", mux_mac_p, 0,
+       MUX(SCLK_MAC, "mac_clk", mux_mac_p, CLK_SET_RATE_PARENT,
                        RK3288_CLKSEL_CON(21), 4, 1, MFLAGS),
        GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
                        RK3288_CLKGATE_CON(5), 3, GFLAGS),
@@ -592,8 +593,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0,
                        RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
                        RK3288_CLKGATE_CON(2), 6, GFLAGS),
-       MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0,
+       MUX(0, "sclk_hsadc_out", mux_hsadcout_p, 0,
                        RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+       INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+                       RK3288_CLKSEL_CON(22), 7, IFLAGS),
 
        GATE(0, "jtag", "ext_jtag", 0,
                        RK3288_CLKGATE_CON(4), 14, GFLAGS),
@@ -768,7 +771,9 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
         */
 
        GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
+       INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS),
        GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+       INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
 };
 
 static const char *const rk3288_critical_clocks[] __initconst = {
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
new file mode 100644 (file)
index 0000000..9c5d61e
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
+ *
+ * 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/platform_device.h>
+#include <dt-bindings/clock/rk3368-cru.h>
+#include "clk.h"
+
+#define RK3368_GRF_SOC_STATUS0 0x480
+
+enum rk3368_plls {
+       apllb, aplll, dpll, cpll, gpll, npll,
+};
+
+static struct rockchip_pll_rate_table rk3368_pll_rates[] = {
+       RK3066_PLL_RATE(2208000000, 1, 92, 1),
+       RK3066_PLL_RATE(2184000000, 1, 91, 1),
+       RK3066_PLL_RATE(2160000000, 1, 90, 1),
+       RK3066_PLL_RATE(2136000000, 1, 89, 1),
+       RK3066_PLL_RATE(2112000000, 1, 88, 1),
+       RK3066_PLL_RATE(2088000000, 1, 87, 1),
+       RK3066_PLL_RATE(2064000000, 1, 86, 1),
+       RK3066_PLL_RATE(2040000000, 1, 85, 1),
+       RK3066_PLL_RATE(2016000000, 1, 84, 1),
+       RK3066_PLL_RATE(1992000000, 1, 83, 1),
+       RK3066_PLL_RATE(1968000000, 1, 82, 1),
+       RK3066_PLL_RATE(1944000000, 1, 81, 1),
+       RK3066_PLL_RATE(1920000000, 1, 80, 1),
+       RK3066_PLL_RATE(1896000000, 1, 79, 1),
+       RK3066_PLL_RATE(1872000000, 1, 78, 1),
+       RK3066_PLL_RATE(1848000000, 1, 77, 1),
+       RK3066_PLL_RATE(1824000000, 1, 76, 1),
+       RK3066_PLL_RATE(1800000000, 1, 75, 1),
+       RK3066_PLL_RATE(1776000000, 1, 74, 1),
+       RK3066_PLL_RATE(1752000000, 1, 73, 1),
+       RK3066_PLL_RATE(1728000000, 1, 72, 1),
+       RK3066_PLL_RATE(1704000000, 1, 71, 1),
+       RK3066_PLL_RATE(1680000000, 1, 70, 1),
+       RK3066_PLL_RATE(1656000000, 1, 69, 1),
+       RK3066_PLL_RATE(1632000000, 1, 68, 1),
+       RK3066_PLL_RATE(1608000000, 1, 67, 1),
+       RK3066_PLL_RATE(1560000000, 1, 65, 1),
+       RK3066_PLL_RATE(1512000000, 1, 63, 1),
+       RK3066_PLL_RATE(1488000000, 1, 62, 1),
+       RK3066_PLL_RATE(1464000000, 1, 61, 1),
+       RK3066_PLL_RATE(1440000000, 1, 60, 1),
+       RK3066_PLL_RATE(1416000000, 1, 59, 1),
+       RK3066_PLL_RATE(1392000000, 1, 58, 1),
+       RK3066_PLL_RATE(1368000000, 1, 57, 1),
+       RK3066_PLL_RATE(1344000000, 1, 56, 1),
+       RK3066_PLL_RATE(1320000000, 1, 55, 1),
+       RK3066_PLL_RATE(1296000000, 1, 54, 1),
+       RK3066_PLL_RATE(1272000000, 1, 53, 1),
+       RK3066_PLL_RATE(1248000000, 1, 52, 1),
+       RK3066_PLL_RATE(1224000000, 1, 51, 1),
+       RK3066_PLL_RATE(1200000000, 1, 50, 1),
+       RK3066_PLL_RATE(1176000000, 1, 49, 1),
+       RK3066_PLL_RATE(1128000000, 1, 47, 1),
+       RK3066_PLL_RATE(1104000000, 1, 46, 1),
+       RK3066_PLL_RATE(1008000000, 1, 84, 2),
+       RK3066_PLL_RATE( 912000000, 1, 76, 2),
+       RK3066_PLL_RATE( 888000000, 1, 74, 2),
+       RK3066_PLL_RATE( 816000000, 1, 68, 2),
+       RK3066_PLL_RATE( 792000000, 1, 66, 2),
+       RK3066_PLL_RATE( 696000000, 1, 58, 2),
+       RK3066_PLL_RATE( 672000000, 1, 56, 2),
+       RK3066_PLL_RATE( 648000000, 1, 54, 2),
+       RK3066_PLL_RATE( 624000000, 1, 52, 2),
+       RK3066_PLL_RATE( 600000000, 1, 50, 2),
+       RK3066_PLL_RATE( 576000000, 1, 48, 2),
+       RK3066_PLL_RATE( 552000000, 1, 46, 2),
+       RK3066_PLL_RATE( 528000000, 1, 88, 4),
+       RK3066_PLL_RATE( 504000000, 1, 84, 4),
+       RK3066_PLL_RATE( 480000000, 1, 80, 4),
+       RK3066_PLL_RATE( 456000000, 1, 76, 4),
+       RK3066_PLL_RATE( 408000000, 1, 68, 4),
+       RK3066_PLL_RATE( 312000000, 1, 52, 4),
+       RK3066_PLL_RATE( 252000000, 1, 84, 8),
+       RK3066_PLL_RATE( 216000000, 1, 72, 8),
+       RK3066_PLL_RATE( 126000000, 2, 84, 8),
+       RK3066_PLL_RATE(  48000000, 2, 32, 8),
+       { /* sentinel */ },
+};
+
+PNAME(mux_pll_p)               = { "xin24m", "xin32k" };
+PNAME(mux_armclkb_p)           = { "apllb_core", "gpllb_core" };
+PNAME(mux_armclkl_p)           = { "aplll_core", "gplll_core" };
+PNAME(mux_ddrphy_p)            = { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_cs_src_p)            = { "apllb_cs", "aplll_cs", "gpll_cs"};
+PNAME(mux_aclk_bus_src_p)      = { "cpll_aclk_bus", "gpll_aclk_bus" };
+
+PNAME(mux_pll_src_cpll_gpll_p)         = { "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p)    = { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p)    = { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_usb_p)     = { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_usb_p) = { "cpll", "gpll", "usbphy_480m",
+                                           "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_npll_p)        = { "cpll", "gpll", "usbphy_480m",
+                                           "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_npll_p) = { "cpll", "gpll", "npll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_usb_p) = { "cpll", "gpll", "npll",
+                                           "usbphy_480m" };
+
+PNAME(mux_i2s_8ch_pre_p)       = { "i2s_8ch_src", "i2s_8ch_frac",
+                                   "ext_i2s", "xin12m" };
+PNAME(mux_i2s_8ch_clkout_p)    = { "i2s_8ch_pre", "xin12m" };
+PNAME(mux_i2s_2ch_p)           = { "i2s_2ch_src", "i2s_2ch_frac",
+                                   "dummy", "xin12m" };
+PNAME(mux_spdif_8ch_p)         = { "spdif_8ch_pre", "spdif_8ch_frac",
+                                   "ext_i2s", "xin12m" };
+PNAME(mux_edp_24m_p)           = { "dummy", "xin24m" };
+PNAME(mux_vip_out_p)           = { "vip_src", "xin24m" };
+PNAME(mux_usbphy480m_p)                = { "usbotg_out", "xin24m" };
+PNAME(mux_hsic_usbphy480m_p)   = { "usbotg_out", "dummy" };
+PNAME(mux_hsicphy480m_p)       = { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_uart0_p)             = { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)             = { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)             = { "uart2_src", "xin24m" };
+PNAME(mux_uart3_p)             = { "uart3_src", "uart3_frac", "xin24m" };
+PNAME(mux_uart4_p)             = { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_mac_p)               = { "mac_pll_src", "ext_gmac" };
+PNAME(mux_mmc_src_p)           = { "cpll", "gpll", "usbphy_480m", "xin24m" };
+
+static struct rockchip_pll_clock rk3368_pll_clks[] __initdata = {
+       [apllb] = PLL(pll_rk3066, PLL_APLLB, "apllb", mux_pll_p, 0, RK3368_PLL_CON(0),
+                    RK3368_PLL_CON(3), 8, 1, 0, rk3368_pll_rates),
+       [aplll] = PLL(pll_rk3066, PLL_APLLL, "aplll", mux_pll_p, 0, RK3368_PLL_CON(4),
+                    RK3368_PLL_CON(7), 8, 0, 0, rk3368_pll_rates),
+       [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3368_PLL_CON(8),
+                    RK3368_PLL_CON(11), 8, 2, 0, NULL),
+       [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3368_PLL_CON(12),
+                    RK3368_PLL_CON(15), 8, 3, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+       [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3368_PLL_CON(16),
+                    RK3368_PLL_CON(19), 8, 4, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+       [npll] = PLL(pll_rk3066, PLL_NPLL, "npll",  mux_pll_p, 0, RK3368_PLL_CON(20),
+                    RK3368_PLL_CON(23), 8, 5, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+};
+
+static struct clk_div_table div_ddrphy_t[] = {
+       { .val = 0, .div = 1 },
+       { .val = 1, .div = 2 },
+       { .val = 3, .div = 4 },
+       { /* sentinel */ },
+};
+
+#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 const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
+       .core_reg = RK3368_CLKSEL_CON(0),
+       .div_core_shift = 0,
+       .div_core_mask = 0x1f,
+       .mux_core_shift = 15,
+};
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
+       .core_reg = RK3368_CLKSEL_CON(2),
+       .div_core_shift = 0,
+       .div_core_mask = 0x1f,
+       .mux_core_shift = 7,
+};
+
+#define RK3368_DIV_ACLKM_MASK          0x1f
+#define RK3368_DIV_ACLKM_SHIFT         8
+#define RK3368_DIV_ATCLK_MASK          0x1f
+#define RK3368_DIV_ATCLK_SHIFT         0
+#define RK3368_DIV_PCLK_DBG_MASK       0x1f
+#define RK3368_DIV_PCLK_DBG_SHIFT      8
+
+#define RK3368_CLKSEL0(_offs, _aclkm)                                  \
+       {                                                               \
+               .reg = RK3288_CLKSEL_CON(0 + _offs),                    \
+               .val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK,     \
+                               RK3368_DIV_ACLKM_SHIFT),                \
+       }
+#define RK3368_CLKSEL1(_offs, _atclk, _pdbg)                           \
+       {                                                               \
+               .reg = RK3288_CLKSEL_CON(1 + _offs),                    \
+               .val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK,     \
+                               RK3368_DIV_ATCLK_SHIFT) |               \
+                      HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK,   \
+                               RK3368_DIV_PCLK_DBG_SHIFT),             \
+       }
+
+/* cluster_b: aclkm in clksel0, rest in clksel1 */
+#define RK3368_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg)             \
+       {                                                               \
+               .prate = _prate,                                        \
+               .divs = {                                               \
+                       RK3368_CLKSEL0(0, _aclkm),                      \
+                       RK3368_CLKSEL1(0, _atclk, _pdbg),               \
+               },                                                      \
+       }
+
+/* cluster_l: aclkm in clksel2, rest in clksel3 */
+#define RK3368_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg)             \
+       {                                                               \
+               .prate = _prate,                                        \
+               .divs = {                                               \
+                       RK3368_CLKSEL0(2, _aclkm),                      \
+                       RK3368_CLKSEL1(2, _atclk, _pdbg),               \
+               },                                                      \
+       }
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
+       RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
+       RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
+       RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
+       RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
+       RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
+       RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
+       RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
+       RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
+       RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
+       RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
+       RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
+       RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
+       RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
+       RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
+       RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
+       RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
+       RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
+       RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
+       RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
+       RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
+       /*
+        * Clock-Architecture Diagram 2
+        */
+
+       MUX(SCLK_USBPHY480M, "usbphy_480m", mux_usbphy480m_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(13), 8, 1, MFLAGS),
+
+       GATE(0, "apllb_core", "apllb", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 0, GFLAGS),
+       GATE(0, "gpllb_core", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 1, GFLAGS),
+
+       GATE(0, "aplll_core", "aplll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 4, GFLAGS),
+       GATE(0, "gplll_core", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 5, GFLAGS),
+
+       DIV(0, "aclkm_core_b", "armclkb", 0,
+                       RK3368_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "atclk_core_b", "armclkb", 0,
+                       RK3368_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "pclk_dbg_b", "armclkb", 0,
+                       RK3368_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+       DIV(0, "aclkm_core_l", "armclkl", 0,
+                       RK3368_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "atclk_core_l", "armclkl", 0,
+                       RK3368_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "pclk_dbg_l", "armclkl", 0,
+                       RK3368_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+       GATE(0, "apllb_cs", "apllb", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 9, GFLAGS),
+       GATE(0, "aplll_cs", "aplll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 10, GFLAGS),
+       GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 8, GFLAGS),
+       COMPOSITE_NOGATE(0, "sclk_cs_pre", mux_cs_src_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS),
+       COMPOSITE_NOMUX(0, "clkin_trace", "sclk_cs_pre", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(4), 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(0), 13, GFLAGS),
+
+       COMPOSITE(0, "aclk_cci_pre", mux_pll_src_cpll_gpll_usb_npll_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(0), 12, GFLAGS),
+       GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3368_CLKGATE_CON(7), 10, GFLAGS),
+
+       GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 8, GFLAGS),
+       GATE(0, "gpll_ddr", "gpll", 0,
+                       RK3368_CLKGATE_CON(1), 9, GFLAGS),
+       COMPOSITE_NOGATE_DIVTBL(0, "ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(13), 4, 1, MFLAGS, 0, 2, DFLAGS, div_ddrphy_t),
+
+       GATE(0, "sclk_ddr", "ddrphy_div4", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(6), 14, GFLAGS),
+       GATE(0, "sclk_ddr4x", "ddrphy_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(6), 15, GFLAGS),
+
+       GATE(0, "gpll_aclk_bus", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 10, GFLAGS),
+       GATE(0, "cpll_aclk_bus", "cpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 11, GFLAGS),
+       COMPOSITE_NOGATE(0, "aclk_bus_src", mux_aclk_bus_src_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(8), 7, 1, MFLAGS, 0, 5, DFLAGS),
+
+       GATE(ACLK_BUS, "aclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 0, GFLAGS),
+       COMPOSITE_NOMUX(PCLK_BUS, "pclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(8), 12, 3, DFLAGS,
+                       RK3368_CLKGATE_CON(1), 2, GFLAGS),
+       COMPOSITE_NOMUX(HCLK_BUS, "hclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(8), 8, 2, DFLAGS,
+                       RK3368_CLKGATE_CON(1), 1, GFLAGS),
+       COMPOSITE_NOMUX(0, "sclk_crypto", "aclk_bus_src", 0,
+                       RK3368_CLKSEL_CON(10), 14, 2, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 2, GFLAGS),
+
+       COMPOSITE(0, "fclk_mcu_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(1), 3, GFLAGS),
+       /*
+        * stclk_mcu is listed as child of fclk_mcu_src in diagram 5,
+        * but stclk_mcu has an additional own divider in diagram 2
+        */
+       COMPOSITE_NOMUX(0, "stclk_mcu", "fclk_mcu_src", 0,
+                       RK3368_CLKSEL_CON(12), 8, 3, DFLAGS,
+                       RK3368_CLKGATE_CON(13), 13, GFLAGS),
+
+       COMPOSITE(0, "i2s_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(27), 12, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 1, GFLAGS),
+       COMPOSITE_FRAC(0, "i2s_8ch_frac", "i2s_8ch_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(28), 0,
+                       RK3368_CLKGATE_CON(6), 2, GFLAGS),
+       MUX(0, "i2s_8ch_pre", mux_i2s_8ch_pre_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(27), 8, 2, MFLAGS),
+       COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "i2s_8ch_clkout", mux_i2s_8ch_clkout_p, 0,
+                       RK3368_CLKSEL_CON(27), 15, 1, MFLAGS,
+                       RK3368_CLKGATE_CON(6), 0, GFLAGS),
+       GATE(SCLK_I2S_8CH, "sclk_i2s_8ch", "i2s_8ch_pre", CLK_SET_RATE_PARENT,
+                       RK3368_CLKGATE_CON(6), 3, GFLAGS),
+       COMPOSITE(0, "spdif_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(31), 12, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 4, GFLAGS),
+       COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(32), 0,
+                       RK3368_CLKGATE_CON(6), 5, GFLAGS),
+       COMPOSITE_NODIV(SCLK_SPDIF_8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+                       RK3368_CLKSEL_CON(31), 8, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(6), 6, GFLAGS),
+       COMPOSITE(0, "i2s_2ch_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(53), 12, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 13, GFLAGS),
+       COMPOSITE_FRAC(0, "i2s_2ch_frac", "i2s_2ch_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(54), 0,
+                       RK3368_CLKGATE_CON(5), 14, GFLAGS),
+       COMPOSITE_NODIV(SCLK_I2S_2CH, "sclk_i2s_2ch", mux_i2s_2ch_p, 0,
+                       RK3368_CLKSEL_CON(53), 8, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(5), 15, GFLAGS),
+
+       COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0,
+                       RK3368_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 12, GFLAGS),
+       GATE(0, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0,
+                       RK3368_CLKGATE_CON(13), 7, GFLAGS),
+
+       MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(35), 12, 1, MFLAGS),
+       COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(37), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 4, GFLAGS),
+       MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(37), 8, 1, MFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 3
+        */
+
+       COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 6, GFLAGS),
+       COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 7, GFLAGS),
+
+       /*
+        * We introduce a virtual node of hclk_vodec_pre_v to split one clock
+        * struct with a gate and a fix divider into two node in software.
+        */
+       GATE(0, "hclk_video_pre_v", "aclk_vdpu", 0,
+               RK3368_CLKGATE_CON(4), 8, GFLAGS),
+
+       COMPOSITE(0, "sclk_hevc_cabac_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+                       RK3368_CLKSEL_CON(17), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 1, GFLAGS),
+       COMPOSITE(0, "sclk_hevc_core_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+                       RK3368_CLKSEL_CON(17), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 2, GFLAGS),
+
+       COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(19), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 0, GFLAGS),
+       DIV(0, "hclk_vio", "aclk_vio0", 0,
+                       RK3368_CLKSEL_CON(21), 0, 5, DFLAGS),
+
+       COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(18), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 3, GFLAGS),
+       COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(18), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 4, GFLAGS),
+
+       COMPOSITE(DCLK_VOP, "dclk_vop", mux_pll_src_cpll_gpll_npll_p, 0,
+                       RK3368_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 1, GFLAGS),
+
+       GATE(SCLK_VOP0_PWM, "sclk_vop0_pwm", "xin24m", 0,
+                       RK3368_CLKGATE_CON(4), 2, GFLAGS),
+
+       COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+                       RK3368_CLKSEL_CON(22), 6, 2, MFLAGS, 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 9, GFLAGS),
+
+       GATE(0, "pclk_isp_in", "ext_isp", 0,
+                       RK3368_CLKGATE_CON(17), 2, GFLAGS),
+       INVERTER(PCLK_ISP, "pclk_isp", "pclk_isp_in",
+                       RK3368_CLKSEL_CON(21), 6, IFLAGS),
+
+       GATE(0, "pclk_vip_in", "ext_vip", 0,
+                       RK3368_CLKGATE_CON(16), 13, GFLAGS),
+       INVERTER(PCLK_VIP, "pclk_vip", "pclk_vip_in",
+                       RK3368_CLKSEL_CON(21), 13, IFLAGS),
+
+       GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
+                       RK3368_CLKGATE_CON(4), 13, GFLAGS),
+       GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
+                       RK3368_CLKGATE_CON(5), 12, GFLAGS),
+
+       COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
+                       RK3368_CLKGATE_CON(4), 5, GFLAGS),
+       COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
+                       RK3368_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS),
+
+       COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0,
+                       RK3368_CLKSEL_CON(23), 8, 1, MFLAGS,
+                       RK3368_CLKGATE_CON(5), 4, GFLAGS),
+       COMPOSITE(SCLK_EDP, "sclk_edp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+                       RK3368_CLKSEL_CON(23), 6, 2, MFLAGS, 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 3, GFLAGS),
+
+       COMPOSITE(SCLK_HDCP, "sclk_hdcp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+                       RK3368_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 5, GFLAGS),
+
+       DIV(0, "pclk_pd_alive", "gpll", 0,
+                       RK3368_CLKSEL_CON(10), 8, 5, DFLAGS),
+
+       /* sclk_timer has a gate in the sgrf */
+
+       COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(10), 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 9, GFLAGS),
+       GATE(SCLK_PVTM_PMU, "sclk_pvtm_pmu", "xin24m", 0,
+                       RK3368_CLKGATE_CON(7), 3, GFLAGS),
+       COMPOSITE(0, "sclk_gpu_core_src", mux_pll_src_cpll_gpll_usb_npll_p, 0,
+                       RK3368_CLKSEL_CON(14), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 11, GFLAGS),
+       MUX(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(14), 14, 1, MFLAGS),
+       COMPOSITE_NOMUX(0, "aclk_gpu_mem_pre", "aclk_gpu_src", 0,
+                       RK3368_CLKSEL_CON(14), 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 8, GFLAGS),
+       COMPOSITE_NOMUX(0, "aclk_gpu_cfg_pre", "aclk_gpu_src", 0,
+                       RK3368_CLKSEL_CON(16), 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 9, GFLAGS),
+       GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0,
+                       RK3368_CLKGATE_CON(7), 11, GFLAGS),
+
+       COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(9), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 0, GFLAGS),
+       COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+                       RK3368_CLKSEL_CON(9), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+                       RK3368_CLKGATE_CON(3), 3, GFLAGS),
+       COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(9), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+                       RK3368_CLKGATE_CON(3), 2, GFLAGS),
+       GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(3), 1, GFLAGS),
+
+       GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3368_CLKGATE_CON(4), 14, GFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 4
+        */
+
+       COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(45), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 7, GFLAGS),
+       COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(45), 15, 1, MFLAGS, 8, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 8, GFLAGS),
+       COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(46), 15, 1, MFLAGS, 8, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 9, GFLAGS),
+
+
+       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
+                       RK3368_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 12, GFLAGS),
+       COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0,
+                       RK3368_CLKSEL_CON(48), 8, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 13, GFLAGS),
+       COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+                       RK3368_CLKSEL_CON(51), 8, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 15, GFLAGS),
+
+       MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3368_SDMMC_CON0, 1),
+       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3368_SDMMC_CON1, 0),
+
+       MMC(SCLK_SDIO0_DRV,    "sdio0_drv",    "sclk_sdio0", RK3368_SDIO0_CON0, 1),
+       MMC(SCLK_SDIO0_SAMPLE, "sdio0_sample", "sclk_sdio0", RK3368_SDIO0_CON1, 0),
+
+       MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3368_EMMC_CON0,  1),
+       MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3368_EMMC_CON1,  0),
+
+       GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(8), 1, GFLAGS),
+
+       /* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+       GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(8), 4, GFLAGS),
+
+       /* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+       COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0,
+                       RK3368_CLKSEL_CON(25), 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 5, GFLAGS),
+
+       COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+                       RK3368_CLKSEL_CON(25), 8, 8, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 6, GFLAGS),
+
+       COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(47), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 8, GFLAGS),
+
+       COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(52), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 7, GFLAGS),
+
+       COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb_usb_p, 0,
+                       RK3368_CLKSEL_CON(33), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 0, GFLAGS),
+       COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(34), 0,
+                       RK3368_CLKGATE_CON(2), 1, GFLAGS),
+       MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(33), 8, 2, MFLAGS),
+
+       COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(35), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 2, GFLAGS),
+       COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(36), 0,
+                       RK3368_CLKGATE_CON(2), 3, GFLAGS),
+       MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(35), 8, 2, MFLAGS),
+
+       COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(39), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 6, GFLAGS),
+       COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(40), 0,
+                       RK3368_CLKGATE_CON(2), 7, GFLAGS),
+       MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(39), 8, 2, MFLAGS),
+
+       COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(41), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 8, GFLAGS),
+       COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(42), 0,
+                       RK3368_CLKGATE_CON(2), 9, GFLAGS),
+       MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(41), 8, 2, MFLAGS),
+
+       COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(43), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 4, GFLAGS),
+       MUX(SCLK_MAC, "mac_clk", mux_mac_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(43), 8, 1, MFLAGS),
+       GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 7, GFLAGS),
+       GATE(SCLK_MACREF, "sclk_macref", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 6, GFLAGS),
+       GATE(SCLK_MAC_RX, "sclk_mac_rx", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 4, GFLAGS),
+       GATE(SCLK_MAC_TX, "sclk_mac_tx", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 5, GFLAGS),
+
+       GATE(0, "jtag", "ext_jtag", 0,
+                       RK3368_CLKGATE_CON(7), 0, GFLAGS),
+
+       COMPOSITE_NODIV(0, "hsic_usbphy_480m", mux_hsic_usbphy480m_p, 0,
+                       RK3368_CLKSEL_CON(26), 8, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(8), 0, GFLAGS),
+       COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
+                       RK3368_CLKSEL_CON(26), 12, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(8), 7, GFLAGS),
+       GATE(SCLK_HSICPHY12M, "sclk_hsicphy12m", "xin12m", 0,
+                       RK3368_CLKGATE_CON(8), 6, GFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 5
+        */
+
+       /* aclk_cci_pre gates */
+       GATE(0, "aclk_core_niu_cpup", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 4, GFLAGS),
+       GATE(0, "aclk_core_niu_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 3, GFLAGS),
+       GATE(0, "aclk_cci400", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 2, GFLAGS),
+       GATE(0, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 1, GFLAGS),
+       GATE(0, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 0, GFLAGS),
+
+       /* aclkm_core_* gates */
+       GATE(0, "aclk_adb400s_pd_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 0, GFLAGS),
+       GATE(0, "aclk_adb400s_pd_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 0, GFLAGS),
+
+       /* armclk* gates */
+       GATE(0, "sclk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 1, GFLAGS),
+       GATE(0, "sclk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 1, GFLAGS),
+
+       /* sclk_cs_pre gates */
+       GATE(0, "sclk_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 7, GFLAGS),
+       GATE(0, "pclk_core_niu_sdbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 6, GFLAGS),
+       GATE(0, "hclk_core_niu_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 5, GFLAGS),
+
+       /* aclk_bus gates */
+       GATE(0, "aclk_strc_sys", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 12, GFLAGS),
+       GATE(ACLK_DMAC_BUS, "aclk_dmac_bus", "aclk_bus", 0, RK3368_CLKGATE_CON(12), 11, GFLAGS),
+       GATE(0, "sclk_intmem1", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 6, GFLAGS),
+       GATE(0, "sclk_intmem0", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 5, GFLAGS),
+       GATE(0, "aclk_intmem", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 4, GFLAGS),
+       GATE(0, "aclk_gic400", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 9, GFLAGS),
+
+       /* sclk_ddr gates */
+       GATE(0, "nclk_ddrupctl", "sclk_ddr", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 2, GFLAGS),
+
+       /* clk_hsadc_tsp is part of diagram2 */
+
+       /* fclk_mcu_src gates */
+       GATE(0, "hclk_noc_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 14, GFLAGS),
+       GATE(0, "fclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 12, GFLAGS),
+       GATE(0, "hclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+       /* hclk_cpu gates */
+       GATE(HCLK_SPDIF, "hclk_spdif", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 10, GFLAGS),
+       GATE(HCLK_ROM, "hclk_rom", "hclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 9, GFLAGS),
+       GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 8, GFLAGS),
+       GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 7, GFLAGS),
+       GATE(HCLK_TSP, "hclk_tsp", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 10, GFLAGS),
+       GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 4, GFLAGS),
+       GATE(MCLK_CRYPTO, "mclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 3, GFLAGS),
+
+       /* pclk_cpu gates */
+       GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 14, GFLAGS),
+       GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 13, GFLAGS),
+       GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 3, GFLAGS),
+       GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 2, GFLAGS),
+       GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 1, GFLAGS),
+       GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 0, GFLAGS),
+       GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS),
+       GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS),
+       GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS),
+       GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS),
+       GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS),
+
+       /*
+        * video clk gates
+        * aclk_video(_pre) can actually select between parents of aclk_vdpu
+        * and aclk_vepu by setting bit GRF_SOC_CON0[7].
+        */
+       GATE(ACLK_VIDEO, "aclk_video", "aclk_vdpu", 0, RK3368_CLKGATE_CON(15), 0, GFLAGS),
+       GATE(SCLK_HEVC_CABAC, "sclk_hevc_cabac", "sclk_hevc_cabac_src", 0, RK3368_CLKGATE_CON(15), 3, GFLAGS),
+       GATE(SCLK_HEVC_CORE, "sclk_hevc_core", "sclk_hevc_core_src", 0, RK3368_CLKGATE_CON(15), 2, GFLAGS),
+       GATE(HCLK_VIDEO, "hclk_video", "hclk_video_pre", 0, RK3368_CLKGATE_CON(15), 1, GFLAGS),
+
+       /* aclk_rga_pre gates */
+       GATE(ACLK_VIO1_NOC, "aclk_vio1_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 10, GFLAGS),
+       GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(16), 0, GFLAGS),
+       GATE(ACLK_HDCP, "aclk_hdcp", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(17), 10, GFLAGS),
+
+       /* aclk_vio0 gates */
+       GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 11, GFLAGS),
+       GATE(ACLK_VIO0_NOC, "aclk_vio0_noc", "aclk_vio0", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 9, GFLAGS),
+       GATE(ACLK_VOP, "aclk_vop", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 5, GFLAGS),
+       GATE(ACLK_VOP_IEP, "aclk_vop_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 4, GFLAGS),
+       GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 2, GFLAGS),
+
+       /* sclk_isp gates */
+       GATE(HCLK_ISP, "hclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(16), 14, GFLAGS),
+       GATE(ACLK_ISP, "aclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+
+       /* hclk_vio gates */
+       GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 12, GFLAGS),
+       GATE(HCLK_VIO_NOC, "hclk_vio_noc", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 8, GFLAGS),
+       GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 7, GFLAGS),
+       GATE(HCLK_VOP, "hclk_vop", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 6, GFLAGS),
+       GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 3, GFLAGS),
+       GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 1, GFLAGS),
+       GATE(HCLK_VIO_HDCPMMU, "hclk_hdcpmmu", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 12, GFLAGS),
+       GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 7, GFLAGS),
+
+       /*
+        * pclk_vio gates
+        * pclk_vio comes from the exactly same source as hclk_vio
+        */
+       GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 11, GFLAGS),
+       GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 9, GFLAGS),
+       GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 8, GFLAGS),
+       GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 6, GFLAGS),
+       GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+       GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+
+       /* ext_vip gates in diagram3 */
+
+       /* gpu gates */
+       GATE(SCLK_GPU_CORE, "sclk_gpu_core", "sclk_gpu_core_src", 0, RK3368_CLKGATE_CON(18), 2, GFLAGS),
+       GATE(ACLK_GPU_MEM, "aclk_gpu_mem", "aclk_gpu_mem_pre", 0, RK3368_CLKGATE_CON(18), 1, GFLAGS),
+       GATE(ACLK_GPU_CFG, "aclk_gpu_cfg", "aclk_gpu_cfg_pre", 0, RK3368_CLKGATE_CON(18), 0, GFLAGS),
+
+       /* aclk_peri gates */
+       GATE(ACLK_DMAC_PERI, "aclk_dmac_peri", "aclk_peri", 0, RK3368_CLKGATE_CON(19), 3, GFLAGS),
+       GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 2, GFLAGS),
+       GATE(HCLK_SFC, "hclk_sfc", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 15, GFLAGS),
+       GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 13, GFLAGS),
+       GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 8, GFLAGS),
+       GATE(ACLK_PERI_MMU, "aclk_peri_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(21), 4, GFLAGS),
+
+       /* hclk_peri gates */
+       GATE(0, "hclk_peri_axi_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 0, GFLAGS),
+       GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 11, GFLAGS),
+       GATE(0, "hclk_mmc_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 10, GFLAGS),
+       GATE(0, "hclk_emem_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 9, GFLAGS),
+       GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 7, GFLAGS),
+       GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 6, GFLAGS),
+       GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 5, GFLAGS),
+       GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 4, GFLAGS),
+       GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 3, GFLAGS),
+       GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 2, GFLAGS),
+       GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 1, GFLAGS),
+       GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 3, GFLAGS),
+       GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 2, GFLAGS),
+       GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 1, GFLAGS),
+       GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 0, GFLAGS),
+
+       /* pclk_peri gates */
+       GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 15, GFLAGS),
+       GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 14, GFLAGS),
+       GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 13, GFLAGS),
+       GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 12, GFLAGS),
+       GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 11, GFLAGS),
+       GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 10, GFLAGS),
+       GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 9, GFLAGS),
+       GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 8, GFLAGS),
+       GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 7, GFLAGS),
+       GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 6, GFLAGS),
+       GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 5, GFLAGS),
+       GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 4, GFLAGS),
+       GATE(0, "pclk_peri_axi_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 1, GFLAGS),
+       GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 14, GFLAGS),
+       GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS),
+
+       /* pclk_pd_alive gates */
+       GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+       GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS),
+       GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS),
+       GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS),
+       GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS),
+       GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS),
+       GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS),
+
+       /*
+        * pclk_vio gates
+        * pclk_vio comes from the exactly same source as hclk_vio
+        */
+       GATE(0, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+       GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+
+       /* pclk_pd_pmu gates */
+       GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+       GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+       GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+       GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+       GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS),
+       GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+
+       /* timer gates */
+       GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
+       GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
+       GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
+       GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
+       GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
+       GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
+       GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
+       GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
+       GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
+       GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
+       GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
+       GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
+};
+
+static void __init rk3368_clk_init(struct device_node *np)
+{
+       void __iomem *reg_base;
+       struct clk *clk;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("%s: could not map cru region\n", __func__);
+               return;
+       }
+
+       rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+       /* xin12m is created by a cru-internal divider */
+       clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock xin12m: %ld\n",
+                       __func__, PTR_ERR(clk));
+
+       /* ddrphy_div4 is created by a cru-internal divider */
+       clk = clk_register_fixed_factor(NULL, "ddrphy_div4", "ddrphy_src", 0, 1, 4);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock xin12m: %ld\n",
+                       __func__, PTR_ERR(clk));
+
+       clk = clk_register_fixed_factor(NULL, "hclk_video_pre",
+                                       "hclk_video_pre_v", 0, 1, 4);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
+                       __func__, PTR_ERR(clk));
+
+       /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
+       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock pclk_wdt: %ld\n",
+                       __func__, PTR_ERR(clk));
+       else
+               rockchip_clk_add_lookup(clk, PCLK_WDT);
+
+       rockchip_clk_register_plls(rk3368_pll_clks,
+                                  ARRAY_SIZE(rk3368_pll_clks),
+                                  RK3368_GRF_SOC_STATUS0);
+       rockchip_clk_register_branches(rk3368_clk_branches,
+                                 ARRAY_SIZE(rk3368_clk_branches));
+
+       rockchip_clk_register_armclk(ARMCLKB, "armclkb",
+                       mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
+                       &rk3368_cpuclkb_data, rk3368_cpuclkb_rates,
+                       ARRAY_SIZE(rk3368_cpuclkb_rates));
+
+       rockchip_clk_register_armclk(ARMCLKL, "armclkl",
+                       mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+                       &rk3368_cpuclkl_data, rk3368_cpuclkl_rates,
+                       ARRAY_SIZE(rk3368_cpuclkl_rates));
+
+       rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
+                                 ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+       rockchip_register_restart_notifier(RK3368_GLB_SRST_FST);
+}
+CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
index 052b94db0ff93a690dda50339b81ad673c00fadd..24938815655fa847512bf2e970589e112a7d35f7 100644 (file)
@@ -277,6 +277,13 @@ void __init rockchip_clk_register_branches(
                                list->div_shift
                        );
                        break;
+               case branch_inverter:
+                       clk = rockchip_clk_register_inverter(
+                               list->name, list->parent_names,
+                               list->num_parents,
+                               reg_base + list->muxdiv_offset,
+                               list->div_shift, list->div_flags, &clk_lock);
+                       break;
                }
 
                /* none of the cases above matched */
index 6b092673048a2514399bd07cf156aefb081fb56a..dc8ecb2673b7b2a249befe3de93a4b39493f3134 100644 (file)
 #define CLK_ROCKCHIP_CLK_H
 
 #include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
+
+struct clk;
 
 #define HIWORD_UPDATE(val, mask, shift) \
                ((val) << (shift) | (mask) << ((shift) + 16))
 
 /* register positions shared by RK2928, RK3066 and RK3188 */
-#define RK2928_PLL_CON(x)              (x * 0x4)
+#define RK2928_PLL_CON(x)              ((x) * 0x4)
 #define RK2928_MODE_CON                0x40
-#define RK2928_CLKSEL_CON(x)   (x * 0x4 + 0x44)
-#define RK2928_CLKGATE_CON(x)  (x * 0x4 + 0xd0)
+#define RK2928_CLKSEL_CON(x)   ((x) * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x)  ((x) * 0x4 + 0xd0)
 #define RK2928_GLB_SRST_FST            0x100
 #define RK2928_GLB_SRST_SND            0x104
-#define RK2928_SOFTRST_CON(x)  (x * 0x4 + 0x110)
+#define RK2928_SOFTRST_CON(x)  ((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON                0x134
 
 #define RK3288_PLL_CON(x)              RK2928_PLL_CON(x)
 #define RK3288_MODE_CON                        0x50
-#define RK3288_CLKSEL_CON(x)           (x * 0x4 + 0x60)
-#define RK3288_CLKGATE_CON(x)          (x * 0x4 + 0x160)
+#define RK3288_CLKSEL_CON(x)           ((x) * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x)          ((x) * 0x4 + 0x160)
 #define RK3288_GLB_SRST_FST            0x1b0
 #define RK3288_GLB_SRST_SND            0x1b4
-#define RK3288_SOFTRST_CON(x)          (x * 0x4 + 0x1b8)
+#define RK3288_SOFTRST_CON(x)          ((x) * 0x4 + 0x1b8)
 #define RK3288_MISC_CON                        0x1e8
 #define RK3288_SDMMC_CON0              0x200
 #define RK3288_SDMMC_CON1              0x204
 #define RK3288_EMMC_CON0               0x218
 #define RK3288_EMMC_CON1               0x21c
 
+#define RK3368_PLL_CON(x)              RK2928_PLL_CON(x)
+#define RK3368_CLKSEL_CON(x)           ((x) * 0x4 + 0x100)
+#define RK3368_CLKGATE_CON(x)          ((x) * 0x4 + 0x200)
+#define RK3368_GLB_SRST_FST            0x280
+#define RK3368_GLB_SRST_SND            0x284
+#define RK3368_SOFTRST_CON(x)          ((x) * 0x4 + 0x300)
+#define RK3368_MISC_CON                        0x380
+#define RK3368_SDMMC_CON0              0x400
+#define RK3368_SDMMC_CON1              0x404
+#define RK3368_SDIO0_CON0              0x408
+#define RK3368_SDIO0_CON1              0x40c
+#define RK3368_SDIO1_CON0              0x410
+#define RK3368_SDIO1_CON1              0x414
+#define RK3368_EMMC_CON0               0x418
+#define RK3368_EMMC_CON1               0x41c
+
 enum rockchip_pll_type {
        pll_rk3066,
 };
@@ -67,16 +83,16 @@ enum rockchip_pll_type {
        .nr = _nr,                              \
        .nf = _nf,                              \
        .no = _no,                              \
-       .bwadj = (_nf >> 1),                    \
+       .nb = ((_nf) < 2) ? 1 : (_nf) >> 1,     \
 }
 
-#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw)       \
+#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb)          \
 {                                                              \
        .rate   = _rate##U,                                     \
        .nr = _nr,                                              \
        .nf = _nf,                                              \
        .no = _no,                                              \
-       .bwadj = _bw,                                           \
+       .nb = _nb,                                              \
 }
 
 struct rockchip_pll_rate_table {
@@ -84,7 +100,7 @@ struct rockchip_pll_rate_table {
        unsigned int nr;
        unsigned int nf;
        unsigned int no;
-       unsigned int bwadj;
+       unsigned int nb;
 };
 
 /**
@@ -182,6 +198,13 @@ struct clk *rockchip_clk_register_mmc(const char *name,
                                const char *const *parent_names, u8 num_parents,
                                void __iomem *reg, int shift);
 
+#define ROCKCHIP_INVERTER_HIWORD_MASK  BIT(0)
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+                               const char *const *parent_names, u8 num_parents,
+                               void __iomem *reg, int shift, int flags,
+                               spinlock_t *lock);
+
 #define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
@@ -191,6 +214,7 @@ enum rockchip_clk_branch_type {
        branch_fraction_divider,
        branch_gate,
        branch_mmc,
+       branch_inverter,
 };
 
 struct rockchip_clk_branch {
@@ -308,6 +332,26 @@ struct rockchip_clk_branch {
                .gate_offset    = -1,                           \
        }
 
+#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \
+                               mw, mf, ds, dw, df, dt)         \
+       {                                                       \
+               .id             = _id,                          \
+               .branch_type    = branch_composite,             \
+               .name           = cname,                        \
+               .parent_names   = pnames,                       \
+               .num_parents    = ARRAY_SIZE(pnames),           \
+               .flags          = f,                            \
+               .muxdiv_offset  = mo,                           \
+               .mux_shift      = ms,                           \
+               .mux_width      = mw,                           \
+               .mux_flags      = mf,                           \
+               .div_shift      = ds,                           \
+               .div_width      = dw,                           \
+               .div_flags      = df,                           \
+               .div_table      = dt,                           \
+               .gate_offset    = -1,                           \
+       }
+
 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
        {                                                       \
                .id             = _id,                          \
@@ -394,6 +438,18 @@ struct rockchip_clk_branch {
                .div_shift      = shift,                        \
        }
 
+#define INVERTER(_id, cname, pname, io, is, if)                        \
+       {                                                       \
+               .id             = _id,                          \
+               .branch_type    = branch_inverter,              \
+               .name           = cname,                        \
+               .parent_names   = (const char *[]){ pname },    \
+               .num_parents    = 1,                            \
+               .muxdiv_offset  = io,                           \
+               .div_shift      = is,                           \
+               .div_flags      = if,                           \
+       }
+
 void rockchip_clk_init(struct device_node *np, void __iomem *base,
                       unsigned long nr_clks);
 struct regmap *rockchip_clk_get_grf(void);
index 3a1fe07cfe9e7b306ddd2eebd22531f81492a512..7c1e1f58e2da2e7dc7909fce407bc477651add3a 100644 (file)
@@ -33,6 +33,9 @@
 */
 
 #include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include "clk-cpu.h"
 
 #define E4210_SRC_CPU          0x0
@@ -97,8 +100,8 @@ static void wait_until_mux_stable(void __iomem *mux_reg, u32 mux_pos,
 static long exynos_cpuclk_round_rate(struct clk_hw *hw,
                        unsigned long drate, unsigned long *prate)
 {
-       struct clk *parent = __clk_get_parent(hw->clk);
-       *prate = __clk_round_rate(parent, drate);
+       struct clk_hw *parent = clk_hw_get_parent(hw);
+       *prate = clk_hw_round_rate(parent, drate);
        return *prate;
 }
 
index 454b02ae486a86917f31614c2c4b016841deefaa..4e9584d79089d355fcc67b4154724f4d6cc2ed62 100644 (file)
@@ -9,8 +9,9 @@
  * Common Clock Framework support for Audio Subsystem Clock Controller.
 */
 
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 03a52228b6d1f1a4a280fcca7862b2aea2b79c0d..7cd02ff37a1f6919fea89e6c1a6306fd3695dc28 100644 (file)
@@ -9,8 +9,8 @@
  * Clock driver for Exynos clock output
  */
 
+#include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 538de66a759e12092e70b385e579bbc112133ca3..fdd41b17a24fc590254768e346f10d7e0b253321 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for Exynos3250 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -19,6 +17,7 @@
 #include <dt-bindings/clock/exynos3250.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 #include "clk-pll.h"
 
 #define SRC_LEFTBUS            0x4200
@@ -319,8 +318,10 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
        MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p,
            SRC_CPU, 24, 1),
        MUX(CLK_MOUT_HPM, "mout_hpm", mout_hpm_p, SRC_CPU, 20, 1),
-       MUX(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1),
-       MUX(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
+       MUX_F(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+                       CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock div_clks[] __initdata = {
@@ -772,6 +773,26 @@ static struct samsung_cmu_info cmu_info __initdata = {
        .nr_clk_regs            = ARRAY_SIZE(exynos3250_cmu_clk_regs),
 };
 
+#define E3250_CPU_DIV0(apll, pclk_dbg, atb, corem)                     \
+               (((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) |  \
+               ((corem) << 4))
+#define E3250_CPU_DIV1(hpm, copy)                                      \
+               (((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data e3250_armclk_d[] __initconst = {
+       { 1000000, E3250_CPU_DIV0(1, 7, 4, 1), E3250_CPU_DIV1(7, 7), },
+       {  900000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  800000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  700000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  600000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  500000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  400000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  300000, E3250_CPU_DIV0(1, 5, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  200000, E3250_CPU_DIV0(1, 3, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  100000, E3250_CPU_DIV0(1, 1, 1, 1), E3250_CPU_DIV1(7, 7), },
+       {  0 },
+};
+
 static void __init exynos3250_cmu_init(struct device_node *np)
 {
        struct samsung_clk_provider *ctx;
@@ -780,6 +801,11 @@ static void __init exynos3250_cmu_init(struct device_node *np)
        if (!ctx)
                return;
 
+       exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+                       mout_core_p[0], mout_core_p[1], 0x14200,
+                       e3250_armclk_d, ARRAY_SIZE(e3250_armclk_d),
+                       CLK_CPU_HAS_DIV1);
+
        exynos3_core_down_clock(ctx->reg_base);
 }
 CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
index cae2c048488db3e7a4c3545c81faa50f450797d7..251f48dcd12d5fa344a80d370bd6177c7f705091 100644 (file)
@@ -11,8 +11,8 @@
 */
 
 #include <dt-bindings/clock/exynos4.h>
+#include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -86,6 +86,7 @@
 #define DIV_PERIL4             0xc560
 #define DIV_PERIL5             0xc564
 #define E4X12_DIV_CAM1         0xc568
+#define E4X12_GATE_BUS_FSYS1   0xc744
 #define GATE_SCLK_CAM          0xc820
 #define GATE_IP_CAM            0xc920
 #define GATE_IP_TV             0xc924
@@ -1097,6 +1098,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
                0),
        GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4X12_GATE_IP_IMAGE, 9, 0,
                0),
+       GATE(CLK_TSADC, "tsadc", "aclk133", E4X12_GATE_BUS_FSYS1, 16, 0, 0),
        GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
        GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
        GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
index 6c78b09c829f9148453f56d4f05981452f91487c..92c39f6efec82a1617881e2dd75d3261dcc4d007 100644 (file)
@@ -9,8 +9,6 @@
  * Common Clock Framework support for Exynos4415 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 70ec3d2608a17e2f282e65dc198cd6af9c3fbbb9..55b83c7ef878bfa8c3fbb683fc6ba329db4a58c3 100644 (file)
 */
 
 #include <dt-bindings/clock/exynos5250.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 
 #define APLL_LOCK              0x0
 #define APLL_CON0              0x100
@@ -748,6 +747,32 @@ static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
                VPLL_LOCK, VPLL_CON0, NULL),
 };
 
+#define E5250_CPU_DIV0(apll, pclk_dbg, atb, periph, acp, cpud)         \
+               ((((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
+                ((periph) << 12) | ((acp) << 8) | ((cpud) << 4)))
+#define E5250_CPU_DIV1(hpm, copy)                                      \
+               (((hpm) << 4) | (copy))
+
+static const struct exynos_cpuclk_cfg_data exynos5250_armclk_d[] __initconst = {
+       { 1700000, E5250_CPU_DIV0(5, 3, 7, 7, 7, 3), E5250_CPU_DIV1(2, 0), },
+       { 1600000, E5250_CPU_DIV0(4, 1, 7, 7, 7, 3), E5250_CPU_DIV1(2, 0), },
+       { 1500000, E5250_CPU_DIV0(4, 1, 7, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1400000, E5250_CPU_DIV0(4, 1, 6, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1300000, E5250_CPU_DIV0(3, 1, 6, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1200000, E5250_CPU_DIV0(3, 1, 5, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1100000, E5250_CPU_DIV0(3, 1, 5, 7, 7, 3), E5250_CPU_DIV1(2, 0), },
+       { 1000000, E5250_CPU_DIV0(2, 1, 4, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  900000, E5250_CPU_DIV0(2, 1, 4, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  800000, E5250_CPU_DIV0(2, 1, 4, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  700000, E5250_CPU_DIV0(1, 1, 3, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  600000, E5250_CPU_DIV0(1, 1, 3, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  500000, E5250_CPU_DIV0(1, 1, 2, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  400000, E5250_CPU_DIV0(1, 1, 2, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  300000, E5250_CPU_DIV0(1, 1, 1, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  200000, E5250_CPU_DIV0(1, 1, 1, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  0 },
+};
+
 static const struct of_device_id ext_clk_match[] __initconst = {
        { .compatible = "samsung,clock-xxti", .data = (void *)0, },
        { },
@@ -797,6 +822,10 @@ static void __init exynos5250_clk_init(struct device_node *np)
                        ARRAY_SIZE(exynos5250_div_clks));
        samsung_clk_register_gate(ctx, exynos5250_gate_clks,
                        ARRAY_SIZE(exynos5250_gate_clks));
+       exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+                       mout_cpu_p[0], mout_cpu_p[1], 0x200,
+                       exynos5250_armclk_d, ARRAY_SIZE(exynos5250_armclk_d),
+                       CLK_CPU_HAS_DIV1);
 
        /*
         * Enable arm clock down (in idle) and set arm divider
index 06f96eb7cf93c5b4c7d946d41b57b30078042db2..d1a29f6c10849f0a0023c7a040a9b55248c81e9a 100644 (file)
@@ -9,8 +9,6 @@
  * Common Clock Framework support for Exynos5260 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 231475bc2b99604ef16351ba49a3874c61d974b3..d5d5dcabc4a968c490a768634f28d8cd04327c93 100644 (file)
@@ -11,8 +11,6 @@
 
 #include <dt-bindings/clock/exynos5410.h>
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index a1d731ca8f48587870753182a1ef76db82072686..389af3c15ec450bf9bf8e8526dca3cf00c958a57 100644 (file)
@@ -11,8 +11,7 @@
 */
 
 #include <dt-bindings/clock/exynos5420.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 39c95649d3d016d14da7500e5b5ea188860252c9..cee062c588dec2c2471b55c4c2b60a44d20ec42f 100644 (file)
@@ -9,8 +9,6 @@
  * Common Clock Framework support for Exynos5443 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 
index 979e81389cdd04bf668f6982ea2ceee5ebb17f82..590813871ffe2bf80ab33be555ce036ea131d6b5 100644 (file)
@@ -10,8 +10,6 @@
 */
 
 #include <dt-bindings/clock/exynos5440.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 03d36e847b78e067d16bdfe1758df10560c4a2b4..8524e667097e062cf426a1e4b18cd1eb0c90e708 100644 (file)
@@ -8,8 +8,6 @@
  *
 */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 
index bebc61b5fce1f3741200bf146e6dd059a222f5b9..b7dd396100d8118381caebffade2ff7e3acf831d 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/errno.h>
 #include <linux/hrtimer.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
 #include "clk.h"
 #include "clk-pll.h"
 
@@ -180,7 +182,7 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -288,7 +290,7 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -403,7 +405,7 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -455,7 +457,7 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
 
                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
                        pr_err("%s: could not lock PLL %s\n",
-                                       __func__, __clk_get_name(hw->clk));
+                                       __func__, clk_hw_get_name(hw));
                        return -EFAULT;
                }
 
@@ -554,7 +556,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -614,7 +616,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
 
                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
                        pr_err("%s: could not lock PLL %s\n",
-                                       __func__, __clk_get_name(hw->clk));
+                                       __func__, clk_hw_get_name(hw));
                        return -EFAULT;
                }
 
@@ -772,7 +774,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -1013,7 +1015,7 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -1111,7 +1113,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
index e56df5064889e00530ddf8c531e29539debecc76..e9eb935d7616b370717deb858e7196310ab7b5fe 100644 (file)
@@ -8,6 +8,10 @@
  * Common Clock Framework support for s3c24xx external clock output.
  */
 
+#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include "clk.h"
@@ -57,7 +61,7 @@ struct s3c24xx_clkout {
 static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
 {
        struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
        val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift;
index 5d2f03461bc5d2fe6cf4acd6ef11b379ef25e0bd..0945a8852299d5f779bcaba6827efae37cb6653b 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for S3C2410 and following SoCs.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 2ceedaf8ce18a6e411cc3e229f311805939535cd..44d6a9f4f5b2f7d1d203f7257d708f6dc42d7590 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for S3C2412 and S3C2413.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 0c3c182b902af709313d69f72477b9f46f187e89..2c0a1ea3c80c7eda87d73b2d0aeb6375009c9e8a 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for S3C2443 and following SoCs.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 0f590e5550cb237ed1e73c836205ef501d723a78..d325ed1e196bf4f536938edb12dce790666fa3db 100644 (file)
@@ -8,8 +8,7 @@
  * Common Clock Framework support for all S3C64xx SoCs.
 */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index de4455b75e8a3be51c22d4064b83a066a7bc4fc6..eefb84b2256650294618b168a23b60d4ca170f74 100644 (file)
@@ -13,8 +13,8 @@
  * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
 */
 
-#include <linux/clkdev.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index cf7e8fa7b624c701511d7cefadb4c721221ec1bd..759aaf342bea986db7414374e6805df2bf24aa5e 100644 (file)
@@ -11,8 +11,6 @@
  * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -828,6 +826,8 @@ static void __init __s5pv210_clk_init(struct device_node *np,
 
        s5pv210_clk_sleep_init();
 
+       samsung_clk_of_add_provider(np, ctx);
+
        pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
                "\tmout_epll = %ld, mout_vpll = %ld\n",
                is_s5p6442 ? "S5P6442" : "S5PV210",
index 0117238391d6532b5b332a0ba09d319b693c03aa..f38a6c49f7449cc1293910ec5c9eacf8df8544aa 100644 (file)
  * clock framework for Samsung platforms.
 */
 
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 
index b775fc29caa507dcaccfa1e54d78fef2f7d4a45b..aa872d2c51052a7f81181aabd57b249c55ea0afc 100644 (file)
 #ifndef __SAMSUNG_CLK_H
 #define __SAMSUNG_CLK_H
 
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include "clk-pll.h"
 
+struct clk;
+
 /**
  * struct samsung_clk_provider: information about clock provider
  * @reg_base: virtual address for the register base.
index 036a692c72195db93760e40dc1fcb1928b1ecded..b4c8d6746f68a7b843efef38de7f6941483690e2 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 
 #define CPG_DIV6_CKSTP         BIT(8)
 #define CPG_DIV6_DIV(d)                ((d) & 0x3f)
@@ -133,13 +133,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
 
        hw_index = (clk_readl(clock->reg) >> clock->src_shift) &
                   (BIT(clock->src_width) - 1);
-       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
                if (clock->parents[i] == hw_index)
                        return i;
        }
 
        pr_err("%s: %s DIV6 clock set to invalid parent %u\n",
-              __func__, __clk_get_name(hw->clk), hw_index);
+              __func__, clk_hw_get_name(hw), hw_index);
        return 0;
 }
 
@@ -149,7 +149,7 @@ static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
        u8 hw_index;
        u32 mask;
 
-       if (index >= __clk_get_num_parents(hw->clk))
+       if (index >= clk_hw_get_num_parents(hw))
                return -EINVAL;
 
        mask = ~((BIT(clock->src_width) - 1) << clock->src_shift);
index 29b9a0b0012ad3260d882be6d5dbb40f3fabaf0d..9326204bed9d6cb7734cfb7b84b80252abcaba7a 100644 (file)
@@ -9,10 +9,10 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/spinlock.h>
index 1e2eaae21e01947b1d2998fd80c3184d32020de3..1e6b1da580658f46e6fc31f42c054760e52e0af6 100644 (file)
@@ -9,10 +9,10 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/spinlock.h>
index cb33b57274bf9f55c016637bddd410610fc6dd26..e97e28fcfc13d102d5ea75566dd4eb97a59a83d4 100644 (file)
@@ -9,9 +9,9 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 
 struct r8a7778_cpg {
        struct clk_onecell_data data;
index 652ecacb6daf79222644252c4886e4df1c5938f1..af297963489f473d82ced3db8237135ddd47d99d 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #include <dt-bindings/clock/r8a7779-clock.h>
index acfb6d7dbd6bc049fe39213d675d5a2602e65d9e..9233ebf8cc49f933d0343cccf8c11a2a4f11ae58 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 struct rcar_gen2_cpg {
index cd529cfe412f1d186bb07e2936b7e1e512cfd9a1..8966f8bbfd726e62f19cc997d2e2c1046aec0b09 100644 (file)
@@ -9,12 +9,12 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 struct sh73a0_cpg {
index d63b76ca60c311edd1dcb66ef35d364e0cb27247..c5eaa9d1624760f6db1347cdbeaf44c7b97a2049 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
index db8ab691dbf6245d1f1ffee966a92a167c39e33d..a98e21fe773a364739f299aac651ccc4d2e18656 100644 (file)
@@ -358,6 +358,7 @@ static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
        if (regctrl0 & SIRFSOC_ABPLL_CTRL0_SSEN) {
                rate = fin;
                rate *= 1 << 24;
+               do_div(rate, nr);
                do_div(rate, (256 * ((ssdiv >> ssdepth) << ssdepth)
                        + (ssmod << ssdepth)));
        } else {
@@ -465,6 +466,9 @@ static struct clk_pll clk_sys3pll = {
  *  double resolution mode:fout = fin * finc / 2^29
  *  normal mode:fout = fin * finc / 2^28
  */
+#define DTO_RESL_DOUBLE        (1ULL << 29)
+#define DTO_RESL_NORMAL        (1ULL << 28)
+
 static int dto_clk_is_enabled(struct clk_hw *hw)
 {
        struct clk_dto *clk = to_dtoclk(hw);
@@ -509,9 +513,9 @@ static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
        rate *= finc;
        if (droff & BIT(0))
                /* Double resolution off */
-               do_div(rate, 1 << 28);
+               do_div(rate, DTO_RESL_NORMAL);
        else
-               do_div(rate, 1 << 29);
+               do_div(rate, DTO_RESL_DOUBLE);
 
        return rate;
 }
@@ -519,11 +523,11 @@ static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
 static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long *parent_rate)
 {
-       u64 dividend = rate * (1 << 29);
+       u64 dividend = rate * DTO_RESL_DOUBLE;
 
        do_div(dividend, *parent_rate);
        dividend *= *parent_rate;
-       do_div(dividend, 1 << 29);
+       do_div(dividend, DTO_RESL_DOUBLE);
 
        return dividend;
 }
@@ -531,7 +535,7 @@ static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 static int dto_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long parent_rate)
 {
-       u64 dividend = rate * (1 << 29);
+       u64 dividend = rate * DTO_RESL_DOUBLE;
        struct clk_dto *clk = to_dtoclk(hw);
 
        do_div(dividend, parent_rate);
@@ -1161,7 +1165,7 @@ static struct atlas7_unit_init_data unit_list[] __initdata = {
        { 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
        { 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
        { 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
-       { 125, "thcpum_cpudiv4", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
+       { 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
        { 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
        { 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
        { 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
@@ -1174,9 +1178,13 @@ static struct atlas7_unit_init_data unit_list[] __initdata = {
        { 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
        { 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
        { 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
+       { 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, &leaf0_gate_lock },
+       { 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, &leaf0_gate_lock },
+       { 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, &leaf0_gate_lock },
+       { 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, &leaf0_gate_lock },
 };
 
-static struct clk *atlas7_clks[ARRAY_SIZE(unit_list)];
+static struct clk *atlas7_clks[ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list)];
 
 static int unit_clk_is_enabled(struct clk_hw *hw)
 {
@@ -1609,6 +1617,7 @@ static void __init atlas7_clk_init(struct device_node *np)
                               sirfsoc_clk_vbase + mux->mux_offset,
                               mux->shift, mux->width,
                               mux->mux_flags, NULL);
+               atlas7_clks[ARRAY_SIZE(unit_list) + i] = clk;
                BUG_ON(!clk);
        }
 
@@ -1620,7 +1629,7 @@ static void __init atlas7_clk_init(struct device_node *np)
        }
 
        clk_data.clks = atlas7_clks;
-       clk_data.clk_num = ARRAY_SIZE(unit_list);
+       clk_data.clk_num = ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list);
 
        ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
        BUG_ON(ret);
index 9fc285d784d3faa4b78eac774cc466b989b8d667..77e1e2491689b9c37e943c43e8fabf5778a561aa 100644 (file)
@@ -7,6 +7,8 @@
  * Licensed under GPLv2 or later.
  */
 
+#include <linux/clk.h>
+
 #define KHZ     1000
 #define MHZ     (KHZ * KHZ)
 
@@ -165,10 +167,10 @@ static long cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
         * SiRF SoC has not cpu clock control,
         * So bypass to it's parent pll.
         */
-       struct clk *parent_clk = clk_get_parent(hw->clk);
-       struct clk *pll_parent_clk = clk_get_parent(parent_clk);
-       unsigned long pll_parent_rate = clk_get_rate(pll_parent_clk);
-       return pll_clk_round_rate(__clk_get_hw(parent_clk), rate, &pll_parent_rate);
+       struct clk_hw *parent_clk = clk_hw_get_parent(hw);
+       struct clk_hw *pll_parent_clk = clk_hw_get_parent(parent_clk);
+       unsigned long pll_parent_rate = clk_hw_get_rate(pll_parent_clk);
+       return pll_clk_round_rate(parent_clk, rate, &pll_parent_rate);
 }
 
 static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw,
@@ -178,8 +180,8 @@ static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw,
         * SiRF SoC has not cpu clock control,
         * So return the parent pll rate.
         */
-       struct clk *parent_clk = clk_get_parent(hw->clk);
-       return __clk_get_rate(parent_clk);
+       struct clk_hw *parent_clk = clk_hw_get_parent(hw);
+       return clk_hw_get_rate(parent_clk);
 }
 
 static struct clk_ops std_pll_ops = {
index 6968e2ebcd8a4d09959d02b2edbf5ffe19e7b9da..f92c40264342574af6fbf2af02de0e3db4236602 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
index 83c6780ff4b2e47dea9db1674fbffadb2bcfcd3a..1cebf253e8fd44dbe22e37e1eb6a18ed63cd2f14 100644 (file)
@@ -13,6 +13,7 @@
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
@@ -38,7 +39,7 @@ static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
                div = socfpgaclk->fixed_div;
        else if (socfpgaclk->div_reg) {
                val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-               val &= div_mask(socfpgaclk->width);
+               val &= GENMASK(socfpgaclk->width - 1, 0);
                div = (1 << val);
        }
 
index 82449cd76fd7e3ebb9b98b39ce81682eb1105173..aa7a6e6a15b656808d3cc9f92229125cb2baea81 100644 (file)
@@ -15,8 +15,7 @@
  * Based from clk-highbank.c
  *
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
@@ -106,7 +105,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
                div = socfpgaclk->fixed_div;
        else if (socfpgaclk->div_reg) {
                val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-               val &= div_mask(socfpgaclk->width);
+               val &= GENMASK(socfpgaclk->width - 1, 0);
                /* Check for GPIO_DB_CLK by its offset */
                if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET)
                        div = val + 1;
index 9d0181b5a6a48d4990b1d2844b194e94cb851a81..1f397cb72e89a8ff421edfaf92cddf2fee1e16a8 100644 (file)
@@ -13,6 +13,7 @@
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -37,7 +38,7 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
                div = socfpgaclk->fixed_div;
        } else if (socfpgaclk->div_reg) {
                div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-               div &= div_mask(socfpgaclk->width);
+               div &= GENMASK(socfpgaclk->width - 1, 0);
                div += 1;
        } else {
                div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
index 83aeaa219d14e82800976e476fc24a72a0f032a9..52c883ea7706715d18b9ec8dc676fbc98060acd7 100644 (file)
@@ -15,8 +15,7 @@
  * Based from clk-highbank.c
  *
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -36,7 +35,7 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
        } else {
                if (socfpgaclk->div_reg) {
                        val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-                       val &= div_mask(socfpgaclk->width);
+                       val &= GENMASK(socfpgaclk->width - 1, 0);
                        parent_rate /= (val + 1);
                }
                div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
@@ -45,8 +44,17 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
        return parent_rate / div;
 }
 
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+       u32 clk_src;
+
+       clk_src = readl(clk_mgr_base_addr + CLKMGR_DBCTRL);
+       return clk_src & 0x1;
+}
+
 static const struct clk_ops periclk_ops = {
        .recalc_rate = clk_periclk_recalc_rate,
+       .get_parent = clk_periclk_get_parent,
 };
 
 static __init void __socfpga_periph_init(struct device_node *node,
@@ -56,7 +64,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
        struct clk *clk;
        struct socfpga_periph_clk *periph_clk;
        const char *clk_name = node->name;
-       const char *parent_name;
+       const char *parent_name[SOCFPGA_MAX_PARENTS];
        struct clk_init_data init;
        int rc;
        u32 fixed_div;
@@ -90,9 +98,10 @@ static __init void __socfpga_periph_init(struct device_node *node,
        init.name = clk_name;
        init.ops = ops;
        init.flags = 0;
-       parent_name = of_clk_get_parent_name(node, 0);
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
+
+       init.num_parents = of_clk_parent_fill(node, parent_name,
+                                             SOCFPGA_MAX_PARENTS);
+       init.parent_names = parent_name;
 
        periph_clk->hw.hw.init = &init;
 
index 1178b11babca028ff6ba7c11a7408d11d65d4f08..402d630bd531ecf65ee15ba3f70966afe33cb8e7 100644 (file)
@@ -13,6 +13,7 @@
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 8f26b5234947eafca2649fdbce3262db4351f8bd..c7f463172e4b93d0cec4b46e45558a301aa16234 100644 (file)
@@ -15,8 +15,7 @@
  * Based from clk-highbank.c
  *
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 603973ab7e2914d0da3c39e56d7613dd8263ee19..814c7247bf73b071fcc2f19770a005425b404294 100644 (file)
 #define __SOCFPGA_CLK_H
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 
 /* Clock Manager offsets */
 #define CLKMGR_CTRL            0x0
 #define CLKMGR_BYPASS          0x4
+#define CLKMGR_DBCTRL          0x10
 #define CLKMGR_L4SRC           0x70
 #define CLKMGR_PERPLL_SRC      0xAC
 
 #define SOCFPGA_MAX_PARENTS            5
-#define div_mask(width) ((1 << (width)) - 1)
 
 #define streq(a, b) (strcmp((a), (b)) == 0)
 #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
index 5ebddc528145bb82827c2a6895b5467fb6dfaeca..dc21ca4601aab28ce2eba866e2d00e0e33f9dbe1 100644 (file)
@@ -87,7 +87,7 @@ static long clk_pll_round_rate_index(struct clk_hw *hw, unsigned long drate,
        struct clk_pll *pll = to_clk_pll(hw);
        unsigned long prev_rate, vco_prev_rate, rate = 0;
        unsigned long vco_parent_rate =
-               __clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk)));
+               clk_hw_get_rate(clk_hw_get_parent(clk_hw_get_parent(hw)));
 
        if (!prate) {
                pr_err("%s: prate is must for pll clk\n", __func__);
index 222ce108b41a0e48afd4bf2d370a535d24511774..009bd1410cfa87759d6aa3c224dbd3a1c64e832f 100644 (file)
@@ -11,7 +11,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 973c9d3fbcf82285e2a6bf6412cb15fe602a892e..9c7abfd951baa2fa91950dd0e4b0a2a76f8fecb5 100644 (file)
@@ -11,7 +11,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 231061fa73a4309b0744d2a8dda0d68bddeda5e0..e24f85cd4300f39845f8bd8dd065ee5fceb1940b 100644 (file)
@@ -9,7 +9,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/spinlock_types.h>
index 8dd8cce273617e1db85c8af512a431cef14cf328..bd355ee33766b807556c848fcabeeb0c9293a187 100644 (file)
@@ -5,6 +5,7 @@
  * Author:  Maxime Coquelin <maxime.coquelin@st.com> for ST-Microelectronics.
  * License terms:  GNU General Public License (GPL), version 2  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -44,7 +45,7 @@ static int flexgen_enable(struct clk_hw *hw)
 
        clk_gate_ops.enable(fgate_hw);
 
-       pr_debug("%s: flexgen output enabled\n", __clk_get_name(hw->clk));
+       pr_debug("%s: flexgen output enabled\n", clk_hw_get_name(hw));
        return 0;
 }
 
@@ -58,7 +59,7 @@ static void flexgen_disable(struct clk_hw *hw)
 
        clk_gate_ops.disable(fgate_hw);
 
-       pr_debug("%s: flexgen output disabled\n", __clk_get_name(hw->clk));
+       pr_debug("%s: flexgen output disabled\n", clk_hw_get_name(hw));
 }
 
 static int flexgen_is_enabled(struct clk_hw *hw)
@@ -108,7 +109,7 @@ static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
        /* Round div according to exact prate and wished rate */
        div = clk_best_div(*prate, rate);
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                *prate = rate * div;
                return rate;
        }
@@ -243,7 +244,7 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
                                                       int *num_parents)
 {
        const char **parents;
-       int nparents, i;
+       int nparents;
 
        nparents = of_clk_get_parent_count(np);
        if (WARN_ON(nparents <= 0))
@@ -253,10 +254,8 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
        if (!parents)
                return NULL;
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
+       *num_parents = of_clk_parent_fill(np, parents, nparents);
 
-       *num_parents = nparents;
        return parents;
 }
 
index d9eb2e1d84710c34abe8b656b4dd5e89a1ac7f9a..83ccf142ff2acaea7b5d4f3cf9d8f6475d1f6093 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #include "clkgen.h"
@@ -512,7 +513,7 @@ static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
        params.ndiv = CLKGEN_READ(pll, ndiv);
        if (clk_fs660c32_vco_get_rate(parent_rate, &params, &rate))
                pr_err("%s:%s error calculating rate\n",
-                      __clk_get_name(hw->clk), __func__);
+                      clk_hw_get_name(hw), __func__);
 
        pll->ndiv = params.ndiv;
 
@@ -557,7 +558,7 @@ static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate
                clk_fs660c32_vco_get_rate(*prate, &params, &rate);
 
        pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
-                __func__, __clk_get_name(hw->clk),
+                __func__, clk_hw_get_name(hw),
                 rate, (unsigned int)params.sdiv,
                 (unsigned int)params.mdiv,
                 (unsigned int)params.pe, (unsigned int)params.nsdiv);
@@ -580,7 +581,7 @@ static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
                clk_fs660c32_vco_get_rate(parent_rate, &params, &hwrate);
 
        pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n",
-                __func__, __clk_get_name(hw->clk),
+                __func__, clk_hw_get_name(hw),
                 hwrate, (unsigned int)params.ndiv);
 
        if (!hwrate)
@@ -744,7 +745,7 @@ static int quadfs_fsynth_enable(struct clk_hw *hw)
        struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
        unsigned long flags = 0;
 
-       pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+       pr_debug("%s: %s\n", __func__, clk_hw_get_name(hw));
 
        quadfs_fsynth_program_rate(fs);
 
@@ -769,7 +770,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw)
        struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
        unsigned long flags = 0;
 
-       pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+       pr_debug("%s: %s\n", __func__, clk_hw_get_name(hw));
 
        if (fs->lock)
                spin_lock_irqsave(fs->lock, flags);
@@ -786,7 +787,7 @@ static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
        u32 nsb = CLKGEN_READ(fs, nsb[fs->chan]);
 
        pr_debug("%s: %s enable bit = 0x%x\n",
-                __func__, __clk_get_name(hw->clk), nsb);
+                __func__, clk_hw_get_name(hw), nsb);
 
        return fs->data->standby_polarity ? !nsb : !!nsb;
 }
@@ -945,10 +946,10 @@ static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
 
        if (clk_fs_get_rate(parent_rate, &params, &rate)) {
                pr_err("%s:%s error calculating rate\n",
-                      __clk_get_name(hw->clk), __func__);
+                      clk_hw_get_name(hw), __func__);
        }
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
@@ -961,7 +962,7 @@ static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
        rate = quadfs_find_best_rate(hw, rate, *prate, &params);
 
        pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
-                __func__, __clk_get_name(hw->clk),
+                __func__, clk_hw_get_name(hw),
                 rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
                         (unsigned int)params.pe, (unsigned int)params.nsdiv);
 
index 717c4a91a17b12643146eb028ed02dd0727eac50..4f7f6c00b219dc005e98e5fc68733742c93efdcf 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
@@ -24,20 +25,17 @@ static const char ** __init clkgen_mux_get_parents(struct device_node *np,
                                                       int *num_parents)
 {
        const char **parents;
-       int nparents, i;
+       int nparents;
 
        nparents = of_clk_get_parent_count(np);
        if (WARN_ON(nparents <= 0))
                return ERR_PTR(-EINVAL);
 
-       parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL);
+       parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL);
        if (!parents)
                return ERR_PTR(-ENOMEM);
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
-
-       *num_parents = nparents;
+       *num_parents = of_clk_parent_fill(np, parents, nparents);
        return parents;
 }
 
@@ -141,7 +139,7 @@ static u8 clkgena_divmux_get_parent(struct clk_hw *hw)
        genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
        if ((s8)genamux->muxsel < 0) {
                pr_debug("%s: %s: Invalid parent, setting to default.\n",
-                     __func__, __clk_get_name(hw->clk));
+                     __func__, clk_hw_get_name(hw));
                genamux->muxsel = 0;
        }
 
@@ -215,7 +213,7 @@ static const struct clk_ops clkgena_divmux_ops = {
 /**
  * clk_register_genamux - register a genamux clock with the clock framework
  */
-static struct clk *clk_register_genamux(const char *name,
+static struct clk * __init clk_register_genamux(const char *name,
                                const char **parent_names, u8 num_parents,
                                void __iomem *reg,
                                const struct clkgena_divmux_data *muxdata,
@@ -369,11 +367,10 @@ static const struct of_device_id clkgena_divmux_of_match[] = {
        {}
 };
 
-static void __iomem * __init clkgen_get_register_base(
-                               struct device_node *np)
+static void __iomem * __init clkgen_get_register_base(struct device_node *np)
 {
        struct device_node *pnode;
-       void __iomem *reg = NULL;
+       void __iomem *reg;
 
        pnode = of_get_parent(np);
        if (!pnode)
@@ -398,7 +395,7 @@ static void __init st_of_clkgena_divmux_setup(struct device_node *np)
        if (WARN_ON(!match))
                return;
 
-       data = (struct clkgena_divmux_data *)match->data;
+       data = match->data;
 
        reg = clkgen_get_register_base(np);
        if (!reg)
@@ -406,18 +403,18 @@ static void __init st_of_clkgena_divmux_setup(struct device_node *np)
 
        parents = clkgen_mux_get_parents(np, &num_parents);
        if (IS_ERR(parents))
-               return;
+               goto err_parents;
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
-               goto err;
+               goto err_alloc;
 
        clk_data->clk_num = data->num_outputs;
-       clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+       clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
                                 GFP_KERNEL);
 
        if (!clk_data->clks)
-               goto err;
+               goto err_alloc_clks;
 
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
@@ -447,11 +444,13 @@ static void __init st_of_clkgena_divmux_setup(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
        return;
 err:
-       if (clk_data)
-               kfree(clk_data->clks);
-
+       kfree(clk_data->clks);
+err_alloc_clks:
        kfree(clk_data);
+err_alloc:
        kfree(parents);
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup);
 
@@ -491,7 +490,7 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
        void __iomem *reg;
        const char *parent_name, *clk_name;
        struct clk *clk;
-       struct clkgena_prediv_data *data;
+       const struct clkgena_prediv_data *data;
 
        match = of_match_node(clkgena_prediv_of_match, np);
        if (!match) {
@@ -499,7 +498,7 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
                return;
        }
 
-       data = (struct clkgena_prediv_data *)match->data;
+       data = match->data;
 
        reg = clkgen_get_register_base(np);
        if (!reg)
@@ -507,18 +506,18 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
 
        parent_name = of_clk_get_parent_name(np, 0);
        if (!parent_name)
-               return;
+               goto err;
 
        if (of_property_read_string_index(np, "clock-output-names",
                                          0, &clk_name))
-               return;
+               goto err;
 
        clk = clk_register_divider_table(NULL, clk_name, parent_name,
                                         CLK_GET_RATE_NOCACHE,
                                         reg + data->offset, data->shift, 1,
                                         0, data->table, NULL);
        if (IS_ERR(clk))
-               return;
+               goto err;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
        pr_debug("%s: parent %s rate %u\n",
@@ -527,6 +526,8 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
                (unsigned int)clk_get_rate(clk));
 
        return;
+err:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
 
@@ -630,7 +631,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
        void __iomem *reg;
        const char **parents;
        int num_parents;
-       struct clkgen_mux_data *data;
+       const struct clkgen_mux_data *data;
 
        match = of_match_node(mux_of_match, np);
        if (!match) {
@@ -638,7 +639,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
                return;
        }
 
-       data = (struct clkgen_mux_data *)match->data;
+       data = match->data;
 
        reg = of_iomap(np, 0);
        if (!reg) {
@@ -650,7 +651,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
        if (IS_ERR(parents)) {
                pr_err("%s: Failed to get parents (%ld)\n",
                                __func__, PTR_ERR(parents));
-               return;
+               goto err_parents;
        }
 
        clk = clk_register_mux(NULL, np->name, parents, num_parents,
@@ -666,12 +667,14 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
                        __clk_get_name(clk_get_parent(clk)),
                        (unsigned int)clk_get_rate(clk));
 
+       kfree(parents);
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
 
 err:
        kfree(parents);
-
-       return;
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup);
 
@@ -707,12 +710,12 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
        const char **parents;
        int num_parents, i;
        struct clk_onecell_data *clk_data;
-       struct clkgen_vcc_data *data;
+       const struct clkgen_vcc_data *data;
 
        match = of_match_node(vcc_of_match, np);
        if (WARN_ON(!match))
                return;
-       data = (struct clkgen_vcc_data *)match->data;
+       data = match->data;
 
        reg = of_iomap(np, 0);
        if (!reg)
@@ -720,18 +723,18 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
 
        parents = clkgen_mux_get_parents(np, &num_parents);
        if (IS_ERR(parents))
-               return;
+               goto err_parents;
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
-               goto err;
+               goto err_alloc;
 
        clk_data->clk_num = VCC_MAX_CHANNELS;
-       clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+       clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
                                 GFP_KERNEL);
 
        if (!clk_data->clks)
-               goto err;
+               goto err_alloc_clks;
 
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
@@ -750,21 +753,21 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
                if (*clk_name == '\0')
                        continue;
 
-               gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+               gate = kzalloc(sizeof(*gate), GFP_KERNEL);
                if (!gate)
-                       break;
+                       goto err;
 
-               div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+               div = kzalloc(sizeof(*div), GFP_KERNEL);
                if (!div) {
                        kfree(gate);
-                       break;
+                       goto err;
                }
 
-               mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+               mux = kzalloc(sizeof(*mux), GFP_KERNEL);
                if (!mux) {
                        kfree(gate);
                        kfree(div);
-                       break;
+                       goto err;
                }
 
                gate->reg = reg + VCC_GATE_OFFSET;
@@ -823,10 +826,12 @@ err:
                kfree(container_of(composite->mux_hw, struct clk_mux, hw));
        }
 
-       if (clk_data)
-               kfree(clk_data->clks);
-
+       kfree(clk_data->clks);
+err_alloc_clks:
        kfree(clk_data);
+err_alloc:
        kfree(parents);
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup);
index 72d1c27eaffa8247a0e49d029c21d2481caa83a7..47a38a994cac7a29113c086cb928e7957180e1fd 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #include "clkgen.h"
@@ -291,7 +292,7 @@ static unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
        res = (uint64_t)2 * (uint64_t)parent_rate * (uint64_t)ndiv;
        rate = (unsigned long)div64_u64(res, mdiv * (1 << pdiv));
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 
@@ -316,7 +317,7 @@ static unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
        /* Note: input is divided by 1000 to avoid overflow */
        rate = ((2 * (parent_rate / 1000) * ndiv) / mdiv) * 1000;
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
@@ -338,7 +339,7 @@ static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
                /* Note: input is divided to avoid overflow */
                rate = ((2 * (parent_rate/1000) * ndiv) / idf) * 1000;
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
@@ -365,7 +366,7 @@ static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
        /* Note: input is divided by 1000 to avoid overflow */
        rate = (((parent_rate / 1000) * ldf) / (odf * idf)) * 1000;
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
index 058f273d6154745d0fc4173677ee533cbd04a243..f5a35b82cc1a8b5bcce5edabf4b3e46479b8e846 100644 (file)
@@ -6,6 +6,7 @@ obj-y += clk-sunxi.o clk-factors.o
 obj-y += clk-a10-hosc.o
 obj-y += clk-a20-gmac.o
 obj-y += clk-mod0.o
+obj-y += clk-simple-gates.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
 obj-y += clk-sun9i-mmc.o
index 0dcf4f205fb86f1510dfa8b74f20311e301613ce..1611b036421c20e76f438e13fb326111b24e5cda 100644 (file)
@@ -80,9 +80,7 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
                goto free_mux;
 
        /* gmac clock requires exactly 2 parents */
-       parents[0] = of_clk_get_parent_name(node, 0);
-       parents[1] = of_clk_get_parent_name(node, 1);
-       if (!parents[0] || !parents[1])
+       if (of_clk_parent_fill(node, parents, 2) != 2)
                goto free_gate;
 
        reg = of_iomap(node, 0);
index 8c20190a3e9f4e134824449c10a72e9e13b5b957..59428dbd607a85d3ff15e3b648f529e1a575abf9 100644 (file)
@@ -79,41 +79,42 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
        return rate;
 }
 
-static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long min_rate,
-                                      unsigned long max_rate,
-                                      unsigned long *best_parent_rate,
-                                      struct clk_hw **best_parent_p)
+static int clk_factors_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
-       struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+       struct clk_hw *parent, *best_parent = NULL;
        int i, num_parents;
        unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
 
        /* find the parent that can help provide the fastest rate <= rate */
-       num_parents = __clk_get_num_parents(clk);
+       num_parents = clk_hw_get_num_parents(hw);
        for (i = 0; i < num_parents; i++) {
-               parent = clk_get_parent_by_index(clk, i);
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
-               if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_round_rate(parent, rate);
+               if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
+                       parent_rate = clk_hw_round_rate(parent, req->rate);
                else
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
 
-               child_rate = clk_factors_round_rate(hw, rate, &parent_rate);
+               child_rate = clk_factors_round_rate(hw, req->rate,
+                                                   &parent_rate);
 
-               if (child_rate <= rate && child_rate > best_child_rate) {
+               if (child_rate <= req->rate && child_rate > best_child_rate) {
                        best_parent = parent;
                        best = parent_rate;
                        best_child_rate = child_rate;
                }
        }
 
-       if (best_parent)
-               *best_parent_p = __clk_get_hw(best_parent);
-       *best_parent_rate = best;
+       if (!best_parent)
+               return -EINVAL;
 
-       return best_child_rate;
+       req->best_parent_hw = best_parent;
+       req->best_parent_rate = best;
+       req->rate = best_child_rate;
+
+       return 0;
 }
 
 static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -174,9 +175,7 @@ struct clk *sunxi_factors_register(struct device_node *node,
        int i = 0;
 
        /* if we have a mux, we will have >1 parents */
-       while (i < FACTORS_MAX_PARENTS &&
-              (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-               i++;
+       i = of_clk_parent_fill(node, parents, FACTORS_MAX_PARENTS);
 
        /*
         * some factor clocks, such as pll5 and pll6, may have multiple
index 9d028aec58e5d8addc3a080ced48594db57c1657..d167e1efb92761a0f223a6054787587d58b11152 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 
 #include "clk-factors.h"
 
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
new file mode 100644 (file)
index 0000000..6ce9118
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(gates_lock);
+
+static void __init sunxi_simple_gates_setup(struct device_node *node,
+                                           const int protected[],
+                                           int nprotected)
+{
+       struct clk_onecell_data *clk_data;
+       const char *clk_parent, *clk_name;
+       struct property *prop;
+       struct resource res;
+       void __iomem *clk_reg;
+       void __iomem *reg;
+       const __be32 *p;
+       int number, i = 0, j;
+       u8 clk_bit;
+       u32 index;
+
+       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+       if (IS_ERR(reg))
+               return;
+
+       clk_parent = of_clk_get_parent_name(node, 0);
+
+       clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+       if (!clk_data)
+               goto err_unmap;
+
+       number = of_property_count_u32_elems(node, "clock-indices");
+       of_property_read_u32_index(node, "clock-indices", number - 1, &number);
+
+       clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+       if (!clk_data->clks)
+               goto err_free_data;
+
+       of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+               of_property_read_string_index(node, "clock-output-names",
+                                             i, &clk_name);
+
+               clk_reg = reg + 4 * (index / 32);
+               clk_bit = index % 32;
+
+               clk_data->clks[index] = clk_register_gate(NULL, clk_name,
+                                                         clk_parent, 0,
+                                                         clk_reg,
+                                                         clk_bit,
+                                                         0, &gates_lock);
+               i++;
+
+               if (IS_ERR(clk_data->clks[index])) {
+                       WARN_ON(true);
+                       continue;
+               }
+
+               for (j = 0; j < nprotected; j++)
+                       if (protected[j] == index)
+                               clk_prepare_enable(clk_data->clks[index]);
+
+       }
+
+       clk_data->clk_num = number + 1;
+       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+       return;
+
+err_free_data:
+       kfree(clk_data);
+err_unmap:
+       iounmap(reg);
+       of_address_to_resource(node, 0, &res);
+       release_mem_region(res.start, resource_size(&res));
+}
+
+static void __init sunxi_simple_gates_init(struct device_node *node)
+{
+       sunxi_simple_gates_setup(node, NULL, 0);
+}
+
+CLK_OF_DECLARE(sun4i_a10_apb0, "allwinner,sun4i-a10-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun4i_a10_apb1, "allwinner,sun4i-a10-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun4i_a10_axi, "allwinner,sun4i-a10-axi-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a10s_apb0, "allwinner,sun5i-a10s-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a10s_apb1, "allwinner,sun5i-a10s-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a13_apb0, "allwinner,sun5i-a13-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a13_apb1, "allwinner,sun5i-a13-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun6i_a31_apb1, "allwinner,sun6i-a31-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun6i_a31_apb2, "allwinner,sun6i-a31-apb2-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun7i_a20_apb0, "allwinner,sun7i-a20-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun7i_a20_apb1, "allwinner,sun7i-a20-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a23_ahb1, "allwinner,sun8i-a23-ahb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a23_apb1, "allwinner,sun8i-a23-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_ahb2, "allwinner,sun9i-a80-ahb2-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-gates-clk",
+              sunxi_simple_gates_init);
+
+static const int sun4i_a10_ahb_critical_clocks[] __initconst = {
+       14,     /* ahb_sdram */
+};
+
+static void __init sun4i_a10_ahb_init(struct device_node *node)
+{
+       sunxi_simple_gates_setup(node, sun4i_a10_ahb_critical_clocks,
+                                ARRAY_SIZE(sun4i_a10_ahb_critical_clocks));
+}
+CLK_OF_DECLARE(sun4i_a10_ahb, "allwinner,sun4i-a10-ahb-gates-clk",
+              sun4i_a10_ahb_init);
+CLK_OF_DECLARE(sun5i_a10s_ahb, "allwinner,sun5i-a10s-ahb-gates-clk",
+              sun4i_a10_ahb_init);
+CLK_OF_DECLARE(sun5i_a13_ahb, "allwinner,sun5i-a13-ahb-gates-clk",
+              sun4i_a10_ahb_init);
+CLK_OF_DECLARE(sun7i_a20_ahb, "allwinner,sun7i-a20-ahb-gates-clk",
+              sun4i_a10_ahb_init);
index 63cf149195ae1a40cb61a7b2256878c0f2ccd5ef..806fd019c05dd103c272446ef03e01e3a9def11f 100644 (file)
@@ -44,28 +44,25 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
        return (parent_rate >> shift) / (div + 1);
 }
 
-static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long min_rate,
-                                unsigned long max_rate,
-                                unsigned long *best_parent_rate,
-                                struct clk_hw **best_parent_clk)
+static int ar100_determine_rate(struct clk_hw *hw,
+                               struct clk_rate_request *req)
 {
-       int nparents = __clk_get_num_parents(hw->clk);
+       int nparents = clk_hw_get_num_parents(hw);
        long best_rate = -EINVAL;
        int i;
 
-       *best_parent_clk = NULL;
+       req->best_parent_hw = NULL;
 
        for (i = 0; i < nparents; i++) {
                unsigned long parent_rate;
                unsigned long tmp_rate;
-               struct clk *parent;
+               struct clk_hw *parent;
                unsigned long div;
                int shift;
 
-               parent = clk_get_parent_by_index(hw->clk, i);
-               parent_rate = __clk_get_rate(parent);
-               div = DIV_ROUND_UP(parent_rate, rate);
+               parent = clk_hw_get_parent_by_index(hw, i);
+               parent_rate = clk_hw_get_rate(parent);
+               div = DIV_ROUND_UP(parent_rate, req->rate);
 
                /*
                 * The AR100 clk contains 2 divisors:
@@ -101,14 +98,19 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
                        continue;
 
                tmp_rate = (parent_rate >> shift) / div;
-               if (!*best_parent_clk || tmp_rate > best_rate) {
-                       *best_parent_clk = __clk_get_hw(parent);
-                       *best_parent_rate = parent_rate;
+               if (!req->best_parent_hw || tmp_rate > best_rate) {
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = parent_rate;
                        best_rate = tmp_rate;
                }
        }
 
-       return best_rate;
+       if (best_rate < 0)
+               return best_rate;
+
+       req->rate = best_rate;
+
+       return 0;
 }
 
 static int ar100_set_parent(struct clk_hw *hw, u8 index)
@@ -180,7 +182,6 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
        struct resource *r;
        struct clk *clk;
        int nparents;
-       int i;
 
        ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL);
        if (!ar100)
@@ -195,8 +196,7 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
        if (nparents > SUN6I_AR100_MAX_PARENTS)
                nparents = SUN6I_AR100_MAX_PARENTS;
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
+       of_clk_parent_fill(np, parents, nparents);
 
        of_property_read_string(np, "clock-output-names", &clk_name);
 
index 14cd026064bf377ed7cbc05bbd84aa608e639fec..bf117a636d2397f6a7059f55962134cade4b3cc0 100644 (file)
@@ -14,8 +14,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of_address.h>
 
 #include "clk-factors.h"
index 887f4ea161bb4eb79700c7778aecbec2c977e2b4..6c4c98324d3cc6800bace1b4a918707e2b4cc53f 100644 (file)
@@ -14,8 +14,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/log2.h>
index 710c273648d709e172b0691acca853c05c658dab..3436a948b796fc42b53181cda67ca89ab731f690 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/reset.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #define SUN9I_MMC_WIDTH                4
index abf7b37faf73f3dd2366024a5bb97affc152cda2..413070d07b3f1f255a8229a259eeb97c5aaf94ae 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/log2.h>
 
@@ -118,42 +120,42 @@ static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
        return (parent_rate / calcm) >> calcp;
 }
 
-static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                         unsigned long min_rate,
-                                         unsigned long max_rate,
-                                         unsigned long *best_parent_rate,
-                                         struct clk_hw **best_parent_clk)
+static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw,
+                                        struct clk_rate_request *req)
 {
-       struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+       struct clk_hw *parent, *best_parent = NULL;
        int i, num_parents;
        unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
 
        /* find the parent that can help provide the fastest rate <= rate */
-       num_parents = __clk_get_num_parents(clk);
+       num_parents = clk_hw_get_num_parents(hw);
        for (i = 0; i < num_parents; i++) {
-               parent = clk_get_parent_by_index(clk, i);
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
-               if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_round_rate(parent, rate);
+               if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
+                       parent_rate = clk_hw_round_rate(parent, req->rate);
                else
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
 
-               child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i,
+               child_rate = sun6i_ahb1_clk_round(req->rate, NULL, NULL, i,
                                                  parent_rate);
 
-               if (child_rate <= rate && child_rate > best_child_rate) {
+               if (child_rate <= req->rate && child_rate > best_child_rate) {
                        best_parent = parent;
                        best = parent_rate;
                        best_child_rate = child_rate;
                }
        }
 
-       if (best_parent)
-               *best_parent_clk = __clk_get_hw(best_parent);
-       *best_parent_rate = best;
+       if (!best_parent)
+               return -EINVAL;
 
-       return best_child_rate;
+       req->best_parent_hw = best_parent;
+       req->best_parent_rate = best;
+       req->rate = best_child_rate;
+
+       return 0;
 }
 
 static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -195,17 +197,14 @@ static void __init sun6i_ahb1_clk_setup(struct device_node *node)
        const char *clk_name = node->name;
        const char *parents[SUN6I_AHB1_MAX_PARENTS];
        void __iomem *reg;
-       int i = 0;
+       int i;
 
        reg = of_io_request_and_map(node, 0, of_node_full_name(node));
        if (IS_ERR(reg))
                return;
 
        /* we have a mux, we will have >1 parents */
-       while (i < SUN6I_AHB1_MAX_PARENTS &&
-              (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-               i++;
-
+       i = of_clk_parent_fill(node, parents, SUN6I_AHB1_MAX_PARENTS);
        of_property_read_string(node, "clock-output-names", &clk_name);
 
        ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL);
@@ -786,14 +785,11 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
        const char *clk_name = node->name;
        const char *parents[SUNXI_MAX_PARENTS];
        void __iomem *reg;
-       int i = 0;
+       int i;
 
        reg = of_iomap(node, 0);
 
-       while (i < SUNXI_MAX_PARENTS &&
-              (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-               i++;
-
+       i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS);
        of_property_read_string(node, "clock-output-names", &clk_name);
 
        clk = clk_register_mux(NULL, clk_name, parents, i,
@@ -900,150 +896,6 @@ struct gates_data {
        DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
 };
 
-static const struct gates_data sun4i_axi_gates_data __initconst = {
-       .mask = {1},
-};
-
-static const struct gates_data sun4i_ahb_gates_data __initconst = {
-       .mask = {0x7F77FFF, 0x14FB3F},
-};
-
-static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
-       .mask = {0x147667e7, 0x185915},
-};
-
-static const struct gates_data sun5i_a13_ahb_gates_data __initconst = {
-       .mask = {0x107067e7, 0x185111},
-};
-
-static const struct gates_data sun6i_a31_ahb1_gates_data __initconst = {
-       .mask = {0xEDFE7F62, 0x794F931},
-};
-
-static const struct gates_data sun7i_a20_ahb_gates_data __initconst = {
-       .mask = { 0x12f77fff, 0x16ff3f },
-};
-
-static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = {
-       .mask = {0x25386742, 0x2505111},
-};
-
-static const struct gates_data sun9i_a80_ahb0_gates_data __initconst = {
-       .mask = {0xF5F12B},
-};
-
-static const struct gates_data sun9i_a80_ahb1_gates_data __initconst = {
-       .mask = {0x1E20003},
-};
-
-static const struct gates_data sun9i_a80_ahb2_gates_data __initconst = {
-       .mask = {0x9B7},
-};
-
-static const struct gates_data sun4i_apb0_gates_data __initconst = {
-       .mask = {0x4EF},
-};
-
-static const struct gates_data sun5i_a10s_apb0_gates_data __initconst = {
-       .mask = {0x469},
-};
-
-static const struct gates_data sun5i_a13_apb0_gates_data __initconst = {
-       .mask = {0x61},
-};
-
-static const struct gates_data sun7i_a20_apb0_gates_data __initconst = {
-       .mask = { 0x4ff },
-};
-
-static const struct gates_data sun9i_a80_apb0_gates_data __initconst = {
-       .mask = {0xEB822},
-};
-
-static const struct gates_data sun4i_apb1_gates_data __initconst = {
-       .mask = {0xFF00F7},
-};
-
-static const struct gates_data sun5i_a10s_apb1_gates_data __initconst = {
-       .mask = {0xf0007},
-};
-
-static const struct gates_data sun5i_a13_apb1_gates_data __initconst = {
-       .mask = {0xa0007},
-};
-
-static const struct gates_data sun6i_a31_apb1_gates_data __initconst = {
-       .mask = {0x3031},
-};
-
-static const struct gates_data sun8i_a23_apb1_gates_data __initconst = {
-       .mask = {0x3021},
-};
-
-static const struct gates_data sun6i_a31_apb2_gates_data __initconst = {
-       .mask = {0x3F000F},
-};
-
-static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
-       .mask = { 0xff80ff },
-};
-
-static const struct gates_data sun9i_a80_apb1_gates_data __initconst = {
-       .mask = {0x3F001F},
-};
-
-static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
-       .mask = {0x1F0007},
-};
-
-static void __init sunxi_gates_clk_setup(struct device_node *node,
-                                        struct gates_data *data)
-{
-       struct clk_onecell_data *clk_data;
-       const char *clk_parent;
-       const char *clk_name;
-       void __iomem *reg;
-       int qty;
-       int i = 0;
-       int j = 0;
-
-       reg = of_iomap(node, 0);
-
-       clk_parent = of_clk_get_parent_name(node, 0);
-
-       /* Worst-case size approximation and memory allocation */
-       qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
-       clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
-       if (!clk_data)
-               return;
-       clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
-       if (!clk_data->clks) {
-               kfree(clk_data);
-               return;
-       }
-
-       for_each_set_bit(i, data->mask, SUNXI_GATES_MAX_SIZE) {
-               of_property_read_string_index(node, "clock-output-names",
-                                             j, &clk_name);
-
-               clk_data->clks[i] = clk_register_gate(NULL, clk_name,
-                                                     clk_parent, 0,
-                                                     reg + 4 * (i/32), i % 32,
-                                                     0, &clk_lock);
-               WARN_ON(IS_ERR(clk_data->clks[i]));
-               clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
-
-               j++;
-       }
-
-       /* Adjust to the real max */
-       clk_data->clk_num = i;
-
-       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
-}
-
-
-
 /**
  * sunxi_divs_clk_setup() helper data
  */
@@ -1281,34 +1133,6 @@ static const struct of_device_id clk_mux_match[] __initconst = {
        {}
 };
 
-/* Matches for gate clocks */
-static const struct of_device_id clk_gates_match[] __initconst = {
-       {.compatible = "allwinner,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
-       {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
-       {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
-       {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
-       {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
-       {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
-       {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
-       {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
-       {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
-       {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
-       {}
-};
 
 static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match,
                                              void *function)
@@ -1340,9 +1164,6 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
        /* Register mux clocks */
        of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
 
-       /* Register gate clocks */
-       of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
-
        /* Protect the clocks that needs to stay on */
        for (i = 0; i < nclocks; i++) {
                struct clk *clk = clk_get(NULL, clocks[i]);
@@ -1354,7 +1175,6 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
 
 static const char *sun4i_a10_critical_clocks[] __initdata = {
        "pll5_ddr",
-       "ahb_sdram",
 };
 
 static void __init sun4i_a10_init_clocks(struct device_node *node)
@@ -1367,7 +1187,6 @@ CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks)
 static const char *sun5i_critical_clocks[] __initdata = {
        "cpu",
        "pll5_ddr",
-       "ahb_sdram",
 };
 
 static void __init sun5i_init_clocks(struct device_node *node)
index 3a25f9588e67b58da122a82056854e5add44fd1c..1a72cd672839e81e63b118b588df75db9de4cf70 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 
index aec862ba7a17547b870a175ef436927b2c7307d3..826c325dc2e8b57bf022fac471f3c028dc1fbbf0 100644 (file)
@@ -1,5 +1,6 @@
 obj-y                                  += clk.o
 obj-y                                  += clk-audio-sync.o
+obj-y                                  += clk-dfll.o
 obj-y                                  += clk-divider.o
 obj-y                                  += clk-periph.o
 obj-y                                  += clk-periph-gate.o
@@ -16,4 +17,6 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += clk-tegra114.o
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)       += clk-tegra124.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)       += clk-tegra124-dfll-fcpu.o
 obj-$(CONFIG_ARCH_TEGRA_132_SOC)       += clk-tegra124.o
+obj-y                                  += cvb.o
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
new file mode 100644 (file)
index 0000000..c2ff859
--- /dev/null
@@ -0,0 +1,1757 @@
+/*
+ * clk-dfll.c - Tegra DFLL clock source common code
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
+ *
+ * Aleksandr Frid <afrid@nvidia.com>
+ * Paul Walmsley <pwalmsley@nvidia.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.
+ *
+ * This library is for the DVCO and DFLL IP blocks on the Tegra124
+ * SoC. These IP blocks together are also known at NVIDIA as
+ * "CL-DVFS". To try to avoid confusion, this code refers to them
+ * collectively as the "DFLL."
+ *
+ * The DFLL is a root clocksource which tolerates some amount of
+ * supply voltage noise. Tegra124 uses it to clock the fast CPU
+ * complex when the target CPU speed is above a particular rate. The
+ * DFLL can be operated in either open-loop mode or closed-loop mode.
+ * In open-loop mode, the DFLL generates an output clock appropriate
+ * to the supply voltage. In closed-loop mode, when configured with a
+ * target frequency, the DFLL minimizes supply voltage while
+ * delivering an average frequency equal to the target.
+ *
+ * Devices clocked by the DFLL must be able to tolerate frequency
+ * variation. In the case of the CPU, it's important to note that the
+ * CPU cycle time will vary. This has implications for
+ * performance-measurement code and any code that relies on the CPU
+ * cycle time to delay for a certain length of time.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+
+#include "clk-dfll.h"
+
+/*
+ * DFLL control registers - access via dfll_{readl,writel}
+ */
+
+/* DFLL_CTRL: DFLL control register */
+#define DFLL_CTRL                      0x00
+#define DFLL_CTRL_MODE_MASK            0x03
+
+/* DFLL_CONFIG: DFLL sample rate control */
+#define DFLL_CONFIG                    0x04
+#define DFLL_CONFIG_DIV_MASK           0xff
+#define DFLL_CONFIG_DIV_PRESCALE       32
+
+/* DFLL_PARAMS: tuning coefficients for closed loop integrator */
+#define DFLL_PARAMS                    0x08
+#define DFLL_PARAMS_CG_SCALE           (0x1 << 24)
+#define DFLL_PARAMS_FORCE_MODE_SHIFT   22
+#define DFLL_PARAMS_FORCE_MODE_MASK    (0x3 << DFLL_PARAMS_FORCE_MODE_SHIFT)
+#define DFLL_PARAMS_CF_PARAM_SHIFT     16
+#define DFLL_PARAMS_CF_PARAM_MASK      (0x3f << DFLL_PARAMS_CF_PARAM_SHIFT)
+#define DFLL_PARAMS_CI_PARAM_SHIFT     8
+#define DFLL_PARAMS_CI_PARAM_MASK      (0x7 << DFLL_PARAMS_CI_PARAM_SHIFT)
+#define DFLL_PARAMS_CG_PARAM_SHIFT     0
+#define DFLL_PARAMS_CG_PARAM_MASK      (0xff << DFLL_PARAMS_CG_PARAM_SHIFT)
+
+/* DFLL_TUNE0: delay line configuration register 0 */
+#define DFLL_TUNE0                     0x0c
+
+/* DFLL_TUNE1: delay line configuration register 1 */
+#define DFLL_TUNE1                     0x10
+
+/* DFLL_FREQ_REQ: target DFLL frequency control */
+#define DFLL_FREQ_REQ                  0x14
+#define DFLL_FREQ_REQ_FORCE_ENABLE     (0x1 << 28)
+#define DFLL_FREQ_REQ_FORCE_SHIFT      16
+#define DFLL_FREQ_REQ_FORCE_MASK       (0xfff << DFLL_FREQ_REQ_FORCE_SHIFT)
+#define FORCE_MAX                      2047
+#define FORCE_MIN                      -2048
+#define DFLL_FREQ_REQ_SCALE_SHIFT      8
+#define DFLL_FREQ_REQ_SCALE_MASK       (0xff << DFLL_FREQ_REQ_SCALE_SHIFT)
+#define DFLL_FREQ_REQ_SCALE_MAX                256
+#define DFLL_FREQ_REQ_FREQ_VALID       (0x1 << 7)
+#define DFLL_FREQ_REQ_MULT_SHIFT       0
+#define DFLL_FREQ_REG_MULT_MASK                (0x7f << DFLL_FREQ_REQ_MULT_SHIFT)
+#define FREQ_MAX                       127
+
+/* DFLL_DROOP_CTRL: droop prevention control */
+#define DFLL_DROOP_CTRL                        0x1c
+
+/* DFLL_OUTPUT_CFG: closed loop mode control registers */
+/* NOTE: access via dfll_i2c_{readl,writel} */
+#define DFLL_OUTPUT_CFG                        0x20
+#define DFLL_OUTPUT_CFG_I2C_ENABLE     (0x1 << 30)
+#define OUT_MASK                       0x3f
+#define DFLL_OUTPUT_CFG_SAFE_SHIFT     24
+#define DFLL_OUTPUT_CFG_SAFE_MASK      \
+               (OUT_MASK << DFLL_OUTPUT_CFG_SAFE_SHIFT)
+#define DFLL_OUTPUT_CFG_MAX_SHIFT      16
+#define DFLL_OUTPUT_CFG_MAX_MASK       \
+               (OUT_MASK << DFLL_OUTPUT_CFG_MAX_SHIFT)
+#define DFLL_OUTPUT_CFG_MIN_SHIFT      8
+#define DFLL_OUTPUT_CFG_MIN_MASK       \
+               (OUT_MASK << DFLL_OUTPUT_CFG_MIN_SHIFT)
+#define DFLL_OUTPUT_CFG_PWM_DELTA      (0x1 << 7)
+#define DFLL_OUTPUT_CFG_PWM_ENABLE     (0x1 << 6)
+#define DFLL_OUTPUT_CFG_PWM_DIV_SHIFT  0
+#define DFLL_OUTPUT_CFG_PWM_DIV_MASK   \
+               (OUT_MASK << DFLL_OUTPUT_CFG_PWM_DIV_SHIFT)
+
+/* DFLL_OUTPUT_FORCE: closed loop mode voltage forcing control */
+#define DFLL_OUTPUT_FORCE              0x24
+#define DFLL_OUTPUT_FORCE_ENABLE       (0x1 << 6)
+#define DFLL_OUTPUT_FORCE_VALUE_SHIFT  0
+#define DFLL_OUTPUT_FORCE_VALUE_MASK   \
+               (OUT_MASK << DFLL_OUTPUT_FORCE_VALUE_SHIFT)
+
+/* DFLL_MONITOR_CTRL: internal monitor data source control */
+#define DFLL_MONITOR_CTRL              0x28
+#define DFLL_MONITOR_CTRL_FREQ         6
+
+/* DFLL_MONITOR_DATA: internal monitor data output */
+#define DFLL_MONITOR_DATA              0x2c
+#define DFLL_MONITOR_DATA_NEW_MASK     (0x1 << 16)
+#define DFLL_MONITOR_DATA_VAL_SHIFT    0
+#define DFLL_MONITOR_DATA_VAL_MASK     (0xFFFF << DFLL_MONITOR_DATA_VAL_SHIFT)
+
+/*
+ * I2C output control registers - access via dfll_i2c_{readl,writel}
+ */
+
+/* DFLL_I2C_CFG: I2C controller configuration register */
+#define DFLL_I2C_CFG                   0x40
+#define DFLL_I2C_CFG_ARB_ENABLE                (0x1 << 20)
+#define DFLL_I2C_CFG_HS_CODE_SHIFT     16
+#define DFLL_I2C_CFG_HS_CODE_MASK      (0x7 << DFLL_I2C_CFG_HS_CODE_SHIFT)
+#define DFLL_I2C_CFG_PACKET_ENABLE     (0x1 << 15)
+#define DFLL_I2C_CFG_SIZE_SHIFT                12
+#define DFLL_I2C_CFG_SIZE_MASK         (0x7 << DFLL_I2C_CFG_SIZE_SHIFT)
+#define DFLL_I2C_CFG_SLAVE_ADDR_10     (0x1 << 10)
+#define DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_7BIT     1
+#define DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_10BIT    0
+
+/* DFLL_I2C_VDD_REG_ADDR: PMIC I2C address for closed loop mode */
+#define DFLL_I2C_VDD_REG_ADDR          0x44
+
+/* DFLL_I2C_STS: I2C controller status */
+#define DFLL_I2C_STS                   0x48
+#define DFLL_I2C_STS_I2C_LAST_SHIFT    1
+#define DFLL_I2C_STS_I2C_REQ_PENDING   0x1
+
+/* DFLL_INTR_STS: DFLL interrupt status register */
+#define DFLL_INTR_STS                  0x5c
+
+/* DFLL_INTR_EN: DFLL interrupt enable register */
+#define DFLL_INTR_EN                   0x60
+#define DFLL_INTR_MIN_MASK             0x1
+#define DFLL_INTR_MAX_MASK             0x2
+
+/*
+ * Integrated I2C controller registers - relative to td->i2c_controller_base
+ */
+
+/* DFLL_I2C_CLK_DIVISOR: I2C controller clock divisor */
+#define DFLL_I2C_CLK_DIVISOR           0x6c
+#define DFLL_I2C_CLK_DIVISOR_MASK      0xffff
+#define DFLL_I2C_CLK_DIVISOR_FS_SHIFT  16
+#define DFLL_I2C_CLK_DIVISOR_HS_SHIFT  0
+#define DFLL_I2C_CLK_DIVISOR_PREDIV    8
+#define DFLL_I2C_CLK_DIVISOR_HSMODE_PREDIV     12
+
+/*
+ * Other constants
+ */
+
+/* MAX_DFLL_VOLTAGES: number of LUT entries in the DFLL IP block */
+#define MAX_DFLL_VOLTAGES              33
+
+/*
+ * REF_CLK_CYC_PER_DVCO_SAMPLE: the number of ref_clk cycles that the hardware
+ *    integrates the DVCO counter over - used for debug rate monitoring and
+ *    droop control
+ */
+#define REF_CLK_CYC_PER_DVCO_SAMPLE    4
+
+/*
+ * REF_CLOCK_RATE: the DFLL reference clock rate currently supported by this
+ * driver, in Hz
+ */
+#define REF_CLOCK_RATE                 51000000UL
+
+#define DVCO_RATE_TO_MULT(rate, ref_rate)      ((rate) / ((ref_rate) / 2))
+#define MULT_TO_DVCO_RATE(mult, ref_rate)      ((mult) * ((ref_rate) / 2))
+
+/**
+ * enum dfll_ctrl_mode - DFLL hardware operating mode
+ * @DFLL_UNINITIALIZED: (uninitialized state - not in hardware bitfield)
+ * @DFLL_DISABLED: DFLL not generating an output clock
+ * @DFLL_OPEN_LOOP: DVCO running, but DFLL not adjusting voltage
+ * @DFLL_CLOSED_LOOP: DVCO running, and DFLL adjusting voltage to match
+ *                   the requested rate
+ *
+ * The integer corresponding to the last two states, minus one, is
+ * written to the DFLL hardware to change operating modes.
+ */
+enum dfll_ctrl_mode {
+       DFLL_UNINITIALIZED = 0,
+       DFLL_DISABLED = 1,
+       DFLL_OPEN_LOOP = 2,
+       DFLL_CLOSED_LOOP = 3,
+};
+
+/**
+ * enum dfll_tune_range - voltage range that the driver believes it's in
+ * @DFLL_TUNE_UNINITIALIZED: DFLL tuning not yet programmed
+ * @DFLL_TUNE_LOW: DFLL in the low-voltage range (or open-loop mode)
+ *
+ * Some DFLL tuning parameters may need to change depending on the
+ * DVCO's voltage; these states represent the ranges that the driver
+ * supports. These are software states; these values are never
+ * written into registers.
+ */
+enum dfll_tune_range {
+       DFLL_TUNE_UNINITIALIZED = 0,
+       DFLL_TUNE_LOW = 1,
+};
+
+/**
+ * struct dfll_rate_req - target DFLL rate request data
+ * @rate: target frequency, after the postscaling
+ * @dvco_target_rate: target frequency, after the postscaling
+ * @lut_index: LUT index at which voltage the dvco_target_rate will be reached
+ * @mult_bits: value to program to the MULT bits of the DFLL_FREQ_REQ register
+ * @scale_bits: value to program to the SCALE bits of the DFLL_FREQ_REQ register
+ */
+struct dfll_rate_req {
+       unsigned long rate;
+       unsigned long dvco_target_rate;
+       int lut_index;
+       u8 mult_bits;
+       u8 scale_bits;
+};
+
+struct tegra_dfll {
+       struct device                   *dev;
+       struct tegra_dfll_soc_data      *soc;
+
+       void __iomem                    *base;
+       void __iomem                    *i2c_base;
+       void __iomem                    *i2c_controller_base;
+       void __iomem                    *lut_base;
+
+       struct regulator                *vdd_reg;
+       struct clk                      *soc_clk;
+       struct clk                      *ref_clk;
+       struct clk                      *i2c_clk;
+       struct clk                      *dfll_clk;
+       struct reset_control            *dvco_rst;
+       unsigned long                   ref_rate;
+       unsigned long                   i2c_clk_rate;
+       unsigned long                   dvco_rate_min;
+
+       enum dfll_ctrl_mode             mode;
+       enum dfll_tune_range            tune_range;
+       struct dentry                   *debugfs_dir;
+       struct clk_hw                   dfll_clk_hw;
+       const char                      *output_clock_name;
+       struct dfll_rate_req            last_req;
+       unsigned long                   last_unrounded_rate;
+
+       /* Parameters from DT */
+       u32                             droop_ctrl;
+       u32                             sample_rate;
+       u32                             force_mode;
+       u32                             cf;
+       u32                             ci;
+       u32                             cg;
+       bool                            cg_scale;
+
+       /* I2C interface parameters */
+       u32                             i2c_fs_rate;
+       u32                             i2c_reg;
+       u32                             i2c_slave_addr;
+
+       /* i2c_lut array entries are regulator framework selectors */
+       unsigned                        i2c_lut[MAX_DFLL_VOLTAGES];
+       int                             i2c_lut_size;
+       u8                              lut_min, lut_max, lut_safe;
+};
+
+#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
+
+/* mode_name: map numeric DFLL modes to names for friendly console messages */
+static const char * const mode_name[] = {
+       [DFLL_UNINITIALIZED] = "uninitialized",
+       [DFLL_DISABLED] = "disabled",
+       [DFLL_OPEN_LOOP] = "open_loop",
+       [DFLL_CLOSED_LOOP] = "closed_loop",
+};
+
+/*
+ * Register accessors
+ */
+
+static inline u32 dfll_readl(struct tegra_dfll *td, u32 offs)
+{
+       return __raw_readl(td->base + offs);
+}
+
+static inline void dfll_writel(struct tegra_dfll *td, u32 val, u32 offs)
+{
+       WARN_ON(offs >= DFLL_I2C_CFG);
+       __raw_writel(val, td->base + offs);
+}
+
+static inline void dfll_wmb(struct tegra_dfll *td)
+{
+       dfll_readl(td, DFLL_CTRL);
+}
+
+/* I2C output control registers - for addresses above DFLL_I2C_CFG */
+
+static inline u32 dfll_i2c_readl(struct tegra_dfll *td, u32 offs)
+{
+       return __raw_readl(td->i2c_base + offs);
+}
+
+static inline void dfll_i2c_writel(struct tegra_dfll *td, u32 val, u32 offs)
+{
+       __raw_writel(val, td->i2c_base + offs);
+}
+
+static inline void dfll_i2c_wmb(struct tegra_dfll *td)
+{
+       dfll_i2c_readl(td, DFLL_I2C_CFG);
+}
+
+/**
+ * dfll_is_running - is the DFLL currently generating a clock?
+ * @td: DFLL instance
+ *
+ * If the DFLL is currently generating an output clock signal, return
+ * true; otherwise return false.
+ */
+static bool dfll_is_running(struct tegra_dfll *td)
+{
+       return td->mode >= DFLL_OPEN_LOOP;
+}
+
+/*
+ * Runtime PM suspend/resume callbacks
+ */
+
+/**
+ * tegra_dfll_runtime_resume - enable all clocks needed by the DFLL
+ * @dev: DFLL device *
+ *
+ * Enable all clocks needed by the DFLL. Assumes that clk_prepare()
+ * has already been called on all the clocks.
+ *
+ * XXX Should also handle context restore when returning from off.
+ */
+int tegra_dfll_runtime_resume(struct device *dev)
+{
+       struct tegra_dfll *td = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_enable(td->ref_clk);
+       if (ret) {
+               dev_err(dev, "could not enable ref clock: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_enable(td->soc_clk);
+       if (ret) {
+               dev_err(dev, "could not enable register clock: %d\n", ret);
+               clk_disable(td->ref_clk);
+               return ret;
+       }
+
+       ret = clk_enable(td->i2c_clk);
+       if (ret) {
+               dev_err(dev, "could not enable i2c clock: %d\n", ret);
+               clk_disable(td->soc_clk);
+               clk_disable(td->ref_clk);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_runtime_resume);
+
+/**
+ * tegra_dfll_runtime_suspend - disable all clocks needed by the DFLL
+ * @dev: DFLL device *
+ *
+ * Disable all clocks needed by the DFLL. Assumes that other code
+ * will later call clk_unprepare().
+ */
+int tegra_dfll_runtime_suspend(struct device *dev)
+{
+       struct tegra_dfll *td = dev_get_drvdata(dev);
+
+       clk_disable(td->ref_clk);
+       clk_disable(td->soc_clk);
+       clk_disable(td->i2c_clk);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_runtime_suspend);
+
+/*
+ * DFLL tuning operations (per-voltage-range tuning settings)
+ */
+
+/**
+ * dfll_tune_low - tune to DFLL and CPU settings valid for any voltage
+ * @td: DFLL instance
+ *
+ * Tune the DFLL oscillator parameters and the CPU clock shaper for
+ * the low-voltage range. These settings are valid for any voltage,
+ * but may not be optimal.
+ */
+static void dfll_tune_low(struct tegra_dfll *td)
+{
+       td->tune_range = DFLL_TUNE_LOW;
+
+       dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0);
+       dfll_writel(td, td->soc->tune1, DFLL_TUNE1);
+       dfll_wmb(td);
+
+       if (td->soc->set_clock_trimmers_low)
+               td->soc->set_clock_trimmers_low();
+}
+
+/*
+ * Output clock scaler helpers
+ */
+
+/**
+ * dfll_scale_dvco_rate - calculate scaled rate from the DVCO rate
+ * @scale_bits: clock scaler value (bits in the DFLL_FREQ_REQ_SCALE field)
+ * @dvco_rate: the DVCO rate
+ *
+ * Apply the same scaling formula that the DFLL hardware uses to scale
+ * the DVCO rate.
+ */
+static unsigned long dfll_scale_dvco_rate(int scale_bits,
+                                         unsigned long dvco_rate)
+{
+       return (u64)dvco_rate * (scale_bits + 1) / DFLL_FREQ_REQ_SCALE_MAX;
+}
+
+/*
+ * Monitor control
+ */
+
+/**
+ * dfll_calc_monitored_rate - convert DFLL_MONITOR_DATA_VAL rate into real freq
+ * @monitor_data: value read from the DFLL_MONITOR_DATA_VAL bitfield
+ * @ref_rate: DFLL reference clock rate
+ *
+ * Convert @monitor_data from DFLL_MONITOR_DATA_VAL units into cycles
+ * per second. Returns the converted value.
+ */
+static u64 dfll_calc_monitored_rate(u32 monitor_data,
+                                   unsigned long ref_rate)
+{
+       return monitor_data * (ref_rate / REF_CLK_CYC_PER_DVCO_SAMPLE);
+}
+
+/**
+ * dfll_read_monitor_rate - return the DFLL's output rate from internal monitor
+ * @td: DFLL instance
+ *
+ * If the DFLL is enabled, return the last rate reported by the DFLL's
+ * internal monitoring hardware. This works in both open-loop and
+ * closed-loop mode, and takes the output scaler setting into account.
+ * Assumes that the monitor was programmed to monitor frequency before
+ * the sample period started. If the driver believes that the DFLL is
+ * currently uninitialized or disabled, it will return 0, since
+ * otherwise the DFLL monitor data register will return the last
+ * measured rate from when the DFLL was active.
+ */
+static u64 dfll_read_monitor_rate(struct tegra_dfll *td)
+{
+       u32 v, s;
+       u64 pre_scaler_rate, post_scaler_rate;
+
+       if (!dfll_is_running(td))
+               return 0;
+
+       v = dfll_readl(td, DFLL_MONITOR_DATA);
+       v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
+       pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);
+
+       s = dfll_readl(td, DFLL_FREQ_REQ);
+       s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
+       post_scaler_rate = dfll_scale_dvco_rate(s, pre_scaler_rate);
+
+       return post_scaler_rate;
+}
+
+/*
+ * DFLL mode switching
+ */
+
+/**
+ * dfll_set_mode - change the DFLL control mode
+ * @td: DFLL instance
+ * @mode: DFLL control mode (see enum dfll_ctrl_mode)
+ *
+ * Change the DFLL's operating mode between disabled, open-loop mode,
+ * and closed-loop mode, or vice versa.
+ */
+static void dfll_set_mode(struct tegra_dfll *td,
+                         enum dfll_ctrl_mode mode)
+{
+       td->mode = mode;
+       dfll_writel(td, mode - 1, DFLL_CTRL);
+       dfll_wmb(td);
+}
+
+/*
+ * DFLL-to-I2C controller interface
+ */
+
+/**
+ * dfll_i2c_set_output_enabled - enable/disable I2C PMIC voltage requests
+ * @td: DFLL instance
+ * @enable: whether to enable or disable the I2C voltage requests
+ *
+ * Set the master enable control for I2C control value updates. If disabled,
+ * then I2C control messages are inhibited, regardless of the DFLL mode.
+ */
+static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
+{
+       u32 val;
+
+       val = dfll_i2c_readl(td, DFLL_OUTPUT_CFG);
+
+       if (enable)
+               val |= DFLL_OUTPUT_CFG_I2C_ENABLE;
+       else
+               val &= ~DFLL_OUTPUT_CFG_I2C_ENABLE;
+
+       dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
+       dfll_i2c_wmb(td);
+
+       return 0;
+}
+
+/**
+ * dfll_load_lut - load the voltage lookup table
+ * @td: struct tegra_dfll *
+ *
+ * Load the voltage-to-PMIC register value lookup table into the DFLL
+ * IP block memory. Look-up tables can be loaded at any time.
+ */
+static void dfll_load_i2c_lut(struct tegra_dfll *td)
+{
+       int i, lut_index;
+       u32 val;
+
+       for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
+               if (i < td->lut_min)
+                       lut_index = td->lut_min;
+               else if (i > td->lut_max)
+                       lut_index = td->lut_max;
+               else
+                       lut_index = i;
+
+               val = regulator_list_hardware_vsel(td->vdd_reg,
+                                                    td->i2c_lut[lut_index]);
+               __raw_writel(val, td->lut_base + i * 4);
+       }
+
+       dfll_i2c_wmb(td);
+}
+
+/**
+ * dfll_init_i2c_if - set up the DFLL's DFLL-I2C interface
+ * @td: DFLL instance
+ *
+ * During DFLL driver initialization, program the DFLL-I2C interface
+ * with the PMU slave address, vdd register offset, and transfer mode.
+ * This data is used by the DFLL to automatically construct I2C
+ * voltage-set commands, which are then passed to the DFLL's internal
+ * I2C controller.
+ */
+static void dfll_init_i2c_if(struct tegra_dfll *td)
+{
+       u32 val;
+
+       if (td->i2c_slave_addr > 0x7f) {
+               val = td->i2c_slave_addr << DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_10BIT;
+               val |= DFLL_I2C_CFG_SLAVE_ADDR_10;
+       } else {
+               val = td->i2c_slave_addr << DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_7BIT;
+       }
+       val |= DFLL_I2C_CFG_SIZE_MASK;
+       val |= DFLL_I2C_CFG_ARB_ENABLE;
+       dfll_i2c_writel(td, val, DFLL_I2C_CFG);
+
+       dfll_i2c_writel(td, td->i2c_reg, DFLL_I2C_VDD_REG_ADDR);
+
+       val = DIV_ROUND_UP(td->i2c_clk_rate, td->i2c_fs_rate * 8);
+       BUG_ON(!val || (val > DFLL_I2C_CLK_DIVISOR_MASK));
+       val = (val - 1) << DFLL_I2C_CLK_DIVISOR_FS_SHIFT;
+
+       /* default hs divisor just in case */
+       val |= 1 << DFLL_I2C_CLK_DIVISOR_HS_SHIFT;
+       __raw_writel(val, td->i2c_controller_base + DFLL_I2C_CLK_DIVISOR);
+       dfll_i2c_wmb(td);
+}
+
+/**
+ * dfll_init_out_if - prepare DFLL-to-PMIC interface
+ * @td: DFLL instance
+ *
+ * During DFLL driver initialization or resume from context loss,
+ * disable the I2C command output to the PMIC, set safe voltage and
+ * output limits, and disable and clear limit interrupts.
+ */
+static void dfll_init_out_if(struct tegra_dfll *td)
+{
+       u32 val;
+
+       td->lut_min = 0;
+       td->lut_max = td->i2c_lut_size - 1;
+       td->lut_safe = td->lut_min + 1;
+
+       dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
+       val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
+               (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
+               (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
+       dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
+       dfll_i2c_wmb(td);
+
+       dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
+       dfll_i2c_writel(td, 0, DFLL_INTR_EN);
+       dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
+                       DFLL_INTR_STS);
+
+       dfll_load_i2c_lut(td);
+       dfll_init_i2c_if(td);
+}
+
+/*
+ * Set/get the DFLL's targeted output clock rate
+ */
+
+/**
+ * find_lut_index_for_rate - determine I2C LUT index for given DFLL rate
+ * @td: DFLL instance
+ * @rate: clock rate
+ *
+ * Determines the index of a I2C LUT entry for a voltage that approximately
+ * produces the given DFLL clock rate. This is used when forcing a value
+ * to the integrator during rate changes. Returns -ENOENT if a suitable
+ * LUT index is not found.
+ */
+static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
+{
+       struct dev_pm_opp *opp;
+       int i, uv;
+
+       opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
+       if (IS_ERR(opp))
+               return PTR_ERR(opp);
+       uv = dev_pm_opp_get_voltage(opp);
+
+       for (i = 0; i < td->i2c_lut_size; i++) {
+               if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
+                       return i;
+       }
+
+       return -ENOENT;
+}
+
+/**
+ * dfll_calculate_rate_request - calculate DFLL parameters for a given rate
+ * @td: DFLL instance
+ * @req: DFLL-rate-request structure
+ * @rate: the desired DFLL rate
+ *
+ * Populate the DFLL-rate-request record @req fields with the scale_bits
+ * and mult_bits fields, based on the target input rate. Returns 0 upon
+ * success, or -EINVAL if the requested rate in req->rate is too high
+ * or low for the DFLL to generate.
+ */
+static int dfll_calculate_rate_request(struct tegra_dfll *td,
+                                      struct dfll_rate_req *req,
+                                      unsigned long rate)
+{
+       u32 val;
+
+       /*
+        * If requested rate is below the minimum DVCO rate, active the scaler.
+        * In the future the DVCO minimum voltage should be selected based on
+        * chip temperature and the actual minimum rate should be calibrated
+        * at runtime.
+        */
+       req->scale_bits = DFLL_FREQ_REQ_SCALE_MAX - 1;
+       if (rate < td->dvco_rate_min) {
+               int scale;
+
+               scale = DIV_ROUND_CLOSEST(rate / 1000 * DFLL_FREQ_REQ_SCALE_MAX,
+                                         td->dvco_rate_min / 1000);
+               if (!scale) {
+                       dev_err(td->dev, "%s: Rate %lu is too low\n",
+                               __func__, rate);
+                       return -EINVAL;
+               }
+               req->scale_bits = scale - 1;
+               rate = td->dvco_rate_min;
+       }
+
+       /* Convert requested rate into frequency request and scale settings */
+       val = DVCO_RATE_TO_MULT(rate, td->ref_rate);
+       if (val > FREQ_MAX) {
+               dev_err(td->dev, "%s: Rate %lu is above dfll range\n",
+                       __func__, rate);
+               return -EINVAL;
+       }
+       req->mult_bits = val;
+       req->dvco_target_rate = MULT_TO_DVCO_RATE(req->mult_bits, td->ref_rate);
+       req->rate = dfll_scale_dvco_rate(req->scale_bits,
+                                        req->dvco_target_rate);
+       req->lut_index = find_lut_index_for_rate(td, req->dvco_target_rate);
+       if (req->lut_index < 0)
+               return req->lut_index;
+
+       return 0;
+}
+
+/**
+ * dfll_set_frequency_request - start the frequency change operation
+ * @td: DFLL instance
+ * @req: rate request structure
+ *
+ * Tell the DFLL to try to change its output frequency to the
+ * frequency represented by @req. DFLL must be in closed-loop mode.
+ */
+static void dfll_set_frequency_request(struct tegra_dfll *td,
+                                      struct dfll_rate_req *req)
+{
+       u32 val = 0;
+       int force_val;
+       int coef = 128; /* FIXME: td->cg_scale? */;
+
+       force_val = (req->lut_index - td->lut_safe) * coef / td->cg;
+       force_val = clamp(force_val, FORCE_MIN, FORCE_MAX);
+
+       val |= req->mult_bits << DFLL_FREQ_REQ_MULT_SHIFT;
+       val |= req->scale_bits << DFLL_FREQ_REQ_SCALE_SHIFT;
+       val |= ((u32)force_val << DFLL_FREQ_REQ_FORCE_SHIFT) &
+               DFLL_FREQ_REQ_FORCE_MASK;
+       val |= DFLL_FREQ_REQ_FREQ_VALID | DFLL_FREQ_REQ_FORCE_ENABLE;
+
+       dfll_writel(td, val, DFLL_FREQ_REQ);
+       dfll_wmb(td);
+}
+
+/**
+ * tegra_dfll_request_rate - set the next rate for the DFLL to tune to
+ * @td: DFLL instance
+ * @rate: clock rate to target
+ *
+ * Convert the requested clock rate @rate into the DFLL control logic
+ * settings. In closed-loop mode, update new settings immediately to
+ * adjust DFLL output rate accordingly. Otherwise, just save them
+ * until the next switch to closed loop. Returns 0 upon success,
+ * -EPERM if the DFLL driver has not yet been initialized, or -EINVAL
+ * if @rate is outside the DFLL's tunable range.
+ */
+static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
+{
+       int ret;
+       struct dfll_rate_req req;
+
+       if (td->mode == DFLL_UNINITIALIZED) {
+               dev_err(td->dev, "%s: Cannot set DFLL rate in %s mode\n",
+                       __func__, mode_name[td->mode]);
+               return -EPERM;
+       }
+
+       ret = dfll_calculate_rate_request(td, &req, rate);
+       if (ret)
+               return ret;
+
+       td->last_unrounded_rate = rate;
+       td->last_req = req;
+
+       if (td->mode == DFLL_CLOSED_LOOP)
+               dfll_set_frequency_request(td, &td->last_req);
+
+       return 0;
+}
+
+/*
+ * DFLL enable/disable & open-loop <-> closed-loop transitions
+ */
+
+/**
+ * dfll_disable - switch from open-loop mode to disabled mode
+ * @td: DFLL instance
+ *
+ * Switch from OPEN_LOOP state to DISABLED state. Returns 0 upon success
+ * or -EPERM if the DFLL is not currently in open-loop mode.
+ */
+static int dfll_disable(struct tegra_dfll *td)
+{
+       if (td->mode != DFLL_OPEN_LOOP) {
+               dev_err(td->dev, "cannot disable DFLL in %s mode\n",
+                       mode_name[td->mode]);
+               return -EINVAL;
+       }
+
+       dfll_set_mode(td, DFLL_DISABLED);
+       pm_runtime_put_sync(td->dev);
+
+       return 0;
+}
+
+/**
+ * dfll_enable - switch a disabled DFLL to open-loop mode
+ * @td: DFLL instance
+ *
+ * Switch from DISABLED state to OPEN_LOOP state. Returns 0 upon success
+ * or -EPERM if the DFLL is not currently disabled.
+ */
+static int dfll_enable(struct tegra_dfll *td)
+{
+       if (td->mode != DFLL_DISABLED) {
+               dev_err(td->dev, "cannot enable DFLL in %s mode\n",
+                       mode_name[td->mode]);
+               return -EPERM;
+       }
+
+       pm_runtime_get_sync(td->dev);
+       dfll_set_mode(td, DFLL_OPEN_LOOP);
+
+       return 0;
+}
+
+/**
+ * dfll_set_open_loop_config - prepare to switch to open-loop mode
+ * @td: DFLL instance
+ *
+ * Prepare to switch the DFLL to open-loop mode. This switches the
+ * DFLL to the low-voltage tuning range, ensures that I2C output
+ * forcing is disabled, and disables the output clock rate scaler.
+ * The DFLL's low-voltage tuning range parameters must be
+ * characterized to keep the downstream device stable at any DVCO
+ * input voltage. No return value.
+ */
+static void dfll_set_open_loop_config(struct tegra_dfll *td)
+{
+       u32 val;
+
+       /* always tune low (safe) in open loop */
+       if (td->tune_range != DFLL_TUNE_LOW)
+               dfll_tune_low(td);
+
+       val = dfll_readl(td, DFLL_FREQ_REQ);
+       val |= DFLL_FREQ_REQ_SCALE_MASK;
+       val &= ~DFLL_FREQ_REQ_FORCE_ENABLE;
+       dfll_writel(td, val, DFLL_FREQ_REQ);
+       dfll_wmb(td);
+}
+
+/**
+ * tegra_dfll_lock - switch from open-loop to closed-loop mode
+ * @td: DFLL instance
+ *
+ * Switch from OPEN_LOOP state to CLOSED_LOOP state. Returns 0 upon success,
+ * -EINVAL if the DFLL's target rate hasn't been set yet, or -EPERM if the
+ * DFLL is not currently in open-loop mode.
+ */
+static int dfll_lock(struct tegra_dfll *td)
+{
+       struct dfll_rate_req *req = &td->last_req;
+
+       switch (td->mode) {
+       case DFLL_CLOSED_LOOP:
+               return 0;
+
+       case DFLL_OPEN_LOOP:
+               if (req->rate == 0) {
+                       dev_err(td->dev, "%s: Cannot lock DFLL at rate 0\n",
+                               __func__);
+                       return -EINVAL;
+               }
+
+               dfll_i2c_set_output_enabled(td, true);
+               dfll_set_mode(td, DFLL_CLOSED_LOOP);
+               dfll_set_frequency_request(td, req);
+               return 0;
+
+       default:
+               BUG_ON(td->mode > DFLL_CLOSED_LOOP);
+               dev_err(td->dev, "%s: Cannot lock DFLL in %s mode\n",
+                       __func__, mode_name[td->mode]);
+               return -EPERM;
+       }
+}
+
+/**
+ * tegra_dfll_unlock - switch from closed-loop to open-loop mode
+ * @td: DFLL instance
+ *
+ * Switch from CLOSED_LOOP state to OPEN_LOOP state. Returns 0 upon success,
+ * or -EPERM if the DFLL is not currently in open-loop mode.
+ */
+static int dfll_unlock(struct tegra_dfll *td)
+{
+       switch (td->mode) {
+       case DFLL_CLOSED_LOOP:
+               dfll_set_open_loop_config(td);
+               dfll_set_mode(td, DFLL_OPEN_LOOP);
+               dfll_i2c_set_output_enabled(td, false);
+               return 0;
+
+       case DFLL_OPEN_LOOP:
+               return 0;
+
+       default:
+               BUG_ON(td->mode > DFLL_CLOSED_LOOP);
+               dev_err(td->dev, "%s: Cannot unlock DFLL in %s mode\n",
+                       __func__, mode_name[td->mode]);
+               return -EPERM;
+       }
+}
+
+/*
+ * Clock framework integration
+ *
+ * When the DFLL is being controlled by the CCF, always enter closed loop
+ * mode when the clk is enabled. This requires that a DFLL rate request
+ * has been set beforehand, which implies that a clk_set_rate() call is
+ * always required before a clk_enable().
+ */
+
+static int dfll_clk_is_enabled(struct clk_hw *hw)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+
+       return dfll_is_running(td);
+}
+
+static int dfll_clk_enable(struct clk_hw *hw)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+       int ret;
+
+       ret = dfll_enable(td);
+       if (ret)
+               return ret;
+
+       ret = dfll_lock(td);
+       if (ret)
+               dfll_disable(td);
+
+       return ret;
+}
+
+static void dfll_clk_disable(struct clk_hw *hw)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+       int ret;
+
+       ret = dfll_unlock(td);
+       if (!ret)
+               dfll_disable(td);
+}
+
+static unsigned long dfll_clk_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+
+       return td->last_unrounded_rate;
+}
+
+static long dfll_clk_round_rate(struct clk_hw *hw,
+                               unsigned long rate,
+                               unsigned long *parent_rate)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+       struct dfll_rate_req req;
+       int ret;
+
+       ret = dfll_calculate_rate_request(td, &req, rate);
+       if (ret)
+               return ret;
+
+       /*
+        * Don't return the rounded rate, since it doesn't really matter as
+        * the output rate will be voltage controlled anyway, and cpufreq
+        * freaks out if any rounding happens.
+        */
+       return rate;
+}
+
+static int dfll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+
+       return dfll_request_rate(td, rate);
+}
+
+static const struct clk_ops dfll_clk_ops = {
+       .is_enabled     = dfll_clk_is_enabled,
+       .enable         = dfll_clk_enable,
+       .disable        = dfll_clk_disable,
+       .recalc_rate    = dfll_clk_recalc_rate,
+       .round_rate     = dfll_clk_round_rate,
+       .set_rate       = dfll_clk_set_rate,
+};
+
+static struct clk_init_data dfll_clk_init_data = {
+       .flags          = CLK_IS_ROOT,
+       .ops            = &dfll_clk_ops,
+       .num_parents    = 0,
+};
+
+/**
+ * dfll_register_clk - register the DFLL output clock with the clock framework
+ * @td: DFLL instance
+ *
+ * Register the DFLL's output clock with the Linux clock framework and register
+ * the DFLL driver as an OF clock provider. Returns 0 upon success or -EINVAL
+ * or -ENOMEM upon failure.
+ */
+static int dfll_register_clk(struct tegra_dfll *td)
+{
+       int ret;
+
+       dfll_clk_init_data.name = td->output_clock_name;
+       td->dfll_clk_hw.init = &dfll_clk_init_data;
+
+       td->dfll_clk = clk_register(td->dev, &td->dfll_clk_hw);
+       if (IS_ERR(td->dfll_clk)) {
+               dev_err(td->dev, "DFLL clock registration error\n");
+               return -EINVAL;
+       }
+
+       ret = of_clk_add_provider(td->dev->of_node, of_clk_src_simple_get,
+                                 td->dfll_clk);
+       if (ret) {
+               dev_err(td->dev, "of_clk_add_provider() failed\n");
+
+               clk_unregister(td->dfll_clk);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * dfll_unregister_clk - unregister the DFLL output clock
+ * @td: DFLL instance
+ *
+ * Unregister the DFLL's output clock from the Linux clock framework
+ * and from clkdev. No return value.
+ */
+static void dfll_unregister_clk(struct tegra_dfll *td)
+{
+       of_clk_del_provider(td->dev->of_node);
+       clk_unregister(td->dfll_clk);
+       td->dfll_clk = NULL;
+}
+
+/*
+ * Debugfs interface
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+static int attr_enable_get(void *data, u64 *val)
+{
+       struct tegra_dfll *td = data;
+
+       *val = dfll_is_running(td);
+
+       return 0;
+}
+static int attr_enable_set(void *data, u64 val)
+{
+       struct tegra_dfll *td = data;
+
+       return val ? dfll_enable(td) : dfll_disable(td);
+}
+DEFINE_SIMPLE_ATTRIBUTE(enable_fops, attr_enable_get, attr_enable_set,
+                       "%llu\n");
+
+static int attr_lock_get(void *data, u64 *val)
+{
+       struct tegra_dfll *td = data;
+
+       *val = (td->mode == DFLL_CLOSED_LOOP);
+
+       return 0;
+}
+static int attr_lock_set(void *data, u64 val)
+{
+       struct tegra_dfll *td = data;
+
+       return val ? dfll_lock(td) :  dfll_unlock(td);
+}
+DEFINE_SIMPLE_ATTRIBUTE(lock_fops, attr_lock_get, attr_lock_set,
+                       "%llu\n");
+
+static int attr_rate_get(void *data, u64 *val)
+{
+       struct tegra_dfll *td = data;
+
+       *val = dfll_read_monitor_rate(td);
+
+       return 0;
+}
+
+static int attr_rate_set(void *data, u64 val)
+{
+       struct tegra_dfll *td = data;
+
+       return dfll_request_rate(td, val);
+}
+DEFINE_SIMPLE_ATTRIBUTE(rate_fops, attr_rate_get, attr_rate_set, "%llu\n");
+
+static int attr_registers_show(struct seq_file *s, void *data)
+{
+       u32 val, offs;
+       struct tegra_dfll *td = s->private;
+
+       seq_puts(s, "CONTROL REGISTERS:\n");
+       for (offs = 0; offs <= DFLL_MONITOR_DATA; offs += 4) {
+               if (offs == DFLL_OUTPUT_CFG)
+                       val = dfll_i2c_readl(td, offs);
+               else
+                       val = dfll_readl(td, offs);
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs, val);
+       }
+
+       seq_puts(s, "\nI2C and INTR REGISTERS:\n");
+       for (offs = DFLL_I2C_CFG; offs <= DFLL_I2C_STS; offs += 4)
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                          dfll_i2c_readl(td, offs));
+       for (offs = DFLL_INTR_STS; offs <= DFLL_INTR_EN; offs += 4)
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                          dfll_i2c_readl(td, offs));
+
+       seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
+       offs = DFLL_I2C_CLK_DIVISOR;
+       seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                  __raw_readl(td->i2c_controller_base + offs));
+
+       seq_puts(s, "\nLUT:\n");
+       for (offs = 0; offs <  4 * MAX_DFLL_VOLTAGES; offs += 4)
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                          __raw_readl(td->lut_base + offs));
+
+       return 0;
+}
+
+static int attr_registers_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, attr_registers_show, inode->i_private);
+}
+
+static const struct file_operations attr_registers_fops = {
+       .open           = attr_registers_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dfll_debug_init(struct tegra_dfll *td)
+{
+       int ret;
+
+       if (!td || (td->mode == DFLL_UNINITIALIZED))
+               return 0;
+
+       td->debugfs_dir = debugfs_create_dir("tegra_dfll_fcpu", NULL);
+       if (!td->debugfs_dir)
+               return -ENOMEM;
+
+       ret = -ENOMEM;
+
+       if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR,
+                                td->debugfs_dir, td, &enable_fops))
+               goto err_out;
+
+       if (!debugfs_create_file("lock", S_IRUGO,
+                                td->debugfs_dir, td, &lock_fops))
+               goto err_out;
+
+       if (!debugfs_create_file("rate", S_IRUGO,
+                                td->debugfs_dir, td, &rate_fops))
+               goto err_out;
+
+       if (!debugfs_create_file("registers", S_IRUGO,
+                                td->debugfs_dir, td, &attr_registers_fops))
+               goto err_out;
+
+       return 0;
+
+err_out:
+       debugfs_remove_recursive(td->debugfs_dir);
+       return ret;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+/*
+ * DFLL initialization
+ */
+
+/**
+ * dfll_set_default_params - program non-output related DFLL parameters
+ * @td: DFLL instance
+ *
+ * During DFLL driver initialization or resume from context loss,
+ * program parameters for the closed loop integrator, DVCO tuning,
+ * voltage droop control and monitor control.
+ */
+static void dfll_set_default_params(struct tegra_dfll *td)
+{
+       u32 val;
+
+       val = DIV_ROUND_UP(td->ref_rate, td->sample_rate * 32);
+       BUG_ON(val > DFLL_CONFIG_DIV_MASK);
+       dfll_writel(td, val, DFLL_CONFIG);
+
+       val = (td->force_mode << DFLL_PARAMS_FORCE_MODE_SHIFT) |
+               (td->cf << DFLL_PARAMS_CF_PARAM_SHIFT) |
+               (td->ci << DFLL_PARAMS_CI_PARAM_SHIFT) |
+               (td->cg << DFLL_PARAMS_CG_PARAM_SHIFT) |
+               (td->cg_scale ? DFLL_PARAMS_CG_SCALE : 0);
+       dfll_writel(td, val, DFLL_PARAMS);
+
+       dfll_tune_low(td);
+       dfll_writel(td, td->droop_ctrl, DFLL_DROOP_CTRL);
+       dfll_writel(td, DFLL_MONITOR_CTRL_FREQ, DFLL_MONITOR_CTRL);
+}
+
+/**
+ * dfll_init_clks - clk_get() the DFLL source clocks
+ * @td: DFLL instance
+ *
+ * Call clk_get() on the DFLL source clocks and save the pointers for later
+ * use. Returns 0 upon success or error (see devm_clk_get) if one or more
+ * of the clocks couldn't be looked up.
+ */
+static int dfll_init_clks(struct tegra_dfll *td)
+{
+       td->ref_clk = devm_clk_get(td->dev, "ref");
+       if (IS_ERR(td->ref_clk)) {
+               dev_err(td->dev, "missing ref clock\n");
+               return PTR_ERR(td->ref_clk);
+       }
+
+       td->soc_clk = devm_clk_get(td->dev, "soc");
+       if (IS_ERR(td->soc_clk)) {
+               dev_err(td->dev, "missing soc clock\n");
+               return PTR_ERR(td->soc_clk);
+       }
+
+       td->i2c_clk = devm_clk_get(td->dev, "i2c");
+       if (IS_ERR(td->i2c_clk)) {
+               dev_err(td->dev, "missing i2c clock\n");
+               return PTR_ERR(td->i2c_clk);
+       }
+       td->i2c_clk_rate = clk_get_rate(td->i2c_clk);
+
+       return 0;
+}
+
+/**
+ * dfll_init - Prepare the DFLL IP block for use
+ * @td: DFLL instance
+ *
+ * Do everything necessary to prepare the DFLL IP block for use. The
+ * DFLL will be left in DISABLED state. Called by dfll_probe().
+ * Returns 0 upon success, or passes along the error from whatever
+ * function returned it.
+ */
+static int dfll_init(struct tegra_dfll *td)
+{
+       int ret;
+
+       td->ref_rate = clk_get_rate(td->ref_clk);
+       if (td->ref_rate != REF_CLOCK_RATE) {
+               dev_err(td->dev, "unexpected ref clk rate %lu, expecting %lu",
+                       td->ref_rate, REF_CLOCK_RATE);
+               return -EINVAL;
+       }
+
+       reset_control_deassert(td->dvco_rst);
+
+       ret = clk_prepare(td->ref_clk);
+       if (ret) {
+               dev_err(td->dev, "failed to prepare ref_clk\n");
+               return ret;
+       }
+
+       ret = clk_prepare(td->soc_clk);
+       if (ret) {
+               dev_err(td->dev, "failed to prepare soc_clk\n");
+               goto di_err1;
+       }
+
+       ret = clk_prepare(td->i2c_clk);
+       if (ret) {
+               dev_err(td->dev, "failed to prepare i2c_clk\n");
+               goto di_err2;
+       }
+
+       td->last_unrounded_rate = 0;
+
+       pm_runtime_enable(td->dev);
+       pm_runtime_get_sync(td->dev);
+
+       dfll_set_mode(td, DFLL_DISABLED);
+       dfll_set_default_params(td);
+
+       if (td->soc->init_clock_trimmers)
+               td->soc->init_clock_trimmers();
+
+       dfll_set_open_loop_config(td);
+
+       dfll_init_out_if(td);
+
+       pm_runtime_put_sync(td->dev);
+
+       return 0;
+
+di_err2:
+       clk_unprepare(td->soc_clk);
+di_err1:
+       clk_unprepare(td->ref_clk);
+
+       reset_control_assert(td->dvco_rst);
+
+       return ret;
+}
+
+/*
+ * DT data fetch
+ */
+
+/*
+ * Find a PMIC voltage register-to-voltage mapping for the given voltage.
+ * An exact voltage match is required.
+ */
+static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
+{
+       int i, n_voltages, reg_uV;
+
+       n_voltages = regulator_count_voltages(td->vdd_reg);
+       for (i = 0; i < n_voltages; i++) {
+               reg_uV = regulator_list_voltage(td->vdd_reg, i);
+               if (reg_uV < 0)
+                       break;
+
+               if (uV == reg_uV)
+                       return i;
+       }
+
+       dev_err(td->dev, "no voltage map entry for %d uV\n", uV);
+       return -EINVAL;
+}
+
+/*
+ * Find a PMIC voltage register-to-voltage mapping for the given voltage,
+ * rounding up to the closest supported voltage.
+ * */
+static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
+{
+       int i, n_voltages, reg_uV;
+
+       n_voltages = regulator_count_voltages(td->vdd_reg);
+       for (i = 0; i < n_voltages; i++) {
+               reg_uV = regulator_list_voltage(td->vdd_reg, i);
+               if (reg_uV < 0)
+                       break;
+
+               if (uV <= reg_uV)
+                       return i;
+       }
+
+       dev_err(td->dev, "no voltage map entry rounding to %d uV\n", uV);
+       return -EINVAL;
+}
+
+/**
+ * dfll_build_i2c_lut - build the I2C voltage register lookup table
+ * @td: DFLL instance
+ *
+ * The DFLL hardware has 33 bytes of look-up table RAM that must be filled with
+ * PMIC voltage register values that span the entire DFLL operating range.
+ * This function builds the look-up table based on the OPP table provided by
+ * the soc-specific platform driver (td->soc->opp_dev) and the PMIC
+ * register-to-voltage mapping queried from the regulator framework.
+ *
+ * On success, fills in td->i2c_lut and returns 0, or -err on failure.
+ */
+static int dfll_build_i2c_lut(struct tegra_dfll *td)
+{
+       int ret = -EINVAL;
+       int j, v, v_max, v_opp;
+       int selector;
+       unsigned long rate;
+       struct dev_pm_opp *opp;
+       int lut;
+
+       rcu_read_lock();
+
+       rate = ULONG_MAX;
+       opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
+       if (IS_ERR(opp)) {
+               dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
+               goto out;
+       }
+       v_max = dev_pm_opp_get_voltage(opp);
+
+       v = td->soc->min_millivolts * 1000;
+       lut = find_vdd_map_entry_exact(td, v);
+       if (lut < 0)
+               goto out;
+       td->i2c_lut[0] = lut;
+
+       for (j = 1, rate = 0; ; rate++) {
+               opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
+               if (IS_ERR(opp))
+                       break;
+               v_opp = dev_pm_opp_get_voltage(opp);
+
+               if (v_opp <= td->soc->min_millivolts * 1000)
+                       td->dvco_rate_min = dev_pm_opp_get_freq(opp);
+
+               for (;;) {
+                       v += max(1, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
+                       if (v >= v_opp)
+                               break;
+
+                       selector = find_vdd_map_entry_min(td, v);
+                       if (selector < 0)
+                               goto out;
+                       if (selector != td->i2c_lut[j - 1])
+                               td->i2c_lut[j++] = selector;
+               }
+
+               v = (j == MAX_DFLL_VOLTAGES - 1) ? v_max : v_opp;
+               selector = find_vdd_map_entry_exact(td, v);
+               if (selector < 0)
+                       goto out;
+               if (selector != td->i2c_lut[j - 1])
+                       td->i2c_lut[j++] = selector;
+
+               if (v >= v_max)
+                       break;
+       }
+       td->i2c_lut_size = j;
+
+       if (!td->dvco_rate_min)
+               dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
+                       td->soc->min_millivolts);
+       else
+               ret = 0;
+
+out:
+       rcu_read_unlock();
+
+       return ret;
+}
+
+/**
+ * read_dt_param - helper function for reading required parameters from the DT
+ * @td: DFLL instance
+ * @param: DT property name
+ * @dest: output pointer for the value read
+ *
+ * Read a required numeric parameter from the DFLL device node, or complain
+ * if the property doesn't exist. Returns a boolean indicating success for
+ * easy chaining of multiple calls to this function.
+ */
+static bool read_dt_param(struct tegra_dfll *td, const char *param, u32 *dest)
+{
+       int err = of_property_read_u32(td->dev->of_node, param, dest);
+
+       if (err < 0) {
+               dev_err(td->dev, "failed to read DT parameter %s: %d\n",
+                       param, err);
+               return false;
+       }
+
+       return true;
+}
+
+/**
+ * dfll_fetch_i2c_params - query PMIC I2C params from DT & regulator subsystem
+ * @td: DFLL instance
+ *
+ * Read all the parameters required for operation in I2C mode. The parameters
+ * can originate from the device tree or the regulator subsystem.
+ * Returns 0 on success or -err on failure.
+ */
+static int dfll_fetch_i2c_params(struct tegra_dfll *td)
+{
+       struct regmap *regmap;
+       struct device *i2c_dev;
+       struct i2c_client *i2c_client;
+       int vsel_reg, vsel_mask;
+       int ret;
+
+       if (!read_dt_param(td, "nvidia,i2c-fs-rate", &td->i2c_fs_rate))
+               return -EINVAL;
+
+       regmap = regulator_get_regmap(td->vdd_reg);
+       i2c_dev = regmap_get_device(regmap);
+       i2c_client = to_i2c_client(i2c_dev);
+
+       td->i2c_slave_addr = i2c_client->addr;
+
+       ret = regulator_get_hardware_vsel_register(td->vdd_reg,
+                                                  &vsel_reg,
+                                                  &vsel_mask);
+       if (ret < 0) {
+               dev_err(td->dev,
+                       "regulator unsuitable for DFLL I2C operation\n");
+               return -EINVAL;
+       }
+       td->i2c_reg = vsel_reg;
+
+       ret = dfll_build_i2c_lut(td);
+       if (ret) {
+               dev_err(td->dev, "couldn't build I2C LUT\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * dfll_fetch_common_params - read DFLL parameters from the device tree
+ * @td: DFLL instance
+ *
+ * Read all the DT parameters that are common to both I2C and PWM operation.
+ * Returns 0 on success or -EINVAL on any failure.
+ */
+static int dfll_fetch_common_params(struct tegra_dfll *td)
+{
+       bool ok = true;
+
+       ok &= read_dt_param(td, "nvidia,droop-ctrl", &td->droop_ctrl);
+       ok &= read_dt_param(td, "nvidia,sample-rate", &td->sample_rate);
+       ok &= read_dt_param(td, "nvidia,force-mode", &td->force_mode);
+       ok &= read_dt_param(td, "nvidia,cf", &td->cf);
+       ok &= read_dt_param(td, "nvidia,ci", &td->ci);
+       ok &= read_dt_param(td, "nvidia,cg", &td->cg);
+       td->cg_scale = of_property_read_bool(td->dev->of_node,
+                                            "nvidia,cg-scale");
+
+       if (of_property_read_string(td->dev->of_node, "clock-output-names",
+                                   &td->output_clock_name)) {
+               dev_err(td->dev, "missing clock-output-names property\n");
+               ok = false;
+       }
+
+       return ok ? 0 : -EINVAL;
+}
+
+/*
+ * API exported to per-SoC platform drivers
+ */
+
+/**
+ * tegra_dfll_register - probe a Tegra DFLL device
+ * @pdev: DFLL platform_device *
+ * @soc: Per-SoC integration and characterization data for this DFLL instance
+ *
+ * Probe and initialize a DFLL device instance. Intended to be called
+ * by a SoC-specific shim driver that passes in per-SoC integration
+ * and configuration data via @soc. Returns 0 on success or -err on failure.
+ */
+int tegra_dfll_register(struct platform_device *pdev,
+                       struct tegra_dfll_soc_data *soc)
+{
+       struct resource *mem;
+       struct tegra_dfll *td;
+       int ret;
+
+       if (!soc) {
+               dev_err(&pdev->dev, "no tegra_dfll_soc_data provided\n");
+               return -EINVAL;
+       }
+
+       td = devm_kzalloc(&pdev->dev, sizeof(*td), GFP_KERNEL);
+       if (!td)
+               return -ENOMEM;
+       td->dev = &pdev->dev;
+       platform_set_drvdata(pdev, td);
+
+       td->soc = soc;
+
+       td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
+       if (IS_ERR(td->vdd_reg)) {
+               dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
+               return PTR_ERR(td->vdd_reg);
+       }
+
+       td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
+       if (IS_ERR(td->dvco_rst)) {
+               dev_err(td->dev, "couldn't get dvco reset\n");
+               return PTR_ERR(td->dvco_rst);
+       }
+
+       ret = dfll_fetch_common_params(td);
+       if (ret) {
+               dev_err(td->dev, "couldn't parse device tree parameters\n");
+               return ret;
+       }
+
+       ret = dfll_fetch_i2c_params(td);
+       if (ret)
+               return ret;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(td->dev, "no control register resource\n");
+               return -ENODEV;
+       }
+
+       td->base = devm_ioremap(td->dev, mem->start, resource_size(mem));
+       if (!td->base) {
+               dev_err(td->dev, "couldn't ioremap DFLL control registers\n");
+               return -ENODEV;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!mem) {
+               dev_err(td->dev, "no i2c_base resource\n");
+               return -ENODEV;
+       }
+
+       td->i2c_base = devm_ioremap(td->dev, mem->start, resource_size(mem));
+       if (!td->i2c_base) {
+               dev_err(td->dev, "couldn't ioremap i2c_base resource\n");
+               return -ENODEV;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       if (!mem) {
+               dev_err(td->dev, "no i2c_controller_base resource\n");
+               return -ENODEV;
+       }
+
+       td->i2c_controller_base = devm_ioremap(td->dev, mem->start,
+                                              resource_size(mem));
+       if (!td->i2c_controller_base) {
+               dev_err(td->dev,
+                       "couldn't ioremap i2c_controller_base resource\n");
+               return -ENODEV;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       if (!mem) {
+               dev_err(td->dev, "no lut_base resource\n");
+               return -ENODEV;
+       }
+
+       td->lut_base = devm_ioremap(td->dev, mem->start, resource_size(mem));
+       if (!td->lut_base) {
+               dev_err(td->dev,
+                       "couldn't ioremap lut_base resource\n");
+               return -ENODEV;
+       }
+
+       ret = dfll_init_clks(td);
+       if (ret) {
+               dev_err(&pdev->dev, "DFLL clock init error\n");
+               return ret;
+       }
+
+       /* Enable the clocks and set the device up */
+       ret = dfll_init(td);
+       if (ret)
+               return ret;
+
+       ret = dfll_register_clk(td);
+       if (ret) {
+               dev_err(&pdev->dev, "DFLL clk registration failed\n");
+               return ret;
+       }
+
+#ifdef CONFIG_DEBUG_FS
+       dfll_debug_init(td);
+#endif
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_register);
+
+/**
+ * tegra_dfll_unregister - release all of the DFLL driver resources for a device
+ * @pdev: DFLL platform_device *
+ *
+ * Unbind this driver from the DFLL hardware device represented by
+ * @pdev. The DFLL must be disabled for this to succeed. Returns 0
+ * upon success or -EBUSY if the DFLL is still active.
+ */
+int tegra_dfll_unregister(struct platform_device *pdev)
+{
+       struct tegra_dfll *td = platform_get_drvdata(pdev);
+
+       /* Try to prevent removal while the DFLL is active */
+       if (td->mode != DFLL_DISABLED) {
+               dev_err(&pdev->dev,
+                       "must disable DFLL before removing driver\n");
+               return -EBUSY;
+       }
+
+       debugfs_remove_recursive(td->debugfs_dir);
+
+       dfll_unregister_clk(td);
+       pm_runtime_disable(&pdev->dev);
+
+       clk_unprepare(td->ref_clk);
+       clk_unprepare(td->soc_clk);
+       clk_unprepare(td->i2c_clk);
+
+       reset_control_assert(td->dvco_rst);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_unregister);
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
new file mode 100644 (file)
index 0000000..2e4c077
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * clk-dfll.h - prototypes and macros for the Tegra DFLL clocksource driver
+ * Copyright (C) 2013 NVIDIA Corporation.  All rights reserved.
+ *
+ * Aleksandr Frid <afrid@nvidia.com>
+ * Paul Walmsley <pwalmsley@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef __DRIVERS_CLK_TEGRA_CLK_DFLL_H
+#define __DRIVERS_CLK_TEGRA_CLK_DFLL_H
+
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/types.h>
+
+/**
+ * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
+ * @opp_dev: struct device * that holds the OPP table for the DFLL
+ * @min_millivolts: minimum voltage (in mV) that the DFLL can operate
+ * @tune0_low: DFLL tuning register 0 (low voltage range)
+ * @tune0_high: DFLL tuning register 0 (high voltage range)
+ * @tune1: DFLL tuning register 1
+ * @assert_dvco_reset: fn ptr to place the DVCO in reset
+ * @deassert_dvco_reset: fn ptr to release the DVCO reset
+ * @set_clock_trimmers_high: fn ptr to tune clock trimmers for high voltage
+ * @set_clock_trimmers_low: fn ptr to tune clock trimmers for low voltage
+ */
+struct tegra_dfll_soc_data {
+       struct device *dev;
+       unsigned int min_millivolts;
+       u32 tune0_low;
+       u32 tune0_high;
+       u32 tune1;
+       void (*init_clock_trimmers)(void);
+       void (*set_clock_trimmers_high)(void);
+       void (*set_clock_trimmers_low)(void);
+};
+
+int tegra_dfll_register(struct platform_device *pdev,
+                       struct tegra_dfll_soc_data *soc);
+int tegra_dfll_unregister(struct platform_device *pdev);
+int tegra_dfll_runtime_suspend(struct device *dev);
+int tegra_dfll_runtime_resume(struct device *dev);
+
+#endif /* __DRIVERS_CLK_TEGRA_CLK_DFLL_H */
index 59a5714dfe18c237323821027ccae5bb59916a38..48c83efda4cff4cb99ab3df0d3c3a26bc7999c26 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 7649685c86bc181dcada918f3bcf181ec9d4c802..138a94b99b5bb5ce0863ef9a0110b4bea928159a 100644 (file)
@@ -103,7 +103,7 @@ static unsigned long emc_recalc_rate(struct clk_hw *hw,
         * CCF wrongly assumes that the parent won't change during set_rate,
         * so get the parent rate explicitly.
         */
-       parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+       parent_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        val = readl(tegra->clk_regs + CLK_SOURCE_EMC);
        div = val & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK;
@@ -116,11 +116,7 @@ static unsigned long emc_recalc_rate(struct clk_hw *hw,
  * safer since things have EMC rate floors. Also don't touch parent_rate
  * since we don't want the CCF to play with our parent clocks.
  */
-static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long min_rate,
-                              unsigned long max_rate,
-                              unsigned long *best_parent_rate,
-                              struct clk_hw **best_parent_hw)
+static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
        struct tegra_clk_emc *tegra;
        u8 ram_code = tegra_read_ram_code();
@@ -135,22 +131,28 @@ static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
 
                timing = tegra->timings + i;
 
-               if (timing->rate > max_rate) {
+               if (timing->rate > req->max_rate) {
                        i = min(i, 1);
-                       return tegra->timings[i - 1].rate;
+                       req->rate = tegra->timings[i - 1].rate;
+                       return 0;
                }
 
-               if (timing->rate < min_rate)
+               if (timing->rate < req->min_rate)
                        continue;
 
-               if (timing->rate >= rate)
-                       return timing->rate;
+               if (timing->rate >= req->rate) {
+                       req->rate = timing->rate;
+                       return 0;
+               }
        }
 
-       if (timing)
-               return timing->rate;
+       if (timing) {
+               req->rate = timing->rate;
+               return 0;
+       }
 
-       return __clk_get_rate(hw->clk);
+       req->rate = clk_hw_get_rate(hw);
+       return 0;
 }
 
 static u8 emc_get_parent(struct clk_hw *hw)
@@ -312,7 +314,7 @@ static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
 
        tegra = container_of(hw, struct tegra_clk_emc, hw);
 
-       if (__clk_get_rate(hw->clk) == rate)
+       if (clk_hw_get_rate(hw) == rate)
                return 0;
 
        /*
@@ -525,8 +527,8 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
        if (IS_ERR(clk))
                return clk;
 
-       tegra->prev_parent = clk_get_parent_by_index(
-               tegra->hw.clk, emc_get_parent(&tegra->hw));
+       tegra->prev_parent = clk_hw_get_parent_by_index(
+               &tegra->hw, emc_get_parent(&tegra->hw))->clk;
        tegra->changing_timing = false;
 
        /* Allow debugging tools to see the EMC clock */
index 0aa8830ae7cc76c5fd1335ce8149a981ec0612d8..d28d6e95020fe3913a0af333ef24680659f6aee4 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
index d84ae49d0e05eead08c6379a0236c339ff88cb5c..ec5b6113b01270f25210216d9093d2bb37c67e4a 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/export.h>
 #include <linux/slab.h>
index 3598987a451d77a33b6d3515a85d9b3d879252f1..257cae0c1488e13f30b12dff93dbe1e2a7d544e1 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 05c6d08a6695861344713919e0474cc05a3c701e..d6d4ecb88e945e6a8c23ecbd12081d3e8616e10a 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/clk-provider.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 
 #include "clk.h"
 
@@ -264,7 +264,7 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
        }
 
        pr_err("%s: Timed out waiting for pll %s lock\n", __func__,
-              __clk_get_name(pll->hw.clk));
+              clk_hw_get_name(&pll->hw));
 
        return -1;
 }
@@ -595,7 +595,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (pll->params->flags & TEGRA_PLL_FIXED) {
                if (rate != pll->params->fixed_rate) {
                        pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
-                               __func__, __clk_get_name(hw->clk),
+                               __func__, clk_hw_get_name(hw),
                                pll->params->fixed_rate, rate);
                        return -EINVAL;
                }
@@ -605,7 +605,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
            _calc_rate(hw, &cfg, rate, parent_rate)) {
                pr_err("%s: Failed to set %s rate %lu\n", __func__,
-                      __clk_get_name(hw->clk), rate);
+                      clk_hw_get_name(hw), rate);
                WARN_ON(1);
                return -EINVAL;
        }
@@ -634,7 +634,7 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 
        /* PLLM is used for memory; we do not change rate */
        if (pll->params->flags & TEGRA_PLLM)
-               return __clk_get_rate(hw->clk);
+               return clk_hw_get_rate(hw);
 
        if (_get_table_rate(hw, &cfg, rate, *prate) &&
            _calc_rate(hw, &cfg, rate, *prate))
@@ -663,7 +663,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
                if (_get_table_rate(hw, &sel, pll->params->fixed_rate,
                                        parent_rate)) {
                        pr_err("Clock %s has unknown fixed frequency\n",
-                              __clk_get_name(hw->clk));
+                              clk_hw_get_name(hw));
                        BUG();
                }
                return pll->params->fixed_rate;
@@ -1577,7 +1577,7 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
        if (!pll_params->pdiv_tohw)
                return ERR_PTR(-EINVAL);
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
@@ -1674,7 +1674,7 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
                return ERR_PTR(-EINVAL);
        }
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
@@ -1715,7 +1715,7 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
                return ERR_PTR(-EINVAL);
        }
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
@@ -1848,7 +1848,7 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
        val &= ~PLLSS_REF_SRC_SEL_MASK;
        pll_writel_base(val, pll);
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
index 2fd924d38606920ce011cb51edf4adb0ab544720..131d1b5085e287a1f3b72d83f79370cd380a7b9e 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 5c38aab2c5b8273a0b2fddc88d398faacdd12e6d..11e3ad7ad7a381b1f3a0ea7081e497f361b58512 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 605676d368eb49acdb7c57d1740e2af151a81279..da0b5941c89ffae2ee3b7b367f0f0413f0a1959a 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 46af9244ba74576f23e3e27dc9b2380cb0d39686..cb6ab830941d4052625b2218a37370761eff7df7 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index 08b21c1ee867e6d898699b904afa6a93781eff3e..91377abfefa19189f82ba32e12a6e0484ed8f9c9 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index feb3201c85ce5df6d8786eaf2e4a0408e5890ec0..5b1d723932c5e07e4a2dd6efce31cf02f0d12b0f 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -44,7 +43,9 @@ static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
 
 static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
                                        "pll_p", "pll_p_out4", "unused",
-                                       "unused", "pll_x" };
+                                       "unused", "pll_x", "unused", "unused",
+                                       "unused", "unused", "unused", "unused",
+                                       "dfllCPU_out" };
 
 static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
                                         "pll_p", "pll_p_out4", "unused",
index 8237d16b407597dab129c5a277802190898a061f..db5871519bf5d5a17cac3bf06dba8d3f4fef3a31 100644 (file)
@@ -15,9 +15,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/delay.h>
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
new file mode 100644 (file)
index 0000000..6125333
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Tegra124 DFLL FCPU clock source driver
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * Aleksandr Frid <afrid@nvidia.com>
+ * Paul Walmsley <pwalmsley@nvidia.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/cpu.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <soc/tegra/fuse.h>
+
+#include "clk.h"
+#include "clk-dfll.h"
+#include "cvb.h"
+
+/* Maximum CPU frequency, indexed by CPU speedo id */
+static const unsigned long cpu_max_freq_table[] = {
+       [0] = 2014500000UL,
+       [1] = 2320500000UL,
+       [2] = 2116500000UL,
+       [3] = 2524500000UL,
+};
+
+static const struct cvb_table tegra124_cpu_cvb_tables[] = {
+       {
+               .speedo_id = -1,
+               .process_id = -1,
+               .min_millivolts = 900,
+               .max_millivolts = 1260,
+               .alignment = {
+                       .step_uv = 10000, /* 10mV */
+               },
+               .speedo_scale = 100,
+               .voltage_scale = 1000,
+               .cvb_table = {
+                       {204000000UL,   {1112619, -29295, 402} },
+                       {306000000UL,   {1150460, -30585, 402} },
+                       {408000000UL,   {1190122, -31865, 402} },
+                       {510000000UL,   {1231606, -33155, 402} },
+                       {612000000UL,   {1274912, -34435, 402} },
+                       {714000000UL,   {1320040, -35725, 402} },
+                       {816000000UL,   {1366990, -37005, 402} },
+                       {918000000UL,   {1415762, -38295, 402} },
+                       {1020000000UL,  {1466355, -39575, 402} },
+                       {1122000000UL,  {1518771, -40865, 402} },
+                       {1224000000UL,  {1573009, -42145, 402} },
+                       {1326000000UL,  {1629068, -43435, 402} },
+                       {1428000000UL,  {1686950, -44715, 402} },
+                       {1530000000UL,  {1746653, -46005, 402} },
+                       {1632000000UL,  {1808179, -47285, 402} },
+                       {1734000000UL,  {1871526, -48575, 402} },
+                       {1836000000UL,  {1936696, -49855, 402} },
+                       {1938000000UL,  {2003687, -51145, 402} },
+                       {2014500000UL,  {2054787, -52095, 402} },
+                       {2116500000UL,  {2124957, -53385, 402} },
+                       {2218500000UL,  {2196950, -54665, 402} },
+                       {2320500000UL,  {2270765, -55955, 402} },
+                       {2422500000UL,  {2346401, -57235, 402} },
+                       {2524500000UL,  {2437299, -58535, 402} },
+                       {0,             {      0,      0,   0} },
+               },
+               .cpu_dfll_data = {
+                       .tune0_low = 0x005020ff,
+                       .tune0_high = 0x005040ff,
+                       .tune1 = 0x00000060,
+               }
+       },
+};
+
+static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
+{
+       int process_id, speedo_id, speedo_value;
+       struct tegra_dfll_soc_data *soc;
+       const struct cvb_table *cvb;
+
+       process_id = tegra_sku_info.cpu_process_id;
+       speedo_id = tegra_sku_info.cpu_speedo_id;
+       speedo_value = tegra_sku_info.cpu_speedo_value;
+
+       if (speedo_id >= ARRAY_SIZE(cpu_max_freq_table)) {
+               dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
+                       speedo_id);
+               return -ENODEV;
+       }
+
+       soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL);
+       if (!soc)
+               return -ENOMEM;
+
+       soc->dev = get_cpu_device(0);
+       if (!soc->dev) {
+               dev_err(&pdev->dev, "no CPU0 device\n");
+               return -ENODEV;
+       }
+
+       cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables,
+                                       ARRAY_SIZE(tegra124_cpu_cvb_tables),
+                                       process_id, speedo_id, speedo_value,
+                                       cpu_max_freq_table[speedo_id],
+                                       soc->dev);
+       if (IS_ERR(cvb)) {
+               dev_err(&pdev->dev, "couldn't build OPP table: %ld\n",
+                       PTR_ERR(cvb));
+               return PTR_ERR(cvb);
+       }
+
+       soc->min_millivolts = cvb->min_millivolts;
+       soc->tune0_low = cvb->cpu_dfll_data.tune0_low;
+       soc->tune0_high = cvb->cpu_dfll_data.tune0_high;
+       soc->tune1 = cvb->cpu_dfll_data.tune1;
+
+       return tegra_dfll_register(pdev, soc);
+}
+
+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,
+                          tegra_dfll_runtime_resume, NULL)
+};
+
+static struct platform_driver tegra124_dfll_fcpu_driver = {
+       .probe = tegra124_dfll_fcpu_probe,
+       .remove = tegra_dfll_unregister,
+       .driver = {
+               .name = "tegra124-dfll",
+               .of_match_table = tegra124_dfll_fcpu_of_match,
+               .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>");
index e8cca3eac00742713cc8fe39f9a63c8fe9b62def..824d75883d2bfbca814f101e1a601387bbce070b 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
@@ -24,6 +23,7 @@
 #include <linux/export.h>
 #include <linux/clk/tegra.h>
 #include <dt-bindings/clock/tegra124-car.h>
+#include <dt-bindings/reset/tegra124-car.h>
 
 #include "clk.h"
 #include "clk-id.h"
@@ -39,6 +39,9 @@
 #define CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 
+#define RST_DFLL_DVCO                  0x2f4
+#define DVFS_DFLL_RESET_SHIFT          0
+
 #define PLLC_BASE 0x80
 #define PLLC_OUT 0x84
 #define PLLC_MISC2 0x88
@@ -94,6 +97,8 @@
 #define PMC_PLLM_WB0_OVERRIDE 0x1dc
 #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
 
+#define CCLKG_BURST_POLICY 0x368
+
 #define UTMIP_PLL_CFG2 0x488
 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
 #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
 #ifdef CONFIG_PM_SLEEP
 static struct cpu_clk_suspend_context {
        u32 clk_csite_src;
+       u32 cclkg_burst;
+       u32 cclkg_divider;
 } tegra124_cpu_clk_sctx;
 #endif
 
@@ -1319,12 +1326,22 @@ static void tegra124_cpu_clock_suspend(void)
        tegra124_cpu_clk_sctx.clk_csite_src =
                                readl(clk_base + CLK_SOURCE_CSITE);
        writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+
+       tegra124_cpu_clk_sctx.cclkg_burst =
+                               readl(clk_base + CCLKG_BURST_POLICY);
+       tegra124_cpu_clk_sctx.cclkg_divider =
+                               readl(clk_base + CCLKG_BURST_POLICY + 4);
 }
 
 static void tegra124_cpu_clock_resume(void)
 {
        writel(tegra124_cpu_clk_sctx.clk_csite_src,
                                clk_base + CLK_SOURCE_CSITE);
+
+       writel(tegra124_cpu_clk_sctx.cclkg_burst,
+                                       clk_base + CCLKG_BURST_POLICY);
+       writel(tegra124_cpu_clk_sctx.cclkg_divider,
+                                       clk_base + CCLKG_BURST_POLICY + 4);
 }
 #endif
 
@@ -1414,6 +1431,68 @@ static void __init tegra124_clock_apply_init_table(void)
        tegra_init_from_table(tegra124_init_table, clks, TEGRA124_CLK_CLK_MAX);
 }
 
+/**
+ * tegra124_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution.  No return value.
+ */
+static void tegra124_car_barrier(void)
+{
+       readl_relaxed(clk_base + RST_DFLL_DVCO);
+}
+
+/**
+ * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO.  No return value.
+ */
+static void tegra124_clock_assert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v |= (1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra124_car_barrier();
+}
+
+/**
+ * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate.  No return value.
+ */
+static void tegra124_clock_deassert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra124_car_barrier();
+}
+
+static int tegra124_reset_assert(unsigned long id)
+{
+       if (id == TEGRA124_RST_DFLL_DVCO)
+               tegra124_clock_assert_dfll_dvco_reset();
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tegra124_reset_deassert(unsigned long id)
+{
+       if (id == TEGRA124_RST_DFLL_DVCO)
+               tegra124_clock_deassert_dfll_dvco_reset();
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
  *
@@ -1499,6 +1578,8 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
 {
        tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
                                  &pll_x_params);
+       tegra_init_special_resets(1, tegra124_reset_assert,
+                                 tegra124_reset_deassert);
        tegra_add_of_provider(np);
 
        clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
index 41272dcc9e225758da291018dc71bf921f85be8f..bf004f0e4f658b39ab38edf4b57e20005922a25e 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index 0af3e834dd24a25d3e3e0cbfa020c596d57bc908..fad561a5896beddbd3ee56efbaa363cc3375964f 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index 41cd87c67be6a009a8b5a138672e21f6a4c0c003..2a3a4fe803d6d27e16c7de373f0ec1b8f2164264 100644 (file)
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/clkdev.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
@@ -49,7 +50,6 @@
 #define RST_DEVICES_L                  0x004
 #define RST_DEVICES_H                  0x008
 #define RST_DEVICES_U                  0x00C
-#define RST_DFLL_DVCO                  0x2F4
 #define RST_DEVICES_V                  0x358
 #define RST_DEVICES_W                  0x35C
 #define RST_DEVICES_X                  0x28C
@@ -79,6 +79,11 @@ static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
 
+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static unsigned int num_special_reset;
+
 static struct tegra_clk_periph_regs periph_regs[] = {
        [0] = {
                .enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +157,29 @@ static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
         */
        tegra_read_chipid();
 
-       writel_relaxed(BIT(id % 32),
-                       clk_base + periph_regs[id / 32].rst_set_reg);
+       if (id < periph_banks * 32) {
+               writel_relaxed(BIT(id % 32),
+                              clk_base + periph_regs[id / 32].rst_set_reg);
+               return 0;
+       } else if (id < periph_banks * 32 + num_special_reset) {
+               return special_reset_assert(id);
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
                unsigned long id)
 {
-       writel_relaxed(BIT(id % 32),
-                       clk_base + periph_regs[id / 32].rst_clr_reg);
+       if (id < periph_banks * 32) {
+               writel_relaxed(BIT(id % 32),
+                              clk_base + periph_regs[id / 32].rst_clr_reg);
+               return 0;
+       } else if (id < periph_banks * 32 + num_special_reset) {
+               return special_reset_deassert(id);
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +301,19 @@ void __init tegra_add_of_provider(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
        rst_ctlr.of_node = np;
-       rst_ctlr.nr_resets = periph_banks * 32;
+       rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
        reset_controller_register(&rst_ctlr);
 }
 
+void __init tegra_init_special_resets(unsigned int num,
+                                     int (*assert)(unsigned long),
+                                     int (*deassert)(unsigned long))
+{
+       num_special_reset = num;
+       special_reset_assert = assert;
+       special_reset_deassert = deassert;
+}
+
 void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 {
        int i;
index 75ddc8ff8bd4aff97d61ff9ae27095aa2ba0cf33..0621887e06f71604eb3193f36690fe28d8ff9124 100644 (file)
@@ -591,6 +591,9 @@ struct tegra_devclk {
        char            *con_id;
 };
 
+void tegra_init_special_resets(unsigned int num, int (*assert)(unsigned long),
+                              int (*deassert)(unsigned long));
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
                struct clk *clks[], int clk_max);
 
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
new file mode 100644 (file)
index 0000000..0204e08
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Utility functions for parsing Tegra CVB voltage tables
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms 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/err.h>
+#include <linux/kernel.h>
+#include <linux/pm_opp.h>
+
+#include "cvb.h"
+
+/* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) */
+static inline int get_cvb_voltage(int speedo, int s_scale,
+                                 const struct cvb_coefficients *cvb)
+{
+       int mv;
+
+       /* apply only speedo scale: output mv = cvb_mv * v_scale */
+       mv = DIV_ROUND_CLOSEST(cvb->c2 * speedo, s_scale);
+       mv = DIV_ROUND_CLOSEST((mv + cvb->c1) * speedo, s_scale) + cvb->c0;
+       return mv;
+}
+
+static int round_cvb_voltage(int mv, int v_scale,
+                            const struct rail_alignment *align)
+{
+       /* combined: apply voltage scale and round to cvb alignment step */
+       int uv;
+       int step = (align->step_uv ? : 1000) * v_scale;
+       int offset = align->offset_uv * v_scale;
+
+       uv = max(mv * 1000, offset) - offset;
+       uv = DIV_ROUND_UP(uv, step) * align->step_uv + align->offset_uv;
+       return uv / 1000;
+}
+
+enum {
+       DOWN,
+       UP
+};
+
+static int round_voltage(int mv, const struct rail_alignment *align, int up)
+{
+       if (align->step_uv) {
+               int uv;
+
+               uv = max(mv * 1000, align->offset_uv) - align->offset_uv;
+               uv = (uv + (up ? align->step_uv - 1 : 0)) / align->step_uv;
+               return (uv * align->step_uv + align->offset_uv) / 1000;
+       }
+       return mv;
+}
+
+static int build_opp_table(const struct cvb_table *d,
+                          int speedo_value,
+                          unsigned long max_freq,
+                          struct device *opp_dev)
+{
+       int i, ret, dfll_mv, min_mv, max_mv;
+       const struct cvb_table_freq_entry *table = NULL;
+       const struct rail_alignment *align = &d->alignment;
+
+       min_mv = round_voltage(d->min_millivolts, align, UP);
+       max_mv = round_voltage(d->max_millivolts, align, DOWN);
+
+       for (i = 0; i < MAX_DVFS_FREQS; i++) {
+               table = &d->cvb_table[i];
+               if (!table->freq || (table->freq > max_freq))
+                       break;
+
+               /*
+                * FIXME after clk_round_rate/clk_determine_rate prototypes
+                * have been updated
+                */
+               if (table->freq & (1<<31))
+                       continue;
+
+               dfll_mv = get_cvb_voltage(
+                       speedo_value, d->speedo_scale, &table->coefficients);
+               dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align);
+               dfll_mv = clamp(dfll_mv, min_mv, max_mv);
+
+               ret = dev_pm_opp_add(opp_dev, table->freq, dfll_mv * 1000);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables
+ * @cvb_tables: array of CVB tables
+ * @sz: 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
+ *
+ * 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
+ * or an ERR_PTR on failure.
+ */
+const struct cvb_table *tegra_cvb_build_opp_table(
+               const struct cvb_table *cvb_tables,
+               size_t sz, int process_id,
+               int speedo_id, int speedo_value,
+               unsigned long max_rate,
+               struct device *opp_dev)
+{
+       int i, ret;
+
+       for (i = 0; i < sz; i++) {
+               const struct cvb_table *d = &cvb_tables[i];
+
+               if (d->speedo_id != -1 && d->speedo_id != speedo_id)
+                       continue;
+               if (d->process_id != -1 && d->process_id != process_id)
+                       continue;
+
+               ret = build_opp_table(d, speedo_value, max_rate, opp_dev);
+               return ret ? ERR_PTR(ret) : d;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
new file mode 100644 (file)
index 0000000..f62cdc4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Utility functions for parsing Tegra CVB voltage tables
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __DRIVERS_CLK_TEGRA_CVB_H
+#define __DRIVERS_CLK_TEGRA_CVB_H
+
+#include <linux/types.h>
+
+struct device;
+
+#define MAX_DVFS_FREQS 40
+
+struct rail_alignment {
+       int offset_uv;
+       int step_uv;
+};
+
+struct cvb_coefficients {
+       int c0;
+       int c1;
+       int c2;
+};
+
+struct cvb_table_freq_entry {
+       unsigned long freq;
+       struct cvb_coefficients coefficients;
+};
+
+struct cvb_cpu_dfll_data {
+       u32 tune0_low;
+       u32 tune0_high;
+       u32 tune1;
+};
+
+struct cvb_table {
+       int speedo_id;
+       int process_id;
+
+       int min_millivolts;
+       int max_millivolts;
+       struct rail_alignment alignment;
+
+       int speedo_scale;
+       int voltage_scale;
+       struct cvb_table_freq_entry cvb_table[MAX_DVFS_FREQS];
+       struct cvb_cpu_dfll_data cpu_dfll_data;
+};
+
+const struct cvb_table *tegra_cvb_build_opp_table(
+               const struct cvb_table *cvb_tables,
+               size_t sz, int process_id,
+               int speedo_id, int speedo_value,
+               unsigned long max_rate,
+               struct device *opp_dev);
+
+#endif
index 105ffd0f5e79da04e496b291e4eb3968b834ba64..9b93e6904359ddd465712a291da1f43b9fefc735 100644 (file)
@@ -1,16 +1,19 @@
 obj-y                                  += clk.o autoidle.o clockdomain.o
 clk-common                             = dpll.o composite.o divider.o gate.o \
-                                         fixed-factor.o mux.o apll.o
-obj-$(CONFIG_SOC_AM33XX)               += $(clk-common) clk-33xx.o
+                                         fixed-factor.o mux.o apll.o \
+                                         clkt_dpll.o clkt_iclk.o clkt_dflt.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clk-common) clk-33xx.o dpll3xxx.o
 obj-$(CONFIG_SOC_TI81XX)               += $(clk-common) fapll.o clk-816x.o
 obj-$(CONFIG_ARCH_OMAP2)               += $(clk-common) interface.o clk-2xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += $(clk-common) interface.o \
-                                          clk-3xxx.o
-obj-$(CONFIG_ARCH_OMAP4)               += $(clk-common) clk-44xx.o
-obj-$(CONFIG_SOC_OMAP5)                        += $(clk-common) clk-54xx.o
+                                          clk-3xxx.o dpll3xxx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(clk-common) clk-44xx.o \
+                                          dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clk-common) clk-54xx.o \
+                                          dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_DRA7XX)               += $(clk-common) clk-7xx.o \
-                                          clk-dra7-atl.o
-obj-$(CONFIG_SOC_AM43XX)               += $(clk-common) clk-43xx.o
+                                          clk-dra7-atl.o dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_AM43XX)               += $(clk-common) dpll3xxx.o clk-43xx.o
 
 ifdef CONFIG_ATAGS
 obj-$(CONFIG_ARCH_OMAP3)                += clk-3xxx-legacy.o
index 49baf38315463d9e77cd6b34e3fdbd8cc21cc832..f3eab6e7902707d6f0d11ea01daef8e1f76a8d9b 100644 (file)
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -27,6 +28,8 @@
 #include <linux/clk/ti.h>
 #include <linux/delay.h>
 
+#include "clock.h"
+
 #define APLL_FORCE_LOCK 0x1
 #define APLL_AUTO_IDLE 0x2
 #define MAX_APLL_WAIT_TRIES            1000000
@@ -47,7 +50,7 @@ static int dra7_apll_enable(struct clk_hw *hw)
        if (!ad)
                return -EINVAL;
 
-       clk_name = __clk_get_name(clk->hw.clk);
+       clk_name = clk_hw_get_name(&clk->hw);
 
        state <<= __ffs(ad->idlest_mask);
 
@@ -170,7 +173,6 @@ static void __init of_dra7_apll_setup(struct device_node *node)
        struct clk_hw_omap *clk_hw = NULL;
        struct clk_init_data *init = NULL;
        const char **parent_names = NULL;
-       int i;
 
        ad = kzalloc(sizeof(*ad), GFP_KERNEL);
        clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
@@ -195,8 +197,7 @@ static void __init of_dra7_apll_setup(struct device_node *node)
        if (!parent_names)
                goto cleanup;
 
-       for (i = 0; i < init->num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, init->num_parents);
 
        init->parent_names = parent_names;
 
@@ -272,7 +273,7 @@ static int omap2_apll_enable(struct clk_hw *hw)
 
        if (i == MAX_APLL_WAIT_TRIES) {
                pr_warn("%s failed to transition to locked\n",
-                       __clk_get_name(clk->hw.clk));
+                       clk_hw_get_name(&clk->hw));
                return -EBUSY;
        }
 
index e75c64c9e81c1d1c3dae2b9779e3538426a66e85..345af43465f0f9a27aeedc431b51d0733bc4b896 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 struct clk_ti_autoidle {
        void __iomem            *reg;
        u8                      shift;
@@ -33,8 +35,41 @@ struct clk_ti_autoidle {
 #define AUTOIDLE_LOW           0x1
 
 static LIST_HEAD(autoidle_clks);
+static LIST_HEAD(clk_hw_omap_clocks);
+
+/**
+ * omap2_clk_deny_idle - disable autoidle on an OMAP clock
+ * @clk: struct clk * to disable autoidle for
+ *
+ * Disable autoidle on an OMAP clock.
+ */
+int omap2_clk_deny_idle(struct clk *clk)
+{
+       struct clk_hw_omap *c;
 
-static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
+       c = to_clk_hw_omap(__clk_get_hw(clk));
+       if (c->ops && c->ops->deny_idle)
+               c->ops->deny_idle(c);
+       return 0;
+}
+
+/**
+ * omap2_clk_allow_idle - enable autoidle on an OMAP clock
+ * @clk: struct clk * to enable autoidle for
+ *
+ * Enable autoidle on an OMAP clock.
+ */
+int omap2_clk_allow_idle(struct clk *clk)
+{
+       struct clk_hw_omap *c;
+
+       c = to_clk_hw_omap(__clk_get_hw(clk));
+       if (c->ops && c->ops->allow_idle)
+               c->ops->allow_idle(c);
+       return 0;
+}
+
+static void _allow_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
@@ -48,7 +83,7 @@ static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
        ti_clk_ll_ops->clk_writel(val, clk->reg);
 }
 
-static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+static void _deny_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
@@ -63,31 +98,31 @@ static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
 }
 
 /**
- * of_ti_clk_allow_autoidle_all - enable autoidle for all clocks
+ * _clk_generic_allow_autoidle_all - enable autoidle for all clocks
  *
  * Enables hardware autoidle for all registered DT clocks, which have
  * the feature.
  */
-void of_ti_clk_allow_autoidle_all(void)
+static void _clk_generic_allow_autoidle_all(void)
 {
        struct clk_ti_autoidle *c;
 
        list_for_each_entry(c, &autoidle_clks, node)
-               ti_allow_autoidle(c);
+               _allow_autoidle(c);
 }
 
 /**
- * of_ti_clk_deny_autoidle_all - disable autoidle for all clocks
+ * _clk_generic_deny_autoidle_all - disable autoidle for all clocks
  *
  * Disables hardware autoidle for all registered DT clocks, which have
  * the feature.
  */
-void of_ti_clk_deny_autoidle_all(void)
+static void _clk_generic_deny_autoidle_all(void)
 {
        struct clk_ti_autoidle *c;
 
        list_for_each_entry(c, &autoidle_clks, node)
-               ti_deny_autoidle(c);
+               _deny_autoidle(c);
 }
 
 /**
@@ -131,3 +166,67 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
 
        return 0;
 }
+
+/**
+ * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
+ * @hw: struct clk_hw * to initialize
+ *
+ * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
+ * temporarily for autoidle handling, until this support can be
+ * integrated into the common clock framework code in some way.  No
+ * return value.
+ */
+void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw)
+{
+       struct clk_hw_omap *c;
+
+       if (clk_hw_get_flags(hw) & CLK_IS_BASIC)
+               return;
+
+       c = to_clk_hw_omap(hw);
+       list_add(&c->node, &clk_hw_omap_clocks);
+}
+
+/**
+ * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Enable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them.  This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code.  Returns 0.
+ */
+int omap2_clk_enable_autoidle_all(void)
+{
+       struct clk_hw_omap *c;
+
+       list_for_each_entry(c, &clk_hw_omap_clocks, node)
+               if (c->ops && c->ops->allow_idle)
+                       c->ops->allow_idle(c);
+
+       _clk_generic_allow_autoidle_all();
+
+       return 0;
+}
+
+/**
+ * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Disable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them.  This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code.  Returns 0.
+ */
+int omap2_clk_disable_autoidle_all(void)
+{
+       struct clk_hw_omap *c;
+
+       list_for_each_entry(c, &clk_hw_omap_clocks, node)
+               if (c->ops && c->ops->deny_idle)
+                       c->ops->deny_idle(c);
+
+       _clk_generic_deny_autoidle_all();
+
+       return 0;
+}
index c808ab3d2bb22e7ceca914de1a7287c73d0cf5cb..657c4fe07a955e615026d1724976789451d561ff 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
-#include <linux/clk-provider.h>
+#include <linux/clk.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk omap2xxx_clks[] = {
        DT_CLK(NULL, "func_32k_ck", "func_32k_ck"),
        DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"),
index 028b33783d383c695a8c3ef6a467e09634094ad5..ef2ec64fe5471aa47b39588c0a8647d0938b6c6e 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk am33xx_clks[] = {
        DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
        DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
index 0b61548d569bc11acf976a9db71c846242e683aa..0fbf8a9179555d052c65251dfdfbf4a322b9c6d3 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
index 757636d166cff45035a355dc83830511c3640c74..676ee8f6d8136729a9665cfb9c29e7faed123781 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#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
+
+#define OMAP34XX_CM_IDLEST_VAL                         1
+
+/*
+ * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
+ * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
+ * at an offset of 4 from ICK enable bit.
+ */
+#define AM35XX_IPSS_ICK_MASK                   0xF
+#define AM35XX_IPSS_ICK_EN_ACK_OFFSET          0x4
+#define AM35XX_IPSS_ICK_FCK_OFFSET             0x8
+#define AM35XX_IPSS_CLK_IDLEST_VAL             0
+
+#define AM35XX_ST_IPSS_SHIFT                   5
+
+/**
+ * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
+ * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
+                                           void __iomem **idlest_reg,
+                                           u8 *idlest_bit,
+                                           u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/**
+ * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
+ * target IDLEST bits.  For our purposes, we are concerned with the
+ * target IDLEST bits, which exist at a different bit position than
+ * the *CLKEN bit position for these modules (DSS and USBHOST) (The
+ * default find_idlest code assumes that they are at the same
+ * position.)  No return value.
+ */
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
+                                                   void __iomem **idlest_reg,
+                                                   u8 *idlest_bit,
+                                                   u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       /* USBHOST_IDLE has same shift */
+       *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
+       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/**
+ * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
+ * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
+                                                void __iomem **idlest_reg,
+                                                u8 *idlest_bit,
+                                                u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/**
+ * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The interface clocks on AM35xx IPSS reflects the clock idle status
+ * in the enable register itsel at a bit offset of 4 from the enable
+ * bit. A value of 1 indicates that clock is enabled.
+ */
+static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
+                                  void __iomem **idlest_reg,
+                                  u8 *idlest_bit,
+                                  u8 *idlest_val)
+{
+       *idlest_reg = (__force void __iomem *)(clk->enable_reg);
+       *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
+       *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
+}
+
+/**
+ * am35xx_clk_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as HECC) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
+ */
+static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
+                                     void __iomem **other_reg,
+                                     u8 *other_bit)
+{
+       *other_reg = (__force void __iomem *)(clk->enable_reg);
+       if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
+               *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
+       else
+       *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
+}
+
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
+       .find_idlest    = am35xx_clk_find_idlest,
+       .find_companion = am35xx_clk_find_companion,
+};
+
+/**
+ * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The IPSS target CM_IDLEST bit is at a different shift from the
+ * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
+ * and @idlest_bit.  No return value.
+ */
+static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
+                                       void __iomem **idlest_reg,
+                                       u8 *idlest_bit,
+                                       u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = AM35XX_ST_IPSS_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = am35xx_clk_ipss_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
 
 static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "apb_pclk", "dummy_apb_pclk"),
@@ -324,6 +535,30 @@ enum {
        OMAP3_SOC_OMAP3630,
 };
 
+/**
+ * omap3_clk_lock_dpll5 - locks DPLL5
+ *
+ * Locks DPLL5 to a pre-defined frequency. This is required for proper
+ * operation of USB.
+ */
+void __init omap3_clk_lock_dpll5(void)
+{
+       struct clk *dpll5_clk;
+       struct clk *dpll5_m2_clk;
+
+       dpll5_clk = clk_get(NULL, "dpll5_ck");
+       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_prepare_enable(dpll5_clk);
+
+       /* Program dpll5_m2_clk divider for no division */
+       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_disable_unprepare(dpll5_m2_clk);
+       clk_disable_unprepare(dpll5_clk);
+}
+
 static int __init omap3xxx_dt_clk_init(int soc_type)
 {
        if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 ||
index 3795fce8a8303e66a004fe12bcf6d9008a7d5c63..72411fbcb6f306a007f6da7eb0ee136c17101fc7 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk am43xx_clks[] = {
        DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
        DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
index 581db7711f511245ab95956427ca51225c5b5c83..7a8b51b35f9fe799388a24d8d8b67ea7eabfbd8a 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 /*
  * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
  * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
index 96c69a335975a2a7cdccbd4060389f6e79378ba1..59ce2fa2c104a3a79e1cd490962a04aca8f2ab28 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/io.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #define OMAP5_DPLL_ABE_DEFFREQ                         98304000
 
 /*
index 63b8323df91836265203015b120af5e2bce82e0c..9b5b289e633456206e81268d00bc212a7f9f62cc 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #define DRA7_DPLL_ABE_DEFFREQ                          180633600
 #define DRA7_DPLL_GMAC_DEFFREQ                         1000000000
 #define DRA7_DPLL_USB_DEFFREQ                          960000000
 
-
 static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
        DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
index 9451e651a1ff748ee69b8ad5feb587a3c86769bb..c69352b24dba1cec5242984d9501c32548ce5264 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk dm816x_clks[] = {
        DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"),
        DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
index 19e543a32e2bad1e4591fb3106258d9f6769551b..2e14dfb588f445f7cb2a3d3c997c6786ca67a3de 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
index 64bb5e8a3b8cd845952bb4e97ffdead89f366d97..b5bcd77e8d0f5e31b3887ebdd3a4f441c7909a46 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/list.h>
+#include <linux/regmap.h>
+#include <linux/bootmem.h>
 
 #include "clock.h"
 
 struct ti_clk_ll_ops *ti_clk_ll_ops;
 static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
 
+static struct ti_clk_features ti_clk_features;
+
+struct clk_iomap {
+       struct regmap *regmap;
+       void __iomem *mem;
+};
+
+static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
+
+static void clk_memmap_writel(u32 val, void __iomem *reg)
+{
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_write(io->regmap, r->offset, val);
+       else
+               writel_relaxed(val, io->mem + r->offset);
+}
+
+static u32 clk_memmap_readl(void __iomem *reg)
+{
+       u32 val;
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_read(io->regmap, r->offset, &val);
+       else
+               val = readl_relaxed(io->mem + r->offset);
+
+       return val;
+}
+
+/**
+ * ti_clk_setup_ll_ops - setup low level clock operations
+ * @ops: low level clock ops descriptor
+ *
+ * Sets up low level clock operations for TI clock driver. This is used
+ * to provide various callbacks for the clock driver towards platform
+ * specific code. Returns 0 on success, -EBUSY if ll_ops have been
+ * registered already.
+ */
+int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
+{
+       if (ti_clk_ll_ops) {
+               pr_err("Attempt to register ll_ops multiple times.\n");
+               return -EBUSY;
+       }
+
+       ti_clk_ll_ops = ops;
+       ops->clk_readl = clk_memmap_readl;
+       ops->clk_writel = clk_memmap_writel;
+
+       return 0;
+}
+
 /**
  * ti_dt_clocks_register - register DT alias clocks during boot
  * @oclks: list of clocks to register
@@ -134,32 +194,67 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
 
        reg->offset = val;
 
-       return (void __iomem *)tmp;
+       return (__force void __iomem *)tmp;
 }
 
 /**
- * ti_dt_clk_init_provider - init master clock provider
+ * omap2_clk_provider_init - init master clock provider
  * @parent: master node
  * @index: internal index for clk_reg_ops
+ * @syscon: syscon regmap pointer for accessing clock registers
+ * @mem: iomem pointer for the clock provider memory area, only used if
+ *       syscon is not provided
  *
  * Initializes a master clock IP block. This basically sets up the
  * mapping from clocks node to the memory map index. All the clocks
  * are then initialized through the common of_clk_init call, and the
  * clocks will access their memory maps based on the node layout.
+ * Returns 0 in success.
  */
-void ti_dt_clk_init_provider(struct device_node *parent, int index)
+int __init omap2_clk_provider_init(struct device_node *parent, int index,
+                                  struct regmap *syscon, void __iomem *mem)
 {
        struct device_node *clocks;
+       struct clk_iomap *io;
 
        /* get clocks for this parent */
        clocks = of_get_child_by_name(parent, "clocks");
        if (!clocks) {
                pr_err("%s missing 'clocks' child node.\n", parent->name);
-               return;
+               return -EINVAL;
        }
 
        /* add clocks node info */
        clocks_node_ptr[index] = clocks;
+
+       io = kzalloc(sizeof(*io), GFP_KERNEL);
+       if (!io)
+               return -ENOMEM;
+
+       io->regmap = syscon;
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
+
+       return 0;
+}
+
+/**
+ * omap2_clk_legacy_provider_init - initialize a legacy clock provider
+ * @index: index for the clock provider
+ * @mem: iomem pointer for the clock provider memory area
+ *
+ * Initializes a legacy clock provider memory mapping.
+ */
+void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
+{
+       struct clk_iomap *io;
+
+       io = memblock_virt_alloc(sizeof(*io), 0);
+
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
 }
 
 /**
@@ -244,11 +339,11 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
        if (!IS_ERR(clk)) {
                setup->clk = clk;
                if (setup->clkdm_name) {
-                       if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+                       clk_hw = __clk_get_hw(clk);
+                       if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
                                pr_warn("can't setup clkdm for basic clk %s\n",
                                        setup->name);
                        } else {
-                               clk_hw = __clk_get_hw(clk);
                                to_clk_hw_omap(clk_hw)->clkdm_name =
                                        setup->clkdm_name;
                                omap2_init_clk_clkdm(clk_hw);
@@ -311,3 +406,50 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
        return 0;
 }
 #endif
+
+/**
+ * ti_clk_setup_features - setup clock features flags
+ * @features: features definition to use
+ *
+ * Initializes the clock driver features flags based on platform
+ * provided data. No return value.
+ */
+void __init ti_clk_setup_features(struct ti_clk_features *features)
+{
+       memcpy(&ti_clk_features, features, sizeof(*features));
+}
+
+/**
+ * ti_clk_get_features - get clock driver features flags
+ *
+ * Get TI clock driver features description. Returns a pointer
+ * to the current feature setup.
+ */
+const struct ti_clk_features *ti_clk_get_features(void)
+{
+       return &ti_clk_features;
+}
+
+/**
+ * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
+ * @clk_names: ptr to an array of strings of clock names to enable
+ * @num_clocks: number of clock names in @clk_names
+ *
+ * Prepare and enable a list of clocks, named by @clk_names.  No
+ * return value. XXX Deprecated; only needed until these clocks are
+ * properly claimed and enabled by the drivers or core code that uses
+ * them.  XXX What code disables & calls clk_put on these clocks?
+ */
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
+{
+       struct clk *init_clk;
+       int i;
+
+       for (i = 0; i < num_clocks; i++) {
+               init_clk = clk_get(NULL, clk_names[i]);
+               if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
+                        clk_names[i]))
+                       continue;
+               clk_prepare_enable(init_clk);
+       }
+}
diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c
new file mode 100644 (file)
index 0000000..90d7d8a
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Default clock type
+ *
+ * Copyright (C) 2005-2008, 2015 Texas Instruments, Inc.
+ * Copyright (C) 2004-2010 Nokia Corporation
+ *
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
+ * Tero Kristo <t-kristo@ti.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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/clk/ti.h>
+#include <linux/delay.h>
+
+#include "clock.h"
+
+/*
+ * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
+ * for a module to indicate that it is no longer in idle
+ */
+#define MAX_MODULE_ENABLE_WAIT         100000
+
+/*
+ * CM module register offsets, used for calculating the companion
+ * register addresses.
+ */
+#define CM_FCLKEN                      0x0000
+#define CM_ICLKEN                      0x0010
+
+/**
+ * _wait_idlest_generic - wait for a module to leave the idle state
+ * @clk: module clock to wait for (needed for register offsets)
+ * @reg: virtual address of module IDLEST register
+ * @mask: value to mask against to determine if the module is active
+ * @idlest: idle state indicator (0 or 1) for the clock
+ * @name: name of the clock (for printk)
+ *
+ * Wait for a module to leave idle, where its idle-status register is
+ * not inside the CM module.  Returns 1 if the module left idle
+ * promptly, or 0 if the module did not leave idle before the timeout
+ * elapsed.  XXX Deprecated - should be moved into drivers for the
+ * individual IP block that the IDLEST register exists in.
+ */
+static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
+                               u32 mask, u8 idlest, const char *name)
+{
+       int i = 0, ena = 0;
+
+       ena = (idlest) ? 0 : mask;
+
+       /* Wait until module enters enabled state */
+       for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
+               if ((ti_clk_ll_ops->clk_readl(reg) & mask) == ena)
+                       break;
+               udelay(1);
+       }
+
+       if (i < MAX_MODULE_ENABLE_WAIT)
+               pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
+                        name, i);
+       else
+               pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
+                      name, MAX_MODULE_ENABLE_WAIT);
+
+       return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
+}
+
+/**
+ * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
+ * @clk: struct clk * belonging to the module
+ *
+ * If the necessary clocks for the OMAP hardware IP block that
+ * corresponds to clock @clk are enabled, then wait for the module to
+ * indicate readiness (i.e., to leave IDLE).  This code does not
+ * belong in the clock code and will be moved in the medium term to
+ * module-dependent code.  No return value.
+ */
+static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
+{
+       void __iomem *companion_reg, *idlest_reg;
+       u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
+       s16 prcm_mod;
+       int r;
+
+       /* Not all modules have multiple clocks that their IDLEST depends on */
+       if (clk->ops->find_companion) {
+               clk->ops->find_companion(clk, &companion_reg, &other_bit);
+               if (!(ti_clk_ll_ops->clk_readl(companion_reg) &
+                     (1 << other_bit)))
+                       return;
+       }
+
+       clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
+       r = ti_clk_ll_ops->cm_split_idlest_reg(idlest_reg, &prcm_mod,
+                                              &idlest_reg_id);
+       if (r) {
+               /* IDLEST register not in the CM module */
+               _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
+                                    idlest_val, clk_hw_get_name(&clk->hw));
+       } else {
+               ti_clk_ll_ops->cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
+                                                   idlest_bit);
+       }
+}
+
+/**
+ * omap2_clk_dflt_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
+ *
+ * Note: We don't need special code here for INVERT_ENABLE for the
+ * time being since INVERT_ENABLE only applies to clocks enabled by
+ * CM_CLKEN_PLL
+ *
+ * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
+ * just a matter of XORing the bits.
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as MAILBOXES) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
+ */
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+                                  void __iomem **other_reg, u8 *other_bit)
+{
+       u32 r;
+
+       /*
+        * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
+        * it's just a matter of XORing the bits.
+        */
+       r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
+
+       *other_reg = (__force void __iomem *)r;
+       *other_bit = clk->enable_bit;
+}
+
+/**
+ * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
+ * @clk: struct clk * to find IDLEST info for
+ * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
+ * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
+ * @idlest_val: u8 * to return the idle status indicator
+ *
+ * Return the CM_IDLEST register address and bit shift corresponding
+ * to the module that "owns" this clock.  This default code assumes
+ * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
+ * the IDLEST register address ID corresponds to the CM_*CLKEN
+ * register address ID (e.g., that CM_FCLKEN2 corresponds to
+ * CM_IDLEST2).  This is not true for all modules.  No return value.
+ */
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+                               void __iomem **idlest_reg, u8 *idlest_bit,
+                               u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = clk->enable_bit;
+
+       /*
+        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+        * 34xx reverses this, just to keep us on our toes
+        * AM35xx uses both, depending on the module.
+        */
+       *idlest_val = ti_clk_get_features()->cm_idlest_val;
+}
+
+/**
+ * omap2_dflt_clk_enable - enable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to enable
+ *
+ * Enable the clock @hw in the hardware.  We first call into the OMAP
+ * clockdomain code to "enable" the corresponding clockdomain if this
+ * is the first enabled user of the clockdomain.  Then program the
+ * hardware to enable the clock.  Then wait for the IP block that uses
+ * this clock to leave idle (if applicable).  Returns the error value
+ * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
+ * if @hw has a null clock enable_reg, or zero upon success.
+ */
+int omap2_dflt_clk_enable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+       u32 v;
+       int ret = 0;
+       bool clkdm_control;
+
+       if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL)
+               clkdm_control = false;
+       else
+               clkdm_control = true;
+
+       clk = to_clk_hw_omap(hw);
+
+       if (clkdm_control && clk->clkdm) {
+               ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
+               if (ret) {
+                       WARN(1,
+                            "%s: could not enable %s's clockdomain %s: %d\n",
+                            __func__, clk_hw_get_name(hw),
+                            clk->clkdm_name, ret);
+                       return ret;
+               }
+       }
+
+       if (unlikely(!clk->enable_reg)) {
+               pr_err("%s: %s missing enable_reg\n", __func__,
+                      clk_hw_get_name(hw));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* FIXME should not have INVERT_ENABLE bit here */
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       if (clk->flags & INVERT_ENABLE)
+               v &= ~(1 << clk->enable_bit);
+       else
+               v |= (1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg); /* OCP barrier */
+
+       if (clk->ops && clk->ops->find_idlest)
+               _omap2_module_wait_ready(clk);
+
+       return 0;
+
+err:
+       if (clkdm_control && clk->clkdm)
+               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+       return ret;
+}
+
+/**
+ * omap2_dflt_clk_disable - disable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to disable
+ *
+ * Disable the clock @hw in the hardware, and call into the OMAP
+ * clockdomain code to "disable" the corresponding clockdomain if all
+ * clocks/hwmods in that clockdomain are now disabled.  No return
+ * value.
+ */
+void omap2_dflt_clk_disable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+       u32 v;
+
+       clk = to_clk_hw_omap(hw);
+       if (!clk->enable_reg) {
+               /*
+                * 'independent' here refers to a clock which is not
+                * controlled by its parent.
+                */
+               pr_err("%s: independent clock %s has no enable_reg\n",
+                      __func__, clk_hw_get_name(hw));
+               return;
+       }
+
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       if (clk->flags & INVERT_ENABLE)
+               v |= (1 << clk->enable_bit);
+       else
+               v &= ~(1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
+       /* No OCP barrier needed here since it is a disable operation */
+
+       if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) &&
+           clk->clkdm)
+               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
+/**
+ * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
+ * @hw: struct clk_hw * to check
+ *
+ * Return 1 if the clock represented by @hw is enabled in the
+ * hardware, or 0 otherwise.  Intended for use in the struct
+ * clk_ops.is_enabled function pointer.
+ */
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       u32 v;
+
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+       if (clk->flags & INVERT_ENABLE)
+               v ^= BIT(clk->enable_bit);
+
+       v &= BIT(clk->enable_bit);
+
+       return v ? 1 : 0;
+}
+
+const struct clk_hw_omap_ops clkhwops_wait = {
+       .find_idlest    = omap2_clk_dflt_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
similarity index 92%
rename from arch/arm/mach-omap2/clkt_dpll.c
rename to drivers/clk/ti/clkt_dpll.c
index f251a14cbf16a05b1cfd1f3157a83ae0053d8203..9023ca9caf84dde6b02c7ffacdded5244b16795d 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/clk/ti.h>
 
 #include <asm/div64.h>
 
@@ -74,14 +76,14 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
        dd = clk->dpll_data;
 
        /* DPLL divider must result in a valid jitter correction val */
-       fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
+       fint = clk_hw_get_rate(clk_hw_get_parent(&clk->hw)) / n;
 
        if (dd->flags & DPLL_J_TYPE) {
                fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
                fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
        } else {
-               fint_min = ti_clk_features.fint_min;
-               fint_max = ti_clk_features.fint_max;
+               fint_min = ti_clk_get_features()->fint_min;
+               fint_max = ti_clk_get_features()->fint_max;
        }
 
        if (!fint_min || !fint_max) {
@@ -89,18 +91,18 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
                return DPLL_FINT_INVALID;
        }
 
-       if (fint < ti_clk_features.fint_min) {
+       if (fint < ti_clk_get_features()->fint_min) {
                pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n",
                         n);
                dd->max_divider = n;
                ret = DPLL_FINT_UNDERFLOW;
-       } else if (fint > ti_clk_features.fint_max) {
+       } else if (fint > ti_clk_get_features()->fint_max) {
                pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
                         n);
                dd->min_divider = n;
                ret = DPLL_FINT_INVALID;
-       } else if (fint > ti_clk_features.fint_band1_max &&
-                  fint < ti_clk_features.fint_band2_min) {
+       } else if (fint > ti_clk_get_features()->fint_band1_max &&
+                  fint < ti_clk_get_features()->fint_band2_min) {
                pr_debug("rejecting n=%d due to Fint failure\n", n);
                ret = DPLL_FINT_INVALID;
        }
@@ -183,7 +185,7 @@ static int _omap2_dpll_is_in_bypass(u32 v)
 {
        u8 mask, val;
 
-       mask = ti_clk_features.dpll_bypass_vals;
+       mask = ti_clk_get_features()->dpll_bypass_vals;
 
        /*
         * Each set bit in the mask corresponds to a bypass value equal
@@ -211,7 +213,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
        if (!dd)
                return -EINVAL;
 
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
@@ -247,20 +249,20 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
                return 0;
 
        /* Return bypass rate if DPLL is bypassed */
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
        if (_omap2_dpll_is_in_bypass(v))
-               return __clk_get_rate(dd->clk_bypass);
+               return clk_get_rate(dd->clk_bypass);
 
-       v = omap2_clk_readl(clk, dd->mult_div1_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
        dpll_mult = v & dd->mult_mask;
        dpll_mult >>= __ffs(dd->mult_mask);
        dpll_div = v & dd->div1_mask;
        dpll_div >>= __ffs(dd->div1_mask);
 
-       dpll_clk = (long long) __clk_get_rate(dd->clk_ref) * dpll_mult;
+       dpll_clk = (long long)clk_get_rate(dd->clk_ref) * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
 
        return dpll_clk;
@@ -281,7 +283,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
  * be rounded, or the rounded rate upon success.
  */
 long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-               unsigned long *parent_rate)
+                          unsigned long *parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        int m, n, r, scaled_max_m;
@@ -299,8 +301,8 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 
        dd = clk->dpll_data;
 
-       ref_rate = __clk_get_rate(dd->clk_ref);
-       clk_name = __clk_get_name(hw->clk);
+       ref_rate = clk_get_rate(dd->clk_ref);
+       clk_name = clk_hw_get_name(hw);
        pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n",
                 clk_name, target_rate);
 
@@ -310,7 +312,6 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
        dd->last_rounded_rate = 0;
 
        for (n = dd->min_divider; n <= dd->max_divider; n++) {
-
                /* Is the (input clk, divider) pair valid for the DPLL? */
                r = _dpll_test_fint(clk, n);
                if (r == DPLL_FINT_UNDERFLOW)
@@ -367,4 +368,3 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 
        return dd->last_rounded_rate;
 }
-
diff --git a/drivers/clk/ti/clkt_iclk.c b/drivers/clk/ti/clkt_iclk.c
new file mode 100644 (file)
index 0000000..38c3690
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * OMAP2/3 interface clock control
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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.
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/clk/ti.h>
+
+#include "clock.h"
+
+/* Register offsets */
+#define OMAP24XX_CM_FCLKEN2            0x04
+#define CM_AUTOIDLE                    0x30
+#define CM_ICLKEN                      0x10
+#define CM_IDLEST                      0x20
+
+#define OMAP24XX_CM_IDLEST_VAL         0
+
+/* Private functions */
+
+/* XXX */
+void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
+{
+       u32 v;
+       void __iomem *r;
+
+       r = (__force void __iomem *)
+               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+       v = ti_clk_ll_ops->clk_readl(r);
+       v |= (1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, r);
+}
+
+/* XXX */
+void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
+{
+       u32 v;
+       void __iomem *r;
+
+       r = (__force void __iomem *)
+               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+       v = ti_clk_ll_ops->clk_readl(r);
+       v &= ~(1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, r);
+}
+
+/**
+ * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
+ * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
+ * passes back the correct CM_IDLEST register address for I2CHS
+ * modules.  No return value.
+ */
+static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
+                                          void __iomem **idlest_reg,
+                                          u8 *idlest_bit,
+                                          u8 *idlest_val)
+{
+       u32 r;
+
+       r = ((__force u32)clk->enable_reg ^ (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST));
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = clk->enable_bit;
+       *idlest_val = OMAP24XX_CM_IDLEST_VAL;
+}
+
+/* Public data */
+
+const struct clk_hw_omap_ops clkhwops_iclk = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+};
+
+const struct clk_hw_omap_ops clkhwops_iclk_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap2_clk_dflt_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/* 2430 I2CHS has non-standard IDLEST register */
+const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
+       .find_idlest    = omap2430_clk_i2chs_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
index 404158d2d7f8800757cb95255525aa4fe87ee501..90f3f472ae1c4c70e537c69a7a58e2d1168abddd 100644 (file)
@@ -154,6 +154,35 @@ struct ti_clk_dpll {
        u8 recal_st_bit;
 };
 
+/* Composite clock component types */
+enum {
+       CLK_COMPONENT_TYPE_GATE = 0,
+       CLK_COMPONENT_TYPE_DIVIDER,
+       CLK_COMPONENT_TYPE_MUX,
+       CLK_COMPONENT_TYPE_MAX,
+};
+
+/**
+ * struct ti_dt_clk - OMAP DT clock alias declarations
+ * @lk: clock lookup definition
+ * @node_name: clock DT node to map to
+ */
+struct ti_dt_clk {
+       struct clk_lookup               lk;
+       char                            *node_name;
+};
+
+#define DT_CLK(dev, con, name)         \
+       {                               \
+               .lk = {                 \
+                       .dev_id = dev,  \
+                       .con_id = con,  \
+               },                      \
+               .node_name = name,      \
+       }
+
+typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
+
 struct clk *ti_clk_register_gate(struct ti_clk *setup);
 struct clk *ti_clk_register_interface(struct ti_clk *setup);
 struct clk *ti_clk_register_mux(struct ti_clk *setup);
@@ -169,4 +198,80 @@ void ti_clk_patch_legacy_clks(struct ti_clk **patch);
 struct clk *ti_clk_register_clk(struct ti_clk *setup);
 int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
 
+void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
+void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
+                     ti_of_clk_init_cb_t func);
+int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
+
+void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw);
+int of_ti_clk_autoidle_setup(struct device_node *node);
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
+
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_iclk;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
+
+extern const struct clk_ops ti_clk_divider_ops;
+extern const struct clk_ops ti_clk_mux_ops;
+
+int omap2_clkops_enable_clkdm(struct clk_hw *hw);
+void omap2_clkops_disable_clkdm(struct clk_hw *hw);
+
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+                                  void __iomem **other_reg,
+                                  u8 *other_bit);
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+                               void __iomem **idlest_reg,
+                               u8 *idlest_bit, u8 *idlest_val);
+
+void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
+void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
+
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+int omap3_noncore_dpll_enable(struct clk_hw *hw);
+void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate);
+int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
+                                          unsigned long rate,
+                                          unsigned long parent_rate,
+                                          u8 index);
+int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req);
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+                          unsigned long *parent_rate);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+                                   unsigned long parent_rate);
+
+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);
+void omap3_clk_lock_dpll5(void);
+
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+                                        unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+                                   unsigned long target_rate,
+                                   unsigned long *parent_rate);
+int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
+                                      struct clk_rate_request *req);
+
+extern struct ti_clk_ll_ops *ti_clk_ll_ops;
+
 #endif
index b82ef07f340341052fa8a92ddacd8f65845ba843..b9bc3b8df659d853ba0a51a631f98d9a0f1c33c1 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
+/**
+ * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being enabled
+ *
+ * Increment the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 1, the clockdomain will be "enabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_enable() as
+ * their enable function pointer.  Passes along the return value of
+ * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
+ * clockdomain, or 0 if clock framework-based clockdomain control is
+ * not implemented.
+ */
+int omap2_clkops_enable_clkdm(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+       int ret = 0;
+
+       clk = to_clk_hw_omap(hw);
+
+       if (unlikely(!clk->clkdm)) {
+               pr_err("%s: %s: no clkdm set ?!\n", __func__,
+                      clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       if (unlikely(clk->enable_reg))
+               pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
+                      clk_hw_get_name(hw));
+
+       if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
+               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+                      __func__, clk_hw_get_name(hw));
+               return 0;
+       }
+
+       ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
+       WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
+            __func__, clk_hw_get_name(hw), clk->clkdm_name, ret);
+
+       return ret;
+}
+
+/**
+ * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being disabled
+ *
+ * Decrement the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 0, the clockdomain will be "disabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
+ * disable function pointer.  No return value.
+ */
+void omap2_clkops_disable_clkdm(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+
+       clk = to_clk_hw_omap(hw);
+
+       if (unlikely(!clk->clkdm)) {
+               pr_err("%s: %s: no clkdm set ?!\n", __func__,
+                      clk_hw_get_name(hw));
+               return;
+       }
+
+       if (unlikely(clk->enable_reg))
+               pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
+                      clk_hw_get_name(hw));
+
+       if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
+               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+                      __func__, clk_hw_get_name(hw));
+               return;
+       }
+
+       ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
 static void __init of_ti_clockdomain_setup(struct device_node *node)
 {
        struct clk *clk;
@@ -41,12 +120,12 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
                               __func__, node->full_name, i, PTR_ERR(clk));
                        continue;
                }
-               if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+               clk_hw = __clk_get_hw(clk);
+               if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
                        pr_warn("can't setup clkdm for basic clk %s\n",
                                __clk_get_name(clk));
                        continue;
                }
-               clk_hw = __clk_get_hw(clk);
                to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name;
                omap2_init_clk_clkdm(clk_hw);
        }
index 96f83cedb4b3ca6426d1351bd5db6bbcc292fb90..dbef218fe5ecd3ad64319700ac1b142d9c42a89c 100644 (file)
@@ -276,7 +276,6 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
        int num_parents;
        const char **parent_names;
        struct component_clk *clk;
-       int i;
 
        num_parents = of_clk_get_parent_count(node);
 
@@ -289,8 +288,7 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
        if (!parent_names)
                return -ENOMEM;
 
-       for (i = 0; i < num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, num_parents);
 
        clk = kzalloc(sizeof(*clk), GFP_KERNEL);
        if (!clk) {
index ff5f117950a933b354c3bf5ba339e3e1a5b2dcd3..5b1726829e6df038de9e8502471cbb6b70414fd5 100644 (file)
@@ -109,7 +109,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
        if (!div) {
                WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
                     "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
-                    __clk_get_name(hw->clk));
+                    clk_hw_get_name(hw));
                return parent_rate;
        }
 
@@ -155,7 +155,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        maxdiv = _get_maxdiv(divider);
 
-       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
                parent_rate = *best_parent_rate;
                bestdiv = DIV_ROUND_UP(parent_rate, rate);
                bestdiv = bestdiv == 0 ? 1 : bestdiv;
@@ -181,7 +181,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
                        *best_parent_rate = parent_rate_saved;
                        return i;
                }
-               parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+               parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
                                MULT_ROUND_UP(rate, i));
                now = DIV_ROUND_UP(parent_rate, i);
                if (now <= rate && now > best) {
@@ -194,7 +194,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
        if (!bestdiv) {
                bestdiv = _get_maxdiv(divider);
                *best_parent_rate =
-                       __clk_round_rate(__clk_get_parent(hw->clk), 1);
+                       clk_hw_round_rate(clk_hw_get_parent(hw), 1);
        }
 
        return bestdiv;
index 2aacf7a3bcaeb137e4e7bb973cea2874ff1aa6a7..5519b386edc02f74992620d99d8d32921523b5b0 100644 (file)
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -162,7 +163,7 @@ static void __init _register_dpll(struct clk_hw *hw,
        clk = clk_register(NULL, &clk_hw->hw);
 
        if (!IS_ERR(clk)) {
-               omap2_init_clk_hw_omap_clocks(clk);
+               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(clk_hw->hw.init->parent_names);
                kfree(clk_hw->hw.init);
@@ -319,7 +320,7 @@ static void _register_dpll_x2(struct device_node *node,
        if (IS_ERR(clk)) {
                kfree(clk_hw);
        } else {
-               omap2_init_clk_hw_omap_clocks(clk);
+               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
        }
 }
@@ -341,7 +342,6 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        struct clk_init_data *init = NULL;
        const char **parent_names = NULL;
        struct dpll_data *dd = NULL;
-       int i;
        u8 dpll_mode = 0;
 
        dd = kzalloc(sizeof(*dd), GFP_KERNEL);
@@ -370,8 +370,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        if (!parent_names)
                goto cleanup;
 
-       for (i = 0; i < init->num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, init->num_parents);
 
        init->parent_names = parent_names;
 
similarity index 79%
rename from arch/arm/mach-omap2/dpll3xxx.c
rename to drivers/clk/ti/dpll3xxx.c
index 44e57ec225d4401c1e2a81fcbfd929e499e65d58..f4dec00fb684f7743b0fcda3df6f245ac46b7b43 100644 (file)
@@ -27,8 +27,8 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
+#include <linux/clk/ti.h>
 
-#include "clockdomain.h"
 #include "clock.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 
 #define MAX_DPLL_WAIT_TRIES            1000000
 
+#define OMAP3XXX_EN_DPLL_LOCKED                0x7
+
+/* Forward declarations */
+static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
+static void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
+static void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
+
 /* Private functions */
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -47,10 +54,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
 
        dd = clk->dpll_data;
 
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        v &= ~dd->enable_mask;
        v |= clken_bits << __ffs(dd->enable_mask);
-       omap2_clk_writel(v, clk, dd->control_reg);
+       ti_clk_ll_ops->clk_writel(v, dd->control_reg);
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -62,18 +69,18 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
        const char *clk_name;
 
        dd = clk->dpll_data;
-       clk_name = __clk_get_name(clk->hw.clk);
+       clk_name = clk_hw_get_name(&clk->hw);
 
        state <<= __ffs(dd->idlest_mask);
 
-       while (((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask)
+       while (((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask)
                != state) && i < MAX_DPLL_WAIT_TRIES) {
                i++;
                udelay(1);
        }
 
        if (i == MAX_DPLL_WAIT_TRIES) {
-               printk(KERN_ERR "clock: %s failed transition to '%s'\n",
+               pr_err("clock: %s failed transition to '%s'\n",
                       clk_name, (state) ? "locked" : "bypassed");
        } else {
                pr_debug("clock: %s transition to '%s' in %d loops\n",
@@ -91,7 +98,7 @@ static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
        unsigned long fint;
        u16 f = 0;
 
-       fint = __clk_get_rate(clk->dpll_data->clk_ref) / n;
+       fint = clk_get_rate(clk->dpll_data->clk_ref) / n;
 
        pr_debug("clock: fint is %lu\n", fint);
 
@@ -138,13 +145,14 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
        u8 state = 1;
        int r = 0;
 
-       pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
+       pr_debug("clock: locking DPLL %s\n", clk_hw_get_name(&clk->hw));
 
        dd = clk->dpll_data;
        state <<= __ffs(dd->idlest_mask);
 
        /* Check if already locked */
-       if ((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) == state)
+       if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) ==
+           state)
                goto done;
 
        ai = omap3_dpll_autoidle_read(clk);
@@ -185,7 +193,7 @@ static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
                return -EINVAL;
 
        pr_debug("clock: configuring DPLL %s for low-power bypass\n",
-                __clk_get_name(clk->hw.clk));
+                clk_hw_get_name(&clk->hw));
 
        ai = omap3_dpll_autoidle_read(clk);
 
@@ -215,7 +223,7 @@ static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
        if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
                return -EINVAL;
 
-       pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk));
+       pr_debug("clock: stopping DPLL %s\n", clk_hw_get_name(&clk->hw));
 
        ai = omap3_dpll_autoidle_read(clk);
 
@@ -243,7 +251,7 @@ static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
 {
        unsigned long fint, clkinp; /* watch out for overflow */
 
-       clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
+       clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
        fint = (clkinp / n) * m;
 
        if (fint < 1000000000)
@@ -269,7 +277,7 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
        unsigned long clkinp, sd; /* watch out for overflow */
        int mod1, mod2;
 
-       clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
+       clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
 
        /*
         * target sigma-delta to near 250MHz
@@ -307,15 +315,15 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
         * Set jitter correction. Jitter correction applicable for OMAP343X
         * only since freqsel field is no longer present on other devices.
         */
-       if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
-               v = omap2_clk_readl(clk, dd->control_reg);
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
+               v = ti_clk_ll_ops->clk_readl(dd->control_reg);
                v &= ~dd->freqsel_mask;
                v |= freqsel << __ffs(dd->freqsel_mask);
-               omap2_clk_writel(v, clk, dd->control_reg);
+               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
        }
 
        /* Set DPLL multiplier, divider */
-       v = omap2_clk_readl(clk, dd->mult_div1_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
 
        /* Handle Duty Cycle Correction */
        if (dd->dcc_mask) {
@@ -342,11 +350,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                v |= sd_div << __ffs(dd->sddiv_mask);
        }
 
-       omap2_clk_writel(v, clk, dd->mult_div1_reg);
+       ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg);
 
        /* Set 4X multiplier and low-power mode */
        if (dd->m4xen_mask || dd->lpmode_mask) {
-               v = omap2_clk_readl(clk, dd->control_reg);
+               v = ti_clk_ll_ops->clk_readl(dd->control_reg);
 
                if (dd->m4xen_mask) {
                        if (dd->last_rounded_m4xen)
@@ -362,7 +370,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                                v &= ~dd->lpmode_mask;
                }
 
-               omap2_clk_writel(v, clk, dd->control_reg);
+               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
        }
 
        /* We let the clock framework set the other output dividers later */
@@ -417,19 +425,19 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
                return -EINVAL;
 
        if (clk->clkdm) {
-               r = clkdm_clk_enable(clk->clkdm, hw->clk);
+               r = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
                if (r) {
                        WARN(1,
                             "%s: could not enable %s's clockdomain %s: %d\n",
-                            __func__, __clk_get_name(hw->clk),
-                            clk->clkdm->name, r);
+                            __func__, clk_hw_get_name(hw),
+                            clk->clkdm_name, r);
                        return r;
                }
        }
 
-       parent = __clk_get_hw(__clk_get_parent(hw->clk));
+       parent = clk_hw_get_parent(hw);
 
-       if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
+       if (clk_hw_get_rate(hw) == clk_get_rate(dd->clk_bypass)) {
                WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
@@ -453,52 +461,46 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
 
        _omap3_noncore_dpll_stop(clk);
        if (clk->clkdm)
-               clkdm_clk_disable(clk->clkdm, hw->clk);
+               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
 }
 
-
 /* Non-CORE DPLL rate set code */
 
 /**
  * omap3_noncore_dpll_determine_rate - determine rate for a DPLL
  * @hw: pointer to the clock to determine rate for
- * @rate: target rate for the DPLL
- * @best_parent_rate: pointer for returning best parent rate
- * @best_parent_clk: pointer for returning best parent clock
+ * @req: target rate request
  *
  * Determines which DPLL mode to use for reaching a desired target rate.
  * Checks whether the DPLL shall be in bypass or locked mode, and if
  * locked, calculates the M,N values for the DPLL via round-rate.
- * Returns a positive clock rate with success, negative error value
- * in failure.
+ * Returns a 0 on success, negative error value in failure.
  */
-long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long min_rate,
-                                      unsigned long max_rate,
-                                      unsigned long *best_parent_rate,
-                                      struct clk_hw **best_parent_clk)
+int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        struct dpll_data *dd;
 
-       if (!hw || !rate)
+       if (!req->rate)
                return -EINVAL;
 
        dd = clk->dpll_data;
        if (!dd)
                return -EINVAL;
 
-       if (__clk_get_rate(dd->clk_bypass) == rate &&
+       if (clk_get_rate(dd->clk_bypass) == req->rate &&
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               *best_parent_clk = __clk_get_hw(dd->clk_bypass);
+               req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
        } else {
-               rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
-               *best_parent_clk = __clk_get_hw(dd->clk_ref);
+               req->rate = omap2_dpll_round_rate(hw, req->rate,
+                                         &req->best_parent_rate);
+               req->best_parent_hw = __clk_get_hw(dd->clk_ref);
        }
 
-       *best_parent_rate = rate;
+       req->best_parent_rate = req->rate;
 
-       return rate;
+       return 0;
 }
 
 /**
@@ -551,21 +553,20 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!dd)
                return -EINVAL;
 
-       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
-           __clk_get_hw(dd->clk_ref))
+       if (clk_hw_get_parent(hw) != __clk_get_hw(dd->clk_ref))
                return -EINVAL;
 
        if (dd->last_rounded_rate == 0)
                return -EINVAL;
 
        /* Freqsel is available only on OMAP343X devices */
-       if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
                freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
                WARN_ON(!freqsel);
        }
 
        pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
-                __clk_get_name(hw->clk), rate);
+                clk_hw_get_name(hw), rate);
 
        ret = omap3_noncore_dpll_program(clk, freqsel);
 
@@ -618,7 +619,7 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
  * -EINVAL if passed a null pointer or if the struct clk does not
  * appear to refer to a DPLL.
  */
-u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
+static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
 {
        const struct dpll_data *dd;
        u32 v;
@@ -631,7 +632,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
        if (!dd->autoidle_reg)
                return -EINVAL;
 
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
        v &= dd->autoidle_mask;
        v >>= __ffs(dd->autoidle_mask);
 
@@ -647,7 +648,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
  * OMAP3430.  The DPLL will enter low-power stop when its downstream
  * clocks are gated.  No return value.
  */
-void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
+static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
 {
        const struct dpll_data *dd;
        u32 v;
@@ -665,11 +666,10 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
         * by writing 0x5 instead of 0x1.  Add some mechanism to
         * optionally enter this mode.
         */
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
-       omap2_clk_writel(v, clk, dd->autoidle_reg);
-
+       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
 }
 
 /**
@@ -678,7 +678,7 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
  *
  * Disable DPLL automatic idle control.  No return value.
  */
-void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
+static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 {
        const struct dpll_data *dd;
        u32 v;
@@ -691,11 +691,10 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
        if (!dd->autoidle_reg)
                return;
 
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
-       omap2_clk_writel(v, clk, dd->autoidle_reg);
-
+       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
 }
 
 /* Clock control for DPLL outputs */
@@ -704,14 +703,12 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
 {
        struct clk_hw_omap *pclk = NULL;
-       struct clk *parent;
 
        /* Walk up the parents of clk, looking for a DPLL */
        do {
                do {
-                       parent = __clk_get_parent(hw->clk);
-                       hw = __clk_get_hw(parent);
-               } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+                       hw = clk_hw_get_parent(hw);
+               } while (hw && (clk_hw_get_flags(hw) & CLK_IS_BASIC));
                if (!hw)
                        break;
                pclk = to_clk_hw_omap(hw);
@@ -753,7 +750,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 
        WARN_ON(!dd->enable_mask);
 
-       v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg) & dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
        if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
                rate = parent_rate;
@@ -762,57 +759,59 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
        return rate;
 }
 
-int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long parent_rate)
-{
-       return 0;
-}
+/* OMAP3/4 non-CORE DPLL clkops */
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
+       .allow_idle     = omap3_dpll_allow_idle,
+       .deny_idle      = omap3_dpll_deny_idle,
+};
 
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *prate)
+/**
+ * omap3_dpll4_set_rate - set rate for omap3 per-dpll
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Check if the current SoC supports the per-dpll reprogram operation
+ * or not, and then do the rate change if supported. Returns -EINVAL
+ * if not supported, 0 for success, and potential error codes from the
+ * clock rate change.
+ */
+int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
+                        unsigned long parent_rate)
 {
-       const struct dpll_data *dd;
-       u32 v;
-       struct clk_hw_omap *pclk = NULL;
-
-       if (!*prate)
-               return 0;
-
-       pclk = omap3_find_clkoutx2_dpll(hw);
-
-       if (!pclk)
-               return 0;
-
-       dd = pclk->dpll_data;
-
-       /* TYPE J does not have a clkoutx2 */
-       if (dd->flags & DPLL_J_TYPE) {
-               *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
-               return *prate;
+       /*
+        * According to the 12-5 CDP code from TI, "Limitation 2.5"
+        * on 3430ES1 prevents us from changing DPLL multipliers or dividers
+        * on DPLL4.
+        */
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
+               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
+               return -EINVAL;
        }
 
-       WARN_ON(!dd->enable_mask);
-
-       v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
-       v >>= __ffs(dd->enable_mask);
-
-       /* If in bypass, the rate is fixed to the bypass rate*/
-       if (v != OMAP3XXX_EN_DPLL_LOCKED)
-               return *prate;
-
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
-               unsigned long best_parent;
+       return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
 
-               best_parent = (rate / 2);
-               *prate = __clk_round_rate(__clk_get_parent(hw->clk),
-                               best_parent);
+/**
+ * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ * @index: parent index, 0 - reference clock, 1 - bypass clock
+ *
+ * Check if the current SoC support the per-dpll reprogram operation
+ * or not, and then do the rate + parent change if supported. Returns
+ * -EINVAL if not supported, 0 for success, and potential error codes
+ * from the clock rate change.
+ */
+int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate, u8 index)
+{
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
+               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
+               return -EINVAL;
        }
 
-       return *prate * 2;
+       return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
+                                                     index);
 }
-
-/* OMAP3/4 non-CORE DPLL clkops */
-const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
-       .allow_idle     = omap3_dpll_allow_idle,
-       .deny_idle      = omap3_dpll_deny_idle,
-};
similarity index 79%
rename from arch/arm/mach-omap2/dpll44xx.c
rename to drivers/clk/ti/dpll44xx.c
index f231be05b9a638de8e52cfe03d78765433815764..660d7436ac243a89a2ac2573a8b67a019bac0301 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/clk/ti.h>
 
 #include "clock.h"
 
 /*
  * Bitfield declarations
  */
-#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK            (1 << 8)
-#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK          (1 << 10)
-#define OMAP4430_DPLL_REGM4XEN_MASK                    (1 << 11)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK            BIT(8)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK          BIT(10)
+#define OMAP4430_DPLL_REGM4XEN_MASK                    BIT(11)
 
 /* Static rate multiplier for OMAP4 REGM4XEN clocks */
 #define OMAP4430_REGM4XEN_MULT                         4
 
-void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
+static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
 {
        u32 v;
        u32 mask;
@@ -48,13 +49,13 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = omap2_clk_readl(clk, clk->clksel_reg);
+       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
        /* Clear the bit to allow gatectrl */
        v &= ~mask;
-       omap2_clk_writel(v, clk, clk->clksel_reg);
+       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
 }
 
-void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
+static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
 {
        u32 v;
        u32 mask;
@@ -66,10 +67,10 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = omap2_clk_readl(clk, clk->clksel_reg);
+       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
        /* Set the bit to deny gatectrl */
        v |= mask;
-       omap2_clk_writel(v, clk, clk->clksel_reg);
+       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
 }
 
 const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
@@ -93,7 +94,7 @@ static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
 {
        long fint, fout;
 
-       fint = __clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1);
+       fint = clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1);
        fout = fint * dd->last_rounded_m;
 
        if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX))
@@ -112,7 +113,7 @@ static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
  * upon success, or 0 upon error.
  */
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-                       unsigned long parent_rate)
+                                        unsigned long parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        u32 v;
@@ -127,7 +128,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
        rate = omap2_get_dpll_rate(clk);
 
        /* regm4xen adds a multiplier of 4 to DPLL calculations */
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        if (v & OMAP4430_DPLL_REGM4XEN_MASK)
                rate *= OMAP4430_REGM4XEN_MULT;
 
@@ -191,42 +192,36 @@ out:
 /**
  * omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
  * @hw: pointer to the clock to determine rate for
- * @rate: target rate for the DPLL
- * @best_parent_rate: pointer for returning best parent rate
- * @best_parent_clk: pointer for returning best parent clock
+ * @req: target rate request
  *
  * Determines which DPLL mode to use for reaching a desired rate.
  * Checks whether the DPLL shall be in bypass or locked mode, and if
  * locked, calculates the M,N values for the DPLL via round-rate.
- * Returns a positive clock rate with success, negative error value
- * in failure.
+ * Returns 0 on success and a negative error value otherwise.
  */
-long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
+                                      struct clk_rate_request *req)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        struct dpll_data *dd;
 
-       if (!hw || !rate)
+       if (!req->rate)
                return -EINVAL;
 
        dd = clk->dpll_data;
        if (!dd)
                return -EINVAL;
 
-       if (__clk_get_rate(dd->clk_bypass) == rate &&
+       if (clk_get_rate(dd->clk_bypass) == req->rate &&
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               *best_parent_clk = __clk_get_hw(dd->clk_bypass);
+               req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
        } else {
-               rate = omap4_dpll_regm4xen_round_rate(hw, rate,
-                                                     best_parent_rate);
-               *best_parent_clk = __clk_get_hw(dd->clk_ref);
+               req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate,
+                                               &req->best_parent_rate);
+               req->best_parent_hw = __clk_get_hw(dd->clk_ref);
        }
 
-       *best_parent_rate = rate;
+       req->best_parent_rate = req->rate;
 
-       return rate;
+       return 0;
 }
index 730aa62454a2454f6a5311adbd16bfff57e366d2..f4b2e9888bdf3c3079b0854b1c04c65a5201c5db 100644 (file)
@@ -9,6 +9,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -558,8 +559,7 @@ static void __init ti_fapll_setup(struct device_node *node)
                goto free;
        }
 
-       parent_name[0] = of_clk_get_parent_name(node, 0);
-       parent_name[1] = of_clk_get_parent_name(node, 1);
+       of_clk_parent_fill(node, parent_name, 2);
        init->parent_names = parent_name;
 
        fd->clk_ref = of_clk_get(node, 0);
index c2c8a287408c914a5b6a7e3c0be4a8594d1894c9..3cd40676890969b1853256d32061b8bfd29093a7 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
index 0c6fdfcd5f93a911178e334a87f371576bd18939..5429d35343639632a821548ef7837ccacd172a31 100644 (file)
@@ -62,7 +62,7 @@ static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
  * (Any other value different from the Read value) to the
  * corresponding CM_CLKSEL register will refresh the dividers.
  */
-static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
 {
        struct clk_divider *parent;
        struct clk_hw *parent_hw;
@@ -70,10 +70,10 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
        int ret;
 
        /* Clear PWRDN bit of HSDIVIDER */
-       ret = omap2_dflt_clk_enable(clk);
+       ret = omap2_dflt_clk_enable(hw);
 
        /* Parent is the x2 node, get parent of parent for the m2 div */
-       parent_hw = __clk_get_hw(__clk_get_parent(__clk_get_parent(clk->clk)));
+       parent_hw = clk_hw_get_parent(clk_hw_get_parent(hw));
        parent = to_clk_divider(parent_hw);
 
        /* Restore the dividers */
index c76230d8dd0464a073097cb70c4303cdf0e06056..e505e6f8228da6ada5ccb4beffd7aa0de78f1f1d 100644 (file)
@@ -63,7 +63,7 @@ static struct clk *_register_interface(struct device *dev, const char *name,
        if (IS_ERR(clk))
                kfree(clk_hw);
        else
-               omap2_init_clk_hw_omap_clocks(clk);
+               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
 
        return clk;
 }
index 5cdeed538b08a2eec168de48a94399c11af33472..69f08a1d047d8672a758e441fcd718bbf64bb946 100644 (file)
@@ -31,7 +31,7 @@
 static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
 {
        struct clk_mux *mux = to_clk_mux(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
        /*
@@ -190,7 +190,6 @@ static void of_mux_clk_setup(struct device_node *node)
        void __iomem *reg;
        int num_parents;
        const char **parent_names;
-       int i;
        u8 clk_mux_flags = 0;
        u32 mask = 0;
        u32 shift = 0;
@@ -205,8 +204,7 @@ static void of_mux_clk_setup(struct device_node *node)
        if (!parent_names)
                goto cleanup;
 
-       for (i = 0; i < num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, num_parents);
 
        reg = ti_clk_get_reg_addr(node, 0);
 
index 521483f0ba335f67a5bf7dc96e26adf3ca89fbcf..f3baef29859c46cd927d6bbf299a4cd5fe62e95d 100644 (file)
@@ -9,7 +9,6 @@ obj-y += clk-sysctrl.o
 
 # Clock definitions
 obj-y += u8500_of_clk.o
-obj-y += u8500_clk.o
 obj-y += u9540_clk.o
 obj-y += u8540_clk.o
 
index 3e5e05101302e569d5bda1a68451abc56b6bb4d0..222425d08ab6ac3faf05b6385d51c2df1b33713f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ab8500-sysctrl.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
index bf63c96acb1a2947ce7e274f2869b51ab8e95550..7f343821f4e4aef06b7261e60ad381c2bafee3af 100644 (file)
@@ -43,7 +43,7 @@ static void clk_prcmu_unprepare(struct clk_hw *hw)
        struct clk_prcmu *clk = to_clk_prcmu(hw);
        if (prcmu_request_clock(clk->cg_sel, false))
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
        else
                clk->is_prepared = 0;
 }
@@ -101,11 +101,11 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw)
 
        if (!clk->opp_requested) {
                err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
-                                               (char *)__clk_get_name(hw->clk),
+                                               (char *)clk_hw_get_name(hw),
                                                100);
                if (err) {
                        pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
-                               __func__, __clk_get_name(hw->clk));
+                               __func__, clk_hw_get_name(hw));
                        return err;
                }
                clk->opp_requested = 1;
@@ -114,7 +114,7 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw)
        err = prcmu_request_clock(clk->cg_sel, true);
        if (err) {
                prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
-                                       (char *)__clk_get_name(hw->clk));
+                                       (char *)clk_hw_get_name(hw));
                clk->opp_requested = 0;
                return err;
        }
@@ -129,13 +129,13 @@ static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
 
        if (prcmu_request_clock(clk->cg_sel, false)) {
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return;
        }
 
        if (clk->opp_requested) {
                prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
-                                       (char *)__clk_get_name(hw->clk));
+                                       (char *)clk_hw_get_name(hw));
                clk->opp_requested = 0;
        }
 
@@ -151,7 +151,7 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
                err = prcmu_request_ape_opp_100_voltage(true);
                if (err) {
                        pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
-                               __func__, __clk_get_name(hw->clk));
+                               __func__, clk_hw_get_name(hw));
                        return err;
                }
                clk->opp_requested = 1;
@@ -174,7 +174,7 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
 
        if (prcmu_request_clock(clk->cg_sel, false)) {
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return;
        }
 
index e364c9d4aa60e38b05085926297d3514da319048..266ddea630d22de9a9ae5a8f339edbfc81887946 100644 (file)
@@ -52,7 +52,7 @@ static void clk_sysctrl_unprepare(struct clk_hw *hw)
        struct clk_sysctrl *clk = to_clk_sysctrl(hw);
        if (ab8500_sysctrl_clear(clk->reg_sel[0], clk->reg_mask[0]))
                dev_err(clk->dev, "clk_sysctrl: %s fail to clear %s.\n",
-                       __func__, __clk_get_name(hw->clk));
+                       __func__, clk_hw_get_name(hw));
 }
 
 static unsigned long clk_sysctrl_recalc_rate(struct clk_hw *hw,
index a2bb92d85ee0a980ad458745f93c2ca00acf4266..b42485da704eaa495ab56d976668e063dd9f8dde 100644 (file)
 #ifndef __UX500_CLK_H
 #define __UX500_CLK_H
 
-#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/types.h>
 
+struct clk;
+
 struct clk *clk_reg_prcc_pclk(const char *name,
                              const char *parent_name,
                              resource_size_t phy_base,
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
deleted file mode 100644 (file)
index 4626b97..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Clock definitions for u8500 platform.
- *
- * Copyright (C) 2012 ST-Ericsson SA
- * Author: Ulf Hansson <ulf.hansson@linaro.org>
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include <linux/platform_data/clk-ux500.h>
-#include "clk.h"
-
-void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base)
-{
-       struct prcmu_fw_version *fw_version;
-       const char *sgaclk_parent = NULL;
-       struct clk *clk;
-
-       /* Clock sources */
-       clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "soc0_pll", NULL);
-
-       clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "soc1_pll", NULL);
-
-       clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "ddr_pll", NULL);
-
-       /* FIXME: Add sys, ulp and int clocks here. */
-
-       clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL",
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED,
-                               32768);
-       clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
-
-       /* PRCMU clocks */
-       fw_version = prcmu_get_fw_version();
-       if (fw_version != NULL) {
-               switch (fw_version->project) {
-               case PRCMU_FW_PROJECT_U8500_C2:
-               case PRCMU_FW_PROJECT_U8520:
-               case PRCMU_FW_PROJECT_U8420:
-                       sgaclk_parent = "soc0_pll";
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (sgaclk_parent)
-               clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent,
-                                       PRCMU_SGACLK, 0);
-       else
-               clk = clk_reg_prcmu_gate("sgclk", NULL,
-                                       PRCMU_SGACLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "mali");
-
-       clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "UART");
-
-       clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "MSP02");
-
-       clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "MSP1");
-
-       clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "I2C");
-
-       clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "slim");
-
-       clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH1");
-
-       clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH2");
-
-       clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH3");
-
-       clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH5");
-
-       clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH6");
-
-       clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH7");
-
-       clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "lcd");
-       clk_register_clkdev(clk, "lcd", "mcde");
-
-       clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "bml");
-
-       clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-
-       clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-
-       clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "hdmi");
-       clk_register_clkdev(clk, "hdmi", "mcde");
-
-       clk = clk_reg_prcmu_scalable("apeatclk", NULL, PRCMU_APEATCLK, 0,
-                                    CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "apeat");
-
-       clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "apetrace");
-
-       clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "mcde");
-       clk_register_clkdev(clk, "mcde", "mcde");
-       clk_register_clkdev(clk, "dsisys", "dsilink.0");
-       clk_register_clkdev(clk, "dsisys", "dsilink.1");
-       clk_register_clkdev(clk, "dsisys", "dsilink.2");
-
-       clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK,
-                               CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "ipi2");
-
-       clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK,
-                               CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "dsialt");
-
-       clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "dma40.0");
-
-       clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "b2r2");
-       clk_register_clkdev(clk, NULL, "b2r2_core");
-       clk_register_clkdev(clk, NULL, "U8500-B2R2.0");
-
-       clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "tv");
-       clk_register_clkdev(clk, "tv", "mcde");
-
-       clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "SSP");
-
-       clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "rngclk");
-
-       clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "uicc");
-
-       clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "mtu0");
-       clk_register_clkdev(clk, NULL, "mtu1");
-
-       clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
-                                       100000000,
-                                       CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdmmc");
-
-       clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
-                               PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs2", "mcde");
-       clk_register_clkdev(clk, "dsihs2", "dsilink.2");
-
-
-       clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
-                               PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs0", "mcde");
-       clk_register_clkdev(clk, "dsihs0", "dsilink.0");
-
-       clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
-                               PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs1", "mcde");
-       clk_register_clkdev(clk, "dsihs1", "dsilink.1");
-
-       clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
-                               PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilp0", "dsilink.0");
-       clk_register_clkdev(clk, "dsilp0", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
-                               PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilp1", "dsilink.1");
-       clk_register_clkdev(clk, "dsilp1", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
-                               PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilp2", "dsilink.2");
-       clk_register_clkdev(clk, "dsilp2", "mcde");
-
-       clk = clk_reg_prcmu_scalable_rate("armss", NULL,
-                               PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "armss", NULL);
-
-       clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
-                               CLK_IGNORE_UNUSED, 1, 2);
-       clk_register_clkdev(clk, NULL, "smp_twd");
-
-       /*
-        * FIXME: Add special handled PRCMU clocks here:
-        * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
-        * 2. ab9540_clkout1yuv, see clkout0yuv
-        */
-
-       /* PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp0");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp1");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
-
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, NULL, "spi3");
-
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
-                               BIT(8), 0);
-       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
-                               BIT(9), 0);
-       clk_register_clkdev(clk, NULL, "gpio.0");
-       clk_register_clkdev(clk, NULL, "gpio.1");
-       clk_register_clkdev(clk, NULL, "gpioblock0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
-
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
-                               BIT(11), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp3");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "spi2");
-
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, NULL, "spi1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, NULL, "pwl");
-
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi4");
-
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp2");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
-
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
-                               BIT(8), 0);
-       clk_register_clkdev(clk, NULL, "spi0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
-                               BIT(9), 0);
-       clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
-                               BIT(11), 0);
-       clk_register_clkdev(clk, NULL, "gpio.6");
-       clk_register_clkdev(clk, NULL, "gpio.7");
-       clk_register_clkdev(clk, NULL, "gpioblock1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
-                               BIT(12), 0);
-
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "fsmc", NULL);
-       clk_register_clkdev(clk, NULL, "smsc911x.0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ssp0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ssp1");
-
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ske");
-       clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
-
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi5");
-
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
-                               BIT(8), 0);
-       clk_register_clkdev(clk, NULL, "gpio.2");
-       clk_register_clkdev(clk, NULL, "gpio.3");
-       clk_register_clkdev(clk, NULL, "gpio.4");
-       clk_register_clkdev(clk, NULL, "gpio.5");
-       clk_register_clkdev(clk, NULL, "gpioblock2");
-
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "usb", "musb-ux500.0");
-
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "gpio.8");
-       clk_register_clkdev(clk, NULL, "gpioblock3");
-
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "rng");
-
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "cryp0");
-       clk_register_clkdev(clk, NULL, "cryp1");
-
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, NULL, "hash0");
-
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, NULL, "pka");
-
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, NULL, "hash1");
-
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, NULL, "cfgreg");
-
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "mtu0");
-
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "mtu1");
-
-       /* PRCC K-clocks
-        *
-        * FIXME: Some drivers requires PERPIH[n| to be automatically enabled
-        * by enabling just the K-clock, even if it is not a valid parent to
-        * the K-clock. Until drivers get fixed we might need some kind of
-        * "parent muxed join".
-        */
-
-       /* Periph1 */
-       clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart0");
-
-       clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart1");
-
-       clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
-
-       clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp0");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
-
-       clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp1");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
-
-       clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
-                       clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi0");
-
-       clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
-
-       clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "slimbus0");
-
-       clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
-
-       clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp3");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
-
-       /* Periph2 */
-       clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
-
-       clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi4");
-
-       clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp2");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
-
-       clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi1");
-
-       clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi3");
-
-       /* Note that rate is received from parent. */
-       clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       clkrst2_base, BIT(6),
-                       CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
-       clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       clkrst2_base, BIT(7),
-                       CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
-
-       /* Periph3 */
-       clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ssp0");
-
-       clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ssp1");
-
-       clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
-
-       clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi2");
-
-       clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ske");
-       clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
-
-       clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart2");
-
-       clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi5");
-
-       /* Periph6 */
-       clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
-                       clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "rng");
-}
index e319ef912dc6c27bbaba940a42a4ef97a5bf07a0..271c09644652c72e3f057e8d90b2ebcb1d1f258c 100644 (file)
@@ -8,8 +8,7 @@
  */
 
 #include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/of_address.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
@@ -54,14 +53,25 @@ static const struct of_device_id u8500_clk_of_match[] = {
        { },
 };
 
-void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                      u32 clkrst5_base, u32 clkrst6_base)
+/* CLKRST4 is missing making it hard to index things */
+enum clkrst_index {
+       CLKRST1_INDEX = 0,
+       CLKRST2_INDEX,
+       CLKRST3_INDEX,
+       CLKRST5_INDEX,
+       CLKRST6_INDEX,
+       CLKRST_MAX,
+};
+
+void u8500_clk_init(void)
 {
        struct prcmu_fw_version *fw_version;
        struct device_node *np = NULL;
        struct device_node *child = NULL;
        const char *sgaclk_parent = NULL;
        struct clk *clk, *rtc_clk, *twd_clk;
+       u32 bases[CLKRST_MAX];
+       int i;
 
        if (of_have_populated_dt())
                np = of_find_matching_node(NULL, u8500_clk_of_match);
@@ -69,6 +79,15 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
                pr_err("Either DT or U8500 Clock node not found\n");
                return;
        }
+       for (i = 0; i < ARRAY_SIZE(bases); i++) {
+               struct resource r;
+
+               if (of_address_to_resource(np, i, &r))
+                       /* Not much choice but to continue */
+                       pr_err("failed to get CLKRST %d base address\n",
+                              i + 1);
+               bases[i] = r.start;
+       }
 
        /* Clock sources */
        clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
@@ -246,179 +265,179 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
         */
 
        /* PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 1, 0);
 
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 1, 1);
 
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 1, 2);
 
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 1, 3);
 
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 1, 4);
 
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 1, 5);
 
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 1, 6);
 
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 1, 7);
 
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX],
                                BIT(8), 0);
        PRCC_PCLK_STORE(clk, 1, 8);
 
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX],
                                BIT(9), 0);
        PRCC_PCLK_STORE(clk, 1, 9);
 
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX],
                                BIT(10), 0);
        PRCC_PCLK_STORE(clk, 1, 10);
 
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX],
                                BIT(11), 0);
        PRCC_PCLK_STORE(clk, 1, 11);
 
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 2, 0);
 
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 2, 1);
 
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 2, 2);
 
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 2, 3);
 
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 2, 4);
 
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 2, 5);
 
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 2, 6);
 
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 2, 7);
 
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX],
                                BIT(8), 0);
        PRCC_PCLK_STORE(clk, 2, 8);
 
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX],
                                BIT(9), 0);
        PRCC_PCLK_STORE(clk, 2, 9);
 
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX],
                                BIT(10), 0);
        PRCC_PCLK_STORE(clk, 2, 10);
 
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX],
                                BIT(11), 0);
        PRCC_PCLK_STORE(clk, 2, 11);
 
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX],
                                BIT(12), 0);
        PRCC_PCLK_STORE(clk, 2, 12);
 
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 3, 0);
 
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 3, 1);
 
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 3, 2);
 
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 3, 3);
 
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 3, 4);
 
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 3, 5);
 
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 3, 6);
 
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 3, 7);
 
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX],
                                BIT(8), 0);
        PRCC_PCLK_STORE(clk, 3, 8);
 
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 5, 0);
 
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 5, 1);
 
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 6, 0);
 
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 6, 1);
 
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 6, 2);
 
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 6, 3);
 
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 6, 4);
 
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 6, 5);
 
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 6, 6);
 
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 6, 7);
 
@@ -432,109 +451,109 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 
        /* Periph1 */
        clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 0);
 
        clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 1);
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 2);
 
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 3);
 
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 4);
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
-                       clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 5);
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 6);
 
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 8);
 
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 9);
 
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 10);
 
        /* Periph2 */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 0);
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 2);
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 3);
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 4);
 
        clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 5);
 
        /* Note that rate is received from parent. */
        clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       clkrst2_base, BIT(6),
+                       bases[CLKRST2_INDEX], BIT(6),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        PRCC_KCLK_STORE(clk, 2, 6);
 
        clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       clkrst2_base, BIT(7),
+                       bases[CLKRST2_INDEX], BIT(7),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        PRCC_KCLK_STORE(clk, 2, 7);
 
        /* Periph3 */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 1);
 
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 2);
 
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 3);
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 4);
 
        clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 5);
 
        clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 6);
 
        clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 7);
 
        /* Periph6 */
        clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
-                       clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 6, 0);
 
        for_each_child_of_node(np, child) {
index 20c8add90d110db1575e0ccb5695499581853af5..d7bcb7a86615f91f518c1719f812b29f783c23d3 100644 (file)
@@ -7,17 +7,51 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
 #include "clk.h"
 
-void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base)
+static const struct of_device_id u8540_clk_of_match[] = {
+       { .compatible = "stericsson,u8540-clks", },
+       { }
+};
+
+/* CLKRST4 is missing making it hard to index things */
+enum clkrst_index {
+       CLKRST1_INDEX = 0,
+       CLKRST2_INDEX,
+       CLKRST3_INDEX,
+       CLKRST5_INDEX,
+       CLKRST6_INDEX,
+       CLKRST_MAX,
+};
+
+void u8540_clk_init(void)
 {
        struct clk *clk;
+       struct device_node *np = NULL;
+       u32 bases[CLKRST_MAX];
+       int i;
+
+       if (of_have_populated_dt())
+               np = of_find_matching_node(NULL, u8540_clk_of_match);
+       if (!np) {
+               pr_err("Either DT or U8540 Clock node not found\n");
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(bases); i++) {
+               struct resource r;
+
+               if (of_address_to_resource(np, i, &r))
+                       /* Not much choice but to continue */
+                       pr_err("failed to get CLKRST %d base address\n",
+                              i + 1);
+               bases[i] = r.start;
+       }
 
        /* Clock sources. */
        /* Fixed ClockGen */
@@ -219,151 +253,151 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 
        /* PRCC P-clocks */
        /* Peripheral 1 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart1");
 
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
 
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp0");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp1");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.1");
 
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
 
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, NULL, "spi3");
 
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX],
                                BIT(8), 0);
        clk_register_clkdev(clk, "apb_pclk", "slimbus0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX],
                                BIT(9), 0);
        clk_register_clkdev(clk, NULL, "gpio.0");
        clk_register_clkdev(clk, NULL, "gpio.1");
        clk_register_clkdev(clk, NULL, "gpioblock0");
        clk_register_clkdev(clk, "apb_pclk", "ab85xx-codec.0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX],
                                BIT(10), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
 
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX],
                                BIT(11), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp3");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.3");
 
        /* Peripheral 2 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
 
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, NULL, "spi2");
 
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, NULL, "spi1");
 
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, NULL, "pwl");
 
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi4");
 
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp2");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.2");
 
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi1");
 
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi3");
 
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX],
                                BIT(8), 0);
        clk_register_clkdev(clk, NULL, "spi0");
 
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX],
                                BIT(9), 0);
        clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
 
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX],
                                BIT(10), 0);
        clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
 
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX],
                                BIT(11), 0);
        clk_register_clkdev(clk, NULL, "gpio.6");
        clk_register_clkdev(clk, NULL, "gpio.7");
        clk_register_clkdev(clk, NULL, "gpioblock1");
 
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX],
                                BIT(12), 0);
        clk_register_clkdev(clk, "msp4-pclk", "ab85xx-codec.0");
 
        /* Peripheral 3 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, NULL, "fsmc");
 
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, "apb_pclk", "ssp0");
 
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, "apb_pclk", "ssp1");
 
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
 
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi2");
 
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, "apb_pclk", "ske");
        clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
 
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart2");
 
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi5");
 
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX],
                                BIT(8), 0);
        clk_register_clkdev(clk, NULL, "gpio.2");
        clk_register_clkdev(clk, NULL, "gpio.3");
@@ -371,64 +405,64 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
        clk_register_clkdev(clk, NULL, "gpio.5");
        clk_register_clkdev(clk, NULL, "gpioblock2");
 
-       clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", bases[CLKRST3_INDEX],
                                BIT(9), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.5");
 
-       clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", bases[CLKRST3_INDEX],
                                BIT(10), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.6");
 
-       clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", bases[CLKRST3_INDEX],
                                BIT(11), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart3");
 
-       clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", bases[CLKRST3_INDEX],
                                BIT(12), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart4");
 
        /* Peripheral 5 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "usb", "musb-ux500.0");
        clk_register_clkdev(clk, "usbclk", "ab-iddet.0");
 
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, NULL, "gpio.8");
        clk_register_clkdev(clk, NULL, "gpioblock3");
 
        /* Peripheral 6 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "apb_pclk", "rng");
 
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, NULL, "cryp0");
        clk_register_clkdev(clk, NULL, "cryp1");
 
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, NULL, "hash0");
 
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, NULL, "pka");
 
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, NULL, "db8540-hash1");
 
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, NULL, "cfgreg");
 
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "mtu0");
 
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "mtu1");
 
@@ -442,138 +476,138 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 
        /* Peripheral 1 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart0");
 
        clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart1");
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.1");
 
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp0");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.0");
 
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp1");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.1");
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmchclk",
-                       clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi0");
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.2");
 
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "slimbus0");
 
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.4");
 
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp3");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.3");
 
        /* Peripheral 2 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.3");
 
        clk = clk_reg_prcc_kclk("p2_pwl_kclk", "rtc32k",
-                       clkrst2_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(1), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "pwl");
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmchclk",
-                       clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi4");
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp2");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.2");
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmchclk",
-                       clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi1");
 
        clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi3");
 
        clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       clkrst2_base, BIT(6),
+                       bases[CLKRST2_INDEX], BIT(6),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        clk_register_clkdev(clk, "hsir_hsirxclk", "ste_hsi.0");
 
        clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       clkrst2_base, BIT(7),
+                       bases[CLKRST2_INDEX], BIT(7),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        clk_register_clkdev(clk, "hsit_hsitxclk", "ste_hsi.0");
 
        /* Should only be 9540, but might be added for 85xx as well */
        clk = clk_reg_prcc_kclk("p2_msp4_kclk", "msp02clk",
-                       clkrst2_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(9), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp4");
        clk_register_clkdev(clk, "msp4", "ab85xx-codec.0");
 
        /* Peripheral 3 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "ssp0");
 
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "ssp1");
 
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.0");
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmchclk",
-                       clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi2");
 
        clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "ske");
        clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
 
        clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart2");
 
        clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi5");
 
        clk = clk_reg_prcc_kclk("p3_i2c5_kclk", "i2cclk",
-                       clkrst3_base, BIT(8), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(8), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.5");
 
        clk = clk_reg_prcc_kclk("p3_i2c6_kclk", "i2cclk",
-                       clkrst3_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(9), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.6");
 
        clk = clk_reg_prcc_kclk("p3_uart3_kclk", "uartclk",
-                       clkrst3_base, BIT(10), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(10), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart3");
 
        clk = clk_reg_prcc_kclk("p3_uart4_kclk", "uartclk",
-                       clkrst3_base, BIT(11), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(11), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart4");
 
        /* Peripheral 6 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p6_rng_kclk", "rngclk",
-                       clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "rng");
 }
index 44794782e7e01681414ad123809bf1b8ce35be0b..2138a4c8cbcaa23de8e8d8bd9f79d8c0ee606521 100644 (file)
@@ -7,15 +7,12 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
 #include "clk.h"
 
-void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base)
+void u9540_clk_init(void)
 {
        /* register clocks here */
 }
index bc96f103bd7caac9c95a977bb3c8559d638bbf9b..a3893ea2199dafa5412207711a1d33fca04c287f 100644 (file)
@@ -13,8 +13,9 @@
  * ICST clock code from the ARM tree should probably be merged into this
  * file.
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
index 1cc1330dc5709bc1cc24f887349291aeff705200..65c842a21c6243149d8d3740cacbd270792bfa0d 100644 (file)
@@ -7,7 +7,6 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
index c8b523117fb7ed4e971b5582f802cab0fb7c0eee..86f70997d59dce436d34c9c5aef74be0f367f869 100644 (file)
@@ -6,7 +6,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -33,13 +32,13 @@ static const struct icst_params realview_oscvco_params = {
        .idx2s          = icst307_idx2s,
 };
 
-static const struct clk_icst_desc __initdata realview_osc0_desc = {
+static const struct clk_icst_desc realview_osc0_desc __initconst = {
        .params = &realview_oscvco_params,
        .vco_offset = REALVIEW_SYS_OSC0_OFFSET,
        .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
 };
 
-static const struct clk_icst_desc __initdata realview_osc4_desc = {
+static const struct clk_icst_desc realview_osc4_desc __initconst = {
        .params = &realview_oscvco_params,
        .vco_offset = REALVIEW_SYS_OSC4_OFFSET,
        .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
index a96dd8e53fdb2d9537a363c480418db859c8c0b1..a1cdef6b0f9045be6dd3e47b712f02b8e485de50 100644 (file)
@@ -12,7 +12,8 @@
  */
 
 #include <linux/amba/sp810.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/of.h>
@@ -32,12 +33,9 @@ struct clk_sp810_timerclken {
 
 struct clk_sp810 {
        struct device_node *node;
-       int refclk_index, timclk_index;
        void __iomem *base;
        spinlock_t lock;
        struct clk_sp810_timerclken timerclken[4];
-       struct clk *refclk;
-       struct clk *timclk;
 };
 
 static u8 clk_sp810_timerclken_get_parent(struct clk_hw *hw)
@@ -70,55 +68,7 @@ static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index)
        return 0;
 }
 
-/*
- * FIXME - setting the parent every time .prepare is invoked is inefficient.
- * This is better handled by a dedicated clock tree configuration mechanism at
- * init-time.  Revisit this later when such a mechanism exists
- */
-static int clk_sp810_timerclken_prepare(struct clk_hw *hw)
-{
-       struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw);
-       struct clk_sp810 *sp810 = timerclken->sp810;
-       struct clk *old_parent = __clk_get_parent(hw->clk);
-       struct clk *new_parent;
-
-       if (!sp810->refclk)
-               sp810->refclk = of_clk_get(sp810->node, sp810->refclk_index);
-
-       if (!sp810->timclk)
-               sp810->timclk = of_clk_get(sp810->node, sp810->timclk_index);
-
-       if (WARN_ON(IS_ERR(sp810->refclk) || IS_ERR(sp810->timclk)))
-               return -ENOENT;
-
-       /* Select fastest parent */
-       if (clk_get_rate(sp810->refclk) > clk_get_rate(sp810->timclk))
-               new_parent = sp810->refclk;
-       else
-               new_parent = sp810->timclk;
-
-       /* Switch the parent if necessary */
-       if (old_parent != new_parent) {
-               clk_prepare(new_parent);
-               clk_set_parent(hw->clk, new_parent);
-               clk_unprepare(old_parent);
-       }
-
-       return 0;
-}
-
-static void clk_sp810_timerclken_unprepare(struct clk_hw *hw)
-{
-       struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw);
-       struct clk_sp810 *sp810 = timerclken->sp810;
-
-       clk_put(sp810->timclk);
-       clk_put(sp810->refclk);
-}
-
 static const struct clk_ops clk_sp810_timerclken_ops = {
-       .prepare = clk_sp810_timerclken_prepare,
-       .unprepare = clk_sp810_timerclken_unprepare,
        .get_parent = clk_sp810_timerclken_get_parent,
        .set_parent = clk_sp810_timerclken_set_parent,
 };
@@ -128,8 +78,8 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec,
 {
        struct clk_sp810 *sp810 = data;
 
-       if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
-                       ARRAY_SIZE(sp810->timerclken)))
+       if (WARN_ON(clkspec->args_count != 1 ||
+                   clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken)))
                return NULL;
 
        return sp810->timerclken[clkspec->args[0]].clk;
@@ -139,24 +89,18 @@ static void __init clk_sp810_of_setup(struct device_node *node)
 {
        struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL);
        const char *parent_names[2];
+       int num = ARRAY_SIZE(parent_names);
        char name[12];
        struct clk_init_data init;
        int i;
+       bool deprecated;
 
        if (!sp810) {
                pr_err("Failed to allocate memory for SP810!\n");
                return;
        }
 
-       sp810->refclk_index = of_property_match_string(node, "clock-names",
-                       "refclk");
-       parent_names[0] = of_clk_get_parent_name(node, sp810->refclk_index);
-
-       sp810->timclk_index = of_property_match_string(node, "clock-names",
-                       "timclk");
-       parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index);
-
-       if (!parent_names[0] || !parent_names[1]) {
+       if (of_clk_parent_fill(node, parent_names, num) != num) {
                pr_warn("Failed to obtain parent clocks for SP810!\n");
                return;
        }
@@ -169,7 +113,9 @@ static void __init clk_sp810_of_setup(struct device_node *node)
        init.ops = &clk_sp810_timerclken_ops;
        init.flags = CLK_IS_BASIC;
        init.parent_names = parent_names;
-       init.num_parents = ARRAY_SIZE(parent_names);
+       init.num_parents = num;
+
+       deprecated = !of_find_property(node, "assigned-clock-parents", NULL);
 
        for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) {
                snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
@@ -178,6 +124,15 @@ static void __init clk_sp810_of_setup(struct device_node *node)
                sp810->timerclken[i].channel = i;
                sp810->timerclken[i].hw.init = &init;
 
+               /*
+                * If DT isn't setting the parent, force it to be
+                * the 1 MHz clock without going through the framework.
+                * We do this before clk_register() so that it can determine
+                * the parent and setup the tree properly.
+                */
+               if (deprecated)
+                       init.ops->set_parent(&sp810->timerclken[i].hw, 1);
+
                sp810->timerclken[i].clk = clk_register(NULL,
                                &sp810->timerclken[i].hw);
                WARN_ON(IS_ERR(sp810->timerclken[i].clk));
index 7a4f8635bd1eb31ce8bbb68e755f124bd5f12f00..a89a927567e0cfae45df95b8aed7cc2218509fc3 100644 (file)
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -35,7 +33,7 @@ static const struct icst_params cp_auxosc_params = {
        .idx2s          = icst525_idx2s,
 };
 
-static const struct clk_icst_desc __initdata cm_auxosc_desc = {
+static const struct clk_icst_desc cm_auxosc_desc __initconst = {
        .params = &cp_auxosc_params,
        .vco_offset = 0x1c,
        .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
index 95b707c18108c475908dcec1f1904ddb1db0c270..74005aa322a2d7d26a1d16deaa2da26b4da1f02b 100644 (file)
@@ -1,2 +1,2 @@
-obj-y := clk-pll.o
+obj-y := clk.o
 obj-$(CONFIG_SOC_ZX296702) += clk-zx296702.o
index 929d033594af5202fbe9664703df422573ebfdde..ebd20d852e733ea788269246f20f3ccb02acae6a 100644 (file)
@@ -36,10 +36,21 @@ static struct clk_onecell_data lsp1clk_data;
 #define CLK_MUX1               (topcrm_base + 0x8c)
 
 #define CLK_SDMMC1             (lsp0crpm_base + 0x0c)
+#define CLK_GPIO               (lsp0crpm_base + 0x2c)
+#define CLK_SPDIF0             (lsp0crpm_base + 0x10)
+#define SPDIF0_DIV             (lsp0crpm_base + 0x14)
+#define CLK_I2S0               (lsp0crpm_base + 0x18)
+#define I2S0_DIV               (lsp0crpm_base + 0x1c)
+#define CLK_I2S1               (lsp0crpm_base + 0x20)
+#define I2S1_DIV               (lsp0crpm_base + 0x24)
+#define CLK_I2S2               (lsp0crpm_base + 0x34)
+#define I2S2_DIV               (lsp0crpm_base + 0x38)
 
 #define CLK_UART0              (lsp1crpm_base + 0x20)
 #define CLK_UART1              (lsp1crpm_base + 0x24)
 #define CLK_SDMMC0             (lsp1crpm_base + 0x2c)
+#define CLK_SPDIF1             (lsp1crpm_base + 0x30)
+#define SPDIF1_DIV             (lsp1crpm_base + 0x34)
 
 static const struct zx_pll_config pll_a9_config[] = {
        { .rate = 700000000, .cfg0 = 0x800405d1, .cfg1 = 0x04555555 },
@@ -72,104 +83,119 @@ static const struct clk_div_table sec_wclk_divider[] = {
        { /* sentinel */ }
 };
 
-static const char * matrix_aclk_sel[] = {
+static const char * const matrix_aclk_sel[] = {
        "pll_mm0_198M",
        "osc",
        "clk_148M5",
        "pll_lsp_104M",
 };
 
-static const char * a9_wclk_sel[] = {
+static const char * const a9_wclk_sel[] = {
        "pll_a9",
        "osc",
        "clk_500",
        "clk_250",
 };
 
-static const char * a9_as1_aclk_sel[] = {
+static const char * const a9_as1_aclk_sel[] = {
        "clk_250",
        "osc",
        "pll_mm0_396M",
        "pll_mac_333M",
 };
 
-static const char * a9_trace_clkin_sel[] = {
+static const char * const a9_trace_clkin_sel[] = {
        "clk_74M25",
        "pll_mm1_108M",
        "clk_125",
        "clk_148M5",
 };
 
-static const char * decppu_aclk_sel[] = {
+static const char * const decppu_aclk_sel[] = {
        "clk_250",
        "pll_mm0_198M",
        "pll_lsp_104M",
        "pll_audio_294M912",
 };
 
-static const char * vou_main_wclk_sel[] = {
+static const char * const vou_main_wclk_sel[] = {
        "clk_148M5",
        "clk_74M25",
        "clk_27",
        "pll_mm1_54M",
 };
 
-static const char * vou_scaler_wclk_sel[] = {
+static const char * const vou_scaler_wclk_sel[] = {
        "clk_250",
        "pll_mac_333M",
        "pll_audio_294M912",
        "pll_mm0_198M",
 };
 
-static const char * r2d_wclk_sel[] = {
+static const char * const r2d_wclk_sel[] = {
        "pll_audio_294M912",
        "pll_mac_333M",
        "pll_a9_350M",
        "pll_mm0_396M",
 };
 
-static const char * ddr_wclk_sel[] = {
+static const char * const ddr_wclk_sel[] = {
        "pll_mac_333M",
        "pll_ddr_266M",
        "pll_audio_294M912",
        "pll_mm0_198M",
 };
 
-static const char * nand_wclk_sel[] = {
+static const char * const nand_wclk_sel[] = {
        "pll_lsp_104M",
        "osc",
 };
 
-static const char * lsp_26_wclk_sel[] = {
+static const char * const lsp_26_wclk_sel[] = {
        "pll_lsp_26M",
        "osc",
 };
 
-static const char * vl0_sel[] = {
+static const char * const vl0_sel[] = {
        "vou_main_channel_div",
        "vou_aux_channel_div",
 };
 
-static const char * hdmi_sel[] = {
+static const char * const hdmi_sel[] = {
        "vou_main_channel_wclk",
        "vou_aux_channel_wclk",
 };
 
-static const char * sdmmc0_wclk_sel[] = {
+static const char * const sdmmc0_wclk_sel[] = {
        "lsp1_104M_wclk",
        "lsp1_26M_wclk",
 };
 
-static const char * sdmmc1_wclk_sel[] = {
+static const char * const sdmmc1_wclk_sel[] = {
        "lsp0_104M_wclk",
        "lsp0_26M_wclk",
 };
 
-static const char * uart_wclk_sel[] = {
+static const char * const uart_wclk_sel[] = {
        "lsp1_104M_wclk",
        "lsp1_26M_wclk",
 };
 
+static const char * const spdif0_wclk_sel[] = {
+       "lsp0_104M_wclk",
+       "lsp0_26M_wclk",
+};
+
+static const char * const spdif1_wclk_sel[] = {
+       "lsp1_104M_wclk",
+       "lsp1_26M_wclk",
+};
+
+static const char * const i2s_wclk_sel[] = {
+       "lsp0_104M_wclk",
+       "lsp0_26M_wclk",
+};
+
 static inline struct clk *zx_divtbl(const char *name, const char *parent,
                                    void __iomem *reg, u8 shift, u8 width,
                                    const struct clk_div_table *table)
@@ -185,7 +211,7 @@ static inline struct clk *zx_div(const char *name, const char *parent,
                                    reg, shift, width, 0, &reg_lock);
 }
 
-static inline struct clk *zx_mux(const char *name, const char **parents,
+static inline struct clk *zx_mux(const char *name, const char * const *parents,
                int num_parents, void __iomem *reg, u8 shift, u8 width)
 {
        return clk_register_mux(NULL, name, parents, num_parents,
@@ -196,7 +222,7 @@ static inline struct clk *zx_gate(const char *name, const char *parent,
                                  void __iomem *reg, u8 shift)
 {
        return clk_register_gate(NULL, name, parent, CLK_IGNORE_UNUSED,
-                                reg, shift, 0, &reg_lock);
+                                reg, shift, CLK_SET_RATE_PARENT, &reg_lock);
 }
 
 static void __init zx296702_top_clocks_init(struct device_node *np)
@@ -585,7 +611,57 @@ static void __init zx296702_lsp0_clocks_init(struct device_node *np)
        clk[ZX296702_SDMMC1_WCLK] =
                zx_gate("sdmmc1_wclk", "sdmmc1_wclk_div", CLK_SDMMC1, 1);
        clk[ZX296702_SDMMC1_PCLK] =
-               zx_gate("sdmmc1_pclk", "lsp1_apb_pclk", CLK_SDMMC1, 0);
+               zx_gate("sdmmc1_pclk", "lsp0_apb_pclk", CLK_SDMMC1, 0);
+
+       clk[ZX296702_GPIO_CLK] =
+               zx_gate("gpio_clk", "lsp0_apb_pclk", CLK_GPIO, 0);
+
+       /* SPDIF */
+       clk[ZX296702_SPDIF0_WCLK_MUX] =
+               zx_mux("spdif0_wclk_mux", spdif0_wclk_sel,
+                               ARRAY_SIZE(spdif0_wclk_sel), CLK_SPDIF0, 4, 1);
+       clk[ZX296702_SPDIF0_WCLK] =
+               zx_gate("spdif0_wclk", "spdif0_wclk_mux", CLK_SPDIF0, 1);
+       clk[ZX296702_SPDIF0_PCLK] =
+               zx_gate("spdif0_pclk", "lsp0_apb_pclk", CLK_SPDIF0, 0);
+
+       clk[ZX296702_SPDIF0_DIV] =
+               clk_register_zx_audio("spdif0_div", "spdif0_wclk", 0,
+                               SPDIF0_DIV);
+
+       /* I2S */
+       clk[ZX296702_I2S0_WCLK_MUX] =
+               zx_mux("i2s0_wclk_mux", i2s_wclk_sel,
+                               ARRAY_SIZE(i2s_wclk_sel), CLK_I2S0, 4, 1);
+       clk[ZX296702_I2S0_WCLK] =
+               zx_gate("i2s0_wclk", "i2s0_wclk_mux", CLK_I2S0, 1);
+       clk[ZX296702_I2S0_PCLK] =
+               zx_gate("i2s0_pclk", "lsp0_apb_pclk", CLK_I2S0, 0);
+
+       clk[ZX296702_I2S0_DIV] =
+               clk_register_zx_audio("i2s0_div", "i2s0_wclk", 0, I2S0_DIV);
+
+       clk[ZX296702_I2S1_WCLK_MUX] =
+               zx_mux("i2s1_wclk_mux", i2s_wclk_sel,
+                               ARRAY_SIZE(i2s_wclk_sel), CLK_I2S1, 4, 1);
+       clk[ZX296702_I2S1_WCLK] =
+               zx_gate("i2s1_wclk", "i2s1_wclk_mux", CLK_I2S1, 1);
+       clk[ZX296702_I2S1_PCLK] =
+               zx_gate("i2s1_pclk", "lsp0_apb_pclk", CLK_I2S1, 0);
+
+       clk[ZX296702_I2S1_DIV] =
+               clk_register_zx_audio("i2s1_div", "i2s1_wclk", 0, I2S1_DIV);
+
+       clk[ZX296702_I2S2_WCLK_MUX] =
+               zx_mux("i2s2_wclk_mux", i2s_wclk_sel,
+                               ARRAY_SIZE(i2s_wclk_sel), CLK_I2S2, 4, 1);
+       clk[ZX296702_I2S2_WCLK] =
+               zx_gate("i2s2_wclk", "i2s2_wclk_mux", CLK_I2S2, 1);
+       clk[ZX296702_I2S2_PCLK] =
+               zx_gate("i2s2_pclk", "lsp0_apb_pclk", CLK_I2S2, 0);
+
+       clk[ZX296702_I2S2_DIV] =
+               clk_register_zx_audio("i2s2_div", "i2s2_wclk", 0, I2S2_DIV);
 
        for (i = 0; i < ARRAY_SIZE(lsp0clk); i++) {
                if (IS_ERR(clk[i])) {
@@ -641,6 +717,18 @@ static void __init zx296702_lsp1_clocks_init(struct device_node *np)
        clk[ZX296702_SDMMC0_PCLK] =
                zx_gate("sdmmc0_pclk", "lsp1_apb_pclk", CLK_SDMMC0, 0);
 
+       clk[ZX296702_SPDIF1_WCLK_MUX] =
+               zx_mux("spdif1_wclk_mux", spdif1_wclk_sel,
+                               ARRAY_SIZE(spdif1_wclk_sel), CLK_SPDIF1, 4, 1);
+       clk[ZX296702_SPDIF1_WCLK] =
+               zx_gate("spdif1_wclk", "spdif1_wclk_mux", CLK_SPDIF1, 1);
+       clk[ZX296702_SPDIF1_PCLK] =
+               zx_gate("spdif1_pclk", "lsp1_apb_pclk", CLK_SPDIF1, 0);
+
+       clk[ZX296702_SPDIF1_DIV] =
+               clk_register_zx_audio("spdif1_div", "spdif1_wclk", 0,
+                               SPDIF1_DIV);
+
        for (i = 0; i < ARRAY_SIZE(lsp1clk); i++) {
                if (IS_ERR(clk[i])) {
                        pr_err("zx296702 clk %d: register failed with %ld\n",
similarity index 55%
rename from drivers/clk/zte/clk-pll.c
rename to drivers/clk/zte/clk.c
index c3b221ae6cd7b8527ba0eb6a243c7d06a8075d6a..7c73c538c43d8a12ee8c64e78bb2cc84ed61867d 100644 (file)
 #include <linux/iopoll.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <asm/div64.h>
 
 #include "clk.h"
 
 #define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
+#define to_clk_zx_audio(_hw) container_of(_hw, struct clk_zx_audio, hw)
 
 #define CFG0_CFG1_OFFSET 4
 #define LOCK_FLAG BIT(30)
@@ -141,8 +143,9 @@ static const struct clk_ops zx_pll_ops = {
 };
 
 struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
-       unsigned long flags, void __iomem *reg_base,
-       const struct zx_pll_config *lookup_table, int count, spinlock_t *lock)
+                               unsigned long flags, void __iomem *reg_base,
+                               const struct zx_pll_config *lookup_table,
+                               int count, spinlock_t *lock)
 {
        struct clk_zx_pll *zx_pll;
        struct clk *clk;
@@ -170,3 +173,137 @@ struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
 
        return clk;
 }
+
+#define BPAR 1000000
+static u32 calc_reg(u32 parent_rate, u32 rate)
+{
+       u32 sel, integ, fra_div, tmp;
+       u64 tmp64 = (u64)parent_rate * BPAR;
+
+       do_div(tmp64, rate);
+       integ = (u32)tmp64 / BPAR;
+       integ = integ >> 1;
+
+       tmp = (u32)tmp64 % BPAR;
+       sel = tmp / BPAR;
+
+       tmp = tmp % BPAR;
+       fra_div = tmp * 0xff / BPAR;
+       tmp = (sel << 24) | (integ << 16) | (0xff << 8) | fra_div;
+
+       /* Set I2S integer divider as 1. This bit is reserved for SPDIF
+        * and do no harm.
+        */
+       tmp |= BIT(28);
+       return tmp;
+}
+
+static u32 calc_rate(u32 reg, u32 parent_rate)
+{
+       u32 sel, integ, fra_div, tmp;
+       u64 tmp64 = (u64)parent_rate * BPAR;
+
+       tmp = reg;
+       sel = (tmp >> 24) & BIT(0);
+       integ = (tmp >> 16) & 0xff;
+       fra_div = tmp & 0xff;
+
+       tmp = fra_div * BPAR;
+       tmp = tmp / 0xff;
+       tmp += sel * BPAR;
+       tmp += 2 * integ * BPAR;
+       do_div(tmp64, tmp);
+
+       return (u32)tmp64;
+}
+
+static unsigned long zx_audio_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = readl_relaxed(zx_audio->reg_base);
+       return calc_rate(reg, parent_rate);
+}
+
+static long zx_audio_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       u32 reg;
+
+       if (rate * 2 > *prate)
+               return -EINVAL;
+
+       reg = calc_reg(*prate, rate);
+       return calc_rate(reg, *prate);
+}
+
+static int zx_audio_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = calc_reg(parent_rate, rate);
+       writel_relaxed(reg, zx_audio->reg_base);
+
+       return 0;
+}
+
+#define ZX_AUDIO_EN BIT(25)
+static int zx_audio_enable(struct clk_hw *hw)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = readl_relaxed(zx_audio->reg_base);
+       writel_relaxed(reg & ~ZX_AUDIO_EN, zx_audio->reg_base);
+       return 0;
+}
+
+static void zx_audio_disable(struct clk_hw *hw)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = readl_relaxed(zx_audio->reg_base);
+       writel_relaxed(reg | ZX_AUDIO_EN, zx_audio->reg_base);
+}
+
+static const struct clk_ops zx_audio_ops = {
+       .recalc_rate = zx_audio_recalc_rate,
+       .round_rate = zx_audio_round_rate,
+       .set_rate = zx_audio_set_rate,
+       .enable = zx_audio_enable,
+       .disable = zx_audio_disable,
+};
+
+struct clk *clk_register_zx_audio(const char *name,
+                                 const char * const parent_name,
+                                 unsigned long flags,
+                                 void __iomem *reg_base)
+{
+       struct clk_zx_audio *zx_audio;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       zx_audio = kzalloc(sizeof(*zx_audio), GFP_KERNEL);
+       if (!zx_audio)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &zx_audio_ops;
+       init.flags = flags;
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.num_parents = parent_name ? 1 : 0;
+
+       zx_audio->reg_base = reg_base;
+       zx_audio->hw.init = &init;
+
+       clk = clk_register(NULL, &zx_audio->hw);
+       if (IS_ERR(clk))
+               kfree(zx_audio);
+
+       return clk;
+}
index 0914a82d0535743cf869b7dd58aba07de45a9c17..65ae08b818d3f836809199341f130c8aff1f0811 100644 (file)
@@ -29,4 +29,13 @@ struct clk_zx_pll {
 struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
        unsigned long flags, void __iomem *reg_base,
        const struct zx_pll_config *lookup_table, int count, spinlock_t *lock);
+
+struct clk_zx_audio {
+       struct clk_hw hw;
+       void __iomem *reg_base;
+};
+
+struct clk *clk_register_zx_audio(const char *name,
+                                 const char * const parent_name,
+                                 unsigned long flags, void __iomem *reg_base);
 #endif
index de614384bb447512344e089a9ed56ea657f731f3..38a65c3e62fc247c39ecaff4853cfd45c3148168 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/clk/zynq.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 510c8a1d37b375841bc49879e3dd0dfccb00470b..5ea91e3818d0ccd7a4496d0401f266bb2dd67505 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/of_address.h>
index eb8ac3097ff501b19bea92c69ed73bf1caa988de..18b7727bdc5785f770bbe1b273a2194084927925 100644 (file)
@@ -455,7 +455,7 @@ static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
        cached_state->postdiv1 =
                        pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
        cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
-       cached_state->vco_rate = __clk_get_rate(pll->clk_hw.clk);
+       cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
 }
 
 static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
@@ -466,7 +466,7 @@ static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
        int ret;
 
        if ((cached_state->vco_rate != 0) &&
-               (cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) {
+               (cached_state->vco_rate == clk_hw_get_rate(&pll->clk_hw))) {
                ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
                                                cached_state->vco_rate, 0);
                if (ret) {
index 5455bf3d5a9191323bca2b9e71c4835a314f2e6f..b8e2f611fd47b027fb0486a02306515e9ec7798a 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
index 1085c0432158c02038aba6f961ea7e300f7f950b..52c5c7e63b525786754689ce0e2751d9790ae0ff 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/platform_data/simplefb.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_platform.h>
 
index aab088d301999278fa283a7f6d4a6e38ce6546d6..63d01c15d2b368f63114622c2fac1eb51977eee7 100644 (file)
@@ -31,6 +31,7 @@
 #define CLK_FOUT_VPLL                  4
 #define CLK_FOUT_UPLL                  5
 #define CLK_FOUT_MPLL                  6
+#define CLK_ARM_CLK                    7
 
 /* Muxes */
 #define CLK_MOUT_MPLL_USER_L           16
index 4273891dc78e41b998fcf17a203868a7237f3095..8183d1c237d9562fc899ea44571a756a7f1491c7 100644 (file)
@@ -21,6 +21,7 @@
 #define CLK_FOUT_CPLL          6
 #define CLK_FOUT_EPLL          7
 #define CLK_FOUT_VPLL          8
+#define CLK_ARM_CLK            9
 
 /* gate for special clocks (sclk) */
 #define CLK_SCLK_CAM_BAYER     128
diff --git a/include/dt-bindings/clock/imx6ul-clock.h b/include/dt-bindings/clock/imx6ul-clock.h
new file mode 100644 (file)
index 0000000..c343894
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, 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.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX6UL_H
+#define __DT_BINDINGS_CLOCK_IMX6UL_H
+
+#define IMX6UL_CLK_DUMMY               0
+#define IMX6UL_CLK_CKIL                        1
+#define IMX6UL_CLK_CKIH                        2
+#define IMX6UL_CLK_OSC                 3
+#define IMX6UL_PLL1_BYPASS_SRC         4
+#define IMX6UL_PLL2_BYPASS_SRC         5
+#define IMX6UL_PLL3_BYPASS_SRC         6
+#define IMX6UL_PLL4_BYPASS_SRC         7
+#define IMX6UL_PLL5_BYPASS_SRC         8
+#define IMX6UL_PLL6_BYPASS_SRC         9
+#define IMX6UL_PLL7_BYPASS_SRC         10
+#define IMX6UL_CLK_PLL1                11
+#define IMX6UL_CLK_PLL2                12
+#define IMX6UL_CLK_PLL3                13
+#define IMX6UL_CLK_PLL4                14
+#define IMX6UL_CLK_PLL5                15
+#define IMX6UL_CLK_PLL6                16
+#define IMX6UL_CLK_PLL7                17
+#define IMX6UL_PLL1_BYPASS             18
+#define IMX6UL_PLL2_BYPASS             19
+#define IMX6UL_PLL3_BYPASS             20
+#define IMX6UL_PLL4_BYPASS             21
+#define IMX6UL_PLL5_BYPASS             22
+#define IMX6UL_PLL6_BYPASS             23
+#define IMX6UL_PLL7_BYPASS             24
+#define IMX6UL_CLK_PLL1_SYS            25
+#define IMX6UL_CLK_PLL2_BUS            26
+#define IMX6UL_CLK_PLL3_USB_OTG        27
+#define IMX6UL_CLK_PLL4_AUDIO          28
+#define IMX6UL_CLK_PLL5_VIDEO          29
+#define IMX6UL_CLK_PLL6_ENET           30
+#define IMX6UL_CLK_PLL7_USB_HOST       31
+#define IMX6UL_CLK_USBPHY1             32
+#define IMX6UL_CLK_USBPHY2             33
+#define IMX6UL_CLK_USBPHY1_GATE                34
+#define IMX6UL_CLK_USBPHY2_GATE                35
+#define IMX6UL_CLK_PLL2_PFD0           36
+#define IMX6UL_CLK_PLL2_PFD1           37
+#define IMX6UL_CLK_PLL2_PFD2           38
+#define IMX6UL_CLK_PLL2_PFD3           39
+#define IMX6UL_CLK_PLL3_PFD0           40
+#define IMX6UL_CLK_PLL3_PFD1           41
+#define IMX6UL_CLK_PLL3_PFD2           42
+#define IMX6UL_CLK_PLL3_PFD3           43
+#define IMX6UL_CLK_ENET_REF            44
+#define IMX6UL_CLK_ENET2_REF           45
+#define IMX6UL_CLK_ENET2_REF_125M      46
+#define IMX6UL_CLK_ENET_PTP_REF                47
+#define IMX6UL_CLK_ENET_PTP            48
+#define IMX6UL_CLK_PLL4_POST_DIV       49
+#define IMX6UL_CLK_PLL4_AUDIO_DIV      50
+#define IMX6UL_CLK_PLL5_POST_DIV       51
+#define IMX6UL_CLK_PLL5_VIDEO_DIV      52
+#define IMX6UL_CLK_PLL2_198M           53
+#define IMX6UL_CLK_PLL3_80M            54
+#define IMX6UL_CLK_PLL3_60M            55
+#define IMX6UL_CLK_STEP                56
+#define IMX6UL_CLK_PLL1_SW             57
+#define IMX6UL_CLK_AXI_ALT_SEL         58
+#define IMX6UL_CLK_AXI_SEL             59
+#define IMX6UL_CLK_PERIPH_PRE          60
+#define IMX6UL_CLK_PERIPH2_PRE         61
+#define IMX6UL_CLK_PERIPH_CLK2_SEL     62
+#define IMX6UL_CLK_PERIPH2_CLK2_SEL    63
+#define IMX6UL_CLK_USDHC1_SEL          64
+#define IMX6UL_CLK_USDHC2_SEL          65
+#define IMX6UL_CLK_BCH_SEL             66
+#define IMX6UL_CLK_GPMI_SEL            67
+#define IMX6UL_CLK_EIM_SLOW_SEL        68
+#define IMX6UL_CLK_SPDIF_SEL           69
+#define IMX6UL_CLK_SAI1_SEL            70
+#define IMX6UL_CLK_SAI2_SEL            71
+#define IMX6UL_CLK_SAI3_SEL            72
+#define IMX6UL_CLK_LCDIF_PRE_SEL       73
+#define IMX6UL_CLK_SIM_PRE_SEL         74
+#define IMX6UL_CLK_LDB_DI0_SEL         75
+#define IMX6UL_CLK_LDB_DI1_SEL         76
+#define IMX6UL_CLK_ENFC_SEL            77
+#define IMX6UL_CLK_CAN_SEL             78
+#define IMX6UL_CLK_ECSPI_SEL           79
+#define IMX6UL_CLK_UART_SEL            80
+#define IMX6UL_CLK_QSPI1_SEL           81
+#define IMX6UL_CLK_PERCLK_SEL          82
+#define IMX6UL_CLK_LCDIF_SEL           83
+#define IMX6UL_CLK_SIM_SEL             84
+#define IMX6UL_CLK_PERIPH              85
+#define IMX6UL_CLK_PERIPH2             86
+#define IMX6UL_CLK_LDB_DI0_DIV_3_5     87
+#define IMX6UL_CLK_LDB_DI0_DIV_7       88
+#define IMX6UL_CLK_LDB_DI1_DIV_3_5     89
+#define IMX6UL_CLK_LDB_DI1_DIV_7       90
+#define IMX6UL_CLK_LDB_DI0_DIV_SEL     91
+#define IMX6UL_CLK_LDB_DI1_DIV_SEL     92
+#define IMX6UL_CLK_ARM                 93
+#define IMX6UL_CLK_PERIPH_CLK2         94
+#define IMX6UL_CLK_PERIPH2_CLK2        95
+#define IMX6UL_CLK_AHB                 96
+#define IMX6UL_CLK_MMDC_PODF           97
+#define IMX6UL_CLK_AXI_PODF            98
+#define IMX6UL_CLK_PERCLK              99
+#define IMX6UL_CLK_IPG                 100
+#define IMX6UL_CLK_USDHC1_PODF         101
+#define IMX6UL_CLK_USDHC2_PODF         102
+#define IMX6UL_CLK_BCH_PODF            103
+#define IMX6UL_CLK_GPMI_PODF           104
+#define IMX6UL_CLK_EIM_SLOW_PODF       105
+#define IMX6UL_CLK_SPDIF_PRED          106
+#define IMX6UL_CLK_SPDIF_PODF          107
+#define IMX6UL_CLK_SAI1_PRED           108
+#define IMX6UL_CLK_SAI1_PODF           109
+#define IMX6UL_CLK_SAI2_PRED           110
+#define IMX6UL_CLK_SAI2_PODF           111
+#define IMX6UL_CLK_SAI3_PRED           112
+#define IMX6UL_CLK_SAI3_PODF           113
+#define IMX6UL_CLK_LCDIF_PRED          114
+#define IMX6UL_CLK_LCDIF_PODF          115
+#define IMX6UL_CLK_SIM_PODF            116
+#define IMX6UL_CLK_QSPI1_PDOF          117
+#define IMX6UL_CLK_ENFC_PRED           118
+#define IMX6UL_CLK_ENFC_PODF           119
+#define IMX6UL_CLK_CAN_PODF            120
+#define IMX6UL_CLK_ECSPI_PODF          121
+#define IMX6UL_CLK_UART_PODF           122
+#define IMX6UL_CLK_ADC1                123
+#define IMX6UL_CLK_ADC2                124
+#define IMX6UL_CLK_AIPSTZ1             125
+#define IMX6UL_CLK_AIPSTZ2             126
+#define IMX6UL_CLK_AIPSTZ3             127
+#define IMX6UL_CLK_APBHDMA             128
+#define IMX6UL_CLK_ASRC_IPG            129
+#define IMX6UL_CLK_ASRC_MEM            130
+#define IMX6UL_CLK_GPMI_BCH_APB        131
+#define IMX6UL_CLK_GPMI_BCH            132
+#define IMX6UL_CLK_GPMI_IO             133
+#define IMX6UL_CLK_GPMI_APB            134
+#define IMX6UL_CLK_CAAM_MEM            135
+#define IMX6UL_CLK_CAAM_ACLK           136
+#define IMX6UL_CLK_CAAM_IPG            137
+#define IMX6UL_CLK_CSI                 138
+#define IMX6UL_CLK_ECSPI1              139
+#define IMX6UL_CLK_ECSPI2              140
+#define IMX6UL_CLK_ECSPI3              141
+#define IMX6UL_CLK_ECSPI4              142
+#define IMX6UL_CLK_EIM                 143
+#define IMX6UL_CLK_ENET                144
+#define IMX6UL_CLK_ENET_AHB            145
+#define IMX6UL_CLK_EPIT1               146
+#define IMX6UL_CLK_EPIT2               147
+#define IMX6UL_CLK_CAN1_IPG            148
+#define IMX6UL_CLK_CAN1_SERIAL         149
+#define IMX6UL_CLK_CAN2_IPG            150
+#define IMX6UL_CLK_CAN2_SERIAL         151
+#define IMX6UL_CLK_GPT1_BUS            152
+#define IMX6UL_CLK_GPT1_SERIAL         153
+#define IMX6UL_CLK_GPT2_BUS            154
+#define IMX6UL_CLK_GPT2_SERIAL         155
+#define IMX6UL_CLK_I2C1                156
+#define IMX6UL_CLK_I2C2                157
+#define IMX6UL_CLK_I2C3                158
+#define IMX6UL_CLK_I2C4                159
+#define IMX6UL_CLK_IOMUXC              160
+#define IMX6UL_CLK_LCDIF_APB           161
+#define IMX6UL_CLK_LCDIF_PIX           162
+#define IMX6UL_CLK_MMDC_P0_FAST        163
+#define IMX6UL_CLK_MMDC_P0_IPG         164
+#define IMX6UL_CLK_OCOTP               165
+#define IMX6UL_CLK_OCRAM               166
+#define IMX6UL_CLK_PWM1                167
+#define IMX6UL_CLK_PWM2                168
+#define IMX6UL_CLK_PWM3                169
+#define IMX6UL_CLK_PWM4                170
+#define IMX6UL_CLK_PWM5                171
+#define IMX6UL_CLK_PWM6                172
+#define IMX6UL_CLK_PWM7                173
+#define IMX6UL_CLK_PWM8                174
+#define IMX6UL_CLK_PXP                 175
+#define IMX6UL_CLK_QSPI                176
+#define IMX6UL_CLK_ROM                 177
+#define IMX6UL_CLK_SAI1                178
+#define IMX6UL_CLK_SAI1_IPG            179
+#define IMX6UL_CLK_SAI2                180
+#define IMX6UL_CLK_SAI2_IPG            181
+#define IMX6UL_CLK_SAI3                182
+#define IMX6UL_CLK_SAI3_IPG            183
+#define IMX6UL_CLK_SDMA                184
+#define IMX6UL_CLK_SIM                 185
+#define IMX6UL_CLK_SIM_S               186
+#define IMX6UL_CLK_SPBA                187
+#define IMX6UL_CLK_SPDIF               188
+#define IMX6UL_CLK_UART1_IPG           189
+#define IMX6UL_CLK_UART1_SERIAL        190
+#define IMX6UL_CLK_UART2_IPG           191
+#define IMX6UL_CLK_UART2_SERIAL        192
+#define IMX6UL_CLK_UART3_IPG           193
+#define IMX6UL_CLK_UART3_SERIAL        194
+#define IMX6UL_CLK_UART4_IPG           195
+#define IMX6UL_CLK_UART4_SERIAL        196
+#define IMX6UL_CLK_UART5_IPG           197
+#define IMX6UL_CLK_UART5_SERIAL        198
+#define IMX6UL_CLK_UART6_IPG           199
+#define IMX6UL_CLK_UART6_SERIAL        200
+#define IMX6UL_CLK_UART7_IPG           201
+#define IMX6UL_CLK_UART7_SERIAL        202
+#define IMX6UL_CLK_UART8_IPG           203
+#define IMX6UL_CLK_UART8_SERIAL        204
+#define IMX6UL_CLK_USBOH3              205
+#define IMX6UL_CLK_USDHC1              206
+#define IMX6UL_CLK_USDHC2              207
+#define IMX6UL_CLK_WDOG1               208
+#define IMX6UL_CLK_WDOG2               209
+#define IMX6UL_CLK_WDOG3               210
+#define IMX6UL_CLK_LDB_DI0             211
+#define IMX6UL_CLK_AXI                 212
+#define IMX6UL_CLK_SPDIF_GCLK          213
+#define IMX6UL_CLK_GPT_3M              214
+#define IMX6UL_CLK_SIM2                        215
+#define IMX6UL_CLK_SIM1                        216
+#define IMX6UL_CLK_IPP_DI0             217
+#define IMX6UL_CLK_IPP_DI1             218
+#define IMX6UL_CA7_SECONDARY_SEL       219
+#define IMX6UL_CLK_PER_BCH             220
+#define IMX6UL_CLK_CSI_SEL             221
+#define IMX6UL_CLK_CSI_PODF            222
+#define IMX6UL_CLK_PLL3_120M           223
+
+#define IMX6UL_CLK_END                 224
+
+#endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
index bc1ed1dbd855667a7b0d62704544af1e4b3ea34d..d3a9824ef6462d775405b38fa41f7b31740d7508 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3066A_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3066A_H
+
 #include <dt-bindings/clock/rk3188-cru-common.h>
 
 /* soft-reset indices */
@@ -33,3 +36,5 @@
 #define SRST_HDMI              96
 #define SRST_HDMI_APB          97
 #define SRST_CIF1              111
+
+#endif
index 6a370503c954e1466e124292fcac0d4584136c8d..8df77a7c030b0647abbf81e3a592c488f273638c 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3188_COMMON_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3188_COMMON_H
+
 /* core clocks from */
 #define PLL_APLL               1
 #define PLL_DPLL               2
 #define SRST_PTM1_ATB          141
 #define SRST_CTM               142
 #define SRST_TS                        143
+
+#endif
index 9fac8edd3f9df65523eaa42b6b02d5c19bdd984a..9f2e631f2651001327c7761d5c1fdc86cb4bf35b 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3188_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3188_H
+
 #include <dt-bindings/clock/rk3188-cru-common.h>
 
 /* soft-reset indices */
@@ -49,3 +52,5 @@
 #define SRST_GPU_BRIDGE                121
 #define SRST_CTI3              123
 #define SRST_CTI3_APB          124
+
+#endif
index dea419708d73ed112fd63a4c8bea747fd087e3ee..c719aacef14fb84f030603d5435a733f7dc2b1ba 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3288_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3288_H
+
 /* core clocks */
 #define PLL_APLL               1
 #define PLL_DPLL               2
 #define SRST_TSP_CLKIN0                189
 #define SRST_TSP_CLKIN1                190
 #define SRST_TSP_27M           191
+
+#endif
diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h
new file mode 100644 (file)
index 0000000..9c5dd9b
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
+ *
+ * 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_RK3368_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3368_H
+
+/* core clocks */
+#define PLL_APLLB              1
+#define PLL_APLLL              2
+#define PLL_DPLL               3
+#define PLL_CPLL               4
+#define PLL_GPLL               5
+#define PLL_NPLL               6
+#define ARMCLKB                        7
+#define ARMCLKL                        8
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU_CORE          64
+#define SCLK_SPI0              65
+#define SCLK_SPI1              66
+#define SCLK_SPI2              67
+#define SCLK_SDMMC             68
+#define SCLK_SDIO0             69
+#define SCLK_EMMC              71
+#define SCLK_TSADC             72
+#define SCLK_SARADC            73
+#define SCLK_NANDC0            75
+#define SCLK_UART0             77
+#define SCLK_UART1             78
+#define SCLK_UART2             79
+#define SCLK_UART3             80
+#define SCLK_UART4             81
+#define SCLK_I2S_8CH           82
+#define SCLK_SPDIF_8CH         83
+#define SCLK_I2S_2CH           84
+#define SCLK_TIMER0            85
+#define SCLK_TIMER1            86
+#define SCLK_TIMER2            87
+#define SCLK_TIMER3            88
+#define SCLK_TIMER4            89
+#define SCLK_TIMER5            90
+#define SCLK_TIMER6            91
+#define SCLK_OTGPHY0           93
+#define SCLK_OTG_ADP           96
+#define SCLK_HSICPHY480M       97
+#define SCLK_HSICPHY12M                98
+#define SCLK_MACREF            99
+#define SCLK_VOP0_PWM          100
+#define SCLK_MAC_RX            102
+#define SCLK_MAC_TX            103
+#define SCLK_EDP_24M           104
+#define SCLK_EDP               105
+#define SCLK_RGA               106
+#define SCLK_ISP               107
+#define SCLK_HDCP              108
+#define SCLK_HDMI_HDCP         109
+#define SCLK_HDMI_CEC          110
+#define SCLK_HEVC_CABAC                111
+#define SCLK_HEVC_CORE         112
+#define SCLK_I2S_8CH_OUT       113
+#define SCLK_SDMMC_DRV         114
+#define SCLK_SDIO0_DRV         115
+#define SCLK_EMMC_DRV          117
+#define SCLK_SDMMC_SAMPLE      118
+#define SCLK_SDIO0_SAMPLE      119
+#define SCLK_EMMC_SAMPLE       121
+#define SCLK_USBPHY480M                122
+#define SCLK_PVTM_CORE         123
+#define SCLK_PVTM_GPU          124
+#define SCLK_PVTM_PMU          125
+#define SCLK_SFC               126
+#define SCLK_MAC               127
+#define SCLK_MACREF_OUT                128
+
+#define DCLK_VOP               190
+#define MCLK_CRYPTO            191
+
+/* aclk gates */
+#define ACLK_GPU_MEM           192
+#define ACLK_GPU_CFG           193
+#define ACLK_DMAC_BUS          194
+#define ACLK_DMAC_PERI         195
+#define ACLK_PERI_MMU          196
+#define ACLK_GMAC              197
+#define ACLK_VOP               198
+#define ACLK_VOP_IEP           199
+#define ACLK_RGA               200
+#define ACLK_HDCP              201
+#define ACLK_IEP               202
+#define ACLK_VIO0_NOC          203
+#define ACLK_VIP               204
+#define ACLK_ISP               205
+#define ACLK_VIO1_NOC          206
+#define ACLK_VIDEO             208
+#define ACLK_BUS               209
+#define ACLK_PERI              210
+
+/* pclk gates */
+#define PCLK_GPIO0             320
+#define PCLK_GPIO1             321
+#define PCLK_GPIO2             322
+#define PCLK_GPIO3             323
+#define PCLK_PMUGRF            324
+#define PCLK_MAILBOX           325
+#define PCLK_GRF               329
+#define PCLK_SGRF              330
+#define PCLK_PMU               331
+#define PCLK_I2C0              332
+#define PCLK_I2C1              333
+#define PCLK_I2C2              334
+#define PCLK_I2C3              335
+#define PCLK_I2C4              336
+#define PCLK_I2C5              337
+#define PCLK_SPI0              338
+#define PCLK_SPI1              339
+#define PCLK_SPI2              340
+#define PCLK_UART0             341
+#define PCLK_UART1             342
+#define PCLK_UART2             343
+#define PCLK_UART3             344
+#define PCLK_UART4             345
+#define PCLK_TSADC             346
+#define PCLK_SARADC            347
+#define PCLK_SIM               348
+#define PCLK_GMAC              349
+#define PCLK_PWM0              350
+#define PCLK_PWM1              351
+#define PCLK_TIMER0            353
+#define PCLK_TIMER1            354
+#define PCLK_EDP_CTRL          355
+#define PCLK_MIPI_DSI0         356
+#define PCLK_MIPI_CSI          358
+#define PCLK_HDCP              359
+#define PCLK_HDMI_CTRL         360
+#define PCLK_VIO_H2P           361
+#define PCLK_BUS               362
+#define PCLK_PERI              363
+#define PCLK_DDRUPCTL          364
+#define PCLK_DDRPHY            365
+#define PCLK_ISP               366
+#define PCLK_VIP               367
+#define PCLK_WDT               368
+
+/* hclk gates */
+#define HCLK_SFC               448
+#define HCLK_OTG0              449
+#define HCLK_HOST0             450
+#define HCLK_HOST1             451
+#define HCLK_HSIC              452
+#define HCLK_NANDC0            453
+#define HCLK_TSP               455
+#define HCLK_SDMMC             456
+#define HCLK_SDIO0             457
+#define HCLK_EMMC              459
+#define HCLK_HSADC             460
+#define HCLK_CRYPTO            461
+#define HCLK_I2S_2CH           462
+#define HCLK_I2S_8CH           463
+#define HCLK_SPDIF             464
+#define HCLK_VOP               465
+#define HCLK_ROM               467
+#define HCLK_IEP               468
+#define HCLK_ISP               469
+#define HCLK_RGA               470
+#define HCLK_VIO_AHB_ARBI      471
+#define HCLK_VIO_NOC           472
+#define HCLK_VIP               473
+#define HCLK_VIO_H2P           474
+#define HCLK_VIO_HDCPMMU       475
+#define HCLK_VIDEO             476
+#define HCLK_BUS               477
+#define HCLK_PERI              478
+
+#define CLK_NR_CLKS            (HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE_B0           0
+#define SRST_CORE_B1           1
+#define SRST_CORE_B2           2
+#define SRST_CORE_B3           3
+#define SRST_CORE_B0_PO                4
+#define SRST_CORE_B1_PO                5
+#define SRST_CORE_B2_PO                6
+#define SRST_CORE_B3_PO                7
+#define SRST_L2_B              8
+#define SRST_ADB_B             9
+#define SRST_PD_CORE_B_NIU     10
+#define SRST_PDBUS_STRSYS      11
+#define SRST_SOCDBG_B          14
+#define SRST_CORE_B_DBG                15
+
+#define SRST_DMAC1             18
+#define SRST_INTMEM            19
+#define SRST_ROM               20
+#define SRST_SPDIF8CH          21
+#define SRST_I2S8CH            23
+#define SRST_MAILBOX           24
+#define SRST_I2S2CH            25
+#define SRST_EFUSE_256         26
+#define SRST_MCU_SYS           28
+#define SRST_MCU_PO            29
+#define SRST_MCU_NOC           30
+#define SRST_EFUSE             31
+
+#define SRST_GPIO0             32
+#define SRST_GPIO1             33
+#define SRST_GPIO2             34
+#define SRST_GPIO3             35
+#define SRST_GPIO4             36
+#define SRST_PMUGRF            41
+#define SRST_I2C0              42
+#define SRST_I2C1              43
+#define SRST_I2C2              44
+#define SRST_I2C3              45
+#define SRST_I2C4              46
+#define SRST_I2C5              47
+
+#define SRST_DWPWM             48
+#define SRST_MMC_PERI          49
+#define SRST_PERIPH_MMU                50
+#define SRST_GRF               55
+#define SRST_PMU               56
+#define SRST_PERIPH_AXI                57
+#define SRST_PERIPH_AHB                58
+#define SRST_PERIPH_APB                59
+#define SRST_PERIPH_NIU                60
+#define SRST_PDPERI_AHB_ARBI   61
+#define SRST_EMEM              62
+#define SRST_USB_PERI          63
+
+#define SRST_DMAC2             64
+#define SRST_MAC               66
+#define SRST_GPS               67
+#define SRST_RKPWM             69
+#define SRST_USBHOST0          72
+#define SRST_HSIC              73
+#define SRST_HSIC_AUX          74
+#define SRST_HSIC_PHY          75
+#define SRST_HSADC             76
+#define SRST_NANDC0            77
+#define SRST_SFC               79
+
+#define SRST_SPI0              83
+#define SRST_SPI1              84
+#define SRST_SPI2              85
+#define SRST_SARADC            87
+#define SRST_PDALIVE_NIU       88
+#define SRST_PDPMU_INTMEM      89
+#define SRST_PDPMU_NIU         90
+#define SRST_SGRF              91
+
+#define SRST_VIO_ARBI          96
+#define SRST_RGA_NIU           97
+#define SRST_VIO0_NIU_AXI      98
+#define SRST_VIO_NIU_AHB       99
+#define SRST_LCDC0_AXI         100
+#define SRST_LCDC0_AHB         101
+#define SRST_LCDC0_DCLK                102
+#define SRST_VIP               104
+#define SRST_RGA_CORE          105
+#define SRST_IEP_AXI           106
+#define SRST_IEP_AHB           107
+#define SRST_RGA_AXI           108
+#define SRST_RGA_AHB           109
+#define SRST_ISP               110
+#define SRST_EDP_24M           111
+
+#define SRST_VIDEO_AXI         112
+#define SRST_VIDEO_AHB         113
+#define SRST_MIPIDPHYTX                114
+#define SRST_MIPIDSI0          115
+#define SRST_MIPIDPHYRX                116
+#define SRST_MIPICSI           117
+#define SRST_GPU               120
+#define SRST_HDMI              121
+#define SRST_EDP               122
+#define SRST_PMU_PVTM          123
+#define SRST_CORE_PVTM         124
+#define SRST_GPU_PVTM          125
+#define SRST_GPU_SYS           126
+#define SRST_GPU_MEM_NIU       127
+
+#define SRST_MMC0              128
+#define SRST_SDIO0             129
+#define SRST_EMMC              131
+#define SRST_USBOTG_AHB                132
+#define SRST_USBOTG_PHY                133
+#define SRST_USBOTG_CON                134
+#define SRST_USBHOST0_AHB      135
+#define SRST_USBHOST0_PHY      136
+#define SRST_USBHOST0_CON      137
+#define SRST_USBOTG_UTMI       138
+#define SRST_USBHOST1_UTMI     139
+#define SRST_USB_ADP           141
+
+#define SRST_CORESIGHT         144
+#define SRST_PD_CORE_AHB_NOC   145
+#define SRST_PD_CORE_APB_NOC   146
+#define SRST_GIC               148
+#define SRST_LCDC_PWM0         149
+#define SRST_RGA_H2P_BRG       153
+#define SRST_VIDEO             154
+#define SRST_GPU_CFG_NIU       157
+#define SRST_TSADC             159
+
+#define SRST_DDRPHY0           160
+#define SRST_DDRPHY0_APB       161
+#define SRST_DDRCTRL0          162
+#define SRST_DDRCTRL0_APB      163
+#define SRST_VIDEO_NIU         165
+#define SRST_VIDEO_NIU_AHB     167
+#define SRST_DDRMSCH0          170
+#define SRST_PDBUS_AHB         173
+#define SRST_CRYPTO            174
+
+#define SRST_UART0             179
+#define SRST_UART1             180
+#define SRST_UART2             181
+#define SRST_UART3             182
+#define SRST_UART4             183
+#define SRST_SIMC              186
+#define SRST_TSP               188
+#define SRST_TSP_CLKIN0                189
+
+#define SRST_CORE_L0           192
+#define SRST_CORE_L1           193
+#define SRST_CORE_L2           194
+#define SRST_CORE_L3           195
+#define SRST_CORE_L0_PO                195
+#define SRST_CORE_L1_PO                197
+#define SRST_CORE_L2_PO                198
+#define SRST_CORE_L3_PO                199
+#define SRST_L2_L              200
+#define SRST_ADB_L             201
+#define SRST_PD_CORE_L_NIU     202
+#define SRST_CCI_SYS           203
+#define SRST_CCI_DDR           204
+#define SRST_CCI               205
+#define SRST_SOCDBG_L          206
+#define SRST_CORE_L_DBG                207
+
+#define SRST_CORE_B0_NC                208
+#define SRST_CORE_B0_PO_NC     209
+#define SRST_L2_B_NC           210
+#define SRST_ADB_B_NC          211
+#define SRST_PD_CORE_B_NIU_NC  212
+#define SRST_PDBUS_STRSYS_NC   213
+#define SRST_CORE_L0_NC                214
+#define SRST_CORE_L0_PO_NC     215
+#define SRST_L2_L_NC           216
+#define SRST_ADB_L_NC          217
+#define SRST_PD_CORE_L_NIU_NC  218
+#define SRST_CCI_SYS_NC                219
+#define SRST_CCI_DDR_NC                220
+#define SRST_CCI_NC            221
+#define SRST_TRACE_NC          222
+
+#define SRST_TIMER00           224
+#define SRST_TIMER01           225
+#define SRST_TIMER02           226
+#define SRST_TIMER03           227
+#define SRST_TIMER04           228
+#define SRST_TIMER05           229
+#define SRST_TIMER10           230
+#define SRST_TIMER11           231
+#define SRST_TIMER12           232
+#define SRST_TIMER13           233
+#define SRST_TIMER14           234
+#define SRST_TIMER15           235
+#define SRST_TIMER0_APB                236
+#define SRST_TIMER1_APB                237
+
+#endif
index e683dbb7e7c5496e4dbe95b08bc5d1c7872dba78..26ee564b0e6892809869ba98c1902cedb9ea9d14 100644 (file)
 #define ZX296702_I2S0_WCLK                     9
 #define ZX296702_I2S0_PCLK                     10
 #define ZX296702_I2S0_DIV                      11
-#define ZX296702_LSP0CLK_END                   12
+#define ZX296702_I2S1_WCLK_MUX                 12
+#define ZX296702_I2S1_WCLK                     13
+#define ZX296702_I2S1_PCLK                     14
+#define ZX296702_I2S1_DIV                      15
+#define ZX296702_I2S2_WCLK_MUX                 16
+#define ZX296702_I2S2_WCLK                     17
+#define ZX296702_I2S2_PCLK                     18
+#define ZX296702_I2S2_DIV                      19
+#define ZX296702_GPIO_CLK                      20
+#define ZX296702_LSP0CLK_END                   21
 
 #define ZX296702_UART0_WCLK_MUX                        0
 #define ZX296702_UART0_WCLK                    1
 #define ZX296702_SDMMC0_WCLK_DIV               7
 #define ZX296702_SDMMC0_WCLK                   8
 #define ZX296702_SDMMC0_PCLK                   9
-#define ZX296702_LSP1CLK_END                   10
+#define ZX296702_SPDIF1_WCLK_MUX               10
+#define ZX296702_SPDIF1_WCLK                   11
+#define ZX296702_SPDIF1_PCLK                   12
+#define ZX296702_SPDIF1_DIV                    13
+#define ZX296702_LSP1CLK_END                   14
 
 #endif /* __DT_BINDINGS_CLOCK_ZX296702_H */
diff --git a/include/dt-bindings/reset/tegra124-car.h b/include/dt-bindings/reset/tegra124-car.h
new file mode 100644 (file)
index 0000000..070e4f6
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * This header provides Tegra124-specific constants for binding
+ * nvidia,tegra124-car.
+ */
+
+#ifndef _DT_BINDINGS_RESET_TEGRA124_CAR_H
+#define _DT_BINDINGS_RESET_TEGRA124_CAR_H
+
+#define TEGRA124_RESET(x)              (6 * 32 + (x))
+#define TEGRA124_RST_DFLL_DVCO         TEGRA124_RESET(0)
+
+#endif /* _DT_BINDINGS_RESET_TEGRA124_CAR_H */
index 78842f46f152694906e0b73f99fd2aa93611e2f7..3ecc07d0da7767555bbe21959c5540375a9a3859 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __LINUX_CLK_PROVIDER_H
 #define __LINUX_CLK_PROVIDER_H
 
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of.h>
 
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 #define CLK_RECALC_NEW_RATES   BIT(9) /* recalc rates after notifications */
 
+struct clk;
 struct clk_hw;
 struct clk_core;
 struct dentry;
 
+/**
+ * struct clk_rate_request - Structure encoding the clk constraints that
+ * a clock user might require.
+ *
+ * @rate:              Requested clock rate. This field will be adjusted by
+ *                     clock drivers according to hardware capabilities.
+ * @min_rate:          Minimum rate imposed by clk users.
+ * @max_rate:          Maximum rate a imposed by clk users.
+ * @best_parent_rate:  The best parent rate a parent can provide to fulfill the
+ *                     requested constraints.
+ * @best_parent_hw:    The most appropriate parent clock that fulfills the
+ *                     requested constraints.
+ *
+ */
+struct clk_rate_request {
+       unsigned long rate;
+       unsigned long min_rate;
+       unsigned long max_rate;
+       unsigned long best_parent_rate;
+       struct clk_hw *best_parent_hw;
+};
+
 /**
  * struct clk_ops -  Callback operations for hardware clocks; these are to
  * be provided by the clock implementation, and will be called by drivers
@@ -176,12 +198,8 @@ struct clk_ops {
                                        unsigned long parent_rate);
        long            (*round_rate)(struct clk_hw *hw, unsigned long rate,
                                        unsigned long *parent_rate);
-       long            (*determine_rate)(struct clk_hw *hw,
-                                         unsigned long rate,
-                                         unsigned long min_rate,
-                                         unsigned long max_rate,
-                                         unsigned long *best_parent_rate,
-                                         struct clk_hw **best_parent_hw);
+       int             (*determine_rate)(struct clk_hw *hw,
+                                         struct clk_rate_request *req);
        int             (*set_parent)(struct clk_hw *hw, u8 index);
        u8              (*get_parent)(struct clk_hw *hw);
        int             (*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -343,6 +361,9 @@ struct clk_div_table {
  *     to the closest integer instead of the up one.
  * CLK_DIVIDER_READ_ONLY - The divider settings are preconfigured and should
  *     not be changed by the clock framework.
+ * CLK_DIVIDER_MAX_AT_ZERO - For dividers which are like CLK_DIVIDER_ONE_BASED
+ *     except when the value read from the register is zero, the divisor is
+ *     2^width of the field.
  */
 struct clk_divider {
        struct clk_hw   hw;
@@ -360,6 +381,7 @@ struct clk_divider {
 #define CLK_DIVIDER_HIWORD_MASK                BIT(3)
 #define CLK_DIVIDER_ROUND_CLOSEST      BIT(4)
 #define CLK_DIVIDER_READ_ONLY          BIT(5)
+#define CLK_DIVIDER_MAX_AT_ZERO                BIT(6)
 
 extern const struct clk_ops clk_divider_ops;
 
@@ -549,6 +571,23 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
 
 void of_gpio_clk_gate_setup(struct device_node *node);
 
+/**
+ * struct clk_gpio_mux - gpio controlled clock multiplexer
+ *
+ * @hw:                see struct clk_gpio
+ * @gpiod:     gpio descriptor to select the parent of this clock multiplexer
+ *
+ * Clock with a gpio control for selecting the parent clock.
+ * Implements .get_parent, .set_parent and .determine_rate
+ */
+
+extern const struct clk_ops clk_gpio_mux_ops;
+struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low, unsigned long flags);
+
+void of_gpio_mux_clk_setup(struct device_node *node);
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -568,31 +607,27 @@ void devm_clk_unregister(struct device *dev, struct clk *clk);
 
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
+const char *clk_hw_get_name(const struct clk_hw *hw);
 struct clk_hw *__clk_get_hw(struct clk *clk);
-u8 __clk_get_num_parents(struct clk *clk);
-struct clk *__clk_get_parent(struct clk *clk);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
+unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
+struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
+struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
+                                         unsigned int index);
 unsigned int __clk_get_enable_count(struct clk *clk);
-unsigned long __clk_get_rate(struct clk *clk);
+unsigned long clk_hw_get_rate(const struct clk_hw *hw);
 unsigned long __clk_get_flags(struct clk *clk);
-bool __clk_is_prepared(struct clk *clk);
+unsigned long clk_hw_get_flags(const struct clk_hw *hw);
+bool clk_hw_is_prepared(const struct clk_hw *hw);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
-long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p);
-unsigned long __clk_determine_rate(struct clk_hw *core,
-                                  unsigned long rate,
-                                  unsigned long min_rate,
-                                  unsigned long max_rate);
-long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p);
+int __clk_mux_determine_rate(struct clk_hw *hw,
+                            struct clk_rate_request *req);
+int __clk_determine_rate(struct clk_hw *core, struct clk_rate_request *req);
+int __clk_mux_determine_rate_closest(struct clk_hw *hw,
+                                    struct clk_rate_request *req);
 void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
+void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
+                          unsigned long max_rate);
 
 static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
 {
@@ -603,7 +638,7 @@ static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
 /*
  * FIXME clock api without lock protection
  */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate);
 
 struct of_device_id;
 
index f3050e15f8333ce596388588f6c1dc0c69d3b4d0..e0c362363c385126de1d90eee5e3a432fa363447 100644 (file)
@@ -7,6 +7,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/types.h>
+
 struct device_node;
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
index 19c4208f4752fd6957712b8a9e900a6baa0b4945..57bf7aab4516eac15cf609642f68b412e290a402 100644 (file)
@@ -17,7 +17,8 @@
 #ifndef __LINUX_CLK_TEGRA_H_
 #define __LINUX_CLK_TEGRA_H_
 
-#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/bug.h>
 
 /*
  * Tegra CPU clock and reset control ops
index 79b76e13d90425db1ed1320b1bfe9f11aecfd767..9299222d680dbbb381e929dd18f5522532565d66 100644 (file)
@@ -188,33 +188,6 @@ struct clk_hw_omap {
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE            0x1
 
-/* Composite clock component types */
-enum {
-       CLK_COMPONENT_TYPE_GATE = 0,
-       CLK_COMPONENT_TYPE_DIVIDER,
-       CLK_COMPONENT_TYPE_MUX,
-       CLK_COMPONENT_TYPE_MAX,
-};
-
-/**
- * struct ti_dt_clk - OMAP DT clock alias declarations
- * @lk: clock lookup definition
- * @node_name: clock DT node to map to
- */
-struct ti_dt_clk {
-       struct clk_lookup               lk;
-       char                            *node_name;
-};
-
-#define DT_CLK(dev, con, name)         \
-       {                               \
-               .lk = {                 \
-                       .dev_id = dev,  \
-                       .con_id = con,  \
-               },                      \
-               .node_name = name,      \
-       }
-
 /* Static memmap indices */
 enum {
        TI_CLKM_CM = 0,
@@ -225,8 +198,6 @@ enum {
        CLK_MAX_MEMMAPS
 };
 
-typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
-
 /**
  * struct clk_omap_reg - OMAP register declaration
  * @offset: offset from the master IP module base address
@@ -238,93 +209,56 @@ struct clk_omap_reg {
 };
 
 /**
- * struct ti_clk_ll_ops - low-level register access ops for a clock
+ * struct ti_clk_ll_ops - low-level ops for clocks
  * @clk_readl: pointer to register read function
  * @clk_writel: pointer to register write function
+ * @clkdm_clk_enable: pointer to clockdomain enable function
+ * @clkdm_clk_disable: pointer to clockdomain disable function
+ * @cm_wait_module_ready: pointer to CM module wait ready function
+ * @cm_split_idlest_reg: pointer to CM module function to split idlest reg
  *
- * Low-level register access ops are generally used by the basic clock types
- * (clk-gate, clk-mux, clk-divider etc.) to provide support for various
- * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be
- * used by other hardware-specific clock drivers if needed.
+ * Low-level ops are generally used by the basic clock types (clk-gate,
+ * clk-mux, clk-divider etc.) to provide support for various low-level
+ * hadrware interfaces (direct MMIO, regmap etc.), and is initialized
+ * by board code. Low-level ops also contain some other platform specific
+ * operations not provided directly by clock drivers.
  */
 struct ti_clk_ll_ops {
        u32     (*clk_readl)(void __iomem *reg);
        void    (*clk_writel)(u32 val, void __iomem *reg);
+       int     (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
+       int     (*clkdm_clk_disable)(struct clockdomain *clkdm,
+                                    struct clk *clk);
+       int     (*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
+                                       u8 idlest_shift);
+       int     (*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
+                                      u8 *idlest_reg_id);
 };
 
-extern struct ti_clk_ll_ops *ti_clk_ll_ops;
-
-extern const struct clk_ops ti_clk_divider_ops;
-extern const struct clk_ops ti_clk_mux_ops;
-
 #define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
 
-void omap2_init_clk_hw_omap_clocks(struct clk *clk);
-int omap3_noncore_dpll_enable(struct clk_hw *hw);
-void omap3_noncore_dpll_disable(struct clk_hw *hw);
-int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate);
-int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
-                                          unsigned long rate,
-                                          unsigned long parent_rate,
-                                          u8 index);
-long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
-                                      unsigned long rate,
-                                      unsigned long min_rate,
-                                      unsigned long max_rate,
-                                      unsigned long *best_parent_rate,
-                                      struct clk_hw **best_parent_clk);
-unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-                                        unsigned long parent_rate);
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-                                   unsigned long target_rate,
-                                   unsigned long *parent_rate);
-long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
-                                       unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk);
-u8 omap2_init_dpll_parent(struct clk_hw *hw);
-unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                          unsigned long *parent_rate);
 void omap2_init_clk_clkdm(struct clk_hw *clk);
-unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
-                                   unsigned long parent_rate);
-int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long parent_rate);
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *prate);
-int omap2_clkops_enable_clkdm(struct clk_hw *hw);
-void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
-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 omap2_dflt_clk_enable(struct clk_hw *hw);
-void omap2_dflt_clk_disable(struct clk_hw *hw);
-int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
-void omap3_clk_lock_dpll5(void);
+int omap2_clk_enable_autoidle_all(void);
+int omap2_clk_allow_idle(struct clk *clk);
+int omap2_clk_deny_idle(struct clk *clk);
 unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
 int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
                             unsigned long parent_rate);
 void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
 void omap2xxx_clkt_vps_init(void);
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
 
-void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
-void ti_dt_clocks_register(struct ti_dt_clk *oclks);
-void ti_dt_clk_init_provider(struct device_node *np, int index);
 void ti_dt_clk_init_retry_clks(void);
 void ti_dt_clockdomains_setup(void);
-int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
-                     ti_of_clk_init_cb_t func);
-int of_ti_clk_autoidle_setup(struct device_node *node);
-int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
+int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops);
+
+struct regmap;
+
+int omap2_clk_provider_init(struct device_node *parent, int index,
+                           struct regmap *syscon, void __iomem *mem);
+void omap2_clk_legacy_provider_init(int index, void __iomem *mem);
 
 int omap3430_dt_clk_init(void);
 int omap3630_dt_clk_init(void);
@@ -338,27 +272,24 @@ int am43xx_dt_clk_init(void);
 int omap2420_dt_clk_init(void);
 int omap2430_dt_clk_init(void);
 
-#ifdef CONFIG_OF
-void of_ti_clk_allow_autoidle_all(void);
-void of_ti_clk_deny_autoidle_all(void);
-#else
-static inline void of_ti_clk_allow_autoidle_all(void) { }
-static inline void of_ti_clk_deny_autoidle_all(void) { }
-#endif
+struct ti_clk_features {
+       u32 flags;
+       long fint_min;
+       long fint_max;
+       long fint_band1_max;
+       long fint_band2_min;
+       u8 dpll_bypass_vals;
+       u8 cm_idlest_val;
+};
+
+#define TI_CLK_DPLL_HAS_FREQSEL                        BIT(0)
+#define TI_CLK_DPLL4_DENY_REPROGRAM            BIT(1)
+#define TI_CLK_DISABLE_CLKDM_CONTROL           BIT(2)
+
+void ti_clk_setup_features(struct ti_clk_features *features);
+const struct ti_clk_features *ti_clk_get_features(void);
 
 extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
-extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
-extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
-extern const struct clk_hw_omap_ops clkhwops_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
-extern const struct clk_hw_omap_ops clkhwops_iclk;
-extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
 
 #ifdef CONFIG_ATAGS
 int omap3430_clk_legacy_init(void);
index 97baf831e07114c04b5e3d4163738da98b0ba5be..3af0da1f3be58bc3f118f2de25d6784261ff8871 100644 (file)
 #ifndef __CLK_UX500_H
 #define __CLK_UX500_H
 
-void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                      u32 clkrst5_base, u32 clkrst6_base);
-
-void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base);
-void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base);
-void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base);
+void u8500_clk_init(void);
+void u9540_clk_init(void);
+void u8540_clk_init(void);
 
 #endif /* __CLK_UX500_H */
index da39c608a28cb910a98697345afa15e8929711e0..95cd63b43b99fa83798fb68dadfbd95a8c0bc57c 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>      /* for KSYM_SYMBOL_LEN */
 #include <linux/types.h>