Commit | Line | Data |
---|---|---|
02c981c0 BD |
1 | /* |
2 | * Clock tree for CSR SiRFprimaII | |
3 | * | |
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | |
5 | * | |
6 | * Licensed under GPLv2 or later. | |
7 | */ | |
8 | ||
9 | #include <linux/module.h> | |
10 | #include <linux/bitops.h> | |
02c981c0 | 11 | #include <linux/io.h> |
02c981c0 | 12 | #include <linux/clk.h> |
198678b0 BD |
13 | #include <linux/clkdev.h> |
14 | #include <linux/clk-provider.h> | |
02c981c0 | 15 | #include <linux/of_address.h> |
198678b0 | 16 | #include <linux/syscore_ops.h> |
02c981c0 BD |
17 | |
18 | #define SIRFSOC_CLKC_CLK_EN0 0x0000 | |
19 | #define SIRFSOC_CLKC_CLK_EN1 0x0004 | |
20 | #define SIRFSOC_CLKC_REF_CFG 0x0014 | |
21 | #define SIRFSOC_CLKC_CPU_CFG 0x0018 | |
22 | #define SIRFSOC_CLKC_MEM_CFG 0x001c | |
23 | #define SIRFSOC_CLKC_SYS_CFG 0x0020 | |
24 | #define SIRFSOC_CLKC_IO_CFG 0x0024 | |
25 | #define SIRFSOC_CLKC_DSP_CFG 0x0028 | |
26 | #define SIRFSOC_CLKC_GFX_CFG 0x002c | |
27 | #define SIRFSOC_CLKC_MM_CFG 0x0030 | |
198678b0 | 28 | #define SIRFSOC_CLKC_LCD_CFG 0x0034 |
02c981c0 BD |
29 | #define SIRFSOC_CLKC_MMC_CFG 0x0038 |
30 | #define SIRFSOC_CLKC_PLL1_CFG0 0x0040 | |
31 | #define SIRFSOC_CLKC_PLL2_CFG0 0x0044 | |
32 | #define SIRFSOC_CLKC_PLL3_CFG0 0x0048 | |
33 | #define SIRFSOC_CLKC_PLL1_CFG1 0x004c | |
34 | #define SIRFSOC_CLKC_PLL2_CFG1 0x0050 | |
35 | #define SIRFSOC_CLKC_PLL3_CFG1 0x0054 | |
36 | #define SIRFSOC_CLKC_PLL1_CFG2 0x0058 | |
37 | #define SIRFSOC_CLKC_PLL2_CFG2 0x005c | |
38 | #define SIRFSOC_CLKC_PLL3_CFG2 0x0060 | |
198678b0 BD |
39 | #define SIRFSOC_USBPHY_PLL_CTRL 0x0008 |
40 | #define SIRFSOC_USBPHY_PLL_POWERDOWN BIT(1) | |
41 | #define SIRFSOC_USBPHY_PLL_BYPASS BIT(2) | |
42 | #define SIRFSOC_USBPHY_PLL_LOCK BIT(3) | |
02c981c0 | 43 | |
198678b0 | 44 | static void *sirfsoc_clk_vbase, *sirfsoc_rsc_vbase; |
02c981c0 BD |
45 | |
46 | #define KHZ 1000 | |
47 | #define MHZ (KHZ * KHZ) | |
48 | ||
198678b0 BD |
49 | /* |
50 | * SiRFprimaII clock controller | |
51 | * - 2 oscillators: osc-26MHz, rtc-32.768KHz | |
52 | * - 3 standard configurable plls: pll1, pll2 & pll3 | |
53 | * - 2 exclusive plls: usb phy pll and sata phy pll | |
54 | * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia, | |
55 | * display and sdphy. | |
56 | * Each clock domain can select its own clock source from five clock sources, | |
57 | * X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source | |
58 | * clock of the group clock. | |
59 | * - dsp domain: gps, mf | |
60 | * - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse | |
61 | * - sys domain: security | |
62 | */ | |
63 | ||
64 | struct clk_pll { | |
65 | struct clk_hw hw; | |
66 | unsigned short regofs; /* register offset */ | |
02c981c0 BD |
67 | }; |
68 | ||
198678b0 BD |
69 | #define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw) |
70 | ||
71 | struct clk_dmn { | |
72 | struct clk_hw hw; | |
02c981c0 BD |
73 | signed char enable_bit; /* enable bit: 0 ~ 63 */ |
74 | unsigned short regofs; /* register offset */ | |
02c981c0 BD |
75 | }; |
76 | ||
198678b0 BD |
77 | #define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw) |
78 | ||
79 | struct clk_std { | |
80 | struct clk_hw hw; | |
81 | signed char enable_bit; /* enable bit: 0 ~ 63 */ | |
82 | }; | |
83 | ||
84 | #define to_stdclk(_hw) container_of(_hw, struct clk_std, hw) | |
85 | ||
86 | static int std_clk_is_enabled(struct clk_hw *hw); | |
87 | static int std_clk_enable(struct clk_hw *hw); | |
88 | static void std_clk_disable(struct clk_hw *hw); | |
02c981c0 BD |
89 | |
90 | static inline unsigned long clkc_readl(unsigned reg) | |
91 | { | |
198678b0 | 92 | return readl(sirfsoc_clk_vbase + reg); |
02c981c0 BD |
93 | } |
94 | ||
95 | static inline void clkc_writel(u32 val, unsigned reg) | |
96 | { | |
198678b0 | 97 | writel(val, sirfsoc_clk_vbase + reg); |
02c981c0 BD |
98 | } |
99 | ||
02c981c0 BD |
100 | /* |
101 | * std pll | |
102 | */ | |
198678b0 BD |
103 | |
104 | static unsigned long pll_clk_recalc_rate(struct clk_hw *hw, | |
105 | unsigned long parent_rate) | |
02c981c0 | 106 | { |
198678b0 BD |
107 | unsigned long fin = parent_rate; |
108 | struct clk_pll *clk = to_pllclk(hw); | |
02c981c0 BD |
109 | u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - |
110 | SIRFSOC_CLKC_PLL1_CFG0; | |
111 | ||
112 | if (clkc_readl(regcfg2) & BIT(2)) { | |
113 | /* pll bypass mode */ | |
198678b0 | 114 | return fin; |
02c981c0 BD |
115 | } else { |
116 | /* fout = fin * nf / nr / od */ | |
117 | u32 cfg0 = clkc_readl(clk->regofs); | |
118 | u32 nf = (cfg0 & (BIT(13) - 1)) + 1; | |
119 | u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; | |
120 | u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; | |
121 | WARN_ON(fin % MHZ); | |
198678b0 | 122 | return fin / MHZ * nf / nr / od * MHZ; |
02c981c0 | 123 | } |
198678b0 BD |
124 | } |
125 | ||
126 | static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate, | |
127 | unsigned long *parent_rate) | |
128 | { | |
129 | unsigned long fin, nf, nr, od; | |
130 | ||
131 | /* | |
132 | * fout = fin * nf / (nr * od); | |
133 | * set od = 1, nr = fin/MHz, so fout = nf * MHz | |
134 | */ | |
135 | rate = rate - rate % MHZ; | |
136 | ||
137 | nf = rate / MHZ; | |
138 | if (nf > BIT(13)) | |
139 | nf = BIT(13); | |
140 | if (nf < 1) | |
141 | nf = 1; | |
02c981c0 | 142 | |
198678b0 BD |
143 | fin = *parent_rate; |
144 | ||
145 | nr = fin / MHZ; | |
146 | if (nr > BIT(6)) | |
147 | nr = BIT(6); | |
148 | od = 1; | |
149 | ||
150 | return fin * nf / (nr * od); | |
02c981c0 BD |
151 | } |
152 | ||
198678b0 BD |
153 | static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
154 | unsigned long parent_rate) | |
02c981c0 | 155 | { |
198678b0 | 156 | struct clk_pll *clk = to_pllclk(hw); |
02c981c0 BD |
157 | unsigned long fin, nf, nr, od, reg; |
158 | ||
159 | /* | |
160 | * fout = fin * nf / (nr * od); | |
161 | * set od = 1, nr = fin/MHz, so fout = nf * MHz | |
162 | */ | |
163 | ||
164 | nf = rate / MHZ; | |
165 | if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) | |
166 | return -EINVAL; | |
167 | ||
198678b0 | 168 | fin = parent_rate; |
02c981c0 BD |
169 | BUG_ON(fin < MHZ); |
170 | ||
171 | nr = fin / MHZ; | |
172 | BUG_ON((fin % MHZ) || nr > BIT(6)); | |
173 | ||
174 | od = 1; | |
175 | ||
176 | reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); | |
177 | clkc_writel(reg, clk->regofs); | |
178 | ||
179 | reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; | |
180 | clkc_writel((nf >> 1) - 1, reg); | |
181 | ||
182 | reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; | |
183 | while (!(clkc_readl(reg) & BIT(6))) | |
184 | cpu_relax(); | |
185 | ||
02c981c0 BD |
186 | return 0; |
187 | } | |
188 | ||
189 | static struct clk_ops std_pll_ops = { | |
198678b0 BD |
190 | .recalc_rate = pll_clk_recalc_rate, |
191 | .round_rate = pll_clk_round_rate, | |
192 | .set_rate = pll_clk_set_rate, | |
02c981c0 BD |
193 | }; |
194 | ||
198678b0 BD |
195 | static const char *pll_clk_parents[] = { |
196 | "osc", | |
197 | }; | |
198 | ||
199 | static struct clk_init_data clk_pll1_init = { | |
200 | .name = "pll1", | |
02c981c0 | 201 | .ops = &std_pll_ops, |
198678b0 BD |
202 | .parent_names = pll_clk_parents, |
203 | .num_parents = ARRAY_SIZE(pll_clk_parents), | |
02c981c0 BD |
204 | }; |
205 | ||
198678b0 BD |
206 | static struct clk_init_data clk_pll2_init = { |
207 | .name = "pll2", | |
02c981c0 | 208 | .ops = &std_pll_ops, |
198678b0 BD |
209 | .parent_names = pll_clk_parents, |
210 | .num_parents = ARRAY_SIZE(pll_clk_parents), | |
02c981c0 BD |
211 | }; |
212 | ||
198678b0 BD |
213 | static struct clk_init_data clk_pll3_init = { |
214 | .name = "pll3", | |
02c981c0 | 215 | .ops = &std_pll_ops, |
198678b0 BD |
216 | .parent_names = pll_clk_parents, |
217 | .num_parents = ARRAY_SIZE(pll_clk_parents), | |
218 | }; | |
219 | ||
220 | static struct clk_pll clk_pll1 = { | |
221 | .regofs = SIRFSOC_CLKC_PLL1_CFG0, | |
222 | .hw = { | |
223 | .init = &clk_pll1_init, | |
224 | }, | |
225 | }; | |
226 | ||
227 | static struct clk_pll clk_pll2 = { | |
228 | .regofs = SIRFSOC_CLKC_PLL2_CFG0, | |
229 | .hw = { | |
230 | .init = &clk_pll2_init, | |
231 | }, | |
232 | }; | |
233 | ||
234 | static struct clk_pll clk_pll3 = { | |
235 | .regofs = SIRFSOC_CLKC_PLL3_CFG0, | |
236 | .hw = { | |
237 | .init = &clk_pll3_init, | |
238 | }, | |
02c981c0 BD |
239 | }; |
240 | ||
241 | /* | |
198678b0 | 242 | * usb uses specified pll |
02c981c0 BD |
243 | */ |
244 | ||
198678b0 BD |
245 | static int usb_pll_clk_enable(struct clk_hw *hw) |
246 | { | |
247 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | |
248 | reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); | |
249 | writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | |
250 | while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) & | |
251 | SIRFSOC_USBPHY_PLL_LOCK)) | |
252 | cpu_relax(); | |
253 | ||
254 | return 0; | |
255 | } | |
256 | ||
257 | static void usb_pll_clk_disable(struct clk_hw *clk) | |
258 | { | |
259 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | |
260 | reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); | |
261 | writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | |
262 | } | |
02c981c0 | 263 | |
198678b0 | 264 | static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
02c981c0 | 265 | { |
198678b0 BD |
266 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); |
267 | return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; | |
268 | } | |
269 | ||
270 | static struct clk_ops usb_pll_ops = { | |
271 | .enable = usb_pll_clk_enable, | |
272 | .disable = usb_pll_clk_disable, | |
273 | .recalc_rate = usb_pll_clk_recalc_rate, | |
274 | }; | |
275 | ||
276 | static struct clk_init_data clk_usb_pll_init = { | |
277 | .name = "usb_pll", | |
278 | .ops = &usb_pll_ops, | |
279 | .parent_names = pll_clk_parents, | |
280 | .num_parents = ARRAY_SIZE(pll_clk_parents), | |
281 | }; | |
282 | ||
283 | static struct clk_hw usb_pll_clk_hw = { | |
284 | .init = &clk_usb_pll_init, | |
285 | }; | |
286 | ||
287 | /* | |
288 | * clock domains - cpu, mem, sys/io, dsp, gfx | |
289 | */ | |
290 | ||
291 | static const char *dmn_clk_parents[] = { | |
292 | "rtc", | |
293 | "osc", | |
294 | "pll1", | |
295 | "pll2", | |
296 | "pll3", | |
297 | }; | |
298 | ||
299 | static u8 dmn_clk_get_parent(struct clk_hw *hw) | |
300 | { | |
301 | struct clk_dmn *clk = to_dmnclk(hw); | |
02c981c0 | 302 | u32 cfg = clkc_readl(clk->regofs); |
198678b0 BD |
303 | |
304 | /* parent of io domain can only be pll3 */ | |
305 | if (strcmp(hw->init->name, "io") == 0) | |
306 | return 4; | |
307 | ||
02c981c0 | 308 | WARN_ON((cfg & (BIT(3) - 1)) > 4); |
198678b0 BD |
309 | |
310 | return cfg & (BIT(3) - 1); | |
02c981c0 BD |
311 | } |
312 | ||
198678b0 | 313 | static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent) |
02c981c0 | 314 | { |
198678b0 | 315 | struct clk_dmn *clk = to_dmnclk(hw); |
02c981c0 | 316 | u32 cfg = clkc_readl(clk->regofs); |
198678b0 BD |
317 | |
318 | /* parent of io domain can only be pll3 */ | |
319 | if (strcmp(hw->init->name, "io") == 0) | |
320 | return -EINVAL; | |
321 | ||
322 | cfg &= ~(BIT(3) - 1); | |
323 | clkc_writel(cfg | parent, clk->regofs); | |
324 | /* BIT(3) - switching status: 1 - busy, 0 - done */ | |
325 | while (clkc_readl(clk->regofs) & BIT(3)) | |
326 | cpu_relax(); | |
327 | ||
328 | return 0; | |
02c981c0 BD |
329 | } |
330 | ||
198678b0 BD |
331 | static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw, |
332 | unsigned long parent_rate) | |
333 | ||
02c981c0 | 334 | { |
198678b0 BD |
335 | unsigned long fin = parent_rate; |
336 | struct clk_dmn *clk = to_dmnclk(hw); | |
337 | ||
02c981c0 | 338 | u32 cfg = clkc_readl(clk->regofs); |
198678b0 | 339 | |
02c981c0 BD |
340 | if (cfg & BIT(24)) { |
341 | /* fcd bypass mode */ | |
198678b0 | 342 | return fin; |
02c981c0 BD |
343 | } else { |
344 | /* | |
345 | * wait count: bit[19:16], hold count: bit[23:20] | |
346 | */ | |
347 | u32 wait = (cfg >> 16) & (BIT(4) - 1); | |
348 | u32 hold = (cfg >> 20) & (BIT(4) - 1); | |
349 | ||
198678b0 | 350 | return fin / (wait + hold + 2); |
02c981c0 | 351 | } |
198678b0 BD |
352 | } |
353 | ||
354 | static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate, | |
355 | unsigned long *parent_rate) | |
356 | { | |
357 | unsigned long fin; | |
358 | unsigned ratio, wait, hold; | |
359 | unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; | |
360 | ||
361 | fin = *parent_rate; | |
362 | ratio = fin / rate; | |
363 | ||
364 | if (ratio < 2) | |
365 | ratio = 2; | |
366 | if (ratio > BIT(bits + 1)) | |
367 | ratio = BIT(bits + 1); | |
02c981c0 | 368 | |
198678b0 BD |
369 | wait = (ratio >> 1) - 1; |
370 | hold = ratio - wait - 2; | |
371 | ||
372 | return fin / (wait + hold + 2); | |
02c981c0 BD |
373 | } |
374 | ||
198678b0 BD |
375 | static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
376 | unsigned long parent_rate) | |
02c981c0 | 377 | { |
198678b0 | 378 | struct clk_dmn *clk = to_dmnclk(hw); |
02c981c0 BD |
379 | unsigned long fin; |
380 | unsigned ratio, wait, hold, reg; | |
198678b0 | 381 | unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; |
02c981c0 | 382 | |
198678b0 | 383 | fin = parent_rate; |
02c981c0 BD |
384 | ratio = fin / rate; |
385 | ||
386 | if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) | |
387 | return -EINVAL; | |
388 | ||
389 | WARN_ON(fin % rate); | |
390 | ||
391 | wait = (ratio >> 1) - 1; | |
392 | hold = ratio - wait - 2; | |
393 | ||
394 | reg = clkc_readl(clk->regofs); | |
395 | reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); | |
396 | reg |= (wait << 16) | (hold << 20) | BIT(25); | |
397 | clkc_writel(reg, clk->regofs); | |
398 | ||
399 | /* waiting FCD been effective */ | |
400 | while (clkc_readl(clk->regofs) & BIT(25)) | |
401 | cpu_relax(); | |
402 | ||
02c981c0 BD |
403 | return 0; |
404 | } | |
405 | ||
198678b0 BD |
406 | static struct clk_ops msi_ops = { |
407 | .set_rate = dmn_clk_set_rate, | |
408 | .round_rate = dmn_clk_round_rate, | |
409 | .recalc_rate = dmn_clk_recalc_rate, | |
410 | .set_parent = dmn_clk_set_parent, | |
411 | .get_parent = dmn_clk_get_parent, | |
412 | }; | |
02c981c0 | 413 | |
198678b0 BD |
414 | static struct clk_init_data clk_mem_init = { |
415 | .name = "mem", | |
416 | .ops = &msi_ops, | |
417 | .parent_names = dmn_clk_parents, | |
418 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
419 | }; | |
02c981c0 | 420 | |
198678b0 BD |
421 | static struct clk_dmn clk_mem = { |
422 | .regofs = SIRFSOC_CLKC_MEM_CFG, | |
423 | .hw = { | |
424 | .init = &clk_mem_init, | |
425 | }, | |
426 | }; | |
02c981c0 | 427 | |
198678b0 BD |
428 | static struct clk_init_data clk_sys_init = { |
429 | .name = "sys", | |
430 | .ops = &msi_ops, | |
431 | .parent_names = dmn_clk_parents, | |
432 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
433 | .flags = CLK_SET_RATE_GATE, | |
434 | }; | |
02c981c0 | 435 | |
198678b0 BD |
436 | static struct clk_dmn clk_sys = { |
437 | .regofs = SIRFSOC_CLKC_SYS_CFG, | |
438 | .hw = { | |
439 | .init = &clk_sys_init, | |
440 | }, | |
441 | }; | |
02c981c0 | 442 | |
198678b0 BD |
443 | static struct clk_init_data clk_io_init = { |
444 | .name = "io", | |
445 | .ops = &msi_ops, | |
446 | .parent_names = dmn_clk_parents, | |
447 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
448 | }; | |
02c981c0 | 449 | |
198678b0 BD |
450 | static struct clk_dmn clk_io = { |
451 | .regofs = SIRFSOC_CLKC_IO_CFG, | |
452 | .hw = { | |
453 | .init = &clk_io_init, | |
454 | }, | |
455 | }; | |
02c981c0 BD |
456 | |
457 | static struct clk_ops cpu_ops = { | |
198678b0 BD |
458 | .set_parent = dmn_clk_set_parent, |
459 | .get_parent = dmn_clk_get_parent, | |
02c981c0 BD |
460 | }; |
461 | ||
198678b0 BD |
462 | static struct clk_init_data clk_cpu_init = { |
463 | .name = "cpu", | |
02c981c0 | 464 | .ops = &cpu_ops, |
198678b0 BD |
465 | .parent_names = dmn_clk_parents, |
466 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
467 | .flags = CLK_SET_RATE_PARENT, | |
02c981c0 BD |
468 | }; |
469 | ||
198678b0 BD |
470 | static struct clk_dmn clk_cpu = { |
471 | .regofs = SIRFSOC_CLKC_CPU_CFG, | |
472 | .hw = { | |
473 | .init = &clk_cpu_init, | |
474 | }, | |
475 | }; | |
02c981c0 | 476 | |
198678b0 BD |
477 | static struct clk_ops dmn_ops = { |
478 | .is_enabled = std_clk_is_enabled, | |
479 | .enable = std_clk_enable, | |
480 | .disable = std_clk_disable, | |
481 | .set_rate = dmn_clk_set_rate, | |
482 | .round_rate = dmn_clk_round_rate, | |
483 | .recalc_rate = dmn_clk_recalc_rate, | |
484 | .set_parent = dmn_clk_set_parent, | |
485 | .get_parent = dmn_clk_get_parent, | |
02c981c0 BD |
486 | }; |
487 | ||
198678b0 BD |
488 | /* dsp, gfx, mm, lcd and vpp domain */ |
489 | ||
490 | static struct clk_init_data clk_dsp_init = { | |
491 | .name = "dsp", | |
492 | .ops = &dmn_ops, | |
493 | .parent_names = dmn_clk_parents, | |
494 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
02c981c0 BD |
495 | }; |
496 | ||
198678b0 BD |
497 | static struct clk_dmn clk_dsp = { |
498 | .regofs = SIRFSOC_CLKC_DSP_CFG, | |
499 | .enable_bit = 0, | |
500 | .hw = { | |
501 | .init = &clk_dsp_init, | |
502 | }, | |
02c981c0 BD |
503 | }; |
504 | ||
198678b0 BD |
505 | static struct clk_init_data clk_gfx_init = { |
506 | .name = "gfx", | |
507 | .ops = &dmn_ops, | |
508 | .parent_names = dmn_clk_parents, | |
509 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
02c981c0 BD |
510 | }; |
511 | ||
198678b0 BD |
512 | static struct clk_dmn clk_gfx = { |
513 | .regofs = SIRFSOC_CLKC_GFX_CFG, | |
514 | .enable_bit = 8, | |
515 | .hw = { | |
516 | .init = &clk_gfx_init, | |
517 | }, | |
518 | }; | |
02c981c0 | 519 | |
198678b0 BD |
520 | static struct clk_init_data clk_mm_init = { |
521 | .name = "mm", | |
522 | .ops = &dmn_ops, | |
523 | .parent_names = dmn_clk_parents, | |
524 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
525 | }; | |
02c981c0 | 526 | |
198678b0 BD |
527 | static struct clk_dmn clk_mm = { |
528 | .regofs = SIRFSOC_CLKC_MM_CFG, | |
529 | .enable_bit = 9, | |
530 | .hw = { | |
531 | .init = &clk_mm_init, | |
532 | }, | |
533 | }; | |
02c981c0 | 534 | |
198678b0 BD |
535 | static struct clk_init_data clk_lcd_init = { |
536 | .name = "lcd", | |
537 | .ops = &dmn_ops, | |
538 | .parent_names = dmn_clk_parents, | |
539 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
540 | }; | |
02c981c0 | 541 | |
198678b0 BD |
542 | static struct clk_dmn clk_lcd = { |
543 | .regofs = SIRFSOC_CLKC_LCD_CFG, | |
544 | .enable_bit = 10, | |
545 | .hw = { | |
546 | .init = &clk_lcd_init, | |
547 | }, | |
548 | }; | |
02c981c0 | 549 | |
198678b0 BD |
550 | static struct clk_init_data clk_vpp_init = { |
551 | .name = "vpp", | |
552 | .ops = &dmn_ops, | |
553 | .parent_names = dmn_clk_parents, | |
554 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
555 | }; | |
02c981c0 | 556 | |
198678b0 BD |
557 | static struct clk_dmn clk_vpp = { |
558 | .regofs = SIRFSOC_CLKC_LCD_CFG, | |
559 | .enable_bit = 11, | |
560 | .hw = { | |
561 | .init = &clk_vpp_init, | |
562 | }, | |
563 | }; | |
02c981c0 | 564 | |
198678b0 BD |
565 | static struct clk_init_data clk_mmc01_init = { |
566 | .name = "mmc01", | |
567 | .ops = &dmn_ops, | |
568 | .parent_names = dmn_clk_parents, | |
569 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
570 | }; | |
02c981c0 | 571 | |
198678b0 BD |
572 | static struct clk_dmn clk_mmc01 = { |
573 | .regofs = SIRFSOC_CLKC_MMC_CFG, | |
574 | .enable_bit = 59, | |
575 | .hw = { | |
576 | .init = &clk_mmc01_init, | |
577 | }, | |
578 | }; | |
02c981c0 | 579 | |
198678b0 BD |
580 | static struct clk_init_data clk_mmc23_init = { |
581 | .name = "mmc23", | |
582 | .ops = &dmn_ops, | |
583 | .parent_names = dmn_clk_parents, | |
584 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
585 | }; | |
02c981c0 | 586 | |
198678b0 BD |
587 | static struct clk_dmn clk_mmc23 = { |
588 | .regofs = SIRFSOC_CLKC_MMC_CFG, | |
589 | .enable_bit = 60, | |
590 | .hw = { | |
591 | .init = &clk_mmc23_init, | |
592 | }, | |
593 | }; | |
02c981c0 | 594 | |
198678b0 BD |
595 | static struct clk_init_data clk_mmc45_init = { |
596 | .name = "mmc45", | |
597 | .ops = &dmn_ops, | |
598 | .parent_names = dmn_clk_parents, | |
599 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | |
600 | }; | |
02c981c0 | 601 | |
198678b0 BD |
602 | static struct clk_dmn clk_mmc45 = { |
603 | .regofs = SIRFSOC_CLKC_MMC_CFG, | |
604 | .enable_bit = 61, | |
605 | .hw = { | |
606 | .init = &clk_mmc45_init, | |
607 | }, | |
608 | }; | |
02c981c0 | 609 | |
198678b0 BD |
610 | /* |
611 | * peripheral controllers in io domain | |
612 | */ | |
613 | ||
614 | static int std_clk_is_enabled(struct clk_hw *hw) | |
02c981c0 | 615 | { |
198678b0 BD |
616 | u32 reg; |
617 | int bit; | |
618 | struct clk_std *clk = to_stdclk(hw); | |
02c981c0 | 619 | |
198678b0 BD |
620 | bit = clk->enable_bit % 32; |
621 | reg = clk->enable_bit / 32; | |
622 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | |
02c981c0 | 623 | |
198678b0 | 624 | return !!(clkc_readl(reg) & BIT(bit)); |
02c981c0 | 625 | } |
02c981c0 | 626 | |
198678b0 | 627 | static int std_clk_enable(struct clk_hw *hw) |
02c981c0 | 628 | { |
198678b0 BD |
629 | u32 val, reg; |
630 | int bit; | |
631 | struct clk_std *clk = to_stdclk(hw); | |
02c981c0 | 632 | |
198678b0 BD |
633 | BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); |
634 | ||
635 | bit = clk->enable_bit % 32; | |
636 | reg = clk->enable_bit / 32; | |
637 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | |
02c981c0 | 638 | |
198678b0 BD |
639 | val = clkc_readl(reg) | BIT(bit); |
640 | clkc_writel(val, reg); | |
641 | return 0; | |
02c981c0 | 642 | } |
02c981c0 | 643 | |
198678b0 | 644 | static void std_clk_disable(struct clk_hw *hw) |
02c981c0 | 645 | { |
198678b0 BD |
646 | u32 val, reg; |
647 | int bit; | |
648 | struct clk_std *clk = to_stdclk(hw); | |
02c981c0 | 649 | |
198678b0 | 650 | BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); |
02c981c0 | 651 | |
198678b0 BD |
652 | bit = clk->enable_bit % 32; |
653 | reg = clk->enable_bit / 32; | |
654 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | |
02c981c0 | 655 | |
198678b0 BD |
656 | val = clkc_readl(reg) & ~BIT(bit); |
657 | clkc_writel(val, reg); | |
02c981c0 | 658 | } |
02c981c0 | 659 | |
198678b0 BD |
660 | static const char *std_clk_io_parents[] = { |
661 | "io", | |
662 | }; | |
02c981c0 | 663 | |
198678b0 BD |
664 | static struct clk_ops ios_ops = { |
665 | .is_enabled = std_clk_is_enabled, | |
666 | .enable = std_clk_enable, | |
667 | .disable = std_clk_disable, | |
668 | }; | |
02c981c0 | 669 | |
198678b0 BD |
670 | static struct clk_init_data clk_dmac0_init = { |
671 | .name = "dmac0", | |
672 | .ops = &ios_ops, | |
673 | .parent_names = std_clk_io_parents, | |
674 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
675 | }; | |
02c981c0 | 676 | |
198678b0 BD |
677 | static struct clk_std clk_dmac0 = { |
678 | .enable_bit = 32, | |
679 | .hw = { | |
680 | .init = &clk_dmac0_init, | |
681 | }, | |
682 | }; | |
02c981c0 | 683 | |
198678b0 BD |
684 | static struct clk_init_data clk_dmac1_init = { |
685 | .name = "dmac1", | |
686 | .ops = &ios_ops, | |
687 | .parent_names = std_clk_io_parents, | |
688 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
689 | }; | |
690 | ||
691 | static struct clk_std clk_dmac1 = { | |
692 | .enable_bit = 33, | |
693 | .hw = { | |
694 | .init = &clk_dmac1_init, | |
695 | }, | |
696 | }; | |
697 | ||
698 | static struct clk_init_data clk_nand_init = { | |
699 | .name = "nand", | |
700 | .ops = &ios_ops, | |
701 | .parent_names = std_clk_io_parents, | |
702 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
703 | }; | |
704 | ||
705 | static struct clk_std clk_nand = { | |
706 | .enable_bit = 34, | |
707 | .hw = { | |
708 | .init = &clk_nand_init, | |
709 | }, | |
710 | }; | |
711 | ||
712 | static struct clk_init_data clk_audio_init = { | |
713 | .name = "audio", | |
714 | .ops = &ios_ops, | |
715 | .parent_names = std_clk_io_parents, | |
716 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
717 | }; | |
718 | ||
719 | static struct clk_std clk_audio = { | |
720 | .enable_bit = 35, | |
721 | .hw = { | |
722 | .init = &clk_audio_init, | |
723 | }, | |
724 | }; | |
725 | ||
726 | static struct clk_init_data clk_uart0_init = { | |
727 | .name = "uart0", | |
728 | .ops = &ios_ops, | |
729 | .parent_names = std_clk_io_parents, | |
730 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
731 | }; | |
732 | ||
733 | static struct clk_std clk_uart0 = { | |
734 | .enable_bit = 36, | |
735 | .hw = { | |
736 | .init = &clk_uart0_init, | |
737 | }, | |
738 | }; | |
739 | ||
740 | static struct clk_init_data clk_uart1_init = { | |
741 | .name = "uart1", | |
742 | .ops = &ios_ops, | |
743 | .parent_names = std_clk_io_parents, | |
744 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
745 | }; | |
746 | ||
747 | static struct clk_std clk_uart1 = { | |
748 | .enable_bit = 37, | |
749 | .hw = { | |
750 | .init = &clk_uart1_init, | |
751 | }, | |
752 | }; | |
753 | ||
754 | static struct clk_init_data clk_uart2_init = { | |
755 | .name = "uart2", | |
756 | .ops = &ios_ops, | |
757 | .parent_names = std_clk_io_parents, | |
758 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
759 | }; | |
760 | ||
761 | static struct clk_std clk_uart2 = { | |
762 | .enable_bit = 38, | |
763 | .hw = { | |
764 | .init = &clk_uart2_init, | |
765 | }, | |
766 | }; | |
767 | ||
768 | static struct clk_init_data clk_usp0_init = { | |
769 | .name = "usp0", | |
770 | .ops = &ios_ops, | |
771 | .parent_names = std_clk_io_parents, | |
772 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
773 | }; | |
774 | ||
775 | static struct clk_std clk_usp0 = { | |
776 | .enable_bit = 39, | |
777 | .hw = { | |
778 | .init = &clk_usp0_init, | |
779 | }, | |
780 | }; | |
781 | ||
782 | static struct clk_init_data clk_usp1_init = { | |
783 | .name = "usp1", | |
784 | .ops = &ios_ops, | |
785 | .parent_names = std_clk_io_parents, | |
786 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
787 | }; | |
788 | ||
789 | static struct clk_std clk_usp1 = { | |
790 | .enable_bit = 40, | |
791 | .hw = { | |
792 | .init = &clk_usp1_init, | |
793 | }, | |
794 | }; | |
795 | ||
796 | static struct clk_init_data clk_usp2_init = { | |
797 | .name = "usp2", | |
798 | .ops = &ios_ops, | |
799 | .parent_names = std_clk_io_parents, | |
800 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
801 | }; | |
802 | ||
803 | static struct clk_std clk_usp2 = { | |
804 | .enable_bit = 41, | |
805 | .hw = { | |
806 | .init = &clk_usp2_init, | |
807 | }, | |
808 | }; | |
809 | ||
810 | static struct clk_init_data clk_vip_init = { | |
811 | .name = "vip", | |
812 | .ops = &ios_ops, | |
813 | .parent_names = std_clk_io_parents, | |
814 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
815 | }; | |
816 | ||
817 | static struct clk_std clk_vip = { | |
818 | .enable_bit = 42, | |
819 | .hw = { | |
820 | .init = &clk_vip_init, | |
821 | }, | |
822 | }; | |
823 | ||
824 | static struct clk_init_data clk_spi0_init = { | |
825 | .name = "spi0", | |
826 | .ops = &ios_ops, | |
827 | .parent_names = std_clk_io_parents, | |
828 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
829 | }; | |
830 | ||
831 | static struct clk_std clk_spi0 = { | |
832 | .enable_bit = 43, | |
833 | .hw = { | |
834 | .init = &clk_spi0_init, | |
835 | }, | |
836 | }; | |
837 | ||
838 | static struct clk_init_data clk_spi1_init = { | |
839 | .name = "spi1", | |
840 | .ops = &ios_ops, | |
841 | .parent_names = std_clk_io_parents, | |
842 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
843 | }; | |
844 | ||
845 | static struct clk_std clk_spi1 = { | |
846 | .enable_bit = 44, | |
847 | .hw = { | |
848 | .init = &clk_spi1_init, | |
849 | }, | |
850 | }; | |
851 | ||
852 | static struct clk_init_data clk_tsc_init = { | |
853 | .name = "tsc", | |
854 | .ops = &ios_ops, | |
855 | .parent_names = std_clk_io_parents, | |
856 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
857 | }; | |
858 | ||
859 | static struct clk_std clk_tsc = { | |
860 | .enable_bit = 45, | |
861 | .hw = { | |
862 | .init = &clk_tsc_init, | |
863 | }, | |
864 | }; | |
865 | ||
866 | static struct clk_init_data clk_i2c0_init = { | |
867 | .name = "i2c0", | |
868 | .ops = &ios_ops, | |
869 | .parent_names = std_clk_io_parents, | |
870 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
871 | }; | |
872 | ||
873 | static struct clk_std clk_i2c0 = { | |
874 | .enable_bit = 46, | |
875 | .hw = { | |
876 | .init = &clk_i2c0_init, | |
877 | }, | |
878 | }; | |
879 | ||
880 | static struct clk_init_data clk_i2c1_init = { | |
881 | .name = "i2c1", | |
882 | .ops = &ios_ops, | |
883 | .parent_names = std_clk_io_parents, | |
884 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
885 | }; | |
886 | ||
887 | static struct clk_std clk_i2c1 = { | |
888 | .enable_bit = 47, | |
889 | .hw = { | |
890 | .init = &clk_i2c1_init, | |
891 | }, | |
892 | }; | |
893 | ||
894 | static struct clk_init_data clk_pwmc_init = { | |
895 | .name = "pwmc", | |
896 | .ops = &ios_ops, | |
897 | .parent_names = std_clk_io_parents, | |
898 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
899 | }; | |
900 | ||
901 | static struct clk_std clk_pwmc = { | |
902 | .enable_bit = 48, | |
903 | .hw = { | |
904 | .init = &clk_pwmc_init, | |
905 | }, | |
906 | }; | |
907 | ||
908 | static struct clk_init_data clk_efuse_init = { | |
909 | .name = "efuse", | |
910 | .ops = &ios_ops, | |
911 | .parent_names = std_clk_io_parents, | |
912 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
913 | }; | |
914 | ||
915 | static struct clk_std clk_efuse = { | |
916 | .enable_bit = 49, | |
917 | .hw = { | |
918 | .init = &clk_efuse_init, | |
919 | }, | |
920 | }; | |
921 | ||
922 | static struct clk_init_data clk_pulse_init = { | |
923 | .name = "pulse", | |
924 | .ops = &ios_ops, | |
925 | .parent_names = std_clk_io_parents, | |
926 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
927 | }; | |
928 | ||
929 | static struct clk_std clk_pulse = { | |
930 | .enable_bit = 50, | |
931 | .hw = { | |
932 | .init = &clk_pulse_init, | |
933 | }, | |
934 | }; | |
935 | ||
936 | static const char *std_clk_dsp_parents[] = { | |
937 | "dsp", | |
938 | }; | |
939 | ||
940 | static struct clk_init_data clk_gps_init = { | |
941 | .name = "gps", | |
942 | .ops = &ios_ops, | |
943 | .parent_names = std_clk_dsp_parents, | |
944 | .num_parents = ARRAY_SIZE(std_clk_dsp_parents), | |
945 | }; | |
946 | ||
947 | static struct clk_std clk_gps = { | |
948 | .enable_bit = 1, | |
949 | .hw = { | |
950 | .init = &clk_gps_init, | |
951 | }, | |
952 | }; | |
953 | ||
954 | static struct clk_init_data clk_mf_init = { | |
955 | .name = "mf", | |
956 | .ops = &ios_ops, | |
957 | .parent_names = std_clk_io_parents, | |
958 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | |
959 | }; | |
960 | ||
961 | static struct clk_std clk_mf = { | |
962 | .enable_bit = 2, | |
963 | .hw = { | |
964 | .init = &clk_mf_init, | |
965 | }, | |
966 | }; | |
967 | ||
968 | static const char *std_clk_sys_parents[] = { | |
969 | "sys", | |
970 | }; | |
971 | ||
972 | static struct clk_init_data clk_security_init = { | |
973 | .name = "mf", | |
974 | .ops = &ios_ops, | |
975 | .parent_names = std_clk_sys_parents, | |
976 | .num_parents = ARRAY_SIZE(std_clk_sys_parents), | |
977 | }; | |
978 | ||
979 | static struct clk_std clk_security = { | |
980 | .enable_bit = 19, | |
981 | .hw = { | |
982 | .init = &clk_security_init, | |
983 | }, | |
984 | }; | |
985 | ||
986 | static const char *std_clk_usb_parents[] = { | |
987 | "usb_pll", | |
988 | }; | |
989 | ||
990 | static struct clk_init_data clk_usb0_init = { | |
991 | .name = "usb0", | |
992 | .ops = &ios_ops, | |
993 | .parent_names = std_clk_usb_parents, | |
994 | .num_parents = ARRAY_SIZE(std_clk_usb_parents), | |
995 | }; | |
996 | ||
997 | static struct clk_std clk_usb0 = { | |
998 | .enable_bit = 16, | |
999 | .hw = { | |
1000 | .init = &clk_usb0_init, | |
1001 | }, | |
1002 | }; | |
1003 | ||
1004 | static struct clk_init_data clk_usb1_init = { | |
1005 | .name = "usb1", | |
1006 | .ops = &ios_ops, | |
1007 | .parent_names = std_clk_usb_parents, | |
1008 | .num_parents = ARRAY_SIZE(std_clk_usb_parents), | |
1009 | }; | |
1010 | ||
1011 | static struct clk_std clk_usb1 = { | |
1012 | .enable_bit = 17, | |
1013 | .hw = { | |
1014 | .init = &clk_usb1_init, | |
1015 | }, | |
1016 | }; | |
02c981c0 BD |
1017 | |
1018 | static struct of_device_id clkc_ids[] = { | |
1019 | { .compatible = "sirf,prima2-clkc" }, | |
6a53747b | 1020 | {}, |
02c981c0 BD |
1021 | }; |
1022 | ||
198678b0 BD |
1023 | static struct of_device_id rsc_ids[] = { |
1024 | { .compatible = "sirf,prima2-rsc" }, | |
1025 | {}, | |
1026 | }; | |
1027 | ||
eb8b8f2e BS |
1028 | enum prima2_clk_index { |
1029 | /* 0 1 2 3 4 5 6 7 8 9 */ | |
1030 | rtc, osc, pll1, pll2, pll3, mem, sys, security, dsp, gps, | |
1031 | mf, io, cpu, uart0, uart1, uart2, tsc, i2c0, i2c1, spi0, | |
1032 | spi1, pwmc, efuse, pulse, dmac0, dmac1, nand, audio, usp0, usp1, | |
1033 | usp2, vip, gfx, mm, lcd, vpp, mmc01, mmc23, mmc45, usbpll, | |
1034 | usb0, usb1, maxclk, | |
1035 | }; | |
1036 | ||
18f5863e | 1037 | static struct clk_hw *prima2_clk_hw_array[maxclk] __initdata = { |
eb8b8f2e BS |
1038 | NULL, /* dummy */ |
1039 | NULL, | |
1040 | &clk_pll1.hw, | |
1041 | &clk_pll2.hw, | |
1042 | &clk_pll3.hw, | |
1043 | &clk_mem.hw, | |
1044 | &clk_sys.hw, | |
1045 | &clk_security.hw, | |
1046 | &clk_dsp.hw, | |
1047 | &clk_gps.hw, | |
1048 | &clk_mf.hw, | |
1049 | &clk_io.hw, | |
1050 | &clk_cpu.hw, | |
1051 | &clk_uart0.hw, | |
1052 | &clk_uart1.hw, | |
1053 | &clk_uart2.hw, | |
1054 | &clk_tsc.hw, | |
1055 | &clk_i2c0.hw, | |
1056 | &clk_i2c1.hw, | |
1057 | &clk_spi0.hw, | |
1058 | &clk_spi1.hw, | |
1059 | &clk_pwmc.hw, | |
1060 | &clk_efuse.hw, | |
1061 | &clk_pulse.hw, | |
1062 | &clk_dmac0.hw, | |
1063 | &clk_dmac1.hw, | |
1064 | &clk_nand.hw, | |
1065 | &clk_audio.hw, | |
1066 | &clk_usp0.hw, | |
1067 | &clk_usp1.hw, | |
1068 | &clk_usp2.hw, | |
1069 | &clk_vip.hw, | |
1070 | &clk_gfx.hw, | |
1071 | &clk_mm.hw, | |
1072 | &clk_lcd.hw, | |
1073 | &clk_vpp.hw, | |
1074 | &clk_mmc01.hw, | |
1075 | &clk_mmc23.hw, | |
1076 | &clk_mmc45.hw, | |
1077 | &usb_pll_clk_hw, | |
1078 | &clk_usb0.hw, | |
1079 | &clk_usb1.hw, | |
1080 | }; | |
1081 | ||
1082 | static struct clk *prima2_clks[maxclk]; | |
1083 | static struct clk_onecell_data clk_data; | |
1084 | ||
02c981c0 BD |
1085 | void __init sirfsoc_of_clk_init(void) |
1086 | { | |
1087 | struct device_node *np; | |
eb8b8f2e | 1088 | int i; |
02c981c0 | 1089 | |
198678b0 BD |
1090 | np = of_find_matching_node(NULL, rsc_ids); |
1091 | if (!np) | |
1092 | panic("unable to find compatible rsc node in dtb\n"); | |
1093 | ||
1094 | sirfsoc_rsc_vbase = of_iomap(np, 0); | |
1095 | if (!sirfsoc_rsc_vbase) | |
1096 | panic("unable to map rsc registers\n"); | |
1097 | ||
1098 | of_node_put(np); | |
02c981c0 | 1099 | |
eb8b8f2e BS |
1100 | np = of_find_matching_node(NULL, clkc_ids); |
1101 | if (!np) | |
1102 | return; | |
1103 | ||
1104 | sirfsoc_clk_vbase = of_iomap(np, 0); | |
1105 | if (!sirfsoc_clk_vbase) | |
1106 | panic("unable to map clkc registers\n"); | |
02c981c0 | 1107 | |
198678b0 | 1108 | /* These are always available (RTC and 26MHz OSC)*/ |
eb8b8f2e | 1109 | prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, |
198678b0 | 1110 | CLK_IS_ROOT, 32768); |
eb8b8f2e | 1111 | prima2_clks[osc]= clk_register_fixed_rate(NULL, "osc", NULL, |
198678b0 | 1112 | CLK_IS_ROOT, 26000000); |
eb8b8f2e BS |
1113 | |
1114 | for (i = pll1; i < maxclk; i++) { | |
1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); | |
f15ea6cb | 1116 | BUG_ON(IS_ERR(prima2_clks[i])); |
eb8b8f2e BS |
1117 | } |
1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); | |
1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); | |
1120 | clk_register_clkdev(prima2_clks[mem], NULL, "mem"); | |
1121 | ||
1122 | clk_data.clks = prima2_clks; | |
1123 | clk_data.clk_num = maxclk; | |
1124 | ||
1125 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | |
02c981c0 | 1126 | } |