1 | /* |
2 | * IMX GPT 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 <jcd@tribudubois.net> |
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 "qemu/osdep.h" |
16 | #include "hw/irq.h" |
17 | #include "hw/timer/imx_gpt.h" |
18 | #include "migration/vmstate.h" |
19 | #include "qemu/main-loop.h" |
20 | #include "qemu/module.h" |
21 | #include "qemu/log.h" |
22 | |
23 | #ifndef DEBUG_IMX_GPT |
24 | #define DEBUG_IMX_GPT 0 |
25 | #endif |
26 | |
27 | #define DPRINTF(fmt, args...) \ |
28 | do { \ |
29 | if (DEBUG_IMX_GPT) { \ |
30 | fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPT, \ |
31 | __func__, ##args); \ |
32 | } \ |
33 | } while (0) |
34 | |
35 | static const char *imx_gpt_reg_name(uint32_t reg) |
36 | { |
37 | switch (reg) { |
38 | case 0: |
39 | return "CR" ; |
40 | case 1: |
41 | return "PR" ; |
42 | case 2: |
43 | return "SR" ; |
44 | case 3: |
45 | return "IR" ; |
46 | case 4: |
47 | return "OCR1" ; |
48 | case 5: |
49 | return "OCR2" ; |
50 | case 6: |
51 | return "OCR3" ; |
52 | case 7: |
53 | return "ICR1" ; |
54 | case 8: |
55 | return "ICR2" ; |
56 | case 9: |
57 | return "CNT" ; |
58 | default: |
59 | return "[?]" ; |
60 | } |
61 | } |
62 | |
63 | static const VMStateDescription vmstate_imx_timer_gpt = { |
64 | .name = TYPE_IMX_GPT, |
65 | .version_id = 3, |
66 | .minimum_version_id = 3, |
67 | .fields = (VMStateField[]) { |
68 | VMSTATE_UINT32(cr, IMXGPTState), |
69 | VMSTATE_UINT32(pr, IMXGPTState), |
70 | VMSTATE_UINT32(sr, IMXGPTState), |
71 | VMSTATE_UINT32(ir, IMXGPTState), |
72 | VMSTATE_UINT32(ocr1, IMXGPTState), |
73 | VMSTATE_UINT32(ocr2, IMXGPTState), |
74 | VMSTATE_UINT32(ocr3, IMXGPTState), |
75 | VMSTATE_UINT32(icr1, IMXGPTState), |
76 | VMSTATE_UINT32(icr2, IMXGPTState), |
77 | VMSTATE_UINT32(cnt, IMXGPTState), |
78 | VMSTATE_UINT32(next_timeout, IMXGPTState), |
79 | VMSTATE_UINT32(next_int, IMXGPTState), |
80 | VMSTATE_UINT32(freq, IMXGPTState), |
81 | VMSTATE_PTIMER(timer, IMXGPTState), |
82 | VMSTATE_END_OF_LIST() |
83 | } |
84 | }; |
85 | |
86 | static const IMXClk imx25_gpt_clocks[] = { |
87 | CLK_NONE, /* 000 No clock source */ |
88 | CLK_IPG, /* 001 ipg_clk, 532MHz*/ |
89 | CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ |
90 | CLK_NONE, /* 011 not defined */ |
91 | CLK_32k, /* 100 ipg_clk_32k */ |
92 | CLK_32k, /* 101 ipg_clk_32k */ |
93 | CLK_32k, /* 110 ipg_clk_32k */ |
94 | CLK_32k, /* 111 ipg_clk_32k */ |
95 | }; |
96 | |
97 | static const IMXClk imx31_gpt_clocks[] = { |
98 | CLK_NONE, /* 000 No clock source */ |
99 | CLK_IPG, /* 001 ipg_clk, 532MHz*/ |
100 | CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ |
101 | CLK_NONE, /* 011 not defined */ |
102 | CLK_32k, /* 100 ipg_clk_32k */ |
103 | CLK_NONE, /* 101 not defined */ |
104 | CLK_NONE, /* 110 not defined */ |
105 | CLK_NONE, /* 111 not defined */ |
106 | }; |
107 | |
108 | static const IMXClk imx6_gpt_clocks[] = { |
109 | CLK_NONE, /* 000 No clock source */ |
110 | CLK_IPG, /* 001 ipg_clk, 532MHz*/ |
111 | CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ |
112 | CLK_EXT, /* 011 External clock */ |
113 | CLK_32k, /* 100 ipg_clk_32k */ |
114 | CLK_HIGH_DIV, /* 101 reference clock / 8 */ |
115 | CLK_NONE, /* 110 not defined */ |
116 | CLK_HIGH, /* 111 reference clock */ |
117 | }; |
118 | |
119 | static const IMXClk imx7_gpt_clocks[] = { |
120 | CLK_NONE, /* 000 No clock source */ |
121 | CLK_IPG, /* 001 ipg_clk, 532MHz*/ |
122 | CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ |
123 | CLK_EXT, /* 011 External clock */ |
124 | CLK_32k, /* 100 ipg_clk_32k */ |
125 | CLK_HIGH, /* 101 reference clock */ |
126 | CLK_NONE, /* 110 not defined */ |
127 | CLK_NONE, /* 111 not defined */ |
128 | }; |
129 | |
130 | static void imx_gpt_set_freq(IMXGPTState *s) |
131 | { |
132 | uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3); |
133 | |
134 | s->freq = imx_ccm_get_clock_frequency(s->ccm, |
135 | s->clocks[clksrc]) / (1 + s->pr); |
136 | |
137 | DPRINTF("Setting clksrc %d to frequency %d\n" , clksrc, s->freq); |
138 | |
139 | if (s->freq) { |
140 | ptimer_set_freq(s->timer, s->freq); |
141 | } |
142 | } |
143 | |
144 | static void imx_gpt_update_int(IMXGPTState *s) |
145 | { |
146 | if ((s->sr & s->ir) && (s->cr & GPT_CR_EN)) { |
147 | qemu_irq_raise(s->irq); |
148 | } else { |
149 | qemu_irq_lower(s->irq); |
150 | } |
151 | } |
152 | |
153 | static uint32_t imx_gpt_update_count(IMXGPTState *s) |
154 | { |
155 | s->cnt = s->next_timeout - (uint32_t)ptimer_get_count(s->timer); |
156 | |
157 | return s->cnt; |
158 | } |
159 | |
160 | static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg, |
161 | uint32_t timeout) |
162 | { |
163 | if ((count < reg) && (timeout > reg)) { |
164 | timeout = reg; |
165 | } |
166 | |
167 | return timeout; |
168 | } |
169 | |
170 | static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event) |
171 | { |
172 | uint32_t timeout = GPT_TIMER_MAX; |
173 | uint32_t count; |
174 | long long limit; |
175 | |
176 | if (!(s->cr & GPT_CR_EN)) { |
177 | /* if not enabled just return */ |
178 | return; |
179 | } |
180 | |
181 | /* update the count */ |
182 | count = imx_gpt_update_count(s); |
183 | |
184 | if (event) { |
185 | /* |
186 | * This is an event (the ptimer reached 0 and stopped), and the |
187 | * timer counter is now equal to s->next_timeout. |
188 | */ |
189 | if (!(s->cr & GPT_CR_FRR) && (count == s->ocr1)) { |
190 | /* We are in restart mode and we crossed the compare channel 1 |
191 | * value. We need to reset the counter to 0. |
192 | */ |
193 | count = s->cnt = s->next_timeout = 0; |
194 | } else if (count == GPT_TIMER_MAX) { |
195 | /* We reached GPT_TIMER_MAX so we need to rollover */ |
196 | count = s->cnt = s->next_timeout = 0; |
197 | } |
198 | } |
199 | |
200 | /* now, find the next timeout related to count */ |
201 | |
202 | if (s->ir & GPT_IR_OF1IE) { |
203 | timeout = imx_gpt_find_limit(count, s->ocr1, timeout); |
204 | } |
205 | if (s->ir & GPT_IR_OF2IE) { |
206 | timeout = imx_gpt_find_limit(count, s->ocr2, timeout); |
207 | } |
208 | if (s->ir & GPT_IR_OF3IE) { |
209 | timeout = imx_gpt_find_limit(count, s->ocr3, timeout); |
210 | } |
211 | |
212 | /* find the next set of interrupts to raise for next timer event */ |
213 | |
214 | s->next_int = 0; |
215 | if ((s->ir & GPT_IR_OF1IE) && (timeout == s->ocr1)) { |
216 | s->next_int |= GPT_SR_OF1; |
217 | } |
218 | if ((s->ir & GPT_IR_OF2IE) && (timeout == s->ocr2)) { |
219 | s->next_int |= GPT_SR_OF2; |
220 | } |
221 | if ((s->ir & GPT_IR_OF3IE) && (timeout == s->ocr3)) { |
222 | s->next_int |= GPT_SR_OF3; |
223 | } |
224 | if ((s->ir & GPT_IR_ROVIE) && (timeout == GPT_TIMER_MAX)) { |
225 | s->next_int |= GPT_SR_ROV; |
226 | } |
227 | |
228 | /* the new range to count down from */ |
229 | limit = timeout - imx_gpt_update_count(s); |
230 | |
231 | if (limit < 0) { |
232 | /* |
233 | * if we reach here, then QEMU is running too slow and we pass the |
234 | * timeout limit while computing it. Let's deliver the interrupt |
235 | * and compute a new limit. |
236 | */ |
237 | s->sr |= s->next_int; |
238 | |
239 | imx_gpt_compute_next_timeout(s, event); |
240 | |
241 | imx_gpt_update_int(s); |
242 | } else { |
243 | /* New timeout value */ |
244 | s->next_timeout = timeout; |
245 | |
246 | /* reset the limit to the computed range */ |
247 | ptimer_set_limit(s->timer, limit, 1); |
248 | } |
249 | } |
250 | |
251 | static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size) |
252 | { |
253 | IMXGPTState *s = IMX_GPT(opaque); |
254 | uint32_t reg_value = 0; |
255 | |
256 | switch (offset >> 2) { |
257 | case 0: /* Control Register */ |
258 | reg_value = s->cr; |
259 | break; |
260 | |
261 | case 1: /* prescaler */ |
262 | reg_value = s->pr; |
263 | break; |
264 | |
265 | case 2: /* Status Register */ |
266 | reg_value = s->sr; |
267 | break; |
268 | |
269 | case 3: /* Interrupt Register */ |
270 | reg_value = s->ir; |
271 | break; |
272 | |
273 | case 4: /* Output Compare Register 1 */ |
274 | reg_value = s->ocr1; |
275 | break; |
276 | |
277 | case 5: /* Output Compare Register 2 */ |
278 | reg_value = s->ocr2; |
279 | break; |
280 | |
281 | case 6: /* Output Compare Register 3 */ |
282 | reg_value = s->ocr3; |
283 | break; |
284 | |
285 | case 7: /* input Capture Register 1 */ |
286 | qemu_log_mask(LOG_UNIMP, "[%s]%s: icr1 feature is not implemented\n" , |
287 | TYPE_IMX_GPT, __func__); |
288 | reg_value = s->icr1; |
289 | break; |
290 | |
291 | case 8: /* input Capture Register 2 */ |
292 | qemu_log_mask(LOG_UNIMP, "[%s]%s: icr2 feature is not implemented\n" , |
293 | TYPE_IMX_GPT, __func__); |
294 | reg_value = s->icr2; |
295 | break; |
296 | |
297 | case 9: /* cnt */ |
298 | imx_gpt_update_count(s); |
299 | reg_value = s->cnt; |
300 | break; |
301 | |
302 | default: |
303 | qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" |
304 | HWADDR_PRIx "\n" , TYPE_IMX_GPT, __func__, offset); |
305 | break; |
306 | } |
307 | |
308 | DPRINTF("(%s) = 0x%08x\n" , imx_gpt_reg_name(offset >> 2), reg_value); |
309 | |
310 | return reg_value; |
311 | } |
312 | |
313 | |
314 | static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset) |
315 | { |
316 | /* stop timer */ |
317 | ptimer_stop(s->timer); |
318 | |
319 | /* Soft reset and hard reset differ only in their handling of the CR |
320 | * register -- soft reset preserves the values of some bits there. |
321 | */ |
322 | if (is_soft_reset) { |
323 | /* Clear all CR bits except those that are preserved by soft reset. */ |
324 | s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN | |
325 | GPT_CR_WAITEN | GPT_CR_DBGEN | |
326 | (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT); |
327 | } else { |
328 | s->cr = 0; |
329 | } |
330 | s->sr = 0; |
331 | s->pr = 0; |
332 | s->ir = 0; |
333 | s->cnt = 0; |
334 | s->ocr1 = GPT_TIMER_MAX; |
335 | s->ocr2 = GPT_TIMER_MAX; |
336 | s->ocr3 = GPT_TIMER_MAX; |
337 | s->icr1 = 0; |
338 | s->icr2 = 0; |
339 | |
340 | s->next_timeout = GPT_TIMER_MAX; |
341 | s->next_int = 0; |
342 | |
343 | /* compute new freq */ |
344 | imx_gpt_set_freq(s); |
345 | |
346 | /* reset the limit to GPT_TIMER_MAX */ |
347 | ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1); |
348 | |
349 | /* if the timer is still enabled, restart it */ |
350 | if (s->freq && (s->cr & GPT_CR_EN)) { |
351 | ptimer_run(s->timer, 1); |
352 | } |
353 | } |
354 | |
355 | static void imx_gpt_soft_reset(DeviceState *dev) |
356 | { |
357 | IMXGPTState *s = IMX_GPT(dev); |
358 | imx_gpt_reset_common(s, true); |
359 | } |
360 | |
361 | static void imx_gpt_reset(DeviceState *dev) |
362 | { |
363 | IMXGPTState *s = IMX_GPT(dev); |
364 | imx_gpt_reset_common(s, false); |
365 | } |
366 | |
367 | static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value, |
368 | unsigned size) |
369 | { |
370 | IMXGPTState *s = IMX_GPT(opaque); |
371 | uint32_t oldreg; |
372 | |
373 | DPRINTF("(%s, value = 0x%08x)\n" , imx_gpt_reg_name(offset >> 2), |
374 | (uint32_t)value); |
375 | |
376 | switch (offset >> 2) { |
377 | case 0: |
378 | oldreg = s->cr; |
379 | s->cr = value & ~0x7c14; |
380 | if (s->cr & GPT_CR_SWR) { /* force reset */ |
381 | /* handle the reset */ |
382 | imx_gpt_soft_reset(DEVICE(s)); |
383 | } else { |
384 | /* set our freq, as the source might have changed */ |
385 | imx_gpt_set_freq(s); |
386 | |
387 | if ((oldreg ^ s->cr) & GPT_CR_EN) { |
388 | if (s->cr & GPT_CR_EN) { |
389 | if (s->cr & GPT_CR_ENMOD) { |
390 | s->next_timeout = GPT_TIMER_MAX; |
391 | ptimer_set_count(s->timer, GPT_TIMER_MAX); |
392 | imx_gpt_compute_next_timeout(s, false); |
393 | } |
394 | ptimer_run(s->timer, 1); |
395 | } else { |
396 | /* stop timer */ |
397 | ptimer_stop(s->timer); |
398 | } |
399 | } |
400 | } |
401 | break; |
402 | |
403 | case 1: /* Prescaler */ |
404 | s->pr = value & 0xfff; |
405 | imx_gpt_set_freq(s); |
406 | break; |
407 | |
408 | case 2: /* SR */ |
409 | s->sr &= ~(value & 0x3f); |
410 | imx_gpt_update_int(s); |
411 | break; |
412 | |
413 | case 3: /* IR -- interrupt register */ |
414 | s->ir = value & 0x3f; |
415 | imx_gpt_update_int(s); |
416 | |
417 | imx_gpt_compute_next_timeout(s, false); |
418 | |
419 | break; |
420 | |
421 | case 4: /* OCR1 -- output compare register */ |
422 | s->ocr1 = value; |
423 | |
424 | /* In non-freerun mode, reset count when this register is written */ |
425 | if (!(s->cr & GPT_CR_FRR)) { |
426 | s->next_timeout = GPT_TIMER_MAX; |
427 | ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1); |
428 | } |
429 | |
430 | /* compute the new timeout */ |
431 | imx_gpt_compute_next_timeout(s, false); |
432 | |
433 | break; |
434 | |
435 | case 5: /* OCR2 -- output compare register */ |
436 | s->ocr2 = value; |
437 | |
438 | /* compute the new timeout */ |
439 | imx_gpt_compute_next_timeout(s, false); |
440 | |
441 | break; |
442 | |
443 | case 6: /* OCR3 -- output compare register */ |
444 | s->ocr3 = value; |
445 | |
446 | /* compute the new timeout */ |
447 | imx_gpt_compute_next_timeout(s, false); |
448 | |
449 | break; |
450 | |
451 | default: |
452 | qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" |
453 | HWADDR_PRIx "\n" , TYPE_IMX_GPT, __func__, offset); |
454 | break; |
455 | } |
456 | } |
457 | |
458 | static void imx_gpt_timeout(void *opaque) |
459 | { |
460 | IMXGPTState *s = IMX_GPT(opaque); |
461 | |
462 | DPRINTF("\n" ); |
463 | |
464 | s->sr |= s->next_int; |
465 | s->next_int = 0; |
466 | |
467 | imx_gpt_compute_next_timeout(s, true); |
468 | |
469 | imx_gpt_update_int(s); |
470 | |
471 | if (s->freq && (s->cr & GPT_CR_EN)) { |
472 | ptimer_run(s->timer, 1); |
473 | } |
474 | } |
475 | |
476 | static const MemoryRegionOps imx_gpt_ops = { |
477 | .read = imx_gpt_read, |
478 | .write = imx_gpt_write, |
479 | .endianness = DEVICE_NATIVE_ENDIAN, |
480 | }; |
481 | |
482 | |
483 | static void imx_gpt_realize(DeviceState *dev, Error **errp) |
484 | { |
485 | IMXGPTState *s = IMX_GPT(dev); |
486 | SysBusDevice *sbd = SYS_BUS_DEVICE(dev); |
487 | QEMUBH *bh; |
488 | |
489 | sysbus_init_irq(sbd, &s->irq); |
490 | memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT, |
491 | 0x00001000); |
492 | sysbus_init_mmio(sbd, &s->iomem); |
493 | |
494 | bh = qemu_bh_new(imx_gpt_timeout, s); |
495 | s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT); |
496 | } |
497 | |
498 | static void imx_gpt_class_init(ObjectClass *klass, void *data) |
499 | { |
500 | DeviceClass *dc = DEVICE_CLASS(klass); |
501 | |
502 | dc->realize = imx_gpt_realize; |
503 | dc->reset = imx_gpt_reset; |
504 | dc->vmsd = &vmstate_imx_timer_gpt; |
505 | dc->desc = "i.MX general timer" ; |
506 | } |
507 | |
508 | static void imx25_gpt_init(Object *obj) |
509 | { |
510 | IMXGPTState *s = IMX_GPT(obj); |
511 | |
512 | s->clocks = imx25_gpt_clocks; |
513 | } |
514 | |
515 | static void imx31_gpt_init(Object *obj) |
516 | { |
517 | IMXGPTState *s = IMX_GPT(obj); |
518 | |
519 | s->clocks = imx31_gpt_clocks; |
520 | } |
521 | |
522 | static void imx6_gpt_init(Object *obj) |
523 | { |
524 | IMXGPTState *s = IMX_GPT(obj); |
525 | |
526 | s->clocks = imx6_gpt_clocks; |
527 | } |
528 | |
529 | static void imx7_gpt_init(Object *obj) |
530 | { |
531 | IMXGPTState *s = IMX_GPT(obj); |
532 | |
533 | s->clocks = imx7_gpt_clocks; |
534 | } |
535 | |
536 | static const TypeInfo imx25_gpt_info = { |
537 | .name = TYPE_IMX25_GPT, |
538 | .parent = TYPE_SYS_BUS_DEVICE, |
539 | .instance_size = sizeof(IMXGPTState), |
540 | .instance_init = imx25_gpt_init, |
541 | .class_init = imx_gpt_class_init, |
542 | }; |
543 | |
544 | static const TypeInfo imx31_gpt_info = { |
545 | .name = TYPE_IMX31_GPT, |
546 | .parent = TYPE_IMX25_GPT, |
547 | .instance_init = imx31_gpt_init, |
548 | }; |
549 | |
550 | static const TypeInfo imx6_gpt_info = { |
551 | .name = TYPE_IMX6_GPT, |
552 | .parent = TYPE_IMX25_GPT, |
553 | .instance_init = imx6_gpt_init, |
554 | }; |
555 | |
556 | static const TypeInfo imx7_gpt_info = { |
557 | .name = TYPE_IMX7_GPT, |
558 | .parent = TYPE_IMX25_GPT, |
559 | .instance_init = imx7_gpt_init, |
560 | }; |
561 | |
562 | static void imx_gpt_register_types(void) |
563 | { |
564 | type_register_static(&imx25_gpt_info); |
565 | type_register_static(&imx31_gpt_info); |
566 | type_register_static(&imx6_gpt_info); |
567 | type_register_static(&imx7_gpt_info); |
568 | } |
569 | |
570 | type_init(imx_gpt_register_types) |
571 | |