4 * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
6 * Clocks data comes in part from arch/arm/mach-omap1/clock.h in Linux.
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.
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.
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/>.
22 #include "qemu/osdep.h"
25 #include "hw/arm/omap.h"
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)
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 */
50 static struct clk xtal_osc12m
= {
51 .name
= "xtal_osc_12m",
53 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
56 static struct clk xtal_osc32k
= {
57 .name
= "xtal_osc_32k",
59 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
62 static struct clk ck_ref
= {
65 .parent
= &xtal_osc12m
,
66 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
70 /* If a dpll is disabled it becomes a bypass, child clocks don't stop */
71 static struct clk dpll1
= {
74 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
78 static struct clk dpll2
= {
81 .flags
= CLOCK_IN_OMAP310
| ALWAYS_ENABLED
,
84 static struct clk dpll3
= {
87 .flags
= CLOCK_IN_OMAP310
| ALWAYS_ENABLED
,
90 static struct clk dpll4
= {
94 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
97 static struct clk apll
= {
102 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
105 static struct clk ck_48m
= {
107 .parent
= &dpll4
, /* either dpll4 or apll */
108 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
111 static struct clk ck_dpll1out
= {
112 .name
= "ck_dpll1out",
114 .flags
= CLOCK_IN_OMAP16XX
,
117 static struct clk sossi_ck
= {
119 .parent
= &ck_dpll1out
,
120 .flags
= CLOCK_IN_OMAP16XX
,
123 static struct clk clkm1
= {
127 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
131 static struct clk clkm2
= {
135 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
139 static struct clk clkm3
= {
142 .parent
= &dpll1
, /* either dpll1 or ck_ref */
143 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
147 static struct clk arm_ck
= {
151 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
155 static struct clk armper_ck
= {
157 .alias
= "mpuper_ck",
159 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
162 static struct clk arm_gpio_ck
= {
163 .name
= "arm_gpio_ck",
164 .alias
= "mpu_gpio_ck",
167 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
,
170 static struct clk armxor_ck
= {
172 .alias
= "mpuxor_ck",
174 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
177 static struct clk 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
,
184 static struct clk armwdt_ck
= {
189 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
193 static struct clk arminth_ck16xx
= {
194 .name
= "arminth_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
200 * 1510 version is in TC clocks.
204 static struct clk dsp_ck
= {
207 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
210 static struct clk dspmmu_ck
= {
213 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
|
217 static struct clk dspper_ck
= {
220 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
223 static struct clk dspxor_ck
= {
226 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
229 static struct clk dsptim_ck
= {
232 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
235 static struct clk tc_ck
= {
238 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
|
239 CLOCK_IN_OMAP730
| CLOCK_IN_OMAP310
|
243 static struct clk arminth_ck15xx
= {
244 .name
= "arminth_ck",
246 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
| ALWAYS_ENABLED
,
247 /* Note: On 1510 the frequency follows TC_CK
249 * 16xx version is in MPU clocks.
253 static struct clk tipb_ck
= {
254 /* No-idle controlled by "tc_ck" */
257 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
| ALWAYS_ENABLED
,
260 static struct clk l3_ocpi_ck
= {
261 /* No-idle controlled by "tc_ck" */
262 .name
= "l3_ocpi_ck",
264 .flags
= CLOCK_IN_OMAP16XX
,
267 static struct clk tc1_ck
= {
270 .flags
= CLOCK_IN_OMAP16XX
,
273 static struct clk tc2_ck
= {
276 .flags
= CLOCK_IN_OMAP16XX
,
279 static struct clk dma_ck
= {
280 /* No-idle controlled by "tc_ck" */
283 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
287 static struct clk dma_lcdfree_ck
= {
288 .name
= "dma_lcdfree_ck",
290 .flags
= CLOCK_IN_OMAP16XX
| ALWAYS_ENABLED
,
293 static struct clk api_ck
= {
297 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
300 static struct clk lb_ck
= {
303 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
,
306 static struct clk lbfree_ck
= {
309 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
,
312 static struct clk hsab_ck
= {
315 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
,
318 static struct clk rhea1_ck
= {
321 .flags
= CLOCK_IN_OMAP16XX
| ALWAYS_ENABLED
,
324 static struct clk rhea2_ck
= {
327 .flags
= CLOCK_IN_OMAP16XX
| ALWAYS_ENABLED
,
330 static struct clk lcd_ck_16xx
= {
333 .flags
= CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP730
,
336 static struct clk lcd_ck_1510
= {
339 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
,
342 static struct clk uart1_1510
= {
344 /* Direct from ULPD, no real parent */
345 .parent
= &armper_ck
, /* either armper_ck or dpll4 */
347 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
| ALWAYS_ENABLED
,
350 static struct clk uart1_16xx
= {
352 /* Direct from ULPD, no real parent */
353 .parent
= &armper_ck
,
355 .flags
= CLOCK_IN_OMAP16XX
,
358 static struct clk uart2_ck
= {
360 /* Direct from ULPD, no real parent */
361 .parent
= &armper_ck
, /* either armper_ck or dpll4 */
363 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
|
367 static struct clk uart3_1510
= {
369 /* Direct from ULPD, no real parent */
370 .parent
= &armper_ck
, /* either armper_ck or dpll4 */
372 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP310
| ALWAYS_ENABLED
,
375 static struct clk uart3_16xx
= {
377 /* Direct from ULPD, no real parent */
378 .parent
= &armper_ck
,
380 .flags
= CLOCK_IN_OMAP16XX
,
383 static struct clk usb_clk0
= { /* 6 MHz output on W4_USB_CLK0 */
386 /* Direct from ULPD, no parent */
388 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
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
,
398 static struct clk usb_hhc_ck16xx
= {
399 .name
= "usb_hhc_ck",
400 /* Direct from ULPD, no parent */
402 /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
403 .flags
= CLOCK_IN_OMAP16XX
,
406 static struct clk usb_w2fc_mclk
= {
407 .name
= "usb_w2fc_mclk",
408 .alias
= "usb_w2fc_ck",
411 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
414 static struct clk mclk_1510
= {
416 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
418 .flags
= CLOCK_IN_OMAP1510
,
421 static struct clk bclk_310
= {
422 .name
= "bt_mclk_out", /* Alias midi_mclk_out? */
423 .parent
= &armper_ck
,
424 .flags
= CLOCK_IN_OMAP310
,
427 static struct clk mclk_310
= {
428 .name
= "com_mclk_out",
429 .parent
= &armper_ck
,
430 .flags
= CLOCK_IN_OMAP310
,
433 static struct clk mclk_16xx
= {
435 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
436 .flags
= CLOCK_IN_OMAP16XX
,
439 static struct clk bclk_1510
= {
441 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
443 .flags
= CLOCK_IN_OMAP1510
,
446 static struct clk bclk_16xx
= {
448 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
449 .flags
= CLOCK_IN_OMAP16XX
,
452 static struct clk mmc1_ck
= {
455 /* Functional clock is direct from ULPD, interface clock is ARMPER */
456 .parent
= &armper_ck
, /* either armper_ck or dpll4 */
458 .flags
= CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
| CLOCK_IN_OMAP310
,
461 static struct clk mmc2_ck
= {
464 /* Functional clock is direct from ULPD, interface clock is ARMPER */
465 .parent
= &armper_ck
,
467 .flags
= CLOCK_IN_OMAP16XX
,
470 static struct clk cam_mclk
= {
472 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
476 static struct clk cam_exclk
= {
478 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
479 /* Either 12M from cam.mclk or 48M from dpll4 */
483 static struct clk cam_lclk
= {
485 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
,
488 static struct clk i2c_fck
= {
491 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
|
493 .parent
= &armxor_ck
,
496 static struct clk i2c_ick
= {
499 .flags
= CLOCK_IN_OMAP16XX
| ALWAYS_ENABLED
,
500 .parent
= &armper_ck
,
503 static struct clk clk32k
= {
505 .flags
= CLOCK_IN_OMAP310
| CLOCK_IN_OMAP1510
| CLOCK_IN_OMAP16XX
|
507 .parent
= &xtal_osc32k
,
510 static struct clk
*onchip_clks
[] = {
513 /* non-ULPD clocks */
533 &arminth_ck15xx
, &arminth_ck16xx
,
565 &usb_hhc_ck1510
, &usb_hhc_ck16xx
,
566 &mclk_1510
, &mclk_16xx
, &mclk_310
,
567 &bclk_1510
, &bclk_16xx
, &bclk_310
,
582 void omap_clk_adduser(struct clk
*clk
, qemu_irq user
)
586 for (i
= clk
->users
; *i
; i
++);
590 struct clk
*omap_findclk(struct omap_mpu_state_s
*mpu
, const char *name
)
594 for (i
= mpu
->clks
; i
->name
; i
++)
595 if (!strcmp(i
->name
, name
) || (i
->alias
&& !strcmp(i
->alias
, name
)))
597 hw_error("%s: %s not found\n", __func__
, name
);
600 void omap_clk_get(struct clk
*clk
)
605 void omap_clk_put(struct clk
*clk
)
607 if (!(clk
->usecount
--))
608 hw_error("%s: %s is not in use\n", __func__
, clk
->name
);
611 static void omap_clk_update(struct clk
*clk
)
618 parent
= clk
->parent
->running
;
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
)
633 static void omap_clk_rate_update_full(struct clk
*clk
, unsigned long int rate
,
634 unsigned long int div
, unsigned long int mult
)
639 clk
->rate
= muldiv64(rate
, mult
, div
);
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
);
648 static void omap_clk_rate_update(struct clk
*clk
)
651 unsigned long int div
, mult
= div
= 1;
653 for (i
= clk
; i
->parent
; i
= i
->parent
) {
655 mult
*= i
->multiplier
;
658 omap_clk_rate_update_full(clk
, i
->rate
, div
, mult
);
661 void omap_clk_reparent(struct clk
*clk
, struct clk
*parent
)
666 for (p
= &clk
->parent
->child1
; *p
!= clk
; p
= &(*p
)->sibling
);
670 clk
->parent
= parent
;
672 clk
->sibling
= parent
->child1
;
673 parent
->child1
= clk
;
674 omap_clk_update(clk
);
675 omap_clk_rate_update(clk
);
680 void omap_clk_onoff(struct clk
*clk
, int on
)
683 omap_clk_update(clk
);
686 void omap_clk_canidle(struct clk
*clk
, int can
)
694 void omap_clk_setrate(struct clk
*clk
, int divide
, int multiply
)
696 clk
->divisor
= divide
;
697 clk
->multiplier
= multiply
;
698 omap_clk_rate_update(clk
);
701 int64_t omap_clk_getrate(omap_clk clk
)
706 void omap_clk_init(struct omap_mpu_state_s
*mpu
)
708 struct clk
**i
, *j
, *k
;
712 if (cpu_is_omap310(mpu
))
713 flag
= CLOCK_IN_OMAP310
;
714 else if (cpu_is_omap1510(mpu
))
715 flag
= CLOCK_IN_OMAP1510
;
719 for (i
= onchip_clks
, count
= 0; *i
; i
++)
720 if ((*i
)->flags
& flag
)
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
)) {
729 j
->sibling
= k
->child1
;
731 } else if (k
->parent
&& !strcmp(k
->parent
->name
, j
->name
)) {
733 k
->sibling
= j
->child1
;
736 j
->divisor
= j
->divisor
?: 1;
737 j
->multiplier
= j
->multiplier
?: 1;
740 for (j
= mpu
->clks
; count
--; j
++) {
742 omap_clk_rate_update(j
);