Merge branch 'v4.3-topic/clk-samsung' of git://git.kernel.org/pub/scm/linux/kernel...
authorMichael Turquette <mturquette@baylibre.com>
Fri, 24 Jul 2015 18:29:53 +0000 (11:29 -0700)
committerStephen Boyd <sboyd@codeaurora.org>
Tue, 28 Jul 2015 18:59:21 +0000 (11:59 -0700)
264 files changed:
Documentation/clk.txt
Documentation/devicetree/bindings/clock/gpio-mux-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt [new file with mode: 0644]
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_dpll.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/dpll3xxx.c [deleted file]
arch/arm/mach-omap2/dpll44xx.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/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-h32mx.c
drivers/clk/at91/clk-main.c
drivers/clk/at91/clk-master.c
drivers/clk/at91/clk-pll.c
drivers/clk/at91/clk-programmable.c
drivers/clk/at91/clk-slow.c
drivers/clk/at91/clk-smd.c
drivers/clk/at91/clk-system.c
drivers/clk/at91/clk-usb.c
drivers/clk/at91/clk-utmi.c
drivers/clk/at91/pmc.h
drivers/clk/bcm/clk-iproc-asiu.c
drivers/clk/bcm/clk-iproc-pll.c
drivers/clk/bcm/clk-kona.c
drivers/clk/clk-axi-clkgen.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-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/clk-hi3620.c
drivers/clk/hisilicon/clk-hip04.c
drivers/clk/hisilicon/clk.c
drivers/clk/hisilicon/clkgate-separated.c
drivers/clk/imx/clk-imx1.c
drivers/clk/imx/clk-imx21.c
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-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.c
drivers/clk/pxa/clk-pxa25x.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/pxa/clk-pxa3xx.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/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-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/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/clk-a20-gmac.c
drivers/clk/sunxi/clk-factors.c
drivers/clk/sunxi/clk-mod0.c
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/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.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
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 [new file with mode: 0644]
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/dpll.c
drivers/clk/ti/dpll3xxx.c [new file with mode: 0644]
drivers/clk/ti/dpll44xx.c [new file with mode: 0644]
drivers/clk/ti/fapll.c
drivers/clk/ti/fixed-factor.c
drivers/clk/ti/mux.c
drivers/clk/ux500/abx500-clk.c
drivers/clk/ux500/clk.h
drivers/clk/ux500/u8500_clk.c
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/zynq/clkc.c
drivers/clocksource/cadence_ttc_timer.c
drivers/spi/spi-pxa2xx-pci.c
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
drivers/video/fbdev/simplefb.c
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/linux/clk-provider.h
include/linux/clk/tegra.h
include/linux/clk/ti.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,
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>;
+       };
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>;
+       };
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..07e1956a26ce9c9a920085a293c62f3858642138 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,7 +61,9 @@ 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;
 
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_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
deleted file mode 100644 (file)
index f251a14..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * OMAP2/3/4 DPLL 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-
-#include <asm/div64.h>
-
-#include "clock.h"
-
-/* DPLL rate rounding: minimum DPLL multiplier, divider values */
-#define DPLL_MIN_MULTIPLIER            2
-#define DPLL_MIN_DIVIDER               1
-
-/* Possible error results from _dpll_test_mult */
-#define DPLL_MULT_UNDERFLOW            -1
-
-/*
- * Scale factor to mitigate roundoff errors in DPLL rate rounding.
- * The higher the scale factor, the greater the risk of arithmetic overflow,
- * but the closer the rounded rate to the target rate.  DPLL_SCALE_FACTOR
- * must be a power of DPLL_SCALE_BASE.
- */
-#define DPLL_SCALE_FACTOR              64
-#define DPLL_SCALE_BASE                        2
-#define DPLL_ROUNDING_VAL              ((DPLL_SCALE_BASE / 2) * \
-                                        (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
-
-/*
- * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
- * From device data manual section 4.3 "DPLL and DLL Specifications".
- */
-#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN  500000
-#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX  2500000
-
-/* _dpll_test_fint() return codes */
-#define DPLL_FINT_UNDERFLOW            -1
-#define DPLL_FINT_INVALID              -2
-
-/* Private functions */
-
-/*
- * _dpll_test_fint - test whether an Fint value is valid for the DPLL
- * @clk: DPLL struct clk to test
- * @n: divider value (N) to test
- *
- * Tests whether a particular divider @n will result in a valid DPLL
- * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter
- * Correction".  Returns 0 if OK, -1 if the enclosing loop can terminate
- * (assuming that it is counting N upwards), or -2 if the enclosing loop
- * should skip to the next iteration (again assuming N is increasing).
- */
-static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
-{
-       struct dpll_data *dd;
-       long fint, fint_min, fint_max;
-       int ret = 0;
-
-       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;
-
-       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;
-       }
-
-       if (!fint_min || !fint_max) {
-               WARN(1, "No fint limits available!\n");
-               return DPLL_FINT_INVALID;
-       }
-
-       if (fint < ti_clk_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) {
-               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) {
-               pr_debug("rejecting n=%d due to Fint failure\n", n);
-               ret = DPLL_FINT_INVALID;
-       }
-
-       return ret;
-}
-
-static unsigned long _dpll_compute_new_rate(unsigned long parent_rate,
-                                           unsigned int m, unsigned int n)
-{
-       unsigned long long num;
-
-       num = (unsigned long long)parent_rate * m;
-       do_div(num, n);
-       return num;
-}
-
-/*
- * _dpll_test_mult - test a DPLL multiplier value
- * @m: pointer to the DPLL m (multiplier) value under test
- * @n: current DPLL n (divider) value under test
- * @new_rate: pointer to storage for the resulting rounded rate
- * @target_rate: the desired DPLL rate
- * @parent_rate: the DPLL's parent clock rate
- *
- * This code tests a DPLL multiplier value, ensuring that the
- * resulting rate will not be higher than the target_rate, and that
- * the multiplier value itself is valid for the DPLL.  Initially, the
- * integer pointed to by the m argument should be prescaled by
- * multiplying by DPLL_SCALE_FACTOR.  The code will replace this with
- * a non-scaled m upon return.  This non-scaled m will result in a
- * new_rate as close as possible to target_rate (but not greater than
- * target_rate) given the current (parent_rate, n, prescaled m)
- * triple. Returns DPLL_MULT_UNDERFLOW in the event that the
- * non-scaled m attempted to underflow, which can allow the calling
- * function to bail out early; or 0 upon success.
- */
-static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
-                          unsigned long target_rate,
-                          unsigned long parent_rate)
-{
-       int r = 0, carry = 0;
-
-       /* Unscale m and round if necessary */
-       if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL)
-               carry = 1;
-       *m = (*m / DPLL_SCALE_FACTOR) + carry;
-
-       /*
-        * The new rate must be <= the target rate to avoid programming
-        * a rate that is impossible for the hardware to handle
-        */
-       *new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
-       if (*new_rate > target_rate) {
-               (*m)--;
-               *new_rate = 0;
-       }
-
-       /* Guard against m underflow */
-       if (*m < DPLL_MIN_MULTIPLIER) {
-               *m = DPLL_MIN_MULTIPLIER;
-               *new_rate = 0;
-               r = DPLL_MULT_UNDERFLOW;
-       }
-
-       if (*new_rate == 0)
-               *new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
-
-       return r;
-}
-
-/**
- * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not
- * @v: bitfield value of the DPLL enable
- *
- * Checks given DPLL enable bitfield to see whether the DPLL is in bypass
- * mode or not. Returns 1 if the DPLL is in bypass, 0 otherwise.
- */
-static int _omap2_dpll_is_in_bypass(u32 v)
-{
-       u8 mask, val;
-
-       mask = ti_clk_features.dpll_bypass_vals;
-
-       /*
-        * Each set bit in the mask corresponds to a bypass value equal
-        * to the bitshift. Go through each set-bit in the mask and
-        * compare against the given register value.
-        */
-       while (mask) {
-               val = __ffs(mask);
-               mask ^= (1 << val);
-               if (v == val)
-                       return 1;
-       }
-
-       return 0;
-}
-
-/* Public functions */
-u8 omap2_init_dpll_parent(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 v;
-       struct dpll_data *dd;
-
-       dd = clk->dpll_data;
-       if (!dd)
-               return -EINVAL;
-
-       v = omap2_clk_readl(clk, dd->control_reg);
-       v &= dd->enable_mask;
-       v >>= __ffs(dd->enable_mask);
-
-       /* Reparent the struct clk in case the dpll is in bypass */
-       if (_omap2_dpll_is_in_bypass(v))
-               return 1;
-
-       return 0;
-}
-
-/**
- * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
- * @clk: struct clk * of a DPLL
- *
- * DPLLs can be locked or bypassed - basically, enabled or disabled.
- * When locked, the DPLL output depends on the M and N values.  When
- * bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock
- * or sys_clk.  Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and
- * 2 are bypassed with dpll1_fclk and dpll2_fclk respectively
- * (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk.
- * Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is
- * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
- * if the clock @clk is not a DPLL.
- */
-unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
-{
-       long long dpll_clk;
-       u32 dpll_mult, dpll_div, v;
-       struct dpll_data *dd;
-
-       dd = clk->dpll_data;
-       if (!dd)
-               return 0;
-
-       /* Return bypass rate if DPLL is bypassed */
-       v = omap2_clk_readl(clk, 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);
-
-       v = omap2_clk_readl(clk, 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;
-       do_div(dpll_clk, dpll_div + 1);
-
-       return dpll_clk;
-}
-
-/* DPLL rate rounding code */
-
-/**
- * omap2_dpll_round_rate - round a target rate for an OMAP DPLL
- * @clk: struct clk * for a DPLL
- * @target_rate: desired DPLL clock rate
- *
- * Given a DPLL and a desired target rate, round the target rate to a
- * possible, programmable rate for this DPLL.  Attempts to select the
- * minimum possible n.  Stores the computed (m, n) in the DPLL's
- * dpll_data structure so set_rate() will not need to call this
- * (expensive) function again.  Returns ~0 if the target rate cannot
- * 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)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       int m, n, r, scaled_max_m;
-       int min_delta_m = INT_MAX, min_delta_n = INT_MAX;
-       unsigned long scaled_rt_rp;
-       unsigned long new_rate = 0;
-       struct dpll_data *dd;
-       unsigned long ref_rate;
-       long delta;
-       long prev_min_delta = LONG_MAX;
-       const char *clk_name;
-
-       if (!clk || !clk->dpll_data)
-               return ~0;
-
-       dd = clk->dpll_data;
-
-       ref_rate = __clk_get_rate(dd->clk_ref);
-       clk_name = __clk_get_name(hw->clk);
-       pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n",
-                clk_name, target_rate);
-
-       scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR);
-       scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
-
-       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)
-                       break;
-               else if (r == DPLL_FINT_INVALID)
-                       continue;
-
-               /* Compute the scaled DPLL multiplier, based on the divider */
-               m = scaled_rt_rp * n;
-
-               /*
-                * Since we're counting n up, a m overflow means we
-                * can bail out completely (since as n increases in
-                * the next iteration, there's no way that m can
-                * increase beyond the current m)
-                */
-               if (m > scaled_max_m)
-                       break;
-
-               r = _dpll_test_mult(&m, n, &new_rate, target_rate,
-                                   ref_rate);
-
-               /* m can't be set low enough for this n - try with a larger n */
-               if (r == DPLL_MULT_UNDERFLOW)
-                       continue;
-
-               /* skip rates above our target rate */
-               delta = target_rate - new_rate;
-               if (delta < 0)
-                       continue;
-
-               if (delta < prev_min_delta) {
-                       prev_min_delta = delta;
-                       min_delta_m = m;
-                       min_delta_n = n;
-               }
-
-               pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n",
-                        clk_name, m, n, new_rate);
-
-               if (delta == 0)
-                       break;
-       }
-
-       if (prev_min_delta == LONG_MAX) {
-               pr_debug("clock: %s: cannot round to rate %lu\n",
-                        clk_name, target_rate);
-               return ~0;
-       }
-
-       dd->last_rounded_m = min_delta_m;
-       dd->last_rounded_n = min_delta_n;
-       dd->last_rounded_rate = target_rate - prev_min_delta;
-
-       return dd->last_rounded_rate;
-}
-
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 },
-};
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
deleted file mode 100644 (file)
index 44e57ec..0000000
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- * OMAP3/4 - specific DPLL control functions
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Written by Paul Walmsley
- * Testing and integration fixes by Jouni Högander
- *
- * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth
- * Menon
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/clkdev.h>
-
-#include "clockdomain.h"
-#include "clock.h"
-
-/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
-#define DPLL_AUTOIDLE_DISABLE                  0x0
-#define DPLL_AUTOIDLE_LOW_POWER_STOP           0x1
-
-#define MAX_DPLL_WAIT_TRIES            1000000
-
-/* Private functions */
-
-/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
-static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
-{
-       const struct dpll_data *dd;
-       u32 v;
-
-       dd = clk->dpll_data;
-
-       v = omap2_clk_readl(clk, dd->control_reg);
-       v &= ~dd->enable_mask;
-       v |= clken_bits << __ffs(dd->enable_mask);
-       omap2_clk_writel(v, clk, dd->control_reg);
-}
-
-/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
-static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
-{
-       const struct dpll_data *dd;
-       int i = 0;
-       int ret = -EINVAL;
-       const char *clk_name;
-
-       dd = clk->dpll_data;
-       clk_name = __clk_get_name(clk->hw.clk);
-
-       state <<= __ffs(dd->idlest_mask);
-
-       while (((omap2_clk_readl(clk, 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",
-                      clk_name, (state) ? "locked" : "bypassed");
-       } else {
-               pr_debug("clock: %s transition to '%s' in %d loops\n",
-                        clk_name, (state) ? "locked" : "bypassed", i);
-
-               ret = 0;
-       }
-
-       return ret;
-}
-
-/* From 3430 TRM ES2 4.7.6.2 */
-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;
-
-       pr_debug("clock: fint is %lu\n", fint);
-
-       if (fint >= 750000 && fint <= 1000000)
-               f = 0x3;
-       else if (fint > 1000000 && fint <= 1250000)
-               f = 0x4;
-       else if (fint > 1250000 && fint <= 1500000)
-               f = 0x5;
-       else if (fint > 1500000 && fint <= 1750000)
-               f = 0x6;
-       else if (fint > 1750000 && fint <= 2100000)
-               f = 0x7;
-       else if (fint > 7500000 && fint <= 10000000)
-               f = 0xB;
-       else if (fint > 10000000 && fint <= 12500000)
-               f = 0xC;
-       else if (fint > 12500000 && fint <= 15000000)
-               f = 0xD;
-       else if (fint > 15000000 && fint <= 17500000)
-               f = 0xE;
-       else if (fint > 17500000 && fint <= 21000000)
-               f = 0xF;
-       else
-               pr_debug("clock: unknown freqsel setting for %d\n", n);
-
-       return f;
-}
-
-/*
- * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to lock.  Waits for the DPLL to report
- * readiness before returning.  Will save and restore the DPLL's
- * autoidle state across the enable, per the CDP code.  If the DPLL
- * locked successfully, return 0; if the DPLL did not lock in the time
- * allotted, or DPLL3 was passed in, return -EINVAL.
- */
-static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
-{
-       const struct dpll_data *dd;
-       u8 ai;
-       u8 state = 1;
-       int r = 0;
-
-       pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
-
-       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)
-               goto done;
-
-       ai = omap3_dpll_autoidle_read(clk);
-
-       if (ai)
-               omap3_dpll_deny_idle(clk);
-
-       _omap3_dpll_write_clken(clk, DPLL_LOCKED);
-
-       r = _omap3_wait_dpll_status(clk, 1);
-
-       if (ai)
-               omap3_dpll_allow_idle(clk);
-
-done:
-       return r;
-}
-
-/*
- * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enter low-power bypass mode.  In
- * bypass mode, the DPLL's rate is set equal to its parent clock's
- * rate.  Waits for the DPLL to report readiness before returning.
- * Will save and restore the DPLL's autoidle state across the enable,
- * per the CDP code.  If the DPLL entered bypass mode successfully,
- * return 0; if the DPLL did not enter bypass in the time allotted, or
- * DPLL3 was passed in, or the DPLL does not support low-power bypass,
- * return -EINVAL.
- */
-static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
-{
-       int r;
-       u8 ai;
-
-       if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
-               return -EINVAL;
-
-       pr_debug("clock: configuring DPLL %s for low-power bypass\n",
-                __clk_get_name(clk->hw.clk));
-
-       ai = omap3_dpll_autoidle_read(clk);
-
-       _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
-
-       r = _omap3_wait_dpll_status(clk, 0);
-
-       if (ai)
-               omap3_dpll_allow_idle(clk);
-
-       return r;
-}
-
-/*
- * _omap3_noncore_dpll_stop - instruct a DPLL to stop
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enter low-power stop. Will save and
- * restore the DPLL's autoidle state across the stop, per the CDP
- * code.  If DPLL3 was passed in, or the DPLL does not support
- * low-power stop, return -EINVAL; otherwise, return 0.
- */
-static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
-{
-       u8 ai;
-
-       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));
-
-       ai = omap3_dpll_autoidle_read(clk);
-
-       _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
-
-       if (ai)
-               omap3_dpll_allow_idle(clk);
-
-       return 0;
-}
-
-/**
- * _lookup_dco - Lookup DCO used by j-type DPLL
- * @clk: pointer to a DPLL struct clk
- * @dco: digital control oscillator selector
- * @m: DPLL multiplier to set
- * @n: DPLL divider to set
- *
- * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
- *
- * XXX This code is not needed for 3430/AM35xx; can it be optimized
- * out in non-multi-OMAP builds for those chips?
- */
-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));
-       fint = (clkinp / n) * m;
-
-       if (fint < 1000000000)
-               *dco = 2;
-       else
-               *dco = 4;
-}
-
-/**
- * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
- * @clk: pointer to a DPLL struct clk
- * @sd_div: target sigma-delta divider
- * @m: DPLL multiplier to set
- * @n: DPLL divider to set
- *
- * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
- *
- * XXX This code is not needed for 3430/AM35xx; can it be optimized
- * out in non-multi-OMAP builds for those chips?
- */
-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));
-
-       /*
-        * target sigma-delta to near 250MHz
-        * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
-        */
-       clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */
-       mod1 = (clkinp * m) % (250 * n);
-       sd = (clkinp * m) / (250 * n);
-       mod2 = sd % 10;
-       sd /= 10;
-
-       if (mod1 || mod2)
-               sd++;
-       *sd_div = sd;
-}
-
-/*
- * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
- * @clk:       struct clk * of DPLL to set
- * @freqsel:   FREQSEL value to set
- *
- * Program the DPLL with the last M, N values calculated, and wait for
- * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success.
- */
-static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
-{
-       struct dpll_data *dd = clk->dpll_data;
-       u8 dco, sd_div;
-       u32 v;
-
-       /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
-       _omap3_noncore_dpll_bypass(clk);
-
-       /*
-        * 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);
-               v &= ~dd->freqsel_mask;
-               v |= freqsel << __ffs(dd->freqsel_mask);
-               omap2_clk_writel(v, clk, dd->control_reg);
-       }
-
-       /* Set DPLL multiplier, divider */
-       v = omap2_clk_readl(clk, dd->mult_div1_reg);
-
-       /* Handle Duty Cycle Correction */
-       if (dd->dcc_mask) {
-               if (dd->last_rounded_rate >= dd->dcc_rate)
-                       v |= dd->dcc_mask; /* Enable DCC */
-               else
-                       v &= ~dd->dcc_mask; /* Disable DCC */
-       }
-
-       v &= ~(dd->mult_mask | dd->div1_mask);
-       v |= dd->last_rounded_m << __ffs(dd->mult_mask);
-       v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
-
-       /* Configure dco and sd_div for dplls that have these fields */
-       if (dd->dco_mask) {
-               _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n);
-               v &= ~(dd->dco_mask);
-               v |= dco << __ffs(dd->dco_mask);
-       }
-       if (dd->sddiv_mask) {
-               _lookup_sddiv(clk, &sd_div, dd->last_rounded_m,
-                             dd->last_rounded_n);
-               v &= ~(dd->sddiv_mask);
-               v |= sd_div << __ffs(dd->sddiv_mask);
-       }
-
-       omap2_clk_writel(v, clk, 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);
-
-               if (dd->m4xen_mask) {
-                       if (dd->last_rounded_m4xen)
-                               v |= dd->m4xen_mask;
-                       else
-                               v &= ~dd->m4xen_mask;
-               }
-
-               if (dd->lpmode_mask) {
-                       if (dd->last_rounded_lpmode)
-                               v |= dd->lpmode_mask;
-                       else
-                               v &= ~dd->lpmode_mask;
-               }
-
-               omap2_clk_writel(v, clk, dd->control_reg);
-       }
-
-       /* We let the clock framework set the other output dividers later */
-
-       /* REVISIT: Set ramp-up delay? */
-
-       _omap3_noncore_dpll_lock(clk);
-
-       return 0;
-}
-
-/* Public functions */
-
-/**
- * omap3_dpll_recalc - recalculate DPLL rate
- * @clk: DPLL struct clk
- *
- * Recalculate and propagate the DPLL rate.
- */
-unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-
-       return omap2_get_dpll_rate(clk);
-}
-
-/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
-
-/**
- * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
- * The choice of modes depends on the DPLL's programmed rate: if it is
- * the same as the DPLL's parent clock, it will enter bypass;
- * otherwise, it will enter lock.  This code will wait for the DPLL to
- * indicate readiness before returning, unless the DPLL takes too long
- * to enter the target state.  Intended to be used as the struct clk's
- * enable function.  If DPLL3 was passed in, or the DPLL does not
- * support low-power stop, or if the DPLL took too long to enter
- * bypass or lock, return -EINVAL; otherwise, return 0.
- */
-int omap3_noncore_dpll_enable(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       int r;
-       struct dpll_data *dd;
-       struct clk_hw *parent;
-
-       dd = clk->dpll_data;
-       if (!dd)
-               return -EINVAL;
-
-       if (clk->clkdm) {
-               r = 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);
-                       return r;
-               }
-       }
-
-       parent = __clk_get_hw(__clk_get_parent(hw->clk));
-
-       if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
-               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
-               r = _omap3_noncore_dpll_bypass(clk);
-       } else {
-               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
-               r = _omap3_noncore_dpll_lock(clk);
-       }
-
-       return r;
-}
-
-/**
- * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enter low-power stop.  This function is
- * intended for use in struct clkops.  No return value.
- */
-void omap3_noncore_dpll_disable(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-
-       _omap3_noncore_dpll_stop(clk);
-       if (clk->clkdm)
-               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
- *
- * 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.
- */
-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)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       struct dpll_data *dd;
-
-       if (!hw || !rate)
-               return -EINVAL;
-
-       dd = clk->dpll_data;
-       if (!dd)
-               return -EINVAL;
-
-       if (__clk_get_rate(dd->clk_bypass) == rate &&
-           (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               *best_parent_clk = __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);
-       }
-
-       *best_parent_rate = rate;
-
-       return rate;
-}
-
-/**
- * omap3_noncore_dpll_set_parent - set parent for a DPLL clock
- * @hw: pointer to the clock to set parent for
- * @index: parent index to select
- *
- * Sets parent for a DPLL clock. This sets the DPLL into bypass or
- * locked mode. Returns 0 with success, negative error value otherwise.
- */
-int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       int ret;
-
-       if (!hw)
-               return -EINVAL;
-
-       if (index)
-               ret = _omap3_noncore_dpll_bypass(clk);
-       else
-               ret = _omap3_noncore_dpll_lock(clk);
-
-       return ret;
-}
-
-/**
- * omap3_noncore_dpll_set_rate - set rate for a DPLL clock
- * @hw: pointer to the clock to set parent for
- * @rate: target rate for the clock
- * @parent_rate: rate of the parent clock
- *
- * Sets rate for a DPLL clock. First checks if the clock parent is
- * reference clock (in bypass mode, the rate of the clock can't be
- * changed) and proceeds with the rate change operation. Returns 0
- * with success, negative error value otherwise.
- */
-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       struct dpll_data *dd;
-       u16 freqsel = 0;
-       int ret;
-
-       if (!hw || !rate)
-               return -EINVAL;
-
-       dd = clk->dpll_data;
-       if (!dd)
-               return -EINVAL;
-
-       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
-           __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) {
-               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);
-
-       ret = omap3_noncore_dpll_program(clk, freqsel);
-
-       return ret;
-}
-
-/**
- * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
- * @hw: pointer to the clock to set rate and parent for
- * @rate: target rate for the DPLL
- * @parent_rate: clock rate of the DPLL parent
- * @index: new parent index for the DPLL, 0 - reference, 1 - bypass
- *
- * Sets rate and parent for a DPLL clock. If new parent is the bypass
- * clock, only selects the parent. Otherwise proceeds with a rate
- * change, as this will effectively also change the parent as the
- * DPLL is put into locked mode. Returns 0 with success, negative error
- * value otherwise.
- */
-int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
-                                          unsigned long rate,
-                                          unsigned long parent_rate,
-                                          u8 index)
-{
-       int ret;
-
-       if (!hw || !rate)
-               return -EINVAL;
-
-       /*
-        * clk-ref at index[0], in which case we only need to set rate,
-        * the parent will be changed automatically with the lock sequence.
-        * With clk-bypass case we only need to change parent.
-        */
-       if (index)
-               ret = omap3_noncore_dpll_set_parent(hw, index);
-       else
-               ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
-
-       return ret;
-}
-
-/* DPLL autoidle read/set code */
-
-/**
- * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
- * @clk: struct clk * of the DPLL to read
- *
- * Return the DPLL's autoidle bits, shifted down to bit 0.  Returns
- * -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)
-{
-       const struct dpll_data *dd;
-       u32 v;
-
-       if (!clk || !clk->dpll_data)
-               return -EINVAL;
-
-       dd = clk->dpll_data;
-
-       if (!dd->autoidle_reg)
-               return -EINVAL;
-
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
-       v &= dd->autoidle_mask;
-       v >>= __ffs(dd->autoidle_mask);
-
-       return v;
-}
-
-/**
- * omap3_dpll_allow_idle - enable DPLL autoidle bits
- * @clk: struct clk * of the DPLL to operate on
- *
- * Enable DPLL automatic idle control.  This automatic idle mode
- * switching takes effect only when the DPLL is locked, at least on
- * 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)
-{
-       const struct dpll_data *dd;
-       u32 v;
-
-       if (!clk || !clk->dpll_data)
-               return;
-
-       dd = clk->dpll_data;
-
-       if (!dd->autoidle_reg)
-               return;
-
-       /*
-        * REVISIT: CORE DPLL can optionally enter low-power bypass
-        * by writing 0x5 instead of 0x1.  Add some mechanism to
-        * optionally enter this mode.
-        */
-       v = omap2_clk_readl(clk, 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);
-
-}
-
-/**
- * omap3_dpll_deny_idle - prevent DPLL from automatically idling
- * @clk: struct clk * of the DPLL to operate on
- *
- * Disable DPLL automatic idle control.  No return value.
- */
-void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
-{
-       const struct dpll_data *dd;
-       u32 v;
-
-       if (!clk || !clk->dpll_data)
-               return;
-
-       dd = clk->dpll_data;
-
-       if (!dd->autoidle_reg)
-               return;
-
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
-       v &= ~dd->autoidle_mask;
-       v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
-       omap2_clk_writel(v, clk, dd->autoidle_reg);
-
-}
-
-/* Clock control for DPLL outputs */
-
-/* Find the parent DPLL for the given clkoutx2 clock */
-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));
-               if (!hw)
-                       break;
-               pclk = to_clk_hw_omap(hw);
-       } while (pclk && !pclk->dpll_data);
-
-       /* clk does not have a DPLL as a parent?  error in the clock data */
-       if (!pclk) {
-               WARN_ON(1);
-               return NULL;
-       }
-
-       return pclk;
-}
-
-/**
- * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
- * @clk: DPLL output struct clk
- *
- * Using parent clock DPLL data, look up DPLL state.  If locked, set our
- * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
- */
-unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
-                                   unsigned long parent_rate)
-{
-       const struct dpll_data *dd;
-       unsigned long rate;
-       u32 v;
-       struct clk_hw_omap *pclk = NULL;
-
-       if (!parent_rate)
-               return 0;
-
-       pclk = omap3_find_clkoutx2_dpll(hw);
-
-       if (!pclk)
-               return 0;
-
-       dd = pclk->dpll_data;
-
-       WARN_ON(!dd->enable_mask);
-
-       v = omap2_clk_readl(pclk, 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;
-       else
-               rate = parent_rate * 2;
-       return rate;
-}
-
-int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long parent_rate)
-{
-       return 0;
-}
-
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *prate)
-{
-       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;
-       }
-
-       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;
-
-               best_parent = (rate / 2);
-               *prate = __clk_round_rate(__clk_get_parent(hw->clk),
-                               best_parent);
-       }
-
-       return *prate * 2;
-}
-
-/* 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,
-};
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
deleted file mode 100644 (file)
index f231be0..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * OMAP4-specific DPLL control functions
- *
- * Copyright (C) 2011 Texas Instruments, Inc.
- * Rajendra Nayak
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-
-#include "clock.h"
-
-/*
- * Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
- * can supported when using the DPLL low-power mode. Frequencies are
- * defined in OMAP4430/60 Public TRM section 3.6.3.3.2 "Enable Control,
- * Status, and Low-Power Operation Mode".
- */
-#define OMAP4_DPLL_LP_FINT_MAX 1000000
-#define OMAP4_DPLL_LP_FOUT_MAX 100000000
-
-/*
- * 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)
-
-/* Static rate multiplier for OMAP4 REGM4XEN clocks */
-#define OMAP4430_REGM4XEN_MULT                         4
-
-void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
-{
-       u32 v;
-       u32 mask;
-
-       if (!clk || !clk->clksel_reg)
-               return;
-
-       mask = clk->flags & CLOCK_CLKOUTX2 ?
-                       OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
-                       OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
-
-       v = omap2_clk_readl(clk, clk->clksel_reg);
-       /* Clear the bit to allow gatectrl */
-       v &= ~mask;
-       omap2_clk_writel(v, clk, clk->clksel_reg);
-}
-
-void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
-{
-       u32 v;
-       u32 mask;
-
-       if (!clk || !clk->clksel_reg)
-               return;
-
-       mask = clk->flags & CLOCK_CLKOUTX2 ?
-                       OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
-                       OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
-
-       v = omap2_clk_readl(clk, clk->clksel_reg);
-       /* Set the bit to deny gatectrl */
-       v |= mask;
-       omap2_clk_writel(v, clk, clk->clksel_reg);
-}
-
-const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
-       .allow_idle     = omap4_dpllmx_allow_gatectrl,
-       .deny_idle      = omap4_dpllmx_deny_gatectrl,
-};
-
-/**
- * omap4_dpll_lpmode_recalc - compute DPLL low-power setting
- * @dd: pointer to the dpll data structure
- *
- * Calculates if low-power mode can be enabled based upon the last
- * multiplier and divider values calculated. If low-power mode can be
- * enabled, then the bit to enable low-power mode is stored in the
- * last_rounded_lpmode variable. This implementation is based upon the
- * criteria for enabling low-power mode as described in the OMAP4430/60
- * Public TRM section 3.6.3.3.2 "Enable Control, Status, and Low-Power
- * Operation Mode".
- */
-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);
-       fout = fint * dd->last_rounded_m;
-
-       if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX))
-               dd->last_rounded_lpmode = 1;
-       else
-               dd->last_rounded_lpmode = 0;
-}
-
-/**
- * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
- * @clk: struct clk * of the DPLL to compute the rate for
- *
- * Compute the output rate for the OMAP4 DPLL represented by @clk.
- * Takes the REGM4XEN bit into consideration, which is needed for the
- * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
- * upon success, or 0 upon error.
- */
-unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-                       unsigned long parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 v;
-       unsigned long rate;
-       struct dpll_data *dd;
-
-       if (!clk || !clk->dpll_data)
-               return 0;
-
-       dd = clk->dpll_data;
-
-       rate = omap2_get_dpll_rate(clk);
-
-       /* regm4xen adds a multiplier of 4 to DPLL calculations */
-       v = omap2_clk_readl(clk, dd->control_reg);
-       if (v & OMAP4430_DPLL_REGM4XEN_MASK)
-               rate *= OMAP4430_REGM4XEN_MULT;
-
-       return rate;
-}
-
-/**
- * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
- * @clk: struct clk * of the DPLL to round a rate for
- * @target_rate: the desired rate of the DPLL
- *
- * Compute the rate that would be programmed into the DPLL hardware
- * for @clk if set_rate() were to be provided with the rate
- * @target_rate.  Takes the REGM4XEN bit into consideration, which is
- * needed for the OMAP4 ABE DPLL.  Returns the rounded rate (before
- * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
- * ~0 if an error occurred in omap2_dpll_round_rate().
- */
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-                                   unsigned long target_rate,
-                                   unsigned long *parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       struct dpll_data *dd;
-       long r;
-
-       if (!clk || !clk->dpll_data)
-               return -EINVAL;
-
-       dd = clk->dpll_data;
-
-       dd->last_rounded_m4xen = 0;
-
-       /*
-        * First try to compute the DPLL configuration for
-        * target rate without using the 4X multiplier.
-        */
-       r = omap2_dpll_round_rate(hw, target_rate, NULL);
-       if (r != ~0)
-               goto out;
-
-       /*
-        * If we did not find a valid DPLL configuration, try again, but
-        * this time see if using the 4X multiplier can help. Enabling the
-        * 4X multiplier is equivalent to dividing the target rate by 4.
-        */
-       r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT,
-                                 NULL);
-       if (r == ~0)
-               return r;
-
-       dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
-       dd->last_rounded_m4xen = 1;
-
-out:
-       omap4_dpll_lpmode_recalc(dd);
-
-       return dd->last_rounded_rate;
-}
-
-/**
- * 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
- *
- * 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.
- */
-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)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       struct dpll_data *dd;
-
-       if (!hw || !rate)
-               return -EINVAL;
-
-       dd = clk->dpll_data;
-       if (!dd)
-               return -EINVAL;
-
-       if (__clk_get_rate(dd->clk_bypass) == rate &&
-           (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               *best_parent_clk = __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);
-       }
-
-       *best_parent_rate = rate;
-
-       return rate;
-}
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 d78c12e7cb5e1ace5f79a9d28f45321e809dea24..de43e4c9a865d5980598a5bc384dd4e5fc403a47 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 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..5a62b18b85001b20171a3ec53dc5bc34980f7839 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,10 +390,9 @@ 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;
        long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
