qemu

Форк
0
/
imx6ul_ccm.c 
932 строки · 26.5 Кб
1
/*
2
 * IMX6UL Clock Control Module
3
 *
4
 * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
5
 *
6
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7
 * See the COPYING file in the top-level directory.
8
 *
9
 * To get the timer frequencies right, we need to emulate at least part of
10
 * the CCM.
11
 */
12

13
#include "qemu/osdep.h"
14
#include "hw/registerfields.h"
15
#include "migration/vmstate.h"
16
#include "hw/misc/imx6ul_ccm.h"
17
#include "qemu/log.h"
18
#include "qemu/module.h"
19

20
#include "trace.h"
21

22
static const uint32_t ccm_mask[CCM_MAX] = {
23
    [CCM_CCR] = 0xf01fef80,
24
    [CCM_CCDR] = 0xfffeffff,
25
    [CCM_CSR] = 0xffffffff,
26
    [CCM_CCSR] = 0xfffffef2,
27
    [CCM_CACRR] = 0xfffffff8,
28
    [CCM_CBCDR] = 0xc1f8e000,
29
    [CCM_CBCMR] = 0xfc03cfff,
30
    [CCM_CSCMR1] = 0x80700000,
31
    [CCM_CSCMR2] = 0xe01ff003,
32
    [CCM_CSCDR1] = 0xfe00c780,
33
    [CCM_CS1CDR] = 0xfe00fe00,
34
    [CCM_CS2CDR] = 0xf8007000,
35
    [CCM_CDCDR] = 0xf00fffff,
36
    [CCM_CHSCCDR] = 0xfffc01ff,
37
    [CCM_CSCDR2] = 0xfe0001ff,
38
    [CCM_CSCDR3] = 0xffffc1ff,
39
    [CCM_CDHIPR] = 0xffffffff,
40
    [CCM_CTOR] = 0x00000000,
41
    [CCM_CLPCR] = 0xf39ff01c,
42
    [CCM_CISR] = 0xfb85ffbe,
43
    [CCM_CIMR] = 0xfb85ffbf,
44
    [CCM_CCOSR] = 0xfe00fe00,
45
    [CCM_CGPR] = 0xfffc3fea,
46
    [CCM_CCGR0] = 0x00000000,
47
    [CCM_CCGR1] = 0x00000000,
48
    [CCM_CCGR2] = 0x00000000,
49
    [CCM_CCGR3] = 0x00000000,
50
    [CCM_CCGR4] = 0x00000000,
51
    [CCM_CCGR5] = 0x00000000,
52
    [CCM_CCGR6] = 0x00000000,
53
    [CCM_CMEOR] = 0xafffff1f,
54
};
55

56
static const uint32_t analog_mask[CCM_ANALOG_MAX] = {
57
    [CCM_ANALOG_PLL_ARM] = 0xfff60f80,
58
    [CCM_ANALOG_PLL_USB1] = 0xfffe0fbc,
59
    [CCM_ANALOG_PLL_USB2] = 0xfffe0fbc,
60
    [CCM_ANALOG_PLL_SYS] = 0xfffa0ffe,
61
    [CCM_ANALOG_PLL_SYS_SS] = 0x00000000,
62
    [CCM_ANALOG_PLL_SYS_NUM] = 0xc0000000,
63
    [CCM_ANALOG_PLL_SYS_DENOM] = 0xc0000000,
64
    [CCM_ANALOG_PLL_AUDIO] = 0xffe20f80,
65
    [CCM_ANALOG_PLL_AUDIO_NUM] = 0xc0000000,
66
    [CCM_ANALOG_PLL_AUDIO_DENOM] = 0xc0000000,
67
    [CCM_ANALOG_PLL_VIDEO] = 0xffe20f80,
68
    [CCM_ANALOG_PLL_VIDEO_NUM] = 0xc0000000,
69
    [CCM_ANALOG_PLL_VIDEO_DENOM] = 0xc0000000,
70
    [CCM_ANALOG_PLL_ENET] = 0xffc20ff0,
71
    [CCM_ANALOG_PFD_480] = 0x40404040,
72
    [CCM_ANALOG_PFD_528] = 0x40404040,
73
    [PMU_MISC0] = 0x01fe8306,
74
    [PMU_MISC1] = 0x07fcede0,
75
    [PMU_MISC2] = 0x005f5f5f,
76
};
77

