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 */
21 #define DPRINTF(fmt, args...) \
22 do { printf("%s: " fmt , TYPE_IMX_CCM, ##args); } while (0)
24 #define DPRINTF(fmt, args...) do {} while (0)
27 static int imx_ccm_post_load(void *opaque
, int version_id
);
29 static const VMStateDescription vmstate_imx_ccm
= {
32 .minimum_version_id
= 1,
33 .fields
= (VMStateField
[]) {
34 VMSTATE_UINT32(ccmr
, IMXCCMState
),
35 VMSTATE_UINT32(pdr0
, IMXCCMState
),
36 VMSTATE_UINT32(pdr1
, IMXCCMState
),
37 VMSTATE_UINT32(mpctl
, IMXCCMState
),
38 VMSTATE_UINT32(spctl
, IMXCCMState
),
39 VMSTATE_UINT32_ARRAY(cgr
, IMXCCMState
, 3),
40 VMSTATE_UINT32(pmcr0
, IMXCCMState
),
41 VMSTATE_UINT32(pmcr1
, IMXCCMState
),
42 VMSTATE_UINT32(pll_refclk_freq
, IMXCCMState
),
45 .post_load
= imx_ccm_post_load
,
48 uint32_t imx_clock_frequency(DeviceState
*dev
, IMXClk clock
)
50 IMXCCMState
*s
= IMX_CCM(dev
);
56 return s
->mcu_clk_freq
;
58 return s
->hsp_clk_freq
;
60 return s
->ipg_clk_freq
;
68 * Calculate PLL output frequency
70 static uint32_t calc_pll(uint32_t pllreg
, uint32_t base_freq
)
72 int32_t mfn
= MFN(pllreg
); /* Numerator */
73 uint32_t mfi
= MFI(pllreg
); /* Integer part */
74 uint32_t mfd
= 1 + MFD(pllreg
); /* Denominator */
75 uint32_t pd
= 1 + PD(pllreg
); /* Pre-divider */
80 /* mfn is 10-bit signed twos-complement */
84 return ((2 * (base_freq
>> 10) * (mfi
* mfd
+ mfn
)) /
88 static void update_clocks(IMXCCMState
*s
)
91 * If we ever emulate more clocks, this should switch to a data-driven
95 if ((s
->ccmr
& CCMR_PRCS
) == 2) {
96 s
->pll_refclk_freq
= CKIL_FREQ
* 1024;
98 s
->pll_refclk_freq
= CKIH_FREQ
;
101 /* ipg_clk_arm aka MCU clock */
102 if ((s
->ccmr
& CCMR_MDS
) || !(s
->ccmr
& CCMR_MPE
)) {
103 s
->mcu_clk_freq
= s
->pll_refclk_freq
;
105 s
->mcu_clk_freq
= calc_pll(s
->mpctl
, s
->pll_refclk_freq
);
108 /* High-speed clock */
109 s
->hsp_clk_freq
= s
->mcu_clk_freq
/ (1 + EXTRACT(s
->pdr0
, HSP
));
110 s
->ipg_clk_freq
= s
->hsp_clk_freq
/ (1 + EXTRACT(s
->pdr0
, IPG
));
112 DPRINTF("%s: mcu %uMHz, HSP %uMHz, IPG %uHz\n", __func__
,
113 s
->mcu_clk_freq
/ 1000000,
114 s
->hsp_clk_freq
/ 1000000,
118 static void imx_ccm_reset(DeviceState
*dev
)
120 IMXCCMState
*s
= IMX_CCM(dev
);
122 s
->ccmr
= 0x074b0b7b;
123 s
->pdr0
= 0xff870b48;
124 s
->pdr1
= 0x49fcfe7f;
125 s
->mpctl
= PLL_PD(1) | PLL_MFD(0) | PLL_MFI(6) | PLL_MFN(0);
126 s
->cgr
[0] = s
->cgr
[1] = s
->cgr
[2] = 0xffffffff;
127 s
->spctl
= PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1);
128 s
->pmcr0
= 0x80209828;
133 static uint64_t imx_ccm_read(void *opaque
, hwaddr offset
,
136 IMXCCMState
*s
= (IMXCCMState
*)opaque
;
138 DPRINTF("%s(offset=%x)", __func__
, offset
>> 2);
139 switch (offset
>> 2) {
141 DPRINTF(" ccmr = 0x%x\n", s
->ccmr
);
144 DPRINTF(" pdr0 = 0x%x\n", s
->pdr0
);
147 DPRINTF(" pdr1 = 0x%x\n", s
->pdr1
);
150 DPRINTF(" mpctl = 0x%x\n", s
->mpctl
);
153 DPRINTF(" spctl = 0x%x\n", s
->spctl
);
156 DPRINTF(" cgr0 = 0x%x\n", s
->cgr
[0]);
159 DPRINTF(" cgr1 = 0x%x\n", s
->cgr
[1]);
162 DPRINTF(" cgr2 = 0x%x\n", s
->cgr
[2]);
167 DPRINTF(" pcmr0 = 0x%x\n", s
->pmcr0
);
170 DPRINTF(" return 0\n");
174 static void imx_ccm_write(void *opaque
, hwaddr offset
,
175 uint64_t value
, unsigned size
)
177 IMXCCMState
*s
= (IMXCCMState
*)opaque
;
179 DPRINTF("%s(offset=%x, value = %x)\n", __func__
,
180 offset
>> 2, (unsigned int)value
);
181 switch (offset
>> 2) {
183 s
->ccmr
= CCMR_FPMF
| (value
& 0x3b6fdfff);
186 s
->pdr0
= value
& 0xff9f3fff;
192 s
->mpctl
= value
& 0xbfff3fff;
195 s
->spctl
= value
& 0xbfff3fff;
213 static const struct MemoryRegionOps imx_ccm_ops
= {
214 .read
= imx_ccm_read
,
215 .write
= imx_ccm_write
,
216 .endianness
= DEVICE_NATIVE_ENDIAN
,
219 static int imx_ccm_init(SysBusDevice
*dev
)
221 IMXCCMState
*s
= IMX_CCM(dev
);
223 memory_region_init_io(&s
->iomem
, OBJECT(dev
), &imx_ccm_ops
, s
,
224 TYPE_IMX_CCM
, 0x1000);
225 sysbus_init_mmio(dev
, &s
->iomem
);
230 static int imx_ccm_post_load(void *opaque
, int version_id
)
232 IMXCCMState
*s
= (IMXCCMState
*)opaque
;
238 static void imx_ccm_class_init(ObjectClass
*klass
, void *data
)
240 DeviceClass
*dc
= DEVICE_CLASS(klass
);
241 SysBusDeviceClass
*sbc
= SYS_BUS_DEVICE_CLASS(klass
);
243 sbc
->init
= imx_ccm_init
;
244 dc
->reset
= imx_ccm_reset
;
245 dc
->vmsd
= &vmstate_imx_ccm
;
246 dc
->desc
= "i.MX Clock Control Module";
249 static const TypeInfo imx_ccm_info
= {
250 .name
= TYPE_IMX_CCM
,
251 .parent
= TYPE_SYS_BUS_DEVICE
,
252 .instance_size
= sizeof(IMXCCMState
),
253 .class_init
= imx_ccm_class_init
,
256 static void imx_ccm_register_types(void)
258 type_register_static(&imx_ccm_info
);
261 type_init(imx_ccm_register_types
)