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/bcm2836.h"
12 #include "hw/arm/raspi_platform.h"
13 #include "hw/sysbus.h"
14 #include "sysemu/sysemu.h" /* for smp_cpus */
15 #include "exec/address-spaces.h"
19 /* Peripheral base address seen by the CPU */
20 #define BCM2836_PERI_BASE 0x3F000000
22 /* "QA7" (Pi2) interrupt controller and mailboxes etc. */
23 #define BCM2836_CONTROL_BASE 0x40000000
25 >>>>>>> upstreaming-raspi
26 static void bcm2836_init(Object *obj)
28 BCM2836State *s = BCM2836(obj);
31 /* TODO: probably shouldn't be using smp_cpus here */
32 assert(smp_cpus <= BCM2836_NCPUS);
33 for (n = 0; n < smp_cpus; n++) {
34 object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
35 "cortex-a15-" TYPE_ARM_CPU);
36 object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
40 object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2836_CONTROL);
41 object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
42 qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
44 object_initialize(&s->peripherals, sizeof(s->peripherals),
45 TYPE_BCM2835_PERIPHERALS);
46 object_property_add_child(obj, "peripherals", OBJECT(&s->peripherals),
49 object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals),
50 "vcram-size", &error_abort);
52 >>>>>>> upstreaming-raspi
53 qdev_set_parent_bus(DEVICE(&s->peripherals), sysbus_get_default());
56 static void bcm2836_realize(DeviceState *dev, Error **errp)
58 BCM2836State *s = BCM2836(dev);
62 >>>>>>> upstreaming-raspi
66 /* common peripherals from bcm2835 */
69 obj = object_property_get_link(OBJECT(dev), "ram", &err);
71 error_setg(errp, "%s: required ram link not found: %s",
72 __func__, error_get_pretty(err));
76 object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj, &err);
78 error_propagate(errp, err);
82 >>>>>>> upstreaming-raspi
83 object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err);
85 error_propagate(errp, err);
89 sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
90 BCM2836_PERI_BASE, 1);
92 /* bcm2836 interrupt controller (and mailboxes, etc.) */
93 object_property_set_bool(OBJECT(&s->ic), true, "realized", &err);
95 error_propagate(errp, err);
99 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ic), 0, BCM2836_CONTROL_BASE);
101 sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
102 qdev_get_gpio_in_named(DEVICE(&s->ic), "gpu_irq", 0));
103 sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
104 qdev_get_gpio_in_named(DEVICE(&s->ic), "gpu_fiq", 0));
106 /* TODO: probably shouldn't be using smp_cpus here */
107 assert(smp_cpus <= BCM2836_NCPUS);
108 for (n = 0; n < smp_cpus; n++) {
109 /* Mirror bcm2836, which has clusterid set to 0xf */
110 s->cpus[n].mp_affinity = 0xF00 | n;
112 /* set periphbase/CBAR value for CPU-local registers */
113 object_property_set_int(OBJECT(&s->cpus[n]),
114 BCM2836_PERI_BASE + MCORE_OFFSET,
117 error_report_err(err);
121 object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err);
123 error_report_err(err);
127 /* Connect irq/fiq outputs from the interrupt controller. */
128 qdev_connect_gpio_out_named(DEVICE(&s->ic), "irq", n,
129 qdev_get_gpio_in(DEVICE(&s->cpus[n]),
131 qdev_connect_gpio_out_named(DEVICE(&s->ic), "fiq", n,
132 qdev_get_gpio_in(DEVICE(&s->cpus[n]),
135 /* Connect timers from the CPU to the interrupt controller */
136 s->cpus[n].gt_timer_outputs[GTIMER_PHYS]
137 = qdev_get_gpio_in_named(DEVICE(&s->ic), "cntpsirq", 0);
138 s->cpus[n].gt_timer_outputs[GTIMER_VIRT]
139 = qdev_get_gpio_in_named(DEVICE(&s->ic), "cntvirq", 0);
143 static void bcm2836_class_init(ObjectClass *oc, void *data)
145 DeviceClass *dc = DEVICE_CLASS(oc);
147 dc->realize = bcm2836_realize;
150 * Reason: creates an ARM CPU, thus use after free(), see
151 * arm_cpu_class_init()
153 dc->cannot_destroy_with_object_finalize_yet = true;
156 static const TypeInfo bcm2836_type_info = {
157 .name = TYPE_BCM2836,
158 .parent = TYPE_SYS_BUS_DEVICE,
159 .instance_size = sizeof(BCM2836State),
160 .instance_init = bcm2836_init,
161 .class_init = bcm2836_class_init,
164 static void bcm2836_register_types(void)
166 type_register_static(&bcm2836_type_info);
169 type_init(bcm2836_register_types)