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.
11 #include "hw/arm/bcm2835_peripherals.h"
12 #include "hw/misc/bcm2835_mbox_defs.h"
13 #include "hw/arm/raspi_platform.h"
17 /* Peripheral base address on the VC (GPU) system bus */
18 #define BCM2835_VC_PERI_BASE 0x7e000000
20 >>>>>>> upstreaming-raspi
21 /* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
22 #define BCM2835_SDHC_CAPAREG 0x52034b4
24 static void bcm2835_peripherals_init(Object *obj)
26 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
28 /* Memory region for peripheral devices, which we export to our parent */
30 memory_region_init_io(&s->peri_mr, OBJECT(s), NULL, s,
31 "bcm2835_peripherals", 0x1000000);
32 object_property_add_child(obj, "peripheral_io", OBJECT(&s->peri_mr), NULL);
33 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
35 /* Internal memory region for peripheral bus addresses (not exported) */
36 memory_region_init_io(&s->gpu_bus_mr, OBJECT(s), NULL, s, "bcm2835_gpu_bus",
38 object_property_add_child(obj, "gpu_bus", OBJECT(&s->gpu_bus_mr), NULL);
40 /* Internal memory region for communication of mailbox channel data */
41 memory_region_init_io(&s->mbox_mr, OBJECT(s), NULL, s, "bcm2835_mbox",
42 MBOX_CHAN_COUNT << 4);
44 memory_region_init_io(&s->peri_mr, obj, NULL, s, "bcm2835-peripherals",
46 object_property_add_child(obj, "peripheral-io", OBJECT(&s->peri_mr), NULL);
47 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
49 /* Internal memory region for peripheral bus addresses (not exported) */
50 memory_region_init(&s->gpu_bus_mr, obj, "bcm2835-gpu", (uint64_t)1 << 32);
51 object_property_add_child(obj, "gpu-bus", OBJECT(&s->gpu_bus_mr), NULL);
53 /* Internal memory region for request/response communication with
54 * mailbox-addressable peripherals (not exported)
56 memory_region_init(&s->mbox_mr, obj, "bcm2835-mbox",
57 MBOX_CHAN_COUNT << MBOX_AS_CHAN_SHIFT);
58 >>>>>>> upstreaming-raspi
60 /* Interrupt Controller */
61 object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
62 object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
63 qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
66 s->uart0 = SYS_BUS_DEVICE(object_new("pl011"));
67 object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL);
68 qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default());
72 object_initialize(&s->aux, sizeof(s->aux), TYPE_BCM2835_AUX);
73 object_property_add_child(obj, "aux", OBJECT(&s->aux), NULL);
74 qdev_set_parent_bus(DEVICE(&s->aux), sysbus_get_default());
77 object_initialize(&s->st, sizeof(s->st), TYPE_BCM2835_ST);
78 object_property_add_child(obj, "systimer", OBJECT(&s->st), NULL);
79 qdev_set_parent_bus(DEVICE(&s->st), sysbus_get_default());
82 object_initialize(&s->timer, sizeof(s->timer), TYPE_BCM2835_TIMER);
83 object_property_add_child(obj, "armtimer", OBJECT(&s->timer), NULL);
84 qdev_set_parent_bus(DEVICE(&s->timer), sysbus_get_default());
87 object_initialize(&s->usb, sizeof(s->usb), TYPE_BCM2835_USB);
88 object_property_add_child(obj, "usb", OBJECT(&s->usb), NULL);
89 qdev_set_parent_bus(DEVICE(&s->usb), sysbus_get_default());
91 object_property_add_const_link(OBJECT(&s->usb), "dma_mr",
92 OBJECT(&s->gpu_bus_mr), &error_abort);
94 /* MPHI - Message-based Parallel Host Interface */
95 object_initialize(&s->mphi, sizeof(s->mphi), TYPE_BCM2835_MPHI);
96 object_property_add_child(obj, "mphi", OBJECT(&s->mphi), NULL);
97 qdev_set_parent_bus(DEVICE(&s->mphi), sysbus_get_default());
100 >>>>>>> upstreaming-raspi
102 object_initialize(&s->mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX);
103 object_property_add_child(obj, "mbox", OBJECT(&s->mboxes), NULL);
104 qdev_set_parent_bus(DEVICE(&s->mboxes), sysbus_get_default());
107 object_property_add_const_link(OBJECT(&s->mboxes), "mbox_mr",
108 OBJECT(&s->mbox_mr), &error_abort);
110 /* Power management */
111 object_initialize(&s->power, sizeof(s->power), TYPE_BCM2835_POWER);
112 object_property_add_child(obj, "power", OBJECT(&s->power), NULL);
113 qdev_set_parent_bus(DEVICE(&s->power), sysbus_get_default());
116 object_initialize(&s->fb, sizeof(s->fb), TYPE_BCM2835_FB);
117 object_property_add_child(obj, "fb", OBJECT(&s->fb), NULL);
118 object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size",
120 qdev_set_parent_bus(DEVICE(&s->fb), sysbus_get_default());
122 object_property_add_const_link(OBJECT(&s->fb), "dma_mr",
123 OBJECT(&s->gpu_bus_mr), &error_abort);
126 object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr",
127 OBJECT(&s->mbox_mr), &error_abort);
129 >>>>>>> upstreaming-raspi
130 /* Property channel */
131 object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY);
132 object_property_add_child(obj, "property", OBJECT(&s->property), NULL);
133 qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default());
136 object_property_add_const_link(OBJECT(&s->property), "bcm2835_fb",
137 OBJECT(&s->fb), &error_abort);
138 object_property_add_const_link(OBJECT(&s->property), "dma_mr",
140 object_property_add_const_link(OBJECT(&s->property), "dma-mr",
141 >>>>>>> upstreaming-raspi
142 OBJECT(&s->gpu_bus_mr), &error_abort);
144 /* Extended Mass Media Controller */
145 object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
146 object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
147 qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
151 object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
152 object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
153 qdev_set_parent_bus(DEVICE(&s->dma), sysbus_get_default());
155 object_property_add_const_link(OBJECT(&s->dma), "dma_mr",
156 OBJECT(&s->gpu_bus_mr), &error_abort);
159 >>>>>>> upstreaming-raspi
162 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
164 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
168 uint32_t ram_size, vcram_size;
171 /* Map peripherals and RAM into the GPU address space. */
172 memory_region_init_alias(&s->peri_mr_alias, OBJECT(s),
173 "bcm2835_peripherals", &s->peri_mr, 0,
181 obj = object_property_get_link(OBJECT(dev), "ram", &err);
183 error_setg(errp, "%s: required ram link not found: %s",
184 __func__, error_get_pretty(err));
188 ram = MEMORY_REGION(obj);
189 ram_size = memory_region_size(ram);
191 /* Map peripherals and RAM into the GPU address space. */
192 memory_region_init_alias(&s->peri_mr_alias, OBJECT(s),
193 "bcm2835-peripherals", &s->peri_mr, 0,
194 >>>>>>> upstreaming-raspi
195 memory_region_size(&s->peri_mr));
197 memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE,
198 &s->peri_mr_alias, 1);
201 /* XXX: assume that RAM is contiguous and mapped at system address zero */
202 ram = memory_region_find(get_system_memory(), 0, 1).mr;
203 assert(ram != NULL && memory_region_size(ram) >= 128 * 1024 * 1024);
204 ram_size = memory_region_size(ram);
206 /* RAM is aliased four times (different cache configurations) on the GPU */
207 for (n = 0; n < 4; n++) {
208 memory_region_init_alias(&s->ram_alias[n], OBJECT(s),
209 "bcm2835_gpu_ram_alias[*]", ram, 0, ram_size);
211 /* RAM is aliased four times (different cache configurations) on the GPU */
212 for (n = 0; n < 4; n++) {
213 memory_region_init_alias(&s->ram_alias[n], OBJECT(s),
214 "bcm2835-gpu-ram-alias[*]", ram, 0, ram_size);
215 >>>>>>> upstreaming-raspi
216 memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30,
217 &s->ram_alias[n], 0);
220 /* Interrupt Controller */
221 object_property_set_bool(OBJECT(&s->ic), true, "realized", &err);
223 error_propagate(errp, err);
227 memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
228 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
229 sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
232 object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
234 error_propagate(errp, err);
238 memory_region_add_subregion(&s->peri_mr, UART0_OFFSET,
239 sysbus_mmio_get_region(s->uart0, 0));
240 sysbus_connect_irq(s->uart0, 0,
241 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
246 object_property_set_bool(OBJECT(&s->aux), true, "realized", &err);
248 error_propagate(errp, err);
252 memory_region_add_subregion(&s->peri_mr, UART1_OFFSET,
253 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0));
254 sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0,
255 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
259 object_property_set_bool(OBJECT(&s->st), true, "realized", &err);
261 error_propagate(errp, err);
265 memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
266 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->st), 0));
267 sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 0,
268 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
270 sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 1,
271 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
273 sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 2,
274 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
276 sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 3,
277 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
281 object_property_set_bool(OBJECT(&s->timer), true, "realized", &err);
283 error_propagate(errp, err);
287 memory_region_add_subregion(&s->peri_mr, ARMCTRL_TIMER0_1_OFFSET,
288 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer), 0));
289 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0,
290 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
291 INTERRUPT_ARM_TIMER - ARM_IRQ0_BASE)); /* XXX */
294 object_property_set_bool(OBJECT(&s->usb), true, "realized", &err);
296 error_propagate(errp, err);
300 memory_region_add_subregion(&s->peri_mr, USB_OFFSET,
301 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->usb), 0));
302 sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb), 0,
303 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
306 /* MPHI - Message-based Parallel Host Interface */
307 object_property_set_bool(OBJECT(&s->mphi), true, "realized", &err);
309 error_propagate(errp, err);
313 memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET,
314 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0));
315 sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0,
316 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
317 INTERRUPT_HOSTPORT));
320 >>>>>>> upstreaming-raspi
323 object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err);
325 error_propagate(errp, err);
329 memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET,
330 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0));
331 sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0,
332 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
334 INTERRUPT_ARM_MAILBOX - ARM_IRQ0_BASE));
336 /* Mailbox-addressable peripherals use the private mbox_mr address space
337 * and pseudo-irqs to dispatch requests and responses. */
339 /* Power management */
340 object_property_set_bool(OBJECT(&s->power), true, "realized", &err);
342 error_propagate(errp, err);
346 memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_POWER << MBOX_AS_CHAN_SHIFT,
347 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->power), 0));
348 sysbus_connect_irq(SYS_BUS_DEVICE(&s->power), 0,
349 qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_POWER));
352 vcram_size = (uint32_t)object_property_get_int(OBJECT(s), "vcram-size",
355 error_propagate(errp, err);
359 object_property_set_int(OBJECT(&s->fb), ram_size - vcram_size,
362 error_propagate(errp, err);
366 object_property_set_bool(OBJECT(&s->fb), true, "realized", &err);
368 INTERRUPT_ARM_MAILBOX));
370 /* Property channel */
371 object_property_set_int(OBJECT(&s->property), ram_size, "ram-size", &err);
372 >>>>>>> upstreaming-raspi
374 error_propagate(errp, err);
379 memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT,
380 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->fb), 0));
381 sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0,
382 qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB));
384 /* Property channel */
386 >>>>>>> upstreaming-raspi
387 object_property_set_bool(OBJECT(&s->property), true, "realized", &err);
389 error_propagate(errp, err);
393 memory_region_add_subregion(&s->mbox_mr,
394 MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT,
395 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0));
396 sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
397 qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
399 /* Extended Mass Media Controller */
400 object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
403 error_propagate(errp, err);
408 object_property_set_bool(OBJECT(&s->sdhci), true, "bcm2835-quirk", &err);
410 error_propagate(errp, err);
415 >>>>>>> upstreaming-raspi
416 object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
418 error_propagate(errp, err);
422 memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET,
423 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0));
424 sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
425 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
427 INTERRUPT_VC_ARASANSDIO));
430 object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
432 error_propagate(errp, err);
436 memory_region_add_subregion(&s->peri_mr, DMA_OFFSET,
437 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 0));
438 memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET,
439 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1));
441 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 0,
442 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0));
443 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 1,
444 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA1));
445 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 2,
446 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_VC_DMA2));
447 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 3,
448 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_VC_DMA3));
449 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 4,
450 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA4));
451 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 5,
452 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA5));
453 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 6,
454 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA6));
455 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 7,
456 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA7));
457 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 8,
458 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA8));
459 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 9,
460 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA9));
461 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 10,
462 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA10));
463 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 11,
464 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA11));
465 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), 12,
466 qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA12));
468 INTERRUPT_ARASANSDIO));
469 >>>>>>> upstreaming-raspi
472 static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
474 DeviceClass *dc = DEVICE_CLASS(oc);
476 dc->realize = bcm2835_peripherals_realize;
479 static const TypeInfo bcm2835_peripherals_type_info = {
480 .name = TYPE_BCM2835_PERIPHERALS,
481 .parent = TYPE_SYS_BUS_DEVICE,
482 .instance_size = sizeof(BCM2835PeripheralState),
483 .instance_init = bcm2835_peripherals_init,
484 .class_init = bcm2835_peripherals_class_init,
487 static void bcm2835_peripherals_register_types(void)
489 type_register_static(&bcm2835_peripherals_type_info);
492 type_init(bcm2835_peripherals_register_types)