root / hw / arm11mpcore.c @ 74382217
History | View | Annotate | Download (3.2 kB)
1 |
/*
|
---|---|
2 |
* ARM11MPCore internal peripheral emulation.
|
3 |
*
|
4 |
* Copyright (c) 2006-2007 CodeSourcery.
|
5 |
* Written by Paul Brook
|
6 |
*
|
7 |
* This code is licenced under the GPL.
|
8 |
*/
|
9 |
|
10 |
/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
|
11 |
(+ 32 internal). However my test chip only exposes/reports 32.
|
12 |
More importantly Linux falls over if more than 32 are present! */
|
13 |
#define GIC_NIRQ 64 |
14 |
#include "mpcore.c" |
15 |
|
16 |
/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
|
17 |
controllers. The output of these, plus some of the raw input lines
|
18 |
are fed into a single SMP-aware interrupt controller on the CPU. */
|
19 |
typedef struct { |
20 |
SysBusDevice busdev; |
21 |
SysBusDevice *priv; |
22 |
qemu_irq cpuic[32];
|
23 |
qemu_irq rvic[4][64]; |
24 |
uint32_t num_cpu; |
25 |
} mpcore_rirq_state; |
26 |
|
27 |
/* Map baseboard IRQs onto CPU IRQ lines. */
|
28 |
static const int mpcore_irq_map[32] = { |
29 |
-1, -1, -1, -1, 1, 2, -1, -1, |
30 |
-1, -1, 6, -1, 4, 5, -1, -1, |
31 |
-1, 14, 15, 0, 7, 8, -1, -1, |
32 |
-1, -1, -1, -1, 9, 3, -1, -1, |
33 |
}; |
34 |
|
35 |
static void mpcore_rirq_set_irq(void *opaque, int irq, int level) |
36 |
{ |
37 |
mpcore_rirq_state *s = (mpcore_rirq_state *)opaque; |
38 |
int i;
|
39 |
|
40 |
for (i = 0; i < 4; i++) { |
41 |
qemu_set_irq(s->rvic[i][irq], level); |
42 |
} |
43 |
if (irq < 32) { |
44 |
irq = mpcore_irq_map[irq]; |
45 |
if (irq >= 0) { |
46 |
qemu_set_irq(s->cpuic[irq], level); |
47 |
} |
48 |
} |
49 |
} |
50 |
|
51 |
static void mpcore_rirq_map(SysBusDevice *dev, target_phys_addr_t base) |
52 |
{ |
53 |
mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev); |
54 |
sysbus_mmio_map(s->priv, 0, base);
|
55 |
} |
56 |
|
57 |
static int realview_mpcore_init(SysBusDevice *dev) |
58 |
{ |
59 |
mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev); |
60 |
DeviceState *gic; |
61 |
DeviceState *priv; |
62 |
int n;
|
63 |
int i;
|
64 |
|
65 |
priv = qdev_create(NULL, "arm11mpcore_priv"); |
66 |
qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
|
67 |
qdev_init_nofail(priv); |
68 |
s->priv = sysbus_from_qdev(priv); |
69 |
sysbus_pass_irq(dev, s->priv); |
70 |
for (i = 0; i < 32; i++) { |
71 |
s->cpuic[i] = qdev_get_gpio_in(priv, i); |
72 |
} |
73 |
/* ??? IRQ routing is hardcoded to "normal" mode. */
|
74 |
for (n = 0; n < 4; n++) { |
75 |
gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000, |
76 |
s->cpuic[10 + n]);
|
77 |
for (i = 0; i < 64; i++) { |
78 |
s->rvic[n][i] = qdev_get_gpio_in(gic, i); |
79 |
} |
80 |
} |
81 |
qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
|
82 |
sysbus_init_mmio_cb(dev, 0x2000, mpcore_rirq_map);
|
83 |
return 0; |
84 |
} |
85 |
|
86 |
static SysBusDeviceInfo mpcore_rirq_info = {
|
87 |
.init = realview_mpcore_init, |
88 |
.qdev.name = "realview_mpcore",
|
89 |
.qdev.size = sizeof(mpcore_rirq_state),
|
90 |
.qdev.props = (Property[]) { |
91 |
DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1), |
92 |
DEFINE_PROP_END_OF_LIST(), |
93 |
} |
94 |
}; |
95 |
|
96 |
static SysBusDeviceInfo mpcore_priv_info = {
|
97 |
.init = mpcore_priv_init, |
98 |
.qdev.name = "arm11mpcore_priv",
|
99 |
.qdev.size = sizeof(mpcore_priv_state),
|
100 |
.qdev.props = (Property[]) { |
101 |
DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1), |
102 |
DEFINE_PROP_END_OF_LIST(), |
103 |
} |
104 |
}; |
105 |
|
106 |
static void arm11mpcore_register_devices(void) |
107 |
{ |
108 |
sysbus_register_withprop(&mpcore_rirq_info); |
109 |
sysbus_register_withprop(&mpcore_priv_info); |
110 |
} |
111 |
|
112 |
device_init(arm11mpcore_register_devices) |