Commit fe7e8758d0abfb6953b5e4f5a1af17ea1598a2bb

Authored by Paul Brook
1 parent 0027b06d

ARM GIC qdev conversion

Signed-off-by: Paul Brook <paul@codesourcery.com>
hw/arm-misc.h
@@ -34,11 +34,8 @@ struct arm_boot_info { @@ -34,11 +34,8 @@ struct arm_boot_info {
34 }; 34 };
35 void arm_load_kernel(CPUState *env, struct arm_boot_info *info); 35 void arm_load_kernel(CPUState *env, struct arm_boot_info *info);
36 36
37 -/* armv7m_nvic.c */  
38 -  
39 /* Multiplication factor to convert from system clock ticks to qemu timer 37 /* Multiplication factor to convert from system clock ticks to qemu timer
40 ticks. */ 38 ticks. */
41 extern int system_clock_scale; 39 extern int system_clock_scale;
42 -qemu_irq *armv7m_nvic_init(CPUState *env);  
43 40
44 #endif /* !ARM_MISC_H */ 41 #endif /* !ARM_MISC_H */
hw/arm_gic.c
@@ -32,6 +32,9 @@ static const uint8_t gic_id[] = @@ -32,6 +32,9 @@ static const uint8_t gic_id[] =
32 #define GIC_BASE_IRQ 0 32 #define GIC_BASE_IRQ 0
33 #endif 33 #endif
34 34
  35 +#define FROM_SYSBUSGIC(type, dev) \
  36 + DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
  37 +