78
static const char *imx6ul_ccm_reg_name(uint32_t reg)
79
{
80
    static char unknown[20];
81

82
    switch (reg) {
83
    case CCM_CCR:
84
        return "CCR";
85
    case CCM_CCDR:
86
        return "CCDR";
87
    case CCM_CSR:
88
        return "CSR";
89
    case CCM_CCSR:
90
        return "CCSR";
91
    case CCM_CACRR:
92
        return "CACRR";
93
    case CCM_CBCDR:
94
        return "CBCDR";
95
    case CCM_CBCMR:
96
        return "CBCMR";
97
    case CCM_CSCMR1:
98
        return "CSCMR1";
99
    case CCM_CSCMR2:
100
        return "CSCMR2";
101
    case CCM_CSCDR1:
102
        return "CSCDR1";
103
    case CCM_CS1CDR:
104
        return "CS1CDR";
105
    case CCM_CS2CDR:
106
        return "CS2CDR";
107
    case CCM_CDCDR:
108
        return "CDCDR";
109
    case CCM_CHSCCDR:
110
        return "CHSCCDR";
111
    case CCM_CSCDR2:
112
        return "CSCDR2";
113
    case CCM_CSCDR3:
114
        return "CSCDR3";
115
    case CCM_CDHIPR:
116
        return "CDHIPR";
117
    case CCM_CTOR:
118
        return "CTOR";
119
    case CCM_CLPCR:
120
        return "CLPCR";
121
    case CCM_CISR:
122
        return "CISR";
123
    case CCM_CIMR:
124
        return "CIMR";
125
    case CCM_CCOSR:
126
        return "CCOSR";
127
    case CCM_CGPR:
128
        return "CGPR";
129
    case CCM_CCGR0:
130
        return "CCGR0";
131
    case CCM_CCGR1:
132
        return "CCGR1";
133
    case CCM_CCGR2:
134
        return "CCGR2";
135
    case CCM_CCGR3:
136
        return "CCGR3";
137
    case CCM_CCGR4:
138
        return "CCGR4";
139
    case CCM_CCGR5:
140
        return "CCGR5";
141
    case CCM_CCGR6:
142
        return "CCGR6";
143
    case CCM_CMEOR:
144
        return "CMEOR";
145
    default:
146
        snprintf(unknown, sizeof(unknown), "%u ?", reg);
147
        return unknown;
148
    }
149
}
150

