]> git.proxmox.com Git - qemu.git/blame - hw/timer/imx_gpt.c
aio / timers: Untangle include files
[qemu.git] / hw / timer / imx_gpt.c
CommitLineData
78d1404d 1/*
a50c0d6f 2 * IMX GPT Timer
78d1404d
PC
3 *
4 * Copyright (c) 2008 OK Labs
5 * Copyright (c) 2011 NICTA Pty Ltd
aade7b91 6 * Originally written by Hans Jiang
78d1404d 7 * Updated by Peter Chubb
5ec694b5 8 * Updated by Jean-Christophe Dubois
78d1404d 9 *
aade7b91 10 * This code is licensed under GPL version 2 or later. See
78d1404d
PC
11 * the COPYING file in the top-level directory.
12 *
13 */
14
83c9f4ca 15#include "hw/hw.h"
a50c0d6f 16#include "qemu/bitops.h"
1de7afc9 17#include "qemu/timer.h"
83c9f4ca
PB
18#include "hw/ptimer.h"
19#include "hw/sysbus.h"
0d09e41a 20#include "hw/arm/imx.h"
6a1751b7 21#include "qemu/main-loop.h"
78d1404d 22
5ec694b5
JCD
23#define TYPE_IMX_GPT "imx.gpt"
24
25/*
26 * Define to 1 for debug messages
27 */
28#define DEBUG_TIMER 0
29#if DEBUG_TIMER
30
67110c3e 31static char const *imx_gpt_reg_name(uint32_t reg)
5ec694b5
JCD
32{
33 switch (reg) {
34 case 0:
35 return "CR";
36 case 1:
37 return "PR";
38 case 2:
39 return "SR";
40 case 3:
41 return "IR";
42 case 4:
43 return "OCR1";
44 case 5:
45 return "OCR2";
46 case 6:
47 return "OCR3";
48 case 7:
49 return "ICR1";
50 case 8:
51 return "ICR2";
52 case 9:
53 return "CNT";
54 default:
55 return "[?]";
56 }
57}
58
78d1404d 59# define DPRINTF(fmt, args...) \
5ec694b5 60 do { printf("%s: " fmt , __func__, ##args); } while (0)
78d1404d
PC
61#else
62# define DPRINTF(fmt, args...) do {} while (0)
63#endif
64
65/*
66 * Define to 1 for messages about attempts to
67 * access unimplemented registers or similar.
68 */
69#define DEBUG_IMPLEMENTATION 1
70#if DEBUG_IMPLEMENTATION
67110c3e 71# define IPRINTF(fmt, args...) \
5ec694b5 72 do { fprintf(stderr, "%s: " fmt, __func__, ##args); } while (0)
78d1404d
PC
73#else
74# define IPRINTF(fmt, args...) do {} while (0)
75#endif
76
67110c3e
JCD
77#define IMX_GPT(obj) \
78 OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT)
78d1404d
PC
79/*
80 * GPT : General purpose timer
81 *
82 * This timer counts up continuously while it is enabled, resetting itself
83 * to 0 when it reaches TIMER_MAX (in freerun mode) or when it
5ec694b5 84 * reaches the value of one of the ocrX (in periodic mode).
78d1404d
PC
85 */
86
78d1404d
PC
87#define TIMER_MAX 0XFFFFFFFFUL
88
89/* Control register. Not all of these bits have any effect (yet) */
90#define GPT_CR_EN (1 << 0) /* GPT Enable */
91#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */
92#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */
93#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */
94#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */
95#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */
96#define GPT_CR_CLKSRC_SHIFT (6)
97#define GPT_CR_CLKSRC_MASK (0x7)
98
99#define GPT_CR_FRR (1 << 9) /* Freerun or Restart */
100#define GPT_CR_SWR (1 << 15) /* Software Reset */
101#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */
102#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */
103#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */
104#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */
105#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */
106#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */
107#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */
108#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */
109
110#define GPT_SR_OF1 (1 << 0)
5ec694b5
JCD
111#define GPT_SR_OF2 (1 << 1)
112#define GPT_SR_OF3 (1 << 2)
78d1404d
PC
113#define GPT_SR_ROV (1 << 5)
114
115#define GPT_IR_OF1IE (1 << 0)
5ec694b5
JCD
116#define GPT_IR_OF2IE (1 << 1)
117#define GPT_IR_OF3IE (1 << 2)
78d1404d
PC
118#define GPT_IR_ROVIE (1 << 5)
119
120typedef struct {
121 SysBusDevice busdev;
122 ptimer_state *timer;
123 MemoryRegion iomem;
124 DeviceState *ccm;
125
126 uint32_t cr;
127 uint32_t pr;
128 uint32_t sr;
129 uint32_t ir;
130 uint32_t ocr1;
462566fc
JCD
131 uint32_t ocr2;
132 uint32_t ocr3;
133 uint32_t icr1;
134 uint32_t icr2;
78d1404d
PC
135 uint32_t cnt;
136
5ec694b5
JCD
137 uint32_t next_timeout;
138 uint32_t next_int;
139
140 uint32_t freq;
141
78d1404d 142 qemu_irq irq;
67110c3e 143} IMXGPTState;
78d1404d 144
67110c3e 145static const VMStateDescription vmstate_imx_timer_gpt = {
6783ecf1 146 .name = "imx.gpt",
5ec694b5
JCD
147 .version_id = 3,
148 .minimum_version_id = 3,
149 .minimum_version_id_old = 3,
78d1404d 150 .fields = (VMStateField[]) {
67110c3e
JCD
151 VMSTATE_UINT32(cr, IMXGPTState),
152 VMSTATE_UINT32(pr, IMXGPTState),
153 VMSTATE_UINT32(sr, IMXGPTState),
154 VMSTATE_UINT32(ir, IMXGPTState),
155 VMSTATE_UINT32(ocr1, IMXGPTState),
156 VMSTATE_UINT32(ocr2, IMXGPTState),
157 VMSTATE_UINT32(ocr3, IMXGPTState),
158 VMSTATE_UINT32(icr1, IMXGPTState),
159 VMSTATE_UINT32(icr2, IMXGPTState),
160 VMSTATE_UINT32(cnt, IMXGPTState),
161 VMSTATE_UINT32(next_timeout, IMXGPTState),
162 VMSTATE_UINT32(next_int, IMXGPTState),
163 VMSTATE_UINT32(freq, IMXGPTState),
164 VMSTATE_PTIMER(timer, IMXGPTState),
78d1404d
PC
165 VMSTATE_END_OF_LIST()
166 }
167};
168
67110c3e 169static const IMXClk imx_gpt_clocks[] = {
78d1404d
PC
170 NOCLK, /* 000 No clock source */
171 IPG, /* 001 ipg_clk, 532MHz*/
172 IPG, /* 010 ipg_clk_highfreq */
173 NOCLK, /* 011 not defined */
174 CLK_32k, /* 100 ipg_clk_32k */
175 NOCLK, /* 101 not defined */
176 NOCLK, /* 110 not defined */
177 NOCLK, /* 111 not defined */
178};
179
67110c3e 180static void imx_gpt_set_freq(IMXGPTState *s)
78d1404d 181{
5ec694b5 182 uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
67110c3e 183 uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc])
5ec694b5
JCD
184 / (1 + s->pr);
185 s->freq = freq;
78d1404d 186
5ec694b5 187 DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq);
a50c0d6f 188
78d1404d
PC
189 if (freq) {
190 ptimer_set_freq(s->timer, freq);
191 }
192}
193
67110c3e 194static void imx_gpt_update_int(IMXGPTState *s)
78d1404d 195{
5ec694b5
JCD
196 if ((s->sr & s->ir) && (s->cr & GPT_CR_EN)) {
197 qemu_irq_raise(s->irq);
198 } else {
199 qemu_irq_lower(s->irq);
200 }
78d1404d
PC
201}
202
67110c3e 203static uint32_t imx_gpt_update_count(IMXGPTState *s)
78d1404d 204{
5ec694b5
JCD
205 s->cnt = s->next_timeout - (uint32_t)ptimer_get_count(s->timer);
206
78d1404d
PC
207 return s->cnt;
208}
209
67110c3e 210static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg,
5ec694b5 211 uint32_t timeout)
78d1404d 212{
5ec694b5
JCD
213 if ((count < reg) && (timeout > reg)) {
214 timeout = reg;
215 }
216
217 return timeout;
218}
78d1404d 219
67110c3e 220static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event)
5ec694b5
JCD
221{
222 uint32_t timeout = TIMER_MAX;
223 uint32_t count = 0;
224 long long limit;
225
226 if (!(s->cr & GPT_CR_EN)) {
227 /* if not enabled just return */
78d1404d
PC
228 return;
229 }
230
5ec694b5
JCD
231 if (event) {
232 /* This is a timer event */
233
234 if ((s->cr & GPT_CR_FRR) && (s->next_timeout != TIMER_MAX)) {
235 /*
236 * if we are in free running mode and we have not reached
237 * the TIMER_MAX limit, then update the count
238 */
67110c3e 239 count = imx_gpt_update_count(s);
5ec694b5 240 }
78d1404d 241 } else {
5ec694b5
JCD
242 /* not a timer event, then just update the count */
243
67110c3e 244 count = imx_gpt_update_count(s);
5ec694b5
JCD
245 }
246
247 /* now, find the next timeout related to count */
248
249 if (s->ir & GPT_IR_OF1IE) {
67110c3e 250 timeout = imx_gpt_find_limit(count, s->ocr1, timeout);
5ec694b5
JCD
251 }
252 if (s->ir & GPT_IR_OF2IE) {
67110c3e 253 timeout = imx_gpt_find_limit(count, s->ocr2, timeout);
5ec694b5
JCD
254 }
255 if (s->ir & GPT_IR_OF3IE) {
67110c3e 256 timeout = imx_gpt_find_limit(count, s->ocr3, timeout);
5ec694b5
JCD
257 }
258
259 /* find the next set of interrupts to raise for next timer event */
260
261 s->next_int = 0;
262 if ((s->ir & GPT_IR_OF1IE) && (timeout == s->ocr1)) {
263 s->next_int |= GPT_SR_OF1;
264 }
265 if ((s->ir & GPT_IR_OF2IE) && (timeout == s->ocr2)) {
266 s->next_int |= GPT_SR_OF2;
267 }
268 if ((s->ir & GPT_IR_OF3IE) && (timeout == s->ocr3)) {
269 s->next_int |= GPT_SR_OF3;
270 }
271 if ((s->ir & GPT_IR_ROVIE) && (timeout == TIMER_MAX)) {
272 s->next_int |= GPT_SR_ROV;
273 }
274
275 /* the new range to count down from */
67110c3e 276 limit = timeout - imx_gpt_update_count(s);
5ec694b5
JCD
277
278 if (limit < 0) {
279 /*
280 * if we reach here, then QEMU is running too slow and we pass the
281 * timeout limit while computing it. Let's deliver the interrupt
282 * and compute a new limit.
283 */
284 s->sr |= s->next_int;
285
67110c3e 286 imx_gpt_compute_next_timeout(s, event);
5ec694b5 287
67110c3e 288 imx_gpt_update_int(s);
5ec694b5
JCD
289 } else {
290 /* New timeout value */
291 s->next_timeout = timeout;
292
293 /* reset the limit to the computed range */
294 ptimer_set_limit(s->timer, limit, 1);
78d1404d 295 }
78d1404d
PC
296}
297
67110c3e 298static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
78d1404d 299{
67110c3e 300 IMXGPTState *s = IMX_GPT(opaque);
5ec694b5
JCD
301 uint32_t reg_value = 0;
302 uint32_t reg = offset >> 2;
78d1404d 303
5ec694b5 304 switch (reg) {
78d1404d 305 case 0: /* Control Register */
5ec694b5
JCD
306 reg_value = s->cr;
307 break;
78d1404d
PC
308
309 case 1: /* prescaler */
5ec694b5
JCD
310 reg_value = s->pr;
311 break;
78d1404d
PC
312
313 case 2: /* Status Register */
5ec694b5
JCD
314 reg_value = s->sr;
315 break;
78d1404d
PC
316
317 case 3: /* Interrupt Register */
5ec694b5
JCD
318 reg_value = s->ir;
319 break;
78d1404d
PC
320
321 case 4: /* Output Compare Register 1 */
5ec694b5
JCD
322 reg_value = s->ocr1;
323 break;
78d1404d 324
462566fc 325 case 5: /* Output Compare Register 2 */
5ec694b5
JCD
326 reg_value = s->ocr2;
327 break;
462566fc
JCD
328
329 case 6: /* Output Compare Register 3 */
5ec694b5
JCD
330 reg_value = s->ocr3;
331 break;
462566fc
JCD
332
333 case 7: /* input Capture Register 1 */
5ec694b5
JCD
334 qemu_log_mask(LOG_UNIMP, "icr1 feature is not implemented\n");
335 reg_value = s->icr1;
336 break;
462566fc
JCD
337
338 case 8: /* input Capture Register 2 */
5ec694b5
JCD
339 qemu_log_mask(LOG_UNIMP, "icr2 feature is not implemented\n");
340 reg_value = s->icr2;
341 break;
78d1404d
PC
342
343 case 9: /* cnt */
67110c3e 344 imx_gpt_update_count(s);
5ec694b5
JCD
345 reg_value = s->cnt;
346 break;
347
348 default:
349 IPRINTF("Bad offset %x\n", reg);
350 break;
78d1404d
PC
351 }
352
67110c3e 353 DPRINTF("(%s) = 0x%08x\n", imx_gpt_reg_name(reg), reg_value);
462566fc 354
5ec694b5 355 return reg_value;
78d1404d
PC
356}
357
67110c3e 358static void imx_gpt_reset(DeviceState *dev)
78d1404d 359{
67110c3e 360 IMXGPTState *s = IMX_GPT(dev);
78d1404d 361
5ec694b5
JCD
362 /* stop timer */
363 ptimer_stop(s->timer);
364
78d1404d
PC
365 /*
366 * Soft reset doesn't touch some bits; hard reset clears them
367 */
462566fc
JCD
368 s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
369 GPT_CR_WAITEN|GPT_CR_DBGEN);
78d1404d
PC
370 s->sr = 0;
371 s->pr = 0;
372 s->ir = 0;
373 s->cnt = 0;
374 s->ocr1 = TIMER_MAX;
462566fc
JCD
375 s->ocr2 = TIMER_MAX;
376 s->ocr3 = TIMER_MAX;
377 s->icr1 = 0;
378 s->icr2 = 0;
5ec694b5
JCD
379
380 s->next_timeout = TIMER_MAX;
381 s->next_int = 0;
382
383 /* compute new freq */
67110c3e 384 imx_gpt_set_freq(s);
5ec694b5
JCD
385
386 /* reset the limit to TIMER_MAX */
387 ptimer_set_limit(s->timer, TIMER_MAX, 1);
388
389 /* if the timer is still enabled, restart it */
390 if (s->freq && (s->cr & GPT_CR_EN)) {
391 ptimer_run(s->timer, 1);
392 }
78d1404d
PC
393}
394
67110c3e
JCD
395static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
396 unsigned size)
78d1404d 397{
67110c3e 398 IMXGPTState *s = IMX_GPT(opaque);
5ec694b5
JCD
399 uint32_t oldreg;
400 uint32_t reg = offset >> 2;
401
67110c3e 402 DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(reg),
5ec694b5
JCD
403 (uint32_t)value);
404
405 switch (reg) {
406 case 0:
407 oldreg = s->cr;
408 s->cr = value & ~0x7c14;
409 if (s->cr & GPT_CR_SWR) { /* force reset */
410 /* handle the reset */
67110c3e 411 imx_gpt_reset(DEVICE(s));
5ec694b5
JCD
412 } else {
413 /* set our freq, as the source might have changed */
67110c3e 414 imx_gpt_set_freq(s);
5ec694b5
JCD
415
416 if ((oldreg ^ s->cr) & GPT_CR_EN) {
417 if (s->cr & GPT_CR_EN) {
418 if (s->cr & GPT_CR_ENMOD) {
419 s->next_timeout = TIMER_MAX;
420 ptimer_set_count(s->timer, TIMER_MAX);
67110c3e 421 imx_gpt_compute_next_timeout(s, false);
5ec694b5
JCD
422 }
423 ptimer_run(s->timer, 1);
424 } else {
425 /* stop timer */
426 ptimer_stop(s->timer);
78d1404d 427 }
5ec694b5 428 }
78d1404d 429 }
5ec694b5 430 break;
78d1404d
PC
431
432 case 1: /* Prescaler */
433 s->pr = value & 0xfff;
67110c3e 434 imx_gpt_set_freq(s);
5ec694b5 435 break;
78d1404d
PC
436
437 case 2: /* SR */
5ec694b5 438 s->sr &= ~(value & 0x3f);
67110c3e 439 imx_gpt_update_int(s);
5ec694b5 440 break;
78d1404d
PC
441
442 case 3: /* IR -- interrupt register */
443 s->ir = value & 0x3f;
67110c3e 444 imx_gpt_update_int(s);
5ec694b5 445
67110c3e 446 imx_gpt_compute_next_timeout(s, false);
5ec694b5
JCD
447
448 break;
78d1404d
PC
449
450 case 4: /* OCR1 -- output compare register */
5ec694b5
JCD
451 s->ocr1 = value;
452
78d1404d
PC
453 /* In non-freerun mode, reset count when this register is written */
454 if (!(s->cr & GPT_CR_FRR)) {
5ec694b5
JCD
455 s->next_timeout = TIMER_MAX;
456 ptimer_set_limit(s->timer, TIMER_MAX, 1);
78d1404d 457 }
5ec694b5
JCD
458
459 /* compute the new timeout */
67110c3e 460 imx_gpt_compute_next_timeout(s, false);
5ec694b5
JCD
461
462 break;
78d1404d 463
462566fc 464 case 5: /* OCR2 -- output compare register */
5ec694b5
JCD
465 s->ocr2 = value;
466
467 /* compute the new timeout */
67110c3e 468 imx_gpt_compute_next_timeout(s, false);
5ec694b5
JCD
469
470 break;
471
462566fc 472 case 6: /* OCR3 -- output compare register */
5ec694b5
JCD
473 s->ocr3 = value;
474
475 /* compute the new timeout */
67110c3e 476 imx_gpt_compute_next_timeout(s, false);
5ec694b5
JCD
477
478 break;
479
78d1404d 480 default:
5ec694b5
JCD
481 IPRINTF("Bad offset %x\n", reg);
482 break;
78d1404d
PC
483 }
484}
485
67110c3e 486static void imx_gpt_timeout(void *opaque)
78d1404d 487{
67110c3e 488 IMXGPTState *s = IMX_GPT(opaque);
78d1404d 489
5ec694b5 490 DPRINTF("\n");
78d1404d 491
5ec694b5
JCD
492 s->sr |= s->next_int;
493 s->next_int = 0;
494
67110c3e 495 imx_gpt_compute_next_timeout(s, true);
78d1404d 496
67110c3e 497 imx_gpt_update_int(s);
5ec694b5
JCD
498
499 if (s->freq && (s->cr & GPT_CR_EN)) {
500 ptimer_run(s->timer, 1);
501 }
78d1404d
PC
502}
503
67110c3e
JCD
504static const MemoryRegionOps imx_gpt_ops = {
505 .read = imx_gpt_read,
506 .write = imx_gpt_write,
78d1404d
PC
507 .endianness = DEVICE_NATIVE_ENDIAN,
508};
509
510
67110c3e 511static void imx_gpt_realize(DeviceState *dev, Error **errp)
78d1404d 512{
67110c3e
JCD
513 IMXGPTState *s = IMX_GPT(dev);
514 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
78d1404d
PC
515 QEMUBH *bh;
516
67110c3e 517 sysbus_init_irq(sbd, &s->irq);
853dca12 518 memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT,
78d1404d 519 0x00001000);
67110c3e 520 sysbus_init_mmio(sbd, &s->iomem);
78d1404d 521
67110c3e 522 bh = qemu_bh_new(imx_gpt_timeout, s);
78d1404d 523 s->timer = ptimer_init(bh);
78d1404d
PC
524}
525
5ec694b5 526void imx_timerg_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
78d1404d 527{
67110c3e 528 IMXGPTState *pp;
78d1404d
PC
529 DeviceState *dev;
530
5ec694b5 531 dev = sysbus_create_simple(TYPE_IMX_GPT, addr, irq);
67110c3e 532 pp = IMX_GPT(dev);
78d1404d
PC
533 pp->ccm = ccm;
534}
535
67110c3e 536static void imx_gpt_class_init(ObjectClass *klass, void *data)
78d1404d 537{
67110c3e
JCD
538 DeviceClass *dc = DEVICE_CLASS(klass);
539
540 dc->realize = imx_gpt_realize;
541 dc->reset = imx_gpt_reset;
542 dc->vmsd = &vmstate_imx_timer_gpt;
78d1404d
PC
543 dc->desc = "i.MX general timer";
544}
545
67110c3e 546static const TypeInfo imx_gpt_info = {
5ec694b5 547 .name = TYPE_IMX_GPT,
78d1404d 548 .parent = TYPE_SYS_BUS_DEVICE,
67110c3e
JCD
549 .instance_size = sizeof(IMXGPTState),
550 .class_init = imx_gpt_class_init,
78d1404d
PC
551};
552
67110c3e 553static void imx_gpt_register_types(void)
78d1404d 554{
67110c3e 555 type_register_static(&imx_gpt_info);
78d1404d
PC
556}
557
67110c3e 558type_init(imx_gpt_register_types)