Add the common resettable peripheral base and model the Octeon RST
state used to hold secondary cores in reset. Create and realize the
controller as part of the machine without exposing its CSR interface
yet.
---
hw/mips/octeon.c | 105 ++++++++++++++++++++++++++++++++++++++
hw/mips/octeon_internal.h | 2 +
2 files changed, 107 insertions(+)
diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c
index 0e02d3693d..4fc5a71a90 100644
--- a/hw/mips/octeon.c
+++ b/hw/mips/octeon.c
@@ -29,6 +29,13 @@
#define TYPE_OCTEON_MACHINE MACHINE_TYPE_NAME("octeon3")
OBJECT_DECLARE_SIMPLE_TYPE(OcteonMachineState, OCTEON_MACHINE)
+#define TYPE_OCTEON_PERIPHERAL "octeon-peripheral"
+OBJECT_DECLARE_TYPE(OcteonPeripheralState, OcteonPeripheralClass,
+ OCTEON_PERIPHERAL)
+
+#define TYPE_OCTEON_RST "octeon-rst"
+OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST)
+
/*
* Clock defaults follow a Ubiquiti E1000 EBB7304 U-Boot banner.
* DDR follows the upstream EBB7304 U-Boot board default.
@@ -85,6 +92,22 @@ struct OcteonMachineState {
uint64_t ddr_hz;
};
+struct OcteonPeripheralState {
+ SysBusDevice parent_obj;
+ OcteonState *board;
+ unsigned int index;
+};
+
+struct OcteonPeripheralClass {
+ SysBusDeviceClass parent_class;
+ ResettablePhases parent_phases;
+};
+
+struct OcteonRstState {
+ OcteonPeripheralState parent_obj;
+ uint64_t rst_pp_power;
+};
+
static void octeon_validate_clocks(OcteonMachineState *oms)
{
if (!oms->cpu_hz || !oms->ref_hz || !oms->io_hz || !oms->ddr_hz) {
@@ -99,6 +122,16 @@ static void octeon_validate_clocks(OcteonMachineState *oms)
}
}
+static uint64_t octeon_present_cpu_mask(OcteonState *s)
+{
+ return (1ULL << s->cpu_count) - 1;
+}
+
+static uint64_t octeon_secondary_cpu_mask(OcteonState *s)
+{
+ return octeon_present_cpu_mask(s) & ~1ULL;
+}
+
static void octeon_cpu_after_reset(OcteonCPUState *cs)
{
CPUMIPSState *env = &cs->cpu->env;
@@ -303,6 +336,62 @@ static void octeon_init_flash(OcteonState *s)
&s->boot_flash_alias);
}
+static void octeon_rst_reset_hold(Object *obj, ResetType type)
+{
+ OcteonPeripheralClass *opc = OCTEON_PERIPHERAL_GET_CLASS(obj);
+ OcteonRstState *rst = OCTEON_RST(obj);
+
+ if (opc->parent_phases.hold) {
+ opc->parent_phases.hold(obj, type);
+ }
+
+ rst->rst_pp_power = octeon_secondary_cpu_mask(rst->parent_obj.board);
+}
+
+static void octeon_peripheral_class_init(ObjectClass *klass,
+ const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->user_creatable = false;
+}
+
+static void octeon_rst_class_init(ObjectClass *klass, const void *data)
+{
+ OcteonPeripheralClass *opc = OCTEON_PERIPHERAL_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ resettable_class_set_parent_phases(rc, NULL, octeon_rst_reset_hold,
+ NULL, &opc->parent_phases);
+}
+
+static OcteonPeripheralState *octeon_new_peripheral(OcteonState *s,
+ const char *type,
+ unsigned int index)
+{
+ DeviceState *qdev = qdev_new(type);
+ OcteonPeripheralState *dev = OCTEON_PERIPHERAL(qdev);
+
+ dev->board = s;
+ dev->index = index;
+ return dev;
+}
+
+static void octeon_create_peripherals(OcteonState *s)
+{
+ s->rst = OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0));
+}
+
+static void octeon_realize_peripheral(OcteonPeripheralState *dev)
+{
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+}
+
+static void octeon_realize_peripherals(OcteonState *s)
+{
+ octeon_realize_peripheral(&s->rst->parent_obj);
+}
+
static void mips_octeon_init(MachineState *machine)
{
OcteonMachineState *oms = OCTEON_MACHINE(machine);
@@ -316,6 +405,7 @@ static void mips_octeon_init(MachineState *machine)
s->ref_hz = oms->ref_hz;
s->io_hz = oms->io_hz;
s->ddr_hz = oms->ddr_hz;
+ octeon_create_peripherals(s);
if (machine->kernel_filename) {
error_report("-kernel is not implemented for octeon3; "
@@ -328,6 +418,7 @@ static void mips_octeon_init(MachineState *machine)
octeon_load_firmware(s);
octeon_create_cpus(s);
+ octeon_realize_peripherals(s);
}
static void octeon_machine_reset(MachineState *machine, ResetType type)
@@ -385,6 +476,20 @@ static void octeon_machine_class_init(ObjectClass *oc,
const void *data)
}
static const TypeInfo octeon_machine_types[] = {
+ {
+ .name = TYPE_OCTEON_PERIPHERAL,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(OcteonPeripheralState),
+ .class_size = sizeof(OcteonPeripheralClass),
+ .class_init = octeon_peripheral_class_init,
+ .abstract = true,
+ },
+ {
+ .name = TYPE_OCTEON_RST,
+ .parent = TYPE_OCTEON_PERIPHERAL,
+ .instance_size = sizeof(OcteonRstState),
+ .class_init = octeon_rst_class_init,
+ },
{
.name = TYPE_OCTEON_MACHINE,
.parent = TYPE_MACHINE,
diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h
index 2e568c29ea..9c1baee292 100644
--- a/hw/mips/octeon_internal.h
+++ b/hw/mips/octeon_internal.h
@@ -15,6 +15,7 @@
#define OCTEON_MAX_CPUS 16
typedef struct OcteonState OcteonState;
+typedef struct OcteonRstState OcteonRstState;
typedef struct OcteonCPUState {
OcteonState *board;
@@ -39,6 +40,7 @@ struct OcteonState {
MemoryRegion boot_flash;
MemoryRegion boot_flash_alias;
MemoryRegion cvmseg;
+ OcteonRstState *rst;
};
#endif
--
2.54.0