xref: /qemu/hw/intc/loongarch_pch_msi.c (revision ed3a06b1)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * QEMU Loongson 7A1000 msi interrupt controller.
4  *
5  * Copyright (C) 2021 Loongson Technology Corporation Limited
6  */
7 
8 #include "qemu/osdep.h"
9 #include "hw/sysbus.h"
10 #include "hw/irq.h"
11 #include "hw/intc/loongarch_pch_msi.h"
12 #include "hw/intc/loongarch_pch_pic.h"
13 #include "hw/pci/msi.h"
14 #include "hw/misc/unimp.h"
15 #include "migration/vmstate.h"
16 #include "trace.h"
17 
18 static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned size)
19 {
20     return 0;
21 }
22 
23 static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
24                                     uint64_t val, unsigned size)
25 {
26     LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
27     int irq_num = val & 0xff;
28 
29     trace_loongarch_msi_set_irq(irq_num);
30     assert(irq_num < PCH_MSI_IRQ_NUM);
31     qemu_set_irq(s->pch_msi_irq[irq_num], 1);
32 }
33 
34 static const MemoryRegionOps loongarch_pch_msi_ops = {
35     .read  = loongarch_msi_mem_read,
36     .write = loongarch_msi_mem_write,
37     .endianness = DEVICE_LITTLE_ENDIAN,
38 };
39 
40 static void pch_msi_irq_handler(void *opaque, int irq, int level)
41 {
42     LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
43 
44     qemu_set_irq(s->pch_msi_irq[irq], level);
45 }
46 
47 static void loongarch_pch_msi_init(Object *obj)
48 {
49     LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
50     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
51 
52     memory_region_init_io(&s->msi_mmio, obj, &loongarch_pch_msi_ops,
53                           s, TYPE_LOONGARCH_PCH_MSI, 0x8);
54     sysbus_init_mmio(sbd, &s->msi_mmio);
55     msi_nonbroken = true;
56 
57     qdev_init_gpio_out(DEVICE(obj), s->pch_msi_irq, PCH_MSI_IRQ_NUM);
58     qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
59 }
60 
61 static const TypeInfo loongarch_pch_msi_info = {
62     .name          = TYPE_LOONGARCH_PCH_MSI,
63     .parent        = TYPE_SYS_BUS_DEVICE,
64     .instance_size = sizeof(LoongArchPCHMSI),
65     .instance_init = loongarch_pch_msi_init,
66 };
67 
68 static void loongarch_pch_msi_register_types(void)
69 {
70     type_register_static(&loongarch_pch_msi_info);
71 }
72 
73 type_init(loongarch_pch_msi_register_types)
74