]>
Commit | Line | Data |
---|---|---|
c3d2689d AZ |
1 | /* |
2 | * OMAP clocks. | |
3 | * | |
4 | * Copyright (C) 2006-2007 Andrzej Zaborowski <[email protected]> | |
5 | * | |
6 | * Clocks data comes in part from arch/arm/mach-omap1/clock.h in Linux. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | #include "vl.h" | |
24 | ||
25 | struct clk { | |
26 | const char *name; | |
27 | const char *alias; | |
28 | struct clk *parent; | |
29 | struct clk *child1; | |
30 | struct clk *sibling; | |
31 | #define ALWAYS_ENABLED (1 << 0) | |
32 | #define CLOCK_IN_OMAP310 (1 << 10) | |
33 | #define CLOCK_IN_OMAP730 (1 << 11) | |
34 | #define CLOCK_IN_OMAP1510 (1 << 12) | |
35 | #define CLOCK_IN_OMAP16XX (1 << 13) | |
36 | uint32_t flags; | |
37 | int id; | |
38 | ||
39 | int running; /* Is currently ticking */ | |
40 | int enabled; /* Is enabled, regardless of its input clk */ | |
41 | unsigned long rate; /* Current rate (if .running) */ | |
42 | unsigned int divisor; /* Rate relative to input (if .enabled) */ | |
43 | unsigned int multiplier; /* Rate relative to input (if .enabled) */ | |
44 | qemu_irq users[16]; /* Who to notify on change */ | |
45 | int usecount; /* Automatically idle when unused */ | |
46 | }; | |
47 | ||
48 | static struct clk xtal_osc12m = { | |
49 | .name = "xtal_osc_12m", | |
50 | .rate = 12000000, | |
51 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
52 | }; | |
53 | ||
54 | static struct clk xtal_osc32k = { | |
55 | .name = "xtal_osc_32k", | |
56 | .rate = 32768, | |
57 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
58 | }; | |
59 | ||
60 | static struct clk ck_ref = { | |
61 | .name = "ck_ref", | |
62 | .alias = "clkin", | |
63 | .parent = &xtal_osc12m, | |
64 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
65 | ALWAYS_ENABLED, | |
66 | }; | |
67 | ||
68 | /* If a dpll is disabled it becomes a bypass, child clocks don't stop */ | |
69 | static struct clk dpll1 = { | |
70 | .name = "dpll1", | |
71 | .parent = &ck_ref, | |
72 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
73 | ALWAYS_ENABLED, | |
74 | }; | |
75 | ||
76 | static struct clk dpll2 = { | |
77 | .name = "dpll2", | |
78 | .parent = &ck_ref, | |
79 | .flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED, | |
80 | }; | |
81 | ||
82 | static struct clk dpll3 = { | |
83 | .name = "dpll3", | |
84 | .parent = &ck_ref, | |
85 | .flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED, | |
86 | }; | |
87 | ||
88 | static struct clk dpll4 = { | |
89 | .name = "dpll4", | |
90 | .parent = &ck_ref, | |
91 | .multiplier = 4, | |
92 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
93 | }; | |
94 | ||
95 | static struct clk apll = { | |
96 | .name = "apll", | |
97 | .parent = &ck_ref, | |
98 | .multiplier = 48, | |
99 | .divisor = 12, | |
100 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
101 | }; | |
102 | ||
103 | static struct clk ck_48m = { | |
104 | .name = "ck_48m", | |
105 | .parent = &dpll4, /* either dpll4 or apll */ | |
106 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
107 | }; | |
108 | ||
109 | static struct clk ck_dpll1out = { | |
110 | .name = "ck_dpll1out", | |
111 | .parent = &dpll1, | |
112 | .flags = CLOCK_IN_OMAP16XX, | |
113 | }; | |
114 | ||
115 | static struct clk sossi_ck = { | |
116 | .name = "ck_sossi", | |
117 | .parent = &ck_dpll1out, | |
118 | .flags = CLOCK_IN_OMAP16XX, | |
119 | }; | |
120 | ||
121 | static struct clk clkm1 = { | |
122 | .name = "clkm1", | |
123 | .alias = "ck_gen1", | |
124 | .parent = &dpll1, | |
125 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
126 | ALWAYS_ENABLED, | |
127 | }; | |
128 | ||
129 | static struct clk clkm2 = { | |
130 | .name = "clkm2", | |
131 | .alias = "ck_gen2", | |
132 | .parent = &dpll1, | |
133 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
134 | ALWAYS_ENABLED, | |
135 | }; | |
136 | ||
137 | static struct clk clkm3 = { | |
138 | .name = "clkm3", | |
139 | .alias = "ck_gen3", | |
140 | .parent = &dpll1, /* either dpll1 or ck_ref */ | |
141 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
142 | ALWAYS_ENABLED, | |
143 | }; | |
144 | ||
145 | static struct clk arm_ck = { | |
146 | .name = "arm_ck", | |
147 | .alias = "mpu_ck", | |
148 | .parent = &clkm1, | |
149 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
150 | ALWAYS_ENABLED, | |
151 | }; | |
152 | ||
153 | static struct clk armper_ck = { | |
154 | .name = "armper_ck", | |
155 | .alias = "mpuper_ck", | |
156 | .parent = &clkm1, | |
157 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
158 | }; | |
159 | ||
160 | static struct clk arm_gpio_ck = { | |
161 | .name = "arm_gpio_ck", | |
162 | .alias = "mpu_gpio_ck", | |
163 | .parent = &clkm1, | |
164 | .divisor = 1, | |
165 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, | |
166 | }; | |
167 | ||
168 | static struct clk armxor_ck = { | |
169 | .name = "armxor_ck", | |
170 | .alias = "mpuxor_ck", | |
171 | .parent = &ck_ref, | |
172 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
173 | }; | |
174 | ||
175 | static struct clk armtim_ck = { | |
176 | .name = "armtim_ck", | |
177 | .alias = "mputim_ck", | |
178 | .parent = &ck_ref, /* either CLKIN or DPLL1 */ | |
179 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
180 | }; | |
181 | ||
182 | static struct clk armwdt_ck = { | |
183 | .name = "armwdt_ck", | |
184 | .alias = "mpuwd_ck", | |
185 | .parent = &clkm1, | |
186 | .divisor = 14, | |
187 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
188 | ALWAYS_ENABLED, | |
189 | }; | |
190 | ||
191 | static struct clk arminth_ck16xx = { | |
192 | .name = "arminth_ck", | |
193 | .parent = &arm_ck, | |
194 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | |
195 | /* Note: On 16xx the frequency can be divided by 2 by programming | |
196 | * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 | |
197 | * | |
198 | * 1510 version is in TC clocks. | |
199 | */ | |
200 | }; | |
201 | ||
202 | static struct clk dsp_ck = { | |
203 | .name = "dsp_ck", | |
204 | .parent = &clkm2, | |
205 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
206 | }; | |
207 | ||
208 | static struct clk dspmmu_ck = { | |
209 | .name = "dspmmu_ck", | |
210 | .parent = &clkm2, | |
211 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | |
212 | ALWAYS_ENABLED, | |
213 | }; | |
214 | ||
215 | static struct clk dspper_ck = { | |
216 | .name = "dspper_ck", | |
217 | .parent = &clkm2, | |
218 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
219 | }; | |
220 | ||
221 | static struct clk dspxor_ck = { | |
222 | .name = "dspxor_ck", | |
223 | .parent = &ck_ref, | |
224 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
225 | }; | |
226 | ||
227 | static struct clk dsptim_ck = { | |
228 | .name = "dsptim_ck", | |
229 | .parent = &ck_ref, | |
230 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
231 | }; | |
232 | ||
233 | static struct clk tc_ck = { | |
234 | .name = "tc_ck", | |
235 | .parent = &clkm3, | |
236 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | |
237 | CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | | |
238 | ALWAYS_ENABLED, | |
239 | }; | |
240 | ||
241 | static struct clk arminth_ck15xx = { | |
242 | .name = "arminth_ck", | |
243 | .parent = &tc_ck, | |
244 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, | |
245 | /* Note: On 1510 the frequency follows TC_CK | |
246 | * | |
247 | * 16xx version is in MPU clocks. | |
248 | */ | |
249 | }; | |
250 | ||
251 | static struct clk tipb_ck = { | |
252 | /* No-idle controlled by "tc_ck" */ | |
253 | .name = "tipb_ck", | |
254 | .parent = &tc_ck, | |
255 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, | |
256 | }; | |
257 | ||
258 | static struct clk l3_ocpi_ck = { | |
259 | /* No-idle controlled by "tc_ck" */ | |
260 | .name = "l3_ocpi_ck", | |
261 | .parent = &tc_ck, | |
262 | .flags = CLOCK_IN_OMAP16XX, | |
263 | }; | |
264 | ||
265 | static struct clk tc1_ck = { | |
266 | .name = "tc1_ck", | |
267 | .parent = &tc_ck, | |
268 | .flags = CLOCK_IN_OMAP16XX, | |
269 | }; | |
270 | ||
271 | static struct clk tc2_ck = { | |
272 | .name = "tc2_ck", | |
273 | .parent = &tc_ck, | |
274 | .flags = CLOCK_IN_OMAP16XX, | |
275 | }; | |
276 | ||
277 | static struct clk dma_ck = { | |
278 | /* No-idle controlled by "tc_ck" */ | |
279 | .name = "dma_ck", | |
280 | .parent = &tc_ck, | |
281 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
282 | ALWAYS_ENABLED, | |
283 | }; | |
284 | ||
285 | static struct clk dma_lcdfree_ck = { | |
286 | .name = "dma_lcdfree_ck", | |
287 | .parent = &tc_ck, | |
288 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | |
289 | }; | |
290 | ||
291 | static struct clk api_ck = { | |
292 | .name = "api_ck", | |
293 | .alias = "mpui_ck", | |
294 | .parent = &tc_ck, | |
295 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
296 | }; | |
297 | ||
298 | static struct clk lb_ck = { | |
299 | .name = "lb_ck", | |
300 | .parent = &tc_ck, | |
301 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, | |
302 | }; | |
303 | ||
304 | static struct clk lbfree_ck = { | |
305 | .name = "lbfree_ck", | |
306 | .parent = &tc_ck, | |
307 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, | |
308 | }; | |
309 | ||
310 | static struct clk rhea1_ck = { | |
311 | .name = "rhea1_ck", | |
312 | .parent = &tc_ck, | |
313 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | |
314 | }; | |
315 | ||
316 | static struct clk rhea2_ck = { | |
317 | .name = "rhea2_ck", | |
318 | .parent = &tc_ck, | |
319 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | |
320 | }; | |
321 | ||
322 | static struct clk lcd_ck_16xx = { | |
323 | .name = "lcd_ck", | |
324 | .parent = &clkm3, | |
325 | .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730, | |
326 | }; | |
327 | ||
328 | static struct clk lcd_ck_1510 = { | |
329 | .name = "lcd_ck", | |
330 | .parent = &clkm3, | |
331 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, | |
332 | }; | |
333 | ||
334 | static struct clk uart1_1510 = { | |
335 | .name = "uart1_ck", | |
336 | /* Direct from ULPD, no real parent */ | |
337 | .parent = &armper_ck, /* either armper_ck or dpll4 */ | |
338 | .rate = 12000000, | |
339 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, | |
340 | }; | |
341 | ||
342 | static struct clk uart1_16xx = { | |
343 | .name = "uart1_ck", | |
344 | /* Direct from ULPD, no real parent */ | |
345 | .parent = &armper_ck, | |
346 | .rate = 48000000, | |
347 | .flags = CLOCK_IN_OMAP16XX, | |
348 | }; | |
349 | ||
350 | static struct clk uart2_ck = { | |
351 | .name = "uart2_ck", | |
352 | /* Direct from ULPD, no real parent */ | |
353 | .parent = &armper_ck, /* either armper_ck or dpll4 */ | |
354 | .rate = 12000000, | |
355 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | | |
356 | ALWAYS_ENABLED, | |
357 | }; | |
358 | ||
359 | static struct clk uart3_1510 = { | |
360 | .name = "uart3_ck", | |
361 | /* Direct from ULPD, no real parent */ | |
362 | .parent = &armper_ck,/* either armper_ck or dpll4 */ | |
363 | .rate = 12000000, | |
364 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, | |
365 | }; | |
366 | ||
367 | static struct clk uart3_16xx = { | |
368 | .name = "uart3_ck", | |
369 | /* Direct from ULPD, no real parent */ | |
370 | .parent = &armper_ck, | |
371 | .rate = 48000000, | |
372 | .flags = CLOCK_IN_OMAP16XX, | |
373 | }; | |
374 | ||
375 | static struct clk usb_clk0 = { /* 6 MHz output on W4_USB_CLK0 */ | |
376 | .name = "usb_clk0", | |
377 | .alias = "usb.clko", | |
378 | /* Direct from ULPD, no parent */ | |
379 | .rate = 6000000, | |
380 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
381 | }; | |
382 | ||
383 | static struct clk usb_hhc_ck1510 = { | |
384 | .name = "usb_hhc_ck", | |
385 | /* Direct from ULPD, no parent */ | |
386 | .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ | |
387 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, | |
388 | }; | |
389 | ||
390 | static struct clk usb_hhc_ck16xx = { | |
391 | .name = "usb_hhc_ck", | |
392 | /* Direct from ULPD, no parent */ | |
393 | .rate = 48000000, | |
394 | /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ | |
395 | .flags = CLOCK_IN_OMAP16XX, | |
396 | }; | |
397 | ||
398 | static struct clk usb_dc_ck = { | |
399 | .name = "usb_dc_ck", | |
400 | /* Direct from ULPD, no parent */ | |
401 | .rate = 48000000, | |
402 | .flags = CLOCK_IN_OMAP16XX, | |
403 | }; | |
404 | ||
405 | static struct clk mclk_1510 = { | |
406 | .name = "mclk", | |
407 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | |
408 | .rate = 12000000, | |
409 | .flags = CLOCK_IN_OMAP1510, | |
410 | }; | |
411 | ||
412 | static struct clk bclk_310 = { | |
413 | .name = "bt_mclk_out", /* Alias midi_mclk_out? */ | |
414 | .parent = &armper_ck, | |
415 | .flags = CLOCK_IN_OMAP310, | |
416 | }; | |
417 | ||
418 | static struct clk mclk_310 = { | |
419 | .name = "com_mclk_out", | |
420 | .parent = &armper_ck, | |
421 | .flags = CLOCK_IN_OMAP310, | |
422 | }; | |
423 | ||
424 | static struct clk mclk_16xx = { | |
425 | .name = "mclk", | |
426 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | |
427 | .flags = CLOCK_IN_OMAP16XX, | |
428 | }; | |
429 | ||
430 | static struct clk bclk_1510 = { | |
431 | .name = "bclk", | |
432 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | |
433 | .rate = 12000000, | |
434 | .flags = CLOCK_IN_OMAP1510, | |
435 | }; | |
436 | ||
437 | static struct clk bclk_16xx = { | |
438 | .name = "bclk", | |
439 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | |
440 | .flags = CLOCK_IN_OMAP16XX, | |
441 | }; | |
442 | ||
443 | static struct clk mmc1_ck = { | |
444 | .name = "mmc_ck", | |
445 | .id = 1, | |
446 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | |
447 | .parent = &armper_ck, /* either armper_ck or dpll4 */ | |
448 | .rate = 48000000, | |
449 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, | |
450 | }; | |
451 | ||
452 | static struct clk mmc2_ck = { | |
453 | .name = "mmc_ck", | |
454 | .id = 2, | |
455 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | |
456 | .parent = &armper_ck, | |
457 | .rate = 48000000, | |
458 | .flags = CLOCK_IN_OMAP16XX, | |
459 | }; | |
460 | ||
461 | static struct clk cam_mclk = { | |
462 | .name = "cam.mclk", | |
463 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
464 | .rate = 12000000, | |
465 | }; | |
466 | ||
467 | static struct clk cam_exclk = { | |
468 | .name = "cam.exclk", | |
469 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
470 | /* Either 12M from cam.mclk or 48M from dpll4 */ | |
471 | .parent = &cam_mclk, | |
472 | }; | |
473 | ||
474 | static struct clk cam_lclk = { | |
475 | .name = "cam.lclk", | |
476 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, | |
477 | }; | |
478 | ||
479 | static struct clk i2c_fck = { | |
480 | .name = "i2c_fck", | |
481 | .id = 1, | |
482 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | |
483 | ALWAYS_ENABLED, | |
484 | .parent = &armxor_ck, | |
485 | }; | |
486 | ||
487 | static struct clk i2c_ick = { | |
488 | .name = "i2c_ick", | |
489 | .id = 1, | |
490 | .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, | |
491 | .parent = &armper_ck, | |
492 | }; | |
493 | ||
494 | static struct clk clk32k = { | |
495 | .name = "clk32-kHz", | |
496 | .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | |
497 | ALWAYS_ENABLED, | |
498 | .parent = &xtal_osc32k, | |
499 | }; | |
500 | ||
501 | static struct clk *onchip_clks[] = { | |
502 | /* non-ULPD clocks */ | |
503 | &xtal_osc12m, | |
504 | &xtal_osc32k, | |
505 | &ck_ref, | |
506 | &dpll1, | |
507 | &dpll2, | |
508 | &dpll3, | |
509 | &dpll4, | |
510 | &apll, | |
511 | &ck_48m, | |
512 | /* CK_GEN1 clocks */ | |
513 | &clkm1, | |
514 | &ck_dpll1out, | |
515 | &sossi_ck, | |
516 | &arm_ck, | |
517 | &armper_ck, | |
518 | &arm_gpio_ck, | |
519 | &armxor_ck, | |
520 | &armtim_ck, | |
521 | &armwdt_ck, | |
522 | &arminth_ck15xx, &arminth_ck16xx, | |
523 | /* CK_GEN2 clocks */ | |
524 | &clkm2, | |
525 | &dsp_ck, | |
526 | &dspmmu_ck, | |
527 | &dspper_ck, | |
528 | &dspxor_ck, | |
529 | &dsptim_ck, | |
530 | /* CK_GEN3 clocks */ | |
531 | &clkm3, | |
532 | &tc_ck, | |
533 | &tipb_ck, | |
534 | &l3_ocpi_ck, | |
535 | &tc1_ck, | |
536 | &tc2_ck, | |
537 | &dma_ck, | |
538 | &dma_lcdfree_ck, | |
539 | &api_ck, | |
540 | &lb_ck, | |
541 | &lbfree_ck, | |
542 | &rhea1_ck, | |
543 | &rhea2_ck, | |
544 | &lcd_ck_16xx, | |
545 | &lcd_ck_1510, | |
546 | /* ULPD clocks */ | |
547 | &uart1_1510, | |
548 | &uart1_16xx, | |
549 | &uart2_ck, | |
550 | &uart3_1510, | |
551 | &uart3_16xx, | |
552 | &usb_clk0, | |
553 | &usb_hhc_ck1510, &usb_hhc_ck16xx, | |
554 | &usb_dc_ck, | |
555 | &mclk_1510, &mclk_16xx, &mclk_310, | |
556 | &bclk_1510, &bclk_16xx, &bclk_310, | |
557 | &mmc1_ck, | |
558 | &mmc2_ck, | |
559 | &cam_mclk, | |
560 | &cam_exclk, | |
561 | &cam_lclk, | |
562 | &clk32k, | |
563 | /* Virtual clocks */ | |
564 | &i2c_fck, | |
565 | &i2c_ick, | |
566 | 0 | |
567 | }; | |
568 | ||
569 | void omap_clk_adduser(struct clk *clk, qemu_irq user) | |
570 | { | |
571 | qemu_irq *i; | |
572 | ||
573 | for (i = clk->users; *i; i ++); | |
574 | *i = user; | |
575 | } | |
576 | ||
577 | /* If a clock is allowed to idle, it is disabled automatically when | |
578 | * all of clock domains using it are disabled. */ | |
579 | int omap_clk_is_idle(struct clk *clk) | |
580 | { | |
581 | struct clk *chld; | |
582 | ||
583 | if (!clk->enabled && (!clk->usecount || !(clk->flags && ALWAYS_ENABLED))) | |
584 | return 1; | |
585 | if (clk->usecount) | |
586 | return 0; | |
587 | ||
588 | for (chld = clk->child1; chld; chld = chld->sibling) | |
589 | if (!omap_clk_is_idle(chld)) | |
590 | return 0; | |
591 | return 1; | |
592 | } | |
593 | ||
594 | struct clk *omap_findclk(struct omap_mpu_state_s *mpu, const char *name) | |
595 | { | |
596 | struct clk *i; | |
597 | ||
598 | for (i = mpu->clks; i->name; i ++) | |
599 | if (!strcmp(i->name, name) || (i->alias && !strcmp(i->alias, name))) | |
600 | return i; | |
601 | cpu_abort(mpu->env, "%s: %s not found\n", __FUNCTION__, name); | |
602 | } | |
603 | ||
604 | void omap_clk_get(struct clk *clk) | |
605 | { | |
606 | clk->usecount ++; | |
607 | } | |
608 | ||
609 | void omap_clk_put(struct clk *clk) | |
610 | { | |
611 | if (!(clk->usecount --)) | |
612 | cpu_abort(cpu_single_env, "%s: %s is not in use\n", | |
613 | __FUNCTION__, clk->name); | |
614 | } | |
615 | ||
616 | static void omap_clk_update(struct clk *clk) | |
617 | { | |
618 | int parent, running; | |
619 | qemu_irq *user; | |
620 | struct clk *i; | |
621 | ||
622 | if (clk->parent) | |
623 | parent = clk->parent->running; | |
624 | else | |
625 | parent = 1; | |
626 | ||
627 | running = parent && (clk->enabled || | |
628 | ((clk->flags & ALWAYS_ENABLED) && clk->usecount)); | |
629 | if (clk->running != running) { | |
630 | clk->running = running; | |
631 | for (user = clk->users; *user; user ++) | |
632 | qemu_set_irq(*user, running); | |
633 | for (i = clk->child1; i; i = i->sibling) | |
634 | omap_clk_update(i); | |
635 | } | |
636 | } | |
637 | ||
638 | static void omap_clk_rate_update_full(struct clk *clk, unsigned long int rate, | |
639 | unsigned long int div, unsigned long int mult) | |
640 | { | |
641 | struct clk *i; | |
642 | qemu_irq *user; | |
643 | ||
644 | clk->rate = muldiv64(rate, mult, div); | |
645 | if (clk->running) | |
646 | for (user = clk->users; *user; user ++) | |
647 | qemu_irq_raise(*user); | |
648 | for (i = clk->child1; i; i = i->sibling) | |
649 | omap_clk_rate_update_full(i, rate, | |
650 | div * i->divisor, mult * i->multiplier); | |
651 | } | |
652 | ||
653 | static void omap_clk_rate_update(struct clk *clk) | |
654 | { | |
655 | struct clk *i; | |
656 | unsigned long int div, mult = div = 1; | |
657 | ||
658 | for (i = clk; i->parent; i = i->parent) { | |
659 | div *= i->divisor; | |
660 | mult *= i->multiplier; | |
661 | } | |
662 | ||
663 | omap_clk_rate_update_full(clk, i->rate, div, mult); | |
664 | } | |
665 | ||
666 | void omap_clk_reparent(struct clk *clk, struct clk *parent) | |
667 | { | |
668 | struct clk **p; | |
669 | ||
670 | if (clk->parent) { | |
671 | for (p = &clk->parent->child1; *p != clk; p = &(*p)->sibling); | |
672 | *p = clk->sibling; | |
673 | } | |
674 | ||
675 | clk->parent = parent; | |
676 | if (parent) { | |
677 | clk->sibling = parent->child1; | |
678 | parent->child1 = clk; | |
679 | omap_clk_update(clk); | |
680 | omap_clk_rate_update(clk); | |
681 | } else | |
682 | clk->sibling = 0; | |
683 | } | |
684 | ||
685 | void omap_clk_onoff(struct clk *clk, int on) | |
686 | { | |
687 | clk->enabled = on; | |
688 | omap_clk_update(clk); | |
689 | } | |
690 | ||
691 | void omap_clk_canidle(struct clk *clk, int can) | |
692 | { | |
693 | if (can) | |
694 | omap_clk_put(clk); | |
695 | else | |
696 | omap_clk_get(clk); | |
697 | } | |
698 | ||
699 | void omap_clk_setrate(struct clk *clk, int divide, int multiply) | |
700 | { | |
701 | clk->divisor = divide; | |
702 | clk->multiplier = multiply; | |
703 | omap_clk_rate_update(clk); | |
704 | } | |
705 | ||
706 | int64_t omap_clk_getrate(omap_clk clk) | |
707 | { | |
708 | return clk->rate; | |
709 | } | |
710 | ||
711 | void omap_clk_init(struct omap_mpu_state_s *mpu) | |
712 | { | |
713 | struct clk **i, *j, *k; | |
714 | int count; | |
715 | int flag; | |
716 | ||
717 | if (cpu_is_omap310(mpu)) | |
718 | flag = CLOCK_IN_OMAP310; | |
719 | else if (cpu_is_omap1510(mpu)) | |
720 | flag = CLOCK_IN_OMAP1510; | |
721 | else | |
722 | return; | |
723 | ||
724 | for (i = onchip_clks, count = 0; *i; i ++) | |
725 | if ((*i)->flags & flag) | |
726 | count ++; | |
727 | mpu->clks = (struct clk *) qemu_mallocz(sizeof(struct clk) * (count + 1)); | |
728 | for (i = onchip_clks, j = mpu->clks; *i; i ++) | |
729 | if ((*i)->flags & flag) { | |
730 | memcpy(j, *i, sizeof(struct clk)); | |
731 | for (k = mpu->clks; k < j; k ++) | |
732 | if (j->parent && !strcmp(j->parent->name, k->name)) { | |
733 | j->parent = k; | |
734 | j->sibling = k->child1; | |
735 | k->child1 = j; | |
736 | } else if (k->parent && !strcmp(k->parent->name, j->name)) { | |
737 | k->parent = j; | |
738 | k->sibling = j->child1; | |
739 | j->child1 = k; | |
740 | } | |
741 | j->divisor = j->divisor ?: 1; | |
742 | j->multiplier = j->multiplier ?: 1; | |
743 | j ++; | |
744 | } | |
745 | } |