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