2 * IMX6UL Clock Control Module
4 * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
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.
9 * To get the timer frequencies right, we need to emulate at least part of
13 #include "qemu/osdep.h"
14 #include "hw/registerfields.h"
15 #include "migration/vmstate.h"
16 #include "hw/misc/imx6ul_ccm.h"
18 #include "qemu/module.h"
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,
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,
78 static const char *imx6ul_ccm_reg_name(uint32_t reg
)
80 static char unknown
[20];
146 snprintf(unknown
, sizeof(unknown
), "%u ?", reg
);
151 static const char *imx6ul_analog_reg_name(uint32_t reg
)
153 static char unknown
[20];
156 case CCM_ANALOG_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
:
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
:
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
:
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
:
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
:
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
:
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
:
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
:
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
:
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
:
244 case CCM_ANALOG_MISC0_SET
:
246 case CCM_ANALOG_MISC0_CLR
:
248 case CCM_ANALOG_MISC0_TOG
:
250 case CCM_ANALOG_MISC2
:
252 case CCM_ANALOG_MISC2_SET
:
254 case CCM_ANALOG_MISC2_CLR
:
256 case CCM_ANALOG_MISC2_TOG
:
259 return "PMU_REG_1P1";
261 return "PMU_REG_3P0";
263 return "PMU_REG_2P5";
265 return "PMU_REG_CORE";
269 return "PMU_MISC1_SET";
271 return "PMU_MISC1_CLR";
273 return "PMU_MISC1_TOG";
274 case USB_ANALOG_DIGPROG
:
275 return "USB_ANALOG_DIGPROG";
277 snprintf(unknown
, sizeof(unknown
), "%u ?", reg
);
282 #define CKIH_FREQ 24000000 /* 24MHz crystal input */
284 static const VMStateDescription vmstate_imx6ul_ccm
= {
285 .name
= TYPE_IMX6UL_CCM
,
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()
295 static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState
*dev
)
297 uint64_t freq
= CKIH_FREQ
;
299 trace_ccm_freq((uint32_t)freq
);
304 static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState
*dev
)
306 uint64_t freq
= imx6ul_analog_get_osc_clk(dev
);
308 if (FIELD_EX32(dev
->analog
[CCM_ANALOG_PLL_SYS
],
309 ANALOG_PLL_SYS
, DIV_SELECT
)) {
315 trace_ccm_freq((uint32_t)freq
);
320 static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState
*dev
)
322 uint64_t freq
= imx6ul_analog_get_osc_clk(dev
) * 20;
324 trace_ccm_freq((uint32_t)freq
);
329 static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState
*dev
)
333 freq
= imx6ul_analog_get_pll2_clk(dev
) * 18
334 / FIELD_EX32(dev
->analog
[CCM_ANALOG_PFD_528
],
335 ANALOG_PFD_528
, PFD0_FRAC
);
337 trace_ccm_freq((uint32_t)freq
);
342 static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState
*dev
)
346 freq
= imx6ul_analog_get_pll2_clk(dev
) * 18
347 / FIELD_EX32(dev
->analog
[CCM_ANALOG_PFD_528
],
348 ANALOG_PFD_528
, PFD2_FRAC
);
350 trace_ccm_freq((uint32_t)freq
);
355 static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState
*dev
)
359 trace_ccm_freq((uint32_t)freq
);
364 static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState
*dev
)
368 switch (FIELD_EX32(dev
->ccm
[CCM_CBCMR
], CBCMR
, PERIPH_CLK2_SEL
)) {
370 freq
= imx6ul_analog_get_pll3_clk(dev
);
373 freq
= imx6ul_analog_get_osc_clk(dev
);
376 freq
= imx6ul_analog_pll2_bypass_clk(dev
);
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 */
386 g_assert_not_reached();
389 trace_ccm_freq((uint32_t)freq
);
394 static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState
*dev
)
398 switch (FIELD_EX32(dev
->ccm
[CCM_CBCMR
], CBCMR
, PRE_PERIPH_CLK_SEL
)) {
400 freq
= imx6ul_analog_get_pll2_clk(dev
);
403 freq
= imx6ul_analog_get_pll2_pfd2_clk(dev
);
406 freq
= imx6ul_analog_get_pll2_pfd0_clk(dev
);
409 freq
= imx6ul_analog_get_pll2_pfd2_clk(dev
) / 2;
412 g_assert_not_reached();
415 trace_ccm_freq((uint32_t)freq
);
420 static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState
*dev
)
424 freq
= imx6ul_ccm_get_periph_clk2_sel_clk(dev
)
425 / (1 + FIELD_EX32(dev
->ccm
[CCM_CBCDR
], CBCDR
, PERIPH_CLK2_PODF
));
427 trace_ccm_freq((uint32_t)freq
);
432 static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState
*dev
)
436 switch (FIELD_EX32(dev
->ccm
[CCM_CBCDR
], CBCDR
, PERIPH_CLK_SEL
)) {
438 freq
= imx6ul_ccm_get_periph_clk_sel_clk(dev
);
441 freq
= imx6ul_ccm_get_periph_clk2_clk(dev
);
444 g_assert_not_reached();
447 trace_ccm_freq((uint32_t)freq
);
452 static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState
*dev
)
456 freq
= imx6ul_ccm_get_periph_sel_clk(dev
)
457 / (1 + FIELD_EX32(dev
->ccm
[CCM_CBCDR
], CBCDR
, AHB_PODF
));
459 trace_ccm_freq((uint32_t)freq
);
464 static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState
*dev
)
468 freq
= imx6ul_ccm_get_ahb_clk(dev
)
469 / (1 + FIELD_EX32(dev
->ccm
[CCM_CBCDR
], CBCDR
, IPG_PODF
));
471 trace_ccm_freq((uint32_t)freq
);
476 static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState
*dev
)
480 switch (FIELD_EX32(dev
->ccm
[CCM_CSCMR1
], CSCMR1
, PERCLK_CLK_SEL
)) {
482 freq
= imx6ul_ccm_get_ipg_clk(dev
);
485 freq
= imx6ul_analog_get_osc_clk(dev
);
488 g_assert_not_reached();
491 trace_ccm_freq((uint32_t)freq
);
496 static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState
*dev
)
500 freq
= imx6ul_ccm_get_per_sel_clk(dev
)
501 / (1 + FIELD_EX32(dev
->ccm
[CCM_CSCMR1
], CSCMR1
, PERCLK_PODF
));
503 trace_ccm_freq((uint32_t)freq
);
508 static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState
*dev
, IMXClk clock
)
511 IMX6ULCCMState
*s
= IMX6UL_CCM(dev
);
517 freq
= imx6ul_ccm_get_ipg_clk(s
);
520 freq
= imx6ul_ccm_get_per_clk(s
);
526 qemu_log_mask(LOG_GUEST_ERROR
, "[%s]%s: unsupported clock %d\n",
527 TYPE_IMX6UL_CCM
, __func__
, clock
);
531 trace_ccm_clock_freq(clock
, freq
);
536 static void imx6ul_ccm_reset(DeviceState
*dev
)
538 IMX6ULCCMState
*s
= IMX6UL_CCM(dev
);
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;
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;
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;
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;
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
;
619 s
->analog
[TEMPMON_TEMPSENSE0
] = 0x00000001;
620 s
->analog
[TEMPMON_TEMPSENSE1
] = 0x00000001;
621 s
->analog
[TEMPMON_TEMPSENSE2
] = 0x00000000;
624 static uint64_t imx6ul_ccm_read(void *opaque
, hwaddr offset
, unsigned size
)
627 uint32_t index
= offset
>> 2;
628 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
630 assert(index
< CCM_MAX
);
632 value
= s
->ccm
[index
];
634 trace_ccm_read_reg(imx6ul_ccm_reg_name(index
), (uint32_t)value
);
636 return (uint64_t)value
;
639 static void imx6ul_ccm_write(void *opaque
, hwaddr offset
, uint64_t value
,
642 uint32_t index
= offset
>> 2;
643 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
645 assert(index
< CCM_MAX
);
647 trace_ccm_write_reg(imx6ul_ccm_reg_name(index
), (uint32_t)value
);
649 s
->ccm
[index
] = (s
->ccm
[index
] & ccm_mask
[index
]) |
650 ((uint32_t)value
& ~ccm_mask
[index
]);
653 static uint64_t imx6ul_analog_read(void *opaque
, hwaddr offset
, unsigned size
)
656 uint32_t index
= offset
>> 2;
657 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
659 assert(index
< CCM_ANALOG_MAX
);
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
:
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
:
684 * All REG_NAME_SET register access are in fact targeting
685 * the REG_NAME register.
687 value
= s
->analog
[index
- 1];
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
:
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
:
711 * All REG_NAME_CLR register access are in fact targeting
712 * the REG_NAME register.
714 value
= s
->analog
[index
- 2];
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
:
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
:
738 * All REG_NAME_TOG register access are in fact targeting
739 * the REG_NAME register.
741 value
= s
->analog
[index
- 3];
744 value
= s
->analog
[index
];
748 trace_ccm_read_reg(imx6ul_analog_reg_name(index
), (uint32_t)value
);
750 return (uint64_t)value
;
753 static void imx6ul_analog_write(void *opaque
, hwaddr offset
, uint64_t value
,
756 uint32_t index
= offset
>> 2;
757 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
759 assert(index
< CCM_ANALOG_MAX
);
761 trace_ccm_write_reg(imx6ul_analog_reg_name(index
), (uint32_t)value
);
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
:
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
:
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.
787 s
->analog
[index
- 1] |= (value
& ~analog_mask
[index
- 1]);
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
:
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
:
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.
812 s
->analog
[index
- 2] &= ~(value
& ~analog_mask
[index
- 2]);
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
:
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
:
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.
837 s
->analog
[index
- 3] ^= (value
& ~analog_mask
[index
- 3]);
840 s
->analog
[index
] = (s
->analog
[index
] & analog_mask
[index
]) |
841 (value
& ~analog_mask
[index
]);
846 static const struct MemoryRegionOps imx6ul_ccm_ops
= {
847 .read
= imx6ul_ccm_read
,
848 .write
= imx6ul_ccm_write
,
849 .endianness
= DEVICE_NATIVE_ENDIAN
,
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.
857 .min_access_size
= 4,
858 .max_access_size
= 4,
863 static const struct MemoryRegionOps imx6ul_analog_ops
= {
864 .read
= imx6ul_analog_read
,
865 .write
= imx6ul_analog_write
,
866 .endianness
= DEVICE_NATIVE_ENDIAN
,
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.
874 .min_access_size
= 4,
875 .max_access_size
= 4,
880 static void imx6ul_ccm_init(Object
*obj
)
882 DeviceState
*dev
= DEVICE(obj
);
883 SysBusDevice
*sd
= SYS_BUS_DEVICE(obj
);
884 IMX6ULCCMState
*s
= IMX6UL_CCM(obj
);
886 /* initialize a container for the all memory range */
887 memory_region_init(&s
->container
, OBJECT(dev
), TYPE_IMX6UL_CCM
, 0x8000);
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));
893 /* Add the CCM as a subregion at offset 0 */
894 memory_region_add_subregion(&s
->container
, 0, &s
->ioccm
);
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));
901 /* Add the ANALOG as a subregion at offset 0x4000 */
902 memory_region_add_subregion(&s
->container
, 0x4000, &s
->ioanalog
);
904 sysbus_init_mmio(sd
, &s
->container
);
907 static void imx6ul_ccm_class_init(ObjectClass
*klass
, void *data
)
909 DeviceClass
*dc
= DEVICE_CLASS(klass
);
910 IMXCCMClass
*ccm
= IMX_CCM_CLASS(klass
);
912 dc
->reset
= imx6ul_ccm_reset
;
913 dc
->vmsd
= &vmstate_imx6ul_ccm
;
914 dc
->desc
= "i.MX6UL Clock Control Module";
916 ccm
->get_clock_frequency
= imx6ul_ccm_get_clock_frequency
;
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
,
927 static void imx6ul_ccm_register_types(void)
929 type_register_static(&imx6ul_ccm_info
);
932 type_init(imx6ul_ccm_register_types
)