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