@@ -422,14 +422,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
                }
 
                pr = clk_get_rate(pc);
-               if (pr < rate)
+               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);
 
-                       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 = __clk_get_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 569ee090343fee43c318f7a1bafee0eadb65e1f6..6817b18ed7228490d4773cfd48cc1d9706c56ba5 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 152dcb3f7b5f50c9897f571885029f487c6fcdf0..61566bcefa53399ab3af07611398af3f114849c7 100644 (file)
@@ -116,8 +116,10 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
        h32mxclk->pmc = pmc;
 
        clk = clk_register(NULL, &h32mxclk->hw);
-       if (!clk)
+       if (!clk) {
+               kfree(h32mxclk);
                return;
+       }
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
index c2400456a04471186ec210d8236951d9e4780901..fd7247deabdc3de9cdf8ab0e4fb67d0c6775ef3e 100644 (file)
@@ -171,8 +171,10 @@ at91_clk_register_main_osc(struct at91_pmc *pmc,
        irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
        ret = request_irq(osc->irq, clk_main_osc_irq_handler,
                          IRQF_TRIGGER_HIGH, name, osc);
-       if (ret)
+       if (ret) {
+               kfree(osc);
                return ERR_PTR(ret);
+       }
 
        if (bypass)
                pmc_write(pmc, AT91_CKGR_MOR,
@@ -612,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 f98eafe9b12dc92d1c68f99cd5d9cc86addfb75f..620ea323356b62145c4f7ef7f1d19511c5832015 100644 (file)
@@ -165,12 +165,16 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq,
        irq_set_status_flags(master->irq, IRQ_NOAUTOEN);
        ret = request_irq(master->irq, clk_master_irq_handler,
                          IRQF_TRIGGER_HIGH, "clk-master", master);
-       if (ret)
+       if (ret) {
+               kfree(master);
                return ERR_PTR(ret);
+       }
 
        clk = clk_register(NULL, &master->hw);
-       if (IS_ERR(clk))
+       if (IS_ERR(clk)) {
+               free_irq(master->irq, master);
                kfree(master);
+       }
 
        return clk;
 }
@@ -218,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;
@@ -228,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 cbbe40377ad622a7f9d38aca5651916dda549e54..18b60f4895a68477a74ebe99a8b64542bd7057c9 100644 (file)
@@ -346,12 +346,16 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name,
        irq_set_status_flags(pll->irq, IRQ_NOAUTOEN);
        ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH,
                          id ? "clk-pllb" : "clk-plla", pll);