151
static const char *imx6ul_analog_reg_name(uint32_t reg)
152
{
153
    static char unknown[20];
154

155
    switch (reg) {
156
    case CCM_ANALOG_PLL_ARM:
157
        return "PLL_ARM";
158
    case CCM_ANALOG_PLL_ARM_SET:
159
        return "PLL_ARM_SET";
160
    case CCM_ANALOG_PLL_ARM_CLR:
161
        return "PLL_ARM_CLR";
162
    case CCM_ANALOG_PLL_ARM_TOG:
163
        return "PLL_ARM_TOG";
164
    case CCM_ANALOG_PLL_USB1:
165
        return "PLL_USB1";
166
    case CCM_ANALOG_PLL_USB1_SET:
167
        return "PLL_USB1_SET";
168
    case CCM_ANALOG_PLL_USB1_CLR:
169
        return "PLL_USB1_CLR";
170
    case CCM_ANALOG_PLL_USB1_TOG:
171
        return "PLL_USB1_TOG";
172
    case CCM_ANALOG_PLL_USB2:
173
        return "PLL_USB2";
174
    case CCM_ANALOG_PLL_USB2_SET:
175
        return "PLL_USB2_SET";
176
    case CCM_ANALOG_PLL_USB2_CLR:
177
        return "PLL_USB2_CLR";
178
    case CCM_ANALOG_PLL_USB2_TOG:
179
        return "PLL_USB2_TOG";
180
    case CCM_ANALOG_PLL_SYS:
181
        return "PLL_SYS";
182
    case CCM_ANALOG_PLL_SYS_SET:
183
        return "PLL_SYS_SET";
184
    case CCM_ANALOG_PLL_SYS_CLR:
185
        return "PLL_SYS_CLR";
186
    case CCM_ANALOG_PLL_SYS_TOG:
187
        return "PLL_SYS_TOG";
188
    case CCM_ANALOG_PLL_SYS_SS:
189
        return "PLL_SYS_SS";
190
    case CCM_ANALOG_PLL_SYS_NUM:
191
        return "PLL_SYS_NUM";
192
    case CCM_ANALOG_PLL_SYS_DENOM:
193
        return "PLL_SYS_DENOM";
194
    case CCM_ANALOG_PLL_AUDIO:
195
        return "PLL_AUDIO";
196
    case CCM_ANALOG_PLL_AUDIO_SET:
197
        return "PLL_AUDIO_SET";
198
    case CCM_ANALOG_PLL_AUDIO_CLR:
199
        return "PLL_AUDIO_CLR";
200
    case CCM_ANALOG_PLL_AUDIO_TOG:
201
        return "PLL_AUDIO_TOG";
202
    case CCM_ANALOG_PLL_AUDIO_NUM:
203
        return "PLL_AUDIO_NUM";
204
    case CCM_ANALOG_PLL_AUDIO_DENOM:
205
        return "PLL_AUDIO_DENOM";
206
    case CCM_ANALOG_PLL_VIDEO:
207
        return "PLL_VIDEO";
208
    case CCM_ANALOG_PLL_VIDEO_SET:
209
        return "PLL_VIDEO_SET";
210
    case CCM_ANALOG_PLL_VIDEO_CLR:
211
        return "PLL_VIDEO_CLR";
212
    case CCM_ANALOG_PLL_VIDEO_TOG:
213
        return "PLL_VIDEO_TOG";
214
    case CCM_ANALOG_PLL_VIDEO_NUM:
215
        return "PLL_VIDEO_NUM";
216
    case CCM_ANALOG_PLL_VIDEO_DENOM:
217
        return "PLL_VIDEO_DENOM";
218
    case CCM_ANALOG_PLL_ENET:
219
        return "PLL_ENET";
220
    case CCM_ANALOG_PLL_ENET_SET:
221
        return "PLL_ENET_SET";
222
    case CCM_ANALOG_PLL_ENET_CLR:
223
        return "PLL_ENET_CLR";
224
    case CCM_ANALOG_PLL_ENET_TOG:
225
        return "PLL_ENET_TOG";
226
    case CCM_ANALOG_PFD_480:
227
        return "PFD_480";
228
    case CCM_ANALOG_PFD_480_SET:
229
        return "PFD_480_SET";
230
    case CCM_ANALOG_PFD_480_CLR:
231
        return "PFD_480_CLR";
232
    case CCM_ANALOG_PFD_480_TOG:
233
        return "PFD_480_TOG";
234
    case CCM_ANALOG_PFD_528:
235
        return "PFD_528";
236
    case CCM_ANALOG_PFD_528_SET:
237
        return "PFD_528_SET";
238
    case CCM_ANALOG_PFD_528_CLR:
239
        return "PFD_528_CLR";
240
    case CCM_ANALOG_PFD_528_TOG:
241
        return "PFD_528_TOG";
242
    case CCM_ANALOG_MISC0:
243
        return "MISC0";
244
    case CCM_ANALOG_MISC0_SET:
245
        return "MISC0_SET";
246
    case CCM_ANALOG_MISC0_CLR:
247
        return "MISC0_CLR";
248
    case CCM_ANALOG_MISC0_TOG:
249
        return "MISC0_TOG";
250
    case CCM_ANALOG_MISC2:
251
        return "MISC2";
252
    case CCM_ANALOG_MISC2_SET:
253
        return "MISC2_SET";
254
    case CCM_ANALOG_MISC2_CLR:
255
        return "MISC2_CLR";
256
    case CCM_ANALOG_MISC2_TOG:
257
        return "MISC2_TOG";
258
    case PMU_REG_1P1:
259
        return "PMU_REG_1P1";
260
    case PMU_REG_3P0:
261
        return "PMU_REG_3P0";
262
    case PMU_REG_2P5:
263
        return "PMU_REG_2P5";
264
    case PMU_REG_CORE:
265
        return "PMU_REG_CORE";
266
    case PMU_MISC1:
267
        return "PMU_MISC1";
268
    case PMU_MISC1_SET:
269
        return "PMU_MISC1_SET";
270
    case PMU_MISC1_CLR:
271
        return "PMU_MISC1_CLR";
272
    case PMU_MISC1_TOG:
273
        return "PMU_MISC1_TOG";
274
    case USB_ANALOG_DIGPROG:
275
        return "USB_ANALOG_DIGPROG";
276
    default:
277
        snprintf(unknown, sizeof(unknown), "%u ?", reg);
278
        return unknown;
279
    }
280
}
281

282
#define CKIH_FREQ 24000000 /* 24MHz crystal input */
283

284
static const VMStateDescription vmstate_imx6ul_ccm = {
285
    .name = TYPE_IMX6UL_CCM,
286
    .version_id = 1,
287
    .minimum_version_id = 1,
288
    .fields = (const VMStateField[]) {
289
        VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX),
290
        VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX),
291
        VMSTATE_END_OF_LIST()
292
    },
293
};
294

295
static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev)
296
{
297
    uint64_t freq = CKIH_FREQ;
298

299
    trace_ccm_freq((uint32_t)freq);
300

301
    return freq;
302
}
303

304
static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev)
305
{
306
    uint64_t freq = imx6ul_analog_get_osc_clk(dev);
307

308
    if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS],
