1
2
3
4
5
6
7
8
9
10
11#include "qemu/osdep.h"
12#include "qapi/error.h"
13#include "hw/cpu/a9mpcore.h"
14#include "qom/cpu.h"
15
16static void a9mp_priv_set_irq(void *opaque, int irq, int level)
17{
18 A9MPPrivState *s = (A9MPPrivState *)opaque;
19
20 qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
21}
22
23static void a9mp_priv_initfn(Object *obj)
24{
25 A9MPPrivState *s = A9MPCORE_PRIV(obj);
26
27 memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000);
28 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container);
29
30 object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU);
31 qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
32
33 object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
34 qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
35
36 object_initialize(&s->gtimer, sizeof(s->gtimer), TYPE_A9_GTIMER);
37 qdev_set_parent_bus(DEVICE(&s->gtimer), sysbus_get_default());
38
39 object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
40 qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
41
42 object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ARM_MPTIMER);
43 qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
44}
45
46static void a9mp_priv_realize(DeviceState *dev, Error **errp)
47{
48 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
49 A9MPPrivState *s = A9MPCORE_PRIV(dev);
50 DeviceState *scudev, *gicdev, *gtimerdev, *mptimerdev, *wdtdev;
51 SysBusDevice *scubusdev, *gicbusdev, *gtimerbusdev, *mptimerbusdev,
52 *wdtbusdev;
53 Error *err = NULL;
54 int i;
55
56
57
58
59 scudev = DEVICE(&s->scu);
60 qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
61 object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
62 if (err != NULL) {
63 error_propagate(errp, err);
64 return;
65 }
66 scubusdev = SYS_BUS_DEVICE(&s->scu);
67
68 gicdev = DEVICE(&s->gic);
69 qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
70 qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
71
72
73
74
75
76
77
78
79
80
81
82 object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
83 if (err != NULL) {
84 error_propagate(errp, err);
85 return;
86 }
87 gicbusdev = SYS_BUS_DEVICE(&s->gic);
88
89
90 sysbus_pass_irq(sbd, gicbusdev);
91
92
93 qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32);
94
95 gtimerdev = DEVICE(&s->gtimer);
96 qdev_prop_set_uint32(gtimerdev, "num-cpu", s->num_cpu);
97 object_property_set_bool(OBJECT(&s->gtimer), true, "realized", &err);
98 if (err != NULL) {
99 error_propagate(errp, err);
100 return;
101 }
102 gtimerbusdev = SYS_BUS_DEVICE(&s->gtimer);
103
104 mptimerdev = DEVICE(&s->mptimer);
105 qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
106 object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
107 if (err != NULL) {
108 error_propagate(errp, err);
109 return;
110 }
111 mptimerbusdev = SYS_BUS_DEVICE(&s->mptimer);
112
113 wdtdev = DEVICE(&s->wdt);
114 qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu);
115 object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
116 if (err != NULL) {
117 error_propagate(errp, err);
118 return;
119 }
120 wdtbusdev = SYS_BUS_DEVICE(&s->wdt);
121
122
123
124
125
126
127
128
129
130
131 memory_region_add_subregion(&s->container, 0,
132 sysbus_mmio_get_region(scubusdev, 0));
133
134 memory_region_add_subregion(&s->container, 0x100,
135 sysbus_mmio_get_region(gicbusdev, 1));
136 memory_region_add_subregion(&s->container, 0x200,
137 sysbus_mmio_get_region(gtimerbusdev, 0));
138
139
140
141 memory_region_add_subregion(&s->container, 0x600,
142 sysbus_mmio_get_region(mptimerbusdev, 0));
143 memory_region_add_subregion(&s->container, 0x620,
144 sysbus_mmio_get_region(wdtbusdev, 0));
145 memory_region_add_subregion(&s->container, 0x1000,
146 sysbus_mmio_get_region(gicbusdev, 0));
147
148
149
150
151
152 for (i = 0; i < s->num_cpu; i++) {
153 int ppibase = (s->num_irq - 32) + i * 32;
154 sysbus_connect_irq(gtimerbusdev, i,
155 qdev_get_gpio_in(gicdev, ppibase + 27));
156 sysbus_connect_irq(mptimerbusdev, i,
157 qdev_get_gpio_in(gicdev, ppibase + 29));
158 sysbus_connect_irq(wdtbusdev, i,
159 qdev_get_gpio_in(gicdev, ppibase + 30));
160 }
161}
162
163static Property a9mp_priv_properties[] = {
164 DEFINE_PROP_UINT32("num-cpu", A9MPPrivState, num_cpu, 1),
165
166
167
168
169
170
171 DEFINE_PROP_UINT32("num-irq", A9MPPrivState, num_irq, 96),
172 DEFINE_PROP_END_OF_LIST(),
173};
174
175static void a9mp_priv_class_init(ObjectClass *klass, void *data)
176{
177 DeviceClass *dc = DEVICE_CLASS(klass);
178
179 dc->realize = a9mp_priv_realize;
180 dc->props = a9mp_priv_properties;
181}
182
183static const TypeInfo a9mp_priv_info = {
184 .name = TYPE_A9MPCORE_PRIV,
185 .parent = TYPE_SYS_BUS_DEVICE,
186 .instance_size = sizeof(A9MPPrivState),
187 .instance_init = a9mp_priv_initfn,
188 .class_init = a9mp_priv_class_init,
189};
190
191static void a9mp_register_types(void)
192{
193 type_register_static(&a9mp_priv_info);
194}
195
196type_init(a9mp_register_types)
197