]> Git Repo - qemu.git/blob - hw/arm_timer.c
Merge remote-tracking branch 'pmaydell/arm-devs.for-upstream' into staging
[qemu.git] / hw / arm_timer.c
1 /*
2  * ARM PrimeCell Timer modules.
3  *
4  * Copyright (c) 2005-2006 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the GPL.
8  */
9
10 #include "sysbus.h"
11 #include "qemu-timer.h"
12 #include "qemu-common.h"
13 #include "qdev.h"
14
15 /* Common timer implementation.  */
16
17 #define TIMER_CTRL_ONESHOT      (1 << 0)
18 #define TIMER_CTRL_32BIT        (1 << 1)
19 #define TIMER_CTRL_DIV1         (0 << 2)
20 #define TIMER_CTRL_DIV16        (1 << 2)
21 #define TIMER_CTRL_DIV256       (2 << 2)
22 #define TIMER_CTRL_IE           (1 << 5)
23 #define TIMER_CTRL_PERIODIC     (1 << 6)
24 #define TIMER_CTRL_ENABLE       (1 << 7)
25
26 typedef struct {
27     ptimer_state *timer;
28     uint32_t control;
29     uint32_t limit;
30     int freq;
31     int int_level;
32     qemu_irq irq;
33 } arm_timer_state;
34
35 /* Check all active timers, and schedule the next timer interrupt.  */
36
37 static void arm_timer_update(arm_timer_state *s)
38 {
39     /* Update interrupts.  */
40     if (s->int_level && (s->control & TIMER_CTRL_IE)) {
41         qemu_irq_raise(s->irq);
42     } else {
43         qemu_irq_lower(s->irq);
44     }
45 }
46
47 static uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
48 {
49     arm_timer_state *s = (arm_timer_state *)opaque;
50
51     switch (offset >> 2) {
52     case 0: /* TimerLoad */
53     case 6: /* TimerBGLoad */
54         return s->limit;
55     case 1: /* TimerValue */
56         return ptimer_get_count(s->timer);
57     case 2: /* TimerControl */
58         return s->control;
59     case 4: /* TimerRIS */
60         return s->int_level;
61     case 5: /* TimerMIS */
62         if ((s->control & TIMER_CTRL_IE) == 0)
63             return 0;
64         return s->int_level;
65     default:
66         hw_error("%s: Bad offset %x\n", __func__, (int)offset);
67         return 0;
68     }
69 }
70
71 /* Reset the timer limit after settings have changed.  */
72 static void arm_timer_recalibrate(arm_timer_state *s, int reload)
73 {
74     uint32_t limit;
75
76     if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
77         /* Free running.  */
78         if (s->control & TIMER_CTRL_32BIT)
79             limit = 0xffffffff;
80         else
81             limit = 0xffff;
82     } else {
83           /* Periodic.  */
84           limit = s->limit;
85     }
86     ptimer_set_limit(s->timer, limit, reload);
87 }
88
89 static void arm_timer_write(void *opaque, target_phys_addr_t offset,
90                             uint32_t value)
91 {
92     arm_timer_state *s = (arm_timer_state *)opaque;
93     int freq;
94
95     switch (offset >> 2) {
96     case 0: /* TimerLoad */
97         s->limit = value;
98         arm_timer_recalibrate(s, 1);
99         break;
100     case 1: /* TimerValue */
101         /* ??? Linux seems to want to write to this readonly register.
102            Ignore it.  */
103         break;
104     case 2: /* TimerControl */
105         if (s->control & TIMER_CTRL_ENABLE) {
106             /* Pause the timer if it is running.  This may cause some
107                inaccuracy dure to rounding, but avoids a whole lot of other
108                messyness.  */
109             ptimer_stop(s->timer);
110         }
111         s->control = value;
112         freq = s->freq;
113         /* ??? Need to recalculate expiry time after changing divisor.  */
114         switch ((value >> 2) & 3) {
115         case 1: freq >>= 4; break;
116         case 2: freq >>= 8; break;
117         }
118         arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE);
119         ptimer_set_freq(s->timer, freq);
120         if (s->control & TIMER_CTRL_ENABLE) {
121             /* Restart the timer if still enabled.  */
122             ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
123         }
124         break;
125     case 3: /* TimerIntClr */
126         s->int_level = 0;
127         break;
128     case 6: /* TimerBGLoad */
129         s->limit = value;
130         arm_timer_recalibrate(s, 0);
131         break;
132     default:
133         hw_error("%s: Bad offset %x\n", __func__, (int)offset);
134     }
135     arm_timer_update(s);
136 }
137
138 static void arm_timer_tick(void *opaque)
139 {
140     arm_timer_state *s = (arm_timer_state *)opaque;
141     s->int_level = 1;
142     arm_timer_update(s);
143 }
144
145 static const VMStateDescription vmstate_arm_timer = {
146     .name = "arm_timer",
147     .version_id = 1,
148     .minimum_version_id = 1,
149     .minimum_version_id_old = 1,
150     .fields      = (VMStateField[]) {
151         VMSTATE_UINT32(control, arm_timer_state),
152         VMSTATE_UINT32(limit, arm_timer_state),
153         VMSTATE_INT32(int_level, arm_timer_state),
154         VMSTATE_PTIMER(timer, arm_timer_state),
155         VMSTATE_END_OF_LIST()
156     }
157 };
158
159 static arm_timer_state *arm_timer_init(uint32_t freq)
160 {
161     arm_timer_state *s;
162     QEMUBH *bh;
163
164     s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
165     s->freq = freq;
166     s->control = TIMER_CTRL_IE;
167
168     bh = qemu_bh_new(arm_timer_tick, s);
169     s->timer = ptimer_init(bh);
170     vmstate_register(NULL, -1, &vmstate_arm_timer, s);
171     return s;
172 }
173
174 /* ARM PrimeCell SP804 dual timer module.
175  * Docs at
176  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
177 */
178
179 typedef struct {
180     SysBusDevice busdev;
181     MemoryRegion iomem;
182     arm_timer_state *timer[2];
183     uint32_t freq0, freq1;
184     int level[2];
185     qemu_irq irq;
186 } sp804_state;
187
188 static const uint8_t sp804_ids[] = {
189     /* Timer ID */
190     0x04, 0x18, 0x14, 0,
191     /* PrimeCell ID */
192     0xd, 0xf0, 0x05, 0xb1
193 };
194
195 /* Merge the IRQs from the two component devices.  */
196 static void sp804_set_irq(void *opaque, int irq, int level)
197 {
198     sp804_state *s = (sp804_state *)opaque;
199
200     s->level[irq] = level;
201     qemu_set_irq(s->irq, s->level[0] || s->level[1]);
202 }
203
204 static uint64_t sp804_read(void *opaque, target_phys_addr_t offset,
205                            unsigned size)
206 {
207     sp804_state *s = (sp804_state *)opaque;
208
209     if (offset < 0x20) {
210         return arm_timer_read(s->timer[0], offset);
211     }
212     if (offset < 0x40) {
213         return arm_timer_read(s->timer[1], offset - 0x20);
214     }
215
216     /* TimerPeriphID */
217     if (offset >= 0xfe0 && offset <= 0xffc) {
218         return sp804_ids[(offset - 0xfe0) >> 2];
219     }
220
221     switch (offset) {
222     /* Integration Test control registers, which we won't support */
223     case 0xf00: /* TimerITCR */
224     case 0xf04: /* TimerITOP (strictly write only but..) */
225         return 0;
226     }
227
228     hw_error("%s: Bad offset %x\n", __func__, (int)offset);
229     return 0;
230 }
231
232 static void sp804_write(void *opaque, target_phys_addr_t offset,
233                         uint64_t value, unsigned size)
234 {
235     sp804_state *s = (sp804_state *)opaque;
236
237     if (offset < 0x20) {
238         arm_timer_write(s->timer[0], offset, value);
239         return;
240     }
241
242     if (offset < 0x40) {
243         arm_timer_write(s->timer[1], offset - 0x20, value);
244         return;
245     }
246
247     /* Technically we could be writing to the Test Registers, but not likely */
248     hw_error("%s: Bad offset %x\n", __func__, (int)offset);
249 }
250
251 static const MemoryRegionOps sp804_ops = {
252     .read = sp804_read,
253     .write = sp804_write,
254     .endianness = DEVICE_NATIVE_ENDIAN,
255 };
256
257 static const VMStateDescription vmstate_sp804 = {
258     .name = "sp804",
259     .version_id = 1,
260     .minimum_version_id = 1,
261     .minimum_version_id_old = 1,
262     .fields      = (VMStateField[]) {
263         VMSTATE_INT32_ARRAY(level, sp804_state, 2),
264         VMSTATE_END_OF_LIST()
265     }
266 };
267
268 static int sp804_init(SysBusDevice *dev)
269 {
270     sp804_state *s = FROM_SYSBUS(sp804_state, dev);
271     qemu_irq *qi;
272
273     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
274     sysbus_init_irq(dev, &s->irq);
275     /* The timers are configurable between 32kHz and 1MHz
276      * defaulting to 1MHz but overrideable as individual properties */
277     s->timer[0] = arm_timer_init(s->freq0);
278     s->timer[1] = arm_timer_init(s->freq1);
279
280     s->timer[0]->irq = qi[0];
281     s->timer[1]->irq = qi[1];
282     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
283     sysbus_init_mmio(dev, &s->iomem);
284     vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
285     return 0;
286 }
287
288 static SysBusDeviceInfo sp804_info = {
289     .init = sp804_init,
290     .qdev.name = "sp804",
291     .qdev.size = sizeof(sp804_state),
292     .qdev.props = (Property[]) {
293         DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
294         DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
295         DEFINE_PROP_END_OF_LIST(),
296     }
297 };
298
299 /* Integrator/CP timer module.  */
300
301 typedef struct {
302     SysBusDevice busdev;
303     MemoryRegion iomem;
304     arm_timer_state *timer[3];
305 } icp_pit_state;
306
307 static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset,
308                              unsigned size)
309 {
310     icp_pit_state *s = (icp_pit_state *)opaque;
311     int n;
312
313     /* ??? Don't know the PrimeCell ID for this device.  */
314     n = offset >> 8;
315     if (n > 2) {
316         hw_error("%s: Bad timer %d\n", __func__, n);
317     }
318
319     return arm_timer_read(s->timer[n], offset & 0xff);
320 }
321
322 static void icp_pit_write(void *opaque, target_phys_addr_t offset,
323                           uint64_t value, unsigned size)
324 {
325     icp_pit_state *s = (icp_pit_state *)opaque;
326     int n;
327
328     n = offset >> 8;
329     if (n > 2) {
330         hw_error("%s: Bad timer %d\n", __func__, n);
331     }
332
333     arm_timer_write(s->timer[n], offset & 0xff, value);
334 }
335
336 static const MemoryRegionOps icp_pit_ops = {
337     .read = icp_pit_read,
338     .write = icp_pit_write,
339     .endianness = DEVICE_NATIVE_ENDIAN,
340 };
341
342 static int icp_pit_init(SysBusDevice *dev)
343 {
344     icp_pit_state *s = FROM_SYSBUS(icp_pit_state, dev);
345
346     /* Timer 0 runs at the system clock speed (40MHz).  */
347     s->timer[0] = arm_timer_init(40000000);
348     /* The other two timers run at 1MHz.  */
349     s->timer[1] = arm_timer_init(1000000);
350     s->timer[2] = arm_timer_init(1000000);
351
352     sysbus_init_irq(dev, &s->timer[0]->irq);
353     sysbus_init_irq(dev, &s->timer[1]->irq);
354     sysbus_init_irq(dev, &s->timer[2]->irq);
355
356     memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
357     sysbus_init_mmio(dev, &s->iomem);
358     /* This device has no state to save/restore.  The component timers will
359        save themselves.  */
360     return 0;
361 }
362
363 static void arm_timer_register_devices(void)
364 {
365     sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init);
366     sysbus_register_withprop(&sp804_info);
367 }
368
369 device_init(arm_timer_register_devices)
This page took 0.053671 seconds and 4 git commands to generate.