2 * IMX31 Clock Control Module
4 * Copyright (C) 2012 NICTA
5 * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
10 * To get the timer frequencies right, we need to emulate at least part of
14 #include "hw/misc/imx_ccm.h"
16 #define CKIH_FREQ 26000000 /* 26MHz crystal input */
17 #define CKIL_FREQ 32768 /* nominal 32khz clock */
20 #define DEBUG_IMX_CCM 0
23 #define DPRINTF(fmt, args...) \
25 if (DEBUG_IMX_CCM) { \
26 fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_CCM, \
31 static int imx_ccm_post_load(void *opaque
, int version_id
);
33 static const VMStateDescription vmstate_imx_ccm
= {
36 .minimum_version_id
= 1,
37 .fields
= (VMStateField
[]) {
38 VMSTATE_UINT32(ccmr
, IMXCCMState
),
39 VMSTATE_UINT32(pdr0
, IMXCCMState
),
40 VMSTATE_UINT32(pdr1
, IMXCCMState
),
41 VMSTATE_UINT32(mpctl
, IMXCCMState
),
42 VMSTATE_UINT32(spctl
, IMXCCMState
),
43 VMSTATE_UINT32_ARRAY(cgr
, IMXCCMState
, 3),
44 VMSTATE_UINT32(pmcr0
, IMXCCMState
),
45 VMSTATE_UINT32(pmcr1
, IMXCCMState
),
46 VMSTATE_UINT32(pll_refclk_freq
, IMXCCMState
),
49 .post_load
= imx_ccm_post_load
,
52 uint32_t imx_clock_frequency(DeviceState
*dev
, IMXClk clock
)
54 IMXCCMState
*s
= IMX_CCM(dev
);
60 return s
->mcu_clk_freq
;
62 return s
->hsp_clk_freq
;
64 return s
->ipg_clk_freq
;
72 * Calculate PLL output frequency
74 static uint32_t calc_pll(uint32_t pllreg
, uint32_t base_freq
)
76 int32_t mfn
= MFN(pllreg
); /* Numerator */
77 uint32_t mfi
= MFI(pllreg
); /* Integer part */
78 uint32_t mfd
= 1 + MFD(pllreg
); /* Denominator */
79 uint32_t pd
= 1 + PD(pllreg
); /* Pre-divider */
84 /* mfn is 10-bit signed twos-complement */
88 return ((2 * (base_freq
>> 10) * (mfi
* mfd
+ mfn
)) /
92 static void update_clocks(IMXCCMState
*s
)
95 * If we ever emulate more clocks, this should switch to a data-driven
99 if ((s
->ccmr
& CCMR_PRCS
) == 2) {
100 s
->pll_refclk_freq
= CKIL_FREQ
* 1024;
102 s
->pll_refclk_freq
= CKIH_FREQ
;
105 /* ipg_clk_arm aka MCU clock */
106 if ((s
->ccmr
& CCMR_MDS
) || !(s
->ccmr
& CCMR_MPE
)) {
107 s
->mcu_clk_freq
= s
->pll_refclk_freq
;
109 s
->mcu_clk_freq
= calc_pll(s
->mpctl
, s
->pll_refclk_freq
);
112 /* High-speed clock */
113 s
->hsp_clk_freq
= s
->mcu_clk_freq
/ (1 + EXTRACT(s
->pdr0
, HSP
));
114 s
->ipg_clk_freq
= s
->hsp_clk_freq
/ (1 + EXTRACT(s
->pdr0
, IPG
));
116 DPRINTF("mcu %uMHz, HSP %uMHz, IPG %uHz\n",
117 s
->mcu_clk_freq
/ 1000000,
118 s
->hsp_clk_freq
/ 1000000,
122 static void imx_ccm_reset(DeviceState
*dev
)
124 IMXCCMState
*s
= IMX_CCM(dev
);
126 s
->ccmr
= 0x074b0b7b;
127 s
->pdr0
= 0xff870b48;
128 s
->pdr1
= 0x49fcfe7f;
129 s
->mpctl
= PLL_PD(1) | PLL_MFD(0) | PLL_MFI(6) | PLL_MFN(0);
130 s
->cgr
[0] = s
->cgr
[1] = s
->cgr
[2] = 0xffffffff;
131 s
->spctl
= PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1);
132 s
->pmcr0
= 0x80209828;
137 static uint64_t imx_ccm_read(void *opaque
, hwaddr offset
,
140 IMXCCMState
*s
= (IMXCCMState
*)opaque
;
142 DPRINTF("(offset=0x%" HWADDR_PRIx
")\n", offset
);
144 switch (offset
>> 2) {
146 DPRINTF(" ccmr = 0x%x\n", s
->ccmr
);
149 DPRINTF(" pdr0 = 0x%x\n", s
->pdr0
);
152 DPRINTF(" pdr1 = 0x%x\n", s
->pdr1
);
155 DPRINTF(" mpctl = 0x%x\n", s
->mpctl
);
158 DPRINTF(" spctl = 0x%x\n", s
->spctl
);
161 DPRINTF(" cgr0 = 0x%x\n", s
->cgr
[0]);
164 DPRINTF(" cgr1 = 0x%x\n", s
->cgr
[1]);
167 DPRINTF(" cgr2 = 0x%x\n", s
->cgr
[2]);
172 DPRINTF(" pcmr0 = 0x%x\n", s
->pmcr0
);
175 qemu_log_mask(LOG_GUEST_ERROR
, "[%s]%s: Bad register at offset 0x%"
176 HWADDR_PRIx
"\n", TYPE_IMX_CCM
, __func__
, offset
);
181 static void imx_ccm_write(void *opaque
, hwaddr offset
,
182 uint64_t value
, unsigned size
)
184 IMXCCMState
*s
= (IMXCCMState
*)opaque
;
186 DPRINTF("(offset=0x%" HWADDR_PRIx
", value = 0x%x)\n",
187 offset
, (unsigned int)value
);
189 switch (offset
>> 2) {
191 s
->ccmr
= CCMR_FPMF
| (value
& 0x3b6fdfff);
194 s
->pdr0
= value
& 0xff9f3fff;
200 s
->mpctl
= value
& 0xbfff3fff;
203 s
->spctl
= value
& 0xbfff3fff;
216 qemu_log_mask(LOG_GUEST_ERROR
, "[%s]%s: Bad register at offset 0x%"
217 HWADDR_PRIx
"\n", TYPE_IMX_CCM
, __func__
, offset
);
223 static const struct MemoryRegionOps imx_ccm_ops
= {
224 .read
= imx_ccm_read
,
225 .write
= imx_ccm_write
,
226 .endianness
= DEVICE_NATIVE_ENDIAN
,
229 static int imx_ccm_init(SysBusDevice
*dev
)
231 IMXCCMState
*s
= IMX_CCM(dev
);
233 memory_region_init_io(&s
->iomem
, OBJECT(dev
), &imx_ccm_ops
, s
,
234 TYPE_IMX_CCM
, 0x1000);
235 sysbus_init_mmio(dev
, &s
->iomem
);
240 static int imx_ccm_post_load(void *opaque
, int version_id
)
242 IMXCCMState
*s
= (IMXCCMState
*)opaque
;
248 static void imx_ccm_class_init(ObjectClass
*klass
, void *data
)
250 DeviceClass
*dc
= DEVICE_CLASS(klass
);
251 SysBusDeviceClass
*sbc
= SYS_BUS_DEVICE_CLASS(klass
);
253 sbc
->init
= imx_ccm_init
;
254 dc
->reset
= imx_ccm_reset
;
255 dc
->vmsd
= &vmstate_imx_ccm
;
256 dc
->desc
= "i.MX Clock Control Module";
259 static const TypeInfo imx_ccm_info
= {
260 .name
= TYPE_IMX_CCM
,
261 .parent
= TYPE_SYS_BUS_DEVICE
,
262 .instance_size
= sizeof(IMXCCMState
),
263 .class_init
= imx_ccm_class_init
,
266 static void imx_ccm_register_types(void)
268 type_register_static(&imx_ccm_info
);
271 type_init(imx_ccm_register_types
)