@@ -85,6 +85,9 @@ config STM32F4XX_EXTI
config MIPS_ITU
bool
+config MIPS_TRICKBOX
+ bool
+
config MPS2_FPGAIO
bool
select LED
@@ -136,6 +136,7 @@ specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c'))
specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cpc.c'))
specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
+specific_ss.add(when: 'CONFIG_MIPS_TRICKBOX', if_true: files('mips_trickbox.c'))
softmmu_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
new file mode 100644
@@ -0,0 +1,97 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ *
+ * MIPS Trickbox
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "sysemu/runstate.h"
+#include "hw/misc/mips_trickbox.h"
+
+static uint64_t mips_trickbox_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ uint64_t value = 0;
+
+ qemu_log_mask(LOG_UNIMP,
+ "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+ __func__, addr);
+ trace_mips_trickbox_read(size, value);
+
+ return 0;
+}
+
+static void mips_trickbox_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ trace_mips_trickbox_write(size, val64);
+
+ switch (addr) {
+ case REG_SIM_CMD:
+ switch (val64) {
+ case TRICK_PANIC:
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+ break;
+ case TRICK_HALT:
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+ break;
+ case TRICK_SUSPEND:
+ qemu_system_suspend_request();
+ break;
+ case TRICK_RESET:
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ break;
+ case TRICK_PASS_MIPS:
+ case TRICK_PASS_NANOMIPS:
+ exit(EXIT_SUCCESS);
+ break;
+ case TRICK_FAIL_MIPS:
+ case TRICK_FAIL_NANOMIPS:
+ exit(EXIT_FAILURE);
+ break;
+ }
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+ __func__, addr);
+ break;
+ }
+}
+
+static const MemoryRegionOps mips_trickbox_ops = {
+ .read = mips_trickbox_read,
+ .write = mips_trickbox_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 2,
+ .max_access_size = 4
+ }
+};
+
+static void mips_trickbox_init(Object *obj)
+{
+ MIPSTrickboxState *s = MIPS_TRICKBOX(obj);
+
+ memory_region_init_io(&s->mmio, obj, &mips_trickbox_ops, s,
+ TYPE_MIPS_TRICKBOX, 0x100);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static const TypeInfo mips_trickbox_info = {
+ .name = TYPE_MIPS_TRICKBOX,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MIPSTrickboxState),
+ .instance_init = mips_trickbox_init,
+};
+
+static void mips_trickbox_register_types(void)
+{
+ type_register_static(&mips_trickbox_info);
+}
+
+type_init(mips_trickbox_register_types)
@@ -279,3 +279,7 @@ virt_ctrl_instance_init(void *dev) "ctrl: %p"
lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" is %d"
lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
lasi_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
+
+# mips_trickbox.c
+mips_trickbox_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
+mips_trickbox_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
new file mode 100644
@@ -0,0 +1,39 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ *
+ * MIPS Trickbox
+ */
+
+
+#ifndef HW_MIPS_TRICKBOX_H
+#define HW_MIPS_TRICKBOX_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_MIPS_TRICKBOX "mips.trickbox"
+
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSTrickboxState, MIPS_TRICKBOX)
+
+struct MIPSTrickboxState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+};
+
+#define REG_SIM_CMD 0x0
+
+enum {
+ TRICK_PANIC = 1,
+ TRICK_HALT = 2,
+ TRICK_SUSPEND = 3,
+ TRICK_RESET = 4,
+ TRICK_FAIL_MIPS = 0x2c00abc1,
+ TRICK_PASS_MIPS = 0x2c00abc2,
+ TRICK_FAIL_NANOMIPS = 0x80005bc1,
+ TRICK_PASS_NANOMIPS = 0x80005bc2
+};
+
+#endif