diff options
Diffstat (limited to 'arch')
43 files changed, 273 insertions, 3674 deletions
diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index b8f81fb418ce..c5fbde3afcf6 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -220,6 +220,13 @@ clocks { compatible = "stericsson,u8500-clks"; + /* + * Registers for the CLKRST block on peripheral + * groups 1, 2, 3, 5, 6, + */ + reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>, + <0x8000f000 0x1000>, <0xa03ff000 0x1000>, + <0xa03cf000 0x1000>; prcmu_clk: prcmu-clock { #clock-cells = <1>; diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 61c03d1fe530..ab0e131587bb 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -241,6 +241,7 @@ compatible = "allwinner,sun4i-a10-axi-gates-clk"; reg = <0x01c2005c 0x4>; clocks = <&axi>; + clock-indices = <0>; clock-output-names = "axi_dram"; }; @@ -257,17 +258,36 @@ compatible = "allwinner,sun4i-a10-ahb-gates-clk"; reg = <0x01c20060 0x8>; clocks = <&ahb>; + clock-indices = <0>, <1>, + <2>, <3>, + <4>, <5>, <6>, + <7>, <8>, <9>, + <10>, <11>, <12>, + <13>, <14>, <16>, + <17>, <18>, <20>, + <21>, <22>, <23>, + <24>, <25>, <26>, + <32>, <33>, <34>, + <35>, <36>, <37>, + <40>, <41>, <43>, + <44>, <45>, + <46>, <47>, + <50>, <52>; clock-output-names = "ahb_usb0", "ahb_ehci0", - "ahb_ohci0", "ahb_ehci1", "ahb_ohci1", "ahb_ss", - "ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1", - "ahb_mmc2", "ahb_mmc3", "ahb_ms", "ahb_nand", - "ahb_sdram", "ahb_ace", "ahb_emac", "ahb_ts", - "ahb_spi0", "ahb_spi1", "ahb_spi2", "ahb_spi3", - "ahb_pata", "ahb_sata", "ahb_gps", "ahb_ve", - "ahb_tvd", "ahb_tve0", "ahb_tve1", "ahb_lcd0", - "ahb_lcd1", "ahb_csi0", "ahb_csi1", "ahb_hdmi", - "ahb_de_be0", "ahb_de_be1", "ahb_de_fe0", - "ahb_de_fe1", "ahb_mp", "ahb_mali400"; + "ahb_ohci0", "ahb_ehci1", + "ahb_ohci1", "ahb_ss", "ahb_dma", + "ahb_bist", "ahb_mmc0", "ahb_mmc1", + "ahb_mmc2", "ahb_mmc3", "ahb_ms", + "ahb_nand", "ahb_sdram", "ahb_ace", + "ahb_emac", "ahb_ts", "ahb_spi0", + "ahb_spi1", "ahb_spi2", "ahb_spi3", + "ahb_pata", "ahb_sata", "ahb_gps", + "ahb_ve", "ahb_tvd", "ahb_tve0", + "ahb_tve1", "ahb_lcd0", "ahb_lcd1", + "ahb_csi0", "ahb_csi1", "ahb_hdmi", + "ahb_de_be0", "ahb_de_be1", + "ahb_de_fe0", "ahb_de_fe1", + "ahb_mp", "ahb_mali400"; }; apb0: apb0@01c20054 { @@ -283,9 +303,14 @@ compatible = "allwinner,sun4i-a10-apb0-gates-clk"; reg = <0x01c20068 0x4>; clocks = <&apb0>; + clock-indices = <0>, <1>, + <2>, <3>, + <5>, <6>, + <7>, <10>; clock-output-names = "apb0_codec", "apb0_spdif", - "apb0_ac97", "apb0_iis", "apb0_pio", "apb0_ir0", - "apb0_ir1", "apb0_keypad"; + "apb0_ac97", "apb0_iis", + "apb0_pio", "apb0_ir0", + "apb0_ir1", "apb0_keypad"; }; apb1: clk@01c20058 { @@ -301,12 +326,22 @@ compatible = "allwinner,sun4i-a10-apb1-gates-clk"; reg = <0x01c2006c 0x4>; clocks = <&apb1>; + clock-indices = <0>, <1>, + <2>, <4>, + <5>, <6>, + <7>, <16>, + <17>, <18>, + <19>, <20>, + <21>, <22>, + <23>; clock-output-names = "apb1_i2c0", "apb1_i2c1", - "apb1_i2c2", "apb1_can", "apb1_scr", - "apb1_ps20", "apb1_ps21", "apb1_uart0", - "apb1_uart1", "apb1_uart2", "apb1_uart3", - "apb1_uart4", "apb1_uart5", "apb1_uart6", - "apb1_uart7"; + "apb1_i2c2", "apb1_can", + "apb1_scr", "apb1_ps20", + "apb1_ps21", "apb1_uart0", + "apb1_uart1", "apb1_uart2", + "apb1_uart3", "apb1_uart4", + "apb1_uart5", "apb1_uart6", + "apb1_uart7"; }; nand_clk: clk@01c20080 { diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index f11efb722bbb..a513b416a807 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -85,6 +85,17 @@ compatible = "allwinner,sun5i-a10s-ahb-gates-clk"; reg = <0x01c20060 0x8>; clocks = <&ahb>; + clock-indices = <0>, <1>, + <2>, <5>, <6>, + <7>, <8>, <9>, + <10>, <13>, + <14>, <17>, <18>, + <20>, <21>, <22>, + <26>, <28>, <32>, + <34>, <36>, <40>, + <43>, <44>, + <46>, <51>, + <52>; clock-output-names = "ahb_usbotg", "ahb_ehci", "ahb_ohci", "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1", @@ -103,6 +114,9 @@ compatible = "allwinner,sun5i-a10s-apb0-gates-clk"; reg = <0x01c20068 0x4>; clocks = <&apb0>; + clock-indices = <0>, <3>, + <5>, <6>, + <10>; clock-output-names = "apb0_codec", "apb0_iis", "apb0_pio", "apb0_ir", "apb0_keypad"; @@ -113,9 +127,14 @@ compatible = "allwinner,sun5i-a10s-apb1-gates-clk"; reg = <0x01c2006c 0x4>; clocks = <&apb1>; + clock-indices = <0>, <1>, + <2>, <16>, + <17>, <18>, + <19>; clock-output-names = "apb1_i2c0", "apb1_i2c1", - "apb1_i2c2", "apb1_uart0", "apb1_uart1", - "apb1_uart2", "apb1_uart3"; + "apb1_i2c2", "apb1_uart0", + "apb1_uart1", "apb1_uart2", + "apb1_uart3"; }; }; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 976d4faa2179..f3631c9c6fa2 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -104,6 +104,16 @@ compatible = "allwinner,sun5i-a13-ahb-gates-clk"; reg = <0x01c20060 0x8>; clocks = <&ahb>; + clock-indices = <0>, <1>, + <2>, <5>, <6>, + <7>, <8>, <9>, + <10>, <13>, + <14>, <20>, + <21>, <22>, + <28>, <32>, <36>, + <40>, <44>, + <46>, <51>, + <52>; clock-output-names = "ahb_usbotg", "ahb_ehci", "ahb_ohci", "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1", @@ -121,6 +131,8 @@ compatible = "allwinner,sun5i-a13-apb0-gates-clk"; reg = <0x01c20068 0x4>; clocks = <&apb0>; + clock-indices = <0>, <5>, + <6>; clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir"; }; @@ -130,8 +142,12 @@ compatible = "allwinner,sun5i-a13-apb1-gates-clk"; reg = <0x01c2006c 0x4>; clocks = <&apb1>; + clock-indices = <0>, <1>, + <2>, <17>, + <19>; clock-output-names = "apb1_i2c0", "apb1_i2c1", - "apb1_i2c2", "apb1_uart1", "apb1_uart3"; + "apb1_i2c2", "apb1_uart1", + "apb1_uart3"; }; }; }; diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 54b097830434..427c0e7289fa 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -178,6 +178,7 @@ compatible = "allwinner,sun4i-a10-axi-gates-clk"; reg = <0x01c2005c 0x4>; clocks = <&axi>; + clock-indices = <0>; clock-output-names = "axi_dram"; }; diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 008047a018cf..3ec456fa03a4 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -252,6 +252,20 @@ compatible = "allwinner,sun6i-a31-ahb1-gates-clk"; reg = <0x01c20060 0x8>; clocks = <&ahb1>; + clock-indices = <1>, <5>, + <6>, <8>, <9>, + <10>, <11>, <12>, + <13>, <14>, + <17>, <18>, <19>, + <20>, <21>, <22>, + <23>, <24>, <26>, + <27>, <29>, + <30>, <31>, <32>, + <36>, <37>, <40>, + <43>, <44>, <45>, + <46>, <47>, <50>, + <52>, <55>, <56>, + <57>, <58>; clock-output-names = "ahb1_mipidsi", "ahb1_ss", "ahb1_dma", "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2", "ahb1_mmc3", "ahb1_nand1", @@ -281,6 +295,9 @@ compatible = "allwinner,sun6i-a31-apb1-gates-clk"; reg = <0x01c20068 0x4>; clocks = <&apb1>; + clock-indices = <0>, <4>, + <5>, <12>, + <13>; clock-output-names = "apb1_codec", "apb1_digital_mic", "apb1_pio", "apb1_daudio0", "apb1_daudio1"; @@ -299,6 +316,10 @@ compatible = "allwinner,sun6i-a31-apb2-gates-clk"; reg = <0x01c2006c 0x4>; clocks = <&apb2>; + clock-indices = <0>, <1>, + <2>, <3>, <16>, + <17>, <18>, <19>, + <20>, <21>; clock-output-names = "apb2_i2c0", "apb2_i2c1", "apb2_i2c2", "apb2_i2c3", "apb2_uart0", "apb2_uart1", @@ -384,6 +405,9 @@ compatible = "allwinner,sun6i-a31-usb-clk"; reg = <0x01c200cc 0x4>; clocks = <&osc24M>; + clock-indices = <8>, <9>, <10>, + <16>, <17>, + <18>; clock-output-names = "usb_phy0", "usb_phy1", "usb_phy2", "usb_ohci0", "usb_ohci1", "usb_ohci2"; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 6a63f30c9a69..ca0b01a96c52 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -267,6 +267,19 @@ compatible = "allwinner,sun7i-a20-ahb-gates-clk"; reg = <0x01c20060 0x8>; clocks = <&ahb>; + clock-indices = <0>, <1>, + <2>, <3>, <4>, + <5>, <6>, <7>, <8>, + <9>, <10>, <11>, <12>, + <13>, <14>, <16>, + <17>, <18>, <20>, <21>, + <22>, <23>, <25>, + <28>, <32>, <33>, <34>, + <35>, <36>, <37>, <40>, + <41>, <42>, <43>, + <44>, <45>, <46>, + <47>, <49>, <50>, + <52>; clock-output-names = "ahb_usb0", "ahb_ehci0", "ahb_ohci0", "ahb_ehci1", "ahb_ohci1", "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0", @@ -295,6 +308,10 @@ compatible = "allwinner,sun7i-a20-apb0-gates-clk"; reg = <0x01c20068 0x4>; clocks = <&apb0>; + clock-indices = <0>, <1>, + <2>, <3>, <4>, + <5>, <6>, <7>, + <8>, <10>; clock-output-names = "apb0_codec", "apb0_spdif", "apb0_ac97", "apb0_iis0", "apb0_iis1", "apb0_pio", "apb0_ir0", "apb0_ir1", @@ -314,6 +331,12 @@ compatible = "allwinner,sun7i-a20-apb1-gates-clk"; reg = <0x01c2006c 0x4>; clocks = <&apb1>; + clock-indices = <0>, <1>, + <2>, <3>, <4>, + <5>, <6>, <7>, + <15>, <16>, <17>, + <18>, <19>, <20>, + <21>, <22>, <23>; clock-output-names = "apb1_i2c0", "apb1_i2c1", "apb1_i2c2", "apb1_i2c3", "apb1_can", "apb1_scr", "apb1_ps20", "apb1_ps21", diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 7abd0ae3143d..c318c770b6c1 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -180,6 +180,15 @@ compatible = "allwinner,sun8i-a23-ahb1-gates-clk"; reg = <0x01c20060 0x8>; clocks = <&ahb1>; + clock-indices = <1>, <6>, + <8>, <9>, <10>, + <13>, <14>, + <19>, <20>, + <21>, <24>, <26>, + <29>, <32>, <36>, + <40>, <44>, <46>, + <52>, <54>, + <57>; clock-output-names = "ahb1_mipidsi", "ahb1_dma", "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2", "ahb1_nand", "ahb1_sdram", @@ -196,6 +205,8 @@ compatible = "allwinner,sun8i-a23-apb1-gates-clk"; reg = <0x01c20068 0x4>; clocks = <&apb1>; + clock-indices = <0>, <5>, + <12>, <13>; clock-output-names = "apb1_codec", "apb1_pio", "apb1_daudio0", "apb1_daudio1"; }; @@ -213,6 +224,10 @@ compatible = "allwinner,sun8i-a23-apb2-gates-clk"; reg = <0x01c2006c 0x4>; clocks = <&apb2>; + clock-indices = <0>, <1>, + <2>, <16>, + <17>, <18>, + <19>, <20>; clock-output-names = "apb2_i2c0", "apb2_i2c1", "apb2_i2c2", "apb2_uart0", "apb2_uart1", "apb2_uart2", diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index a43ad779ee2f..5908e3dcf965 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -277,9 +277,12 @@ compatible = "allwinner,sun9i-a80-ahb0-gates-clk"; reg = <0x06000580 0x4>; clocks = <&ahb0>; - clock-indices = <0>, <1>, <3>, <5>, <8>, <12>, <13>, - <14>, <15>, <16>, <18>, <20>, <21>, - <22>, <23>; + clock-indices = <0>, <1>, <3>, + <5>, <8>, <12>, + <13>, <14>, + <15>, <16>, <18>, + <20>, <21>, <22>, + <23>; clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu", "ahb0_ss", "ahb0_sd", "ahb0_nand1", "ahb0_nand0", "ahb0_sdram", @@ -293,7 +296,10 @@ compatible = "allwinner,sun9i-a80-ahb1-gates-clk"; reg = <0x06000584 0x4>; clocks = <&ahb1>; - clock-indices = <0>, <1>, <17>, <21>, <22>, <23>, <24>; + clock-indices = <0>, <1>, + <17>, <21>, + <22>, <23>, + <24>; clock-output-names = "ahb1_usbotg", "ahb1_usbhci", "ahb1_gmac", "ahb1_msgbox", "ahb1_spinlock", "ahb1_hstimer", @@ -305,8 +311,9 @@ compatible = "allwinner,sun9i-a80-ahb2-gates-clk"; reg = <0x06000588 0x4>; clocks = <&ahb2>; - clock-indices = <0>, <1>, <2>, <4>, <5>, <7>, <8>, - <11>; + clock-indices = <0>, <1>, + <2>, <4>, <5>, + <7>, <8>, <11>; clock-output-names = "ahb2_lcd0", "ahb2_lcd1", "ahb2_edp", "ahb2_csi", "ahb2_hdmi", "ahb2_de", "ahb2_mp", "ahb2_mipi_dsi"; @@ -317,8 +324,10 @@ compatible = "allwinner,sun9i-a80-apb0-gates-clk"; reg = <0x06000590 0x4>; clocks = <&apb0>; - clock-indices = <1>, <5>, <11>, <12>, <13>, <15>, - <17>, <18>, <19>; + clock-indices = <1>, <5>, + <11>, <12>, <13>, + <15>, <17>, <18>, + <19>; clock-output-names = "apb0_spdif", "apb0_pio", "apb0_ac97", "apb0_i2s0", "apb0_i2s1", "apb0_lradc", "apb0_gpadc", "apb0_twd", @@ -330,8 +339,11 @@ compatible = "allwinner,sun9i-a80-apb1-gates-clk"; reg = <0x06000594 0x4>; clocks = <&apb1>; - clock-indices = <0>, <1>, <2>, <3>, <4>, - <16>, <17>, <18>, <19>, <20>, <21>; + clock-indices = <0>, <1>, + <2>, <3>, <4>, + <16>, <17>, + <18>, <19>, + <20>, <21>; clock-output-names = "apb1_i2c0", "apb1_i2c1", "apb1_i2c2", "apb1_i2c3", "apb1_i2c4", "apb1_uart0", "apb1_uart1", diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index eaf58f88ef5d..685826c4a710 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -8,7 +8,6 @@ * Licensed under GPLv2 or later. */ -#include <linux/clk-provider.h> #include <linux/of.h> #include <linux/of_platform.h> diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c index c6bd7c7bd4aa..8cc62150116a 100644 --- a/arch/arm/mach-hisi/hisilicon.c +++ b/arch/arm/mach-hisi/hisilicon.c @@ -11,7 +11,6 @@ * published by the Free Software Foundation. */ -#include <linux/clk-provider.h> #include <linux/clocksource.h> #include <linux/irqchip.h> diff --git a/arch/arm/mach-keystone/pm_domain.c b/arch/arm/mach-keystone/pm_domain.c index edea697e8253..e283939a216f 100644 --- a/arch/arm/mach-keystone/pm_domain.c +++ b/arch/arm/mach-keystone/pm_domain.c @@ -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 = { diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index afee9083ad92..9f739f3cad4c 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -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> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 903c85be2897..7892c7d3b6f4 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -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 diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c index eb69acf21014..3f6521313c93 100644 --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c @@ -23,12 +23,13 @@ #include "clock.h" #include "clock3xxx.h" -#include "clock34xx.h" #include "sdrc.h" #include "sram.h" #define CYCLES_PER_MHZ 1000000 +struct clk *sdrc_ick_p, *arm_fck_p; + /* * CORE DPLL (DPLL3) M2 divider rate programming functions * @@ -60,12 +61,14 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate, if (!clk || !rate) return -EINVAL; - validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); + new_div = DIV_ROUND_UP(parent_rate, rate); + validrate = parent_rate / new_div; + if (validrate != rate) return -EINVAL; - sdrcrate = __clk_get_rate(sdrc_ick_p); - clkrate = __clk_get_rate(hw->clk); + sdrcrate = clk_get_rate(sdrc_ick_p); + clkrate = clk_hw_get_rate(hw); if (rate > clkrate) sdrcrate <<= ((rate / clkrate) >> 1); else @@ -83,7 +86,7 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate, /* * XXX This only needs to be done when the CPU frequency changes */ - _mpurate = __clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ; + _mpurate = clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ; c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT; c += 1; /* for safety */ c *= SDRC_MPURATE_LOOPS; diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c deleted file mode 100644 index 7ee26108ac0d..000000000000 --- a/arch/arm/mach-omap2/clkt_clksel.c +++ /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 index f251a14cbf16..000000000000 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ /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 index 55eb579aeae1..000000000000 --- a/arch/arm/mach-omap2/clkt_iclk.c +++ /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, -}; - - - diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index a699d7169307..acb60ed17273 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -20,12 +20,11 @@ #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> @@ -40,19 +39,8 @@ #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 *)® - 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 *)® - 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; /* @@ -584,178 +133,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 * @core_ck_name: clk name for the on-chip CORE_CLK @@ -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); } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 652ed0ab86ec..67da640ba1c7 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -23,90 +23,6 @@ #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 index cef0c8d1de52..000000000000 --- a/arch/arm/mach-omap2/clock2430.c +++ /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 index b870f6a9e283..000000000000 --- a/arch/arm/mach-omap2/clock2xxx.c +++ /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 index 4596468e50ab..000000000000 --- a/arch/arm/mach-omap2/clock34xx.c +++ /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 index 084ba71b2b31..000000000000 --- a/arch/arm/mach-omap2/clock34xx.h +++ /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 index 4d79ae2c0241..000000000000 --- a/arch/arm/mach-omap2/clock3517.c +++ /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 index ca5e5a64c2e2..000000000000 --- a/arch/arm/mach-omap2/clock3517.h +++ /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 index 91ccb962e09e..000000000000 --- a/arch/arm/mach-omap2/clock36xx.c +++ /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 index 945bb7f083e9..000000000000 --- a/arch/arm/mach-omap2/clock36xx.h +++ /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 index a9e86db5daf9..000000000000 --- a/arch/arm/mach-omap2/clock3xxx.c +++ /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 index 287a46f78d97..000000000000 --- a/arch/arm/mach-omap2/clock44xx.h +++ /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 index 61b60dfb14ce..000000000000 --- a/arch/arm/mach-omap2/clock_common_data.c +++ /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 index 44e57ec225d4..000000000000 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ /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 index f231be05b9a6..000000000000 --- a/arch/arm/mach-omap2/dpll44xx.c +++ /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; -} diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 820dde8b5b04..a253aafbb9a2 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -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) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 486cc4ded190..6ef9e6341d96 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -130,6 +130,7 @@ #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> diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index b1aad7e1426c..2a1a4180d5d0 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -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> diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index 79f033b1ddff..d0871786dd8a 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -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> diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index 16547f2641a3..25d6676f8d6e 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -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> diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 5d1a318f1302..0fa4c5f8b1be 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -8,6 +8,7 @@ menuconfig ARCH_TEGRA select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select PINCTRL + select PM_OPP select ARCH_HAS_RESET_CONTROLLER select RESET_CONTROLLER select SOC_BUS diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index e31d3d61c998..b316e18a76aa 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -72,21 +72,12 @@ void __init ux500_init_irq(void) * Init clocks here so that they are available for system timer * initialization. */ - if (cpu_is_u8500_family()) { - u8500_of_clk_init(U8500_CLKRST1_BASE, - U8500_CLKRST2_BASE, - U8500_CLKRST3_BASE, - U8500_CLKRST5_BASE, - U8500_CLKRST6_BASE); - } else if (cpu_is_u9540()) { - u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE, - U8500_CLKRST3_BASE, U8500_CLKRST5_BASE, - U8500_CLKRST6_BASE); - } else if (cpu_is_u8540()) { - u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE, - U8500_CLKRST3_BASE, U8500_CLKRST5_BASE, - U8500_CLKRST6_BASE); - } + if (cpu_is_u8500_family()) + u8500_clk_init(); + else if (cpu_is_u9540()) + u9540_clk_init(); + else if (cpu_is_u8540()) + u8540_clk_init(); } static const char * __init ux500_get_machine(void) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index f3067d4d4e35..926ae8d9abc5 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -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> diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 6e46abe0dac6..bd34f4093cd9 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -35,6 +35,7 @@ #include <linux/init.h> #include <linux/io.h> +#include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/slab.h> @@ -389,12 +390,11 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, return div1; } -static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_clk, - int scale, int maxdiv) +static int alchemy_clk_fgcs_detr(struct clk_hw *hw, + struct clk_rate_request *req, + int scale, int maxdiv) { - struct clk *pc, *bpc, *free; + struct clk_hw *pc, *bpc, *free; long tdv, tpr, pr, nr, br, bpr, diff, lastdiff; int j; @@ -408,7 +408,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, * the one that gets closest to but not over the requested rate. */ for (j = 0; j < 7; j++) { - pc = clk_get_parent_by_index(hw->clk, j); + pc = clk_hw_get_parent_by_index(hw, j); if (!pc) break; @@ -416,20 +416,20 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, * XXX: we would actually want clk_has_active_children() * but this is a good-enough approximation for now. */ - if (!__clk_is_prepared(pc)) { + if (!clk_hw_is_prepared(pc)) { if (!free) free = pc; } - pr = clk_get_rate(pc); - if (pr < rate) + pr = clk_hw_get_rate(pc); + if (pr < req->rate) continue; /* what can hardware actually provide */ - tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL); + tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL); nr = pr / tdv; - diff = rate - nr; - if (nr > rate) + diff = req->rate - nr; + if (nr > req->rate) continue; if (diff < lastdiff) { @@ -448,15 +448,16 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, */ if (lastdiff && free) { for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) { - tpr = rate * j; + tpr = req->rate * j; if (tpr < 0) break; - pr = clk_round_rate(free, tpr); + pr = clk_hw_round_rate(free, tpr); - tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL); + tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, + NULL); nr = pr / tdv; - diff = rate - nr; - if (nr > rate) + diff = req->rate - nr; + if (nr > req->rate) continue; if (diff < lastdiff) { lastdiff = diff; @@ -469,9 +470,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, } } - *best_parent_rate = bpr; - *best_parent_clk = __clk_get_hw(bpc); - return br; + if (br < 0) + return br; + + req->best_parent_rate = bpr; + req->best_parent_hw = bpc; + req->rate = br; + + return 0; } static int alchemy_clk_fgv1_en(struct clk_hw *hw) @@ -562,14 +568,10 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw, return parent_rate / v; } -static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_clk) +static int alchemy_clk_fgv1_detr(struct clk_hw *hw, + struct clk_rate_request *req) { - return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate, - best_parent_clk, 2, 512); + return alchemy_clk_fgcs_detr(hw, req, 2, 512); } /* Au1000, Au1100, Au15x0, Au12x0 */ @@ -696,11 +698,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw, return t; } -static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_clk) +static int alchemy_clk_fgv2_detr(struct clk_hw *hw, + struct clk_rate_request *req) { struct alchemy_fgcs_clk *c = to_fgcs_clk(hw); int scale, maxdiv; @@ -713,8 +712,7 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate, maxdiv = 512; } - return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate, - best_parent_clk, scale, maxdiv); + return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv); } /* Au1300 larger input mux, no separate disable bit, flexible divider */ @@ -917,17 +915,13 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate, return 0; } -static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_clk) +static int alchemy_clk_csrc_detr(struct clk_hw *hw, + struct clk_rate_request *req) { struct alchemy_fgcs_clk *c = to_fgcs_clk(hw); int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */ - return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate, - best_parent_clk, scale, 4); + return alchemy_clk_fgcs_detr(hw, req, scale, 4); } static struct clk_ops alchemy_clkops_csrc = { diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c index f691bcabd710..c50ea76ba66c 100644 --- a/arch/powerpc/platforms/512x/clock-commonclk.c +++ b/arch/powerpc/platforms/512x/clock-commonclk.c @@ -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> |