xref: /qemu/hw/intc/loongarch_extioi_common.c (revision e45c96b7d62513327324e801c325b5b6530f8e4a)
16b69f778SBibo Mao /* SPDX-License-Identifier: GPL-2.0-or-later */
26b69f778SBibo Mao /*
36b69f778SBibo Mao  * Loongson extioi interrupt controller emulation
46b69f778SBibo Mao  * Copyright (C) 2024 Loongson Technology Corporation Limited
56b69f778SBibo Mao  */
6272c467aSBibo Mao #include "qemu/osdep.h"
7*e45c96b7SBibo Mao #include "qemu/error-report.h"
8272c467aSBibo Mao #include "qemu/module.h"
9272c467aSBibo Mao #include "qapi/error.h"
10272c467aSBibo Mao #include "hw/qdev-properties.h"
11272c467aSBibo Mao #include "hw/intc/loongarch_extioi_common.h"
12272c467aSBibo Mao #include "migration/vmstate.h"
13*e45c96b7SBibo Mao #include "target/loongarch/cpu.h"
14*e45c96b7SBibo Mao 
15*e45c96b7SBibo Mao static void loongarch_extioi_cpu_plug(HotplugHandler *hotplug_dev,
16*e45c96b7SBibo Mao                                       DeviceState *dev, Error **errp)
17*e45c96b7SBibo Mao {
18*e45c96b7SBibo Mao     Object *obj = OBJECT(dev);
19*e45c96b7SBibo Mao 
20*e45c96b7SBibo Mao     if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
21*e45c96b7SBibo Mao         warn_report("LoongArch extioi: Invalid %s device type",
22*e45c96b7SBibo Mao                                        object_get_typename(obj));
23*e45c96b7SBibo Mao         return;
24*e45c96b7SBibo Mao     }
25*e45c96b7SBibo Mao }
26*e45c96b7SBibo Mao 
27*e45c96b7SBibo Mao static void loongarch_extioi_cpu_unplug(HotplugHandler *hotplug_dev,
28*e45c96b7SBibo Mao                                         DeviceState *dev, Error **errp)
29*e45c96b7SBibo Mao {
30*e45c96b7SBibo Mao     Object *obj = OBJECT(dev);
31*e45c96b7SBibo Mao 
32*e45c96b7SBibo Mao     if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
33*e45c96b7SBibo Mao         warn_report("LoongArch extioi: Invalid %s device type",
34*e45c96b7SBibo Mao                                        object_get_typename(obj));
35*e45c96b7SBibo Mao         return;
36*e45c96b7SBibo Mao     }
37*e45c96b7SBibo Mao }
386b69f778SBibo Mao 
396b69f778SBibo Mao static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp)
406b69f778SBibo Mao {
416b69f778SBibo Mao     LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)dev;
425a3e068dSBibo Mao     MachineState *machine = MACHINE(qdev_get_machine());
435a3e068dSBibo Mao     MachineClass *mc = MACHINE_GET_CLASS(machine);
445a3e068dSBibo Mao     const CPUArchIdList *id_list;
458b4b668fSBibo Mao     int i, pin;
466b69f778SBibo Mao 
475a3e068dSBibo Mao     assert(mc->possible_cpu_arch_ids);
485a3e068dSBibo Mao     id_list = mc->possible_cpu_arch_ids(machine);
495a3e068dSBibo Mao     s->num_cpu = id_list->len;
505a3e068dSBibo Mao     s->cpu = g_new0(ExtIOICore, s->num_cpu);
515a3e068dSBibo Mao     if (s->cpu == NULL) {
525a3e068dSBibo Mao         error_setg(errp, "Memory allocation for ExtIOICore faile");
536b69f778SBibo Mao         return;
546b69f778SBibo Mao     }
555a3e068dSBibo Mao 
565a3e068dSBibo Mao     for (i = 0; i < s->num_cpu; i++) {
575a3e068dSBibo Mao         s->cpu[i].arch_id = id_list->cpus[i].arch_id;
585a3e068dSBibo Mao         s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
598b4b668fSBibo Mao 
608b4b668fSBibo Mao         for (pin = 0; pin < LS3A_INTC_IP; pin++) {
618b4b668fSBibo Mao             qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[pin], 1);
628b4b668fSBibo Mao         }
635a3e068dSBibo Mao     }
646b69f778SBibo Mao }
656b69f778SBibo Mao 
66ff09444aSBibo Mao static int loongarch_extioi_common_pre_save(void *opaque)
67ff09444aSBibo Mao {
68ff09444aSBibo Mao     LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque;
69ff09444aSBibo Mao     LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(s);
70ff09444aSBibo Mao 
71ff09444aSBibo Mao     if (lecc->pre_save) {
72ff09444aSBibo Mao         return lecc->pre_save(s);
73ff09444aSBibo Mao     }
74ff09444aSBibo Mao 
75ff09444aSBibo Mao     return 0;
76ff09444aSBibo Mao }
77ff09444aSBibo Mao 
786b69f778SBibo Mao static int loongarch_extioi_common_post_load(void *opaque, int version_id)
796b69f778SBibo Mao {
80272c467aSBibo Mao     LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque;
81272c467aSBibo Mao     LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(s);
82272c467aSBibo Mao 
83272c467aSBibo Mao     if (lecc->post_load) {
84272c467aSBibo Mao         return lecc->post_load(s, version_id);
85272c467aSBibo Mao     }
86272c467aSBibo Mao 
87272c467aSBibo Mao     return 0;
886b69f778SBibo Mao }
896b69f778SBibo Mao 
906b69f778SBibo Mao static const VMStateDescription vmstate_extioi_core = {
916b69f778SBibo Mao     .name = "extioi-core",
926b69f778SBibo Mao     .version_id = 1,
936b69f778SBibo Mao     .minimum_version_id = 1,
946b69f778SBibo Mao     .fields = (const VMStateField[]) {
956b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(coreisr, ExtIOICore, EXTIOI_IRQS_GROUP_COUNT),
966b69f778SBibo Mao         VMSTATE_END_OF_LIST()
976b69f778SBibo Mao     }
986b69f778SBibo Mao };
996b69f778SBibo Mao 
1006b69f778SBibo Mao static const VMStateDescription vmstate_loongarch_extioi = {
1016b69f778SBibo Mao     .name = "loongarch.extioi",
1026b69f778SBibo Mao     .version_id = 3,
1036b69f778SBibo Mao     .minimum_version_id = 3,
104ff09444aSBibo Mao     .pre_save  = loongarch_extioi_common_pre_save,
1056b69f778SBibo Mao     .post_load = loongarch_extioi_common_post_load,
1066b69f778SBibo Mao     .fields = (const VMStateField[]) {
1076b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOICommonState,
1086b69f778SBibo Mao                              EXTIOI_IRQS_GROUP_COUNT),
1096b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOICommonState,
1106b69f778SBibo Mao                              EXTIOI_IRQS_NODETYPE_COUNT / 2),
1116b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(enable, LoongArchExtIOICommonState,
1126b69f778SBibo Mao                              EXTIOI_IRQS / 32),
1136b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOICommonState,
1146b69f778SBibo Mao                              EXTIOI_IRQS / 32),
1156b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOICommonState,
1166b69f778SBibo Mao                              EXTIOI_IRQS_IPMAP_SIZE / 4),
1176b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOICommonState,
1186b69f778SBibo Mao                              EXTIOI_IRQS / 4),
1196b69f778SBibo Mao         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOICommonState,
1206b69f778SBibo Mao                              num_cpu, vmstate_extioi_core, ExtIOICore),
1216b69f778SBibo Mao         VMSTATE_UINT32(features, LoongArchExtIOICommonState),
1226b69f778SBibo Mao         VMSTATE_UINT32(status, LoongArchExtIOICommonState),
1236b69f778SBibo Mao         VMSTATE_END_OF_LIST()
1246b69f778SBibo Mao     }
1256b69f778SBibo Mao };
1266b69f778SBibo Mao 
1276b69f778SBibo Mao static const Property extioi_properties[] = {
1286b69f778SBibo Mao     DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOICommonState,
1296b69f778SBibo Mao                     features, EXTIOI_HAS_VIRT_EXTENSION, 0),
1306b69f778SBibo Mao };
131272c467aSBibo Mao 
132272c467aSBibo Mao static void loongarch_extioi_common_class_init(ObjectClass *klass, void *data)
133272c467aSBibo Mao {
134272c467aSBibo Mao     DeviceClass *dc = DEVICE_CLASS(klass);
135272c467aSBibo Mao     LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass);
136*e45c96b7SBibo Mao     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
137272c467aSBibo Mao 
138272c467aSBibo Mao     device_class_set_parent_realize(dc, loongarch_extioi_common_realize,
139272c467aSBibo Mao                                     &lecc->parent_realize);
140272c467aSBibo Mao     device_class_set_props(dc, extioi_properties);
141272c467aSBibo Mao     dc->vmsd = &vmstate_loongarch_extioi;
142*e45c96b7SBibo Mao     hc->plug = loongarch_extioi_cpu_plug;
143*e45c96b7SBibo Mao     hc->unplug = loongarch_extioi_cpu_unplug;
144272c467aSBibo Mao }
145272c467aSBibo Mao 
146272c467aSBibo Mao static const TypeInfo loongarch_extioi_common_types[] = {
147272c467aSBibo Mao     {
148272c467aSBibo Mao         .name               = TYPE_LOONGARCH_EXTIOI_COMMON,
149272c467aSBibo Mao         .parent             = TYPE_SYS_BUS_DEVICE,
150272c467aSBibo Mao         .instance_size      = sizeof(LoongArchExtIOICommonState),
151272c467aSBibo Mao         .class_size         = sizeof(LoongArchExtIOICommonClass),
152272c467aSBibo Mao         .class_init         = loongarch_extioi_common_class_init,
153*e45c96b7SBibo Mao         .interfaces         = (InterfaceInfo[]) {
154*e45c96b7SBibo Mao             { TYPE_HOTPLUG_HANDLER },
155*e45c96b7SBibo Mao             { }
156*e45c96b7SBibo Mao         },
157272c467aSBibo Mao         .abstract           = true,
158272c467aSBibo Mao     }
159272c467aSBibo Mao };
160272c467aSBibo Mao 
161272c467aSBibo Mao DEFINE_TYPES(loongarch_extioi_common_types)
162