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
imx6ul_ccm_reg_name(uint32_t reg)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
imx6ul_analog_reg_name(uint32_t reg)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
imx6ul_analog_get_osc_clk(IMX6ULCCMState * dev)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
imx6ul_analog_get_pll2_clk(IMX6ULCCMState * dev)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
imx6ul_analog_get_pll3_clk(IMX6ULCCMState * dev)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
imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState * dev)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
imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState * dev)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
imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_ahb_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_ipg_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_per_clk(IMX6ULCCMState * dev)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
imx6ul_ccm_get_clock_frequency(IMXCCMState * dev,IMXClk clock)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
imx6ul_ccm_reset(DeviceState * dev)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
imx6ul_ccm_read(void * opaque,hwaddr offset,unsigned size)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
imx6ul_ccm_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)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
imx6ul_analog_read(void * opaque,hwaddr offset,unsigned size)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
imx6ul_analog_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)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
imx6ul_ccm_init(Object * obj)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
imx6ul_ccm_class_init(ObjectClass * klass,void * data)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 device_class_set_legacy_reset(dc, 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
imx6ul_ccm_register_types(void)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