-       if (ret)
+       if (ret) {
+               kfree(pll);
                return ERR_PTR(ret);
+       }
 
        clk = clk_register(NULL, &pll->hw);
-       if (IS_ERR(clk))
+       if (IS_ERR(clk)) {
+               free_irq(pll->irq, pll);
                kfree(pll);
+       }
 
        return clk;
 }
index 8c86c0f7847a55a0cdc257289c49c67777216d73..ce9c3b9d00f2e8ebeba0ac17104e654e2eb2769a 100644 (file)
@@ -54,12 +54,8 @@ 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;
        long best_rate = -EINVAL;
@@ -76,24 +72,29 @@ static long clk_programmable_determine_rate(struct clk_hw *hw,
                parent_rate = __clk_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 = __clk_get_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 a76d03fd577be05fe86a95d51092380ab01e4eb1..58008b3e8bc175f8befb8126e99e5f55c57d2176 100644 (file)
@@ -130,13 +130,17 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
                irq_set_status_flags(sys->irq, IRQ_NOAUTOEN);
                ret = request_irq(sys->irq, clk_system_irq_handler,
                                IRQF_TRIGGER_HIGH, name, sys);
-               if (ret)
+               if (ret) {
+                       kfree(sys);
                        return ERR_PTR(ret);
+               }
        }
 
        clk = clk_register(NULL, &sys->hw);
