From bfe01532011570c7fd565d799a68330b2bb8a3fe Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Tue, 16 Sep 2025 12:25:05 +0200 Subject: [PATCH 1/4] [ot] hw/riscv: Kconfig: remove useless dependencies from OT_DARJEELING machine Signed-off-by: Emmanuel Blot --- hw/riscv/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index cf0a3dac61b64..410edfab16ae4 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -34,7 +34,6 @@ config OT_DARJEELING select OT_DM_TL select OT_DMA select OT_EDN - select OT_ENTROPY_SRC_DJ select OT_GPIO_DJ select OT_HMAC select OT_I2C @@ -63,7 +62,6 @@ config OT_DARJEELING select SIFIVE_PLIC select SPLIT_IRQ select TAP_CTRL_RBB - select UNIMP config OT_EARLGREY bool From 1ef76d98bb9fdd62fbe153e574896e5e3d10e34f Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Tue, 16 Sep 2025 12:25:56 +0200 Subject: [PATCH 2/4] [ot] scripts/opentitan: dtm.py: do not attempt to halt a hart if it is not available Signed-off-by: Emmanuel Blot --- python/qemu/ot/dm/dm.py | 8 ++++++++ scripts/opentitan/dtm.py | 13 ++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/python/qemu/ot/dm/dm.py b/python/qemu/ot/dm/dm.py index 0c764de6c7eb4..b99723e7e225f 100644 --- a/python/qemu/ot/dm/dm.py +++ b/python/qemu/ot/dm/dm.py @@ -230,6 +230,14 @@ def system_bus_info(self) -> dict[str, int]: btf = self.BITFIELDS['SBCS'] return btf.decode(self.sbcs) + @property + def is_available(self) -> bool: + """Report whether the currently selected hart is available.""" + btf = self.BITFIELDS['DMSTATUS'] + val = self.dmstatus + status = btf.decode(val) + return not status['anyunavail'] + @property def is_halted(self) -> bool: """Report whether the currently selected hart is halted.""" diff --git a/scripts/opentitan/dtm.py b/scripts/opentitan/dtm.py index 1ba4b8c8e6943..053124dcbc667 100755 --- a/scripts/opentitan/dtm.py +++ b/scripts/opentitan/dtm.py @@ -14,7 +14,7 @@ from os import linesep from os.path import dirname, join as joinpath, normpath from socket import create_connection, socket, AF_UNIX, SOCK_STREAM -from time import sleep +from time import sleep, time as now from traceback import format_exc from typing import Optional import sys @@ -198,6 +198,17 @@ def main(): if not rvdm: rvdm = DebugModule(dtm, args.base) rvdm.initialize() + # it may take some time for a hart to be initialized and to + # be up and running as HW initialization (ROM check, etc.) + # takes time. Wait for the hart to become available before + # attempting to halt it + timeout = now() + 2.0 + while now() < timeout: + if rvdm.is_available: + break + sleep(0.1) + else: + raise ValueError('Hart did not become available') rvdm.halt() dmver = rvdm.status['version'] if args.info: From 3441cd2b20c3c459bd9371b94e5b88aa14aae16e Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Tue, 16 Sep 2025 12:27:24 +0200 Subject: [PATCH 3/4] [ot] hw/riscv: ot_darjeeling: rework machine/board/soc reset management. Signed-off-by: Emmanuel Blot --- hw/riscv/ot_darjeeling.c | 147 ++++++++++++++++++------------- include/hw/riscv/ot_darjeeling.h | 2 +- 2 files changed, 86 insertions(+), 63 deletions(-) diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index 691f270f44378..31bd3b8de47eb 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -1,5 +1,5 @@ /* - * QEMU RISC-V Board Compatible with OpenTitan "integrated" Darjeeling platform + * QEMU RISC-V Board Compatible with OpenTitan Darjeeling platform * * Copyright (c) 2023-2025 Rivos, Inc. * @@ -7,10 +7,6 @@ * Emmanuel Blot * Loïc Lefort * - * This implementation is based on: - * https://docs.google.com/document/d/ - * 1jGeVNqmEUEJcmOfQ0mEZ_E8pG-RYovtVMelVTQZECcA - * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2 or later, as published by the Free Software Foundation. @@ -277,6 +273,13 @@ enum OtDjPinmuxMioOut { MIO_OUT_COUNT, /* 5 */ }; +enum OtDjBoardDevice { + OT_DJ_BOARD_DEV_SOC, + OT_DJ_BOARD_DEV_FLASH, + OT_DJ_BOARD_DEV_DEV_PROXY, + OT_DJ_BOARD_DEV_COUNT, +}; + #define OT_DJ_PRIVATE_REGION_OFFSET 0x00000000u #define OT_DJ_PRIVATE_REGION_SIZE (1u << 30u) @@ -1467,17 +1470,18 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { /* clang-format on */ }; -enum OtDjBoardDevice { - OT_DJ_BOARD_DEV_SOC, - OT_DJ_BOARD_DEV_FLASH, - OT_DJ_BOARD_DEV_DEV_PROXY, - OT_DJ_BOARD_DEV_COUNT, -}; - /* ------------------------------------------------------------------------ */ /* Type definitions */ /* ------------------------------------------------------------------------ */ +/* Temporary storage for reset iteration */ +typedef struct { + OtDjSoCState *soc; + ResettableChildCallback cb; /* the callback to call for each child */ + void *opaque; /* opaque data for the callback */ + ResetType type; /* type of reset */ +} OtDjSocChildReset; + struct OtDjSoCClass { DeviceClass parent_class; DeviceRealize parent_realize; @@ -1487,6 +1491,8 @@ struct OtDjSoCClass { struct OtDjSoCState { SysBusDevice parent_obj; + BusState *ot_bus; /* private OpenTitan bus */ + DeviceState **devices; }; @@ -1505,11 +1511,6 @@ struct OtDjMachineState { bool ignore_elf_entry; }; -struct OtDjMachineClass { - MachineClass parent_class; - ResettablePhases parent_phases; -}; - /* ------------------------------------------------------------------------ */ /* Device Configuration */ /* ------------------------------------------------------------------------ */ @@ -1612,6 +1613,43 @@ static void ot_dj_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, /* SoC */ /* ------------------------------------------------------------------------ */ +static int ot_dj_soc_reset_child(Object *child, void *opaque) +{ + OtDjSocChildReset *cr = opaque; + + if (object_dynamic_cast(child, TYPE_SYS_BUS_DEVICE)) { + /* + * sysbus devices being connected to the OT bus, and the bus performing + * its own children traversal to perform reset, skip this kind of + * devices to avoid resetting each of them twice + */ + return 0; + } + + if (object_dynamic_cast(child, TYPE_RESETTABLE_INTERFACE)) { + cr->cb(child, cr->opaque, cr->type); + } + + /* resume with next child */ + return 0; +} + +static void ot_dj_soc_reset_child_foreach( + Object *obj, ResettableChildCallback cb, void *opaque, ResetType type) +{ + OtDjSoCState *s = RISCV_OT_DJ_SOC(obj); + + OtDjSocChildReset r = { + .soc = s, + .cb = cb, + .opaque = opaque, + .type = type, + }; + + /* execute reset stage for each child */ + object_child_foreach(obj, &ot_dj_soc_reset_child, &r); +} + static void ot_dj_soc_hw_reset(void *opaque, int irq, int level) { OtDjSoCState *s = opaque; @@ -1619,11 +1657,7 @@ static void ot_dj_soc_hw_reset(void *opaque, int irq, int level) g_assert(irq == 0); if (level) { - CPUState *cs = CPU(s->devices[OT_DJ_SOC_DEV_HART]); - cpu_synchronize_state(cs); - bus_cold_reset(sysbus_get_default()); - resettable_reset(OBJECT(cs), RESET_TYPE_COLD); - cpu_synchronize_post_reset(cs); + resettable_reset(OBJECT(s), RESET_TYPE_COLD); } } @@ -1636,18 +1670,15 @@ static void ot_dj_soc_reset_hold(Object *obj, ResetType type) c->parent_phases.hold(obj, type); } - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_LC_CTRL]), type); - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_MBX]), type); - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DTM]), type); - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM]), type); - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_VMAPPER]), type); - /* + * This function is called after all children have been reset_hold, + * before any child has been reset_exit. + * * Power-On-Reset: leave hart disabled on reset * PowerManager takes care of managing Ibex reset when ready */ CPUState *cs = CPU(s->devices[OT_DJ_SOC_DEV_HART]); - cs->disabled = 1; + cs->disabled = true; } static void ot_dj_soc_reset_exit(Object *obj, ResetType type) @@ -1675,9 +1706,14 @@ static void ot_dj_soc_realize(DeviceState *dev, Error **errp) cpu->memory = get_system_memory(); cpu->cpu_index = 0; + /* Create the private bus on which all OpenTitan IPs are connected */ + s->ot_bus = BUS(object_new(TYPE_SYSTEM_BUS)); + qbus_init(s->ot_bus, sizeof(*s->ot_bus), TYPE_SYSTEM_BUS, DEVICE(s), + "ot.bus"); + /* Link, define properties and realize devices, then connect GPIOs */ - ot_common_configure_devices_with_id(s->devices, dev->parent_bus, "soc", - false, ot_dj_soc_devices, + ot_common_configure_devices_with_id(s->devices, s->ot_bus, "soc", false, + ot_dj_soc_devices, ARRAY_SIZE(ot_dj_soc_devices)); Object *oas; @@ -1786,6 +1822,7 @@ static void ot_dj_soc_class_init(ObjectClass *oc, void *data) resettable_class_set_parent_phases(rc, NULL, &ot_dj_soc_reset_hold, &ot_dj_soc_reset_exit, &sc->parent_phases); + rc->child_foreach = &ot_dj_soc_reset_child_foreach; dc->realize = &ot_dj_soc_realize; dc->user_creatable = false; } @@ -1810,12 +1847,14 @@ type_init(ot_dj_soc_register_types); /* Board */ /* ------------------------------------------------------------------------ */ -static void ot_dj_board_reset(DeviceState *dev) +static void ot_dj_board_child_foreach(Object *obj, ResettableChildCallback cb, + void *opaque, ResetType type) { - OtDjBoardState *s = RISCV_OT_DJ_BOARD(dev); + OtDjBoardState *s = RISCV_OT_DJ_BOARD(obj); - resettable_reset(OBJECT(s->devices[OT_DJ_BOARD_DEV_DEV_PROXY]), - RESET_TYPE_COLD); + for (unsigned ix = 0; ix < OT_DJ_BOARD_DEV_COUNT; ix++) { + cb(OBJECT(s->devices[ix]), opaque, type); + } } static void ot_dj_board_realize(DeviceState *dev, Error **errp) @@ -1840,7 +1879,7 @@ static void ot_dj_board_realize(DeviceState *dev, Error **errp) OtDjSoCState *s = RISCV_OT_DJ_SOC(soc); BusState *bus = sysbus_get_default(); - qdev_realize_and_unref(DEVICE(soc), bus, &error_fatal); + qdev_realize_and_unref(soc, bus, &error_fatal); /* CTN RAM */ MemoryRegion *ctn_ram = g_new0(MemoryRegion, 1u); @@ -1891,8 +1930,10 @@ static void ot_dj_board_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); (void)data; - device_class_set_legacy_reset(dc, &ot_dj_board_reset); dc->realize = &ot_dj_board_realize; + + ResettableClass *rc = RESETTABLE_CLASS(oc); + rc->child_foreach = &ot_dj_board_child_foreach; } static const TypeInfo ot_dj_board_type_info = { @@ -1947,26 +1988,19 @@ ot_dj_machine_set_ignore_elf_entry(Object *obj, bool value, Error **errp) s->ignore_elf_entry = value; } -static ResettableState *ot_dj_get_reset_state(Object *obj) +static ResettableState *ot_dj_machine_get_reset_state(Object *obj) { OtDjMachineState *s = RISCV_OT_DJ_MACHINE(obj); return &s->reset; } -static void ot_dj_reset_hold(Object *obj, ResetType type) +static void ot_dj_machine_child_foreach(Object *obj, ResettableChildCallback cb, + void *opaque, ResetType type) { - (void)obj; + Object *board = object_property_get_link(obj, "board", &error_fatal); - /* - * The way the resettable APIs are implemented does not allow to call the - * legacy qemu_devices_reset from the enter phase, where a global static - * variable singleton enforces that entering reset is exclusive. However - * qemu_devices_reset implements the full enter/hold/exit reset sequence. - * This legacy function is therefore invoked from the hold stage of the - * machine reset sequence. - */ - qemu_devices_reset(type); + cb(board, opaque, type); } static void ot_dj_machine_reset(MachineState *ms, ResetType reason) @@ -2000,12 +2034,6 @@ static void ot_dj_machine_init(MachineState *state) object_property_add_child(OBJECT(state), "board", OBJECT(dev)); - /* - * any object not part of the default system bus hiearchy is never reset - * otherwise - */ - qemu_register_reset(resettable_cold_reset_fn, dev); - qdev_realize(dev, NULL, &error_fatal); } @@ -2023,15 +2051,11 @@ static void ot_dj_machine_class_init(ObjectClass *oc, void *data) /* * Implement the resettable interface to ensure the proper initialization * sequence. - * The hold stage is used to perform most of the device reset sequence. */ ResettableClass *rc = RESETTABLE_CLASS(oc); - rc->get_state = &ot_dj_get_reset_state; - - OtDjMachineClass *sc = RISCV_OT_DJ_MACHINE_CLASS(oc); - resettable_class_set_parent_phases(rc, NULL, &ot_dj_reset_hold, NULL, - &sc->parent_phases); + rc->get_state = &ot_dj_machine_get_reset_state; + rc->child_foreach = &ot_dj_machine_child_foreach; } static const TypeInfo ot_dj_machine_type_info = { @@ -2039,7 +2063,6 @@ static const TypeInfo ot_dj_machine_type_info = { .parent = TYPE_MACHINE, .instance_size = sizeof(OtDjMachineState), .instance_init = &ot_dj_machine_instance_init, - .class_size = sizeof(OtDjMachineClass), .class_init = &ot_dj_machine_class_init, .interfaces = (InterfaceInfo[]){ { TYPE_RESETTABLE_INTERFACE }, {} }, }; diff --git a/include/hw/riscv/ot_darjeeling.h b/include/hw/riscv/ot_darjeeling.h index 52ab935edd211..2df919c76ce6a 100644 --- a/include/hw/riscv/ot_darjeeling.h +++ b/include/hw/riscv/ot_darjeeling.h @@ -26,7 +26,7 @@ #include "qom/object.h" #define TYPE_RISCV_OT_DJ_MACHINE MACHINE_TYPE_NAME("ot-darjeeling") -OBJECT_DECLARE_TYPE(OtDjMachineState, OtDjMachineClass, RISCV_OT_DJ_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(OtDjMachineState, RISCV_OT_DJ_MACHINE) #define TYPE_RISCV_OT_DJ_BOARD "riscv.ot_darjeeling.board" OBJECT_DECLARE_SIMPLE_TYPE(OtDjBoardState, RISCV_OT_DJ_BOARD) From 53669d62fec62ba50d0a133b233f87f3e9b517fa Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Tue, 16 Sep 2025 14:14:41 +0200 Subject: [PATCH 4/4] [ot] hw/riscv: ot_earlgrey: rework machine/board/soc reset management. Signed-off-by: Emmanuel Blot --- hw/riscv/ot_earlgrey.c | 148 +++++++++++++++++++++++---------- include/hw/riscv/ot_earlgrey.h | 2 +- 2 files changed, 103 insertions(+), 47 deletions(-) diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index da742e5925959..4a3826d1e218f 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -1435,6 +1435,14 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { /* Type definitions */ /* ------------------------------------------------------------------------ */ +/* Temporary storage for reset iteration */ +typedef struct { + OtEGSoCState *soc; + ResettableChildCallback cb; /* the callback to call for each child */ + void *opaque; /* opaque data for the callback */ + ResetType type; /* type of reset */ +} OtEgSocChildReset; + struct OtEGSoCClass { DeviceClass parent_class; DeviceRealize parent_realize; @@ -1444,12 +1452,16 @@ struct OtEGSoCClass { struct OtEGSoCState { SysBusDevice parent_obj; + BusState *ot_bus; /* private OpenTitan bus */ + DeviceState **devices; }; struct OtEGBoardState { DeviceState parent_obj; + DeviceState **devices; + /* optional SPI data flash (type of device) */ char *spiflash[OT_EG_MTD_SPI_COUNT]; }; @@ -1604,6 +1616,43 @@ static void ot_eg_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, /* SoC */ /* ------------------------------------------------------------------------ */ +static int ot_eg_soc_reset_child(Object *child, void *opaque) +{ + OtEgSocChildReset *cr = opaque; + + if (object_dynamic_cast(child, TYPE_SYS_BUS_DEVICE)) { + /* + * sysbus devices being connected to the OT bus, and the bus performing + * its own children traversal to perform reset, skip this kind of + * devices to avoid resetting each of them twice + */ + return 0; + } + + if (object_dynamic_cast(child, TYPE_RESETTABLE_INTERFACE)) { + cr->cb(child, cr->opaque, cr->type); + } + + /* resume with next child */ + return 0; +} + +static void ot_eg_soc_reset_child_foreach( + Object *obj, ResettableChildCallback cb, void *opaque, ResetType type) +{ + OtEGSoCState *s = RISCV_OT_EG_SOC(obj); + + OtEgSocChildReset r = { + .soc = s, + .cb = cb, + .opaque = opaque, + .type = type, + }; + + /* execute reset stage for each child */ + object_child_foreach(obj, &ot_eg_soc_reset_child, &r); +} + static void ot_eg_soc_hw_reset(void *opaque, int irq, int level) { OtEGSoCState *s = opaque; @@ -1611,11 +1660,7 @@ static void ot_eg_soc_hw_reset(void *opaque, int irq, int level) g_assert(irq == 0); if (level) { - CPUState *cs = CPU(s->devices[OT_EG_SOC_DEV_HART]); - cpu_synchronize_state(cs); - bus_cold_reset(sysbus_get_default()); - resettable_reset(OBJECT(cs), RESET_TYPE_COLD); - cpu_synchronize_post_reset(cs); + resettable_reset(OBJECT(s), RESET_TYPE_COLD); } } @@ -1628,16 +1673,15 @@ static void ot_eg_soc_reset_hold(Object *obj, ResetType type) c->parent_phases.hold(obj, type); } - resettable_reset(OBJECT(s->devices[OT_EG_SOC_DEV_DTM]), type); - resettable_reset(OBJECT(s->devices[OT_EG_SOC_DEV_DM]), type); - resettable_reset(OBJECT(s->devices[OT_EG_SOC_DEV_VMAPPER]), type); - /* + * This function is called after all children have been reset_hold, + * before any child has been reset_exit. + * * Power-On-Reset: leave hart disabled on reset * PowerManager takes care of managing Ibex reset when ready */ CPUState *cs = CPU(s->devices[OT_EG_SOC_DEV_HART]); - cs->disabled = 1; + cs->disabled = false; } static void ot_eg_soc_reset_exit(Object *obj, ResetType type) @@ -1659,9 +1703,17 @@ static void ot_eg_soc_realize(DeviceState *dev, Error **errp) OtEGSoCState *s = RISCV_OT_EG_SOC(dev); (void)errp; + CPUState *cpu = CPU(s->devices[OT_EG_SOC_DEV_HART]); + cpu->memory = get_system_memory(); + cpu->cpu_index = 0; + + /* Create the private bus on which all OpenTitan IPs are connected */ + s->ot_bus = BUS(object_new(TYPE_SYSTEM_BUS)); + qbus_init(s->ot_bus, sizeof(*s->ot_bus), TYPE_SYSTEM_BUS, DEVICE(s), + "ot.bus"); + /* Link, define properties and realize devices, then connect GPIOs */ - BusState *bus = sysbus_get_default(); - ot_common_configure_devices_with_id(s->devices, bus, "soc", false, + ot_common_configure_devices_with_id(s->devices, s->ot_bus, "soc", false, ot_eg_soc_devices, ARRAY_SIZE(ot_eg_soc_devices)); @@ -1677,7 +1729,7 @@ static void ot_eg_soc_realize(DeviceState *dev, Error **errp) ot_common_check_rom_configuration(); /* load kernel if provided */ - ibex_load_kernel(NULL); + ibex_load_kernel(cpu); } static void ot_eg_soc_init(Object *obj) @@ -1701,6 +1753,7 @@ static void ot_eg_soc_class_init(ObjectClass *oc, void *data) resettable_class_set_parent_phases(rc, NULL, &ot_eg_soc_reset_hold, &ot_eg_soc_reset_exit, &sc->parent_phases); + rc->child_foreach = &ot_eg_soc_reset_child_foreach; dc->realize = &ot_eg_soc_realize; dc->user_creatable = false; } @@ -1745,14 +1798,28 @@ static void ot_eg_board_set_spiflash1(Object *obj, const char *value, board->spiflash[OT_EG_MTD_SPI1] = g_strdup(value); } +static void ot_eg_board_child_foreach(Object *obj, ResettableChildCallback cb, + void *opaque, ResetType type) +{ + OtEGBoardState *s = RISCV_OT_EG_BOARD(obj); + + for (unsigned ix = 0; ix < OT_EG_BOARD_DEV_COUNT; ix++) { + /* flash devices are optional */ + if (s->devices[ix]) { + cb(OBJECT(s->devices[ix]), opaque, type); + } + } +} + static void ot_eg_board_realize(DeviceState *dev, Error **errp) { OtEGBoardState *board = RISCV_OT_EG_BOARD(dev); - DeviceState *soc = qdev_new(TYPE_RISCV_OT_EG_SOC); - + DeviceState *soc = board->devices[OT_EG_BOARD_DEV_SOC]; object_property_add_child(OBJECT(board), "soc", OBJECT(soc)); - sysbus_realize_and_unref(SYS_BUS_DEVICE(soc), &error_fatal); + + BusState *bus = sysbus_get_default(); + qdev_realize_and_unref(soc, bus, &error_fatal); for (unsigned fix = 0; fix < OT_EG_MTD_SPI_COUNT; fix++) { const char *flash_type = board->spiflash[OT_EG_MTD_SPI0 + fix]; @@ -1799,6 +1866,8 @@ static void ot_eg_board_realize(DeviceState *dev, Error **errp) /* connect it as a peripheral of the SPI host controller bus */ ssi_realize_and_unref(flash, SSI_BUS(spibus), errp); + board->devices[OT_EG_BOARD_DEV_FLASH0 + fix] = flash; + /* * finally, connect the first CS line of the SPI controller to control * to select this SPI flash device @@ -1819,6 +1888,11 @@ static void ot_eg_board_init(Object *obj) object_property_add_str(obj, "spiflash1", NULL, &ot_eg_board_set_spiflash1); object_property_set_description(obj, "spiflash1", "SPI dataflash on SPI1 bus"); + + OtEGBoardState *s = RISCV_OT_EG_BOARD(obj); + + s->devices = g_new0(DeviceState *, OT_EG_BOARD_DEV_COUNT); + s->devices[OT_EG_BOARD_DEV_SOC] = qdev_new(TYPE_RISCV_OT_EG_SOC); } static void ot_eg_board_class_init(ObjectClass *oc, void *data) @@ -1827,6 +1901,9 @@ static void ot_eg_board_class_init(ObjectClass *oc, void *data) (void)data; dc->realize = &ot_eg_board_realize; + + ResettableClass *rc = RESETTABLE_CLASS(oc); + rc->child_foreach = &ot_eg_board_child_foreach; } static const TypeInfo ot_eg_board_type_info = { @@ -1897,26 +1974,19 @@ static void ot_eg_machine_set_verilator(Object *obj, bool value, Error **errp) s->verilator = value; } -static ResettableState *ot_eg_get_reset_state(Object *obj) +static ResettableState *ot_eg_machine_get_reset_state(Object *obj) { OtEGMachineState *s = RISCV_OT_EG_MACHINE(obj); return &s->reset; } -static void ot_eg_reset_hold(Object *obj, ResetType type) +static void ot_eg_machine_child_foreach(Object *obj, ResettableChildCallback cb, + void *opaque, ResetType type) { - (void)obj; + Object *board = object_property_get_link(obj, "board", &error_fatal); - /* - * The way the resettable APIs are implemented does not allow to call the - * legacy qemu_devices_reset from the enter phase, where a global static - * variable singleton enforces that entering reset is exclusive. However - * qemu_devices_reset implements the full enter/hold/exit reset sequence. - * This legacy function is therefore invoked from the hold stage of the - * machine reset sequence. - */ - qemu_devices_reset(type); + cb(board, opaque, type); } static void ot_eg_machine_reset(MachineState *ms, ResetType reason) @@ -1953,12 +2023,6 @@ static void ot_eg_machine_init(MachineState *state) object_property_add_child(OBJECT(state), "board", OBJECT(dev)); - /* - * any object not part of the default system bus hiearchy is never reset - * otherwise - */ - qemu_register_reset(resettable_cold_reset_fn, dev); - qdev_realize(dev, NULL, &error_fatal); } @@ -1971,23 +2035,16 @@ static void ot_eg_machine_class_init(ObjectClass *oc, void *data) mc->init = ot_eg_machine_init; mc->reset = &ot_eg_machine_reset; mc->max_cpus = 1u; - mc->default_cpu_type = ot_eg_soc_devices[OT_EG_SOC_DEV_HART].type; - const IbexDeviceDef *sram = - &ot_eg_soc_devices[OT_EG_SOC_DEV_SRAM_MAIN_CTRL]; - mc->default_ram_id = sram->type; - mc->default_ram_size = SRAM_MAIN_SIZE; + mc->default_cpus = 1u; + /* * Implement the resettable interface to ensure the proper initialization * sequence. - * The hold stage is used to perform most of the device reset sequence. */ ResettableClass *rc = RESETTABLE_CLASS(oc); - rc->get_state = &ot_eg_get_reset_state; - - OtEGMachineClass *sc = RISCV_OT_EG_MACHINE_CLASS(oc); - resettable_class_set_parent_phases(rc, NULL, &ot_eg_reset_hold, NULL, - &sc->parent_phases); + rc->get_state = &ot_eg_machine_get_reset_state; + rc->child_foreach = &ot_eg_machine_child_foreach; } static const TypeInfo ot_eg_machine_type_info = { @@ -1995,7 +2052,6 @@ static const TypeInfo ot_eg_machine_type_info = { .parent = TYPE_MACHINE, .instance_size = sizeof(OtEGMachineState), .instance_init = &ot_eg_machine_instance_init, - .class_size = sizeof(OtEGMachineClass), .class_init = &ot_eg_machine_class_init, .interfaces = (InterfaceInfo[]){ { TYPE_RESETTABLE_INTERFACE }, {} }, }; diff --git a/include/hw/riscv/ot_earlgrey.h b/include/hw/riscv/ot_earlgrey.h index fa9ce941a721c..c996ddee1ea65 100644 --- a/include/hw/riscv/ot_earlgrey.h +++ b/include/hw/riscv/ot_earlgrey.h @@ -28,7 +28,7 @@ #define OT_EARLGREY "ot-earlgrey" #define TYPE_RISCV_OT_EG_MACHINE MACHINE_TYPE_NAME(OT_EARLGREY) -OBJECT_DECLARE_TYPE(OtEGMachineState, OtEGMachineClass, RISCV_OT_EG_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(OtEGMachineState, RISCV_OT_EG_MACHINE) #define TYPE_RISCV_OT_EG_BOARD OT_EARLGREY "-board" OBJECT_DECLARE_SIMPLE_TYPE(OtEGBoardState, RISCV_OT_EG_BOARD)