Commit fe7e8758d0abfb6953b5e4f5a1af17ea1598a2bb
1 parent
0027b06d
ARM GIC qdev conversion
Signed-off-by: Paul Brook <paul@codesourcery.com>
Showing
8 changed files
with
168 additions
and
124 deletions
hw/arm-misc.h
... | ... | @@ -34,11 +34,8 @@ struct arm_boot_info { |
34 | 34 | }; |
35 | 35 | void arm_load_kernel(CPUState *env, struct arm_boot_info *info); |
36 | 36 | |
37 | -/* armv7m_nvic.c */ | |
38 | - | |
39 | 37 | /* Multiplication factor to convert from system clock ticks to qemu timer |
40 | 38 | ticks. */ |
41 | 39 | extern int system_clock_scale; |
42 | -qemu_irq *armv7m_nvic_init(CPUState *env); | |
43 | 40 | |
44 | 41 | #endif /* !ARM_MISC_H */ | ... | ... |
hw/arm_gic.c
... | ... | @@ -32,6 +32,9 @@ static const uint8_t gic_id[] = |
32 | 32 | #define GIC_BASE_IRQ 0 |
33 | 33 | #endif |
34 | 34 | |
35 | +#define FROM_SYSBUSGIC(type, dev) \ | |
36 | + DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev)) | |
37 | + | |
35 | 38 | typedef struct gic_irq_state |
36 | 39 | { |
37 | 40 | /* ??? The documentation seems to imply the enable bits are global, even |
... | ... | @@ -74,6 +77,7 @@ typedef struct gic_irq_state |
74 | 77 | |
75 | 78 | typedef struct gic_state |
76 | 79 | { |
80 | + SysBusDevice busdev; | |
77 | 81 | qemu_irq parent_irq[NCPU]; |
78 | 82 | int enabled; |
79 | 83 | int cpu_enabled[NCPU]; |
... | ... | @@ -91,10 +95,7 @@ typedef struct gic_state |
91 | 95 | int running_priority[NCPU]; |
92 | 96 | int current_pending[NCPU]; |
93 | 97 | |
94 | - qemu_irq *in; | |
95 | -#ifdef NVIC | |
96 | - void *nvic; | |
97 | -#endif | |
98 | + int iomemtype; | |
98 | 99 | } gic_state; |
99 | 100 | |
100 | 101 | /* TODO: Many places that call this routine could be optimized. */ |
... | ... | @@ -363,7 +364,7 @@ static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset) |
363 | 364 | uint32_t addr; |
364 | 365 | addr = offset; |
365 | 366 | if (addr < 0x100 || addr > 0xd00) |
366 | - return nvic_readl(s->nvic, addr); | |
367 | + return nvic_readl(s, addr); | |
367 | 368 | #endif |
368 | 369 | val = gic_dist_readw(opaque, offset); |
369 | 370 | val |= gic_dist_readw(opaque, offset + 2) << 16; |
... | ... | @@ -523,7 +524,7 @@ static void gic_dist_writel(void *opaque, target_phys_addr_t offset, |
523 | 524 | uint32_t addr; |
524 | 525 | addr = offset; |
525 | 526 | if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) { |
526 | - nvic_writel(s->nvic, addr, value); | |
527 | + nvic_writel(s, addr, value); | |
527 | 528 | return; |
528 | 529 | } |
529 | 530 | #endif |
... | ... | @@ -716,22 +717,16 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id) |
716 | 717 | return 0; |
717 | 718 | } |
718 | 719 | |
719 | -static gic_state *gic_init(uint32_t dist_base, qemu_irq *parent_irq) | |
720 | +static void gic_init(gic_state *s) | |
720 | 721 | { |
721 | - gic_state *s; | |
722 | - int iomemtype; | |
723 | 722 | int i; |
724 | 723 | |
725 | - s = (gic_state *)qemu_mallocz(sizeof(gic_state)); | |
726 | - s->in = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ); | |
724 | + qdev_init_irq_sink(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32); | |
727 | 725 | for (i = 0; i < NCPU; i++) { |
728 | - s->parent_irq[i] = parent_irq[i]; | |
726 | + sysbus_init_irq(&s->busdev, &s->parent_irq[i]); | |
729 | 727 | } |
730 | - iomemtype = cpu_register_io_memory(0, gic_dist_readfn, | |
731 | - gic_dist_writefn, s); | |
732 | - cpu_register_physical_memory(dist_base, 0x00001000, | |
733 | - iomemtype); | |
728 | + s->iomemtype = cpu_register_io_memory(0, gic_dist_readfn, | |
729 | + gic_dist_writefn, s); | |
734 | 730 | gic_reset(s); |
735 | 731 | register_savevm("arm_gic", -1, 1, gic_save, gic_load, s); |
736 | - return s; | |
737 | 732 | } | ... | ... |
hw/armv7m.c
... | ... | @@ -7,7 +7,7 @@ |
7 | 7 | * This code is licenced under the GPL. |
8 | 8 | */ |
9 | 9 | |
10 | -#include "hw.h" | |
10 | +#include "sysbus.h" | |
11 | 11 | #include "arm-misc.h" |
12 | 12 | #include "sysemu.h" |
13 | 13 | |
... | ... | @@ -140,11 +140,15 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, |
140 | 140 | const char *kernel_filename, const char *cpu_model) |
141 | 141 | { |
142 | 142 | CPUState *env; |
143 | - qemu_irq *pic; | |
143 | + DeviceState *nvic; | |
144 | + /* FIXME: make this local state. */ | |
145 | + static qemu_irq pic[64]; | |
146 | + qemu_irq *cpu_pic; | |
144 | 147 | uint32_t pc; |
145 | 148 | int image_size; |
146 | 149 | uint64_t entry; |
147 | 150 | uint64_t lowaddr; |
151 | + int i; | |
148 | 152 | |
149 | 153 | flash_size *= 1024; |
150 | 154 | sram_size *= 1024; |
... | ... | @@ -176,7 +180,14 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, |
176 | 180 | qemu_ram_alloc(sram_size) | IO_MEM_RAM); |
177 | 181 | armv7m_bitband_init(); |
178 | 182 | |
179 | - pic = armv7m_nvic_init(env); | |
183 | + nvic = qdev_create(NULL, "armv7m_nvic"); | |
184 | + qdev_set_prop_ptr(nvic, "cpu", env); | |
185 | + qdev_init(nvic); | |
186 | + cpu_pic = arm_pic_init_cpu(env); | |
187 | + sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]); | |
188 | + for (i = 0; i < 64; i++) { | |
189 | + pic[i] = qdev_get_irq_sink(nvic, i); | |
190 | + } | |
180 | 191 | |
181 | 192 | image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL); |
182 | 193 | if (image_size < 0) { | ... | ... |
hw/armv7m_nvic.c
... | ... | @@ -10,7 +10,7 @@ |
10 | 10 | * NVIC. Much of that is also implemented here. |
11 | 11 | */ |
12 | 12 | |
13 | -#include "hw.h" | |
13 | +#include "sysbus.h" | |
14 | 14 | #include "qemu-timer.h" |
15 | 15 | #include "arm-misc.h" |
16 | 16 | |
... | ... | @@ -33,13 +33,13 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value); |
33 | 33 | #include "arm_gic.c" |
34 | 34 | |
35 | 35 | typedef struct { |
36 | + gic_state gic; | |
36 | 37 | struct { |
37 | 38 | uint32_t control; |
38 | 39 | uint32_t reload; |
39 | 40 | int64_t tick; |
40 | 41 | QEMUTimer *timer; |
41 | 42 | } systick; |
42 | - gic_state *gic; | |
43 | 43 | } nvic_state; |
44 | 44 | |
45 | 45 | /* qemu timers run at 1GHz. We want something closer to 1MHz. */ |
... | ... | @@ -91,7 +91,7 @@ void armv7m_nvic_set_pending(void *opaque, int irq) |
91 | 91 | nvic_state *s = (nvic_state *)opaque; |
92 | 92 | if (irq >= 16) |
93 | 93 | irq += 16; |
94 | - gic_set_pending_private(s->gic, 0, irq); | |
94 | + gic_set_pending_private(&s->gic, 0, irq); | |
95 | 95 | } |
96 | 96 | |
97 | 97 | /* Make pending IRQ active. */ |
... | ... | @@ -100,7 +100,7 @@ int armv7m_nvic_acknowledge_irq(void *opaque) |
100 | 100 | nvic_state *s = (nvic_state *)opaque; |
101 | 101 | uint32_t irq; |
102 | 102 | |
103 | - irq = gic_acknowledge_irq(s->gic, 0); | |
103 | + irq = gic_acknowledge_irq(&s->gic, 0); | |
104 | 104 | if (irq == 1023) |
105 | 105 | hw_error("Interrupt but no vector\n"); |
106 | 106 | if (irq >= 32) |
... | ... | @@ -113,7 +113,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) |
113 | 113 | nvic_state *s = (nvic_state *)opaque; |
114 | 114 | if (irq >= 16) |
115 | 115 | irq += 16; |
116 | - gic_complete_irq(s->gic, 0, irq); | |
116 | + gic_complete_irq(&s->gic, 0, irq); | |
117 | 117 | } |
118 | 118 | |
119 | 119 | static uint32_t nvic_readl(void *opaque, uint32_t offset) |
... | ... | @@ -153,35 +153,35 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset) |
153 | 153 | return cpu_single_env->cp15.c0_cpuid; |
154 | 154 | case 0xd04: /* Interrypt Control State. */ |
155 | 155 | /* VECTACTIVE */ |
156 | - val = s->gic->running_irq[0]; | |
156 | + val = s->gic.running_irq[0]; | |
157 | 157 | if (val == 1023) { |
158 | 158 | val = 0; |
159 | 159 | } else if (val >= 32) { |
160 | 160 | val -= 16; |
161 | 161 | } |
162 | 162 | /* RETTOBASE */ |
163 | - if (s->gic->running_irq[0] == 1023 | |
164 | - || s->gic->last_active[s->gic->running_irq[0]][0] == 1023) { | |
163 | + if (s->gic.running_irq[0] == 1023 | |
164 | + || s->gic.last_active[s->gic.running_irq[0]][0] == 1023) { | |
165 | 165 | val |= (1 << 11); |
166 | 166 | } |
167 | 167 | /* VECTPENDING */ |
168 | - if (s->gic->current_pending[0] != 1023) | |
169 | - val |= (s->gic->current_pending[0] << 12); | |
168 | + if (s->gic.current_pending[0] != 1023) | |
169 | + val |= (s->gic.current_pending[0] << 12); | |
170 | 170 | /* ISRPENDING */ |
171 | 171 | for (irq = 32; irq < GIC_NIRQ; irq++) { |
172 | - if (s->gic->irq_state[irq].pending) { | |
172 | + if (s->gic.irq_state[irq].pending) { | |
173 | 173 | val |= (1 << 22); |
174 | 174 | break; |
175 | 175 | } |
176 | 176 | } |
177 | 177 | /* PENDSTSET */ |
178 | - if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending) | |
178 | + if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending) | |
179 | 179 | val |= (1 << 26); |
180 | 180 | /* PENDSVSET */ |
181 | - if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending) | |
181 | + if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending) | |
182 | 182 | val |= (1 << 28); |
183 | 183 | /* NMIPENDSET */ |
184 | - if (s->gic->irq_state[ARMV7M_EXCP_NMI].pending) | |
184 | + if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending) | |
185 | 185 | val |= (1 << 31); |
186 | 186 | return val; |
187 | 187 | case 0xd08: /* Vector Table Offset. */ |
... | ... | @@ -197,27 +197,27 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset) |
197 | 197 | case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */ |
198 | 198 | irq = offset - 0xd14; |
199 | 199 | val = 0; |
200 | - val = s->gic->priority1[irq++][0]; | |
201 | - val = s->gic->priority1[irq++][0] << 8; | |
202 | - val = s->gic->priority1[irq++][0] << 16; | |
203 | - val = s->gic->priority1[irq][0] << 24; | |
200 | + val = s->gic.priority1[irq++][0]; | |
201 | + val = s->gic.priority1[irq++][0] << 8; | |
202 | + val = s->gic.priority1[irq++][0] << 16; | |
203 | + val = s->gic.priority1[irq][0] << 24; | |
204 | 204 | return val; |
205 | 205 | case 0xd24: /* System Handler Status. */ |
206 | 206 | val = 0; |
207 | - if (s->gic->irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0); | |
208 | - if (s->gic->irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1); | |
209 | - if (s->gic->irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3); | |
210 | - if (s->gic->irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7); | |
211 | - if (s->gic->irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8); | |
212 | - if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10); | |
213 | - if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11); | |
214 | - if (s->gic->irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12); | |
215 | - if (s->gic->irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13); | |
216 | - if (s->gic->irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14); | |
217 | - if (s->gic->irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15); | |
218 | - if (s->gic->irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16); | |
219 | - if (s->gic->irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17); | |
220 | - if (s->gic->irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18); | |
207 | + if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0); | |
208 | + if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1); | |
209 | + if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3); | |
210 | + if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7); | |
211 | + if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8); | |
212 | + if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10); | |
213 | + if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11); | |
214 | + if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12); | |
215 | + if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13); | |
216 | + if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14); | |
217 | + if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15); | |
218 | + if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16); | |
219 | + if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17); | |
220 | + if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18); | |
221 | 221 | return val; |
222 | 222 | case 0xd28: /* Configurable Fault Status. */ |
223 | 223 | /* TODO: Implement Fault Status. */ |
... | ... | @@ -307,14 +307,14 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) |
307 | 307 | if (value & (1 << 28)) { |
308 | 308 | armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV); |
309 | 309 | } else if (value & (1 << 27)) { |
310 | - s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending = 0; | |
311 | - gic_update(s->gic); | |
310 | + s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0; | |
311 | + gic_update(&s->gic); | |
312 | 312 | } |
313 | 313 | if (value & (1 << 26)) { |
314 | 314 | armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK); |
315 | 315 | } else if (value & (1 << 25)) { |
316 | - s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending = 0; | |
317 | - gic_update(s->gic); | |
316 | + s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0; | |
317 | + gic_update(&s->gic); | |
318 | 318 | } |
319 | 319 | break; |
320 | 320 | case 0xd08: /* Vector Table Offset. */ |
... | ... | @@ -338,19 +338,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) |
338 | 338 | { |
339 | 339 | int irq; |
340 | 340 | irq = offset - 0xd14; |
341 | - s->gic->priority1[irq++][0] = value & 0xff; | |
342 | - s->gic->priority1[irq++][0] = (value >> 8) & 0xff; | |
343 | - s->gic->priority1[irq++][0] = (value >> 16) & 0xff; | |
344 | - s->gic->priority1[irq][0] = (value >> 24) & 0xff; | |
345 | - gic_update(s->gic); | |
341 | + s->gic.priority1[irq++][0] = value & 0xff; | |
342 | + s->gic.priority1[irq++][0] = (value >> 8) & 0xff; | |
343 | + s->gic.priority1[irq++][0] = (value >> 16) & 0xff; | |
344 | + s->gic.priority1[irq][0] = (value >> 24) & 0xff; | |
345 | + gic_update(&s->gic); | |
346 | 346 | } |
347 | 347 | break; |
348 | 348 | case 0xd24: /* System Handler Control. */ |
349 | 349 | /* TODO: Real hardware allows you to set/clear the active bits |
350 | 350 | under some circumstances. We don't implement this. */ |
351 | - s->gic->irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0; | |
352 | - s->gic->irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0; | |
353 | - s->gic->irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0; | |
351 | + s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0; | |
352 | + s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0; | |
353 | + s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0; | |
354 | 354 | break; |
355 | 355 | case 0xd28: /* Configurable Fault Status. */ |
356 | 356 | case 0xd2c: /* Hard Fault Status. */ |
... | ... | @@ -390,19 +390,24 @@ static int nvic_load(QEMUFile *f, void *opaque, int version_id) |
390 | 390 | return 0; |
391 | 391 | } |
392 | 392 | |
393 | -qemu_irq *armv7m_nvic_init(CPUState *env) | |
393 | +static void armv7m_nvic_init(SysBusDevice *dev) | |
394 | 394 | { |
395 | - nvic_state *s; | |
396 | - qemu_irq *parent; | |
395 | + nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev); | |
396 | + CPUState *env; | |
397 | 397 | |
398 | - parent = arm_pic_init_cpu(env); | |
399 | - s = (nvic_state *)qemu_mallocz(sizeof(nvic_state)); | |
400 | - s->gic = gic_init(0xe000e000, &parent[ARM_PIC_CPU_IRQ]); | |
401 | - s->gic->nvic = s; | |
398 | + env = qdev_get_prop_ptr(&dev->qdev, "cpu"); | |
399 | + gic_init(&s->gic); | |
400 | + cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype); | |
402 | 401 | s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s); |
403 | 402 | if (env->v7m.nvic) |
404 | 403 | hw_error("CPU can only have one NVIC\n"); |
405 | 404 | env->v7m.nvic = s; |
406 | 405 | register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s); |
407 | - return s->gic->in; | |
408 | 406 | } |
407 | + | |
408 | +static void armv7m_nvic_register_devices(void) | |
409 | +{ | |
410 | + sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init); | |
411 | +} | |
412 | + | |
413 | +device_init(armv7m_nvic_register_devices) | ... | ... |
hw/mpcore.c
... | ... | @@ -7,9 +7,8 @@ |
7 | 7 | * This code is licenced under the GPL. |
8 | 8 | */ |
9 | 9 | |
10 | -#include "hw.h" | |
10 | +#include "sysbus.h" | |
11 | 11 | #include "qemu-timer.h" |
12 | -#include "primecell.h" | |
13 | 12 | |
14 | 13 | #define MPCORE_PRIV_BASE 0x10100000 |
15 | 14 | #define NCPU 4 |
... | ... | @@ -41,8 +40,9 @@ typedef struct { |
41 | 40 | } mpcore_timer_state; |
42 | 41 | |
43 | 42 | typedef struct mpcore_priv_state { |
44 | - gic_state *gic; | |
43 | + gic_state gic; | |
45 | 44 | uint32_t scu_control; |
45 | + int iomemtype; | |
46 | 46 | mpcore_timer_state timer[8]; |
47 | 47 | } mpcore_priv_state; |
48 | 48 | |
... | ... | @@ -51,7 +51,7 @@ typedef struct mpcore_priv_state { |
51 | 51 | static inline void mpcore_timer_update_irq(mpcore_timer_state *s) |
52 | 52 | { |
53 | 53 | if (s->status & ~s->old_status) { |
54 | - gic_set_pending_private(s->mpcore->gic, s->id >> 1, 29 + (s->id & 1)); | |
54 | + gic_set_pending_private(&s->mpcore->gic, s->id >> 1, 29 + (s->id & 1)); | |
55 | 55 | } |
56 | 56 | s->old_status = s->status; |
57 | 57 | } |
... | ... | @@ -181,7 +181,7 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset) |
181 | 181 | } else { |
182 | 182 | id = (offset - 0x200) >> 8; |
183 | 183 | } |
184 | - return gic_cpu_read(s->gic, id, offset & 0xff); | |
184 | + return gic_cpu_read(&s->gic, id, offset & 0xff); | |
185 | 185 | } else if (offset < 0xb00) { |
186 | 186 | /* Timers. */ |
187 | 187 | if (offset < 0x700) { |
... | ... | @@ -224,7 +224,7 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset, |
224 | 224 | } else { |
225 | 225 | id = (offset - 0x200) >> 8; |
226 | 226 | } |
227 | - gic_cpu_write(s->gic, id, offset & 0xff, value); | |
227 | + gic_cpu_write(&s->gic, id, offset & 0xff, value); | |
228 | 228 | } else if (offset < 0xb00) { |
229 | 229 | /* Timers. */ |
230 | 230 | if (offset < 0x700) { |
... | ... | @@ -255,32 +255,34 @@ static CPUWriteMemoryFunc *mpcore_priv_writefn[] = { |
255 | 255 | mpcore_priv_write |
256 | 256 | }; |
257 | 257 | |
258 | +static void mpcore_priv_map(SysBusDevice *dev, target_phys_addr_t base) | |
259 | +{ | |
260 | + mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev); | |
261 | + cpu_register_physical_memory(base, 0x1000, s->iomemtype); | |
262 | + cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype); | |
263 | +} | |
258 | 264 | |
259 | -static qemu_irq *mpcore_priv_init(uint32_t base, qemu_irq *pic_irq) | |
265 | +static void mpcore_priv_init(SysBusDevice *dev) | |
260 | 266 | { |
261 | - mpcore_priv_state *s; | |
262 | - int iomemtype; | |
267 | + mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev); | |
263 | 268 | int i; |
264 | 269 | |
265 | - s = (mpcore_priv_state *)qemu_mallocz(sizeof(mpcore_priv_state)); | |
266 | - s->gic = gic_init(base + 0x1000, pic_irq); | |
267 | - if (!s->gic) | |
268 | - return NULL; | |
269 | - iomemtype = cpu_register_io_memory(0, mpcore_priv_readfn, | |
270 | - mpcore_priv_writefn, s); | |
271 | - cpu_register_physical_memory(base, 0x00001000, iomemtype); | |
270 | + gic_init(&s->gic); | |
271 | + s->iomemtype = cpu_register_io_memory(0, mpcore_priv_readfn, | |
272 | + mpcore_priv_writefn, s); | |
273 | + sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map); | |
272 | 274 | for (i = 0; i < 8; i++) { |
273 | 275 | mpcore_timer_init(s, &s->timer[i], i); |
274 | 276 | } |
275 | - return s->gic->in; | |
276 | 277 | } |
277 | 278 | |
278 | 279 | /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ |
279 | 280 | controllers. The output of these, plus some of the raw input lines |
280 | 281 | are fed into a single SMP-aware interrupt controller on the CPU. */ |
281 | 282 | typedef struct { |
282 | - qemu_irq *cpuic; | |
283 | - qemu_irq *rvic[4]; | |
283 | + SysBusDevice busdev; | |
284 | + qemu_irq cpuic[32]; | |
285 | + qemu_irq rvic[4][64]; | |
284 | 286 | } mpcore_rirq_state; |
285 | 287 | |
286 | 288 | /* Map baseboard IRQs onto CPU IRQ lines. */ |
... | ... | @@ -307,17 +309,36 @@ static void mpcore_rirq_set_irq(void *opaque, int irq, int level) |
307 | 309 | } |
308 | 310 | } |
309 | 311 | |
310 | -qemu_irq *mpcore_irq_init(qemu_irq *cpu_irq) | |
312 | +static void realview_mpcore_init(SysBusDevice *dev) | |
311 | 313 | { |
312 | - mpcore_rirq_state *s; | |
314 | + mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev); | |
315 | + DeviceState *gic; | |
316 | + DeviceState *priv; | |
313 | 317 | int n; |
318 | + int i; | |
314 | 319 | |
320 | + priv = sysbus_create_simple("arm11mpcore_priv", MPCORE_PRIV_BASE, NULL); | |
321 | + sysbus_pass_irq(dev, sysbus_from_qdev(priv)); | |
322 | + for (i = 0; i < 32; i++) { | |
323 | + s->cpuic[i] = qdev_get_irq_sink(priv, i); | |
324 | + } | |
315 | 325 | /* ??? IRQ routing is hardcoded to "normal" mode. */ |
316 | - s = qemu_mallocz(sizeof(mpcore_rirq_state)); | |
317 | - s->cpuic = mpcore_priv_init(MPCORE_PRIV_BASE, cpu_irq); | |
318 | 326 | for (n = 0; n < 4; n++) { |
319 | - s->rvic[n] = realview_gic_init(0x10040000 + n * 0x10000, | |
320 | - s->cpuic[10 + n]); | |
327 | + gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000, | |
328 | + s->cpuic[10 + n]); | |
329 | + for (i = 0; i < 64; i++) { | |
330 | + s->rvic[n][i] = qdev_get_irq_sink(gic, i); | |
331 | + } | |
321 | 332 | } |
322 | - return qemu_allocate_irqs(mpcore_rirq_set_irq, s, 64); | |
333 | + qdev_init_irq_sink(&dev->qdev, mpcore_rirq_set_irq, 64); | |
323 | 334 | } |
335 | + | |
336 | +static void mpcore_register_devices(void) | |
337 | +{ | |
338 | + sysbus_register_dev("realview_mpcore", sizeof(mpcore_rirq_state), | |
339 | + realview_mpcore_init); | |
340 | + sysbus_register_dev("arm11mpcore_priv", sizeof(mpcore_priv_state), | |
341 | + mpcore_priv_init); | |
342 | +} | |
343 | + | |
344 | +device_init(mpcore_register_devices) | ... | ... |
hw/primecell.h
... | ... | @@ -17,12 +17,6 @@ qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out); |
17 | 17 | /* pl080.c */ |
18 | 18 | void *pl080_init(uint32_t base, qemu_irq irq, int nchannels); |
19 | 19 | |
20 | -/* realview_gic.c */ | |
21 | -qemu_irq *realview_gic_init(uint32_t base, qemu_irq parent_irq); | |
22 | - | |
23 | -/* mpcore.c */ | |
24 | -extern qemu_irq *mpcore_irq_init(qemu_irq *cpu_irq); | |
25 | - | |
26 | 20 | /* arm_sysctl.c */ |
27 | 21 | void arm_sysctl_init(uint32_t base, uint32_t sys_id); |
28 | 22 | ... | ... |
hw/realview.c
... | ... | @@ -31,8 +31,9 @@ static void realview_init(ram_addr_t ram_size, |
31 | 31 | { |
32 | 32 | CPUState *env; |
33 | 33 | ram_addr_t ram_offset; |
34 | - qemu_irq *pic; | |
35 | 34 | DeviceState *dev; |
35 | + qemu_irq *irqp; | |
36 | + qemu_irq pic[64]; | |
36 | 37 | PCIBus *pci_bus; |
37 | 38 | NICInfo *nd; |
38 | 39 | int n; |
... | ... | @@ -55,8 +56,8 @@ static void realview_init(ram_addr_t ram_size, |
55 | 56 | fprintf(stderr, "Unable to find CPU definition\n"); |
56 | 57 | exit(1); |
57 | 58 | } |
58 | - pic = arm_pic_init_cpu(env); | |
59 | - cpu_irq[n] = pic[ARM_PIC_CPU_IRQ]; | |
59 | + irqp = arm_pic_init_cpu(env); | |
60 | + cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; | |
60 | 61 | if (n > 0) { |
61 | 62 | /* Set entry point for secondary CPUs. This assumes we're using |
62 | 63 | the init code from arm_boot.c. Real hardware resets all CPUs |
... | ... | @@ -76,9 +77,14 @@ static void realview_init(ram_addr_t ram_size, |
76 | 77 | /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3 |
77 | 78 | is nIRQ (there are inconsistencies). However Linux 2.6.17 expects |
78 | 79 | GIC1 to be nIRQ and ignores all the others, so do that for now. */ |
79 | - pic = realview_gic_init(0x10040000, cpu_irq[0]); | |
80 | + dev = sysbus_create_simple("realview_gic", 0x10040000, cpu_irq[0]); | |
80 | 81 | } else { |
81 | - pic = mpcore_irq_init(cpu_irq); | |
82 | + dev = sysbus_create_varargs("realview_mpcore", -1, | |
83 | + cpu_irq[0], cpu_irq[1], cpu_irq[2], | |
84 | + cpu_irq[3], NULL); | |
85 | + } | |
86 | + for (n = 0; n < 64; n++) { | |
87 | + pic[n] = qdev_get_irq_sink(dev, n); | |
82 | 88 | } |
83 | 89 | |
84 | 90 | sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]); | ... | ... |
hw/realview_gic.c
... | ... | @@ -7,8 +7,7 @@ |
7 | 7 | * This code is licenced under the GPL. |
8 | 8 | */ |
9 | 9 | |
10 | -#include "hw.h" | |
11 | -#include "primecell.h" | |
10 | +#include "sysbus.h" | |
12 | 11 | |
13 | 12 | #define GIC_NIRQ 96 |
14 | 13 | #define NCPU 1 |
... | ... | @@ -22,6 +21,11 @@ gic_get_current_cpu(void) |
22 | 21 | |
23 | 22 | #include "arm_gic.c" |
24 | 23 | |
24 | +typedef struct { | |
25 | + gic_state gic; | |
26 | + int iomemtype; | |
27 | +} RealViewGICState; | |
28 | + | |
25 | 29 | static uint32_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset) |
26 | 30 | { |
27 | 31 | gic_state *s = (gic_state *)opaque; |
... | ... | @@ -47,16 +51,27 @@ static CPUWriteMemoryFunc *realview_gic_cpu_writefn[] = { |
47 | 51 | realview_gic_cpu_write |
48 | 52 | }; |
49 | 53 | |
50 | -qemu_irq *realview_gic_init(uint32_t base, qemu_irq parent_irq) | |
54 | +static void realview_gic_map(SysBusDevice *dev, target_phys_addr_t base) | |
51 | 55 | { |
52 | - gic_state *s; | |
53 | - int iomemtype; | |
56 | + RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev); | |
57 | + cpu_register_physical_memory(base, 0x1000, s->iomemtype); | |
58 | + cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype); | |
59 | +} | |
60 | + | |
61 | +static void realview_gic_init(SysBusDevice *dev) | |
62 | +{ | |
63 | + RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev); | |
54 | 64 | |
55 | - s = gic_init(base + 0x1000, &parent_irq); | |
56 | - if (!s) | |
57 | - return NULL; | |
58 | - iomemtype = cpu_register_io_memory(0, realview_gic_cpu_readfn, | |
59 | - realview_gic_cpu_writefn, s); | |
60 | - cpu_register_physical_memory(base, 0x00001000, iomemtype); | |
61 | - return s->in; | |
65 | + gic_init(&s->gic); | |
66 | + s->iomemtype = cpu_register_io_memory(0, realview_gic_cpu_readfn, | |
67 | + realview_gic_cpu_writefn, s); | |
68 | + sysbus_init_mmio_cb(dev, 0x2000, realview_gic_map); | |
62 | 69 | } |
70 | + | |
71 | +static void realview_gic_register_devices(void) | |
72 | +{ | |
73 | + sysbus_register_dev("realview_gic", sizeof(RealViewGICState), | |
74 | + realview_gic_init); | |
75 | +} | |
76 | + | |
77 | +device_init(realview_gic_register_devices) | ... | ... |