-       if (IS_ERR(clk))
+       if (IS_ERR(clk)) {
+               free_irq(sys->irq, sys);
                kfree(sys);
+       }
 
        return clk;
 }
index b0cbd2b1ff5957027a5643963d45038435e8b1ce..1fdf0e33545d3f599bc110777b1dff920a58d44e 100644 (file)
@@ -56,12 +56,8 @@ 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;
        long best_rate = -EINVAL;
@@ -80,23 +76,23 @@ static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
                for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
                        unsigned long tmp_parent_rate;
 
-                       tmp_parent_rate = rate * div;
+                       tmp_parent_rate = req->rate * div;
                        tmp_parent_rate = __clk_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 = __clk_get_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)
@@ -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 ae3263bc14765042d035bea91a476b45655aae75..30dd697b1668bea6d437655d5c7fc825cda3f52a 100644 (file)
@@ -118,12 +118,16 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq,
        irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN);
        ret = request_irq(utmi->irq, clk_utmi_irq_handler,
                          IRQF_TRIGGER_HIGH, "clk-utmi", utmi);
-       if (ret)
+       if (ret) {
+               kfree(utmi);
                return ERR_PTR(ret);
+       }
 
        clk = clk_register(NULL, &utmi->hw);
-       if (IS_ERR(clk))
+       if (IS_ERR(clk)) {
+               free_irq(utmi->irq, utmi);
                kfree(utmi);
+       }
 
        return clk;
 }
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 e19c09cd9645557602840576668fbbc4c18b099d..f630e1bbdcfee9ba2016c856ee7f3b9f449a0205 100644 (file)
@@ -222,10 +222,6 @@ void __init iproc_asiu_setup(struct device_node *node,
                struct iproc_asiu_clk *asiu_clk;
                const char *clk_name;
 
-               clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL);
-               if (WARN_ON(!clk_name))
-                       goto err_clk_register;
-
                ret = of_property_read_string_index(node, "clock-output-names",
                                                    i, &clk_name);
                if (WARN_ON(ret))
@@ -259,7 +255,7 @@ void __init iproc_asiu_setup(struct device_node *node,
 
 err_clk_register:
        for (i = 0; i < num_clks; i++)
-               kfree(asiu->clks[i].name);
+               clk_unregister(asiu->clk_data.clks[i]);
        iounmap(asiu->gate_base);
 
 err_iomap_gate:
index 46fb84bc26740dde1679d7015949977337418561..2dda4e8295a912a4ca28f091fc8a4af86f1c4662 100644 (file)
@@ -366,7 +366,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
        val = readl(pll->pll_base + ctrl->ndiv_int.offset);
        ndiv_int = (val >> ctrl->ndiv_int.shift) &
                bit_mask(ctrl->ndiv_int.width);
-       ndiv = ndiv_int << ctrl->ndiv_int.shift;
+       ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift;
 
        if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
                val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
@@ -374,7 +374,8 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
                        bit_mask(ctrl->ndiv_frac.width);
 
                if (ndiv_frac != 0)
-                       ndiv = (ndiv_int << ctrl->ndiv_int.shift) | ndiv_frac;
+                       ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) |
+                               ndiv_frac;
        }
 
        val = readl(pll->pll_base + ctrl->pdiv.offset);
@@ -655,10 +656,6 @@ void __init iproc_pll_clk_setup(struct device_node *node,
                memset(&init, 0, sizeof(init));
                parent_name = node->name;
 
-               clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL);
-               if (WARN_ON(!clk_name))
-                       goto err_clk_register;
-
                ret = of_property_read_string_index(node, "clock-output-names",
                                                    i, &clk_name);
                if (WARN_ON(ret))
@@ -690,10 +687,8 @@ void __init iproc_pll_clk_setup(struct device_node *node,
        return;
 
 err_clk_register:
-       for (i = 0; i < num_clks; i++) {
-               kfree(pll->clks[i].name);
+       for (i = 0; i < num_clks; i++)
                clk_unregister(pll->clk_data.clks[i]);
-       }
 
 err_pll_register:
        if (pll->asiu_base)
index 79a98506c433bbbbc12bd50d0f7cf82a029d3b8b..05fa322bc5fb73f4e0ddeededbfbf4fe42b4ea0d 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
@@ -1017,10 +1018,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
                                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;
@@ -1029,6 +1028,7 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long best_delta;
        unsigned long best_rate;
        u32 parent_count;
+       long rate;
        u32 which;
 
        /*
@@ -1037,14 +1037,21 @@ 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);
+       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++) {
@@ -1058,17 +1065,19 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
 
                /* 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);
+               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 = __clk_get_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)
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 f01164fada5dafd4e80d0eac8f5f0242847399dd..21830526fd8e98310f9f2e836a24e4634586fb77 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>
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..35ac062d7df65ca07fa71f702cf93f61679b29fa 100644 (file)
@@ -55,11 +55,8 @@ 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;
@@ -71,25 +68,28 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long 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);
+                       req->best_parent_hw = __clk_get_hw(parent);
+                       req->best_parent_rate = __clk_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++) {
@@ -99,34 +99,33 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 
                        parent_rate = __clk_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 = __clk_get_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..2cab88b9c1a814b1f2d24e51d288f3f80a5e0c8b 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,9 +121,10 @@ 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",
@@ -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));
 }
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>
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..41277a1
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * 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 **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 **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 **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 **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 **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 **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..c705cf573569d2b31ac34f34f04cc94b6a1946d4 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>
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..ba7fb1b8c182c6e8e7bbf72b251692beca54f07f 100644 (file)
@@ -246,7 +246,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 +265,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;
 }
index e39e1e680b3c6c09b117e7a32a35b7d1a808bf37..9e6de57eae3b4c3c6e2ffd455bfdb4593be9df02 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>
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 b9b12a742970d5e195f048e571bd5cf7936694e6..3f6f7ad39490458a6e9cdcf4d944665abd34df86 100644 (file)
@@ -268,7 +268,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
        memcpy(table, stm32f42xx_gate_map, sizeof(table));
 
        /* only bits set in table can be used as indices */
-       if (WARN_ON(secondary > 8 * sizeof(table) ||
+       if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
                    0 == (table[BIT_ULL_WORD(secondary)] &
                          BIT_ULL_MASK(secondary))))
                return -EINVAL;
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..4caee93564076c912fa384f752ee24ee4389ff09 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_get_name(hw->clk),
                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_get_name(hw->clk),
                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_get_name(hw->clk));
                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_get_name(hw->clk), &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_get_name(hw->clk), &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_get_name(hw->clk));
                /* 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_get_name(hw->clk));
                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_get_name(hw->clk),
                        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_get_name(hw->clk),
+                       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_get_name(hw->clk), 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_get_name(hw->clk),
                        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..819ffa6db83d7cd0c792262c4705ad6dfa2db1eb 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>
@@ -58,6 +59,8 @@ struct clk_core {
        unsigned long           flags;
        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;
@@ -436,28 +439,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 +473,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 +515,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 +525,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 +771,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 +783,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,15 +818,14 @@ 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);
 
@@ -821,15 +838,20 @@ EXPORT_SYMBOL_GPL(__clk_determine_rate);
  */
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       unsigned long min_rate;
-       unsigned long max_rate;
+       struct clk_rate_request req;
+       int ret;
 
        if (!clk)
                return 0;
 
-       clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+       clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
+       req.rate = rate;
 
-       return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
+       ret = clk_core_round_rate_nolock(clk->core, &req);
+       if (ret)
+               return 0;
+
+       return req.rate;
 }
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
@@ -1249,7 +1271,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 +1291,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;
 
@@ -2479,6 +2509,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 +3086,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 +3136,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 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)
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..155e2e6c83163cdc1634678c037fc79801e77f7f 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"
 
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 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 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 4b9e04cdf7e8e5d7135351db855a8dcfac5e47fb..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>
@@ -700,6 +701,22 @@ static const struct mtk_composite peri_clks[] __initconst = {
        MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
 };
 
+static struct clk_onecell_data *mt8173_top_clk_data __initdata;
+static struct clk_onecell_data *mt8173_pll_clk_data __initdata;
+
+static void __init mtk_clk_enable_critical(void)
+{
+       if (!mt8173_top_clk_data || !mt8173_pll_clk_data)
+               return;
+
+       clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+       clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]);
+       clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]);
+       clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]);
+       clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]);
+       clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]);
+}
+
 static void __init mtk_topckgen_init(struct device_node *node)
 {
        struct clk_onecell_data *clk_data;
@@ -712,19 +729,19 @@ static void __init mtk_topckgen_init(struct device_node *node)
                return;
        }
 
-       clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+       mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
 
        mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
        mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
        mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
                        &mt8173_clk_lock, clk_data);
 
-       clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
-
        r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
        if (r)
                pr_err("%s(): could not register clock provider: %d\n",
                        __func__, r);
+
+       mtk_clk_enable_critical();
 }
 CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
 