309
                   ANALOG_PLL_SYS, DIV_SELECT)) {
310
        freq *= 22;
311
    } else {
312
        freq *= 20;
313
    }
314

315
    trace_ccm_freq((uint32_t)freq);
316

317
    return freq;
318
}
319

320
static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev)
321
{
322
    uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20;
323

324
    trace_ccm_freq((uint32_t)freq);
325

326
    return freq;
327
}
328

329
static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev)
330
{
331
    uint64_t freq = 0;
332

333
    freq = imx6ul_analog_get_pll2_clk(dev) * 18
334
           / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
335
                        ANALOG_PFD_528, PFD0_FRAC);
336

337
    trace_ccm_freq((uint32_t)freq);
338

339
    return freq;
340
}
341

342
static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev)
343
{
344
    uint64_t freq = 0;
345

346
    freq = imx6ul_analog_get_pll2_clk(dev) * 18
347
           / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
348
                        ANALOG_PFD_528, PFD2_FRAC);
349

350
    trace_ccm_freq((uint32_t)freq);
351

352
    return freq;
353
}
354

355
static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev)
356
{
357
    uint64_t freq = 0;
358

359
    trace_ccm_freq((uint32_t)freq);
360

361
    return freq;
362
}
363

364
static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev)
365
{
366
    uint64_t freq = 0;
367

368
    switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) {
369
    case 0:
370
        freq = imx6ul_analog_get_pll3_clk(dev);
371
        break;
372
    case 1:
373
        freq = imx6ul_analog_get_osc_clk(dev);
374
        break;
375
    case 2:
376
        freq = imx6ul_analog_pll2_bypass_clk(dev);
377
        break;
378
    case 3:
379
        /* We should never get there as 3 is a reserved value */
380
        qemu_log_mask(LOG_GUEST_ERROR,
381
                      "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n",
382
                      TYPE_IMX6UL_CCM, __func__);
383
        /* freq is set to 0 as we don't know what it should be */
384
        break;
385
    default:
386
        g_assert_not_reached();
387
    }
388

389
    trace_ccm_freq((uint32_t)freq);
390

391
    return freq;
392
}
393

394
static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev)
395
{
396
    uint64_t freq = 0;
397

398
    switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) {
399
    case 0:
400
        freq = imx6ul_analog_get_pll2_clk(dev);
401
        break;
402
    case 1:
403
        freq = imx6ul_analog_get_pll2_pfd2_clk(dev);
404
        break;
405
    case 2:
406
        freq = imx6ul_analog_get_pll2_pfd0_clk(dev);
407
        break;
408
    case 3:
409
        freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2;
410
        break;
411
    default:
412
        g_assert_not_reached();
413
    }
414

415
    trace_ccm_freq((uint32_t)freq);
416

417
    return freq;
418
}
419

420
static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev)
421
{
422
    uint64_t freq = 0;
423

424
    freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev)
425
           / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF));
426

427
    trace_ccm_freq((uint32_t)freq);
428

429
    return freq;
430
}
431

432
static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev)
433
{
434
    uint64_t freq = 0;
435

436
    switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) {
437
    case 0:
438
        freq = imx6ul_ccm_get_periph_clk_sel_clk(dev);
439
        break;
440
    case 1:
441
        freq = imx6ul_ccm_get_periph_clk2_clk(dev);
442
        break;
443
    default:
444
        g_assert_not_reached();
445
    }
446

447
    trace_ccm_freq((uint32_t)freq);
448

449
    return freq;
450
}
451

452
static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev)
453
{
454
    uint64_t freq = 0;
455

456
    freq = imx6ul_ccm_get_periph_sel_clk(dev)
457
           / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF));
458

459
    trace_ccm_freq((uint32_t)freq);
460

461
    return freq;
462
}
463

464
static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev)
465
{
466
    uint64_t freq = 0;
467

468
    freq = imx6ul_ccm_get_ahb_clk(dev)
469
           / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF));
470

471
    trace_ccm_freq((uint32_t)freq);
472

473
    return freq;
474
}
475

476
static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev)
477
{
478
    uint64_t freq = 0;
479

480
    switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) {
481
    case 0:
482
        freq = imx6ul_ccm_get_ipg_clk(dev);
483
        break;
484
    case 1:
485
        freq = imx6ul_analog_get_osc_clk(dev);
486
        break;
487
    default:
488
        g_assert_not_reached();
489
    }
490

491
    trace_ccm_freq((uint32_t)freq);
492

493
    return freq;
494
}
495

496
static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev)
497
{
498
    uint64_t freq = 0;
499

500
    freq = imx6ul_ccm_get_per_sel_clk(dev)
501
           / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF));
502

