Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'clk-for-linus-3.13' of git://git.linaro.org/people/mturquette/linux

Pull clock framework changes from Mike Turquette:
"The clock changes for 3.13 are an even mix of framework improvements &
bug fixes along with updates to existing clock drivers and the
additional of new clock drivers"

* tag 'clk-for-linus-3.13' of git://git.linaro.org/people/mturquette/linux:
clk: new driver for efm32 SoC
clk: of: helper for determining number of parent clocks
clk/zynq: Fix possible memory leak
clk: keystone: Build Keystone clock drivers
clk: keystone: Add gate control clock driver
clk: keystone: add Keystone PLL clock driver
Documentation: Add documentation for APM X-Gene clock binding
clk: arm64: Add DTS clock entry for APM X-Gene Storm SoC
clk: Add APM X-Gene SoC clock driver
clk: wm831x: get rid of the implementation of remove function
clk: Correct lookup logic in clk_fetch_parent_index()
clk: Use kcalloc() to allocate arrays
clk: Add error handling to clk_fetch_parent_index()

+1591 -29
+11
Documentation/devicetree/bindings/clock/efm32-clock.txt
··· 1 + * Clock bindings for Energy Micro efm32 Giant Gecko's Clock Management Unit 2 + 3 + Required properties: 4 + - compatible: Should be "efm32gg,cmu" 5 + - reg: Base address and length of the register set 6 + - interrupts: Interrupt used by the CMU 7 + - #clock-cells: Should be <1> 8 + 9 + The clock consumer should specify the desired clock by having the clock ID in 10 + its "clocks" phandle cell. The header efm32-clk.h contains a list of available 11 + IDs.
+29
Documentation/devicetree/bindings/clock/keystone-gate.txt
··· 1 + Status: Unstable - ABI compatibility may be broken in the future 2 + 3 + Binding for Keystone gate control driver which uses PSC controller IP. 4 + 5 + This binding uses the common clock binding[1]. 6 + 7 + [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 8 + 9 + Required properties: 10 + - compatible : shall be "ti,keystone,psc-clock". 11 + - #clock-cells : from common clock binding; shall be set to 0. 12 + - clocks : parent clock phandle 13 + - reg : psc control and domain address address space 14 + - reg-names : psc control and domain registers 15 + - domain-id : psc domain id needed to check the transition state register 16 + 17 + Optional properties: 18 + - clock-output-names : From common clock binding to override the 19 + default output clock name 20 + Example: 21 + clkusb: clkusb { 22 + #clock-cells = <0>; 23 + compatible = "ti,keystone,psc-clock"; 24 + clocks = <&chipclk16>; 25 + clock-output-names = "usb"; 26 + reg = <0x02350008 0xb00>, <0x02350000 0x400>; 27 + reg-names = "control", "domain"; 28 + domain-id = <0>; 29 + };
+84
Documentation/devicetree/bindings/clock/keystone-pll.txt
··· 1 + Status: Unstable - ABI compatibility may be broken in the future 2 + 3 + Binding for keystone PLLs. The main PLL IP typically has a multiplier, 4 + a divider and a post divider. The additional PLL IPs like ARMPLL, DDRPLL 5 + and PAPLL are controlled by the memory mapped register where as the Main 6 + PLL is controlled by a PLL controller registers along with memory mapped 7 + registers. 8 + 9 + This binding uses the common clock binding[1]. 10 + 11 + [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 12 + 13 + Required properties: 14 + - #clock-cells : from common clock binding; shall be set to 0. 15 + - compatible : shall be "ti,keystone,main-pll-clock" or "ti,keystone,pll-clock" 16 + - clocks : parent clock phandle 17 + - reg - pll control0 and pll multipler registers 18 + - reg-names : control and multiplier. The multiplier is applicable only for 19 + main pll clock 20 + - fixed-postdiv : fixed post divider value 21 + 22 + Example: 23 + mainpllclk: mainpllclk@2310110 { 24 + #clock-cells = <0>; 25 + compatible = "ti,keystone,main-pll-clock"; 26 + clocks = <&refclkmain>; 27 + reg = <0x02620350 4>, <0x02310110 4>; 28 + reg-names = "control", "multiplier"; 29 + fixed-postdiv = <2>; 30 + }; 31 + 32 + papllclk: papllclk@2620358 { 33 + #clock-cells = <0>; 34 + compatible = "ti,keystone,pll-clock"; 35 + clocks = <&refclkmain>; 36 + clock-output-names = "pa-pll-clk"; 37 + reg = <0x02620358 4>; 38 + reg-names = "control"; 39 + fixed-postdiv = <6>; 40 + }; 41 + 42 + Required properties: 43 + - #clock-cells : from common clock binding; shall be set to 0. 44 + - compatible : shall be "ti,keystone,pll-mux-clock" 45 + - clocks : link phandles of parent clocks 46 + - reg - pll mux register 47 + - bit-shift : number of bits to shift the bit-mask 48 + - bit-mask : arbitrary bitmask for programming the mux 49 + 50 + Optional properties: 51 + - clock-output-names : From common clock binding. 52 + 53 + Example: 54 + mainmuxclk: mainmuxclk@2310108 { 55 + #clock-cells = <0>; 56 + compatible = "ti,keystone,pll-mux-clock"; 57 + clocks = <&mainpllclk>, <&refclkmain>; 58 + reg = <0x02310108 4>; 59 + bit-shift = <23>; 60 + bit-mask = <1>; 61 + clock-output-names = "mainmuxclk"; 62 + }; 63 + 64 + Required properties: 65 + - #clock-cells : from common clock binding; shall be set to 0. 66 + - compatible : shall be "ti,keystone,pll-divider-clock" 67 + - clocks : parent clock phandle 68 + - reg - pll mux register 69 + - bit-shift : number of bits to shift the bit-mask 70 + - bit-mask : arbitrary bitmask for programming the divider 71 + 72 + Optional properties: 73 + - clock-output-names : From common clock binding. 74 + 75 + Example: 76 + gemtraceclk: gemtraceclk@2310120 { 77 + #clock-cells = <0>; 78 + compatible = "ti,keystone,pll-divider-clock"; 79 + clocks = <&mainmuxclk>; 80 + reg = <0x02310120 4>; 81 + bit-shift = <0>; 82 + bit-mask = <8>; 83 + clock-output-names = "gemtraceclk"; 84 + };
+111
Documentation/devicetree/bindings/clock/xgene.txt
··· 1 + Device Tree Clock bindings for APM X-Gene 2 + 3 + This binding uses the common clock binding[1]. 4 + 5 + [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 6 + 7 + Required properties: 8 + - compatible : shall be one of the following: 9 + "apm,xgene-socpll-clock" - for a X-Gene SoC PLL clock 10 + "apm,xgene-pcppll-clock" - for a X-Gene PCP PLL clock 11 + "apm,xgene-device-clock" - for a X-Gene device clock 12 + 13 + Required properties for SoC or PCP PLL clocks: 14 + - reg : shall be the physical PLL register address for the pll clock. 15 + - clocks : shall be the input parent clock phandle for the clock. This should 16 + be the reference clock. 17 + - #clock-cells : shall be set to 1. 18 + - clock-output-names : shall be the name of the PLL referenced by derive 19 + clock. 20 + Optional properties for PLL clocks: 21 + - clock-names : shall be the name of the PLL. If missing, use the device name. 22 + 23 + Required properties for device clocks: 24 + - reg : shall be a list of address and length pairs describing the CSR 25 + reset and/or the divider. Either may be omitted, but at least 26 + one must be present. 27 + - reg-names : shall be a string list describing the reg resource. This 28 + may include "csr-reg" and/or "div-reg". If this property 29 + is not present, the reg property is assumed to describe 30 + only "csr-reg". 31 + - clocks : shall be the input parent clock phandle for the clock. 32 + - #clock-cells : shall be set to 1. 33 + - clock-output-names : shall be the name of the device referenced. 34 + Optional properties for device clocks: 35 + - clock-names : shall be the name of the device clock. If missing, use the 36 + device name. 37 + - csr-offset : Offset to the CSR reset register from the reset address base. 38 + Default is 0. 39 + - csr-mask : CSR reset mask bit. Default is 0xF. 40 + - enable-offset : Offset to the enable register from the reset address base. 41 + Default is 0x8. 42 + - enable-mask : CSR enable mask bit. Default is 0xF. 43 + - divider-offset : Offset to the divider CSR register from the divider base. 44 + Default is 0x0. 45 + - divider-width : Width of the divider register. Default is 0. 46 + - divider-shift : Bit shift of the divider register. Default is 0. 47 + 48 + For example: 49 + 50 + pcppll: pcppll@17000100 { 51 + compatible = "apm,xgene-pcppll-clock"; 52 + #clock-cells = <1>; 53 + clocks = <&refclk 0>; 54 + clock-names = "pcppll"; 55 + reg = <0x0 0x17000100 0x0 0x1000>; 56 + clock-output-names = "pcppll"; 57 + type = <0>; 58 + }; 59 + 60 + socpll: socpll@17000120 { 61 + compatible = "apm,xgene-socpll-clock"; 62 + #clock-cells = <1>; 63 + clocks = <&refclk 0>; 64 + clock-names = "socpll"; 65 + reg = <0x0 0x17000120 0x0 0x1000>; 66 + clock-output-names = "socpll"; 67 + type = <1>; 68 + }; 69 + 70 + qmlclk: qmlclk { 71 + compatible = "apm,xgene-device-clock"; 72 + #clock-cells = <1>; 73 + clocks = <&socplldiv2 0>; 74 + clock-names = "qmlclk"; 75 + reg = <0x0 0x1703C000 0x0 0x1000>; 76 + reg-name = "csr-reg"; 77 + clock-output-names = "qmlclk"; 78 + }; 79 + 80 + ethclk: ethclk { 81 + compatible = "apm,xgene-device-clock"; 82 + #clock-cells = <1>; 83 + clocks = <&socplldiv2 0>; 84 + clock-names = "ethclk"; 85 + reg = <0x0 0x17000000 0x0 0x1000>; 86 + reg-names = "div-reg"; 87 + divider-offset = <0x238>; 88 + divider-width = <0x9>; 89 + divider-shift = <0x0>; 90 + clock-output-names = "ethclk"; 91 + }; 92 + 93 + apbclk: apbclk { 94 + compatible = "apm,xgene-device-clock"; 95 + #clock-cells = <1>; 96 + clocks = <&ahbclk 0>; 97 + clock-names = "apbclk"; 98 + reg = <0x0 0x1F2AC000 0x0 0x1000 99 + 0x0 0x1F2AC000 0x0 0x1000>; 100 + reg-names = "csr-reg", "div-reg"; 101 + csr-offset = <0x0>; 102 + csr-mask = <0x200>; 103 + enable-offset = <0x8>; 104 + enable-mask = <0x200>; 105 + divider-offset = <0x10>; 106 + divider-width = <0x2>; 107 + divider-shift = <0x0>; 108 + flags = <0x8>; 109 + clock-output-names = "apbclk"; 110 + }; 111 +
+75
arch/arm64/boot/dts/apm-storm.dtsi
··· 103 103 #size-cells = <2>; 104 104 ranges; 105 105 106 + clocks { 107 + #address-cells = <2>; 108 + #size-cells = <2>; 109 + ranges; 110 + refclk: refclk { 111 + compatible = "fixed-clock"; 112 + #clock-cells = <1>; 113 + clock-frequency = <100000000>; 114 + clock-output-names = "refclk"; 115 + }; 116 + 117 + pcppll: pcppll@17000100 { 118 + compatible = "apm,xgene-pcppll-clock"; 119 + #clock-cells = <1>; 120 + clocks = <&refclk 0>; 121 + clock-names = "pcppll"; 122 + reg = <0x0 0x17000100 0x0 0x1000>; 123 + clock-output-names = "pcppll"; 124 + type = <0>; 125 + }; 126 + 127 + socpll: socpll@17000120 { 128 + compatible = "apm,xgene-socpll-clock"; 129 + #clock-cells = <1>; 130 + clocks = <&refclk 0>; 131 + clock-names = "socpll"; 132 + reg = <0x0 0x17000120 0x0 0x1000>; 133 + clock-output-names = "socpll"; 134 + type = <1>; 135 + }; 136 + 137 + socplldiv2: socplldiv2 { 138 + compatible = "fixed-factor-clock"; 139 + #clock-cells = <1>; 140 + clocks = <&socpll 0>; 141 + clock-names = "socplldiv2"; 142 + clock-mult = <1>; 143 + clock-div = <2>; 144 + clock-output-names = "socplldiv2"; 145 + }; 146 + 147 + qmlclk: qmlclk { 148 + compatible = "apm,xgene-device-clock"; 149 + #clock-cells = <1>; 150 + clocks = <&socplldiv2 0>; 151 + clock-names = "qmlclk"; 152 + reg = <0x0 0x1703C000 0x0 0x1000>; 153 + reg-names = "csr-reg"; 154 + clock-output-names = "qmlclk"; 155 + }; 156 + 157 + ethclk: ethclk { 158 + compatible = "apm,xgene-device-clock"; 159 + #clock-cells = <1>; 160 + clocks = <&socplldiv2 0>; 161 + clock-names = "ethclk"; 162 + reg = <0x0 0x17000000 0x0 0x1000>; 163 + reg-names = "div-reg"; 164 + divider-offset = <0x238>; 165 + divider-width = <0x9>; 166 + divider-shift = <0x0>; 167 + clock-output-names = "ethclk"; 168 + }; 169 + 170 + eth8clk: eth8clk { 171 + compatible = "apm,xgene-device-clock"; 172 + #clock-cells = <1>; 173 + clocks = <&ethclk 0>; 174 + clock-names = "eth8clk"; 175 + reg = <0x0 0x1702C000 0x0 0x1000>; 176 + reg-names = "csr-reg"; 177 + clock-output-names = "eth8clk"; 178 + }; 179 + }; 180 + 106 181 serial0: serial@1c020000 { 107 182 device_type = "serial"; 108 183 compatible = "ns16550";
+14
drivers/clk/Kconfig
··· 93 93 This adds the clock driver support for Freescale PowerPC corenet 94 94 platforms using common clock framework. 95 95 96 + config COMMON_CLK_XGENE 97 + bool "Clock driver for APM XGene SoC" 98 + default y 99 + depends on ARM64 100 + ---help--- 101 + Sypport for the APM X-Gene SoC reference, PLL, and device clocks. 102 + 103 + config COMMON_CLK_KEYSTONE 104 + tristate "Clock drivers for Keystone based SOCs" 105 + depends on ARCH_KEYSTONE && OF 106 + ---help--- 107 + Supports clock drivers for Keystone based SOCs. These SOCs have local 108 + a power sleep control module that gate the clock to the IPs and PLLs. 109 + 96 110 endmenu 97 111 98 112 source "drivers/clk/mvebu/Kconfig"
+3
drivers/clk/Makefile
··· 11 11 12 12 # SoCs specific 13 13 obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o 14 + obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o 14 15 obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o 15 16 obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 16 17 obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o ··· 33 32 obj-$(CONFIG_ARCH_ZYNQ) += zynq/ 34 33 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 35 34 obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ 35 + obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o 36 + obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ 36 37 37 38 obj-$(CONFIG_X86) += x86/ 38 39
+81
drivers/clk/clk-efm32gg.c
··· 1 + /* 2 + * Copyright (C) 2013 Pengutronix 3 + * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> 4 + * 5 + * This program is free software; you can redistribute it and/or modify it under 6 + * the terms of the GNU General Public License version 2 as published by the 7 + * Free Software Foundation. 8 + */ 9 + #include <linux/clk.h> 10 + #include <linux/io.h> 11 + #include <linux/clk-provider.h> 12 + #include <linux/of.h> 13 + #include <linux/of_address.h> 14 + 15 + #include <dt-bindings/clock/efm32-cmu.h> 16 + 17 + #define CMU_HFPERCLKEN0 0x44 18 + 19 + static struct clk *clk[37]; 20 + static struct clk_onecell_data clk_data = { 21 + .clks = clk, 22 + .clk_num = ARRAY_SIZE(clk), 23 + }; 24 + 25 + static int __init efm32gg_cmu_init(struct device_node *np) 26 + { 27 + int i; 28 + void __iomem *base; 29 + 30 + for (i = 0; i < ARRAY_SIZE(clk); ++i) 31 + clk[i] = ERR_PTR(-ENOENT); 32 + 33 + base = of_iomap(np, 0); 34 + if (!base) { 35 + pr_warn("Failed to map address range for efm32gg,cmu node\n"); 36 + return -EADDRNOTAVAIL; 37 + } 38 + 39 + clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL, 40 + CLK_IS_ROOT, 48000000); 41 + 42 + clk[clk_HFPERCLKUSART0] = clk_register_gate(NULL, "HFPERCLK.USART0", 43 + "HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL); 44 + clk[clk_HFPERCLKUSART1] = clk_register_gate(NULL, "HFPERCLK.USART1", 45 + "HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL); 46 + clk[clk_HFPERCLKUSART2] = clk_register_gate(NULL, "HFPERCLK.USART2", 47 + "HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL); 48 + clk[clk_HFPERCLKUART0] = clk_register_gate(NULL, "HFPERCLK.UART0", 49 + "HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL); 50 + clk[clk_HFPERCLKUART1] = clk_register_gate(NULL, "HFPERCLK.UART1", 51 + "HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL); 52 + clk[clk_HFPERCLKTIMER0] = clk_register_gate(NULL, "HFPERCLK.TIMER0", 53 + "HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL); 54 + clk[clk_HFPERCLKTIMER1] = clk_register_gate(NULL, "HFPERCLK.TIMER1", 55 + "HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL); 56 + clk[clk_HFPERCLKTIMER2] = clk_register_gate(NULL, "HFPERCLK.TIMER2", 57 + "HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL); 58 + clk[clk_HFPERCLKTIMER3] = clk_register_gate(NULL, "HFPERCLK.TIMER3", 59 + "HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL); 60 + clk[clk_HFPERCLKACMP0] = clk_register_gate(NULL, "HFPERCLK.ACMP0", 61 + "HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL); 62 + clk[clk_HFPERCLKACMP1] = clk_register_gate(NULL, "HFPERCLK.ACMP1", 63 + "HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL); 64 + clk[clk_HFPERCLKI2C0] = clk_register_gate(NULL, "HFPERCLK.I2C0", 65 + "HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL); 66 + clk[clk_HFPERCLKI2C1] = clk_register_gate(NULL, "HFPERCLK.I2C1", 67 + "HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL); 68 + clk[clk_HFPERCLKGPIO] = clk_register_gate(NULL, "HFPERCLK.GPIO", 69 + "HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL); 70 + clk[clk_HFPERCLKVCMP] = clk_register_gate(NULL, "HFPERCLK.VCMP", 71 + "HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL); 72 + clk[clk_HFPERCLKPRS] = clk_register_gate(NULL, "HFPERCLK.PRS", 73 + "HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL); 74 + clk[clk_HFPERCLKADC0] = clk_register_gate(NULL, "HFPERCLK.ADC0", 75 + "HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL); 76 + clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0", 77 + "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL); 78 + 79 + return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 80 + } 81 + CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init);
-6
drivers/clk/clk-wm831x.c
··· 391 391 return 0; 392 392 } 393 393 394 - static int wm831x_clk_remove(struct platform_device *pdev) 395 - { 396 - return 0; 397 - } 398 - 399 394 static struct platform_driver wm831x_clk_driver = { 400 395 .probe = wm831x_clk_probe, 401 - .remove = wm831x_clk_remove, 402 396 .driver = { 403 397 .name = "wm831x-clk", 404 398 .owner = THIS_MODULE,
+521
drivers/clk/clk-xgene.c
··· 1 + /* 2 + * clk-xgene.c - AppliedMicro X-Gene Clock Interface 3 + * 4 + * Copyright (c) 2013, Applied Micro Circuits Corporation 5 + * Author: Loc Ho <lho@apm.com> 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License as 9 + * published by the Free Software Foundation; either version 2 of 10 + * the License, or (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 + * MA 02111-1307 USA 21 + * 22 + */ 23 + #include <linux/module.h> 24 + #include <linux/spinlock.h> 25 + #include <linux/io.h> 26 + #include <linux/of.h> 27 + #include <linux/clkdev.h> 28 + #include <linux/clk-provider.h> 29 + #include <linux/of_address.h> 30 + #include <asm/setup.h> 31 + 32 + /* Register SCU_PCPPLL bit fields */ 33 + #define N_DIV_RD(src) (((src) & 0x000001ff)) 34 + 35 + /* Register SCU_SOCPLL bit fields */ 36 + #define CLKR_RD(src) (((src) & 0x07000000)>>24) 37 + #define CLKOD_RD(src) (((src) & 0x00300000)>>20) 38 + #define REGSPEC_RESET_F1_MASK 0x00010000 39 + #define CLKF_RD(src) (((src) & 0x000001ff)) 40 + 41 + #define XGENE_CLK_DRIVER_VER "0.1" 42 + 43 + static DEFINE_SPINLOCK(clk_lock); 44 + 45 + static inline u32 xgene_clk_read(void *csr) 46 + { 47 + return readl_relaxed(csr); 48 + } 49 + 50 + static inline void xgene_clk_write(u32 data, void *csr) 51 + { 52 + return writel_relaxed(data, csr); 53 + } 54 + 55 + /* PLL Clock */ 56 + enum xgene_pll_type { 57 + PLL_TYPE_PCP = 0, 58 + PLL_TYPE_SOC = 1, 59 + }; 60 + 61 + struct xgene_clk_pll { 62 + struct clk_hw hw; 63 + const char *name; 64 + void __iomem *reg; 65 + spinlock_t *lock; 66 + u32 pll_offset; 67 + enum xgene_pll_type type; 68 + }; 69 + 70 + #define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw) 71 + 72 + static int xgene_clk_pll_is_enabled(struct clk_hw *hw) 73 + { 74 + struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw); 75 + u32 data; 76 + 77 + data = xgene_clk_read(pllclk->reg + pllclk->pll_offset); 78 + pr_debug("%s pll %s\n", pllclk->name, 79 + data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled"); 80 + 81 + return data & REGSPEC_RESET_F1_MASK ? 0 : 1; 82 + } 83 + 84 + static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw, 85 + unsigned long parent_rate) 86 + { 87 + struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw); 88 + unsigned long fref; 89 + unsigned long fvco; 90 + u32 pll; 91 + u32 nref; 92 + u32 nout; 93 + u32 nfb; 94 + 95 + pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset); 96 + 97 + if (pllclk->type == PLL_TYPE_PCP) { 98 + /* 99 + * PLL VCO = Reference clock * NF 100 + * PCP PLL = PLL_VCO / 2 101 + */ 102 + nout = 2; 103 + fvco = parent_rate * (N_DIV_RD(pll) + 4); 104 + } else { 105 + /* 106 + * Fref = Reference Clock / NREF; 107 + * Fvco = Fref * NFB; 108 + * Fout = Fvco / NOUT; 109 + */ 110 + nref = CLKR_RD(pll) + 1; 111 + nout = CLKOD_RD(pll) + 1; 112 + nfb = CLKF_RD(pll); 113 + fref = parent_rate / nref; 114 + fvco = fref * nfb; 115 + } 116 + pr_debug("%s pll recalc rate %ld parent %ld\n", pllclk->name, 117 + fvco / nout, parent_rate); 118 + 119 + return fvco / nout; 120 + } 121 + 122 + const struct clk_ops xgene_clk_pll_ops = { 123 + .is_enabled = xgene_clk_pll_is_enabled, 124 + .recalc_rate = xgene_clk_pll_recalc_rate, 125 + }; 126 + 127 + static struct clk *xgene_register_clk_pll(struct device *dev, 128 + const char *name, const char *parent_name, 129 + unsigned long flags, void __iomem *reg, u32 pll_offset, 130 + u32 type, spinlock_t *lock) 131 + { 132 + struct xgene_clk_pll *apmclk; 133 + struct clk *clk; 134 + struct clk_init_data init; 135 + 136 + /* allocate the APM clock structure */ 137 + apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL); 138 + if (!apmclk) { 139 + pr_err("%s: could not allocate APM clk\n", __func__); 140 + return ERR_PTR(-ENOMEM); 141 + } 142 + 143 + init.name = name; 144 + init.ops = &xgene_clk_pll_ops; 145 + init.flags = flags; 146 + init.parent_names = parent_name ? &parent_name : NULL; 147 + init.num_parents = parent_name ? 1 : 0; 148 + 149 + apmclk->name = name; 150 + apmclk->reg = reg; 151 + apmclk->lock = lock; 152 + apmclk->pll_offset = pll_offset; 153 + apmclk->type = type; 154 + apmclk->hw.init = &init; 155 + 156 + /* Register the clock */ 157 + clk = clk_register(dev, &apmclk->hw); 158 + if (IS_ERR(clk)) { 159 + pr_err("%s: could not register clk %s\n", __func__, name); 160 + kfree(apmclk); 161 + return NULL; 162 + } 163 + return clk; 164 + } 165 + 166 + static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type) 167 + { 168 + const char *clk_name = np->full_name; 169 + struct clk *clk; 170 + void *reg; 171 + 172 + reg = of_iomap(np, 0); 173 + if (reg == NULL) { 174 + pr_err("Unable to map CSR register for %s\n", np->full_name); 175 + return; 176 + } 177 + of_property_read_string(np, "clock-output-names", &clk_name); 178 + clk = xgene_register_clk_pll(NULL, 179 + clk_name, of_clk_get_parent_name(np, 0), 180 + CLK_IS_ROOT, reg, 0, pll_type, &clk_lock); 181 + if (!IS_ERR(clk)) { 182 + of_clk_add_provider(np, of_clk_src_simple_get, clk); 183 + clk_register_clkdev(clk, clk_name, NULL); 184 + pr_debug("Add %s clock PLL\n", clk_name); 185 + } 186 + } 187 + 188 + static void xgene_socpllclk_init(struct device_node *np) 189 + { 190 + xgene_pllclk_init(np, PLL_TYPE_SOC); 191 + } 192 + 193 + static void xgene_pcppllclk_init(struct device_node *np) 194 + { 195 + xgene_pllclk_init(np, PLL_TYPE_PCP); 196 + } 197 + 198 + /* IP Clock */ 199 + struct xgene_dev_parameters { 200 + void __iomem *csr_reg; /* CSR for IP clock */ 201 + u32 reg_clk_offset; /* Offset to clock enable CSR */ 202 + u32 reg_clk_mask; /* Mask bit for clock enable */ 203 + u32 reg_csr_offset; /* Offset to CSR reset */ 204 + u32 reg_csr_mask; /* Mask bit for disable CSR reset */ 205 + void __iomem *divider_reg; /* CSR for divider */ 206 + u32 reg_divider_offset; /* Offset to divider register */ 207 + u32 reg_divider_shift; /* Bit shift to divider field */ 208 + u32 reg_divider_width; /* Width of the bit to divider field */ 209 + }; 210 + 211 + struct xgene_clk { 212 + struct clk_hw hw; 213 + const char *name; 214 + spinlock_t *lock; 215 + struct xgene_dev_parameters param; 216 + }; 217 + 218 + #define to_xgene_clk(_hw) container_of(_hw, struct xgene_clk, hw) 219 + 220 + static int xgene_clk_enable(struct clk_hw *hw) 221 + { 222 + struct xgene_clk *pclk = to_xgene_clk(hw); 223 + unsigned long flags = 0; 224 + u32 data; 225 + 226 + if (pclk->lock) 227 + spin_lock_irqsave(pclk->lock, flags); 228 + 229 + if (pclk->param.csr_reg != NULL) { 230 + pr_debug("%s clock enabled\n", pclk->name); 231 + /* First enable the clock */ 232 + data = xgene_clk_read(pclk->param.csr_reg + 233 + pclk->param.reg_clk_offset); 234 + data |= pclk->param.reg_clk_mask; 235 + xgene_clk_write(data, pclk->param.csr_reg + 236 + pclk->param.reg_clk_offset); 237 + pr_debug("%s clock PADDR base 0x%016LX clk offset 0x%08X mask 0x%08X value 0x%08X\n", 238 + pclk->name, __pa(pclk->param.csr_reg), 239 + pclk->param.reg_clk_offset, pclk->param.reg_clk_mask, 240 + data); 241 + 242 + /* Second enable the CSR */ 243 + data = xgene_clk_read(pclk->param.csr_reg + 244 + pclk->param.reg_csr_offset); 245 + data &= ~pclk->param.reg_csr_mask; 246 + xgene_clk_write(data, pclk->param.csr_reg + 247 + pclk->param.reg_csr_offset); 248 + pr_debug("%s CSR RESET PADDR base 0x%016LX csr offset 0x%08X mask 0x%08X value 0x%08X\n", 249 + pclk->name, __pa(pclk->param.csr_reg), 250 + pclk->param.reg_csr_offset, pclk->param.reg_csr_mask, 251 + data); 252 + } 253 + 254 + if (pclk->lock) 255 + spin_unlock_irqrestore(pclk->lock, flags); 256 + 257 + return 0; 258 + } 259 + 260 + static void xgene_clk_disable(struct clk_hw *hw) 261 + { 262 + struct xgene_clk *pclk = to_xgene_clk(hw); 263 + unsigned long flags = 0; 264 + u32 data; 265 + 266 + if (pclk->lock) 267 + spin_lock_irqsave(pclk->lock, flags); 268 + 269 + if (pclk->param.csr_reg != NULL) { 270 + pr_debug("%s clock disabled\n", pclk->name); 271 + /* First put the CSR in reset */ 272 + data = xgene_clk_read(pclk->param.csr_reg + 273 + pclk->param.reg_csr_offset); 274 + data |= pclk->param.reg_csr_mask; 275 + xgene_clk_write(data, pclk->param.csr_reg + 276 + pclk->param.reg_csr_offset); 277 + 278 + /* Second disable the clock */ 279 + data = xgene_clk_read(pclk->param.csr_reg + 280 + pclk->param.reg_clk_offset); 281 + data &= ~pclk->param.reg_clk_mask; 282 + xgene_clk_write(data, pclk->param.csr_reg + 283 + pclk->param.reg_clk_offset); 284 + } 285 + 286 + if (pclk->lock) 287 + spin_unlock_irqrestore(pclk->lock, flags); 288 + } 289 + 290 + static int xgene_clk_is_enabled(struct clk_hw *hw) 291 + { 292 + struct xgene_clk *pclk = to_xgene_clk(hw); 293 + u32 data = 0; 294 + 295 + if (pclk->param.csr_reg != NULL) { 296 + pr_debug("%s clock checking\n", pclk->name); 297 + data = xgene_clk_read(pclk->param.csr_reg + 298 + pclk->param.reg_clk_offset); 299 + pr_debug("%s clock is %s\n", pclk->name, 300 + data & pclk->param.reg_clk_mask ? "enabled" : 301 + "disabled"); 302 + } 303 + 304 + if (pclk->param.csr_reg == NULL) 305 + return 1; 306 + return data & pclk->param.reg_clk_mask ? 1 : 0; 307 + } 308 + 309 + static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw, 310 + unsigned long parent_rate) 311 + { 312 + struct xgene_clk *pclk = to_xgene_clk(hw); 313 + u32 data; 314 + 315 + if (pclk->param.divider_reg) { 316 + data = xgene_clk_read(pclk->param.divider_reg + 317 + pclk->param.reg_divider_offset); 318 + data >>= pclk->param.reg_divider_shift; 319 + data &= (1 << pclk->param.reg_divider_width) - 1; 320 + 321 + pr_debug("%s clock recalc rate %ld parent %ld\n", 322 + pclk->name, parent_rate / data, parent_rate); 323 + return parent_rate / data; 324 + } else { 325 + pr_debug("%s clock recalc rate %ld parent %ld\n", 326 + pclk->name, parent_rate, parent_rate); 327 + return parent_rate; 328 + } 329 + } 330 + 331 + static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate, 332 + unsigned long parent_rate) 333 + { 334 + struct xgene_clk *pclk = to_xgene_clk(hw); 335 + unsigned long flags = 0; 336 + u32 data; 337 + u32 divider; 338 + u32 divider_save; 339 + 340 + if (pclk->lock) 341 + spin_lock_irqsave(pclk->lock, flags); 342 + 343 + if (pclk->param.divider_reg) { 344 + /* Let's compute the divider */ 345 + if (rate > parent_rate) 346 + rate = parent_rate; 347 + divider_save = divider = parent_rate / rate; /* Rounded down */ 348 + divider &= (1 << pclk->param.reg_divider_width) - 1; 349 + divider <<= pclk->param.reg_divider_shift; 350 + 351 + /* Set new divider */ 352 + data = xgene_clk_read(pclk->param.divider_reg + 353 + pclk->param.reg_divider_offset); 354 + data &= ~((1 << pclk->param.reg_divider_width) - 1); 355 + data |= divider; 356 + xgene_clk_write(data, pclk->param.divider_reg + 357 + pclk->param.reg_divider_offset); 358 + pr_debug("%s clock set rate %ld\n", pclk->name, 359 + parent_rate / divider_save); 360 + } else { 361 + divider_save = 1; 362 + } 363 + 364 + if (pclk->lock) 365 + spin_unlock_irqrestore(pclk->lock, flags); 366 + 367 + return parent_rate / divider_save; 368 + } 369 + 370 + static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate, 371 + unsigned long *prate) 372 + { 373 + struct xgene_clk *pclk = to_xgene_clk(hw); 374 + unsigned long parent_rate = *prate; 375 + u32 divider; 376 + 377 + if (pclk->param.divider_reg) { 378 + /* Let's compute the divider */ 379 + if (rate > parent_rate) 380 + rate = parent_rate; 381 + divider = parent_rate / rate; /* Rounded down */ 382 + } else { 383 + divider = 1; 384 + } 385 + 386 + return parent_rate / divider; 387 + } 388 + 389 + const struct clk_ops xgene_clk_ops = { 390 + .enable = xgene_clk_enable, 391 + .disable = xgene_clk_disable, 392 + .is_enabled = xgene_clk_is_enabled, 393 + .recalc_rate = xgene_clk_recalc_rate, 394 + .set_rate = xgene_clk_set_rate, 395 + .round_rate = xgene_clk_round_rate, 396 + }; 397 + 398 + static struct clk *xgene_register_clk(struct device *dev, 399 + const char *name, const char *parent_name, 400 + struct xgene_dev_parameters *parameters, spinlock_t *lock) 401 + { 402 + struct xgene_clk *apmclk; 403 + struct clk *clk; 404 + struct clk_init_data init; 405 + int rc; 406 + 407 + /* allocate the APM clock structure */ 408 + apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL); 409 + if (!apmclk) { 410 + pr_err("%s: could not allocate APM clk\n", __func__); 411 + return ERR_PTR(-ENOMEM); 412 + } 413 + 414 + init.name = name; 415 + init.ops = &xgene_clk_ops; 416 + init.flags = 0; 417 + init.parent_names = parent_name ? &parent_name : NULL; 418 + init.num_parents = parent_name ? 1 : 0; 419 + 420 + apmclk->name = name; 421 + apmclk->lock = lock; 422 + apmclk->hw.init = &init; 423 + apmclk->param = *parameters; 424 + 425 + /* Register the clock */ 426 + clk = clk_register(dev, &apmclk->hw); 427 + if (IS_ERR(clk)) { 428 + pr_err("%s: could not register clk %s\n", __func__, name); 429 + kfree(apmclk); 430 + return clk; 431 + } 432 + 433 + /* Register the clock for lookup */ 434 + rc = clk_register_clkdev(clk, name, NULL); 435 + if (rc != 0) { 436 + pr_err("%s: could not register lookup clk %s\n", 437 + __func__, name); 438 + } 439 + return clk; 440 + } 441 + 442 + static void __init xgene_devclk_init(struct device_node *np) 443 + { 444 + const char *clk_name = np->full_name; 445 + struct clk *clk; 446 + struct resource res; 447 + int rc; 448 + struct xgene_dev_parameters parameters; 449 + int i; 450 + 451 + /* Check if the entry is disabled */ 452 + if (!of_device_is_available(np)) 453 + return; 454 + 455 + /* Parse the DTS register for resource */ 456 + parameters.csr_reg = NULL; 457 + parameters.divider_reg = NULL; 458 + for (i = 0; i < 2; i++) { 459 + void *map_res; 460 + rc = of_address_to_resource(np, i, &res); 461 + if (rc != 0) { 462 + if (i == 0) { 463 + pr_err("no DTS register for %s\n", 464 + np->full_name); 465 + return; 466 + } 467 + break; 468 + } 469 + map_res = of_iomap(np, i); 470 + if (map_res == NULL) { 471 + pr_err("Unable to map resource %d for %s\n", 472 + i, np->full_name); 473 + goto err; 474 + } 475 + if (strcmp(res.name, "div-reg") == 0) 476 + parameters.divider_reg = map_res; 477 + else /* if (strcmp(res->name, "csr-reg") == 0) */ 478 + parameters.csr_reg = map_res; 479 + } 480 + if (of_property_read_u32(np, "csr-offset", &parameters.reg_csr_offset)) 481 + parameters.reg_csr_offset = 0; 482 + if (of_property_read_u32(np, "csr-mask", &parameters.reg_csr_mask)) 483 + parameters.reg_csr_mask = 0xF; 484 + if (of_property_read_u32(np, "enable-offset", 485 + &parameters.reg_clk_offset)) 486 + parameters.reg_clk_offset = 0x8; 487 + if (of_property_read_u32(np, "enable-mask", &parameters.reg_clk_mask)) 488 + parameters.reg_clk_mask = 0xF; 489 + if (of_property_read_u32(np, "divider-offset", 490 + &parameters.reg_divider_offset)) 491 + parameters.reg_divider_offset = 0; 492 + if (of_property_read_u32(np, "divider-width", 493 + &parameters.reg_divider_width)) 494 + parameters.reg_divider_width = 0; 495 + if (of_property_read_u32(np, "divider-shift", 496 + &parameters.reg_divider_shift)) 497 + parameters.reg_divider_shift = 0; 498 + of_property_read_string(np, "clock-output-names", &clk_name); 499 + 500 + clk = xgene_register_clk(NULL, clk_name, 501 + of_clk_get_parent_name(np, 0), &parameters, &clk_lock); 502 + if (IS_ERR(clk)) 503 + goto err; 504 + pr_debug("Add %s clock\n", clk_name); 505 + rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); 506 + if (rc != 0) 507 + pr_err("%s: could register provider clk %s\n", __func__, 508 + np->full_name); 509 + 510 + return; 511 + 512 + err: 513 + if (parameters.csr_reg) 514 + iounmap(parameters.csr_reg); 515 + if (parameters.divider_reg) 516 + iounmap(parameters.divider_reg); 517 + } 518 + 519 + CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init); 520 + CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init); 521 + CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);
+34 -22
drivers/clk/clk.c
··· 1080 1080 } 1081 1081 EXPORT_SYMBOL_GPL(clk_get_rate); 1082 1082 1083 - static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) 1083 + static int clk_fetch_parent_index(struct clk *clk, struct clk *parent) 1084 1084 { 1085 - u8 i; 1085 + int i; 1086 1086 1087 - if (!clk->parents) 1088 - clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), 1089 - GFP_KERNEL); 1087 + if (!clk->parents) { 1088 + clk->parents = kcalloc(clk->num_parents, 1089 + sizeof(struct clk *), GFP_KERNEL); 1090 + if (!clk->parents) 1091 + return -ENOMEM; 1092 + } 1090 1093 1091 1094 /* 1092 1095 * find index of new parent clock using cached parent ptrs, ··· 1097 1094 * them now to avoid future calls to __clk_lookup. 1098 1095 */ 1099 1096 for (i = 0; i < clk->num_parents; i++) { 1100 - if (clk->parents && clk->parents[i] == parent) 1101 - break; 1102 - else if (!strcmp(clk->parent_names[i], parent->name)) { 1103 - if (clk->parents) 1104 - clk->parents[i] = __clk_lookup(parent->name); 1105 - break; 1097 + if (clk->parents[i] == parent) 1098 + return i; 1099 + 1100 + if (clk->parents[i]) 1101 + continue; 1102 + 1103 + if (!strcmp(clk->parent_names[i], parent->name)) { 1104 + clk->parents[i] = __clk_lookup(parent->name); 1105 + return i; 1106 1106 } 1107 1107 } 1108 1108 1109 - return i; 1109 + return -EINVAL; 1110 1110 } 1111 1111 1112 1112 static void clk_reparent(struct clk *clk, struct clk *new_parent) ··· 1271 1265 struct clk *old_parent, *parent; 1272 1266 unsigned long best_parent_rate = 0; 1273 1267 unsigned long new_rate; 1274 - u8 p_index = 0; 1268 + int p_index = 0; 1275 1269 1276 1270 /* sanity */ 1277 1271 if (IS_ERR_OR_NULL(clk)) ··· 1312 1306 /* try finding the new parent index */ 1313 1307 if (parent) { 1314 1308 p_index = clk_fetch_parent_index(clk, parent); 1315 - if (p_index == clk->num_parents) { 1309 + if (p_index < 0) { 1316 1310 pr_debug("%s: clk %s can not be parent of clk %s\n", 1317 1311 __func__, parent->name, clk->name); 1318 1312 return NULL; ··· 1538 1532 1539 1533 if (!clk->parents) 1540 1534 clk->parents = 1541 - kzalloc((sizeof(struct clk*) * clk->num_parents), 1535 + kcalloc(clk->num_parents, sizeof(struct clk *), 1542 1536 GFP_KERNEL); 1543 1537 1544 1538 ret = clk_get_parent_by_index(clk, index); ··· 1574 1568 int clk_set_parent(struct clk *clk, struct clk *parent) 1575 1569 { 1576 1570 int ret = 0; 1577 - u8 p_index = 0; 1571 + int p_index = 0; 1578 1572 unsigned long p_rate = 0; 1579 1573 1580 1574 if (!clk) ··· 1603 1597 if (parent) { 1604 1598 p_index = clk_fetch_parent_index(clk, parent); 1605 1599 p_rate = parent->rate; 1606 - if (p_index == clk->num_parents) { 1600 + if (p_index < 0) { 1607 1601 pr_debug("%s: clk %s can not be parent of clk %s\n", 1608 1602 __func__, parent->name, clk->name); 1609 - ret = -EINVAL; 1603 + ret = p_index; 1610 1604 goto out; 1611 1605 } 1612 1606 } ··· 1695 1689 * for clock drivers to statically initialize clk->parents. 1696 1690 */ 1697 1691 if (clk->num_parents > 1 && !clk->parents) { 1698 - clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), 1699 - GFP_KERNEL); 1692 + clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *), 1693 + GFP_KERNEL); 1700 1694 /* 1701 1695 * __clk_lookup returns NULL for parents that have not been 1702 1696 * clk_init'd; thus any access to clk->parents[] must check ··· 1836 1830 hw->clk = clk; 1837 1831 1838 1832 /* allocate local copy in case parent_names is __initdata */ 1839 - clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents), 1840 - GFP_KERNEL); 1833 + clk->parent_names = kcalloc(clk->num_parents, sizeof(char *), 1834 + GFP_KERNEL); 1841 1835 1842 1836 if (!clk->parent_names) { 1843 1837 pr_err("%s: could not allocate clk->parent_names\n", __func__); ··· 2201 2195 2202 2196 return clk; 2203 2197 } 2198 + 2199 + int of_clk_get_parent_count(struct device_node *np) 2200 + { 2201 + return of_count_phandle_with_args(np, "clocks", "#clock-cells"); 2202 + } 2203 + EXPORT_SYMBOL_GPL(of_clk_get_parent_count); 2204 2204 2205 2205 const char *of_clk_get_parent_name(struct device_node *np, int index) 2206 2206 {
+1
drivers/clk/keystone/Makefile
··· 1 + obj-y += pll.o gate.o
+264
drivers/clk/keystone/gate.c
··· 1 + /* 2 + * Clock driver for Keystone 2 based devices 3 + * 4 + * Copyright (C) 2013 Texas Instruments. 5 + * Murali Karicheri <m-karicheri2@ti.com> 6 + * Santosh Shilimkar <santosh.shilimkar@ti.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + #include <linux/clk.h> 14 + #include <linux/clk-provider.h> 15 + #include <linux/err.h> 16 + #include <linux/io.h> 17 + #include <linux/slab.h> 18 + #include <linux/of_address.h> 19 + #include <linux/of.h> 20 + #include <linux/module.h> 21 + 22 + /* PSC register offsets */ 23 + #define PTCMD 0x120 24 + #define PTSTAT 0x128 25 + #define PDSTAT 0x200 26 + #define PDCTL 0x300 27 + #define MDSTAT 0x800 28 + #define MDCTL 0xa00 29 + 30 + /* PSC module states */ 31 + #define PSC_STATE_SWRSTDISABLE 0 32 + #define PSC_STATE_SYNCRST 1 33 + #define PSC_STATE_DISABLE 2 34 + #define PSC_STATE_ENABLE 3 35 + 36 + #define MDSTAT_STATE_MASK 0x3f 37 + #define MDSTAT_MCKOUT BIT(12) 38 + #define PDSTAT_STATE_MASK 0x1f 39 + #define MDCTL_FORCE BIT(31) 40 + #define MDCTL_LRESET BIT(8) 41 + #define PDCTL_NEXT BIT(0) 42 + 43 + /* Maximum timeout to bail out state transition for module */ 44 + #define STATE_TRANS_MAX_COUNT 0xffff 45 + 46 + static void __iomem *domain_transition_base; 47 + 48 + /** 49 + * struct clk_psc_data - PSC data 50 + * @control_base: Base address for a PSC control 51 + * @domain_base: Base address for a PSC domain 52 + * @domain_id: PSC domain id number 53 + */ 54 + struct clk_psc_data { 55 + void __iomem *control_base; 56 + void __iomem *domain_base; 57 + u32 domain_id; 58 + }; 59 + 60 + /** 61 + * struct clk_psc - PSC clock structure 62 + * @hw: clk_hw for the psc 63 + * @psc_data: PSC driver specific data 64 + * @lock: Spinlock used by the driver 65 + */ 66 + struct clk_psc { 67 + struct clk_hw hw; 68 + struct clk_psc_data *psc_data; 69 + spinlock_t *lock; 70 + }; 71 + 72 + static DEFINE_SPINLOCK(psc_lock); 73 + 74 + #define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw) 75 + 76 + static void psc_config(void __iomem *control_base, void __iomem *domain_base, 77 + u32 next_state, u32 domain_id) 78 + { 79 + u32 ptcmd, pdstat, pdctl, mdstat, mdctl, ptstat; 80 + u32 count = STATE_TRANS_MAX_COUNT; 81 + 82 + mdctl = readl(control_base + MDCTL); 83 + mdctl &= ~MDSTAT_STATE_MASK; 84 + mdctl |= next_state; 85 + /* For disable, we always put the module in local reset */ 86 + if (next_state == PSC_STATE_DISABLE) 87 + mdctl &= ~MDCTL_LRESET; 88 + writel(mdctl, control_base + MDCTL); 89 + 90 + pdstat = readl(domain_base + PDSTAT); 91 + if (!(pdstat & PDSTAT_STATE_MASK)) { 92 + pdctl = readl(domain_base + PDCTL); 93 + pdctl |= PDCTL_NEXT; 94 + writel(pdctl, domain_base + PDCTL); 95 + } 96 + 97 + ptcmd = 1 << domain_id; 98 + writel(ptcmd, domain_transition_base + PTCMD); 99 + do { 100 + ptstat = readl(domain_transition_base + PTSTAT); 101 + } while (((ptstat >> domain_id) & 1) && count--); 102 + 103 + count = STATE_TRANS_MAX_COUNT; 104 + do { 105 + mdstat = readl(control_base + MDSTAT); 106 + } while (!((mdstat & MDSTAT_STATE_MASK) == next_state) && count--); 107 + } 108 + 109 + static int keystone_clk_is_enabled(struct clk_hw *hw) 110 + { 111 + struct clk_psc *psc = to_clk_psc(hw); 112 + struct clk_psc_data *data = psc->psc_data; 113 + u32 mdstat = readl(data->control_base + MDSTAT); 114 + 115 + return (mdstat & MDSTAT_MCKOUT) ? 1 : 0; 116 + } 117 + 118 + static int keystone_clk_enable(struct clk_hw *hw) 119 + { 120 + struct clk_psc *psc = to_clk_psc(hw); 121 + struct clk_psc_data *data = psc->psc_data; 122 + unsigned long flags = 0; 123 + 124 + if (psc->lock) 125 + spin_lock_irqsave(psc->lock, flags); 126 + 127 + psc_config(data->control_base, data->domain_base, 128 + PSC_STATE_ENABLE, data->domain_id); 129 + 130 + if (psc->lock) 131 + spin_unlock_irqrestore(psc->lock, flags); 132 + 133 + return 0; 134 + } 135 + 136 + static void keystone_clk_disable(struct clk_hw *hw) 137 + { 138 + struct clk_psc *psc = to_clk_psc(hw); 139 + struct clk_psc_data *data = psc->psc_data; 140 + unsigned long flags = 0; 141 + 142 + if (psc->lock) 143 + spin_lock_irqsave(psc->lock, flags); 144 + 145 + psc_config(data->control_base, data->domain_base, 146 + PSC_STATE_DISABLE, data->domain_id); 147 + 148 + if (psc->lock) 149 + spin_unlock_irqrestore(psc->lock, flags); 150 + } 151 + 152 + static const struct clk_ops clk_psc_ops = { 153 + .enable = keystone_clk_enable, 154 + .disable = keystone_clk_disable, 155 + .is_enabled = keystone_clk_is_enabled, 156 + }; 157 + 158 + /** 159 + * clk_register_psc - register psc clock 160 + * @dev: device that is registering this clock 161 + * @name: name of this clock 162 + * @parent_name: name of clock's parent 163 + * @psc_data: platform data to configure this clock 164 + * @lock: spinlock used by this clock 165 + */ 166 + static struct clk *clk_register_psc(struct device *dev, 167 + const char *name, 168 + const char *parent_name, 169 + struct clk_psc_data *psc_data, 170 + spinlock_t *lock) 171 + { 172 + struct clk_init_data init; 173 + struct clk_psc *psc; 174 + struct clk *clk; 175 + 176 + psc = kzalloc(sizeof(*psc), GFP_KERNEL); 177 + if (!psc) 178 + return ERR_PTR(-ENOMEM); 179 + 180 + init.name = name; 181 + init.ops = &clk_psc_ops; 182 + init.parent_names = (parent_name ? &parent_name : NULL); 183 + init.num_parents = (parent_name ? 1 : 0); 184 + 185 + psc->psc_data = psc_data; 186 + psc->lock = lock; 187 + psc->hw.init = &init; 188 + 189 + clk = clk_register(NULL, &psc->hw); 190 + if (IS_ERR(clk)) 191 + kfree(psc); 192 + 193 + return clk; 194 + } 195 + 196 + /** 197 + * of_psc_clk_init - initialize psc clock through DT 198 + * @node: device tree node for this clock 199 + * @lock: spinlock used by this clock 200 + */ 201 + static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock) 202 + { 203 + const char *clk_name = node->name; 204 + const char *parent_name; 205 + struct clk_psc_data *data; 206 + struct clk *clk; 207 + int i; 208 + 209 + data = kzalloc(sizeof(*data), GFP_KERNEL); 210 + if (!data) { 211 + pr_err("%s: Out of memory\n", __func__); 212 + return; 213 + } 214 + 215 + i = of_property_match_string(node, "reg-names", "control"); 216 + data->control_base = of_iomap(node, i); 217 + if (!data->control_base) { 218 + pr_err("%s: control ioremap failed\n", __func__); 219 + goto out; 220 + } 221 + 222 + i = of_property_match_string(node, "reg-names", "domain"); 223 + data->domain_base = of_iomap(node, i); 224 + if (!data->domain_base) { 225 + pr_err("%s: domain ioremap failed\n", __func__); 226 + iounmap(data->control_base); 227 + goto out; 228 + } 229 + 230 + of_property_read_u32(node, "domain-id", &data->domain_id); 231 + 232 + /* Domain transition registers at fixed address space of domain_id 0 */ 233 + if (!domain_transition_base && !data->domain_id) 234 + domain_transition_base = data->domain_base; 235 + 236 + of_property_read_string(node, "clock-output-names", &clk_name); 237 + parent_name = of_clk_get_parent_name(node, 0); 238 + if (!parent_name) { 239 + pr_err("%s: Parent clock not found\n", __func__); 240 + goto out; 241 + } 242 + 243 + clk = clk_register_psc(NULL, clk_name, parent_name, data, lock); 244 + if (clk) { 245 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 246 + return; 247 + } 248 + 249 + pr_err("%s: error registering clk %s\n", __func__, node->name); 250 + out: 251 + kfree(data); 252 + return; 253 + } 254 + 255 + /** 256 + * of_keystone_psc_clk_init - initialize psc clock through DT 257 + * @node: device tree node for this clock 258 + */ 259 + static void __init of_keystone_psc_clk_init(struct device_node *node) 260 + { 261 + of_psc_clk_init(node, &psc_lock); 262 + } 263 + CLK_OF_DECLARE(keystone_gate_clk, "ti,keystone,psc-clock", 264 + of_keystone_psc_clk_init);
+305
drivers/clk/keystone/pll.c
··· 1 + /* 2 + * PLL clock driver for Keystone devices 3 + * 4 + * Copyright (C) 2013 Texas Instruments Inc. 5 + * Murali Karicheri <m-karicheri2@ti.com> 6 + * Santosh Shilimkar <santosh.shilimkar@ti.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + #include <linux/clk.h> 14 + #include <linux/clk-provider.h> 15 + #include <linux/err.h> 16 + #include <linux/io.h> 17 + #include <linux/slab.h> 18 + #include <linux/of_address.h> 19 + #include <linux/of.h> 20 + #include <linux/module.h> 21 + 22 + #define PLLM_LOW_MASK 0x3f 23 + #define PLLM_HIGH_MASK 0x7ffc0 24 + #define MAIN_PLLM_HIGH_MASK 0x7f000 25 + #define PLLM_HIGH_SHIFT 6 26 + #define PLLD_MASK 0x3f 27 + 28 + /** 29 + * struct clk_pll_data - pll data structure 30 + * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm 31 + * register of pll controller, else it is in the pll_ctrl0((bit 11-6) 32 + * @phy_pllm: Physical address of PLLM in pll controller. Used when 33 + * has_pllctrl is non zero. 34 + * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of 35 + * Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL 36 + * or PA PLL available on keystone2. These PLLs are controlled by 37 + * this register. Main PLL is controlled by a PLL controller. 38 + * @pllm: PLL register map address 39 + * @pll_ctl0: PLL controller map address 40 + * @pllm_lower_mask: multiplier lower mask 41 + * @pllm_upper_mask: multiplier upper mask 42 + * @pllm_upper_shift: multiplier upper shift 43 + * @plld_mask: divider mask 44 + * @postdiv: Post divider 45 + */ 46 + struct clk_pll_data { 47 + bool has_pllctrl; 48 + u32 phy_pllm; 49 + u32 phy_pll_ctl0; 50 + void __iomem *pllm; 51 + void __iomem *pll_ctl0; 52 + u32 pllm_lower_mask; 53 + u32 pllm_upper_mask; 54 + u32 pllm_upper_shift; 55 + u32 plld_mask; 56 + u32 postdiv; 57 + }; 58 + 59 + /** 60 + * struct clk_pll - Main pll clock 61 + * @hw: clk_hw for the pll 62 + * @pll_data: PLL driver specific data 63 + */ 64 + struct clk_pll { 65 + struct clk_hw hw; 66 + struct clk_pll_data *pll_data; 67 + }; 68 + 69 + #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) 70 + 71 + static unsigned long clk_pllclk_recalc(struct clk_hw *hw, 72 + unsigned long parent_rate) 73 + { 74 + struct clk_pll *pll = to_clk_pll(hw); 75 + struct clk_pll_data *pll_data = pll->pll_data; 76 + unsigned long rate = parent_rate; 77 + u32 mult = 0, prediv, postdiv, val; 78 + 79 + /* 80 + * get bits 0-5 of multiplier from pllctrl PLLM register 81 + * if has_pllctrl is non zero 82 + */ 83 + if (pll_data->has_pllctrl) { 84 + val = readl(pll_data->pllm); 85 + mult = (val & pll_data->pllm_lower_mask); 86 + } 87 + 88 + /* bit6-12 of PLLM is in Main PLL control register */ 89 + val = readl(pll_data->pll_ctl0); 90 + mult |= ((val & pll_data->pllm_upper_mask) 91 + >> pll_data->pllm_upper_shift); 92 + prediv = (val & pll_data->plld_mask); 93 + postdiv = pll_data->postdiv; 94 + 95 + rate /= (prediv + 1); 96 + rate = (rate * (mult + 1)); 97 + rate /= postdiv; 98 + 99 + return rate; 100 + } 101 + 102 + static const struct clk_ops clk_pll_ops = { 103 + .recalc_rate = clk_pllclk_recalc, 104 + }; 105 + 106 + static struct clk *clk_register_pll(struct device *dev, 107 + const char *name, 108 + const char *parent_name, 109 + struct clk_pll_data *pll_data) 110 + { 111 + struct clk_init_data init; 112 + struct clk_pll *pll; 113 + struct clk *clk; 114 + 115 + pll = kzalloc(sizeof(*pll), GFP_KERNEL); 116 + if (!pll) 117 + return ERR_PTR(-ENOMEM); 118 + 119 + init.name = name; 120 + init.ops = &clk_pll_ops; 121 + init.flags = 0; 122 + init.parent_names = (parent_name ? &parent_name : NULL); 123 + init.num_parents = (parent_name ? 1 : 0); 124 + 125 + pll->pll_data = pll_data; 126 + pll->hw.init = &init; 127 + 128 + clk = clk_register(NULL, &pll->hw); 129 + if (IS_ERR(clk)) 130 + goto out; 131 + 132 + return clk; 133 + out: 134 + kfree(pll); 135 + return NULL; 136 + } 137 + 138 + /** 139 + * _of_clk_init - PLL initialisation via DT 140 + * @node: device tree node for this clock 141 + * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of 142 + * pll controller, else it is in the control regsiter0(bit 11-6) 143 + */ 144 + static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl) 145 + { 146 + struct clk_pll_data *pll_data; 147 + const char *parent_name; 148 + struct clk *clk; 149 + int i; 150 + 151 + pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL); 152 + if (!pll_data) { 153 + pr_err("%s: Out of memory\n", __func__); 154 + return; 155 + } 156 + 157 + parent_name = of_clk_get_parent_name(node, 0); 158 + if (of_property_read_u32(node, "fixed-postdiv", &pll_data->postdiv)) 159 + goto out; 160 + 161 + i = of_property_match_string(node, "reg-names", "control"); 162 + pll_data->pll_ctl0 = of_iomap(node, i); 163 + if (!pll_data->pll_ctl0) { 164 + pr_err("%s: ioremap failed\n", __func__); 165 + goto out; 166 + } 167 + 168 + pll_data->pllm_lower_mask = PLLM_LOW_MASK; 169 + pll_data->pllm_upper_shift = PLLM_HIGH_SHIFT; 170 + pll_data->plld_mask = PLLD_MASK; 171 + pll_data->has_pllctrl = pllctrl; 172 + if (!pll_data->has_pllctrl) { 173 + pll_data->pllm_upper_mask = PLLM_HIGH_MASK; 174 + } else { 175 + pll_data->pllm_upper_mask = MAIN_PLLM_HIGH_MASK; 176 + i = of_property_match_string(node, "reg-names", "multiplier"); 177 + pll_data->pllm = of_iomap(node, i); 178 + if (!pll_data->pllm) { 179 + iounmap(pll_data->pll_ctl0); 180 + goto out; 181 + } 182 + } 183 + 184 + clk = clk_register_pll(NULL, node->name, parent_name, pll_data); 185 + if (clk) { 186 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 187 + return; 188 + } 189 + 190 + out: 191 + pr_err("%s: error initializing pll %s\n", __func__, node->name); 192 + kfree(pll_data); 193 + } 194 + 195 + /** 196 + * of_keystone_pll_clk_init - PLL initialisation DT wrapper 197 + * @node: device tree node for this clock 198 + */ 199 + static void __init of_keystone_pll_clk_init(struct device_node *node) 200 + { 201 + _of_pll_clk_init(node, false); 202 + } 203 + CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock", 204 + of_keystone_pll_clk_init); 205 + 206 + /** 207 + * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper 208 + * @node: device tree node for this clock 209 + */ 210 + static void __init of_keystone_main_pll_clk_init(struct device_node *node) 211 + { 212 + _of_pll_clk_init(node, true); 213 + } 214 + CLK_OF_DECLARE(keystone_main_pll_clock, "ti,keystone,main-pll-clock", 215 + of_keystone_main_pll_clk_init); 216 + 217 + /** 218 + * of_pll_div_clk_init - PLL divider setup function 219 + * @node: device tree node for this clock 220 + */ 221 + static void __init of_pll_div_clk_init(struct device_node *node) 222 + { 223 + const char *parent_name; 224 + void __iomem *reg; 225 + u32 shift, mask; 226 + struct clk *clk; 227 + const char *clk_name = node->name; 228 + 229 + of_property_read_string(node, "clock-output-names", &clk_name); 230 + reg = of_iomap(node, 0); 231 + if (!reg) { 232 + pr_err("%s: ioremap failed\n", __func__); 233 + return; 234 + } 235 + 236 + parent_name = of_clk_get_parent_name(node, 0); 237 + if (!parent_name) { 238 + pr_err("%s: missing parent clock\n", __func__); 239 + return; 240 + } 241 + 242 + if (of_property_read_u32(node, "bit-shift", &shift)) { 243 + pr_err("%s: missing 'shift' property\n", __func__); 244 + return; 245 + } 246 + 247 + if (of_property_read_u32(node, "bit-mask", &mask)) { 248 + pr_err("%s: missing 'bit-mask' property\n", __func__); 249 + return; 250 + } 251 + 252 + clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift, 253 + mask, 0, NULL); 254 + if (clk) 255 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 256 + else 257 + pr_err("%s: error registering divider %s\n", __func__, clk_name); 258 + } 259 + CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init); 260 + 261 + /** 262 + * of_pll_mux_clk_init - PLL mux setup function 263 + * @node: device tree node for this clock 264 + */ 265 + static void __init of_pll_mux_clk_init(struct device_node *node) 266 + { 267 + void __iomem *reg; 268 + u32 shift, mask; 269 + struct clk *clk; 270 + const char *parents[2]; 271 + const char *clk_name = node->name; 272 + 273 + of_property_read_string(node, "clock-output-names", &clk_name); 274 + reg = of_iomap(node, 0); 275 + if (!reg) { 276 + pr_err("%s: ioremap failed\n", __func__); 277 + return; 278 + } 279 + 280 + parents[0] = of_clk_get_parent_name(node, 0); 281 + parents[1] = of_clk_get_parent_name(node, 1); 282 + if (!parents[0] || !parents[1]) { 283 + pr_err("%s: missing parent clocks\n", __func__); 284 + return; 285 + } 286 + 287 + if (of_property_read_u32(node, "bit-shift", &shift)) { 288 + pr_err("%s: missing 'shift' property\n", __func__); 289 + return; 290 + } 291 + 292 + if (of_property_read_u32(node, "bit-mask", &mask)) { 293 + pr_err("%s: missing 'bit-mask' property\n", __func__); 294 + return; 295 + } 296 + 297 + clk = clk_register_mux(NULL, clk_name, (const char **)&parents, 298 + ARRAY_SIZE(parents) , 0, reg, shift, mask, 299 + 0, NULL); 300 + if (clk) 301 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 302 + else 303 + pr_err("%s: error registering mux %s\n", __func__, clk_name); 304 + } 305 + CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
+15 -1
drivers/clk/zynq/clkc.c
··· 117 117 goto err; 118 118 fclk_gate_lock = kmalloc(sizeof(*fclk_gate_lock), GFP_KERNEL); 119 119 if (!fclk_gate_lock) 120 - goto err; 120 + goto err_fclk_gate_lock; 121 121 spin_lock_init(fclk_lock); 122 122 spin_lock_init(fclk_gate_lock); 123 123 124 124 mux_name = kasprintf(GFP_KERNEL, "%s_mux", clk_name); 125 + if (!mux_name) 126 + goto err_mux_name; 125 127 div0_name = kasprintf(GFP_KERNEL, "%s_div0", clk_name); 128 + if (!div0_name) 129 + goto err_div0_name; 126 130 div1_name = kasprintf(GFP_KERNEL, "%s_div1", clk_name); 131 + if (!div1_name) 132 + goto err_div1_name; 127 133 128 134 clk = clk_register_mux(NULL, mux_name, parents, 4, 129 135 CLK_SET_RATE_NO_REPARENT, fclk_ctrl_reg, 4, 2, 0, ··· 153 147 154 148 return; 155 149 150 + err_div1_name: 151 + kfree(div0_name); 152 + err_div0_name: 153 + kfree(mux_name); 154 + err_mux_name: 155 + kfree(fclk_gate_lock); 156 + err_fclk_gate_lock: 157 + kfree(fclk_lock); 156 158 err: 157 159 clks[fclk] = ERR_PTR(-ENOMEM); 158 160 }
+42
include/dt-bindings/clock/efm32-cmu.h
··· 1 + #ifndef __DT_BINDINGS_CLOCK_EFM32_CMU_H 2 + #define __DT_BINDINGS_CLOCK_EFM32_CMU_H 3 + 4 + #define clk_HFXO 0 5 + #define clk_HFRCO 1 6 + #define clk_LFXO 2 7 + #define clk_LFRCO 3 8 + #define clk_ULFRCO 4 9 + #define clk_AUXHFRCO 5 10 + #define clk_HFCLKNODIV 6 11 + #define clk_HFCLK 7 12 + #define clk_HFPERCLK 8 13 + #define clk_HFCORECLK 9 14 + #define clk_LFACLK 10 15 + #define clk_LFBCLK 11 16 + #define clk_WDOGCLK 12 17 + #define clk_HFCORECLKDMA 13 18 + #define clk_HFCORECLKAES 14 19 + #define clk_HFCORECLKUSBC 15 20 + #define clk_HFCORECLKUSB 16 21 + #define clk_HFCORECLKLE 17 22 + #define clk_HFCORECLKEBI 18 23 + #define clk_HFPERCLKUSART0 19 24 + #define clk_HFPERCLKUSART1 20 25 + #define clk_HFPERCLKUSART2 21 26 + #define clk_HFPERCLKUART0 22 27 + #define clk_HFPERCLKUART1 23 28 + #define clk_HFPERCLKTIMER0 24 29 + #define clk_HFPERCLKTIMER1 25 30 + #define clk_HFPERCLKTIMER2 26 31 + #define clk_HFPERCLKTIMER3 27 32 + #define clk_HFPERCLKACMP0 28 33 + #define clk_HFPERCLKACMP1 29 34 + #define clk_HFPERCLKI2C0 30 35 + #define clk_HFPERCLKI2C1 31 36 + #define clk_HFPERCLKGPIO 32 37 + #define clk_HFPERCLKVCMP 33 38 + #define clk_HFPERCLKPRS 34 39 + #define clk_HFPERCLKADC0 35 40 + #define clk_HFPERCLKDAC0 36 41 + 42 + #endif /* __DT_BINDINGS_CLOCK_EFM32_CMU_H */
+1
include/linux/clk-provider.h
··· 472 472 struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, 473 473 void *data); 474 474 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); 475 + int of_clk_get_parent_count(struct device_node *np); 475 476 const char *of_clk_get_parent_name(struct device_node *np, int index); 476 477 477 478 void of_clk_init(const struct of_device_id *matches);