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"
plot_trace( data, var_names, divergences, kind, figsize, rug, lines, circ_var_names, circ_var_units, compact, compact_prop, combined, chain_prop, legend, labeller, plot_kwargs, fill_kwargs, rug_kwargs, hist_kwargs, trace_kwargs, rank_kwargs, plotters, divergence_data, axes, backend_kwargs, backend_config, show, )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 sprintf(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 sprintf(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 = (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;
_plot_chains_mpl( axes, idy, value, data, chain_prop, combined, xt_labelsize, rug, kind, trace_kwargs, hist_kwargs, plot_kwargs, fill_kwargs, rug_kwargs, rank_kwargs, circular, circ_var_units, circ_units_trace, )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 case CLK_HIGH:
526 freq = CKIH_FREQ;
527 break;
528 case CLK_HIGH_DIV:
529 freq = CKIH_FREQ / 8;
530 break;
531 default:
532 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
533 TYPE_IMX6UL_CCM, __func__, clock);
534 break;
535 }
536
537 trace_ccm_clock_freq(clock, freq);
538
539 return freq;
540 }
541
542 static void imx6ul_ccm_reset(DeviceState *dev)
543 {
544 IMX6ULCCMState *s = IMX6UL_CCM(dev);
545
546 trace_ccm_entry();
547
548 s->ccm[CCM_CCR] = 0x0401167F;
549 s->ccm[CCM_CCDR] = 0x00000000;
550 s->ccm[CCM_CSR] = 0x00000010;
551 s->ccm[CCM_CCSR] = 0x00000100;
552 s->ccm[CCM_CACRR] = 0x00000000;
553 s->ccm[CCM_CBCDR] = 0x00018D00;
554 s->ccm[CCM_CBCMR] = 0x24860324;
555 s->ccm[CCM_CSCMR1] = 0x04900080;
556 s->ccm[CCM_CSCMR2] = 0x03192F06;
557 s->ccm[CCM_CSCDR1] = 0x00490B00;
558 s->ccm[CCM_CS1CDR] = 0x0EC102C1;
559 s->ccm[CCM_CS2CDR] = 0x000336C1;
560 s->ccm[CCM_CDCDR] = 0x33F71F92;
561 s->ccm[CCM_CHSCCDR] = 0x000248A4;
562 s->ccm[CCM_CSCDR2] = 0x00029B48;
563 s->ccm[CCM_CSCDR3] = 0x00014841;
564 s->ccm[CCM_CDHIPR] = 0x00000000;
565 s->ccm[CCM_CTOR] = 0x00000000;
566 s->ccm[CCM_CLPCR] = 0x00000079;
567 s->ccm[CCM_CISR] = 0x00000000;
568 s->ccm[CCM_CIMR] = 0xFFFFFFFF;
569 s->ccm[CCM_CCOSR] = 0x000A0001;
570 s->ccm[CCM_CGPR] = 0x0000FE62;
571 s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
572 s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
573 s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
574 s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
575 s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
576 s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
577 s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
578 s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
579
580 s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063;
581 s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
582 s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
583 s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
584 s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
585 s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
586 s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
587 s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
588 s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
589 s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
590 s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
591 s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
592 s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
593 s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
594 s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
595 s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
596
597 s->analog[PMU_REG_1P1] = 0x00001073;
598 s->analog[PMU_REG_3P0] = 0x00000F74;
599 s->analog[PMU_REG_2P5] = 0x00001073;
600 s->analog[PMU_REG_CORE] = 0x00482012;
601 s->analog[PMU_MISC0] = 0x04000000;
602 s->analog[PMU_MISC1] = 0x00000000;
603 s->analog[PMU_MISC2] = 0x00272727;
604 s->analog[PMU_LOWPWR_CTRL] = 0x00004009;
605
606 s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004;
607 s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
608 s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
609 s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
610 s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
611 s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004;
612 s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
613 s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
614 s->analog[USB_ANALOG_DIGPROG] = 0x00640000;
615
616 /* all PLLs need to be locked */
617 s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK;
618 s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK;
619 s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK;
620 s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK;
621 s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
622 s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
623 s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK;
624
625 s->analog[TEMPMON_TEMPSENSE0] = 0x00000001;
626 s->analog[TEMPMON_TEMPSENSE1] = 0x00000001;
627 s->analog[TEMPMON_TEMPSENSE2] = 0x00000000;
628 }
629
630 static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size)
631 {
632 uint32_t value = 0;
633 uint32_t index = offset >> 2;
634 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
635
636 assert(index < CCM_MAX);
637
638 value = s->ccm[index];
639
640 trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
641
642 return (uint64_t)value;
643 }
644
645 static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
646 unsigned size)
647 {
648 uint32_t index = offset >> 2;
649 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
650
651 assert(index < CCM_MAX);
652
653 trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
654
655 s->ccm[index] = (s->ccm[index] & ccm_mask[index]) |
656 ((uint32_t)value & ~ccm_mask[index]);
657 }
658
659 static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
660 {
661 uint32_t value;
662 uint32_t index = offset >> 2;
663 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
664
665 assert(index < CCM_ANALOG_MAX);
666
667 switch (index) {
668 case CCM_ANALOG_PLL_ARM_SET:
669 case CCM_ANALOG_PLL_USB1_SET:
670 case CCM_ANALOG_PLL_USB2_SET:
671 case CCM_ANALOG_PLL_SYS_SET:
672 case CCM_ANALOG_PLL_AUDIO_SET:
673 case CCM_ANALOG_PLL_VIDEO_SET:
674 case CCM_ANALOG_PLL_ENET_SET:
675 case CCM_ANALOG_PFD_480_SET:
676 case CCM_ANALOG_PFD_528_SET:
677 case CCM_ANALOG_MISC0_SET:
678 case PMU_MISC1_SET:
679 case CCM_ANALOG_MISC2_SET:
680 case USB_ANALOG_USB1_VBUS_DETECT_SET:
681 case USB_ANALOG_USB1_CHRG_DETECT_SET:
682 case USB_ANALOG_USB1_MISC_SET:
683 case USB_ANALOG_USB2_VBUS_DETECT_SET:
684 case USB_ANALOG_USB2_CHRG_DETECT_SET:
685 case USB_ANALOG_USB2_MISC_SET:
686 case TEMPMON_TEMPSENSE0_SET:
687 case TEMPMON_TEMPSENSE1_SET:
688 case TEMPMON_TEMPSENSE2_SET:
689 /*
690 * All REG_NAME_SET register access are in fact targeting
691 * the REG_NAME register.
692 */
693 value = s->analog[index - 1];
694 break;
695 case CCM_ANALOG_PLL_ARM_CLR:
696 case CCM_ANALOG_PLL_USB1_CLR:
697 case CCM_ANALOG_PLL_USB2_CLR:
698 case CCM_ANALOG_PLL_SYS_CLR:
699 case CCM_ANALOG_PLL_AUDIO_CLR:
700 case CCM_ANALOG_PLL_VIDEO_CLR:
701 case CCM_ANALOG_PLL_ENET_CLR:
702 case CCM_ANALOG_PFD_480_CLR:
703 case CCM_ANALOG_PFD_528_CLR:
704 case CCM_ANALOG_MISC0_CLR:
705 case PMU_MISC1_CLR:
706 case CCM_ANALOG_MISC2_CLR:
707 case USB_ANALOG_USB1_VBUS_DETECT_CLR:
708 case USB_ANALOG_USB1_CHRG_DETECT_CLR:
709 case USB_ANALOG_USB1_MISC_CLR:
710 case USB_ANALOG_USB2_VBUS_DETECT_CLR:
711 case USB_ANALOG_USB2_CHRG_DETECT_CLR:
712 case USB_ANALOG_USB2_MISC_CLR:
713 case TEMPMON_TEMPSENSE0_CLR:
714 case TEMPMON_TEMPSENSE1_CLR:
715 case TEMPMON_TEMPSENSE2_CLR:
716 /*
717 * All REG_NAME_CLR register access are in fact targeting
718 * the REG_NAME register.
719 */
720 value = s->analog[index - 2];
721 break;
722 case CCM_ANALOG_PLL_ARM_TOG:
723 case CCM_ANALOG_PLL_USB1_TOG:
724 case CCM_ANALOG_PLL_USB2_TOG:
725 case CCM_ANALOG_PLL_SYS_TOG:
726 case CCM_ANALOG_PLL_AUDIO_TOG:
727 case CCM_ANALOG_PLL_VIDEO_TOG:
728 case CCM_ANALOG_PLL_ENET_TOG:
729 case CCM_ANALOG_PFD_480_TOG:
730 case CCM_ANALOG_PFD_528_TOG:
731 case CCM_ANALOG_MISC0_TOG:
732 case PMU_MISC1_TOG:
733 case CCM_ANALOG_MISC2_TOG:
734 case USB_ANALOG_USB1_VBUS_DETECT_TOG:
735 case USB_ANALOG_USB1_CHRG_DETECT_TOG:
736 case USB_ANALOG_USB1_MISC_TOG:
737 case USB_ANALOG_USB2_VBUS_DETECT_TOG:
738 case USB_ANALOG_USB2_CHRG_DETECT_TOG:
739 case USB_ANALOG_USB2_MISC_TOG:
740 case TEMPMON_TEMPSENSE0_TOG:
741 case TEMPMON_TEMPSENSE1_TOG:
742 case TEMPMON_TEMPSENSE2_TOG:
743 /*
744 * All REG_NAME_TOG register access are in fact targeting
745 * the REG_NAME register.
746 */
747 value = s->analog[index - 3];
748 break;
749 default:
750 value = s->analog[index];
751 break;
752 }
753
754 trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
755
756 return (uint64_t)value;
757 }
758
759 static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
760 unsigned size)
761 {
762 uint32_t index = offset >> 2;
763 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
764
765 assert(index < CCM_ANALOG_MAX);
766
767 trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
768
769 switch (index) {
770 case CCM_ANALOG_PLL_ARM_SET:
771 case CCM_ANALOG_PLL_USB1_SET:
772 case CCM_ANALOG_PLL_USB2_SET:
773 case CCM_ANALOG_PLL_SYS_SET:
774 case CCM_ANALOG_PLL_AUDIO_SET:
775 case CCM_ANALOG_PLL_VIDEO_SET:
776 case CCM_ANALOG_PLL_ENET_SET:
777 case CCM_ANALOG_PFD_480_SET:
778 case CCM_ANALOG_PFD_528_SET:
779 case CCM_ANALOG_MISC0_SET:
780 case PMU_MISC1_SET:
781 case CCM_ANALOG_MISC2_SET:
782 case USB_ANALOG_USB1_VBUS_DETECT_SET:
783 case USB_ANALOG_USB1_CHRG_DETECT_SET:
784 case USB_ANALOG_USB1_MISC_SET:
785 case USB_ANALOG_USB2_VBUS_DETECT_SET:
786 case USB_ANALOG_USB2_CHRG_DETECT_SET:
787 case USB_ANALOG_USB2_MISC_SET:
788 /*
789 * All REG_NAME_SET register access are in fact targeting
790 * the REG_NAME register. So we change the value of the
791 * REG_NAME register, setting bits passed in the value.
792 */
793 s->analog[index - 1] |= (value & ~analog_mask[index - 1]);
794 break;
795 case CCM_ANALOG_PLL_ARM_CLR:
796 case CCM_ANALOG_PLL_USB1_CLR:
797 case CCM_ANALOG_PLL_USB2_CLR:
798 case CCM_ANALOG_PLL_SYS_CLR:
799 case CCM_ANALOG_PLL_AUDIO_CLR:
800 case CCM_ANALOG_PLL_VIDEO_CLR:
801 case CCM_ANALOG_PLL_ENET_CLR:
802 case CCM_ANALOG_PFD_480_CLR:
803 case CCM_ANALOG_PFD_528_CLR:
804 case CCM_ANALOG_MISC0_CLR:
805 case PMU_MISC1_CLR:
806 case CCM_ANALOG_MISC2_CLR:
807 case USB_ANALOG_USB1_VBUS_DETECT_CLR:
808 case USB_ANALOG_USB1_CHRG_DETECT_CLR:
809 case USB_ANALOG_USB1_MISC_CLR:
810 case USB_ANALOG_USB2_VBUS_DETECT_CLR:
811 case USB_ANALOG_USB2_CHRG_DETECT_CLR:
812 case USB_ANALOG_USB2_MISC_CLR:
813 /*
814 * All REG_NAME_CLR register access are in fact targeting
815 * the REG_NAME register. So we change the value of the
816 * REG_NAME register, unsetting bits passed in the value.
817 */
818 s->analog[index - 2] &= ~(value & ~analog_mask[index - 2]);
819 break;
820 case CCM_ANALOG_PLL_ARM_TOG:
821 case CCM_ANALOG_PLL_USB1_TOG:
822 case CCM_ANALOG_PLL_USB2_TOG:
823 case CCM_ANALOG_PLL_SYS_TOG:
824 case CCM_ANALOG_PLL_AUDIO_TOG:
825 case CCM_ANALOG_PLL_VIDEO_TOG:
826 case CCM_ANALOG_PLL_ENET_TOG:
827 case CCM_ANALOG_PFD_480_TOG:
828 case CCM_ANALOG_PFD_528_TOG:
829 case CCM_ANALOG_MISC0_TOG:
830 case PMU_MISC1_TOG:
831 case CCM_ANALOG_MISC2_TOG:
832 case USB_ANALOG_USB1_VBUS_DETECT_TOG:
833 case USB_ANALOG_USB1_CHRG_DETECT_TOG:
834 case USB_ANALOG_USB1_MISC_TOG:
835 case USB_ANALOG_USB2_VBUS_DETECT_TOG:
836 case USB_ANALOG_USB2_CHRG_DETECT_TOG:
837 case USB_ANALOG_USB2_MISC_TOG:
838 /*
839 * All REG_NAME_TOG register access are in fact targeting
840 * the REG_NAME register. So we change the value of the
841 * REG_NAME register, toggling bits passed in the value.
842 */
843 s->analog[index - 3] ^= (value & ~analog_mask[index - 3]);
844 break;
845 default:
846 s->analog[index] = (s->analog[index] & analog_mask[index]) |
847 (value & ~analog_mask[index]);
848 break;
849 }
850 }
851
852 static const struct MemoryRegionOps imx6ul_ccm_ops = {
853 .read = imx6ul_ccm_read,
854 .write = imx6ul_ccm_write,
855 .endianness = DEVICE_NATIVE_ENDIAN,
856 .valid = {
857 /*
858 * Our device would not work correctly if the guest was doing
859 * unaligned access. This might not be a limitation on the real
860 * device but in practice there is no reason for a guest to access
861 * this device unaligned.
862 */
863 .min_access_size = 4,
864 .max_access_size = 4,
865 .unaligned = false,
866 },
867 };
868
869 static const struct MemoryRegionOps imx6ul_analog_ops = {
870 .read = imx6ul_analog_read,
871 .write = imx6ul_analog_write,
872 .endianness = DEVICE_NATIVE_ENDIAN,
873 .valid = {
874 /*
875 * Our device would not work correctly if the guest was doing
876 * unaligned access. This might not be a limitation on the real
877 * device but in practice there is no reason for a guest to access
878 * this device unaligned.
879 */
880 .min_access_size = 4,
881 .max_access_size = 4,
882 .unaligned = false,
883 },
884 };
885
886 static void imx6ul_ccm_init(Object *obj)
887 {
888 DeviceState *dev = DEVICE(obj);
889 SysBusDevice *sd = SYS_BUS_DEVICE(obj);
890 IMX6ULCCMState *s = IMX6UL_CCM(obj);
891
892 /* initialize a container for the all memory range */
893 memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000);
894
895 /* We initialize an IO memory region for the CCM part */
896 memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s,
897 TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
898
899 /* Add the CCM as a subregion at offset 0 */
900 memory_region_add_subregion(&s->container, 0, &s->ioccm);
901
902 /* We initialize an IO memory region for the ANALOG part */
903 memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s,
904 TYPE_IMX6UL_CCM ".analog",
905 CCM_ANALOG_MAX * sizeof(uint32_t));
906
907 /* Add the ANALOG as a subregion at offset 0x4000 */
908 memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
909
910 sysbus_init_mmio(sd, &s->container);
911 }
912
913 static void imx6ul_ccm_class_init(ObjectClass *klass, void *data)
914 {
915 DeviceClass *dc = DEVICE_CLASS(klass);
916 IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
917
918 dc->reset = imx6ul_ccm_reset;
919 dc->vmsd = &vmstate_imx6ul_ccm;
920 dc->desc = "i.MX6UL Clock Control Module";
921
922 ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency;
923 }
924
925 static const TypeInfo imx6ul_ccm_info = {
926 .name = TYPE_IMX6UL_CCM,
927 .parent = TYPE_IMX_CCM,
928 .instance_size = sizeof(IMX6ULCCMState),
929 .instance_init = imx6ul_ccm_init,
930 .class_init = imx6ul_ccm_class_init,
931 };
932
933 static void imx6ul_ccm_register_types(void)
934 {
935 type_register_static(&imx6ul_ccm_info);
936 }
937
938 type_init(imx6ul_ccm_register_types)
939