xref: /qemu/hw/intc/loongarch_extioi_common.c (revision 8b4b668f6a3661885fcabcedcf812930d5577f7e)
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"
7272c467aSBibo Mao #include "qemu/module.h"
8272c467aSBibo Mao #include "qapi/error.h"
9272c467aSBibo Mao #include "hw/qdev-properties.h"
10272c467aSBibo Mao #include "hw/intc/loongarch_extioi_common.h"
11272c467aSBibo Mao #include "migration/vmstate.h"
126b69f778SBibo Mao 
136b69f778SBibo Mao static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp)
146b69f778SBibo Mao {
156b69f778SBibo Mao     LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)dev;
165a3e068dSBibo Mao     MachineState *machine = MACHINE(qdev_get_machine());
175a3e068dSBibo Mao     MachineClass *mc = MACHINE_GET_CLASS(machine);
185a3e068dSBibo Mao     const CPUArchIdList *id_list;
19*8b4b668fSBibo Mao     int i, pin;
206b69f778SBibo Mao 
215a3e068dSBibo Mao     assert(mc->possible_cpu_arch_ids);
225a3e068dSBibo Mao     id_list = mc->possible_cpu_arch_ids(machine);
235a3e068dSBibo Mao     s->num_cpu = id_list->len;
245a3e068dSBibo Mao     s->cpu = g_new0(ExtIOICore, s->num_cpu);
255a3e068dSBibo Mao     if (s->cpu == NULL) {
265a3e068dSBibo Mao         error_setg(errp, "Memory allocation for ExtIOICore faile");
276b69f778SBibo Mao         return;
286b69f778SBibo Mao     }
295a3e068dSBibo Mao 
305a3e068dSBibo Mao     for (i = 0; i < s->num_cpu; i++) {
315a3e068dSBibo Mao         s->cpu[i].arch_id = id_list->cpus[i].arch_id;
325a3e068dSBibo Mao         s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
33*8b4b668fSBibo Mao 
34*8b4b668fSBibo Mao         for (pin = 0; pin < LS3A_INTC_IP; pin++) {
35*8b4b668fSBibo Mao             qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[pin], 1);
36*8b4b668fSBibo Mao         }
375a3e068dSBibo Mao     }
386b69f778SBibo Mao }
396b69f778SBibo Mao 
40ff09444aSBibo Mao static int loongarch_extioi_common_pre_save(void *opaque)
41ff09444aSBibo Mao {
42ff09444aSBibo Mao     LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque;
43ff09444aSBibo Mao     LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(s);
44ff09444aSBibo Mao 
45ff09444aSBibo Mao     if (lecc->pre_save) {
46ff09444aSBibo Mao         return lecc->pre_save(s);
47ff09444aSBibo Mao     }
48ff09444aSBibo Mao 
49ff09444aSBibo Mao     return 0;
50ff09444aSBibo Mao }
51ff09444aSBibo Mao 
526b69f778SBibo Mao static int loongarch_extioi_common_post_load(void *opaque, int version_id)
536b69f778SBibo Mao {
54272c467aSBibo Mao     LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque;
55272c467aSBibo Mao     LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(s);
56272c467aSBibo Mao 
57272c467aSBibo Mao     if (lecc->post_load) {
58272c467aSBibo Mao         return lecc->post_load(s, version_id);
59272c467aSBibo Mao     }
60272c467aSBibo Mao 
61272c467aSBibo Mao     return 0;
626b69f778SBibo Mao }
636b69f778SBibo Mao 
646b69f778SBibo Mao static const VMStateDescription vmstate_extioi_core = {
656b69f778SBibo Mao     .name = "extioi-core",
666b69f778SBibo Mao     .version_id = 1,
676b69f778SBibo Mao     .minimum_version_id = 1,
686b69f778SBibo Mao     .fields = (const VMStateField[]) {
696b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(coreisr, ExtIOICore, EXTIOI_IRQS_GROUP_COUNT),
706b69f778SBibo Mao         VMSTATE_END_OF_LIST()
716b69f778SBibo Mao     }
726b69f778SBibo Mao };
736b69f778SBibo Mao 
746b69f778SBibo Mao static const VMStateDescription vmstate_loongarch_extioi = {
756b69f778SBibo Mao     .name = "loongarch.extioi",
766b69f778SBibo Mao     .version_id = 3,
776b69f778SBibo Mao     .minimum_version_id = 3,
78ff09444aSBibo Mao     .pre_save  = loongarch_extioi_common_pre_save,
796b69f778SBibo Mao     .post_load = loongarch_extioi_common_post_load,
806b69f778SBibo Mao     .fields = (const VMStateField[]) {
816b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOICommonState,
826b69f778SBibo Mao                              EXTIOI_IRQS_GROUP_COUNT),
836b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOICommonState,
846b69f778SBibo Mao                              EXTIOI_IRQS_NODETYPE_COUNT / 2),
856b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(enable, LoongArchExtIOICommonState,
866b69f778SBibo Mao                              EXTIOI_IRQS / 32),
876b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOICommonState,
886b69f778SBibo Mao                              EXTIOI_IRQS / 32),
896b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOICommonState,
906b69f778SBibo Mao                              EXTIOI_IRQS_IPMAP_SIZE / 4),
916b69f778SBibo Mao         VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOICommonState,
926b69f778SBibo Mao                              EXTIOI_IRQS / 4),
936b69f778SBibo Mao         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOICommonState,
946b69f778SBibo Mao                              num_cpu, vmstate_extioi_core, ExtIOICore),
956b69f778SBibo Mao         VMSTATE_UINT32(features, LoongArchExtIOICommonState),
966b69f778SBibo Mao         VMSTATE_UINT32(status, LoongArchExtIOICommonState),
976b69f778SBibo Mao         VMSTATE_END_OF_LIST()
986b69f778SBibo Mao     }
996b69f778SBibo Mao };
1006b69f778SBibo Mao 
1016b69f778SBibo Mao static const Property extioi_properties[] = {
1026b69f778SBibo Mao     DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOICommonState,
1036b69f778SBibo Mao                     features, EXTIOI_HAS_VIRT_EXTENSION, 0),
1046b69f778SBibo Mao };
105272c467aSBibo Mao 
106272c467aSBibo Mao static void loongarch_extioi_common_class_init(ObjectClass *klass, void *data)
107272c467aSBibo Mao {
108272c467aSBibo Mao     DeviceClass *dc = DEVICE_CLASS(klass);
109272c467aSBibo Mao     LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass);
110272c467aSBibo Mao 
111272c467aSBibo Mao     device_class_set_parent_realize(dc, loongarch_extioi_common_realize,
112272c467aSBibo Mao                                     &lecc->parent_realize);
113272c467aSBibo Mao     device_class_set_props(dc, extioi_properties);
114272c467aSBibo Mao     dc->vmsd = &vmstate_loongarch_extioi;
115272c467aSBibo Mao }
116272c467aSBibo Mao 
117272c467aSBibo Mao static const TypeInfo loongarch_extioi_common_types[] = {
118272c467aSBibo Mao     {
119272c467aSBibo Mao         .name               = TYPE_LOONGARCH_EXTIOI_COMMON,
120272c467aSBibo Mao         .parent             = TYPE_SYS_BUS_DEVICE,
121272c467aSBibo Mao         .instance_size      = sizeof(LoongArchExtIOICommonState),
122272c467aSBibo Mao         .class_size         = sizeof(LoongArchExtIOICommonClass),
123272c467aSBibo Mao         .class_init         = loongarch_extioi_common_class_init,
124272c467aSBibo Mao         .abstract           = true,
125272c467aSBibo Mao     }
126272c467aSBibo Mao };
127272c467aSBibo Mao 
128272c467aSBibo Mao DEFINE_TYPES(loongarch_extioi_common_types)
129