2 * Raspberry Pi 4B emulation
4 * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinnikov@auriga.com>
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "qemu/osdep.h"
10 #include "qemu/units.h"
11 #include "qemu/cutils.h"
12 #include "qapi/error.h"
13 #include "qapi/visitor.h"
14 #include "hw/arm/raspi_platform.h"
15 #include "hw/display/bcm2835_fb.h"
16 #include "hw/registerfields.h"
17 #include "qemu/error-report.h"
18 #include "sysemu/device_tree.h"
19 #include "hw/boards.h"
20 #include "hw/loader.h"
21 #include "hw/arm/boot.h"
22 #include "qom/object.h"
23 #include "hw/arm/bcm2838.h"
26 #define TYPE_RASPI4B_MACHINE MACHINE_TYPE_NAME("raspi4b")
27 OBJECT_DECLARE_SIMPLE_TYPE(Raspi4bMachineState
, RASPI4B_MACHINE
)
29 struct Raspi4bMachineState
{
30 RaspiBaseMachineState parent_obj
;
35 * Add second memory region if board RAM amount exceeds VC base address
36 * (see https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf
39 static int raspi_add_memory_node(void *fdt
, hwaddr mem_base
, hwaddr mem_len
)
42 uint32_t acells
, scells
;
43 char *nodename
= g_strdup_printf("/memory@%" PRIx64
, mem_base
);
45 acells
= qemu_fdt_getprop_cell(fdt
, "/", "#address-cells",
47 scells
= qemu_fdt_getprop_cell(fdt
, "/", "#size-cells",
49 if (acells
== 0 || scells
== 0) {
50 fprintf(stderr
, "dtb file invalid (#address-cells or #size-cells 0)\n");
53 qemu_fdt_add_subnode(fdt
, nodename
);
54 qemu_fdt_setprop_string(fdt
, nodename
, "device_type", "memory");
55 ret
= qemu_fdt_setprop_sized_cells(fdt
, nodename
, "reg",
64 static void raspi4_modify_dtb(const struct arm_boot_info
*info
, void *fdt
)
68 /* Temporarily disable following devices until they are implemented */
69 const char *nodes_to_remove
[] = {
71 "brcm,bcm2711-rng200",
72 "brcm,bcm2711-thermal",
73 "brcm,bcm2711-genet-v5",
76 for (int i
= 0; i
< ARRAY_SIZE(nodes_to_remove
); i
++) {
77 const char *dev_str
= nodes_to_remove
[i
];
79 int offset
= fdt_node_offset_by_compatible(fdt
, -1, dev_str
);
81 if (!fdt_nop_node(fdt
, offset
)) {
82 warn_report("bcm2711 dtc: %s has been disabled!", dev_str
);
87 ram_size
= board_ram_size(info
->board_id
);
89 if (info
->ram_size
> UPPER_RAM_BASE
) {
90 raspi_add_memory_node(fdt
, UPPER_RAM_BASE
, ram_size
- UPPER_RAM_BASE
);
94 static void raspi4b_machine_init(MachineState
*machine
)
96 Raspi4bMachineState
*s
= RASPI4B_MACHINE(machine
);
97 RaspiBaseMachineState
*s_base
= RASPI_BASE_MACHINE(machine
);
98 RaspiBaseMachineClass
*mc
= RASPI_BASE_MACHINE_GET_CLASS(machine
);
99 BCM2838State
*soc
= &s
->soc
;
101 s_base
->binfo
.modify_dtb
= raspi4_modify_dtb
;
102 s_base
->binfo
.board_id
= mc
->board_rev
;
104 object_initialize_child(OBJECT(machine
), "soc", soc
,
105 board_soc_type(mc
->board_rev
));
107 raspi_base_machine_init(machine
, &soc
->parent_obj
);
110 static void raspi4b_machine_class_init(ObjectClass
*oc
, void *data
)
112 MachineClass
*mc
= MACHINE_CLASS(oc
);
113 RaspiBaseMachineClass
*rmc
= RASPI_BASE_MACHINE_CLASS(oc
);
115 #if HOST_LONG_BITS == 32
116 rmc
->board_rev
= 0xa03111; /* Revision 1.1, 1 Gb RAM */
118 rmc
->board_rev
= 0xb03115; /* Revision 1.5, 2 Gb RAM */
120 raspi_machine_class_common_init(mc
, rmc
->board_rev
);
121 mc
->init
= raspi4b_machine_init
;
124 static const TypeInfo raspi4b_machine_type
= {
125 .name
= TYPE_RASPI4B_MACHINE
,
126 .parent
= TYPE_RASPI_BASE_MACHINE
,
127 .instance_size
= sizeof(Raspi4bMachineState
),
128 .class_init
= raspi4b_machine_class_init
,
131 static void raspi4b_machine_register_type(void)
133 type_register_static(&raspi4b_machine_type
);
136 type_init(raspi4b_machine_register_type
)