@@ -779,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,                                            \
@@ -795,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),
@@ -818,13 +853,13 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
 {
        struct clk_onecell_data *clk_data;
 
-       clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+       mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
        if (!clk_data)
                return;
 
        mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
 
-       clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+       mtk_clk_enable_critical();
 }
 CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
                mtk_apmixedsys_init);
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 de6a873175d2b833f64d95f8e2bf5729da6fd1b4..665cb6794639606595024287a6d38e04592b3669 100644 (file)
@@ -201,11 +201,8 @@ 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;
@@ -221,7 +218,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
        parent = NULL;
        mix_rate_best = 0;
        parent_rate_best = 0;
-       gap_best = rate;
+       gap_best = ULONG_MAX;
        parent_best = NULL;
 
        if (mix->table) {
@@ -233,7 +230,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
                                                        item->parent_index);
                        parent_rate = __clk_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;
@@ -251,7 +248,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
                        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 +262,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 = __clk_get_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,
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..86888a658d4c81ab7f896ec4335b070ea6ea77aa 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>
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 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 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 4b93a1efb36d11fa7171735d29bac283e4bb6d97..c677b9ab53673b1f06b6fb0e2ed4eeeeba584f4a 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 245d5063a385968a5081050b7ef679f86a71b124..a34656bec648b4d7bbd823c118d7b7a24c8f3d7b 100644 (file)
@@ -135,19 +135,23 @@ 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 *parent = __clk_get_parent(hw->clk);
        struct clk_pll *pll = to_clk_pll(hw);
        const struct pll_freq_tbl *f;
 
-       f = find_freq(pll->freq_tbl, rate);
+       req->best_parent_hw = __clk_get_hw(parent);
+       req->best_parent_rate = __clk_get_rate(parent);
+
+       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
@@ -292,3 +296,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..2bc42bb21b3d7e94fa849d2a174687c540f720cf 100644 (file)
@@ -404,13 +404,11 @@ 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;
+       unsigned long clk_flags, rate = req->rate;
        struct clk *p;
        int index;
 
@@ -435,25 +433,24 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
        } else {
                rate =  __clk_get_rate(p);
        }
-       *p_hw = __clk_get_hw(p);
-       *p_rate = rate;
+       req->best_parent_hw = __clk_get_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,13 +461,11 @@ 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;
@@ -478,10 +473,11 @@ static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
        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 = __clk_get_hw(p);
+       req->best_parent_rate = __clk_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 b95d17fbb8d7edb86fa6754d21b47dc6d1e66ee6..db3471eecfeea1f8837e8464839584456d5fae47 100644 (file)
@@ -176,11 +176,10 @@ 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;
+       unsigned long clk_flags, rate = req->rate;
        struct clk *p;
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        int index;
@@ -210,19 +209,19 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
        } else {
                rate =  __clk_get_rate(p);
        }
-       *p_hw = __clk_get_hw(p);
-       *p_rate = rate;
+       req->best_parent_hw = __clk_get_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,34 @@ 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);
+       struct clk *p = clk_get_parent_by_index(hw->clk, index);
 
        /* Force the correct parent */
-       *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, index));
+       req->best_parent_hw = __clk_get_hw(p);
+       req->best_parent_rate = __clk_get_rate(p);
 
-       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 +408,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,9 +428,8 @@ 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;
@@ -439,17 +438,19 @@ static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
        u32 mask = BIT(rcg->hid_width) - 1;
        struct clk *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 = __clk_get_hw(p);
+       req->best_parent_rate = parent_rate = __clk_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 +495,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;
@@ -507,18 +506,19 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
        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_get_hw(parent);
 
        for (; frac->num; frac++) {
-               request = (rate * frac->den) / frac->num;
+               request = (req->rate * frac->den) / frac->num;
 
                src_rate = __clk_round_rate(parent, 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;
@@ -530,19 +530,16 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        struct freq_tbl f = *rcg->freq_tbl;
        const struct frac_entry *frac = frac_table_pixel;
-       unsigned long request, src_rate;
+       unsigned long request;
        int delta = 100000;
        u32 mask = BIT(rcg->hid_width) - 1;
        u32 hid_div;
-       int index = qcom_find_src_index(hw, rcg->parent_map, f.src);
-       struct clk *parent = clk_get_parent_by_index(hw->clk, index);
 
        for (; frac->num; frac++) {
                request = (rate * frac->den) / frac->num;
 
-               src_rate = __clk_round_rate(parent, request);
-               if ((src_rate < (request - delta)) ||
-                       (src_rate > (request + delta)))
+               if ((parent_rate < (request - delta)) ||
+                       (parent_rate > (request + delta)))
                        continue;
 
                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
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..3bf4fb3deef6ab277c3c3f20cf3ee90ca767dea5 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",
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..70316a3a107d546ef1c2629511d846bd1ab3177d 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",
@@ -579,7 +580,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 +710,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 +1386,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 +1429,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..8054fdb
--- /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_get_name(hw->clk));
+               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..77e19097bdc7c9c1b29979ab220f7ccb47662881 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 {
@@ -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..96903ae8b192447ae665a1cf3b783856d614ca99 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)
@@ -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,7 +261,7 @@ 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;
 
@@ -284,13 +283,13 @@ 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",
+       pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
                 __func__, __clk_get_name(hw->clk), drate, rate->nr, nr,
-               rate->no, no, rate->nf, nf, rate->bwadj, bwadj);
+               rate->no, no, rate->nf, nf, rate->nb, nb);
        if (rate->nr != nr || rate->no != no || rate->nf != nf
-                                            || rate->bwadj != bwadj) {
+                                            || rate->nb != nb) {
                struct clk *parent = __clk_get_parent(hw->clk);
                unsigned long prate;
 
index e4f9d472f1ffb52f7ffb5f5061b39d56d519fb89..0abf22d14401230d2adb181e407d862f32dd3d9b 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>
@@ -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,
@@ -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..8e7f36f105c1562ac94f1dfa246ec10567bfbaaf 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
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 1880a90e2ebca600bca7b71722b7550651245dac..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>
index cae2c048488db3e7a4c3545c81faa50f450797d7..65e20eb6356e1a98bb83704cc1beb83734808515 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>
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 d87f34de215220dfa764bf80e655e4124d78cfa2..55b83c7ef878bfa8c3fbb683fc6ba329db4a58c3 100644 (file)
@@ -11,8 +11,6 @@
 */
 
 #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>
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..e9394261f80fda9195f3867f3eb9c47a2bc03a8c 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"
 
index e56df5064889e00530ddf8c531e29539debecc76..71ebad941f86a833a2aefe389480b3b9b4edea78 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"
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..67bf813809c6a93fa464de87d06733a1eaead2ae 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>
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..6810bfb6ef5e09d1a9de91df72f1c91e8f4791c0 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)
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 9fc285d784d3faa4b78eac774cc466b989b8d667..2f64d4beeb527567368170ef93eb5e2b58a23d1b 100644 (file)
@@ -7,6 +7,8 @@
  * Licensed under GPLv2 or later.
  */
 
+#include <linux/clk.h>
+
 #define KHZ     1000
 #define MHZ     (KHZ * KHZ)
 
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..0c66863314933179413b87a2e004c6dbce72cc49 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);
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..aa2741dbe81abb4704ef357ef5fcbed48842ff1a 100644 (file)
@@ -18,7 +18,6 @@
 #define __SOCFPGA_CLK_H
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 
 /* Clock Manager offsets */
 #define CLKMGR_CTRL            0x0
@@ -27,7 +26,6 @@
 #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 4daa5977793ae058803c178581c0dbdc2409b2e9..7cd010f6e12db96b2efc46f5d869088c990357b0 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 5a5c6648308dbc6f8009e6d5702dce3d95572532..eef57a2e39ee141dbcdd1b71c6960bdec5b33b73 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 4f649c9cb094e2c9019cc5528d64819a632e0489..46a4dafe46a75a60b5a227d65eb0fb1dc3f59fb3 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 657ca14ba709a64b97e297e74f15f8f5d751efdf..ec20a2c6f9f3219f17f7b3c89f266bf566b32a0b 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>
@@ -190,7 +191,7 @@ static struct clk *clk_register_flexgen(const char *name,
 
        init.name = name;
        init.ops = &flexgen_ops;
-       init.flags = CLK_IS_BASIC | flexgen_flags;
+       init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE | flexgen_flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
@@ -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;
 }
 
@@ -303,6 +302,8 @@ static void __init st_of_flexgen_setup(struct device_node *np)
        if (!rlock)
                goto err;
 
+       spin_lock_init(rlock);
+
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
                const char *clk_name;
index e94197f04b0b3bae5a811c70e7d91393a2a263c6..aa3117db451436cc8d17c6c12fece15d4397442a 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"
@@ -340,7 +341,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C_407 = {
                    CLKGEN_FIELD(0x30c, 0xf, 20),
                    CLKGEN_FIELD(0x310, 0xf, 20) },
        .lockstatus_present = true,
-       .lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24),
+       .lock_status = CLKGEN_FIELD(0x2f0, 0x1, 24),
        .powerup_polarity = 1,
        .standby_polarity = 1,
        .pll_ops        = &st_quadfs_pll_c32_ops,
@@ -489,7 +490,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw)
        struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
        u32 npda = CLKGEN_READ(pll, npda);
 
-       return !!npda;
+       return pll->data->powerup_polarity ? !npda : !!npda;
 }
 
 static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
@@ -635,7 +636,7 @@ static struct clk * __init st_clk_register_quadfs_pll(
 
        init.name = name;
        init.ops = quadfs->pll_ops;
-       init.flags = CLK_IS_BASIC;
+       init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE;
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
@@ -774,7 +775,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw)
        if (fs->lock)
                spin_lock_irqsave(fs->lock, flags);
 
-       CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity);
+       CLKGEN_WRITE(fs, nsb[fs->chan], fs->data->standby_polarity);
 
        if (fs->lock)
                spin_unlock_irqrestore(fs->lock, flags);
@@ -1082,10 +1083,6 @@ static const struct of_device_id quadfs_of_match[] = {
                .compatible = "st,stih407-quadfs660-D",
                .data = &st_fs660c32_D_407
        },
-       {
-               .compatible = "st,stih407-quadfs660-D",
-               .data = (void *)&st_fs660c32_D_407
-       },
        {}
 };
 
index 4fbe6e099587c0541ce9a22783fb2dc4e4becf8c..81f2372b97ff10187bb3025440546943d1f0d7f7 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;
 }
 
@@ -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,
@@ -237,7 +235,7 @@ static struct clk *clk_register_genamux(const char *name,
 
        init.name = name;
        init.ops = &clkgena_divmux_ops;
-       init.flags = CLK_IS_BASIC;
+       init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
@@ -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,17 +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, 0,
+       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",
@@ -526,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);
 
@@ -582,7 +584,7 @@ static struct clkgen_mux_data stih416_a9_mux_data = {
 };
 static struct clkgen_mux_data stih407_a9_mux_data = {
        .offset = 0x1a4,
-       .shift = 1,
+       .shift = 0,
        .width = 2,
 };
 
@@ -629,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) {
@@ -637,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) {
@@ -649,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,
@@ -665,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);
 
@@ -706,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)
@@ -719,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;
@@ -749,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;
@@ -786,7 +790,8 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
                                             &mux->hw, &clk_mux_ops,
                                             &div->hw, &clk_divider_ops,
                                             &gate->hw, &clk_gate_ops,
-                                            data->clk_flags);
+                                            data->clk_flags |
+                                            CLK_GET_RATE_NOCACHE);
                if (IS_ERR(clk)) {
                        kfree(gate);
                        kfree(div);
@@ -821,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 1065322072136bd90c868f9d6a2fd4c56104f303..cc2b52ec730aac6c89ffff836b447b211929f085 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"
@@ -406,7 +407,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name,
        init.name = clk_name;
        init.ops = pll_data->ops;
 
-       init.flags = CLK_IS_BASIC;
+       init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE;
        init.parent_names = &parent_name;
        init.num_parents  = 1;
 
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..a650eae4cc49d7c8bacda292bd33edf70982dc9d 100644 (file)
@@ -79,11 +79,8 @@ 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;
        int i, num_parents;
@@ -96,24 +93,28 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
                if (!parent)
                        continue;
                if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_round_rate(parent, rate);
+                       parent_rate = __clk_round_rate(parent, req->rate);
                else
                        parent_rate = __clk_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 = __clk_get_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"
 
index 63cf149195ae1a40cb61a7b2256878c0f2ccd5ef..3a2ea010f148f3a1ef73f938f71cb0671b9bf6e5 100644 (file)
@@ -44,17 +44,14 @@ 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);
        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;
