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 sprintf(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 sprintf(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
= (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
);
529 freq
= CKIH_FREQ
/ 8;
532 qemu_log_mask(LOG_GUEST_ERROR
, "[%s]%s: unsupported clock %d\n",
533 TYPE_IMX6UL_CCM
, __func__
, clock
);
537 trace_ccm_clock_freq(clock
, freq
);
542 static void imx6ul_ccm_reset(DeviceState
*dev
)
544 IMX6ULCCMState
*s
= IMX6UL_CCM(dev
);
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;
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;
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;
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;
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
;
625 s
->analog
[TEMPMON_TEMPSENSE0
] = 0x00000001;
626 s
->analog
[TEMPMON_TEMPSENSE1
] = 0x00000001;
627 s
->analog
[TEMPMON_TEMPSENSE2
] = 0x00000000;
630 static uint64_t imx6ul_ccm_read(void *opaque
, hwaddr offset
, unsigned size
)
633 uint32_t index
= offset
>> 2;
634 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
636 assert(index
< CCM_MAX
);
638 value
= s
->ccm
[index
];
640 trace_ccm_read_reg(imx6ul_ccm_reg_name(index
), (uint32_t)value
);
642 return (uint64_t)value
;
645 static void imx6ul_ccm_write(void *opaque
, hwaddr offset
, uint64_t value
,
648 uint32_t index
= offset
>> 2;
649 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
651 assert(index
< CCM_MAX
);
653 trace_ccm_write_reg(imx6ul_ccm_reg_name(index
), (uint32_t)value
);
655 s
->ccm
[index
] = (s
->ccm
[index
] & ccm_mask
[index
]) |
656 ((uint32_t)value
& ~ccm_mask
[index
]);
659 static uint64_t imx6ul_analog_read(void *opaque
, hwaddr offset
, unsigned size
)
662 uint32_t index
= offset
>> 2;
663 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
665 assert(index
< CCM_ANALOG_MAX
);
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
:
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
:
690 * All REG_NAME_SET register access are in fact targeting
691 * the REG_NAME register.
693 value
= s
->analog
[index
- 1];
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
:
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
:
717 * All REG_NAME_CLR register access are in fact targeting
718 * the REG_NAME register.
720 value
= s
->analog
[index
- 2];
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
:
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
:
744 * All REG_NAME_TOG register access are in fact targeting
745 * the REG_NAME register.
747 value
= s
->analog
[index
- 3];
750 value
= s
->analog
[index
];
754 trace_ccm_read_reg(imx6ul_analog_reg_name(index
), (uint32_t)value
);
756 return (uint64_t)value
;
759 static void imx6ul_analog_write(void *opaque
, hwaddr offset
, uint64_t value
,
762 uint32_t index
= offset
>> 2;
763 IMX6ULCCMState
*s
= (IMX6ULCCMState
*)opaque
;
765 assert(index
< CCM_ANALOG_MAX
);
767 trace_ccm_write_reg(imx6ul_analog_reg_name(index
), (uint32_t)value
);
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
:
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
:
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.
793 s
->analog
[index
- 1] |= (value
& ~analog_mask
[index
- 1]);
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
:
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
:
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.
818 s
->analog
[index
- 2] &= ~(value
& ~analog_mask
[index
- 2]);
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
:
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
:
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.
843 s
->analog
[index
- 3] ^= (value
& ~analog_mask
[index
- 3]);
846 s
->analog
[index
] = (s
->analog
[index
] & analog_mask
[index
]) |
847 (value
& ~analog_mask
[index
]);
852 static const struct MemoryRegionOps imx6ul_ccm_ops
= {
853 .read
= imx6ul_ccm_read
,
854 .write
= imx6ul_ccm_write
,
855 .endianness
= DEVICE_NATIVE_ENDIAN
,
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.
863 .min_access_size
= 4,
864 .max_access_size
= 4,
869 static const struct MemoryRegionOps imx6ul_analog_ops
= {
870 .read
= imx6ul_analog_read
,
871 .write
= imx6ul_analog_write
,
872 .endianness
= DEVICE_NATIVE_ENDIAN
,
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.
880 .min_access_size
= 4,
881 .max_access_size
= 4,
886 static void imx6ul_ccm_init(Object
*obj
)
888 DeviceState
*dev
= DEVICE(obj
);
889 SysBusDevice
*sd
= SYS_BUS_DEVICE(obj
);
890 IMX6ULCCMState
*s
= IMX6UL_CCM(obj
);
892 /* initialize a container for the all memory range */
893 memory_region_init(&s
->container
, OBJECT(dev
), TYPE_IMX6UL_CCM
, 0x8000);
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));
899 /* Add the CCM as a subregion at offset 0 */
900 memory_region_add_subregion(&s
->container
, 0, &s
->ioccm
);
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));
907 /* Add the ANALOG as a subregion at offset 0x4000 */
908 memory_region_add_subregion(&s
->container
, 0x4000, &s
->ioanalog
);
910 sysbus_init_mmio(sd
, &s
->container
);
913 static void imx6ul_ccm_class_init(ObjectClass
*klass
, void *data
)
915 DeviceClass
*dc
= DEVICE_CLASS(klass
);
916 IMXCCMClass
*ccm
= IMX_CCM_CLASS(klass
);
918 dc
->reset
= imx6ul_ccm_reset
;
919 dc
->vmsd
= &vmstate_imx6ul_ccm
;
920 dc
->desc
= "i.MX6UL Clock Control Module";
922 ccm
->get_clock_frequency
= imx6ul_ccm_get_clock_frequency
;
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
,
933 static void imx6ul_ccm_register_types(void)
935 type_register_static(&imx6ul_ccm_info
);
938 type_init(imx6ul_ccm_register_types
)