minor style cleanups
[qemu/ar7.git] / hw / arm / bcm2835_peripherals.c
blob1606a2b6343ab8a701f8dc4c609e613d5255123d
1 /*
2 * Raspberry Pi emulation (c) 2012 Gregory Estrade
3 * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
5 * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
6 * Written by Andrew Baumann
8 * This code is licensed under the GNU GPLv2 and later.
9 */
11 #include "hw/arm/bcm2835_peripherals.h"
12 #include "hw/arm/bcm2835_mbox.h"
13 #include "hw/arm/raspi_platform.h"
14 #include "exec/address-spaces.h"
16 static void bcm2835_peripherals_init(Object *obj)
18 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
19 SysBusDevice *dev;
21 /* Memory region for peripheral devices, which we export to our parent */
22 memory_region_init_io(&s->peri_mr, OBJECT(s), NULL, s,
23 "bcm2835_peripherals", 0x1000000);
24 object_property_add_child(obj, "peripheral_io", OBJECT(&s->peri_mr), NULL);
25 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
27 /* Internal memory region for peripheral bus addresses (not exported) */
28 memory_region_init_io(&s->gpu_bus_mr, OBJECT(s), NULL, s, "bcm2835_gpu_bus",
29 (uint64_t)1 << 32);
30 object_property_add_child(obj, "gpu_bus", OBJECT(&s->gpu_bus_mr), NULL);
32 /* Internal memory region for communication of mailbox channel data */
33 memory_region_init_io(&s->mbox_mr, OBJECT(s), NULL, s, "bcm2835_mbox",
34 MBOX_CHAN_COUNT << 4);
36 /* Interrupt Controller */
37 s->ic = dev = SYS_BUS_DEVICE(object_new("bcm2835_ic"));
38 object_property_add_child(obj, "ic", OBJECT(dev), NULL);
39 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
41 /* UART0 */
42 s->uart0 = dev = SYS_BUS_DEVICE(object_new("pl011"));
43 object_property_add_child(obj, "uart0", OBJECT(dev), NULL);
44 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
46 /* UART1 */
47 s->uart1 = dev = SYS_BUS_DEVICE(object_new("bcm2835_aux"));
48 object_property_add_child(obj, "uart1", OBJECT(dev), NULL);
49 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
51 /* System timer */
52 s->systimer = dev = SYS_BUS_DEVICE(object_new("bcm2835_st"));
53 object_property_add_child(obj, "systimer", OBJECT(dev), NULL);
54 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
56 /* ARM timer */
57 s->armtimer = dev = SYS_BUS_DEVICE(object_new("bcm2835_timer"));
58 object_property_add_child(obj, "armtimer", OBJECT(dev), NULL);
59 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
61 /* USB controller */
62 s->usb = dev = SYS_BUS_DEVICE(object_new("bcm2835_usb"));
63 object_property_add_child(obj, "usb", OBJECT(dev), NULL);
64 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
66 /* MPHI - Message-based Parallel Host Interface */
67 s->mphi = dev = SYS_BUS_DEVICE(object_new("bcm2835_mphi"));
68 object_property_add_child(obj, "mphi", OBJECT(dev), NULL);
69 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
71 /* Semaphores / Doorbells / Mailboxes */
72 s->sbm = dev = SYS_BUS_DEVICE(object_new("bcm2835_sbm"));
73 object_property_add_child(obj, "sbm", OBJECT(dev), NULL);
74 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
76 object_property_add_const_link(OBJECT(dev), "mbox_mr",
77 OBJECT(&s->mbox_mr), &error_abort);
79 /* Power management */
80 s->power = dev = SYS_BUS_DEVICE(object_new("bcm2835_power"));
81 object_property_add_child(obj, "power", OBJECT(dev), NULL);
82 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
84 /* Framebuffer */
85 s->fb = dev = SYS_BUS_DEVICE(object_new("bcm2835_fb"));
86 object_property_add_child(obj, "fb", OBJECT(dev), NULL);
87 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
89 object_property_add_const_link(OBJECT(dev), "dma_mr",
90 OBJECT(&s->gpu_bus_mr), &error_abort);
92 /* Property channel */
93 s->property = dev = SYS_BUS_DEVICE(object_new("bcm2835_property"));
94 object_property_add_child(obj, "property", OBJECT(dev), NULL);
95 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
97 object_property_add_const_link(OBJECT(dev), "bcm2835_fb",
98 OBJECT(s->fb), &error_abort);
99 object_property_add_const_link(OBJECT(dev), "dma_mr",
100 OBJECT(&s->gpu_bus_mr), &error_abort);
102 /* VCHIQ */
103 s->vchiq = dev = SYS_BUS_DEVICE(object_new("bcm2835_vchiq"));
104 object_property_add_child(obj, "vchiq", OBJECT(dev), NULL);
105 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
107 /* Extended Mass Media Controller */
108 s->emmc = dev = SYS_BUS_DEVICE(object_new("bcm2835_emmc"));
109 object_property_add_child(obj, "emmc", OBJECT(dev), NULL);
110 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
112 /* DMA Channels */
113 s->dma = dev = SYS_BUS_DEVICE(object_new("bcm2835_dma"));
114 object_property_add_child(obj, "dma", OBJECT(dev), NULL);
115 qdev_set_parent_bus(DEVICE(dev), sysbus_get_default());
117 object_property_add_const_link(OBJECT(dev), "dma_mr",
118 OBJECT(&s->gpu_bus_mr), &error_abort);
121 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
123 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
124 MemoryRegion *ram;
125 qemu_irq pic[72];
126 qemu_irq mbox_irq[MBOX_CHAN_COUNT];
127 Error *err = NULL;
128 size_t ram_size;
129 int n;
131 /* Map peripherals and RAM into the GPU address space. */
132 memory_region_init_alias(&s->peri_mr_alias, OBJECT(s),
133 "bcm2835_peripherals", &s->peri_mr, 0,
134 memory_region_size(&s->peri_mr));
136 memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE,
137 &s->peri_mr_alias, 1);
139 /* XXX: assume that RAM is contiguous and mapped at system address zero */
140 ram = memory_region_find(get_system_memory(), 0, 1).mr;
141 assert(ram != NULL && memory_region_size(ram) >= 128 * 1024 * 1024);
142 ram_size = memory_region_size(ram);
144 /* RAM is aliased four times (different cache configurations) on the GPU */
145 for (n = 0; n < 4; n++) {
146 memory_region_init_alias(&s->ram_alias[n], OBJECT(s),
147 "bcm2835_gpu_ram_alias[*]", ram, 0, ram_size);
148 memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30,
149 &s->ram_alias[n], 0);
152 /* Interrupt Controller */
153 object_property_set_bool(OBJECT(s->ic), true, "realized", &err);
154 if (err) {
155 error_propagate(errp, err);
156 return;
159 memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
160 sysbus_mmio_get_region(s->ic, 0));
161 sysbus_pass_irq(SYS_BUS_DEVICE(s), s->ic);
163 for (n = 0; n < 72; n++) {
164 pic[n] = qdev_get_gpio_in(DEVICE(s->ic), n);
167 /* UART0 */
168 object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
169 if (err) {
170 error_propagate(errp, err);
171 return;
174 memory_region_add_subregion(&s->peri_mr, UART0_OFFSET,
175 sysbus_mmio_get_region(s->uart0, 0));
176 sysbus_connect_irq(s->uart0, 0, pic[INTERRUPT_VC_UART]);
178 /* UART1 */
179 object_property_set_bool(OBJECT(s->uart1), true, "realized", &err);
180 if (err) {
181 error_propagate(errp, err);
182 return;
185 memory_region_add_subregion(&s->peri_mr, UART1_OFFSET,
186 sysbus_mmio_get_region(s->uart1, 0));
187 sysbus_connect_irq(s->uart1, 0, pic[INTERRUPT_AUX]);
189 /* System timer */
190 object_property_set_bool(OBJECT(s->systimer), true, "realized", &err);
191 if (err) {
192 error_propagate(errp, err);
193 return;
196 memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
197 sysbus_mmio_get_region(s->systimer, 0));
198 sysbus_connect_irq(s->systimer, 0, pic[INTERRUPT_TIMER0]);
199 sysbus_connect_irq(s->systimer, 1, pic[INTERRUPT_TIMER1]);
200 sysbus_connect_irq(s->systimer, 2, pic[INTERRUPT_TIMER2]);
201 sysbus_connect_irq(s->systimer, 3, pic[INTERRUPT_TIMER3]);
203 /* ARM timer */
204 object_property_set_bool(OBJECT(s->armtimer), true, "realized", &err);
205 if (err) {
206 error_propagate(errp, err);
207 return;
210 memory_region_add_subregion(&s->peri_mr, ARMCTRL_TIMER0_1_OFFSET,
211 sysbus_mmio_get_region(s->armtimer, 0));
212 sysbus_connect_irq(s->armtimer, 0, pic[INTERRUPT_ARM_TIMER]);
214 /* USB controller */
215 object_property_set_bool(OBJECT(s->usb), true, "realized", &err);
216 if (err) {
217 error_propagate(errp, err);
218 return;
221 memory_region_add_subregion(&s->peri_mr, USB_OFFSET,
222 sysbus_mmio_get_region(s->usb, 0));
223 sysbus_connect_irq(s->usb, 0, pic[INTERRUPT_VC_USB]);
225 /* MPHI - Message-based Parallel Host Interface */
226 object_property_set_bool(OBJECT(s->mphi), true, "realized", &err);
227 if (err) {
228 error_propagate(errp, err);
229 return;
232 memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET,
233 sysbus_mmio_get_region(s->mphi, 0));
234 sysbus_connect_irq(s->mphi, 0, pic[INTERRUPT_HOSTPORT]);
236 /* Semaphores / Doorbells / Mailboxes */
237 object_property_set_bool(OBJECT(s->sbm), true, "realized", &err);
238 if (err) {
239 error_propagate(errp, err);
240 return;
243 memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET,
244 sysbus_mmio_get_region(s->sbm, 0));
245 sysbus_connect_irq(s->sbm, 0, pic[INTERRUPT_ARM_MAILBOX]);
247 for (n = 0; n < MBOX_CHAN_COUNT; n++) {
248 mbox_irq[n] = qdev_get_gpio_in(DEVICE(s->sbm), n);
251 /* Mailbox-addressable peripherals use the private mbox_mr address space
252 * and pseudo-irqs to dispatch requests and responses. */
254 /* Power management */
255 object_property_set_bool(OBJECT(s->power), true, "realized", &err);
256 if (err) {
257 error_propagate(errp, err);
258 return;
261 memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_POWER<<4,
262 sysbus_mmio_get_region(s->power, 0));
263 sysbus_connect_irq(s->power, 0, mbox_irq[MBOX_CHAN_POWER]);
265 /* Framebuffer */
266 object_property_set_int(OBJECT(s->fb), ram_size - s->vcram_size,
267 "vcram-base", &err);
268 object_property_set_int(OBJECT(s->fb), s->vcram_size, "vcram-size", &err);
270 object_property_set_bool(OBJECT(s->fb), true, "realized", &err);
271 if (err) {
272 error_propagate(errp, err);
273 return;
276 memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB<<4,
277 sysbus_mmio_get_region(s->fb, 0));
278 sysbus_connect_irq(s->fb, 0, mbox_irq[MBOX_CHAN_FB]);
280 /* Property channel */
281 object_property_set_bool(OBJECT(s->property), true, "realized", &err);
282 if (err) {
283 error_propagate(errp, err);
284 return;
287 memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_PROPERTY<<4,
288 sysbus_mmio_get_region(s->property, 0));
289 sysbus_connect_irq(s->property, 0, mbox_irq[MBOX_CHAN_PROPERTY]);
291 /* VCHIQ */
292 object_property_set_bool(OBJECT(s->vchiq), true, "realized", &err);
293 if (err) {
294 error_propagate(errp, err);
295 return;
298 memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_VCHIQ<<4,
299 sysbus_mmio_get_region(s->vchiq, 0));
300 sysbus_connect_irq(s->vchiq, 0, mbox_irq[MBOX_CHAN_VCHIQ]);
302 /* Extended Mass Media Controller */
303 object_property_set_bool(OBJECT(s->emmc), true, "realized", &err);
304 if (err) {
305 error_propagate(errp, err);
306 return;
309 memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET,
310 sysbus_mmio_get_region(s->emmc, 0));
311 sysbus_connect_irq(s->emmc, 0, pic[INTERRUPT_VC_ARASANSDIO]);
313 /* DMA Channels */
314 object_property_set_bool(OBJECT(s->dma), true, "realized", &err);
315 if (err) {
316 error_propagate(errp, err);
317 return;
320 memory_region_add_subregion(&s->peri_mr, DMA_OFFSET,
321 sysbus_mmio_get_region(s->dma, 0));
322 /* XXX: this address was in the original raspi port.
323 * It's unclear where it is derived from. */
324 memory_region_add_subregion(&s->peri_mr, 0xe05000,
325 sysbus_mmio_get_region(s->dma, 1));
327 sysbus_connect_irq(s->dma, 0, pic[INTERRUPT_DMA0]);
328 sysbus_connect_irq(s->dma, 1, pic[INTERRUPT_DMA1]);
329 sysbus_connect_irq(s->dma, 2, pic[INTERRUPT_VC_DMA2]);
330 sysbus_connect_irq(s->dma, 3, pic[INTERRUPT_VC_DMA3]);
331 sysbus_connect_irq(s->dma, 4, pic[INTERRUPT_DMA4]);
332 sysbus_connect_irq(s->dma, 5, pic[INTERRUPT_DMA5]);
333 sysbus_connect_irq(s->dma, 6, pic[INTERRUPT_DMA6]);
334 sysbus_connect_irq(s->dma, 7, pic[INTERRUPT_DMA7]);
335 sysbus_connect_irq(s->dma, 8, pic[INTERRUPT_DMA8]);
336 sysbus_connect_irq(s->dma, 9, pic[INTERRUPT_DMA9]);
337 sysbus_connect_irq(s->dma, 10, pic[INTERRUPT_DMA10]);
338 sysbus_connect_irq(s->dma, 11, pic[INTERRUPT_DMA11]);
339 sysbus_connect_irq(s->dma, 12, pic[INTERRUPT_DMA12]);
342 static Property bcm2835_peripherals_props[] = {
343 DEFINE_PROP_UINT32("vcram-size", BCM2835PeripheralState, vcram_size, 0),
344 DEFINE_PROP_END_OF_LIST()
347 static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
349 DeviceClass *dc = DEVICE_CLASS(oc);
351 dc->props = bcm2835_peripherals_props;
352 dc->realize = bcm2835_peripherals_realize;
355 static const TypeInfo bcm2835_peripherals_type_info = {
356 .name = TYPE_BCM2835_PERIPHERALS,
357 .parent = TYPE_SYS_BUS_DEVICE,
358 .instance_size = sizeof(BCM2835PeripheralState),
359 .instance_init = bcm2835_peripherals_init,
360 .class_init = bcm2835_peripherals_class_init,
363 static void bcm2835_peripherals_register_types(void)
365 type_register_static(&bcm2835_peripherals_type_info);
368 type_init(bcm2835_peripherals_register_types)