]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/bcm2836.c
hw/arm/bcm2836: QOM'ify more by adding class_init() to each SoC type
[mirror_qemu.git] / hw / arm / bcm2836.c
CommitLineData
bad56236
AB
1/*
2 * Raspberry Pi emulation (c) 2012 Gregory Estrade
3 * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
4 *
5 * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
6 * Written by Andrew Baumann
7 *
6111a0c0
PMD
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
bad56236
AB
10 */
11
c964b660 12#include "qemu/osdep.h"
da34e65c 13#include "qapi/error.h"
0b8fa32f 14#include "qemu/module.h"
4771d756 15#include "cpu.h"
bad56236
AB
16#include "hw/arm/bcm2836.h"
17#include "hw/arm/raspi_platform.h"
18#include "hw/sysbus.h"
bad56236 19
58b35028
PMD
20typedef struct BCM283XClass {
21 /*< private >*/
22 DeviceClass parent_class;
23 /*< public >*/
0fd74f03 24 const char *name;
210f4784 25 const char *cpu_type;
d0567e94
PMD
26 hwaddr peri_base; /* Peripheral base address seen by the CPU */
27 hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
1bcb4d16 28 int clusterid;
34d1a4f5 29} BCM283XClass;
0fd74f03 30
58b35028
PMD
31#define BCM283X_CLASS(klass) \
32 OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
33#define BCM283X_GET_CLASS(obj) \
34 OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
35
bad56236
AB
36static void bcm2836_init(Object *obj)
37{
926dcdf0 38 BCM283XState *s = BCM283X(obj);
210f4784 39 BCM283XClass *bc = BCM283X_GET_CLASS(obj);
210f4784
PM
40 int n;
41
42 for (n = 0; n < BCM283X_NCPUS; n++) {
5e5e9ed6 43 object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
34d1a4f5 44 bc->cpu_type);
210f4784 45 }
bad56236 46
db873cc5 47 object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
bad56236 48
db873cc5
MA
49 object_initialize_child(obj, "peripherals", &s->peripherals,
50 TYPE_BCM2835_PERIPHERALS);
f0afa731 51 object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals),
d2623129 52 "board-rev");
5e9c2a8d 53 object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals),
d2623129 54 "vcram-size");
bad56236
AB
55}
56
57static void bcm2836_realize(DeviceState *dev, Error **errp)
58{
926dcdf0 59 BCM283XState *s = BCM283X(dev);
1bcb4d16 60 BCM283XClass *bc = BCM283X_GET_CLASS(dev);
bad56236 61 Object *obj;
bad56236
AB
62 int n;
63
64 /* common peripherals from bcm2835 */
65
4d21fcd5 66 obj = object_property_get_link(OBJECT(dev), "ram", &error_abort);
bad56236 67
d2623129 68 object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj);
bad56236 69
668f62ec 70 if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) {
bad56236
AB
71 return;
72 }
73
a55b53a2 74 object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals),
d2623129 75 "sd-bus");
a55b53a2 76
bad56236 77 sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
34d1a4f5 78 bc->peri_base, 1);
bad56236
AB
79
80 /* bcm2836 interrupt controller (and mailboxes, etc.) */
668f62ec 81 if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
bad56236
AB
82 return;
83 }
84
34d1a4f5 85 sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, bc->ctrl_base);
bad56236
AB
86
87 sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
88 qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
89 sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
90 qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
91
926dcdf0 92 for (n = 0; n < BCM283X_NCPUS; n++) {
1bcb4d16 93 /* TODO: this should be converted to a property of ARM_CPU */
34d1a4f5 94 s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
bad56236
AB
95
96 /* set periphbase/CBAR value for CPU-local registers */
778a2dc5 97 if (!object_property_set_int(OBJECT(&s->cpu[n].core), "reset-cbar",
34d1a4f5 98 bc->peri_base, errp)) {
bad56236
AB
99 return;
100 }
101
102 /* start powered off if not enabled */
778a2dc5
MA
103 if (!object_property_set_bool(OBJECT(&s->cpu[n].core),
104 "start-powered-off",
105 n >= s->enabled_cpus,
668f62ec 106 errp)) {
bad56236
AB
107 return;
108 }
109
668f62ec 110 if (!qdev_realize(DEVICE(&s->cpu[n].core), NULL, errp)) {
bad56236
AB
111 return;
112 }
113
114 /* Connect irq/fiq outputs from the interrupt controller. */
115 qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n,
5e5e9ed6 116 qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_IRQ));
bad56236 117 qdev_connect_gpio_out_named(DEVICE(&s->control), "fiq", n,
5e5e9ed6 118 qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_FIQ));
bad56236
AB
119
120 /* Connect timers from the CPU to the interrupt controller */
5e5e9ed6 121 qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_PHYS,
0dc19823 122 qdev_get_gpio_in_named(DEVICE(&s->control), "cntpnsirq", n));
5e5e9ed6 123 qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_VIRT,
bad56236 124 qdev_get_gpio_in_named(DEVICE(&s->control), "cntvirq", n));
5e5e9ed6 125 qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_HYP,
0dc19823 126 qdev_get_gpio_in_named(DEVICE(&s->control), "cnthpirq", n));
5e5e9ed6 127 qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_SEC,
0dc19823 128 qdev_get_gpio_in_named(DEVICE(&s->control), "cntpsirq", n));
bad56236
AB
129 }
130}
131
132static Property bcm2836_props[] = {
926dcdf0
PM
133 DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
134 BCM283X_NCPUS),
bad56236
AB
135 DEFINE_PROP_END_OF_LIST()
136};
137
0fd74f03 138static void bcm283x_class_init(ObjectClass *oc, void *data)
bad56236
AB
139{
140 DeviceClass *dc = DEVICE_CLASS(oc);
141
cccf96c3
TH
142 /* Reason: Must be wired up in code (see raspi_init() function) */
143 dc->user_creatable = false;
bad56236
AB
144}
145
34d1a4f5
PMD
146static void bcm2836_class_init(ObjectClass *oc, void *data)
147{
148 DeviceClass *dc = DEVICE_CLASS(oc);
149 BCM283XClass *bc = BCM283X_CLASS(oc);
150
151 bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
152 bc->peri_base = 0x3f000000;
153 bc->ctrl_base = 0x40000000;
154 bc->clusterid = 0xf;
155 dc->realize = bcm2836_realize;
156 device_class_set_props(dc, bcm2836_props);
bad56236
AB
157};
158
34d1a4f5
PMD
159#ifdef TARGET_AARCH64
160static void bcm2837_class_init(ObjectClass *oc, void *data)
bad56236 161{
34d1a4f5
PMD
162 DeviceClass *dc = DEVICE_CLASS(oc);
163 BCM283XClass *bc = BCM283X_CLASS(oc);
164
165 bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
166 bc->peri_base = 0x3f000000;
167 bc->ctrl_base = 0x40000000;
168 bc->clusterid = 0x0;
169 dc->realize = bcm2836_realize;
170 device_class_set_props(dc, bcm2836_props);
171};
172#endif
173
174static const TypeInfo bcm283x_types[] = {
175 {
176 .name = TYPE_BCM2836,
177 .parent = TYPE_BCM283X,
178 .class_init = bcm2836_class_init,
179#ifdef TARGET_AARCH64
180 }, {
181 .name = TYPE_BCM2837,
182 .parent = TYPE_BCM283X,
183 .class_init = bcm2837_class_init,
184#endif
185 }, {
186 .name = TYPE_BCM283X,
187 .parent = TYPE_DEVICE,
188 .instance_size = sizeof(BCM283XState),
189 .instance_init = bcm2836_init,
190 .class_size = sizeof(BCM283XClass),
191 .class_init = bcm283x_class_init,
192 .abstract = true,
0fd74f03 193 }
34d1a4f5 194};
bad56236 195
34d1a4f5 196DEFINE_TYPES(bcm283x_types)