35 typedef struct gic_irq_state 38 typedef struct gic_irq_state
36 { 39 {
37 /* ??? The documentation seems to imply the enable bits are global, even 40 /* ??? The documentation seems to imply the enable bits are global, even
@@ -74,6 +77,7 @@ typedef struct gic_irq_state @@ -74,6 +77,7 @@ typedef struct gic_irq_state
74 77
75 typedef struct gic_state 78 typedef struct gic_state
76 { 79 {
  80 + SysBusDevice busdev;
77 qemu_irq parent_irq[NCPU]; 81 qemu_irq parent_irq[NCPU];
78 int enabled; 82 int enabled;
79 int cpu_enabled[NCPU]; 83 int cpu_enabled[NCPU];
@@ -91,10 +95,7 @@ typedef struct gic_state @@ -91,10 +95,7 @@ typedef struct gic_state
91 int running_priority[NCPU]; 95 int running_priority[NCPU];
92 int current_pending[NCPU]; 96 int current_pending[NCPU];
93 97
94 - qemu_irq *in;  
95 -#ifdef NVIC  
96 - void *nvic;  
97 -#endif 98 + int iomemtype;
98 } gic_state; 99 } gic_state;
99 100
100 /* TODO: Many places that call this routine could be optimized. */ 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,7 +364,7 @@ static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
363 uint32_t addr; 364 uint32_t addr;
364 addr = offset; 365 addr = offset;
365 if (addr < 0x100 || addr > 0xd00) 366 if (addr < 0x100 || addr > 0xd00)
366 - return nvic_readl(s->nvic, addr); 367 + return nvic_readl(s, addr);
367 #endif 368 #endif
368 val = gic_dist_readw(opaque, offset); 369 val = gic_dist_readw(opaque, offset);
369 val |= gic_dist_readw(opaque, offset + 2) << 16; 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,7 +524,7 @@ static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
523 uint32_t addr; 524 uint32_t addr;
524 addr = offset; 525 addr = offset;
525 if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) { 526 if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
526 - nvic_writel(s->nvic, addr, value); 527 + nvic_writel(s, addr, value);
527 return; 528 return;
528 } 529 }
529 #endif 530 #endif
@@ -716,22 +717,16 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id) @@ -716,22 +717,16 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
716 return 0; 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 int i; 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 for (i = 0; i < NCPU; i++) { 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 gic_reset(s); 730 gic_reset(s);
735 register_savevm("arm_gic", -1, 1, gic_save, gic_load, s); 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 +7,7 @@
7 * This code is licenced under the GPL. 7 * This code is licenced under the GPL.
8 */ 8 */
9 9
10 -#include "hw.h" 10 +#include "sysbus.h"
11 #include "arm-misc.h" 11 #include "arm-misc.h"
12 #include "sysemu.h" 12 #include "sysemu.h"
13 13
@@ -140,11 +140,15 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, @@ -140,11 +140,15 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
140 const char *kernel_filename, const char *cpu_model) 140 const char *kernel_filename, const char *cpu_model)
141 { 141 {
142 CPUState *env; 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 uint32_t pc; 147 uint32_t pc;
145 int image_size; 148 int image_size;
146 uint64_t entry; 149 uint64_t entry;
147 uint64_t lowaddr; 150 uint64_t lowaddr;
  151 + int i;
148 152
149 flash_size *= 1024; 153 flash_size *= 1024;
150 sram_size *= 1024; 154 sram_size *= 1024;
@@ -176,7 +180,14 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, @@ -176,7 +180,14 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
176 qemu_ram_alloc(sram_size) | IO_MEM_RAM); 180 qemu_ram_alloc(sram_size) | IO_MEM_RAM);
177 armv7m_bitband_init(); 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 image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL); 192 image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
182 if (image_size < 0) { 193 if (image_size < 0) {
hw/armv7m_nvic.c
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 * NVIC. Much of that is also implemented here. 10 * NVIC. Much of that is also implemented here.
11 */ 11 */
12 12
13 -#include "hw.h" 13 +#include "sysbus.h"
14 #include "qemu-timer.h" 14 #include "qemu-timer.h"
15 #include "arm-misc.h" 15 #include "arm-misc.h"
16 16
@@ -33,13 +33,13 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value); @@ -33,13 +33,13 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value);
33 #include "arm_gic.c" 33 #include "arm_gic.c"
34 34
35 typedef struct { 35 typedef struct {
  36 + gic_state gic;
36 struct { 37 struct {
37 uint32_t control; 38 uint32_t control;
38 uint32_t reload; 39 uint32_t reload;
39 int64_t tick; 40 int64_t tick;
40 QEMUTimer *timer; 41 QEMUTimer *timer;
41 } systick; 42 } systick;
42 - gic_state *gic;  
43 } nvic_state; 43 } nvic_state;
44 44
45 /* qemu timers run at 1GHz. We want something closer to 1MHz. */ 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,7 +91,7 @@ void armv7m_nvic_set_pending(void *opaque, int irq)
91 nvic_state *s = (nvic_state *)opaque; 91 nvic_state *s = (nvic_state *)opaque;
92 if (irq >= 16) 92 if (irq >= 16)
93 irq += 16; 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 /* Make pending IRQ active. */ 97 /* Make pending IRQ active. */
@@ -100,7 +100,7 @@ int armv7m_nvic_acknowledge_irq(void *opaque) @@ -100,7 +100,7 @@ int armv7m_nvic_acknowledge_irq(void *opaque)
100 nvic_state *s = (nvic_state *)opaque; 100 nvic_state *s = (nvic_state *)opaque;
101 uint32_t irq; 101 uint32_t irq;
102 102
103 - irq = gic_acknowledge_irq(s->gic, 0); 103 + irq = gic_acknowledge_irq(&s->gic, 0);
104 if (irq == 1023) 104 if (irq == 1023)
105 hw_error("Interrupt but no vector\n"); 105 hw_error("Interrupt but no vector\n");
106 if (irq >= 32) 106 if (irq >= 32)
@@ -113,7 +113,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) @@ -113,7 +113,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
113 nvic_state *s = (nvic_state *)opaque; 113 nvic_state *s = (nvic_state *)opaque;
114 if (irq >= 16) 114 if (irq >= 16)
115 irq += 16; 115 irq += 16;
116 - gic_complete_irq(s->gic, 0, irq); 116 + gic_complete_irq(&s->gic, 0, irq);
117 } 117 }
118 118
119 static uint32_t nvic_readl(void *opaque, uint32_t offset) 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,35 +153,35 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
153 return cpu_single_env->cp15.c0_cpuid; 153 return cpu_single_env->cp15.c0_cpuid;
154 case 0xd04: /* Interrypt Control State. */ 154 case 0xd04: /* Interrypt Control State. */
155 /* VECTACTIVE */ 155 /* VECTACTIVE */
156 - val = s->gic->running_irq[0]; 156 + val = s->gic.running_irq[0];
157 if (val == 1023) { 157 if (val == 1023) {
158 val = 0; 158 val = 0;
159 } else if (val >= 32) { 159 } else if (val >= 32) {
160 val -= 16; 160 val -= 16;
161 } 161 }
162 /* RETTOBASE */ 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 val |= (1 << 11); 165 val |= (1 << 11);
166 } 166 }
167 /* VECTPENDING */ 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 /* ISRPENDING */ 170 /* ISRPENDING */
171 for (irq = 32; irq < GIC_NIRQ; irq++) { 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 val |= (1 << 22); 173 val |= (1 << 22);
174 break; 174 break;
175 } 175 }
176 } 176 }
177 /* PENDSTSET */ 177 /* PENDSTSET */
178 - if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending) 178 + if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
179 val |= (1 << 26); 179 val |= (1 << 26);
180 /* PENDSVSET */ 180 /* PENDSVSET */
181 - if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending) 181 + if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
182 val |= (1 << 28); 182 val |= (1 << 28);
183 /* NMIPENDSET */ 183 /* NMIPENDSET */
184 - if (s->gic->irq_state[ARMV7M_EXCP_NMI].pending) 184 + if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
185 val |= (1 << 31); 185 val |= (1 << 31);
186 return val; 186 return val;
187 case 0xd08: /* Vector Table Offset. */ 187 case 0xd08: /* Vector Table Offset. */
@@ -197,27 +197,27 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset) @@ -197,27 +197,27 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
197 case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */ 197 case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
198 irq = offset - 0xd14; 198 irq = offset - 0xd14;
199 val = 0; 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 return val; 204 return val;
205 case 0xd24: /* System Handler Status. */ 205 case 0xd24: /* System Handler Status. */
206 val = 0; 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 return val; 221 return val;
222 case 0xd28: /* Configurable Fault Status. */ 222 case 0xd28: /* Configurable Fault Status. */
223 /* TODO: Implement Fault Status. */ 223 /* TODO: Implement Fault Status. */
@@ -307,14 +307,14 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) @@ -307,14 +307,14 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
307 if (value & (1 << 28)) { 307 if (value & (1 << 28)) {
308 armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV); 308 armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
309 } else if (value & (1 << 27)) { 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 if (value & (1 << 26)) { 313 if (value & (1 << 26)) {
314 armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK); 314 armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
315 } else if (value & (1 << 25)) { 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 break; 319 break;
320 case 0xd08: /* Vector Table Offset. */ 320 case 0xd08: /* Vector Table Offset. */
@@ -338,19 +338,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) @@ -338,19 +338,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
338 { 338 {
339 int irq; 339 int irq;
340 irq = offset - 0xd14; 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 break; 347 break;
348 case 0xd24: /* System Handler Control. */ 348 case 0xd24: /* System Handler Control. */
349 /* TODO: Real hardware allows you to set/clear the active bits 349 /* TODO: Real hardware allows you to set/clear the active bits
350 under some circumstances. We don't implement this. */ 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 break; 354 break;
355 case 0xd28: /* Configurable Fault Status. */ 355 case 0xd28: /* Configurable Fault Status. */
356 case 0xd2c: /* Hard Fault Status. */ 356 case 0xd2c: /* Hard Fault Status. */
@@ -390,19 +390,24 @@ static int nvic_load(QEMUFile *f, void *opaque, int version_id) @@ -390,19 +390,24 @@ static int nvic_load(QEMUFile *f, void *opaque, int version_id)
390 return 0; 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 s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s); 401 s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
403 if (env->v7m.nvic) 402 if (env->v7m.nvic)
404 hw_error("CPU can only have one NVIC\n"); 403 hw_error("CPU can only have one NVIC\n");
405 env->v7m.nvic = s; 404 env->v7m.nvic = s;
406 register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s); 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,9 +7,8 @@
7 * This code is licenced under the GPL. 7 * This code is licenced under the GPL.
8 */ 8 */
9 9
10 -#include "hw.h" 10 +#include "sysbus.h"
11 #include "qemu-timer.h" 11 #include "qemu-timer.h"
12 -#include "primecell.h"  
13 12
14 #define MPCORE_PRIV_BASE 0x10100000 13 #define MPCORE_PRIV_BASE 0x10100000
15 #define NCPU 4 14 #define NCPU 4
@@ -41,8 +40,9 @@ typedef struct { @@ -41,8 +40,9 @@ typedef struct {
41 } mpcore_timer_state; 40 } mpcore_timer_state;
42 41
43 typedef struct mpcore_priv_state { 42 typedef struct mpcore_priv_state {
44 - gic_state *gic; 43 + gic_state gic;
45 uint32_t scu_control; 44 uint32_t scu_control;
  45 + int iomemtype;
46 mpcore_timer_state timer[8]; 46 mpcore_timer_state timer[8];
47 } mpcore_priv_state; 47 } mpcore_priv_state;
48 48
@@ -51,7 +51,7 @@ typedef struct mpcore_priv_state { @@ -51,7 +51,7 @@ typedef struct mpcore_priv_state {
51 static inline void mpcore_timer_update_irq(mpcore_timer_state *s) 51 static inline void mpcore_timer_update_irq(mpcore_timer_state *s)
52 { 52 {
53 if (s->status & ~s->old_status) { 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 s->old_status = s->status; 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,7 +181,7 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
181 } else { 181 } else {
182 id = (offset - 0x200) >> 8; 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 } else if (offset < 0xb00) { 185 } else if (offset < 0xb00) {
186 /* Timers. */ 186 /* Timers. */
187 if (offset < 0x700) { 187 if (offset < 0x700) {
@@ -224,7 +224,7 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset, @@ -224,7 +224,7 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
224 } else { 224 } else {
225 id = (offset - 0x200) >> 8; 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 } else if (offset < 0xb00) { 228 } else if (offset < 0xb00) {
229 /* Timers. */ 229 /* Timers. */
230 if (offset < 0x700) { 230 if (offset < 0x700) {
@@ -255,32 +255,34 @@ static CPUWriteMemoryFunc *mpcore_priv_writefn[] = { @@ -255,32 +255,34 @@ static CPUWriteMemoryFunc *mpcore_priv_writefn[] = {
255 mpcore_priv_write 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 int i; 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 for (i = 0; i < 8; i++) { 274 for (i = 0; i < 8; i++) {
273 mpcore_timer_init(s, &s->timer[i], i); 275 mpcore_timer_init(s, &s->timer[i], i);
274 } 276 }
275 - return s->gic->in;  
276 } 277 }
277 278
278 /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ 279 /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
279 controllers. The output of these, plus some of the raw input lines 280 controllers. The output of these, plus some of the raw input lines
280 are fed into a single SMP-aware interrupt controller on the CPU. */ 281 are fed into a single SMP-aware interrupt controller on the CPU. */
281 typedef struct { 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 } mpcore_rirq_state; 286 } mpcore_rirq_state;
285 287
286 /* Map baseboard IRQs onto CPU IRQ lines. */ 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,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 int n; 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 /* ??? IRQ routing is hardcoded to "normal" mode. */ 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 for (n = 0; n < 4; n++) { 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,12 +17,6 @@ qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out);
17 /* pl080.c */ 17 /* pl080.c */
18 void *pl080_init(uint32_t base, qemu_irq irq, int nchannels); 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 /* arm_sysctl.c */ 20 /* arm_sysctl.c */
27 void arm_sysctl_init(uint32_t base, uint32_t sys_id); 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,8 +31,9 @@ static void realview_init(ram_addr_t ram_size,
31 { 31 {
32 CPUState *env; 32 CPUState *env;
33 ram_addr_t ram_offset; 33 ram_addr_t ram_offset;
34 - qemu_irq *pic;  
35 DeviceState *dev; 34 DeviceState *dev;
  35 + qemu_irq *irqp;
  36 + qemu_irq pic[64];
36 PCIBus *pci_bus; 37 PCIBus *pci_bus;
37 NICInfo *nd; 38 NICInfo *nd;
38 int n; 39 int n;
@@ -55,8 +56,8 @@ static void realview_init(ram_addr_t ram_size, @@ -55,8 +56,8 @@ static void realview_init(ram_addr_t ram_size,
55 fprintf(stderr, "Unable to find CPU definition\n"); 56 fprintf(stderr, "Unable to find CPU definition\n");
56 exit(1); 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 if (n > 0) { 61 if (n > 0) {
61 /* Set entry point for secondary CPUs. This assumes we're using 62 /* Set entry point for secondary CPUs. This assumes we're using
62 the init code from arm_boot.c. Real hardware resets all CPUs 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,9 +77,14 @@ static void realview_init(ram_addr_t ram_size,
76 /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3 77 /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3
77 is nIRQ (there are inconsistencies). However Linux 2.6.17 expects 78 is nIRQ (there are inconsistencies). However Linux 2.6.17 expects
78 GIC1 to be nIRQ and ignores all the others, so do that for now. */ 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 } else { 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 sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]); 90 sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
hw/realview_gic.c
@@ -7,8 +7,7 @@ @@ -7,8 +7,7 @@
7 * This code is licenced under the GPL. 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 #define GIC_NIRQ 96 12 #define GIC_NIRQ 96
14 #define NCPU 1 13 #define NCPU 1
@@ -22,6 +21,11 @@ gic_get_current_cpu(void) @@ -22,6 +21,11 @@ gic_get_current_cpu(void)
22 21
23 #include "arm_gic.c" 22 #include "arm_gic.c"
24 23
  24 +typedef struct {
  25 + gic_state gic;
  26 + int iomemtype;
  27 +} RealViewGICState;
  28 +
25 static uint32_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset) 29 static uint32_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset)
26 { 30 {
27 gic_state *s = (gic_state *)opaque; 31 gic_state *s = (gic_state *)opaque;
@@ -47,16 +51,27 @@ static CPUWriteMemoryFunc *realview_gic_cpu_writefn[] = { @@ -47,16 +51,27 @@ static CPUWriteMemoryFunc *realview_gic_cpu_writefn[] = {
47 realview_gic_cpu_write 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)