@@ -65,7 +62,7 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
 
                parent = clk_get_parent_by_index(hw->clk, i);
                parent_rate = __clk_get_rate(parent);
-               div = DIV_ROUND_UP(parent_rate, rate);
+               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 = __clk_get_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 9a82f17d2d73daf611ac5e8651e35c2101ea6245..1c5b1369e8f3e93a2c083ca8dcdca09554049f8e 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,11 +120,8 @@ 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;
        int i, num_parents;
@@ -135,25 +134,28 @@ static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
                if (!parent)
                        continue;
                if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_round_rate(parent, rate);
+                       parent_rate = __clk_round_rate(parent, req->rate);
                else
                        parent_rate = __clk_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 = __clk_get_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,
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 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..08ae518c995003a878ed3b0fe1399abb143b56ad 100644 (file)
@@ -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_get_rate(hw->clk);
+       return 0;
 }
 
 static u8 emc_get_parent(struct clk_hw *hw)
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..63499c461482ef57863a771748e59d5bbcb15d5a 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"
 
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..ecd7ff736b741d3e671a3bf5220c3d5ddfca53a2 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 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>
index e8cca3eac00742713cc8fe39f9a63c8fe9b62def..0c44cc7f8558dcf9f1b1c24083a94d455d253564 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 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..22aa8b18c840e3c603bfb25d4ca5921e54f663d0 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>
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..24febd4fe3245e6d53e794e5479905bfe08ce011 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
@@ -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;
 
