xref: /openbmc/qemu/hw/misc/virt_ctrl.c (revision 0791bc02)
1*0791bc02SLaurent Vivier /*
2*0791bc02SLaurent Vivier  * SPDX-License-Identifer: GPL-2.0-or-later
3*0791bc02SLaurent Vivier  *
4*0791bc02SLaurent Vivier  * Virt system Controller
5*0791bc02SLaurent Vivier  */
6*0791bc02SLaurent Vivier 
7*0791bc02SLaurent Vivier #include "qemu/osdep.h"
8*0791bc02SLaurent Vivier #include "hw/irq.h"
9*0791bc02SLaurent Vivier #include "hw/qdev-properties.h"
10*0791bc02SLaurent Vivier #include "hw/sysbus.h"
11*0791bc02SLaurent Vivier #include "migration/vmstate.h"
12*0791bc02SLaurent Vivier #include "qemu/log.h"
13*0791bc02SLaurent Vivier #include "trace.h"
14*0791bc02SLaurent Vivier #include "sysemu/runstate.h"
15*0791bc02SLaurent Vivier #include "hw/misc/virt_ctrl.h"
16*0791bc02SLaurent Vivier 
17*0791bc02SLaurent Vivier enum {
18*0791bc02SLaurent Vivier     REG_FEATURES = 0x00,
19*0791bc02SLaurent Vivier     REG_CMD      = 0x04,
20*0791bc02SLaurent Vivier };
21*0791bc02SLaurent Vivier 
22*0791bc02SLaurent Vivier #define FEAT_POWER_CTRL 0x00000001
23*0791bc02SLaurent Vivier 
24*0791bc02SLaurent Vivier enum {
25*0791bc02SLaurent Vivier     CMD_NOOP,
26*0791bc02SLaurent Vivier     CMD_RESET,
27*0791bc02SLaurent Vivier     CMD_HALT,
28*0791bc02SLaurent Vivier     CMD_PANIC,
29*0791bc02SLaurent Vivier };
30*0791bc02SLaurent Vivier 
31*0791bc02SLaurent Vivier static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, unsigned size)
32*0791bc02SLaurent Vivier {
33*0791bc02SLaurent Vivier     VirtCtrlState *s = opaque;
34*0791bc02SLaurent Vivier     uint64_t value = 0;
35*0791bc02SLaurent Vivier 
36*0791bc02SLaurent Vivier     switch (addr) {
37*0791bc02SLaurent Vivier     case REG_FEATURES:
38*0791bc02SLaurent Vivier         value = FEAT_POWER_CTRL;
39*0791bc02SLaurent Vivier         break;
40*0791bc02SLaurent Vivier     default:
41*0791bc02SLaurent Vivier         qemu_log_mask(LOG_UNIMP,
42*0791bc02SLaurent Vivier                       "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
43*0791bc02SLaurent Vivier                       __func__, addr);
44*0791bc02SLaurent Vivier         break;
45*0791bc02SLaurent Vivier     }
46*0791bc02SLaurent Vivier 
47*0791bc02SLaurent Vivier     trace_virt_ctrl_write(s, addr, size, value);
48*0791bc02SLaurent Vivier 
49*0791bc02SLaurent Vivier     return value;
50*0791bc02SLaurent Vivier }
51*0791bc02SLaurent Vivier 
52*0791bc02SLaurent Vivier static void virt_ctrl_write(void *opaque, hwaddr addr, uint64_t value,
53*0791bc02SLaurent Vivier                             unsigned size)
54*0791bc02SLaurent Vivier {
55*0791bc02SLaurent Vivier     VirtCtrlState *s = opaque;
56*0791bc02SLaurent Vivier 
57*0791bc02SLaurent Vivier     trace_virt_ctrl_write(s, addr, size, value);
58*0791bc02SLaurent Vivier 
59*0791bc02SLaurent Vivier     switch (addr) {
60*0791bc02SLaurent Vivier     case REG_CMD:
61*0791bc02SLaurent Vivier         switch (value) {
62*0791bc02SLaurent Vivier         case CMD_NOOP:
63*0791bc02SLaurent Vivier             break;
64*0791bc02SLaurent Vivier         case CMD_RESET:
65*0791bc02SLaurent Vivier             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
66*0791bc02SLaurent Vivier             break;
67*0791bc02SLaurent Vivier         case CMD_HALT:
68*0791bc02SLaurent Vivier             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
69*0791bc02SLaurent Vivier             break;
70*0791bc02SLaurent Vivier         case CMD_PANIC:
71*0791bc02SLaurent Vivier             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
72*0791bc02SLaurent Vivier             break;
73*0791bc02SLaurent Vivier         }
74*0791bc02SLaurent Vivier         break;
75*0791bc02SLaurent Vivier     default:
76*0791bc02SLaurent Vivier         qemu_log_mask(LOG_UNIMP,
77*0791bc02SLaurent Vivier                       "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
78*0791bc02SLaurent Vivier                       __func__, addr);
79*0791bc02SLaurent Vivier         break;
80*0791bc02SLaurent Vivier     }
81*0791bc02SLaurent Vivier }
82*0791bc02SLaurent Vivier 
83*0791bc02SLaurent Vivier static const MemoryRegionOps virt_ctrl_ops = {
84*0791bc02SLaurent Vivier     .read = virt_ctrl_read,
85*0791bc02SLaurent Vivier     .write = virt_ctrl_write,
86*0791bc02SLaurent Vivier     .endianness = DEVICE_NATIVE_ENDIAN,
87*0791bc02SLaurent Vivier     .valid.max_access_size = 4,
88*0791bc02SLaurent Vivier     .impl.max_access_size = 4,
89*0791bc02SLaurent Vivier };
90*0791bc02SLaurent Vivier 
91*0791bc02SLaurent Vivier static void virt_ctrl_reset(DeviceState *dev)
92*0791bc02SLaurent Vivier {
93*0791bc02SLaurent Vivier     VirtCtrlState *s = VIRT_CTRL(dev);
94*0791bc02SLaurent Vivier 
95*0791bc02SLaurent Vivier     trace_virt_ctrl_reset(s);
96*0791bc02SLaurent Vivier }
97*0791bc02SLaurent Vivier 
98*0791bc02SLaurent Vivier static void virt_ctrl_realize(DeviceState *dev, Error **errp)
99*0791bc02SLaurent Vivier {
100*0791bc02SLaurent Vivier     VirtCtrlState *s = VIRT_CTRL(dev);
101*0791bc02SLaurent Vivier 
102*0791bc02SLaurent Vivier     trace_virt_ctrl_instance_init(s);
103*0791bc02SLaurent Vivier 
104*0791bc02SLaurent Vivier     memory_region_init_io(&s->iomem, OBJECT(s), &virt_ctrl_ops, s,
105*0791bc02SLaurent Vivier                           "virt-ctrl", 0x100);
106*0791bc02SLaurent Vivier }
107*0791bc02SLaurent Vivier 
108*0791bc02SLaurent Vivier static const VMStateDescription vmstate_virt_ctrl = {
109*0791bc02SLaurent Vivier     .name = "virt-ctrl",
110*0791bc02SLaurent Vivier     .version_id = 1,
111*0791bc02SLaurent Vivier     .minimum_version_id = 1,
112*0791bc02SLaurent Vivier     .fields = (VMStateField[]) {
113*0791bc02SLaurent Vivier         VMSTATE_UINT32(irq_enabled, VirtCtrlState),
114*0791bc02SLaurent Vivier         VMSTATE_END_OF_LIST()
115*0791bc02SLaurent Vivier     }
116*0791bc02SLaurent Vivier };
117*0791bc02SLaurent Vivier 
118*0791bc02SLaurent Vivier static void virt_ctrl_instance_init(Object *obj)
119*0791bc02SLaurent Vivier {
120*0791bc02SLaurent Vivier     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
121*0791bc02SLaurent Vivier     VirtCtrlState *s = VIRT_CTRL(obj);
122*0791bc02SLaurent Vivier 
123*0791bc02SLaurent Vivier     trace_virt_ctrl_instance_init(s);
124*0791bc02SLaurent Vivier 
125*0791bc02SLaurent Vivier     sysbus_init_mmio(dev, &s->iomem);
126*0791bc02SLaurent Vivier     sysbus_init_irq(dev, &s->irq);
127*0791bc02SLaurent Vivier }
128*0791bc02SLaurent Vivier 
129*0791bc02SLaurent Vivier static void virt_ctrl_class_init(ObjectClass *oc, void *data)
130*0791bc02SLaurent Vivier {
131*0791bc02SLaurent Vivier     DeviceClass *dc = DEVICE_CLASS(oc);
132*0791bc02SLaurent Vivier 
133*0791bc02SLaurent Vivier     dc->reset = virt_ctrl_reset;
134*0791bc02SLaurent Vivier     dc->realize = virt_ctrl_realize;
135*0791bc02SLaurent Vivier     dc->vmsd = &vmstate_virt_ctrl;
136*0791bc02SLaurent Vivier }
137*0791bc02SLaurent Vivier 
138*0791bc02SLaurent Vivier static const TypeInfo virt_ctrl_info = {
139*0791bc02SLaurent Vivier     .name = TYPE_VIRT_CTRL,
140*0791bc02SLaurent Vivier     .parent = TYPE_SYS_BUS_DEVICE,
141*0791bc02SLaurent Vivier     .class_init = virt_ctrl_class_init,
142*0791bc02SLaurent Vivier     .instance_init = virt_ctrl_instance_init,
143*0791bc02SLaurent Vivier     .instance_size = sizeof(VirtCtrlState),
144*0791bc02SLaurent Vivier };
145*0791bc02SLaurent Vivier 
146*0791bc02SLaurent Vivier static void virt_ctrl_register_types(void)
147*0791bc02SLaurent Vivier {
148*0791bc02SLaurent Vivier     type_register_static(&virt_ctrl_info);
149*0791bc02SLaurent Vivier }
150*0791bc02SLaurent Vivier 
151*0791bc02SLaurent Vivier type_init(virt_ctrl_register_types)
152