503
    trace_ccm_freq((uint32_t)freq);
504

505
    return freq;
506
}
507

508
static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
509
{
510
    uint32_t freq = 0;
511
    IMX6ULCCMState *s = IMX6UL_CCM(dev);
512

513
    switch (clock) {
514
    case CLK_NONE:
515
        break;
516
    case CLK_IPG:
517
        freq = imx6ul_ccm_get_ipg_clk(s);
518
        break;
519
    case CLK_IPG_HIGH:
520
        freq = imx6ul_ccm_get_per_clk(s);
521
        break;
522
    case CLK_32k:
523
        freq = CKIL_FREQ;
524
        break;
525
    default:
526
        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
527
                      TYPE_IMX6UL_CCM, __func__, clock);
528
        break;
529
    }
530

531
    trace_ccm_clock_freq(clock, freq);
532

533
    return freq;
534
}
535

536
static void imx6ul_ccm_reset(DeviceState *dev)
537
{
538
    IMX6ULCCMState *s = IMX6UL_CCM(dev);
539

540
    trace_ccm_entry();
541

542
    s->ccm[CCM_CCR] = 0x0401167F;
543
    s->ccm[CCM_CCDR] = 0x00000000;
544
    s->ccm[CCM_CSR] = 0x00000010;
545
    s->ccm[CCM_CCSR] = 0x00000100;
546
    s->ccm[CCM_CACRR] = 0x00000000;
547
    s->ccm[CCM_CBCDR] = 0x00018D00;
548
    s->ccm[CCM_CBCMR] = 0x24860324;
549
    s->ccm[CCM_CSCMR1] = 0x04900080;
550
    s->ccm[CCM_CSCMR2] = 0x03192F06;
551
    s->ccm[CCM_CSCDR1] = 0x00490B00;
552
    s->ccm[CCM_CS1CDR] = 0x0EC102C1;
553
    s->ccm[CCM_CS2CDR] = 0x000336C1;
554
    s->ccm[CCM_CDCDR] = 0x33F71F92;
555
    s->ccm[CCM_CHSCCDR] = 0x000248A4;
556
    s->ccm[CCM_CSCDR2] = 0x00029B48;
557
    s->ccm[CCM_CSCDR3] = 0x00014841;
558
    s->ccm[CCM_CDHIPR] = 0x00000000;
559
    s->ccm[CCM_CTOR] = 0x00000000;
560
    s->ccm[CCM_CLPCR] = 0x00000079;
561
    s->ccm[CCM_CISR] = 0x00000000;
562
    s->ccm[CCM_CIMR] = 0xFFFFFFFF;
563
    s->ccm[CCM_CCOSR] = 0x000A0001;
564
    s->ccm[CCM_CGPR] = 0x0000FE62;
565
    s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
566
    s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
567
    s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
568
    s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
569
    s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
570
    s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
571
    s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
572
    s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
573

574
    s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063;
575
    s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
576
    s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
577
    s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
578
    s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
579
    s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
580
    s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
581
    s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
582
    s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
583
    s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
584
    s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
585
    s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
586
    s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
587
    s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
588
    s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
589
    s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
590

591
    s->analog[PMU_REG_1P1] = 0x00001073;
592
    s->analog[PMU_REG_3P0] = 0x00000F74;
593
    s->analog[PMU_REG_2P5] = 0x00001073;
594
    s->analog[PMU_REG_CORE] = 0x00482012;
595
    s->analog[PMU_MISC0] = 0x04000000;
596
    s->analog[PMU_MISC1] = 0x00000000;
597
    s->analog[PMU_MISC2] = 0x00272727;
598
    s->analog[PMU_LOWPWR_CTRL] = 0x00004009;
599

600
    s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004;
601
    s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
602
    s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
603
    s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
604
    s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
605
    s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004;
606
    s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
607
    s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
608
    s->analog[USB_ANALOG_DIGPROG] = 0x00640000;
609

610
    /* all PLLs need to be locked */
611
    s->analog[CCM_ANALOG_PLL_ARM]   |= CCM_ANALOG_PLL_LOCK;
612
    s->analog[CCM_ANALOG_PLL_USB1]  |= CCM_ANALOG_PLL_LOCK;
613
    s->analog[CCM_ANALOG_PLL_USB2]  |= CCM_ANALOG_PLL_LOCK;
614
    s->analog[CCM_ANALOG_PLL_SYS]   |= CCM_ANALOG_PLL_LOCK;
615
    s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
616
    s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
617
    s->analog[CCM_ANALOG_PLL_ENET]  |= CCM_ANALOG_PLL_LOCK;
618

619
    s->analog[TEMPMON_TEMPSENSE0] = 0x00000001;
620
    s->analog[TEMPMON_TEMPSENSE1] = 0x00000001;
621
    s->analog[TEMPMON_TEMPSENSE2] = 0x00000000;
622
}
623

