1:
2:
3:
4:
5:
6:
7:
8:
9:
10: #include "hw.h"
11: #include "qemu-timer.h"
12: #include "primecell.h"
13:
14:
15:
16: #define TIMER_CTRL_ONESHOT (1 << 0)
17: #define TIMER_CTRL_32BIT (1 << 1)
18: #define TIMER_CTRL_DIV1 (0 << 2)
19: #define TIMER_CTRL_DIV16 (1 << 2)
20: #define TIMER_CTRL_DIV256 (2 << 2)
21: #define TIMER_CTRL_IE (1 << 5)
22: #define TIMER_CTRL_PERIODIC (1 << 6)
23: #define TIMER_CTRL_ENABLE (1 << 7)
24:
25: typedef struct {
26: ptimer_state *timer;
27: uint32_t control;
28: uint32_t limit;
29: int freq;
30: int int_level;
31: qemu_irq irq;
32: } arm_timer_state;
33:
34:
35:
36: static void arm_timer_update(arm_timer_state *s)
37: {
38:
39: if (s->int_level && (s->control & TIMER_CTRL_IE)) {
40: qemu_irq_raise(s->irq);
41: } else {
42: qemu_irq_lower(s->irq);
43: }
44: }
45:
46: static uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
47: {
48: arm_timer_state *s = (arm_timer_state *)opaque;
49:
50: switch (offset >> 2) {
51: case 0:
52: case 6:
53: return s->limit;
54: case 1:
55: return ptimer_get_count(s->timer);
56: case 2:
57: return s->control;
58: case 4:
59: return s->int_level;
60: case 5:
61: if ((s->control & TIMER_CTRL_IE) == 0)
62: return 0;
63: return s->int_level;
64: default:
65: cpu_abort (cpu_single_env, "arm_timer_read: Bad offset %x\n",
66: (int)offset);
67: return 0;
68: }
69: }
70:
71:
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) == 0) {
77:
78: if (s->control & TIMER_CTRL_32BIT)
79: limit = 0xffffffff;
80: else
81: limit = 0xffff;
82: } else {
83:
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:
97: s->limit = value;
98: arm_timer_recalibrate(s, 1);
99: break;
100: case 1:
101:
102:
103: break;
104: case 2:
105: if (s->control & TIMER_CTRL_ENABLE) {
106:
107:
108:
109: ptimer_stop(s->timer);
110: }
111: s->control = value;
112: freq = s->freq;
113:
114: switch ((value >> 2) & 3) {
115: case 1: freq >>= 4; break;
116: case 2: freq >>= 8; break;
117: }
118: arm_timer_recalibrate(s, 0);
119: ptimer_set_freq(s->timer, freq);
120: if (s->control & TIMER_CTRL_ENABLE) {
121:
122: ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
123: }
124: break;
125: case 3:
126: s->int_level = 0;
127: break;
128: case 6:
129: s->limit = value;
130: arm_timer_recalibrate(s, 0);
131: break;
132: default:
133: cpu_abort (cpu_single_env, "arm_timer_write: Bad offset %x\n",
134: (int)offset);
135: }
136: arm_timer_update(s);
137: }
138:
139: static void arm_timer_tick(void *opaque)
140: {
141: arm_timer_state *s = (arm_timer_state *)opaque;
142: s->int_level = 1;
143: arm_timer_update(s);
144: }
145:
146: static void *arm_timer_init(uint32_t freq, qemu_irq irq)
147: {
148: arm_timer_state *s;
149: QEMUBH *bh;
150:
151: s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
152: s->irq = irq;
153: s->freq = freq;
154: s->control = TIMER_CTRL_IE;
155:
156: bh = qemu_bh_new(arm_timer_tick, s);
157: s->timer = ptimer_init(bh);
158:
159: return s;
160: }
161:
162:
163:
164:
165:
166:
167: typedef struct {
168: void *timer[2];
169: int level[2];
170: uint32_t base;
171: qemu_irq irq;
172: } sp804_state;
173:
174:
175: static void sp804_set_irq(void *opaque, int irq, int level)
176: {
177: sp804_state *s = (sp804_state *)opaque;
178:
179: s->level[irq] = level;
180: qemu_set_irq(s->irq, s->level[0] || s->level[1]);
181: }
182:
183: static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
184: {
185: sp804_state *s = (sp804_state *)opaque;
186:
187:
188: offset -= s->base;
189: if (offset < 0x20) {
190: return arm_timer_read(s->timer[0], offset);
191: } else {
192: return arm_timer_read(s->timer[1], offset - 0x20);
193: }
194: }
195:
196: static void sp804_write(void *opaque, target_phys_addr_t offset,
197: uint32_t value)
198: {
199: sp804_state *s = (sp804_state *)opaque;
200:
201: offset -= s->base;
202: if (offset < 0x20) {
203: arm_timer_write(s->timer[0], offset, value);
204: } else {
205: arm_timer_write(s->timer[1], offset - 0x20, value);
206: }
207: }
208:
209: static CPUReadMemoryFunc *sp804_readfn[] = {
210: sp804_read,
211: sp804_read,
212: sp804_read
213: };
214:
215: static CPUWriteMemoryFunc *sp804_writefn[] = {
216: sp804_write,
217: sp804_write,
218: sp804_write
219: };
220:
221: void sp804_init(uint32_t base, qemu_irq irq)
222: {
223: int iomemtype;
224: sp804_state *s;
225: qemu_irq *qi;
226:
227: s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
228: qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
229: s->base = base;
230: s->irq = irq;
231:
232:
233: s->timer[0] = arm_timer_init(1000000, qi[0]);
234: s->timer[1] = arm_timer_init(1000000, qi[1]);
235: iomemtype = cpu_register_io_memory(0, sp804_readfn,
236: sp804_writefn, s);
237: cpu_register_physical_memory(base, 0x00001000, iomemtype);
238:
239: }
240:
241:
242:
243:
244: typedef struct {
245: void *timer[3];
246: uint32_t base;
247: } icp_pit_state;
248:
249: static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
250: {
251: icp_pit_state *s = (icp_pit_state *)opaque;
252: int n;
253:
254:
255: offset -= s->base;
256: n = offset >> 8;
257: if (n > 3)
258: cpu_abort(cpu_single_env, "sp804_read: Bad timer %d\n", n);
259:
260: return arm_timer_read(s->timer[n], offset & 0xff);
261: }
262:
263: static void icp_pit_write(void *opaque, target_phys_addr_t offset,
264: uint32_t value)
265: {
266: icp_pit_state *s = (icp_pit_state *)opaque;
267: int n;
268:
269: offset -= s->base;
270: n = offset >> 8;
271: if (n > 3)
272: cpu_abort(cpu_single_env, "sp804_write: Bad timer %d\n", n);
273:
274: arm_timer_write(s->timer[n], offset & 0xff, value);
275: }
276:
277:
278: static CPUReadMemoryFunc *icp_pit_readfn[] = {
279: icp_pit_read,
280: icp_pit_read,
281: icp_pit_read
282: };
283:
284: static CPUWriteMemoryFunc *icp_pit_writefn[] = {
285: icp_pit_write,
286: icp_pit_write,
287: icp_pit_write
288: };
289:
290: void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
291: {
292: int iomemtype;
293: icp_pit_state *s;
294:
295: s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
296: s->base = base;
297:
298: s->timer[0] = arm_timer_init(40000000, pic[irq]);
299:
300: s->timer[1] = arm_timer_init(1000000, pic[irq + 1]);
301: s->timer[2] = arm_timer_init(1000000, pic[irq + 2]);
302:
303: iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
304: icp_pit_writefn, s);
305: cpu_register_physical_memory(base, 0x00001000, iomemtype);
306:
307: }
308: