rtl8139: remove muldiv64()
[qemu/kevin.git] / hw / misc / imx_ccm.c
blob2e19dbb1bbef26ac68beae4858c00bbd690ab11f
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 //#define DEBUG_CCM 1
20 #ifdef DEBUG_CCM
21 #define DPRINTF(fmt, args...) \
22 do { printf("%s: " fmt , TYPE_IMX_CCM, ##args); } while (0)
23 #else
24 #define DPRINTF(fmt, args...) do {} while (0)
25 #endif
27 static int imx_ccm_post_load(void *opaque, int version_id);
29 static const VMStateDescription vmstate_imx_ccm = {
30 .name = TYPE_IMX_CCM,
31 .version_id = 1,
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),
43 VMSTATE_END_OF_LIST()
45 .post_load = imx_ccm_post_load,
48 uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
50 IMXCCMState *s = IMX_CCM(dev);
52 switch (clock) {
53 case NOCLK:
54 return 0;
55 case MCU:
56 return s->mcu_clk_freq;
57 case HSP:
58 return s->hsp_clk_freq;
59 case IPG:
60 return s->ipg_clk_freq;
61 case CLK_32k:
62 return CKIL_FREQ;
64 return 0;
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 */
77 if (mfi < 5) {
78 mfi = 5;
80 /* mfn is 10-bit signed twos-complement */
81 mfn <<= 32 - 10;
82 mfn >>= 32 - 10;
84 return ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
85 (mfd * pd)) << 10;
88 static void update_clocks(IMXCCMState *s)
91 * If we ever emulate more clocks, this should switch to a data-driven
92 * approach
95 if ((s->ccmr & CCMR_PRCS) == 2) {
96 s->pll_refclk_freq = CKIL_FREQ * 1024;
97 } else {
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;
104 } else {
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,
115 s->ipg_clk_freq);
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;
130 update_clocks(s);
133 static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
134 unsigned size)
136 IMXCCMState *s = (IMXCCMState *)opaque;
138 DPRINTF("%s(offset=%x)", __func__, offset >> 2);
139 switch (offset >> 2) {
140 case 0: /* CCMR */
141 DPRINTF(" ccmr = 0x%x\n", s->ccmr);
142 return s->ccmr;
143 case 1:
144 DPRINTF(" pdr0 = 0x%x\n", s->pdr0);
145 return s->pdr0;
146 case 2:
147 DPRINTF(" pdr1 = 0x%x\n", s->pdr1);
148 return s->pdr1;
149 case 4:
150 DPRINTF(" mpctl = 0x%x\n", s->mpctl);
151 return s->mpctl;
152 case 6:
153 DPRINTF(" spctl = 0x%x\n", s->spctl);
154 return s->spctl;
155 case 8:
156 DPRINTF(" cgr0 = 0x%x\n", s->cgr[0]);
157 return s->cgr[0];
158 case 9:
159 DPRINTF(" cgr1 = 0x%x\n", s->cgr[1]);
160 return s->cgr[1];
161 case 10:
162 DPRINTF(" cgr2 = 0x%x\n", s->cgr[2]);
163 return s->cgr[2];
164 case 18: /* LTR1 */
165 return 0x00004040;
166 case 23:
167 DPRINTF(" pcmr0 = 0x%x\n", s->pmcr0);
168 return s->pmcr0;
170 DPRINTF(" return 0\n");
171 return 0;
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) {
182 case 0:
183 s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
184 break;
185 case 1:
186 s->pdr0 = value & 0xff9f3fff;
187 break;
188 case 2:
189 s->pdr1 = value;
190 break;
191 case 4:
192 s->mpctl = value & 0xbfff3fff;
193 break;
194 case 6:
195 s->spctl = value & 0xbfff3fff;
196 break;
197 case 8:
198 s->cgr[0] = value;
199 return;
200 case 9:
201 s->cgr[1] = value;
202 return;
203 case 10:
204 s->cgr[2] = value;
205 return;
207 default:
208 return;
210 update_clocks(s);
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);
227 return 0;
230 static int imx_ccm_post_load(void *opaque, int version_id)
232 IMXCCMState *s = (IMXCCMState *)opaque;
234 update_clocks(s);
235 return 0;
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)