624
static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size)
625
{
626
    uint32_t value = 0;
627
    uint32_t index = offset >> 2;
628
    IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
629

630
    assert(index < CCM_MAX);
631

632
    value = s->ccm[index];
633

634
    trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
635

636
    return (uint64_t)value;
637
}
638

639
static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
640
                           unsigned size)
641
{
642
    uint32_t index = offset >> 2;
643
    IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
644

645
    assert(index < CCM_MAX);
646

647
    trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
648

649
    s->ccm[index] = (s->ccm[index] & ccm_mask[index]) |
650
                           ((uint32_t)value & ~ccm_mask[index]);
651
}
652

653
static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
654
{
655
    uint32_t value;
656
    uint32_t index = offset >> 2;
657
    IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
658

659
    assert(index < CCM_ANALOG_MAX);
660

661
    switch (index) {
662
    case CCM_ANALOG_PLL_ARM_SET:
663
    case CCM_ANALOG_PLL_USB1_SET:
664
    case CCM_ANALOG_PLL_USB2_SET:
665
    case CCM_ANALOG_PLL_SYS_SET:
666
    case CCM_ANALOG_PLL_AUDIO_SET:
667
    case CCM_ANALOG_PLL_VIDEO_SET:
668
    case CCM_ANALOG_PLL_ENET_SET:
669
    case CCM_ANALOG_PFD_480_SET:
670
    case CCM_ANALOG_PFD_528_SET:
671
    case CCM_ANALOG_MISC0_SET:
672
    case PMU_MISC1_SET:
673
    case CCM_ANALOG_MISC2_SET:
674
    case USB_ANALOG_USB1_VBUS_DETECT_SET:
675
    case USB_ANALOG_USB1_CHRG_DETECT_SET:
676
    case USB_ANALOG_USB1_MISC_SET:
677
    case USB_ANALOG_USB2_VBUS_DETECT_SET:
678
    case USB_ANALOG_USB2_CHRG_DETECT_SET:
679
    case USB_ANALOG_USB2_MISC_SET:
680
    case TEMPMON_TEMPSENSE0_SET:
681
    case TEMPMON_TEMPSENSE1_SET:
682
    case TEMPMON_TEMPSENSE2_SET:
683
        /*
684
         * All REG_NAME_SET register access are in fact targeting
685
         * the REG_NAME register.
686
         */
687
        value = s->analog[index - 1];
688
        break;
689
    case CCM_ANALOG_PLL_ARM_CLR:
690
    case CCM_ANALOG_PLL_USB1_CLR:
691
    case CCM_ANALOG_PLL_USB2_CLR:
692
    case CCM_ANALOG_PLL_SYS_CLR:
693
    case CCM_ANALOG_PLL_AUDIO_CLR:
694
    case CCM_ANALOG_PLL_VIDEO_CLR:
695
    case CCM_ANALOG_PLL_ENET_CLR:
696
    case CCM_ANALOG_PFD_480_CLR:
697
    case CCM_ANALOG_PFD_528_CLR:
698
    case CCM_ANALOG_MISC0_CLR:
699
    case PMU_MISC1_CLR:
700
    case CCM_ANALOG_MISC2_CLR:
701
    case USB_ANALOG_USB1_VBUS_DETECT_CLR:
702
    case USB_ANALOG_USB1_CHRG_DETECT_CLR:
703
    case USB_ANALOG_USB1_MISC_CLR:
704
    case USB_ANALOG_USB2_VBUS_DETECT_CLR:
705
    case USB_ANALOG_USB2_CHRG_DETECT_CLR:
706
    case USB_ANALOG_USB2_MISC_CLR:
707
    case TEMPMON_TEMPSENSE0_CLR:
708
    case TEMPMON_TEMPSENSE1_CLR:
709
    case TEMPMON_TEMPSENSE2_CLR:
710
        /*
711
         * All REG_NAME_CLR register access are in fact targeting
712
         * the REG_NAME register.
713
         */
714
        value = s->analog[index - 2];
715
        break;
716
    case CCM_ANALOG_PLL_ARM_TOG:
717
    case CCM_ANALOG_PLL_USB1_TOG:
718
    case CCM_ANALOG_PLL_USB2_TOG:
719
    case CCM_ANALOG_PLL_SYS_TOG:
720
    case CCM_ANALOG_PLL_AUDIO_TOG:
721
    case CCM_ANALOG_PLL_VIDEO_TOG:
722
    case CCM_ANALOG_PLL_ENET_TOG:
723
    case CCM_ANALOG_PFD_480_TOG:
724
    case CCM_ANALOG_PFD_528_TOG:
725
    case CCM_ANALOG_MISC0_TOG:
726
    case PMU_MISC1_TOG:
727
    case CCM_ANALOG_MISC2_TOG:
728
    case USB_ANALOG_USB1_VBUS_DETECT_TOG:
729
    case USB_ANALOG_USB1_CHRG_DETECT_TOG:
730
    case USB_ANALOG_USB1_MISC_TOG:
731
    case USB_ANALOG_USB2_VBUS_DETECT_TOG:
732
    case USB_ANALOG_USB2_CHRG_DETECT_TOG:
733
    case USB_ANALOG_USB2_MISC_TOG:
734
    case TEMPMON_TEMPSENSE0_TOG:
735
    case TEMPMON_TEMPSENSE1_TOG:
736
    case TEMPMON_TEMPSENSE2_TOG:
737
        /*
738
         * All REG_NAME_TOG register access are in fact targeting
739
         * the REG_NAME register.
740
         */
741
        value = s->analog[index - 3];
742
        break;
743
    default:
744
        value = s->analog[index];
745
        break;
746
    }
747

748
    trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
749

750
    return (uint64_t)value;
751
}
752

