]> git.proxmox.com Git - qemu.git/blob - hw/timer/imx_epit.c
aio / timers: Untangle include files
[qemu.git] / hw / timer / imx_epit.c
1 /*
2 * IMX EPIT Timer
3 *
4 * Copyright (c) 2008 OK Labs
5 * Copyright (c) 2011 NICTA Pty Ltd
6 * Originally written by Hans Jiang
7 * Updated by Peter Chubb
8 * Updated by Jean-Christophe Dubois
9 *
10 * This code is licensed under GPL version 2 or later. See
11 * the COPYING file in the top-level directory.
12 *
13 */
14
15 #include "hw/hw.h"
16 #include "qemu/bitops.h"
17 #include "qemu/timer.h"
18 #include "hw/ptimer.h"
19 #include "hw/sysbus.h"
20 #include "hw/arm/imx.h"
21 #include "qemu/main-loop.h"
22
23 #define TYPE_IMX_EPIT "imx.epit"
24
25 #define DEBUG_TIMER 0
26 #if DEBUG_TIMER
27
28 static char const *imx_epit_reg_name(uint32_t reg)
29 {
30 switch (reg) {
31 case 0:
32 return "CR";
33 case 1:
34 return "SR";
35 case 2:
36 return "LR";
37 case 3:
38 return "CMP";
39 case 4:
40 return "CNT";
41 default:
42 return "[?]";
43 }
44 }
45
46 # define DPRINTF(fmt, args...) \
47 do { fprintf(stderr, "%s: " fmt , __func__, ##args); } while (0)
48 #else
49 # define DPRINTF(fmt, args...) do {} while (0)
50 #endif
51
52 /*
53 * Define to 1 for messages about attempts to
54 * access unimplemented registers or similar.
55 */
56 #define DEBUG_IMPLEMENTATION 1
57 #if DEBUG_IMPLEMENTATION
58 # define IPRINTF(fmt, args...) \
59 do { fprintf(stderr, "%s: " fmt, __func__, ##args); } while (0)
60 #else
61 # define IPRINTF(fmt, args...) do {} while (0)
62 #endif
63
64 #define IMX_EPIT(obj) \
65 OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
66
67 /*
68 * EPIT: Enhanced periodic interrupt timer
69 */
70
71 #define CR_EN (1 << 0)
72 #define CR_ENMOD (1 << 1)
73 #define CR_OCIEN (1 << 2)
74 #define CR_RLD (1 << 3)
75 #define CR_PRESCALE_SHIFT (4)
76 #define CR_PRESCALE_MASK (0xfff)
77 #define CR_SWR (1 << 16)
78 #define CR_IOVW (1 << 17)
79 #define CR_DBGEN (1 << 18)
80 #define CR_WAITEN (1 << 19)
81 #define CR_DOZEN (1 << 20)
82 #define CR_STOPEN (1 << 21)
83 #define CR_CLKSRC_SHIFT (24)
84 #define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT)
85
86 #define TIMER_MAX 0XFFFFFFFFUL
87
88 /*
89 * Exact clock frequencies vary from board to board.
90 * These are typical.
91 */
92 static const IMXClk imx_epit_clocks[] = {
93 0, /* 00 disabled */
94 IPG, /* 01 ipg_clk, ~532MHz */
95 IPG, /* 10 ipg_clk_highfreq */
96 CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */
97 };
98
99 typedef struct {
100 SysBusDevice busdev;
101 ptimer_state *timer_reload;
102 ptimer_state *timer_cmp;
103 MemoryRegion iomem;
104 DeviceState *ccm;
105
106 uint32_t cr;
107 uint32_t sr;
108 uint32_t lr;
109 uint32_t cmp;
110 uint32_t cnt;
111
112 uint32_t freq;
113 qemu_irq irq;
114 } IMXEPITState;
115
116 /*
117 * Update interrupt status
118 */
119 static void imx_epit_update_int(IMXEPITState *s)
120 {
121 if (s->sr && (s->cr & CR_OCIEN) && (s->cr & CR_EN)) {
122 qemu_irq_raise(s->irq);
123 } else {
124 qemu_irq_lower(s->irq);
125 }
126 }
127
128 static void imx_epit_set_freq(IMXEPITState *s)
129 {
130 uint32_t clksrc;
131 uint32_t prescaler;
132 uint32_t freq;
133
134 clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2);
135 prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12);
136
137 freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler;
138
139 s->freq = freq;
140
141 DPRINTF("Setting ptimer frequency to %u\n", freq);
142
143 if (freq) {
144 ptimer_set_freq(s->timer_reload, freq);
145 ptimer_set_freq(s->timer_cmp, freq);
146 }
147 }
148
149 static void imx_epit_reset(DeviceState *dev)
150 {
151 IMXEPITState *s = IMX_EPIT(dev);
152
153 /*
154 * Soft reset doesn't touch some bits; hard reset clears them
155 */
156 s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
157 s->sr = 0;
158 s->lr = TIMER_MAX;
159 s->cmp = 0;
160 s->cnt = 0;
161 /* stop both timers */
162 ptimer_stop(s->timer_cmp);
163 ptimer_stop(s->timer_reload);
164 /* compute new frequency */
165 imx_epit_set_freq(s);
166 /* init both timers to TIMER_MAX */
167 ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1);
168 ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
169 if (s->freq && (s->cr & CR_EN)) {
170 /* if the timer is still enabled, restart it */
171 ptimer_run(s->timer_reload, 0);
172 }
173 }
174
175 static uint32_t imx_epit_update_count(IMXEPITState *s)
176 {
177 s->cnt = ptimer_get_count(s->timer_reload);
178
179 return s->cnt;
180 }
181
182 static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
183 {
184 IMXEPITState *s = IMX_EPIT(opaque);
185 uint32_t reg_value = 0;
186 uint32_t reg = offset >> 2;
187
188 switch (reg) {
189 case 0: /* Control Register */
190 reg_value = s->cr;
191 break;
192
193 case 1: /* Status Register */
194 reg_value = s->sr;
195 break;
196
197 case 2: /* LR - ticks*/
198 reg_value = s->lr;
199 break;
200
201 case 3: /* CMP */
202 reg_value = s->cmp;
203 break;
204
205 case 4: /* CNT */
206 imx_epit_update_count(s);
207 reg_value = s->cnt;
208 break;
209
210 default:
211 IPRINTF("Bad offset %x\n", reg);
212 break;
213 }
214
215 DPRINTF("(%s) = 0x%08x\n", imx_epit_reg_name(reg), reg_value);
216
217 return reg_value;
218 }
219
220 static void imx_epit_reload_compare_timer(IMXEPITState *s)
221 {
222 if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
223 /* if the compare feature is on and timers are running */
224 uint32_t tmp = imx_epit_update_count(s);
225 uint64_t next;
226 if (tmp > s->cmp) {
227 /* It'll fire in this round of the timer */
228 next = tmp - s->cmp;
229 } else { /* catch it next time around */
230 next = tmp - s->cmp + ((s->cr & CR_RLD) ? TIMER_MAX : s->lr);
231 }
232 ptimer_set_count(s->timer_cmp, next);
233 }
234 }
235
236 static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
237 unsigned size)
238 {
239 IMXEPITState *s = IMX_EPIT(opaque);
240 uint32_t reg = offset >> 2;
241 uint64_t oldcr;
242
243 DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value);
244
245 switch (reg) {
246 case 0: /* CR */
247
248 oldcr = s->cr;
249 s->cr = value & 0x03ffffff;
250 if (s->cr & CR_SWR) {
251 /* handle the reset */
252 imx_epit_reset(DEVICE(s));
253 } else {
254 imx_epit_set_freq(s);
255 }
256
257 if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
258 if (s->cr & CR_ENMOD) {
259 if (s->cr & CR_RLD) {
260 ptimer_set_limit(s->timer_reload, s->lr, 1);
261 ptimer_set_limit(s->timer_cmp, s->lr, 1);
262 } else {
263 ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
264 ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1);
265 }
266 }
267
268 imx_epit_reload_compare_timer(s);
269 ptimer_run(s->timer_reload, 0);
270 if (s->cr & CR_OCIEN) {
271 ptimer_run(s->timer_cmp, 0);
272 } else {
273 ptimer_stop(s->timer_cmp);
274 }
275 } else if (!(s->cr & CR_EN)) {
276 /* stop both timers */
277 ptimer_stop(s->timer_reload);
278 ptimer_stop(s->timer_cmp);
279 } else if (s->cr & CR_OCIEN) {
280 if (!(oldcr & CR_OCIEN)) {
281 imx_epit_reload_compare_timer(s);
282 ptimer_run(s->timer_cmp, 0);
283 }
284 } else {
285 ptimer_stop(s->timer_cmp);
286 }
287 break;
288
289 case 1: /* SR - ACK*/
290 /* writing 1 to OCIF clear the OCIF bit */
291 if (value & 0x01) {
292 s->sr = 0;
293 imx_epit_update_int(s);
294 }
295 break;
296
297 case 2: /* LR - set ticks */
298 s->lr = value;
299
300 if (s->cr & CR_RLD) {
301 /* Also set the limit if the LRD bit is set */
302 /* If IOVW bit is set then set the timer value */
303 ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW);
304 ptimer_set_limit(s->timer_cmp, s->lr, 0);
305 } else if (s->cr & CR_IOVW) {
306 /* If IOVW bit is set then set the timer value */
307 ptimer_set_count(s->timer_reload, s->lr);
308 }
309
310 imx_epit_reload_compare_timer(s);
311 break;
312
313 case 3: /* CMP */
314 s->cmp = value;
315
316 imx_epit_reload_compare_timer(s);
317
318 break;
319
320 default:
321 IPRINTF("Bad offset %x\n", reg);
322
323 break;
324 }
325 }
326 static void imx_epit_cmp(void *opaque)
327 {
328 IMXEPITState *s = IMX_EPIT(opaque);
329
330 DPRINTF("sr was %d\n", s->sr);
331
332 s->sr = 1;
333 imx_epit_update_int(s);
334 }
335
336 void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
337 {
338 IMXEPITState *pp;
339 DeviceState *dev;
340
341 dev = sysbus_create_simple(TYPE_IMX_EPIT, addr, irq);
342 pp = IMX_EPIT(dev);
343 pp->ccm = ccm;
344 }
345
346 static const MemoryRegionOps imx_epit_ops = {
347 .read = imx_epit_read,
348 .write = imx_epit_write,
349 .endianness = DEVICE_NATIVE_ENDIAN,
350 };
351
352 static const VMStateDescription vmstate_imx_timer_epit = {
353 .name = "imx.epit",
354 .version_id = 2,
355 .minimum_version_id = 2,
356 .minimum_version_id_old = 2,
357 .fields = (VMStateField[]) {
358 VMSTATE_UINT32(cr, IMXEPITState),
359 VMSTATE_UINT32(sr, IMXEPITState),
360 VMSTATE_UINT32(lr, IMXEPITState),
361 VMSTATE_UINT32(cmp, IMXEPITState),
362 VMSTATE_UINT32(cnt, IMXEPITState),
363 VMSTATE_UINT32(freq, IMXEPITState),
364 VMSTATE_PTIMER(timer_reload, IMXEPITState),
365 VMSTATE_PTIMER(timer_cmp, IMXEPITState),
366 VMSTATE_END_OF_LIST()
367 }
368 };
369
370 static void imx_epit_realize(DeviceState *dev, Error **errp)
371 {
372 IMXEPITState *s = IMX_EPIT(dev);
373 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
374 QEMUBH *bh;
375
376 DPRINTF("\n");
377
378 sysbus_init_irq(sbd, &s->irq);
379 memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT,
380 0x00001000);
381 sysbus_init_mmio(sbd, &s->iomem);
382
383 s->timer_reload = ptimer_init(NULL);
384
385 bh = qemu_bh_new(imx_epit_cmp, s);
386 s->timer_cmp = ptimer_init(bh);
387 }
388
389 static void imx_epit_class_init(ObjectClass *klass, void *data)
390 {
391 DeviceClass *dc = DEVICE_CLASS(klass);
392
393 dc->realize = imx_epit_realize;
394 dc->reset = imx_epit_reset;
395 dc->vmsd = &vmstate_imx_timer_epit;
396 dc->desc = "i.MX periodic timer";
397 }
398
399 static const TypeInfo imx_epit_info = {
400 .name = TYPE_IMX_EPIT,
401 .parent = TYPE_SYS_BUS_DEVICE,
402 .instance_size = sizeof(IMXEPITState),
403 .class_init = imx_epit_class_init,
404 };
405
406 static void imx_epit_register_types(void)
407 {
408 type_register_static(&imx_epit_info);
409 }
410
411 type_init(imx_epit_register_types)