i.MX: Fix i.MX31 default/reset configuration
[qemu/ar7.git] / hw / misc / imx_ccm.c
blob500dda5024a552c6d399b3f51493ad5d0a95d38f
1 /*
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
11 * the CCM.
14 #include "hw/misc/imx_ccm.h"
16 #define CKIH_FREQ 26000000 /* 26MHz crystal input */
17 #define CKIL_FREQ 32768 /* nominal 32khz clock */
19 #ifndef DEBUG_IMX_CCM
20 #define DEBUG_IMX_CCM 0
21 #endif
23 #define DPRINTF(fmt, args...) \
24 do { \
25 if (DEBUG_IMX_CCM) { \
26 fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_CCM, \
27 __func__, ##args); \
28 } \
29 } while (0)
31 static int imx_ccm_post_load(void *opaque, int version_id);
33 static const VMStateDescription vmstate_imx_ccm = {
34 .name = TYPE_IMX_CCM,
35 .version_id = 1,
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),
47 VMSTATE_END_OF_LIST()
49 .post_load = imx_ccm_post_load,
52 uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
54 IMXCCMState *s = IMX_CCM(dev);
56 switch (clock) {
57 case NOCLK:
58 return 0;
59 case MCU:
60 return s->mcu_clk_freq;
61 case HSP:
62 return s->hsp_clk_freq;
63 case IPG:
64 return s->ipg_clk_freq;
65 case CLK_32k:
66 return CKIL_FREQ;
68 return 0;
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 */
81 if (mfi < 5) {
82 mfi = 5;
84 /* mfn is 10-bit signed twos-complement */
85 mfn <<= 32 - 10;
86 mfn >>= 32 - 10;
88 return ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
89 (mfd * pd)) << 10;
92 static void update_clocks(IMXCCMState *s)
95 * If we ever emulate more clocks, this should switch to a data-driven
96 * approach
99 if ((s->ccmr & CCMR_PRCS) == 2) {
100 s->pll_refclk_freq = CKIL_FREQ * 1024;
101 } else {
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;
108 } else {
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,
119 s->ipg_clk_freq);
122 static void imx_ccm_reset(DeviceState *dev)
124 IMXCCMState *s = IMX_CCM(dev);
126 s->ccmr = 0x074b0b7d;
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;
134 update_clocks(s);
137 static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
138 unsigned size)
140 IMXCCMState *s = (IMXCCMState *)opaque;
142 DPRINTF("(offset=0x%" HWADDR_PRIx ")\n", offset);
144 switch (offset >> 2) {
145 case 0: /* CCMR */
146 DPRINTF(" ccmr = 0x%x\n", s->ccmr);
147 return s->ccmr;
148 case 1:
149 DPRINTF(" pdr0 = 0x%x\n", s->pdr0);
150 return s->pdr0;
151 case 2:
152 DPRINTF(" pdr1 = 0x%x\n", s->pdr1);
153 return s->pdr1;
154 case 4:
155 DPRINTF(" mpctl = 0x%x\n", s->mpctl);
156 return s->mpctl;
157 case 6:
158 DPRINTF(" spctl = 0x%x\n", s->spctl);
159 return s->spctl;
160 case 8:
161 DPRINTF(" cgr0 = 0x%x\n", s->cgr[0]);
162 return s->cgr[0];
163 case 9:
164 DPRINTF(" cgr1 = 0x%x\n", s->cgr[1]);
165 return s->cgr[1];
166 case 10:
167 DPRINTF(" cgr2 = 0x%x\n", s->cgr[2]);
168 return s->cgr[2];
169 case 18: /* LTR1 */
170 return 0x00004040;
171 case 23:
172 DPRINTF(" pcmr0 = 0x%x\n", s->pmcr0);
173 return s->pmcr0;
174 default:
175 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
176 HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
177 return 0;
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) {
190 case 0:
191 s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
192 break;
193 case 1:
194 s->pdr0 = value & 0xff9f3fff;
195 break;
196 case 2:
197 s->pdr1 = value;
198 break;
199 case 4:
200 s->mpctl = value & 0xbfff3fff;
201 break;
202 case 6:
203 s->spctl = value & 0xbfff3fff;
204 break;
205 case 8:
206 s->cgr[0] = value;
207 return;
208 case 9:
209 s->cgr[1] = value;
210 return;
211 case 10:
212 s->cgr[2] = value;
213 return;
215 default:
216 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
217 HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
218 return;
220 update_clocks(s);
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);
237 return 0;
240 static int imx_ccm_post_load(void *opaque, int version_id)
242 IMXCCMState *s = (IMXCCMState *)opaque;
244 update_clocks(s);
245 return 0;
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)