xref: /openbmc/qemu/hw/misc/virt_ctrl.c (revision 65b4c8c7)
10791bc02SLaurent Vivier /*
2*65b4c8c7SPhilippe Mathieu-Daudé  * SPDX-License-Identifier: GPL-2.0-or-later
30791bc02SLaurent Vivier  *
40791bc02SLaurent Vivier  * Virt system Controller
50791bc02SLaurent Vivier  */
60791bc02SLaurent Vivier 
70791bc02SLaurent Vivier #include "qemu/osdep.h"
80791bc02SLaurent Vivier #include "hw/qdev-properties.h"
90791bc02SLaurent Vivier #include "hw/sysbus.h"
100791bc02SLaurent Vivier #include "migration/vmstate.h"
110791bc02SLaurent Vivier #include "qemu/log.h"
120791bc02SLaurent Vivier #include "trace.h"
130791bc02SLaurent Vivier #include "sysemu/runstate.h"
140791bc02SLaurent Vivier #include "hw/misc/virt_ctrl.h"
150791bc02SLaurent Vivier 
160791bc02SLaurent Vivier enum {
170791bc02SLaurent Vivier     REG_FEATURES = 0x00,
180791bc02SLaurent Vivier     REG_CMD      = 0x04,
190791bc02SLaurent Vivier };
200791bc02SLaurent Vivier 
210791bc02SLaurent Vivier #define FEAT_POWER_CTRL 0x00000001
220791bc02SLaurent Vivier 
230791bc02SLaurent Vivier enum {
240791bc02SLaurent Vivier     CMD_NOOP,
250791bc02SLaurent Vivier     CMD_RESET,
260791bc02SLaurent Vivier     CMD_HALT,
270791bc02SLaurent Vivier     CMD_PANIC,
280791bc02SLaurent Vivier };
290791bc02SLaurent Vivier 
virt_ctrl_read(void * opaque,hwaddr addr,unsigned size)300791bc02SLaurent Vivier static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, unsigned size)
310791bc02SLaurent Vivier {
320791bc02SLaurent Vivier     VirtCtrlState *s = opaque;
330791bc02SLaurent Vivier     uint64_t value = 0;
340791bc02SLaurent Vivier 
350791bc02SLaurent Vivier     switch (addr) {
360791bc02SLaurent Vivier     case REG_FEATURES:
370791bc02SLaurent Vivier         value = FEAT_POWER_CTRL;
380791bc02SLaurent Vivier         break;
390791bc02SLaurent Vivier     default:
400791bc02SLaurent Vivier         qemu_log_mask(LOG_UNIMP,
410791bc02SLaurent Vivier                       "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
420791bc02SLaurent Vivier                       __func__, addr);
430791bc02SLaurent Vivier         break;
440791bc02SLaurent Vivier     }
450791bc02SLaurent Vivier 
460791bc02SLaurent Vivier     trace_virt_ctrl_write(s, addr, size, value);
470791bc02SLaurent Vivier 
480791bc02SLaurent Vivier     return value;
490791bc02SLaurent Vivier }
500791bc02SLaurent Vivier 
virt_ctrl_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)510791bc02SLaurent Vivier static void virt_ctrl_write(void *opaque, hwaddr addr, uint64_t value,
520791bc02SLaurent Vivier                             unsigned size)
530791bc02SLaurent Vivier {
540791bc02SLaurent Vivier     VirtCtrlState *s = opaque;
550791bc02SLaurent Vivier 
560791bc02SLaurent Vivier     trace_virt_ctrl_write(s, addr, size, value);
570791bc02SLaurent Vivier 
580791bc02SLaurent Vivier     switch (addr) {
590791bc02SLaurent Vivier     case REG_CMD:
600791bc02SLaurent Vivier         switch (value) {
610791bc02SLaurent Vivier         case CMD_NOOP:
620791bc02SLaurent Vivier             break;
630791bc02SLaurent Vivier         case CMD_RESET:
640791bc02SLaurent Vivier             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
650791bc02SLaurent Vivier             break;
660791bc02SLaurent Vivier         case CMD_HALT:
670791bc02SLaurent Vivier             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
680791bc02SLaurent Vivier             break;
690791bc02SLaurent Vivier         case CMD_PANIC:
700791bc02SLaurent Vivier             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
710791bc02SLaurent Vivier             break;
720791bc02SLaurent Vivier         }
730791bc02SLaurent Vivier         break;
740791bc02SLaurent Vivier     default:
750791bc02SLaurent Vivier         qemu_log_mask(LOG_UNIMP,
760791bc02SLaurent Vivier                       "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
770791bc02SLaurent Vivier                       __func__, addr);
780791bc02SLaurent Vivier         break;
790791bc02SLaurent Vivier     }
800791bc02SLaurent Vivier }
810791bc02SLaurent Vivier 
820791bc02SLaurent Vivier static const MemoryRegionOps virt_ctrl_ops = {
830791bc02SLaurent Vivier     .read = virt_ctrl_read,
840791bc02SLaurent Vivier     .write = virt_ctrl_write,
850791bc02SLaurent Vivier     .endianness = DEVICE_NATIVE_ENDIAN,
860791bc02SLaurent Vivier     .valid.max_access_size = 4,
870791bc02SLaurent Vivier     .impl.max_access_size = 4,
880791bc02SLaurent Vivier };
890791bc02SLaurent Vivier 
virt_ctrl_reset(DeviceState * dev)900791bc02SLaurent Vivier static void virt_ctrl_reset(DeviceState *dev)
910791bc02SLaurent Vivier {
920791bc02SLaurent Vivier     VirtCtrlState *s = VIRT_CTRL(dev);
930791bc02SLaurent Vivier 
940791bc02SLaurent Vivier     trace_virt_ctrl_reset(s);
950791bc02SLaurent Vivier }
960791bc02SLaurent Vivier 
virt_ctrl_realize(DeviceState * dev,Error ** errp)970791bc02SLaurent Vivier static void virt_ctrl_realize(DeviceState *dev, Error **errp)
980791bc02SLaurent Vivier {
990791bc02SLaurent Vivier     VirtCtrlState *s = VIRT_CTRL(dev);
1000791bc02SLaurent Vivier 
1010791bc02SLaurent Vivier     trace_virt_ctrl_instance_init(s);
1020791bc02SLaurent Vivier 
1030791bc02SLaurent Vivier     memory_region_init_io(&s->iomem, OBJECT(s), &virt_ctrl_ops, s,
1040791bc02SLaurent Vivier                           "virt-ctrl", 0x100);
1050791bc02SLaurent Vivier }
1060791bc02SLaurent Vivier 
1070791bc02SLaurent Vivier static const VMStateDescription vmstate_virt_ctrl = {
1080791bc02SLaurent Vivier     .name = "virt-ctrl",
1090791bc02SLaurent Vivier     .version_id = 1,
1100791bc02SLaurent Vivier     .minimum_version_id = 1,
1110791bc02SLaurent Vivier     .fields = (VMStateField[]) {
1120791bc02SLaurent Vivier         VMSTATE_UINT32(irq_enabled, VirtCtrlState),
1130791bc02SLaurent Vivier         VMSTATE_END_OF_LIST()
1140791bc02SLaurent Vivier     }
1150791bc02SLaurent Vivier };
1160791bc02SLaurent Vivier 
virt_ctrl_instance_init(Object * obj)1170791bc02SLaurent Vivier static void virt_ctrl_instance_init(Object *obj)
1180791bc02SLaurent Vivier {
1190791bc02SLaurent Vivier     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
1200791bc02SLaurent Vivier     VirtCtrlState *s = VIRT_CTRL(obj);
1210791bc02SLaurent Vivier 
1220791bc02SLaurent Vivier     trace_virt_ctrl_instance_init(s);
1230791bc02SLaurent Vivier 
1240791bc02SLaurent Vivier     sysbus_init_mmio(dev, &s->iomem);
1250791bc02SLaurent Vivier     sysbus_init_irq(dev, &s->irq);
1260791bc02SLaurent Vivier }
1270791bc02SLaurent Vivier 
virt_ctrl_class_init(ObjectClass * oc,void * data)1280791bc02SLaurent Vivier static void virt_ctrl_class_init(ObjectClass *oc, void *data)
1290791bc02SLaurent Vivier {
1300791bc02SLaurent Vivier     DeviceClass *dc = DEVICE_CLASS(oc);
1310791bc02SLaurent Vivier 
1320791bc02SLaurent Vivier     dc->reset = virt_ctrl_reset;
1330791bc02SLaurent Vivier     dc->realize = virt_ctrl_realize;
1340791bc02SLaurent Vivier     dc->vmsd = &vmstate_virt_ctrl;
1350791bc02SLaurent Vivier }
1360791bc02SLaurent Vivier 
1370791bc02SLaurent Vivier static const TypeInfo virt_ctrl_info = {
1380791bc02SLaurent Vivier     .name = TYPE_VIRT_CTRL,
1390791bc02SLaurent Vivier     .parent = TYPE_SYS_BUS_DEVICE,
1400791bc02SLaurent Vivier     .class_init = virt_ctrl_class_init,
1410791bc02SLaurent Vivier     .instance_init = virt_ctrl_instance_init,
1420791bc02SLaurent Vivier     .instance_size = sizeof(VirtCtrlState),
1430791bc02SLaurent Vivier };
1440791bc02SLaurent Vivier 
virt_ctrl_register_types(void)1450791bc02SLaurent Vivier static void virt_ctrl_register_types(void)
1460791bc02SLaurent Vivier {
1470791bc02SLaurent Vivier     type_register_static(&virt_ctrl_info);
1480791bc02SLaurent Vivier }
1490791bc02SLaurent Vivier 
1500791bc02SLaurent Vivier type_init(virt_ctrl_register_types)
151