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