Signed-off-by: Sergey Kambalin <sergey.kamba...@auriga.com> --- hw/arm/bcm2838.c | 110 +++++++++++++++++++++++++++ hw/arm/bcm2838_peripherals.c | 72 ++++++++++++++++++ hw/arm/meson.build | 2 + include/hw/arm/bcm2838.h | 26 +++++++ include/hw/arm/bcm2838_peripherals.h | 36 +++++++++ 5 files changed, 246 insertions(+) create mode 100644 hw/arm/bcm2838.c create mode 100644 hw/arm/bcm2838_peripherals.c create mode 100644 include/hw/arm/bcm2838.h create mode 100644 include/hw/arm/bcm2838_peripherals.h
diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c new file mode 100644 index 0000000000..dd650c8148 --- /dev/null +++ b/hw/arm/bcm2838.c @@ -0,0 +1,110 @@ +/* + * BCM2838 SoC emulation + * + * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinni...@auriga.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "hw/arm/raspi_platform.h" +#include "hw/sysbus.h" +#include "hw/arm/bcm2838.h" +#include "trace.h" + +struct BCM2838Class { + /*< private >*/ + BCM283XBaseClass parent_class; + /*< public >*/ + hwaddr peri_low_base; /* Lower peripheral base address seen by the CPU */ + hwaddr gic_base; /* GIC base address inside ARM local peripherals region */ +}; + +#define VIRTUAL_PMU_IRQ 7 + +static void bcm2838_init(Object *obj) +{ + BCM2838State *s = BCM2838(obj); + + object_initialize_child(obj, "peripherals", &s->peripherals, + TYPE_BCM2838_PERIPHERALS); + object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals), + "board-rev"); + object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals), + "vcram-size"); + object_property_add_alias(obj, "command-line", OBJECT(&s->peripherals), + "command-line"); +} + +static void bcm2838_realize(DeviceState *dev, Error **errp) +{ + int n; + BCM2838State *s = BCM2838(dev); + BCM283XBaseState *s_base = BCM283X_BASE(dev); + BCM2838Class *bc = BCM2838_GET_CLASS(dev); + BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev); + BCM2838PeripheralState *ps = BCM2838_PERIPHERALS(&s->peripherals); + RaspiPeripheralBaseState *ps_base = RASPI_PERIPHERALS_BASE(&s->peripherals); + + if (!bcm283x_common_realize(dev, ps_base, errp)) { + return; + } + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(ps), 1, bc->peri_low_base, 1); + + /* bcm2836 interrupt controller (and mailboxes, etc.) */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s_base->control), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s_base->control), 0, bc_base->ctrl_base); + + /* Create cores */ + for (n = 0; n < bc_base->core_count; n++) { + /* TODO: this should be converted to a property of ARM_CPU */ + s_base->cpu[n].core.mp_affinity = (bc_base->clusterid << 8) | n; + + /* start powered off if not enabled */ + if (!object_property_set_bool(OBJECT(&s_base->cpu[n].core), + "start-powered-off", + n >= s_base->enabled_cpus, + errp)) { + return; + } + + if (!qdev_realize(DEVICE(&s_base->cpu[n].core), NULL, errp)) { + return; + } + } +} + +static void bcm2838_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + BCM2838Class *bc = BCM2838_CLASS(oc); + BCM283XBaseClass *bc_base = BCM283X_BASE_CLASS(oc); + + bc_base->cpu_type = ARM_CPU_TYPE_NAME("cortex-a72"); + bc_base->core_count = BCM283X_NCPUS; + bc_base->peri_base = 0xfe000000; + bc_base->ctrl_base = 0xff800000; + bc_base->clusterid = 0x0; + bc->peri_low_base = 0xfc000000; + dc->realize = bcm2838_realize; +} + +static const TypeInfo bcm2838_type = { + .name = TYPE_BCM2838, + .parent = TYPE_BCM283X_BASE, + .instance_size = sizeof(BCM2838State), + .instance_init = bcm2838_init, + .class_size = sizeof(BCM2838Class), + .class_init = bcm2838_class_init, +}; + +static void bcm2838_register_types(void) +{ + type_register_static(&bcm2838_type); +} + +type_init(bcm2838_register_types); diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c new file mode 100644 index 0000000000..864941c231 --- /dev/null +++ b/hw/arm/bcm2838_peripherals.c @@ -0,0 +1,72 @@ +/* + * BCM2838 peripherals emulation + * + * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinni...@auriga.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "hw/arm/raspi_platform.h" +#include "hw/arm/bcm2838_peripherals.h" + +/* Lower peripheral base address on the VC (GPU) system bus */ +#define BCM2838_VC_PERI_LOW_BASE 0x7c000000 + +static void bcm2838_peripherals_init(Object *obj) +{ + BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj); + BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj); + + /* Lower memory region for peripheral devices (exported to the Soc) */ + memory_region_init(&s->peri_low_mr, obj, "bcm2838-peripherals", + bc->peri_low_size); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_low_mr); + +} + +static void bcm2838_peripherals_realize(DeviceState *dev, Error **errp) +{ + BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev); + RaspiPeripheralBaseState *s_base = RASPI_PERIPHERALS_BASE(dev); + + raspi_peripherals_common_realize(dev, errp); + + /* Map lower peripherals into the GPU address space */ + memory_region_init_alias(&s->peri_low_mr_alias, OBJECT(s), + "bcm2838-peripherals", &s->peri_low_mr, 0, + memory_region_size(&s->peri_low_mr)); + memory_region_add_subregion_overlap(&s_base->gpu_bus_mr, + BCM2838_VC_PERI_LOW_BASE, + &s->peri_low_mr_alias, 1); + +} + +static void bcm2838_peripherals_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_CLASS(oc); + RaspiPeripheralBaseClass *bc_base = RASPI_PERIPHERALS_BASE_CLASS(oc); + + bc->peri_low_size = 0x2000000; + bc_base->peri_size = 0x1800000; + dc->realize = bcm2838_peripherals_realize; +} + +static const TypeInfo bcm2838_peripherals_type_info = { + .name = TYPE_BCM2838_PERIPHERALS, + .parent = TYPE_RASPI_PERIPHERALS_BASE, + .instance_size = sizeof(BCM2838PeripheralState), + .instance_init = bcm2838_peripherals_init, + .class_size = sizeof(BCM2838PeripheralClass), + .class_init = bcm2838_peripherals_class_init, +}; + +static void bcm2838_peripherals_register_types(void) +{ + type_register_static(&bcm2838_peripherals_type_info); +} + +type_init(bcm2838_peripherals_register_types) diff --git a/hw/arm/meson.build b/hw/arm/meson.build index 11eb9112f8..071819b527 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -39,6 +39,7 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubi arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c')) arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 'bananapi_m2u.c')) arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c')) +arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files('bcm2838.c')) arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c')) arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c')) arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c')) @@ -69,6 +70,7 @@ arm_ss.add_all(xen_ss) system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c')) system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c')) system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c')) +system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_peripherals.c')) system_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c')) hw_arch += {'arm': arm_ss} diff --git a/include/hw/arm/bcm2838.h b/include/hw/arm/bcm2838.h new file mode 100644 index 0000000000..6e5a8ec30e --- /dev/null +++ b/include/hw/arm/bcm2838.h @@ -0,0 +1,26 @@ +/* + * BCM2838 SoC emulation + * + * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinni...@auriga.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef BCM2838_H +#define BCM2838_H + +#include "hw/arm/bcm2836.h" +#include "hw/arm/bcm2838_peripherals.h" + +#define TYPE_BCM2838 "bcm2838" + +OBJECT_DECLARE_TYPE(BCM2838State, BCM2838Class, BCM2838) + +struct BCM2838State { + /*< private >*/ + BCM283XBaseState parent_obj; + /*< public >*/ + BCM2838PeripheralState peripherals; +}; + +#endif /* BCM2838_H */ diff --git a/include/hw/arm/bcm2838_peripherals.h b/include/hw/arm/bcm2838_peripherals.h new file mode 100644 index 0000000000..8214003baf --- /dev/null +++ b/include/hw/arm/bcm2838_peripherals.h @@ -0,0 +1,36 @@ +/* + * BCM2838 peripherals emulation + * + * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinni...@auriga.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef BCM2838_PERIPHERALS_H +#define BCM2838_PERIPHERALS_H + +#include "hw/arm/bcm2835_peripherals.h" + + +#define TYPE_BCM2838_PERIPHERALS "bcm2838-peripherals" +OBJECT_DECLARE_TYPE(BCM2838PeripheralState, BCM2838PeripheralClass, + BCM2838_PERIPHERALS) + +struct BCM2838PeripheralState { + /*< private >*/ + RaspiPeripheralBaseState parent_obj; + + /*< public >*/ + MemoryRegion peri_low_mr; + MemoryRegion peri_low_mr_alias; + MemoryRegion mphi_mr_alias; +}; + +struct BCM2838PeripheralClass { + /*< private >*/ + RaspiPeripheralBaseClass parent_class; + /*< public >*/ + uint64_t peri_low_size; /* Peripheral lower range size */ +}; + +#endif /* BCM2838_PERIPHERALS_H */ -- 2.34.1