753
static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
754
                              unsigned size)
755
{
756
    uint32_t index = offset >> 2;
757
    IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
758

759
    assert(index < CCM_ANALOG_MAX);
760

761
    trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
762

763
    switch (index) {
764
    case CCM_ANALOG_PLL_ARM_SET:
765
    case CCM_ANALOG_PLL_USB1_SET:
766
    case CCM_ANALOG_PLL_USB2_SET:
767
    case CCM_ANALOG_PLL_SYS_SET:
768
    case CCM_ANALOG_PLL_AUDIO_SET:
769
    case CCM_ANALOG_PLL_VIDEO_SET:
770
    case CCM_ANALOG_PLL_ENET_SET:
771
    case CCM_ANALOG_PFD_480_SET:
772
    case CCM_ANALOG_PFD_528_SET:
773
    case CCM_ANALOG_MISC0_SET:
774
    case PMU_MISC1_SET:
775
    case CCM_ANALOG_MISC2_SET:
776
    case USB_ANALOG_USB1_VBUS_DETECT_SET:
777
    case USB_ANALOG_USB1_CHRG_DETECT_SET:
778
    case USB_ANALOG_USB1_MISC_SET:
779
    case USB_ANALOG_USB2_VBUS_DETECT_SET:
780
    case USB_ANALOG_USB2_CHRG_DETECT_SET:
781
    case USB_ANALOG_USB2_MISC_SET:
782
        /*
783
         * All REG_NAME_SET register access are in fact targeting
784
         * the REG_NAME register. So we change the value of the
785
         * REG_NAME register, setting bits passed in the value.
786
         */
787
        s->analog[index - 1] |= (value & ~analog_mask[index - 1]);
788
        break;
789
    case CCM_ANALOG_PLL_ARM_CLR:
790
    case CCM_ANALOG_PLL_USB1_CLR:
791
    case CCM_ANALOG_PLL_USB2_CLR:
792
    case CCM_ANALOG_PLL_SYS_CLR:
793
    case CCM_ANALOG_PLL_AUDIO_CLR:
794
    case CCM_ANALOG_PLL_VIDEO_CLR:
795
    case CCM_ANALOG_PLL_ENET_CLR:
796
    case CCM_ANALOG_PFD_480_CLR:
797
    case CCM_ANALOG_PFD_528_CLR:
798
    case CCM_ANALOG_MISC0_CLR:
799
    case PMU_MISC1_CLR:
800
    case CCM_ANALOG_MISC2_CLR:
801
    case USB_ANALOG_USB1_VBUS_DETECT_CLR:
802
    case USB_ANALOG_USB1_CHRG_DETECT_CLR:
803
    case USB_ANALOG_USB1_MISC_CLR:
804
    case USB_ANALOG_USB2_VBUS_DETECT_CLR:
805
    case USB_ANALOG_USB2_CHRG_DETECT_CLR:
806
    case USB_ANALOG_USB2_MISC_CLR:
807
        /*
808
         * All REG_NAME_CLR register access are in fact targeting
809
         * the REG_NAME register. So we change the value of the
810
         * REG_NAME register, unsetting bits passed in the value.
811
         */
812
        s->analog[index - 2] &= ~(value & ~analog_mask[index - 2]);
813
        break;
814
    case CCM_ANALOG_PLL_ARM_TOG:
815
    case CCM_ANALOG_PLL_USB1_TOG:
816
    case CCM_ANALOG_PLL_USB2_TOG:
817
    case CCM_ANALOG_PLL_SYS_TOG:
818
    case CCM_ANALOG_PLL_AUDIO_TOG:
819
    case CCM_ANALOG_PLL_VIDEO_TOG:
820
    case CCM_ANALOG_PLL_ENET_TOG:
821
    case CCM_ANALOG_PFD_480_TOG:
822
    case CCM_ANALOG_PFD_528_TOG:
823
    case CCM_ANALOG_MISC0_TOG:
824
    case PMU_MISC1_TOG:
825
    case CCM_ANALOG_MISC2_TOG:
826
    case USB_ANALOG_USB1_VBUS_DETECT_TOG:
827
    case USB_ANALOG_USB1_CHRG_DETECT_TOG:
828
    case USB_ANALOG_USB1_MISC_TOG:
829
    case USB_ANALOG_USB2_VBUS_DETECT_TOG:
830
    case USB_ANALOG_USB2_CHRG_DETECT_TOG:
831
    case USB_ANALOG_USB2_MISC_TOG:
832
        /*
833
         * All REG_NAME_TOG register access are in fact targeting
834
         * the REG_NAME register. So we change the value of the
835
         * REG_NAME register, toggling bits passed in the value.
836
         */
837
        s->analog[index - 3] ^= (value & ~analog_mask[index - 3]);
838
        break;
839
    default:
840
        s->analog[index] = (s->analog[index] & analog_mask[index]) |
841
                           (value & ~analog_mask[index]);
842
        break;
843
    }
844
}
845

