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

clk: add highbank clock support

This adds real clock support to Calxeda Highbank SOC using the common
clock infrastructure.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
[mturquette@linaro.org: fixed up invalid writes to const struct member]
Signed-off-by: Mike Turquette <mturquette@linaro.org>

authored by

Rob Herring and committed by
Mike Turquette
8d4d9f52 260b6aa0

+463 -64
+17
Documentation/devicetree/bindings/clock/calxeda.txt
··· 1 + Device Tree Clock bindings for Calxeda highbank platform 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 + "calxeda,hb-pll-clock" - for a PLL clock 10 + "calxeda,hb-a9periph-clock" - The A9 peripheral clock divided from the 11 + A9 clock. 12 + "calxeda,hb-a9bus-clock" - The A9 bus clock divided from the A9 clock. 13 + "calxeda,hb-emmc-clock" - Divided clock for MMC/SD controller. 14 + - reg : shall be the control register offset from SYSREGs base for the clock. 15 + - clocks : shall be the input parent clock phandle for the clock. This is 16 + either an oscillator or a pll output. 17 + - #clock-cells : from common clock binding; shall be set to 0.
+1
arch/arm/Kconfig
··· 352 352 select ARM_TIMER_SP804 353 353 select CACHE_L2X0 354 354 select CLKDEV_LOOKUP 355 + select COMMON_CLK 355 356 select CPU_V7 356 357 select GENERIC_CLOCKEVENTS 357 358 select HAVE_ARM_SCU
+90 -1
arch/arm/boot/dts/highbank.dts
··· 1 1 /* 2 - * Copyright 2011 Calxeda, Inc. 2 + * Copyright 2011-2012 Calxeda, Inc. 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify it 5 5 * under the terms and conditions of the GNU General Public License, ··· 24 24 compatible = "calxeda,highbank"; 25 25 #address-cells = <1>; 26 26 #size-cells = <1>; 27 + clock-ranges; 27 28 28 29 cpus { 29 30 #address-cells = <1>; ··· 34 33 compatible = "arm,cortex-a9"; 35 34 reg = <0>; 36 35 next-level-cache = <&L2>; 36 + clocks = <&a9pll>; 37 + clock-names = "cpu"; 37 38 }; 38 39 39 40 cpu@1 { 40 41 compatible = "arm,cortex-a9"; 41 42 reg = <1>; 42 43 next-level-cache = <&L2>; 44 + clocks = <&a9pll>; 45 + clock-names = "cpu"; 43 46 }; 44 47 45 48 cpu@2 { 46 49 compatible = "arm,cortex-a9"; 47 50 reg = <2>; 48 51 next-level-cache = <&L2>; 52 + clocks = <&a9pll>; 53 + clock-names = "cpu"; 49 54 }; 50 55 51 56 cpu@3 { 52 57 compatible = "arm,cortex-a9"; 53 58 reg = <3>; 54 59 next-level-cache = <&L2>; 60 + clocks = <&a9pll>; 61 + clock-names = "cpu"; 55 62 }; 56 63 }; 57 64 ··· 84 75 compatible = "arm,cortex-a9-twd-timer"; 85 76 reg = <0xfff10600 0x20>; 86 77 interrupts = <1 13 0xf01>; 78 + clocks = <&a9periphclk>; 87 79 }; 88 80 89 81 watchdog@fff10620 { 90 82 compatible = "arm,cortex-a9-twd-wdt"; 91 83 reg = <0xfff10620 0x20>; 92 84 interrupts = <1 14 0xf01>; 85 + clocks = <&a9periphclk>; 93 86 }; 94 87 95 88 intc: interrupt-controller@fff11000 { ··· 127 116 compatible = "calxeda,hb-sdhci"; 128 117 reg = <0xffe0e000 0x1000>; 129 118 interrupts = <0 90 4>; 119 + clocks = <&eclk>; 130 120 }; 131 121 132 122 ipc@fff20000 { 133 123 compatible = "arm,pl320", "arm,primecell"; 134 124 reg = <0xfff20000 0x1000>; 135 125 interrupts = <0 7 4>; 126 + clocks = <&pclk>; 127 + clock-names = "apb_pclk"; 136 128 }; 137 129 138 130 gpioe: gpio@fff30000 { ··· 144 130 gpio-controller; 145 131 reg = <0xfff30000 0x1000>; 146 132 interrupts = <0 14 4>; 133 + clocks = <&pclk>; 134 + clock-names = "apb_pclk"; 147 135 }; 148 136 149 137 gpiof: gpio@fff31000 { ··· 154 138 gpio-controller; 155 139 reg = <0xfff31000 0x1000>; 156 140 interrupts = <0 15 4>; 141 + clocks = <&pclk>; 142 + clock-names = "apb_pclk"; 157 143 }; 158 144 159 145 gpiog: gpio@fff32000 { ··· 164 146 gpio-controller; 165 147 reg = <0xfff32000 0x1000>; 166 148 interrupts = <0 16 4>; 149 + clocks = <&pclk>; 150 + clock-names = "apb_pclk"; 167 151 }; 168 152 169 153 gpioh: gpio@fff33000 { ··· 174 154 gpio-controller; 175 155 reg = <0xfff33000 0x1000>; 176 156 interrupts = <0 17 4>; 157 + clocks = <&pclk>; 158 + clock-names = "apb_pclk"; 177 159 }; 178 160 179 161 timer { 180 162 compatible = "arm,sp804", "arm,primecell"; 181 163 reg = <0xfff34000 0x1000>; 182 164 interrupts = <0 18 4>; 165 + clocks = <&pclk>; 166 + clock-names = "apb_pclk"; 183 167 }; 184 168 185 169 rtc@fff35000 { 186 170 compatible = "arm,pl031", "arm,primecell"; 187 171 reg = <0xfff35000 0x1000>; 188 172 interrupts = <0 19 4>; 173 + clocks = <&pclk>; 174 + clock-names = "apb_pclk"; 189 175 }; 190 176 191 177 serial@fff36000 { 192 178 compatible = "arm,pl011", "arm,primecell"; 193 179 reg = <0xfff36000 0x1000>; 194 180 interrupts = <0 20 4>; 181 + clocks = <&pclk>; 182 + clock-names = "apb_pclk"; 195 183 }; 196 184 197 185 smic@fff3a000 { ··· 214 186 sregs@fff3c000 { 215 187 compatible = "calxeda,hb-sregs"; 216 188 reg = <0xfff3c000 0x1000>; 189 + 190 + clocks { 191 + #address-cells = <1>; 192 + #size-cells = <0>; 193 + 194 + osc: oscillator { 195 + #clock-cells = <0>; 196 + compatible = "fixed-clock"; 197 + clock-frequency = <33333000>; 198 + }; 199 + 200 + ddrpll: ddrpll { 201 + #clock-cells = <0>; 202 + compatible = "calxeda,hb-pll-clock"; 203 + clocks = <&osc>; 204 + reg = <0x108>; 205 + }; 206 + 207 + a9pll: a9pll { 208 + #clock-cells = <0>; 209 + compatible = "calxeda,hb-pll-clock"; 210 + clocks = <&osc>; 211 + reg = <0x100>; 212 + }; 213 + 214 + a9periphclk: a9periphclk { 215 + #clock-cells = <0>; 216 + compatible = "calxeda,hb-a9periph-clock"; 217 + clocks = <&a9pll>; 218 + reg = <0x104>; 219 + }; 220 + 221 + a9bclk: a9bclk { 222 + #clock-cells = <0>; 223 + compatible = "calxeda,hb-a9bus-clock"; 224 + clocks = <&a9pll>; 225 + reg = <0x104>; 226 + }; 227 + 228 + emmcpll: emmcpll { 229 + #clock-cells = <0>; 230 + compatible = "calxeda,hb-pll-clock"; 231 + clocks = <&osc>; 232 + reg = <0x10C>; 233 + }; 234 + 235 + eclk: eclk { 236 + #clock-cells = <0>; 237 + compatible = "calxeda,hb-emmc-clock"; 238 + clocks = <&emmcpll>; 239 + reg = <0x114>; 240 + }; 241 + 242 + pclk: pclk { 243 + #clock-cells = <0>; 244 + compatible = "fixed-clock"; 245 + clock-frequency = <150000000>; 246 + }; 247 + }; 217 248 }; 218 249 219 250 dma@fff3d000 { 220 251 compatible = "arm,pl330", "arm,primecell"; 221 252 reg = <0xfff3d000 0x1000>; 222 253 interrupts = <0 92 4>; 254 + clocks = <&pclk>; 255 + clock-names = "apb_pclk"; 223 256 }; 224 257 225 258 ethernet@fff50000 {
+1 -1
arch/arm/mach-highbank/Makefile
··· 1 - obj-y := clock.o highbank.o system.o smc.o 1 + obj-y := highbank.o system.o smc.o 2 2 3 3 plus_sec := $(call as-instr,.arch_extension sec,+sec) 4 4 AFLAGS_smc.o :=-Wa,-march=armv7-a$(plus_sec)
-62
arch/arm/mach-highbank/clock.c
··· 1 - /* 2 - * Copyright 2011 Calxeda, Inc. 3 - * 4 - * This program is free software; you can redistribute it and/or modify it 5 - * under the terms and conditions of the GNU General Public License, 6 - * version 2, as published by the Free Software Foundation. 7 - * 8 - * This program is distributed in the hope it will be useful, but WITHOUT 9 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 - * more details. 12 - * 13 - * You should have received a copy of the GNU General Public License along with 14 - * this program. If not, see <http://www.gnu.org/licenses/>. 15 - */ 16 - #include <linux/module.h> 17 - #include <linux/kernel.h> 18 - #include <linux/errno.h> 19 - #include <linux/clk.h> 20 - #include <linux/clkdev.h> 21 - 22 - struct clk { 23 - unsigned long rate; 24 - }; 25 - 26 - int clk_enable(struct clk *clk) 27 - { 28 - return 0; 29 - } 30 - 31 - void clk_disable(struct clk *clk) 32 - {} 33 - 34 - unsigned long clk_get_rate(struct clk *clk) 35 - { 36 - return clk->rate; 37 - } 38 - 39 - long clk_round_rate(struct clk *clk, unsigned long rate) 40 - { 41 - return clk->rate; 42 - } 43 - 44 - int clk_set_rate(struct clk *clk, unsigned long rate) 45 - { 46 - return 0; 47 - } 48 - 49 - static struct clk eclk = { .rate = 200000000 }; 50 - static struct clk pclk = { .rate = 150000000 }; 51 - 52 - static struct clk_lookup lookups[] = { 53 - { .clk = &pclk, .con_id = "apb_pclk", }, 54 - { .clk = &pclk, .dev_id = "sp804", }, 55 - { .clk = &eclk, .dev_id = "ffe0e000.sdhci", }, 56 - { .clk = &pclk, .dev_id = "fff36000.serial", }, 57 - }; 58 - 59 - void __init highbank_clocks_init(void) 60 - { 61 - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 62 - }
+7
arch/arm/mach-highbank/highbank.c
··· 105 105 #endif 106 106 } 107 107 108 + static struct clk_lookup lookup = { 109 + .dev_id = "sp804", 110 + .con_id = NULL, 111 + }; 112 + 108 113 static void __init highbank_timer_init(void) 109 114 { 110 115 int irq; ··· 127 122 irq = irq_of_parse_and_map(np, 0); 128 123 129 124 highbank_clocks_init(); 125 + lookup.clk = of_clk_get(np, 0); 126 + clkdev_add(&lookup); 130 127 131 128 sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1"); 132 129 sp804_clockevents_init(timer_base, irq, "timer0");
+1
drivers/clk/Makefile
··· 3 3 obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ 4 4 clk-mux.o clk-divider.o clk-fixed-factor.o 5 5 # SoCs specific 6 + obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 6 7 obj-$(CONFIG_ARCH_MXS) += mxs/ 7 8 obj-$(CONFIG_PLAT_SPEAR) += spear/ 8 9 obj-$(CONFIG_ARCH_U300) += clk-u300.o
+346
drivers/clk/clk-highbank.c
··· 1 + /* 2 + * Copyright 2011-2012 Calxeda, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/slab.h> 19 + #include <linux/err.h> 20 + #include <linux/clk-provider.h> 21 + #include <linux/io.h> 22 + #include <linux/of.h> 23 + 24 + extern void __iomem *sregs_base; 25 + 26 + #define HB_PLL_LOCK_500 0x20000000 27 + #define HB_PLL_LOCK 0x10000000 28 + #define HB_PLL_DIVF_SHIFT 20 29 + #define HB_PLL_DIVF_MASK 0x0ff00000 30 + #define HB_PLL_DIVQ_SHIFT 16 31 + #define HB_PLL_DIVQ_MASK 0x00070000 32 + #define HB_PLL_DIVR_SHIFT 8 33 + #define HB_PLL_DIVR_MASK 0x00001f00 34 + #define HB_PLL_RANGE_SHIFT 4 35 + #define HB_PLL_RANGE_MASK 0x00000070 36 + #define HB_PLL_BYPASS 0x00000008 37 + #define HB_PLL_RESET 0x00000004 38 + #define HB_PLL_EXT_BYPASS 0x00000002 39 + #define HB_PLL_EXT_ENA 0x00000001 40 + 41 + #define HB_PLL_VCO_MIN_FREQ 2133000000 42 + #define HB_PLL_MAX_FREQ HB_PLL_VCO_MIN_FREQ 43 + #define HB_PLL_MIN_FREQ (HB_PLL_VCO_MIN_FREQ / 64) 44 + 45 + #define HB_A9_BCLK_DIV_MASK 0x00000006 46 + #define HB_A9_BCLK_DIV_SHIFT 1 47 + #define HB_A9_PCLK_DIV 0x00000001 48 + 49 + struct hb_clk { 50 + struct clk_hw hw; 51 + void __iomem *reg; 52 + char *parent_name; 53 + }; 54 + #define to_hb_clk(p) container_of(p, struct hb_clk, hw) 55 + 56 + static int clk_pll_prepare(struct clk_hw *hwclk) 57 + { 58 + struct hb_clk *hbclk = to_hb_clk(hwclk); 59 + u32 reg; 60 + 61 + reg = readl(hbclk->reg); 62 + reg &= ~HB_PLL_RESET; 63 + writel(reg, hbclk->reg); 64 + 65 + while ((readl(hbclk->reg) & HB_PLL_LOCK) == 0) 66 + ; 67 + while ((readl(hbclk->reg) & HB_PLL_LOCK_500) == 0) 68 + ; 69 + 70 + return 0; 71 + } 72 + 73 + static void clk_pll_unprepare(struct clk_hw *hwclk) 74 + { 75 + struct hb_clk *hbclk = to_hb_clk(hwclk); 76 + u32 reg; 77 + 78 + reg = readl(hbclk->reg); 79 + reg |= HB_PLL_RESET; 80 + writel(reg, hbclk->reg); 81 + } 82 + 83 + static int clk_pll_enable(struct clk_hw *hwclk) 84 + { 85 + struct hb_clk *hbclk = to_hb_clk(hwclk); 86 + u32 reg; 87 + 88 + reg = readl(hbclk->reg); 89 + reg |= HB_PLL_EXT_ENA; 90 + writel(reg, hbclk->reg); 91 + 92 + return 0; 93 + } 94 + 95 + static void clk_pll_disable(struct clk_hw *hwclk) 96 + { 97 + struct hb_clk *hbclk = to_hb_clk(hwclk); 98 + u32 reg; 99 + 100 + reg = readl(hbclk->reg); 101 + reg &= ~HB_PLL_EXT_ENA; 102 + writel(reg, hbclk->reg); 103 + } 104 + 105 + static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, 106 + unsigned long parent_rate) 107 + { 108 + struct hb_clk *hbclk = to_hb_clk(hwclk); 109 + unsigned long divf, divq, vco_freq, reg; 110 + 111 + reg = readl(hbclk->reg); 112 + if (reg & HB_PLL_EXT_BYPASS) 113 + return parent_rate; 114 + 115 + divf = (reg & HB_PLL_DIVF_MASK) >> HB_PLL_DIVF_SHIFT; 116 + divq = (reg & HB_PLL_DIVQ_MASK) >> HB_PLL_DIVQ_SHIFT; 117 + vco_freq = parent_rate * (divf + 1); 118 + 119 + return vco_freq / (1 << divq); 120 + } 121 + 122 + static void clk_pll_calc(unsigned long rate, unsigned long ref_freq, 123 + u32 *pdivq, u32 *pdivf) 124 + { 125 + u32 divq, divf; 126 + unsigned long vco_freq; 127 + 128 + if (rate < HB_PLL_MIN_FREQ) 129 + rate = HB_PLL_MIN_FREQ; 130 + if (rate > HB_PLL_MAX_FREQ) 131 + rate = HB_PLL_MAX_FREQ; 132 + 133 + for (divq = 1; divq <= 6; divq++) { 134 + if ((rate * (1 << divq)) >= HB_PLL_VCO_MIN_FREQ) 135 + break; 136 + } 137 + 138 + vco_freq = rate * (1 << divq); 139 + divf = (vco_freq + (ref_freq / 2)) / ref_freq; 140 + divf--; 141 + 142 + *pdivq = divq; 143 + *pdivf = divf; 144 + } 145 + 146 + static long clk_pll_round_rate(struct clk_hw *hwclk, unsigned long rate, 147 + unsigned long *parent_rate) 148 + { 149 + u32 divq, divf; 150 + unsigned long ref_freq = *parent_rate; 151 + 152 + clk_pll_calc(rate, ref_freq, &divq, &divf); 153 + 154 + return (ref_freq * (divf + 1)) / (1 << divq); 155 + } 156 + 157 + static int clk_pll_set_rate(struct clk_hw *hwclk, unsigned long rate, 158 + unsigned long parent_rate) 159 + { 160 + struct hb_clk *hbclk = to_hb_clk(hwclk); 161 + u32 divq, divf; 162 + u32 reg; 163 + 164 + clk_pll_calc(rate, parent_rate, &divq, &divf); 165 + 166 + reg = readl(hbclk->reg); 167 + if (divf != ((reg & HB_PLL_DIVF_MASK) >> HB_PLL_DIVF_SHIFT)) { 168 + /* Need to re-lock PLL, so put it into bypass mode */ 169 + reg |= HB_PLL_EXT_BYPASS; 170 + writel(reg | HB_PLL_EXT_BYPASS, hbclk->reg); 171 + 172 + writel(reg | HB_PLL_RESET, hbclk->reg); 173 + reg &= ~(HB_PLL_DIVF_MASK | HB_PLL_DIVQ_MASK); 174 + reg |= (divf << HB_PLL_DIVF_SHIFT) | (divq << HB_PLL_DIVQ_SHIFT); 175 + writel(reg | HB_PLL_RESET, hbclk->reg); 176 + writel(reg, hbclk->reg); 177 + 178 + while ((readl(hbclk->reg) & HB_PLL_LOCK) == 0) 179 + ; 180 + while ((readl(hbclk->reg) & HB_PLL_LOCK_500) == 0) 181 + ; 182 + reg |= HB_PLL_EXT_ENA; 183 + reg &= ~HB_PLL_EXT_BYPASS; 184 + } else { 185 + reg &= ~HB_PLL_DIVQ_MASK; 186 + reg |= divq << HB_PLL_DIVQ_SHIFT; 187 + } 188 + writel(reg, hbclk->reg); 189 + 190 + return 0; 191 + } 192 + 193 + static const struct clk_ops clk_pll_ops = { 194 + .prepare = clk_pll_prepare, 195 + .unprepare = clk_pll_unprepare, 196 + .enable = clk_pll_enable, 197 + .disable = clk_pll_disable, 198 + .recalc_rate = clk_pll_recalc_rate, 199 + .round_rate = clk_pll_round_rate, 200 + .set_rate = clk_pll_set_rate, 201 + }; 202 + 203 + static unsigned long clk_cpu_periphclk_recalc_rate(struct clk_hw *hwclk, 204 + unsigned long parent_rate) 205 + { 206 + struct hb_clk *hbclk = to_hb_clk(hwclk); 207 + u32 div = (readl(hbclk->reg) & HB_A9_PCLK_DIV) ? 8 : 4; 208 + return parent_rate / div; 209 + } 210 + 211 + static const struct clk_ops a9periphclk_ops = { 212 + .recalc_rate = clk_cpu_periphclk_recalc_rate, 213 + }; 214 + 215 + static unsigned long clk_cpu_a9bclk_recalc_rate(struct clk_hw *hwclk, 216 + unsigned long parent_rate) 217 + { 218 + struct hb_clk *hbclk = to_hb_clk(hwclk); 219 + u32 div = (readl(hbclk->reg) & HB_A9_BCLK_DIV_MASK) >> HB_A9_BCLK_DIV_SHIFT; 220 + 221 + return parent_rate / (div + 2); 222 + } 223 + 224 + static const struct clk_ops a9bclk_ops = { 225 + .recalc_rate = clk_cpu_a9bclk_recalc_rate, 226 + }; 227 + 228 + static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk, 229 + unsigned long parent_rate) 230 + { 231 + struct hb_clk *hbclk = to_hb_clk(hwclk); 232 + u32 div; 233 + 234 + div = readl(hbclk->reg) & 0x1f; 235 + div++; 236 + div *= 2; 237 + 238 + return parent_rate / div; 239 + } 240 + 241 + static long clk_periclk_round_rate(struct clk_hw *hwclk, unsigned long rate, 242 + unsigned long *parent_rate) 243 + { 244 + u32 div; 245 + 246 + div = *parent_rate / rate; 247 + div++; 248 + div &= ~0x1; 249 + 250 + return *parent_rate / div; 251 + } 252 + 253 + static int clk_periclk_set_rate(struct clk_hw *hwclk, unsigned long rate, 254 + unsigned long parent_rate) 255 + { 256 + struct hb_clk *hbclk = to_hb_clk(hwclk); 257 + u32 div; 258 + 259 + div = parent_rate / rate; 260 + if (div & 0x1) 261 + return -EINVAL; 262 + 263 + writel(div >> 1, hbclk->reg); 264 + return 0; 265 + } 266 + 267 + static const struct clk_ops periclk_ops = { 268 + .recalc_rate = clk_periclk_recalc_rate, 269 + .round_rate = clk_periclk_round_rate, 270 + .set_rate = clk_periclk_set_rate, 271 + }; 272 + 273 + static __init struct clk *hb_clk_init(struct device_node *node, const struct clk_ops *ops) 274 + { 275 + u32 reg; 276 + struct clk *clk; 277 + struct hb_clk *hb_clk; 278 + const char *clk_name = node->name; 279 + const char *parent_name; 280 + struct clk_init_data init; 281 + int rc; 282 + 283 + rc = of_property_read_u32(node, "reg", &reg); 284 + if (WARN_ON(rc)) 285 + return NULL; 286 + 287 + hb_clk = kzalloc(sizeof(*hb_clk), GFP_KERNEL); 288 + if (WARN_ON(!hb_clk)) 289 + return NULL; 290 + 291 + hb_clk->reg = sregs_base + reg; 292 + 293 + of_property_read_string(node, "clock-output-names", &clk_name); 294 + 295 + init.name = clk_name; 296 + init.ops = ops; 297 + init.flags = 0; 298 + parent_name = of_clk_get_parent_name(node, 0); 299 + init.parent_names = &parent_name; 300 + init.num_parents = 1; 301 + 302 + hb_clk->hw.init = &init; 303 + 304 + clk = clk_register(NULL, &hb_clk->hw); 305 + if (WARN_ON(IS_ERR(clk))) { 306 + kfree(hb_clk); 307 + return NULL; 308 + } 309 + rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); 310 + return clk; 311 + } 312 + 313 + static void __init hb_pll_init(struct device_node *node) 314 + { 315 + hb_clk_init(node, &clk_pll_ops); 316 + } 317 + 318 + static void __init hb_a9periph_init(struct device_node *node) 319 + { 320 + hb_clk_init(node, &a9periphclk_ops); 321 + } 322 + 323 + static void __init hb_a9bus_init(struct device_node *node) 324 + { 325 + struct clk *clk = hb_clk_init(node, &a9bclk_ops); 326 + clk_prepare_enable(clk); 327 + } 328 + 329 + static void __init hb_emmc_init(struct device_node *node) 330 + { 331 + hb_clk_init(node, &periclk_ops); 332 + } 333 + 334 + static const __initconst struct of_device_id clk_match[] = { 335 + { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, 336 + { .compatible = "calxeda,hb-pll-clock", .data = hb_pll_init, }, 337 + { .compatible = "calxeda,hb-a9periph-clock", .data = hb_a9periph_init, }, 338 + { .compatible = "calxeda,hb-a9bus-clock", .data = hb_a9bus_init, }, 339 + { .compatible = "calxeda,hb-emmc-clock", .data = hb_emmc_init, }, 340 + {} 341 + }; 342 + 343 + void __init highbank_clocks_init(void) 344 + { 345 + of_clk_init(clk_match); 346 + }