Statistics
| Branch: | Revision:

root / hw / omap1_clk.c @ 8c9d7f83

History | View | Annotate | Download (18.4 kB)

1
/*
2
 * OMAP clocks.
3
 *
4
 * Copyright (C) 2006-2007 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
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
}