MAINTAINERS: mark megasas as maintained
[qemu/ar7.git] / hw / timer / imx_epit.c
blob0dbe15c99b27a3262097d6d336875d48a0121df3
1 /*
2 * IMX EPIT Timer
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
10 * This code is licensed under GPL version 2 or later. See
11 * the COPYING file in the top-level directory.
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"
23 #define TYPE_IMX_EPIT "imx.epit"
25 #define DEBUG_TIMER 0
26 #if DEBUG_TIMER
28 static char const *imx_epit_reg_name(uint32_t reg)
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 "[?]";
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
53 * Define to 1 for messages about attempts to
54 * access unimplemented registers or similar.
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
64 #define IMX_EPIT(obj) \
65 OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
68 * EPIT: Enhanced periodic interrupt timer
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)
86 #define TIMER_MAX 0XFFFFFFFFUL
89 * Exact clock frequencies vary from board to board.
90 * These are typical.
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 */
99 typedef struct {
100 SysBusDevice busdev;
101 ptimer_state *timer_reload;
102 ptimer_state *timer_cmp;
103 MemoryRegion iomem;
104 DeviceState *ccm;
106 uint32_t cr;
107 uint32_t sr;
108 uint32_t lr;
109 uint32_t cmp;
110 uint32_t cnt;
112 uint32_t freq;
113 qemu_irq irq;
114 } IMXEPITState;
117 * Update interrupt status
119 static void imx_epit_update_int(IMXEPITState *s)
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);
128 static void imx_epit_set_freq(IMXEPITState *s)
130 uint32_t clksrc;
131 uint32_t prescaler;
132 uint32_t freq;
134 clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2);
135 prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12);
137 freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler;
139 s->freq = freq;
141 DPRINTF("Setting ptimer frequency to %u\n", freq);
143 if (freq) {
144 ptimer_set_freq(s->timer_reload, freq);
145 ptimer_set_freq(s->timer_cmp, freq);
149 static void imx_epit_reset(DeviceState *dev)
151 IMXEPITState *s = IMX_EPIT(dev);
154 * Soft reset doesn't touch some bits; hard reset clears them
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);
175 static uint32_t imx_epit_update_count(IMXEPITState *s)
177 s->cnt = ptimer_get_count(s->timer_reload);
179 return s->cnt;
182 static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
184 IMXEPITState *s = IMX_EPIT(opaque);
185 uint32_t reg_value = 0;
186 uint32_t reg = offset >> 2;
188 switch (reg) {
189 case 0: /* Control Register */
190 reg_value = s->cr;
191 break;
193 case 1: /* Status Register */
194 reg_value = s->sr;
195 break;
197 case 2: /* LR - ticks*/
198 reg_value = s->lr;
199 break;
201 case 3: /* CMP */
202 reg_value = s->cmp;
203 break;
205 case 4: /* CNT */
206 imx_epit_update_count(s);
207 reg_value = s->cnt;
208 break;
210 default:
211 IPRINTF("Bad offset %x\n", reg);
212 break;
215 DPRINTF("(%s) = 0x%08x\n", imx_epit_reg_name(reg), reg_value);
217 return reg_value;
220 static void imx_epit_reload_compare_timer(IMXEPITState *s)
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);
232 ptimer_set_count(s->timer_cmp, next);
236 static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
237 unsigned size)
239 IMXEPITState *s = IMX_EPIT(opaque);
240 uint32_t reg = offset >> 2;
241 uint64_t oldcr;
243 DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value);
245 switch (reg) {
246 case 0: /* CR */
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);
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);
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);
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);
284 } else {
285 ptimer_stop(s->timer_cmp);
287 break;
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);
295 break;
297 case 2: /* LR - set ticks */
298 s->lr = value;
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);
310 imx_epit_reload_compare_timer(s);
311 break;
313 case 3: /* CMP */
314 s->cmp = value;
316 imx_epit_reload_compare_timer(s);
318 break;
320 default:
321 IPRINTF("Bad offset %x\n", reg);
323 break;
326 static void imx_epit_cmp(void *opaque)
328 IMXEPITState *s = IMX_EPIT(opaque);
330 DPRINTF("sr was %d\n", s->sr);
332 s->sr = 1;
333 imx_epit_update_int(s);
336 void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
338 IMXEPITState *pp;
339 DeviceState *dev;
341 dev = sysbus_create_simple(TYPE_IMX_EPIT, addr, irq);
342 pp = IMX_EPIT(dev);
343 pp->ccm = ccm;
346 static const MemoryRegionOps imx_epit_ops = {
347 .read = imx_epit_read,
348 .write = imx_epit_write,
349 .endianness = DEVICE_NATIVE_ENDIAN,
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()
370 static void imx_epit_realize(DeviceState *dev, Error **errp)
372 IMXEPITState *s = IMX_EPIT(dev);
373 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
374 QEMUBH *bh;
376 DPRINTF("\n");
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);
383 s->timer_reload = ptimer_init(NULL);
385 bh = qemu_bh_new(imx_epit_cmp, s);
386 s->timer_cmp = ptimer_init(bh);
389 static void imx_epit_class_init(ObjectClass *klass, void *data)
391 DeviceClass *dc = DEVICE_CLASS(klass);
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";
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,
406 static void imx_epit_register_types(void)
408 type_register_static(&imx_epit_info);
411 type_init(imx_epit_register_types)