1 #include "hw/arm/bcm2836.h"
2 #include "hw/arm/raspi_platform.h"
4 #include "sysemu/sysemu.h" /* for smp_cpus */
5 #include "exec/address-spaces.h"
7 #define DEFAULT_VCRAM_SIZE 0x4000000
9 static void bcm2836_init(Object
*obj
)
11 BCM2836State
*s
= BCM2836(obj
);
15 /* TODO: probably shouldn't be using smp_cpus here */
16 assert(smp_cpus
<= BCM2836_NCPUS
);
17 for (n
= 0; n
< smp_cpus
; n
++) {
18 object_initialize(&s
->cpus
[n
], sizeof(s
->cpus
[n
]),
19 "cortex-a15-" TYPE_ARM_CPU
);
20 object_property_add_child(obj
, "cpu[*]", OBJECT(&s
->cpus
[n
]),
24 s
->ic
= dev
= SYS_BUS_DEVICE(object_new("bcm2836_control"));
25 object_property_add_child(obj
, "ic", OBJECT(dev
), NULL
);
26 qdev_set_parent_bus(DEVICE(dev
), sysbus_get_default());
28 object_initialize(&s
->peripherals
, sizeof(s
->peripherals
),
29 TYPE_BCM2835_PERIPHERALS
);
30 object_property_add_child(obj
, "peripherals", OBJECT(&s
->peripherals
),
32 qdev_set_parent_bus(DEVICE(&s
->peripherals
), sysbus_get_default());
35 static void bcm2836_realize(DeviceState
*dev
, Error
**errp
)
37 BCM2836State
*s
= BCM2836(dev
);
41 /* common peripherals from bcm2835 */
42 object_property_set_bool(OBJECT(&s
->peripherals
), true, "realized", &err
);
44 error_propagate(errp
, err
);
48 sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s
->peripherals
), 0,
49 BCM2836_PERI_BASE
, 1);
51 /* bcm2836 interrupt controller (and mailboxes, etc.) */
52 object_property_set_bool(OBJECT(s
->ic
), true, "realized", &err
);
54 error_propagate(errp
, err
);
58 sysbus_mmio_map(SYS_BUS_DEVICE(s
->ic
), 0, BCM2836_CONTROL_BASE
);
60 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->peripherals
), 0,
61 qdev_get_gpio_in_named(DEVICE(s
->ic
), "gpu_irq", 0));
62 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->peripherals
), 1,
63 qdev_get_gpio_in_named(DEVICE(s
->ic
), "gpu_fiq", 0));
65 /* TODO: probably shouldn't be using smp_cpus here */
66 assert(smp_cpus
<= BCM2836_NCPUS
);
67 for (n
= 0; n
< smp_cpus
; n
++) {
68 /* Mirror bcm2836, which has clusterid set to 0xf */
69 s
->cpus
[n
].mp_affinity
= 0xF00 | n
;
71 /* set periphbase/CBAR value for CPU-local registers */
72 object_property_set_int(OBJECT(&s
->cpus
[n
]),
73 BCM2836_PERI_BASE
+ MCORE_OFFSET
,
76 error_report_err(err
);
80 object_property_set_bool(OBJECT(&s
->cpus
[n
]), true, "realized", &err
);
82 error_report_err(err
);
86 /* Connect irq/fiq outputs from the interrupt controller. */
87 qdev_connect_gpio_out_named(DEVICE(s
->ic
), "irq", n
,
88 qdev_get_gpio_in(DEVICE(&s
->cpus
[n
]),
90 qdev_connect_gpio_out_named(DEVICE(s
->ic
), "fiq", n
,
91 qdev_get_gpio_in(DEVICE(&s
->cpus
[n
]),
94 /* Connect timers from the CPU to the interrupt controller */
95 s
->cpus
[n
].gt_timer_outputs
[GTIMER_PHYS
]
96 = qdev_get_gpio_in_named(DEVICE(s
->ic
), "cntpsirq", 0);
97 s
->cpus
[n
].gt_timer_outputs
[GTIMER_VIRT
]
98 = qdev_get_gpio_in_named(DEVICE(s
->ic
), "cntvirq", 0);
102 static Property bcm2836_props
[] = {
103 DEFINE_PROP_SIZE("vcram-size", BCM2836State
, vcram_size
, DEFAULT_VCRAM_SIZE
),
104 DEFINE_PROP_END_OF_LIST()
107 static void bcm2836_class_init(ObjectClass
*oc
, void *data
)
109 DeviceClass
*dc
= DEVICE_CLASS(oc
);
111 dc
->props
= bcm2836_props
;
112 dc
->realize
= bcm2836_realize
;
115 * Reason: creates an ARM CPU, thus use after free(), see
116 * arm_cpu_class_init()
118 dc
->cannot_destroy_with_object_finalize_yet
= true;
121 static const TypeInfo bcm2836_type_info
= {
122 .name
= TYPE_BCM2836
,
123 .parent
= TYPE_SYS_BUS_DEVICE
,
124 .instance_size
= sizeof(BCM2836State
),
125 .instance_init
= bcm2836_init
,
126 .class_init
= bcm2836_class_init
,
129 static void bcm2836_register_types(void)
131 type_register_static(&bcm2836_type_info
);
134 type_init(bcm2836_register_types
)