index e75c64c9e81c1d1c3dae2b9779e3538426a66e85..94f0dcd94181da18f275d441eb140a5eef068929 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,47 @@ struct clk_ti_autoidle {
 #define AUTOIDLE_LOW           0x1
 
 static LIST_HEAD(autoidle_clks);
+static LIST_HEAD(clk_hw_omap_clocks);
 
-static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
+/**
+ * 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;
+}
+
+static void _allow_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
@@ -48,7 +89,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 +104,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 +172,67 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
 
        return 0;
 }
+
+/**
+ * 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);
+
+       _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..ace35047783ba99a84b95884294a8d0414c64285 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;
 }
 
 /**
@@ -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..a176b8a
--- /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_get_name(clk->hw.clk));
+       } 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_get_name(hw->clk),
+                            clk->clkdm_name, ret);
+                       return ret;
+               }
+       }
+
+       if (unlikely(!clk->enable_reg)) {
+               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 = 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_get_name(hw->clk));
+               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,
+};
diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c
new file mode 100644 (file)
index 0000000..a01fc7f
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * OMAP2/3/4 DPLL 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.
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/clk/ti.h>
+
+#include <asm/div64.h>
+
+#include "clock.h"
+
+/* DPLL rate rounding: minimum DPLL multiplier, divider values */
+#define DPLL_MIN_MULTIPLIER            2
+#define DPLL_MIN_DIVIDER               1
+
+/* Possible error results from _dpll_test_mult */
+#define DPLL_MULT_UNDERFLOW            -1
+
+/*
+ * Scale factor to mitigate roundoff errors in DPLL rate rounding.
+ * The higher the scale factor, the greater the risk of arithmetic overflow,
+ * but the closer the rounded rate to the target rate.  DPLL_SCALE_FACTOR
+ * must be a power of DPLL_SCALE_BASE.
+ */
+#define DPLL_SCALE_FACTOR              64
+#define DPLL_SCALE_BASE                        2
+#define DPLL_ROUNDING_VAL              ((DPLL_SCALE_BASE / 2) * \
+                                        (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN  500000
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX  2500000
+
+/* _dpll_test_fint() return codes */
+#define DPLL_FINT_UNDERFLOW            -1
+#define DPLL_FINT_INVALID              -2
+
+/* Private functions */
+
+/*
+ * _dpll_test_fint - test whether an Fint value is valid for the DPLL
+ * @clk: DPLL struct clk to test
+ * @n: divider value (N) to test
+ *
+ * Tests whether a particular divider @n will result in a valid DPLL
+ * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter
+ * Correction".  Returns 0 if OK, -1 if the enclosing loop can terminate
+ * (assuming that it is counting N upwards), or -2 if the enclosing loop
+ * should skip to the next iteration (again assuming N is increasing).
+ */
+static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
+{
+       struct dpll_data *dd;
+       long fint, fint_min, fint_max;
+       int ret = 0;
+
+       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;
+
+       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_get_features()->fint_min;
+               fint_max = ti_clk_get_features()->fint_max;
+       }
+
+       if (!fint_min || !fint_max) {
+               WARN(1, "No fint limits available!\n");
+               return DPLL_FINT_INVALID;
+       }
+
+       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_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_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;
+       }
+
+       return ret;
+}
+
+static unsigned long _dpll_compute_new_rate(unsigned long parent_rate,
+                                           unsigned int m, unsigned int n)
+{
+       unsigned long long num;
+
+       num = (unsigned long long)parent_rate * m;
+       do_div(num, n);
+       return num;
+}
+
+/*
+ * _dpll_test_mult - test a DPLL multiplier value
+ * @m: pointer to the DPLL m (multiplier) value under test
+ * @n: current DPLL n (divider) value under test
+ * @new_rate: pointer to storage for the resulting rounded rate
+ * @target_rate: the desired DPLL rate
+ * @parent_rate: the DPLL's parent clock rate
+ *
+ * This code tests a DPLL multiplier value, ensuring that the
+ * resulting rate will not be higher than the target_rate, and that
+ * the multiplier value itself is valid for the DPLL.  Initially, the
+ * integer pointed to by the m argument should be prescaled by
+ * multiplying by DPLL_SCALE_FACTOR.  The code will replace this with
+ * a non-scaled m upon return.  This non-scaled m will result in a
+ * new_rate as close as possible to target_rate (but not greater than
+ * target_rate) given the current (parent_rate, n, prescaled m)
+ * triple. Returns DPLL_MULT_UNDERFLOW in the event that the
+ * non-scaled m attempted to underflow, which can allow the calling
+ * function to bail out early; or 0 upon success.
+ */
+static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
+                          unsigned long target_rate,
+                          unsigned long parent_rate)
+{
+       int r = 0, carry = 0;
+
+       /* Unscale m and round if necessary */
+       if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL)
+               carry = 1;
+       *m = (*m / DPLL_SCALE_FACTOR) + carry;
+
+       /*
+        * The new rate must be <= the target rate to avoid programming
+        * a rate that is impossible for the hardware to handle
+        */
+       *new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
+       if (*new_rate > target_rate) {
+               (*m)--;
+               *new_rate = 0;
+       }
+
+       /* Guard against m underflow */
+       if (*m < DPLL_MIN_MULTIPLIER) {
+               *m = DPLL_MIN_MULTIPLIER;
+               *new_rate = 0;
+               r = DPLL_MULT_UNDERFLOW;
+       }
+
+       if (*new_rate == 0)
+               *new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
+
+       return r;
+}
+
+/**
+ * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not
+ * @v: bitfield value of the DPLL enable
+ *
+ * Checks given DPLL enable bitfield to see whether the DPLL is in bypass
+ * mode or not. Returns 1 if the DPLL is in bypass, 0 otherwise.
+ */
+static int _omap2_dpll_is_in_bypass(u32 v)
+{
+       u8 mask, val;
+
+       mask = ti_clk_get_features()->dpll_bypass_vals;
+
+       /*
+        * Each set bit in the mask corresponds to a bypass value equal
+        * to the bitshift. Go through each set-bit in the mask and
+        * compare against the given register value.
+        */
+       while (mask) {
+               val = __ffs(mask);
+               mask ^= (1 << val);
+               if (v == val)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* Public functions */
+u8 omap2_init_dpll_parent(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       u32 v;
+       struct dpll_data *dd;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       v &= dd->enable_mask;
+       v >>= __ffs(dd->enable_mask);
+
+       /* Reparent the struct clk in case the dpll is in bypass */
+       if (_omap2_dpll_is_in_bypass(v))
+               return 1;
+
+       return 0;
+}
+
+/**
+ * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
+ * @clk: struct clk * of a DPLL
+ *
+ * DPLLs can be locked or bypassed - basically, enabled or disabled.
+ * When locked, the DPLL output depends on the M and N values.  When
+ * bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock
+ * or sys_clk.  Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and
+ * 2 are bypassed with dpll1_fclk and dpll2_fclk respectively
+ * (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk.
+ * Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is
+ * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
+ * if the clock @clk is not a DPLL.
+ */
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
+{
+       long long dpll_clk;
+       u32 dpll_mult, dpll_div, v;
+       struct dpll_data *dd;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return 0;
+
+       /* Return bypass rate if DPLL is bypassed */
+       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);
+
+       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;
+       do_div(dpll_clk, dpll_div + 1);
+
+       return dpll_clk;
+}
+
+/* DPLL rate rounding code */
+
+/**
+ * omap2_dpll_round_rate - round a target rate for an OMAP DPLL
+ * @clk: struct clk * for a DPLL
+ * @target_rate: desired DPLL clock rate
+ *
+ * Given a DPLL and a desired target rate, round the target rate to a
+ * possible, programmable rate for this DPLL.  Attempts to select the
+ * minimum possible n.  Stores the computed (m, n) in the DPLL's
+ * dpll_data structure so set_rate() will not need to call this
+ * (expensive) function again.  Returns ~0 if the target rate cannot
+ * 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)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       int m, n, r, scaled_max_m;
+       int min_delta_m = INT_MAX, min_delta_n = INT_MAX;
+       unsigned long scaled_rt_rp;
+       unsigned long new_rate = 0;
+       struct dpll_data *dd;
+       unsigned long ref_rate;
+       long delta;
+       long prev_min_delta = LONG_MAX;
+       const char *clk_name;
+
+       if (!clk || !clk->dpll_data)
+               return ~0;
+
+       dd = clk->dpll_data;
+
+       ref_rate = __clk_get_rate(dd->clk_ref);
+       clk_name = __clk_get_name(hw->clk);
+       pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n",
+                clk_name, target_rate);
+
+       scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR);
+       scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
+
+       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)
+                       break;
+               else if (r == DPLL_FINT_INVALID)
+                       continue;
+
+               /* Compute the scaled DPLL multiplier, based on the divider */
+               m = scaled_rt_rp * n;
+
+               /*
+                * Since we're counting n up, a m overflow means we
+                * can bail out completely (since as n increases in
+                * the next iteration, there's no way that m can
+                * increase beyond the current m)
+                */
+               if (m > scaled_max_m)
+                       break;
+
+               r = _dpll_test_mult(&m, n, &new_rate, target_rate,
+                                   ref_rate);
+
+               /* m can't be set low enough for this n - try with a larger n */
+               if (r == DPLL_MULT_UNDERFLOW)
+                       continue;
+
+               /* skip rates above our target rate */
+               delta = target_rate - new_rate;
+               if (delta < 0)
+                       continue;
+
+               if (delta < prev_min_delta) {
+                       prev_min_delta = delta;
+                       min_delta_m = m;
+                       min_delta_n = n;
+               }
+
+               pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n",
+                        clk_name, m, n, new_rate);
+
+               if (delta == 0)
+                       break;
+       }
+
+       if (prev_min_delta == LONG_MAX) {
+               pr_debug("clock: %s: cannot round to rate %lu\n",
+                        clk_name, target_rate);
+               return ~0;
+       }
+
+       dd->last_rounded_m = min_delta_m;
+       dd->last_rounded_n = min_delta_n;
+       dd->last_rounded_rate = target_rate - prev_min_delta;
+
+       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..d8aafd3330583789b8be93988dfb7757213a6e89 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 *clk);
+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..08a38c954510b7b8eea332ae30eb82eba2b83057 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_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 (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
+               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+                      __func__, __clk_get_name(hw->clk));
+               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_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 (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
+               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+                      __func__, __clk_get_name(hw->clk));
+               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;
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 2aacf7a3bcaeb137e4e7bb973cea2874ff1aa6a7..3999894149a97f045195d0f144944b169b4f2376 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>
@@ -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;
 
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
new file mode 100644 (file)
index 0000000..b0aa87b
--- /dev/null
@@ -0,0 +1,820 @@
+/*
+ * OMAP3/4 - specific DPLL control functions
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ * Testing and integration fixes by Jouni Högander
+ *
+ * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth
+ * Menon
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/clkdev.h>
+#include <linux/clk/ti.h>
+
+#include "clock.h"
+
+/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
+#define DPLL_AUTOIDLE_DISABLE                  0x0
+#define DPLL_AUTOIDLE_LOW_POWER_STOP           0x1
+
+#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 */
+static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
+{
+       const struct dpll_data *dd;
+       u32 v;
+
+       dd = clk->dpll_data;
+
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       v &= ~dd->enable_mask;
+       v |= clken_bits << __ffs(dd->enable_mask);
+       ti_clk_ll_ops->clk_writel(v, dd->control_reg);
+}
+
+/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
+static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
+{
+       const struct dpll_data *dd;
+       int i = 0;
+       int ret = -EINVAL;
+       const char *clk_name;
+
+       dd = clk->dpll_data;
+       clk_name = __clk_get_name(clk->hw.clk);
+
+       state <<= __ffs(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) {
+               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",
+                        clk_name, (state) ? "locked" : "bypassed", i);
+
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/* From 3430 TRM ES2 4.7.6.2 */
+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;
+
+       pr_debug("clock: fint is %lu\n", fint);
+
+       if (fint >= 750000 && fint <= 1000000)
+               f = 0x3;
+       else if (fint > 1000000 && fint <= 1250000)
+               f = 0x4;
+       else if (fint > 1250000 && fint <= 1500000)
+               f = 0x5;
+       else if (fint > 1500000 && fint <= 1750000)
+               f = 0x6;
+       else if (fint > 1750000 && fint <= 2100000)
+               f = 0x7;
+       else if (fint > 7500000 && fint <= 10000000)
+               f = 0xB;
+       else if (fint > 10000000 && fint <= 12500000)
+               f = 0xC;
+       else if (fint > 12500000 && fint <= 15000000)
+               f = 0xD;
+       else if (fint > 15000000 && fint <= 17500000)
+               f = 0xE;
+       else if (fint > 17500000 && fint <= 21000000)
+               f = 0xF;
+       else
+               pr_debug("clock: unknown freqsel setting for %d\n", n);
+
+       return f;
+}
+
+/*
+ * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to lock.  Waits for the DPLL to report
+ * readiness before returning.  Will save and restore the DPLL's
+ * autoidle state across the enable, per the CDP code.  If the DPLL
+ * locked successfully, return 0; if the DPLL did not lock in the time
+ * allotted, or DPLL3 was passed in, return -EINVAL.
+ */
+static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
+{
+       const struct dpll_data *dd;
+       u8 ai;
+       u8 state = 1;
+       int r = 0;
+
+       pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
+
+       dd = clk->dpll_data;
+       state <<= __ffs(dd->idlest_mask);
+
+       /* Check if already locked */
+       if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) ==
+           state)
+               goto done;
+
+       ai = omap3_dpll_autoidle_read(clk);
+
+       if (ai)
+               omap3_dpll_deny_idle(clk);
+
+       _omap3_dpll_write_clken(clk, DPLL_LOCKED);
+
+       r = _omap3_wait_dpll_status(clk, 1);
+
+       if (ai)
+               omap3_dpll_allow_idle(clk);
+
+done:
+       return r;
+}
+
+/*
+ * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power bypass mode.  In
+ * bypass mode, the DPLL's rate is set equal to its parent clock's
+ * rate.  Waits for the DPLL to report readiness before returning.
+ * Will save and restore the DPLL's autoidle state across the enable,
+ * per the CDP code.  If the DPLL entered bypass mode successfully,
+ * return 0; if the DPLL did not enter bypass in the time allotted, or
+ * DPLL3 was passed in, or the DPLL does not support low-power bypass,
+ * return -EINVAL.
+ */
+static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
+{
+       int r;
+       u8 ai;
+
+       if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
+               return -EINVAL;
+
+       pr_debug("clock: configuring DPLL %s for low-power bypass\n",
+                __clk_get_name(clk->hw.clk));
+
+       ai = omap3_dpll_autoidle_read(clk);
+
+       _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
+
+       r = _omap3_wait_dpll_status(clk, 0);
+
+       if (ai)
+               omap3_dpll_allow_idle(clk);
+
+       return r;
+}
+
+/*
+ * _omap3_noncore_dpll_stop - instruct a DPLL to stop
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power stop. Will save and
+ * restore the DPLL's autoidle state across the stop, per the CDP
+ * code.  If DPLL3 was passed in, or the DPLL does not support
+ * low-power stop, return -EINVAL; otherwise, return 0.
+ */
+static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
+{
+       u8 ai;
+
+       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));
+
+       ai = omap3_dpll_autoidle_read(clk);
+
+       _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
+
+       if (ai)
+               omap3_dpll_allow_idle(clk);
+
+       return 0;
+}
+
+/**
+ * _lookup_dco - Lookup DCO used by j-type DPLL
+ * @clk: pointer to a DPLL struct clk
+ * @dco: digital control oscillator selector
+ * @m: DPLL multiplier to set
+ * @n: DPLL divider to set
+ *
+ * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
+ *
+ * XXX This code is not needed for 3430/AM35xx; can it be optimized
+ * out in non-multi-OMAP builds for those chips?
+ */
+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));
+       fint = (clkinp / n) * m;
+
+       if (fint < 1000000000)
+               *dco = 2;
+       else
+               *dco = 4;
+}
+
+/**
+ * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
+ * @clk: pointer to a DPLL struct clk
+ * @sd_div: target sigma-delta divider
+ * @m: DPLL multiplier to set
+ * @n: DPLL divider to set
+ *
+ * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
+ *
+ * XXX This code is not needed for 3430/AM35xx; can it be optimized
+ * out in non-multi-OMAP builds for those chips?
+ */
+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));
+
+       /*
+        * target sigma-delta to near 250MHz
+        * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
+        */
+       clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */
+       mod1 = (clkinp * m) % (250 * n);
+       sd = (clkinp * m) / (250 * n);
+       mod2 = sd % 10;
+       sd /= 10;
+
+       if (mod1 || mod2)
+               sd++;
+       *sd_div = sd;
+}
+
+/*
+ * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
+ * @clk:       struct clk * of DPLL to set
+ * @freqsel:   FREQSEL value to set
+ *
+ * Program the DPLL with the last M, N values calculated, and wait for
+ * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success.
+ */
+static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
+{
+       struct dpll_data *dd = clk->dpll_data;
+       u8 dco, sd_div;
+       u32 v;
+
+       /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
+       _omap3_noncore_dpll_bypass(clk);
+
+       /*
+        * Set jitter correction. Jitter correction applicable for OMAP343X
+        * only since freqsel field is no longer present on other devices.
+        */
+       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);
+               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
+       }
+
+       /* Set DPLL multiplier, divider */
+       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
+
+       /* Handle Duty Cycle Correction */
+       if (dd->dcc_mask) {
+               if (dd->last_rounded_rate >= dd->dcc_rate)
+                       v |= dd->dcc_mask; /* Enable DCC */
+               else
+                       v &= ~dd->dcc_mask; /* Disable DCC */
+       }
+
+       v &= ~(dd->mult_mask | dd->div1_mask);
+       v |= dd->last_rounded_m << __ffs(dd->mult_mask);
+       v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
+
+       /* Configure dco and sd_div for dplls that have these fields */
+       if (dd->dco_mask) {
+               _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n);
+               v &= ~(dd->dco_mask);
+               v |= dco << __ffs(dd->dco_mask);
+       }
+       if (dd->sddiv_mask) {
+               _lookup_sddiv(clk, &sd_div, dd->last_rounded_m,
+                             dd->last_rounded_n);
+               v &= ~(dd->sddiv_mask);
+               v |= sd_div << __ffs(dd->sddiv_mask);
+       }
+
+       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 = ti_clk_ll_ops->clk_readl(dd->control_reg);
+
+               if (dd->m4xen_mask) {
+                       if (dd->last_rounded_m4xen)
+                               v |= dd->m4xen_mask;
+                       else
+                               v &= ~dd->m4xen_mask;
+               }
+
+               if (dd->lpmode_mask) {
+                       if (dd->last_rounded_lpmode)
+                               v |= dd->lpmode_mask;
+                       else
+                               v &= ~dd->lpmode_mask;
+               }
+
+               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
+       }
+
+       /* We let the clock framework set the other output dividers later */
+
+       /* REVISIT: Set ramp-up delay? */
+
+       _omap3_noncore_dpll_lock(clk);
+
+       return 0;
+}
+
+/* Public functions */
+
+/**
+ * omap3_dpll_recalc - recalculate DPLL rate
+ * @clk: DPLL struct clk
+ *
+ * Recalculate and propagate the DPLL rate.
+ */
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
+       return omap2_get_dpll_rate(clk);
+}
+
+/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
+
+/**
+ * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
+ * The choice of modes depends on the DPLL's programmed rate: if it is
+ * the same as the DPLL's parent clock, it will enter bypass;
+ * otherwise, it will enter lock.  This code will wait for the DPLL to
+ * indicate readiness before returning, unless the DPLL takes too long
+ * to enter the target state.  Intended to be used as the struct clk's
+ * enable function.  If DPLL3 was passed in, or the DPLL does not
+ * support low-power stop, or if the DPLL took too long to enter
+ * bypass or lock, return -EINVAL; otherwise, return 0.
+ */
+int omap3_noncore_dpll_enable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       int r;
+       struct dpll_data *dd;
+       struct clk_hw *parent;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       if (clk->clkdm) {
+               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);
+                       return r;
+               }
+       }
+
+       parent = __clk_get_hw(__clk_get_parent(hw->clk));
+
+       if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
+               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
+               r = _omap3_noncore_dpll_bypass(clk);
+       } else {
+               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
+               r = _omap3_noncore_dpll_lock(clk);
+       }
+
+       return r;
+}
+
+/**
+ * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power stop.  This function is
+ * intended for use in struct clkops.  No return value.
+ */
+void omap3_noncore_dpll_disable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
+       _omap3_noncore_dpll_stop(clk);
+       if (clk->clkdm)
+               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
+ * @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 0 on success, negative error value in failure.
+ */
+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 (!req->rate)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       if (__clk_get_rate(dd->clk_bypass) == req->rate &&
+           (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+               req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
+       } else {
+               req->rate = omap2_dpll_round_rate(hw, req->rate,
+                                         &req->best_parent_rate);
+               req->best_parent_hw = __clk_get_hw(dd->clk_ref);
+       }
+
+       req->best_parent_rate = req->rate;
+
+       return 0;
+}
+
+/**
+ * omap3_noncore_dpll_set_parent - set parent for a DPLL clock
+ * @hw: pointer to the clock to set parent for
+ * @index: parent index to select
+ *
+ * Sets parent for a DPLL clock. This sets the DPLL into bypass or
+ * locked mode. Returns 0 with success, negative error value otherwise.
+ */
+int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       int ret;
+
+       if (!hw)
+               return -EINVAL;
+
+       if (index)
+               ret = _omap3_noncore_dpll_bypass(clk);
+       else
+               ret = _omap3_noncore_dpll_lock(clk);
+
+       return ret;
+}
+
+/**
+ * omap3_noncore_dpll_set_rate - set rate for a DPLL clock
+ * @hw: pointer to the clock to set parent for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Sets rate for a DPLL clock. First checks if the clock parent is
+ * reference clock (in bypass mode, the rate of the clock can't be
+ * changed) and proceeds with the rate change operation. Returns 0
+ * with success, negative error value otherwise.
+ */
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *dd;
+       u16 freqsel = 0;
+       int ret;
+
+       if (!hw || !rate)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+           __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_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);
+
+       ret = omap3_noncore_dpll_program(clk, freqsel);
+
+       return ret;
+}
+
+/**
+ * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
+ * @hw: pointer to the clock to set rate and parent for
+ * @rate: target rate for the DPLL
+ * @parent_rate: clock rate of the DPLL parent
+ * @index: new parent index for the DPLL, 0 - reference, 1 - bypass
+ *
+ * Sets rate and parent for a DPLL clock. If new parent is the bypass
+ * clock, only selects the parent. Otherwise proceeds with a rate
+ * change, as this will effectively also change the parent as the
+ * DPLL is put into locked mode. Returns 0 with success, negative error
+ * value otherwise.
+ */
+int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
+                                          unsigned long rate,
+                                          unsigned long parent_rate,
+                                          u8 index)
+{
+       int ret;
+
+       if (!hw || !rate)
+               return -EINVAL;
+
+       /*
+        * clk-ref at index[0], in which case we only need to set rate,
+        * the parent will be changed automatically with the lock sequence.
+        * With clk-bypass case we only need to change parent.
+        */
+       if (index)
+               ret = omap3_noncore_dpll_set_parent(hw, index);
+       else
+               ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+
+       return ret;
+}
+
+/* DPLL autoidle read/set code */
+
+/**
+ * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
+ * @clk: struct clk * of the DPLL to read
+ *
+ * Return the DPLL's autoidle bits, shifted down to bit 0.  Returns
+ * -EINVAL if passed a null pointer or if the struct clk does not
+ * appear to refer to a DPLL.
+ */
+static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
+{
+       const struct dpll_data *dd;
+       u32 v;
+
+       if (!clk || !clk->dpll_data)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+
+       if (!dd->autoidle_reg)
+               return -EINVAL;
+
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
+       v &= dd->autoidle_mask;
+       v >>= __ffs(dd->autoidle_mask);
+
+       return v;
+}
+
+/**
+ * omap3_dpll_allow_idle - enable DPLL autoidle bits
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Enable DPLL automatic idle control.  This automatic idle mode
+ * switching takes effect only when the DPLL is locked, at least on
+ * OMAP3430.  The DPLL will enter low-power stop when its downstream
+ * clocks are gated.  No return value.
+ */
+static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
+{
+       const struct dpll_data *dd;
+       u32 v;
+
+       if (!clk || !clk->dpll_data)
+               return;
+
+       dd = clk->dpll_data;
+
+       if (!dd->autoidle_reg)
+               return;
+
+       /*
+        * REVISIT: CORE DPLL can optionally enter low-power bypass
+        * by writing 0x5 instead of 0x1.  Add some mechanism to
+        * optionally enter this mode.
+        */
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
+       v &= ~dd->autoidle_mask;
+       v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
+       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
+}
+
+/**
+ * omap3_dpll_deny_idle - prevent DPLL from automatically idling
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Disable DPLL automatic idle control.  No return value.
+ */
+static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
+{
+       const struct dpll_data *dd;
+       u32 v;
+
+       if (!clk || !clk->dpll_data)
+               return;
+
+       dd = clk->dpll_data;
+
+       if (!dd->autoidle_reg)
+               return;
+
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
+       v &= ~dd->autoidle_mask;
+       v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
+       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
+}
+
+/* Clock control for DPLL outputs */
+
+/* Find the parent DPLL for the given clkoutx2 clock */
+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));
+               if (!hw)
+                       break;
+               pclk = to_clk_hw_omap(hw);
+       } while (pclk && !pclk->dpll_data);
+
+       /* clk does not have a DPLL as a parent?  error in the clock data */
+       if (!pclk) {
+               WARN_ON(1);
+               return NULL;
+       }
+
+       return pclk;
+}
+
+/**
+ * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
+ * @clk: DPLL output struct clk
+ *
+ * Using parent clock DPLL data, look up DPLL state.  If locked, set our
+ * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
+ */
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+                                   unsigned long parent_rate)
+{
+       const struct dpll_data *dd;
+       unsigned long rate;
+       u32 v;
+       struct clk_hw_omap *pclk = NULL;
+
+       if (!parent_rate)
+               return 0;
+
+       pclk = omap3_find_clkoutx2_dpll(hw);
+
+       if (!pclk)
+               return 0;
+
+       dd = pclk->dpll_data;
+
+       WARN_ON(!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;
+       else
+               rate = parent_rate * 2;
+       return rate;
+}
+
+/* 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,
+};
+
+/**
+ * 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_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 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_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 omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
+                                                     index);
+}
diff --git a/drivers/clk/ti/dpll44xx.c b/drivers/clk/ti/dpll44xx.c
new file mode 100644 (file)
index 0000000..73af77a
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * OMAP4-specific DPLL control functions
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Rajendra Nayak
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/clk/ti.h>
+
+#include "clock.h"
+
+/*
+ * Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
+ * can supported when using the DPLL low-power mode. Frequencies are
+ * defined in OMAP4430/60 Public TRM section 3.6.3.3.2 "Enable Control,
+ * Status, and Low-Power Operation Mode".
+ */
+#define OMAP4_DPLL_LP_FINT_MAX 1000000
+#define OMAP4_DPLL_LP_FOUT_MAX 100000000
+
+/*
+ * Bitfield declarations
+ */
+#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
+
+static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
+{
+       u32 v;
+       u32 mask;
+
+       if (!clk || !clk->clksel_reg)
+               return;
+
+       mask = clk->flags & CLOCK_CLKOUTX2 ?
+                       OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+                       OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
+       /* Clear the bit to allow gatectrl */
+       v &= ~mask;
+       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
+}
+
+static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
+{
+       u32 v;
+       u32 mask;
+
+       if (!clk || !clk->clksel_reg)
+               return;
+
+       mask = clk->flags & CLOCK_CLKOUTX2 ?
+                       OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+                       OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
+       /* Set the bit to deny gatectrl */
+       v |= mask;
+       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
+}
+
+const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
+       .allow_idle     = omap4_dpllmx_allow_gatectrl,
+       .deny_idle      = omap4_dpllmx_deny_gatectrl,
+};
+
+/**
+ * omap4_dpll_lpmode_recalc - compute DPLL low-power setting
+ * @dd: pointer to the dpll data structure
+ *
+ * Calculates if low-power mode can be enabled based upon the last
+ * multiplier and divider values calculated. If low-power mode can be
+ * enabled, then the bit to enable low-power mode is stored in the
+ * last_rounded_lpmode variable. This implementation is based upon the
+ * criteria for enabling low-power mode as described in the OMAP4430/60
+ * Public TRM section 3.6.3.3.2 "Enable Control, Status, and Low-Power
+ * Operation Mode".
+ */
+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);
+       fout = fint * dd->last_rounded_m;
+
+       if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX))
+               dd->last_rounded_lpmode = 1;
+       else
+               dd->last_rounded_lpmode = 0;
+}
+
+/**
+ * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to compute the rate for
+ *
+ * Compute the output rate for the OMAP4 DPLL represented by @clk.
+ * Takes the REGM4XEN bit into consideration, which is needed for the
+ * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
+ * upon success, or 0 upon error.
+ */
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       u32 v;
+       unsigned long rate;
+       struct dpll_data *dd;
+
+       if (!clk || !clk->dpll_data)
+               return 0;
+
+       dd = clk->dpll_data;
+
+       rate = omap2_get_dpll_rate(clk);
+
+       /* regm4xen adds a multiplier of 4 to DPLL calculations */
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       if (v & OMAP4430_DPLL_REGM4XEN_MASK)
+               rate *= OMAP4430_REGM4XEN_MULT;
+
+       return rate;
+}
+
+/**
+ * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to round a rate for
+ * @target_rate: the desired rate of the DPLL
+ *
+ * Compute the rate that would be programmed into the DPLL hardware
+ * for @clk if set_rate() were to be provided with the rate
+ * @target_rate.  Takes the REGM4XEN bit into consideration, which is
+ * needed for the OMAP4 ABE DPLL.  Returns the rounded rate (before
+ * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
+ * ~0 if an error occurred in omap2_dpll_round_rate().
+ */
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+                                   unsigned long target_rate,
+                                   unsigned long *parent_rate)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *dd;
+       long r;
+
+       if (!clk || !clk->dpll_data)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+
+       dd->last_rounded_m4xen = 0;
+
+       /*
+        * First try to compute the DPLL configuration for
+        * target rate without using the 4X multiplier.
+        */
+       r = omap2_dpll_round_rate(hw, target_rate, NULL);
+       if (r != ~0)
+               goto out;
+
+       /*
+        * If we did not find a valid DPLL configuration, try again, but
+        * this time see if using the 4X multiplier can help. Enabling the
+        * 4X multiplier is equivalent to dividing the target rate by 4.
+        */
+       r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT,
+                                 NULL);
+       if (r == ~0)
+               return r;
+
+       dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
+       dd->last_rounded_m4xen = 1;
+
+out:
+       omap4_dpll_lpmode_recalc(dd);
+
+       return dd->last_rounded_rate;
+}
+
+/**
+ * omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
+ * @hw: pointer to the clock to determine rate for
+ * @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 0 on success and a negative error value otherwise.
+ */
+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 (!req->rate)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       if (__clk_get_rate(dd->clk_bypass) == req->rate &&
+           (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+               req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
+       } else {
+               req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate,
+                                               &req->best_parent_rate);
+               req->best_parent_hw = __clk_get_hw(dd->clk_ref);
+       }
+
+       req->best_parent_rate = req->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 5cdeed538b08a2eec168de48a94399c11af33472..99fe27e8376bfec54b5728687481ab1970e71e0a 100644 (file)
@@ -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 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 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,
index 4626b97b7d83295b06d0259a5f55574572dc6a09..1c7b639d9222bb3ab2370cfef1b2b3058e13edbd 100644 (file)
@@ -7,7 +7,6 @@
  * 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>
