xref: /qemu/hw/intc/loongarch_pic_common.c (revision 864813878951b44e964eb4c012d832fd21f8cc0c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * QEMU Loongson 7A1000 I/O interrupt controller.
4  * Copyright (C) 2024 Loongson Technology Corporation Limited
5  */
6 
7 #include "qemu/osdep.h"
8 #include "qapi/error.h"
9 #include "hw/intc/loongarch_pic_common.h"
10 #include "hw/qdev-properties.h"
11 #include "migration/vmstate.h"
12 
loongarch_pic_pre_save(void * opaque)13 static int loongarch_pic_pre_save(void *opaque)
14 {
15     LoongArchPICCommonState *s = (LoongArchPICCommonState *)opaque;
16     LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_GET_CLASS(s);
17 
18     if (lpcc->pre_save) {
19         return lpcc->pre_save(s);
20     }
21 
22     return 0;
23 }
24 
loongarch_pic_post_load(void * opaque,int version_id)25 static int loongarch_pic_post_load(void *opaque, int version_id)
26 {
27     LoongArchPICCommonState *s = (LoongArchPICCommonState *)opaque;
28     LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_GET_CLASS(s);
29 
30     if (lpcc->post_load) {
31         return lpcc->post_load(s, version_id);
32     }
33 
34     return 0;
35 }
36 
loongarch_pic_common_realize(DeviceState * dev,Error ** errp)37 static void loongarch_pic_common_realize(DeviceState *dev, Error **errp)
38 {
39     LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(dev);
40 
41     if (!s->irq_num || s->irq_num  > VIRT_PCH_PIC_IRQ_NUM) {
42         error_setg(errp, "Invalid 'pic_irq_num'");
43         return;
44     }
45 }
46 
loongarch_pic_common_reset_hold(Object * obj,ResetType type)47 static void loongarch_pic_common_reset_hold(Object *obj, ResetType type)
48 {
49     LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(obj);
50     int i;
51 
52     /*
53      * With Loongson 7A1000 user manual
54      * Chapter 5.2 "Description of Interrupt-related Registers"
55      *
56      * Interrupt controller identification register 1
57      *   Bit 24-31 Interrupt Controller ID
58      * Interrupt controller identification register 2
59      *   Bit  0-7  Interrupt Controller version number
60      *   Bit 16-23 The number of interrupt sources supported
61      */
62     s->id.desc.id = PCH_PIC_INT_ID_VAL;
63     s->id.desc.version = PCH_PIC_INT_ID_VER;
64     s->id.desc.irq_num = s->irq_num - 1;
65     s->int_mask = UINT64_MAX;
66     s->htmsi_en = 0x0;
67     s->intedge  = 0x0;
68     s->intclr   = 0x0;
69     s->auto_crtl0 = 0x0;
70     s->auto_crtl1 = 0x0;
71     for (i = 0; i < 64; i++) {
72         s->route_entry[i] = 0x1;
73         s->htmsi_vector[i] = 0x0;
74     }
75     s->intirr = 0x0;
76     s->intisr = 0x0;
77     s->last_intirr = 0x0;
78     s->int_polarity = 0x0;
79 }
80 
81 static const Property loongarch_pic_common_properties[] = {
82     DEFINE_PROP_UINT32("pch_pic_irq_num", LoongArchPICCommonState, irq_num, 0),
83 };
84 
85 static const VMStateDescription vmstate_loongarch_pic_common = {
86     .name = "loongarch_pch_pic",
87     .version_id = 1,
88     .minimum_version_id = 1,
89     .pre_save  = loongarch_pic_pre_save,
90     .post_load = loongarch_pic_post_load,
91     .fields = (const VMStateField[]) {
92         VMSTATE_UINT64(int_mask, LoongArchPICCommonState),
93         VMSTATE_UINT64(htmsi_en, LoongArchPICCommonState),
94         VMSTATE_UINT64(intedge, LoongArchPICCommonState),
95         VMSTATE_UINT64(intclr, LoongArchPICCommonState),
96         VMSTATE_UINT64(auto_crtl0, LoongArchPICCommonState),
97         VMSTATE_UINT64(auto_crtl1, LoongArchPICCommonState),
98         VMSTATE_UINT8_ARRAY(route_entry, LoongArchPICCommonState, 64),
99         VMSTATE_UINT8_ARRAY(htmsi_vector, LoongArchPICCommonState, 64),
100         VMSTATE_UINT64(last_intirr, LoongArchPICCommonState),
101         VMSTATE_UINT64(intirr, LoongArchPICCommonState),
102         VMSTATE_UINT64(intisr, LoongArchPICCommonState),
103         VMSTATE_UINT64(int_polarity, LoongArchPICCommonState),
104         VMSTATE_END_OF_LIST()
105     }
106 };
107 
loongarch_pic_common_class_init(ObjectClass * klass,const void * data)108 static void loongarch_pic_common_class_init(ObjectClass *klass,
109                                             const void *data)
110 {
111     DeviceClass *dc = DEVICE_CLASS(klass);
112     LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_CLASS(klass);
113     ResettableClass *rc = RESETTABLE_CLASS(klass);
114 
115     device_class_set_parent_realize(dc, loongarch_pic_common_realize,
116                                     &lpcc->parent_realize);
117     resettable_class_set_parent_phases(rc, NULL,
118                                        loongarch_pic_common_reset_hold,
119                                        NULL, &lpcc->parent_phases);
120     device_class_set_props(dc, loongarch_pic_common_properties);
121     dc->vmsd = &vmstate_loongarch_pic_common;
122 }
123 
124 static const TypeInfo loongarch_pic_common_types[] = {
125     {
126         .name               = TYPE_LOONGARCH_PIC_COMMON,
127         .parent             = TYPE_SYS_BUS_DEVICE,
128         .instance_size      = sizeof(LoongArchPICCommonState),
129         .class_size         = sizeof(LoongArchPICCommonClass),
130         .class_init         = loongarch_pic_common_class_init,
131         .abstract           = true,
132     }
133 };
134 
135 DEFINE_TYPES(loongarch_pic_common_types)
136