* Raspberry Pi 3 emulation Copyright (c) 2018 Zoltán Baldaszti
* Upstream code cleanup (c) 2018 Pekka Enberg
*
- * This code is licensed under the GNU GPLv2 and later.
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
#define MACH_TYPE_BCM2708 3138
-typedef struct RasPiState {
+typedef struct RaspiMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+ /*< public >*/
BCM283XState soc;
- MemoryRegion ram;
-} RasPiState;
+} RaspiMachineState;
+
+typedef struct RaspiMachineClass {
+ /*< private >*/
+ MachineClass parent_obj;
+ /*< public >*/
+ uint32_t board_rev;
+} RaspiMachineClass;
+
+#define TYPE_RASPI_MACHINE MACHINE_TYPE_NAME("raspi-common")
+#define RASPI_MACHINE(obj) \
+ OBJECT_CHECK(RaspiMachineState, (obj), TYPE_RASPI_MACHINE)
+
+#define RASPI_MACHINE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(RaspiMachineClass, (klass), TYPE_RASPI_MACHINE)
+#define RASPI_MACHINE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(RaspiMachineClass, (obj), TYPE_RASPI_MACHINE)
/*
* Board revision codes:
return board_processor_id(board_rev) + 1;
}
+static const char *board_soc_type(uint32_t board_rev)
+{
+ static const char *soc_types[] = {
+ NULL, TYPE_BCM2836, TYPE_BCM2837,
+ };
+ int proc_id = board_processor_id(board_rev);
+
+ if (proc_id >= ARRAY_SIZE(soc_types) || !soc_types[proc_id]) {
+ error_report("Unsupported processor id '%d' (board revision: 0x%x)",
+ proc_id, board_rev);
+ exit(1);
+ }
+ return soc_types[proc_id];
+}
+
+static int cores_count(uint32_t board_rev)
+{
+ static const int soc_cores_count[] = {
+ 0, BCM283X_NCPUS, BCM283X_NCPUS,
+ };
+ int proc_id = board_processor_id(board_rev);
+
+ if (proc_id >= ARRAY_SIZE(soc_cores_count) || !soc_cores_count[proc_id]) {
+ error_report("Unsupported processor id '%d' (board revision: 0x%x)",
+ proc_id, board_rev);
+ exit(1);
+ }
+ return soc_cores_count[proc_id];
+}
+
+static const char *board_type(uint32_t board_rev)
+{
+ static const char *types[] = {
+ "A", "B", "A+", "B+", "2B", "Alpha", "CM1", NULL, "3B", "Zero",
+ "CM3", NULL, "Zero W", "3B+", "3A+", NULL, "CM3+", "4B",
+ };
+ assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
+ int bt = FIELD_EX32(board_rev, REV_CODE, TYPE);
+ if (bt >= ARRAY_SIZE(types) || !types[bt]) {
+ return "Unknown";
+ }
+ return types[bt];
+}
+
static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
{
static const uint32_t smpboot[] = {
arm_load_kernel(ARM_CPU(first_cpu), machine, &binfo);
}
-static void raspi_init(MachineState *machine, uint32_t board_rev)
+static void raspi_machine_init(MachineState *machine)
{
- RasPiState *s = g_new0(RasPiState, 1);
+ RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine);
+ RaspiMachineState *s = RASPI_MACHINE(machine);
+ uint32_t board_rev = mc->board_rev;
int version = board_version(board_rev);
uint64_t ram_size = board_ram_size(board_rev);
uint32_t vcram_size;
exit(1);
}
- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
- version == 3 ? TYPE_BCM2837 : TYPE_BCM2836,
- &error_abort, NULL);
-
- /* Allocate and map RAM */
- memory_region_allocate_system_memory(&s->ram, OBJECT(machine), "ram",
- machine->ram_size);
/* FIXME: Remove when we have custom CPU address space support */
- memory_region_add_subregion_overlap(get_system_memory(), 0, &s->ram, 0);
+ memory_region_add_subregion_overlap(get_system_memory(), 0,
+ machine->ram, 0);
/* Setup the SOC */
- object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
- &error_abort);
- object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
+ object_initialize_child(OBJECT(machine), "soc", &s->soc,
+ board_soc_type(board_rev));
+ object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram));
+ object_property_set_int(OBJECT(&s->soc), "board-rev", board_rev,
&error_abort);
- object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);
+ qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
/* Create and plug in the SD cards */
di = drive_get_next(IF_SD);
error_report("No SD bus found in SOC object");
exit(1);
}
- carddev = qdev_create(bus, TYPE_SD_CARD);
- qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
- object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
+ carddev = qdev_new(TYPE_SD_CARD);
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
&error_abort);
setup_boot(machine, version, machine->ram_size - vcram_size);
}
-static void raspi2_init(MachineState *machine)
+static void raspi_machine_class_init(ObjectClass *oc, void *data)
{
- raspi_init(machine, 0xa21041);
-}
+ MachineClass *mc = MACHINE_CLASS(oc);
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
+ uint32_t board_rev = (uint32_t)(uintptr_t)data;
-static void raspi2_machine_init(MachineClass *mc)
-{
- mc->desc = "Raspberry Pi 2B";
- mc->init = raspi2_init;
+ rmc->board_rev = board_rev;
+ mc->desc = g_strdup_printf("Raspberry Pi %s", board_type(board_rev));
+ mc->init = raspi_machine_init;
mc->block_default_type = IF_SD;
mc->no_parallel = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
- mc->max_cpus = BCM283X_NCPUS;
- mc->min_cpus = BCM283X_NCPUS;
- mc->default_cpus = BCM283X_NCPUS;
- mc->default_ram_size = 1 * GiB;
- mc->ignore_memory_transaction_failures = true;
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = cores_count(board_rev);
+ mc->default_ram_size = board_ram_size(board_rev);
+ mc->default_ram_id = "ram";
+ if (board_version(board_rev) == 2) {
+ mc->ignore_memory_transaction_failures = true;
+ }
};
-DEFINE_MACHINE("raspi2", raspi2_machine_init)
+static const TypeInfo raspi_machine_types[] = {
+ {
+ .name = MACHINE_TYPE_NAME("raspi2"),
+ .parent = TYPE_RASPI_MACHINE,
+ .class_init = raspi_machine_class_init,
+ .class_data = (void *)0xa21041,
#ifdef TARGET_AARCH64
-static void raspi3_init(MachineState *machine)
-{
- raspi_init(machine, 0xa02082);
-}
-
-static void raspi3_machine_init(MachineClass *mc)
-{
- mc->desc = "Raspberry Pi 3B";
- mc->init = raspi3_init;
- mc->block_default_type = IF_SD;
- mc->no_parallel = 1;
- mc->no_floppy = 1;
- mc->no_cdrom = 1;
- mc->max_cpus = BCM283X_NCPUS;
- mc->min_cpus = BCM283X_NCPUS;
- mc->default_cpus = BCM283X_NCPUS;
- mc->default_ram_size = 1 * GiB;
-}
-DEFINE_MACHINE("raspi3", raspi3_machine_init)
+ }, {
+ .name = MACHINE_TYPE_NAME("raspi3"),
+ .parent = TYPE_RASPI_MACHINE,
+ .class_init = raspi_machine_class_init,
+ .class_data = (void *)0xa02082,
#endif
+ }, {
+ .name = TYPE_RASPI_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(RaspiMachineState),
+ .class_size = sizeof(RaspiMachineClass),
+ .abstract = true,
+ }
+};
+
+DEFINE_TYPES(raspi_machine_types)