index e319ef912dc6c27bbaba940a42a4ef97a5bf07a0..c3e3b20e4b43d0ea36d4b69b97652cad2e61b172 100644 (file)
@@ -8,8 +8,6 @@
  */
 
 #include <linux/of.h>
-#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>
index 20c8add90d110db1575e0ccb5695499581853af5..d0de335ea1e9e31ec3846ff394ceb95828a1b06a 100644 (file)
@@ -7,7 +7,6 @@
  * 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>
index 44794782e7e01681414ad123809bf1b8ce35be0b..179bd3871b348fc84044cad777c2f2dcc9d55c6c 100644 (file)
@@ -7,8 +7,6 @@
  * 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>
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..940cc6f14578b6e6fd1e66fd86584750e77e3c83 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>
index a96dd8e53fdb2d9537a363c480418db859c8c0b1..64b0129a0216f3b8d7bb524b7b1688c9c0228d68 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>
index 7a4f8635bd1eb31ce8bbb68e755f124bd5f12f00..71fa5da89afdb44f7b90c929bf39672f7f4047f0 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>
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 3cfd4357489aba1a5904da3f39d0d12346d2a908..d19d7f28aecb3c5ac9ca6409fc9c8e2e5f7fc180 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/of_device.h>
 #include <linux/module.h>
 #include <linux/spi/pxa2xx_spi.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #include <linux/dmaengine.h>
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 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 78842f46f152694906e0b73f99fd2aa93611e2f7..699a2507517069f18ae2f88d18682a9d5a8df4f5 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 **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
@@ -578,21 +617,14 @@ unsigned long __clk_get_flags(struct clk *clk);
 bool __clk_is_prepared(struct clk *clk);
 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)
 {
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 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>