4
* Copyright (C) 2006-2007 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
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32
#define ALWAYS_ENABLED (1 << 0)
33
#define CLOCK_IN_OMAP310 (1 << 10)
34
#define CLOCK_IN_OMAP730 (1 << 11)
35
#define CLOCK_IN_OMAP1510 (1 << 12)
36
#define CLOCK_IN_OMAP16XX (1 << 13)
40
int running; /* Is currently ticking */
41
int enabled; /* Is enabled, regardless of its input clk */
42
unsigned long rate; /* Current rate (if .running) */
43
unsigned int divisor; /* Rate relative to input (if .enabled) */
44
unsigned int multiplier; /* Rate relative to input (if .enabled) */
45
qemu_irq users[16]; /* Who to notify on change */
46
int usecount; /* Automatically idle when unused */
49
static struct clk xtal_osc12m = {
50
.name = "xtal_osc_12m",
52
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
55
static struct clk xtal_osc32k = {
56
.name = "xtal_osc_32k",
58
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
61
static struct clk ck_ref = {
64
.parent = &xtal_osc12m,
65
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
69
/* If a dpll is disabled it becomes a bypass, child clocks don't stop */
70
static struct clk dpll1 = {
73
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
77
static struct clk dpll2 = {
80
.flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
83
static struct clk dpll3 = {
86
.flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
89
static struct clk dpll4 = {
93
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
96
static struct clk apll = {
101
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
104
static struct clk ck_48m = {
106
.parent = &dpll4, /* either dpll4 or apll */
107
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
110
static struct clk ck_dpll1out = {
111
.name = "ck_dpll1out",
113
.flags = CLOCK_IN_OMAP16XX,
116
static struct clk sossi_ck = {
118
.parent = &ck_dpll1out,
119
.flags = CLOCK_IN_OMAP16XX,
122
static struct clk clkm1 = {
126
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
130
static struct clk clkm2 = {
134
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
138
static struct clk clkm3 = {
141
.parent = &dpll1, /* either dpll1 or ck_ref */
142
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
146
static struct clk arm_ck = {
150
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
154
static struct clk armper_ck = {
156
.alias = "mpuper_ck",
158
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
161
static struct clk arm_gpio_ck = {
162
.name = "arm_gpio_ck",
163
.alias = "mpu_gpio_ck",
166
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
169
static struct clk armxor_ck = {
171
.alias = "mpuxor_ck",
173
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
176
static struct clk armtim_ck = {
178
.alias = "mputim_ck",
179
.parent = &ck_ref, /* either CLKIN or DPLL1 */
180
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
183
static struct clk armwdt_ck = {
188
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
192
static struct clk arminth_ck16xx = {
193
.name = "arminth_ck",
195
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
196
/* Note: On 16xx the frequency can be divided by 2 by programming
197
* ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
199
* 1510 version is in TC clocks.
203
static struct clk dsp_ck = {
206
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
209
static struct clk dspmmu_ck = {
212
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
216
static struct clk dspper_ck = {
219
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
222
static struct clk dspxor_ck = {
225
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
228
static struct clk dsptim_ck = {
231
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
234
static struct clk tc_ck = {
237
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
238
CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
242
static struct clk arminth_ck15xx = {
243
.name = "arminth_ck",
245
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
246
/* Note: On 1510 the frequency follows TC_CK
248
* 16xx version is in MPU clocks.
252
static struct clk tipb_ck = {
253
/* No-idle controlled by "tc_ck" */
256
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
259
static struct clk l3_ocpi_ck = {
260
/* No-idle controlled by "tc_ck" */
261
.name = "l3_ocpi_ck",
263
.flags = CLOCK_IN_OMAP16XX,
266
static struct clk tc1_ck = {
269
.flags = CLOCK_IN_OMAP16XX,
272
static struct clk tc2_ck = {
275
.flags = CLOCK_IN_OMAP16XX,
278
static struct clk dma_ck = {
279
/* No-idle controlled by "tc_ck" */
282
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
286
static struct clk dma_lcdfree_ck = {
287
.name = "dma_lcdfree_ck",
289
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
292
static struct clk api_ck = {
296
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
299
static struct clk lb_ck = {
302
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
305
static struct clk lbfree_ck = {
308
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
311
static struct clk hsab_ck = {
314
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
317
static struct clk rhea1_ck = {
320
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
323
static struct clk rhea2_ck = {
326
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
329
static struct clk lcd_ck_16xx = {
332
.flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730,
335
static struct clk lcd_ck_1510 = {
338
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
341
static struct clk uart1_1510 = {
343
/* Direct from ULPD, no real parent */
344
.parent = &armper_ck, /* either armper_ck or dpll4 */
346
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
349
static struct clk uart1_16xx = {
351
/* Direct from ULPD, no real parent */
352
.parent = &armper_ck,
354
.flags = CLOCK_IN_OMAP16XX,
357
static struct clk uart2_ck = {
359
/* Direct from ULPD, no real parent */
360
.parent = &armper_ck, /* either armper_ck or dpll4 */
362
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
366
static struct clk uart3_1510 = {
368
/* Direct from ULPD, no real parent */
369
.parent = &armper_ck, /* either armper_ck or dpll4 */
371
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
374
static struct clk uart3_16xx = {
376
/* Direct from ULPD, no real parent */
377
.parent = &armper_ck,
379
.flags = CLOCK_IN_OMAP16XX,
382
static struct clk usb_clk0 = { /* 6 MHz output on W4_USB_CLK0 */
385
/* Direct from ULPD, no parent */
387
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
390
static struct clk usb_hhc_ck1510 = {
391
.name = "usb_hhc_ck",
392
/* Direct from ULPD, no parent */
393
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
394
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
397
static struct clk usb_hhc_ck16xx = {
398
.name = "usb_hhc_ck",
399
/* Direct from ULPD, no parent */
401
/* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
402
.flags = CLOCK_IN_OMAP16XX,
405
static struct clk usb_w2fc_mclk = {
406
.name = "usb_w2fc_mclk",
407
.alias = "usb_w2fc_ck",
410
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
413
static struct clk mclk_1510 = {
415
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
417
.flags = CLOCK_IN_OMAP1510,
420
static struct clk bclk_310 = {
421
.name = "bt_mclk_out", /* Alias midi_mclk_out? */
422
.parent = &armper_ck,
423
.flags = CLOCK_IN_OMAP310,
426
static struct clk mclk_310 = {
427
.name = "com_mclk_out",
428
.parent = &armper_ck,
429
.flags = CLOCK_IN_OMAP310,
432
static struct clk mclk_16xx = {
434
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
435
.flags = CLOCK_IN_OMAP16XX,
438
static struct clk bclk_1510 = {
440
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
442
.flags = CLOCK_IN_OMAP1510,
445
static struct clk bclk_16xx = {
447
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
448
.flags = CLOCK_IN_OMAP16XX,
451
static struct clk mmc1_ck = {
454
/* Functional clock is direct from ULPD, interface clock is ARMPER */
455
.parent = &armper_ck, /* either armper_ck or dpll4 */
457
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
460
static struct clk mmc2_ck = {
463
/* Functional clock is direct from ULPD, interface clock is ARMPER */
464
.parent = &armper_ck,
466
.flags = CLOCK_IN_OMAP16XX,
469
static struct clk cam_mclk = {
471
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
475
static struct clk cam_exclk = {
477
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
478
/* Either 12M from cam.mclk or 48M from dpll4 */
482
static struct clk cam_lclk = {
484
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
487
static struct clk i2c_fck = {
490
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
492
.parent = &armxor_ck,
495
static struct clk i2c_ick = {
498
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
499
.parent = &armper_ck,
502
static struct clk clk32k = {
504
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
506
.parent = &xtal_osc32k,
509
static struct clk *onchip_clks[] = {
510
/* non-ULPD clocks */
530
&arminth_ck15xx, &arminth_ck16xx,
562
&usb_hhc_ck1510, &usb_hhc_ck16xx,
563
&mclk_1510, &mclk_16xx, &mclk_310,
564
&bclk_1510, &bclk_16xx, &bclk_310,
578
void omap_clk_adduser(struct clk *clk, qemu_irq user)
582
for (i = clk->users; *i; i ++);
586
/* If a clock is allowed to idle, it is disabled automatically when
587
* all of clock domains using it are disabled. */
588
int omap_clk_is_idle(struct clk *clk)
592
if (!clk->enabled && (!clk->usecount || !(clk->flags && ALWAYS_ENABLED)))
597
for (chld = clk->child1; chld; chld = chld->sibling)
598
if (!omap_clk_is_idle(chld))
603
struct clk *omap_findclk(struct omap_mpu_state_s *mpu, const char *name)
607
for (i = mpu->clks; i->name; i ++)
608
if (!strcmp(i->name, name) || (i->alias && !strcmp(i->alias, name)))
610
cpu_abort(mpu->env, "%s: %s not found\n", __FUNCTION__, name);
613
void omap_clk_get(struct clk *clk)
618
void omap_clk_put(struct clk *clk)
620
if (!(clk->usecount --))
621
cpu_abort(cpu_single_env, "%s: %s is not in use\n",
622
__FUNCTION__, clk->name);
625
static void omap_clk_update(struct clk *clk)
632
parent = clk->parent->running;
636
running = parent && (clk->enabled ||
637
((clk->flags & ALWAYS_ENABLED) && clk->usecount));
638
if (clk->running != running) {
639
clk->running = running;
640
for (user = clk->users; *user; user ++)
641
qemu_set_irq(*user, running);
642
for (i = clk->child1; i; i = i->sibling)
647
static void omap_clk_rate_update_full(struct clk *clk, unsigned long int rate,
648
unsigned long int div, unsigned long int mult)
653
clk->rate = muldiv64(rate, mult, div);
655
for (user = clk->users; *user; user ++)
656
qemu_irq_raise(*user);
657
for (i = clk->child1; i; i = i->sibling)
658
omap_clk_rate_update_full(i, rate,
659
div * i->divisor, mult * i->multiplier);
662
static void omap_clk_rate_update(struct clk *clk)
665
unsigned long int div, mult = div = 1;
667
for (i = clk; i->parent; i = i->parent) {
669
mult *= i->multiplier;
672
omap_clk_rate_update_full(clk, i->rate, div, mult);
675
void omap_clk_reparent(struct clk *clk, struct clk *parent)
680
for (p = &clk->parent->child1; *p != clk; p = &(*p)->sibling);
684
clk->parent = parent;
686
clk->sibling = parent->child1;
687
parent->child1 = clk;
688
omap_clk_update(clk);
689
omap_clk_rate_update(clk);
694
void omap_clk_onoff(struct clk *clk, int on)
697
omap_clk_update(clk);
700
void omap_clk_canidle(struct clk *clk, int can)
708
void omap_clk_setrate(struct clk *clk, int divide, int multiply)
710
clk->divisor = divide;
711
clk->multiplier = multiply;
712
omap_clk_rate_update(clk);
715
int64_t omap_clk_getrate(omap_clk clk)
720
void omap_clk_init(struct omap_mpu_state_s *mpu)
722
struct clk **i, *j, *k;
726
if (cpu_is_omap310(mpu))
727
flag = CLOCK_IN_OMAP310;
728
else if (cpu_is_omap1510(mpu))
729
flag = CLOCK_IN_OMAP1510;
733
for (i = onchip_clks, count = 0; *i; i ++)
734
if ((*i)->flags & flag)
736
mpu->clks = (struct clk *) qemu_mallocz(sizeof(struct clk) * (count + 1));
737
for (i = onchip_clks, j = mpu->clks; *i; i ++)
738
if ((*i)->flags & flag) {
739
memcpy(j, *i, sizeof(struct clk));
740
for (k = mpu->clks; k < j; k ++)
741
if (j->parent && !strcmp(j->parent->name, k->name)) {
743
j->sibling = k->child1;
745
} else if (k->parent && !strcmp(k->parent->name, j->name)) {
747
k->sibling = j->child1;
750
j->divisor = j->divisor ?: 1;
751
j->multiplier = j->multiplier ?: 1;
754
for (j = mpu->clks; count --; j ++) {
756
omap_clk_rate_update(j);