846
static const struct MemoryRegionOps imx6ul_ccm_ops = {
847
    .read = imx6ul_ccm_read,
848
    .write = imx6ul_ccm_write,
849
    .endianness = DEVICE_NATIVE_ENDIAN,
850
    .valid = {
851
        /*
852
         * Our device would not work correctly if the guest was doing
853
         * unaligned access. This might not be a limitation on the real
854
         * device but in practice there is no reason for a guest to access
855
         * this device unaligned.
856
         */
857
        .min_access_size = 4,
858
        .max_access_size = 4,
859
        .unaligned = false,
860
    },
861
};
862

863
static const struct MemoryRegionOps imx6ul_analog_ops = {
864
    .read = imx6ul_analog_read,
865
    .write = imx6ul_analog_write,
866
    .endianness = DEVICE_NATIVE_ENDIAN,
867
    .valid = {
868
        /*
869
         * Our device would not work correctly if the guest was doing
870
         * unaligned access. This might not be a limitation on the real
871
         * device but in practice there is no reason for a guest to access
872
         * this device unaligned.
873
         */
874
        .min_access_size = 4,
875
        .max_access_size = 4,
876
        .unaligned = false,
877
    },
878
};
879

880
static void imx6ul_ccm_init(Object *obj)
881
{
882
    DeviceState *dev = DEVICE(obj);
883
    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
884
    IMX6ULCCMState *s = IMX6UL_CCM(obj);
885

886
    /* initialize a container for the all memory range */
887
    memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000);
888

889
    /* We initialize an IO memory region for the CCM part */
890
    memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s,
891
                          TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
892

893
    /* Add the CCM as a subregion at offset 0 */
894
    memory_region_add_subregion(&s->container, 0, &s->ioccm);
895

896
    /* We initialize an IO memory region for the ANALOG part */
897
    memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s,
898
                          TYPE_IMX6UL_CCM ".analog",
899
                          CCM_ANALOG_MAX * sizeof(uint32_t));
900

901
    /* Add the ANALOG as a subregion at offset 0x4000 */
902
    memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
903

904
    sysbus_init_mmio(sd, &s->container);
905
}
906

907
static void imx6ul_ccm_class_init(ObjectClass *klass, void *data)
908
{
909
    DeviceClass *dc = DEVICE_CLASS(klass);
910
    IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
911

912
    dc->reset = imx6ul_ccm_reset;
913
    dc->vmsd = &vmstate_imx6ul_ccm;
914
    dc->desc = "i.MX6UL Clock Control Module";
915

916
    ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency;
917
}
918

919
static const TypeInfo imx6ul_ccm_info = {
920
    .name          = TYPE_IMX6UL_CCM,
921
    .parent        = TYPE_IMX_CCM,
922
    .instance_size = sizeof(IMX6ULCCMState),
923
    .instance_init = imx6ul_ccm_init,
924
    .class_init    = imx6ul_ccm_class_init,
925
};
926

927
static void imx6ul_ccm_register_types(void)
928
{
929
    type_register_static(&imx6ul_ccm_info);
930
}
931

932
type_init(imx6ul_ccm_register_types)
933

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.