1b4a12dfcSJiaxun Yang /* SPDX-License-Identifier: GPL-2.0-or-later */ 2b4a12dfcSJiaxun Yang /* 3b4a12dfcSJiaxun Yang * Loongson ipi interrupt support 4b4a12dfcSJiaxun Yang * 5b4a12dfcSJiaxun Yang * Copyright (C) 2021 Loongson Technology Corporation Limited 6b4a12dfcSJiaxun Yang */ 7b4a12dfcSJiaxun Yang 8b4a12dfcSJiaxun Yang #include "qemu/osdep.h" 9b4a12dfcSJiaxun Yang #include "hw/boards.h" 10b4a12dfcSJiaxun Yang #include "hw/sysbus.h" 11b4a12dfcSJiaxun Yang #include "hw/intc/loongson_ipi.h" 12b4a12dfcSJiaxun Yang #include "hw/irq.h" 13b4a12dfcSJiaxun Yang #include "hw/qdev-properties.h" 14b4a12dfcSJiaxun Yang #include "qapi/error.h" 15b4a12dfcSJiaxun Yang #include "qemu/log.h" 16b4a12dfcSJiaxun Yang #include "exec/address-spaces.h" 172465c89fSBibo Mao #include "exec/memory.h" 18b4a12dfcSJiaxun Yang #include "migration/vmstate.h" 1991d0b151SJiaxun Yang #ifdef TARGET_LOONGARCH64 20b4a12dfcSJiaxun Yang #include "target/loongarch/cpu.h" 2191d0b151SJiaxun Yang #endif 2291d0b151SJiaxun Yang #ifdef TARGET_MIPS 2391d0b151SJiaxun Yang #include "target/mips/cpu.h" 2491d0b151SJiaxun Yang #endif 25b4a12dfcSJiaxun Yang #include "trace.h" 26b4a12dfcSJiaxun Yang 2749eba52aSJiaxun Yang static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, 28b4a12dfcSJiaxun Yang uint64_t *data, 29b4a12dfcSJiaxun Yang unsigned size, MemTxAttrs attrs) 30b4a12dfcSJiaxun Yang { 3149eba52aSJiaxun Yang IPICore *s = opaque; 32b4a12dfcSJiaxun Yang uint64_t ret = 0; 33b4a12dfcSJiaxun Yang int index = 0; 34b4a12dfcSJiaxun Yang 35b4a12dfcSJiaxun Yang addr &= 0xff; 36b4a12dfcSJiaxun Yang switch (addr) { 37b4a12dfcSJiaxun Yang case CORE_STATUS_OFF: 38b4a12dfcSJiaxun Yang ret = s->status; 39b4a12dfcSJiaxun Yang break; 40b4a12dfcSJiaxun Yang case CORE_EN_OFF: 41b4a12dfcSJiaxun Yang ret = s->en; 42b4a12dfcSJiaxun Yang break; 43b4a12dfcSJiaxun Yang case CORE_SET_OFF: 44b4a12dfcSJiaxun Yang ret = 0; 45b4a12dfcSJiaxun Yang break; 46b4a12dfcSJiaxun Yang case CORE_CLEAR_OFF: 47b4a12dfcSJiaxun Yang ret = 0; 48b4a12dfcSJiaxun Yang break; 49b4a12dfcSJiaxun Yang case CORE_BUF_20 ... CORE_BUF_38 + 4: 50b4a12dfcSJiaxun Yang index = (addr - CORE_BUF_20) >> 2; 51b4a12dfcSJiaxun Yang ret = s->buf[index]; 52b4a12dfcSJiaxun Yang break; 53b4a12dfcSJiaxun Yang default: 54b4a12dfcSJiaxun Yang qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); 55b4a12dfcSJiaxun Yang break; 56b4a12dfcSJiaxun Yang } 57b4a12dfcSJiaxun Yang 58b4a12dfcSJiaxun Yang trace_loongson_ipi_read(size, (uint64_t)addr, ret); 59b4a12dfcSJiaxun Yang *data = ret; 60b4a12dfcSJiaxun Yang return MEMTX_OK; 61b4a12dfcSJiaxun Yang } 62b4a12dfcSJiaxun Yang 6349eba52aSJiaxun Yang static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, 6449eba52aSJiaxun Yang uint64_t *data, 6549eba52aSJiaxun Yang unsigned size, MemTxAttrs attrs) 6649eba52aSJiaxun Yang { 676c8698a5SBibo Mao LoongsonIPICommonState *ipi = opaque; 6849eba52aSJiaxun Yang IPICore *s; 6949eba52aSJiaxun Yang 7049eba52aSJiaxun Yang if (attrs.requester_id >= ipi->num_cpu) { 7149eba52aSJiaxun Yang return MEMTX_DECODE_ERROR; 7249eba52aSJiaxun Yang } 7349eba52aSJiaxun Yang 7449eba52aSJiaxun Yang s = &ipi->cpu[attrs.requester_id]; 7549eba52aSJiaxun Yang return loongson_ipi_core_readl(s, addr, data, size, attrs); 7649eba52aSJiaxun Yang } 7749eba52aSJiaxun Yang 7891d0b151SJiaxun Yang static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) 7991d0b151SJiaxun Yang { 8091d0b151SJiaxun Yang #ifdef TARGET_LOONGARCH64 8191d0b151SJiaxun Yang return LOONGARCH_CPU(cpu)->env.address_space_iocsr; 8291d0b151SJiaxun Yang #endif 8391d0b151SJiaxun Yang #ifdef TARGET_MIPS 8491d0b151SJiaxun Yang if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) { 8591d0b151SJiaxun Yang return &MIPS_CPU(cpu)->env.iocsr.as; 8691d0b151SJiaxun Yang } 8791d0b151SJiaxun Yang #endif 8891d0b151SJiaxun Yang return NULL; 8991d0b151SJiaxun Yang } 9091d0b151SJiaxun Yang 91*ed722e0eSBibo Mao static MemTxResult send_ipi_data(LoongsonIPICommonState *ipi, CPUState *cpu, 92*ed722e0eSBibo Mao uint64_t val, hwaddr addr, MemTxAttrs attrs) 93b4a12dfcSJiaxun Yang { 94b4a12dfcSJiaxun Yang int i, mask = 0, data = 0; 9591d0b151SJiaxun Yang AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu); 9691d0b151SJiaxun Yang 9791d0b151SJiaxun Yang if (!iocsr_as) { 9891d0b151SJiaxun Yang return MEMTX_DECODE_ERROR; 9991d0b151SJiaxun Yang } 100b4a12dfcSJiaxun Yang 101b4a12dfcSJiaxun Yang /* 102b4a12dfcSJiaxun Yang * bit 27-30 is mask for byte writing, 103b4a12dfcSJiaxun Yang * if the mask is 0, we need not to do anything. 104b4a12dfcSJiaxun Yang */ 105b4a12dfcSJiaxun Yang if ((val >> 27) & 0xf) { 1062465c89fSBibo Mao data = address_space_ldl_le(iocsr_as, addr, attrs, NULL); 107b4a12dfcSJiaxun Yang for (i = 0; i < 4; i++) { 108b4a12dfcSJiaxun Yang /* get mask for byte writing */ 109b4a12dfcSJiaxun Yang if (val & (0x1 << (27 + i))) { 110b4a12dfcSJiaxun Yang mask |= 0xff << (i * 8); 111b4a12dfcSJiaxun Yang } 112b4a12dfcSJiaxun Yang } 113b4a12dfcSJiaxun Yang } 114b4a12dfcSJiaxun Yang 115b4a12dfcSJiaxun Yang data &= mask; 116b4a12dfcSJiaxun Yang data |= (val >> 32) & ~mask; 1172465c89fSBibo Mao address_space_stl_le(iocsr_as, addr, data, attrs, NULL); 11891d0b151SJiaxun Yang 11991d0b151SJiaxun Yang return MEMTX_OK; 120b4a12dfcSJiaxun Yang } 121b4a12dfcSJiaxun Yang 122*ed722e0eSBibo Mao static MemTxResult mail_send(LoongsonIPICommonState *ipi, 123*ed722e0eSBibo Mao uint64_t val, MemTxAttrs attrs) 124b4a12dfcSJiaxun Yang { 125b4a12dfcSJiaxun Yang uint32_t cpuid; 126b4a12dfcSJiaxun Yang hwaddr addr; 127b4a12dfcSJiaxun Yang CPUState *cs; 128b4a12dfcSJiaxun Yang 129b4a12dfcSJiaxun Yang cpuid = extract32(val, 16, 10); 13003ca348bSJiaxun Yang cs = cpu_by_arch_id(cpuid); 131b4a12dfcSJiaxun Yang if (cs == NULL) { 132b4a12dfcSJiaxun Yang return MEMTX_DECODE_ERROR; 133b4a12dfcSJiaxun Yang } 134b4a12dfcSJiaxun Yang 135b4a12dfcSJiaxun Yang /* override requester_id */ 136b4a12dfcSJiaxun Yang addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); 137b4a12dfcSJiaxun Yang attrs.requester_id = cs->cpu_index; 138*ed722e0eSBibo Mao return send_ipi_data(ipi, cs, val, addr, attrs); 139b4a12dfcSJiaxun Yang } 140b4a12dfcSJiaxun Yang 141*ed722e0eSBibo Mao static MemTxResult any_send(LoongsonIPICommonState *ipi, 142*ed722e0eSBibo Mao uint64_t val, MemTxAttrs attrs) 143b4a12dfcSJiaxun Yang { 144b4a12dfcSJiaxun Yang uint32_t cpuid; 145b4a12dfcSJiaxun Yang hwaddr addr; 146b4a12dfcSJiaxun Yang CPUState *cs; 147b4a12dfcSJiaxun Yang 148b4a12dfcSJiaxun Yang cpuid = extract32(val, 16, 10); 14903ca348bSJiaxun Yang cs = cpu_by_arch_id(cpuid); 150b4a12dfcSJiaxun Yang if (cs == NULL) { 151b4a12dfcSJiaxun Yang return MEMTX_DECODE_ERROR; 152b4a12dfcSJiaxun Yang } 153b4a12dfcSJiaxun Yang 154b4a12dfcSJiaxun Yang /* override requester_id */ 155b4a12dfcSJiaxun Yang addr = val & 0xffff; 156b4a12dfcSJiaxun Yang attrs.requester_id = cs->cpu_index; 157*ed722e0eSBibo Mao return send_ipi_data(ipi, cs, val, addr, attrs); 158b4a12dfcSJiaxun Yang } 159b4a12dfcSJiaxun Yang 16049eba52aSJiaxun Yang static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, 16149eba52aSJiaxun Yang uint64_t val, unsigned size, 16249eba52aSJiaxun Yang MemTxAttrs attrs) 163b4a12dfcSJiaxun Yang { 16449eba52aSJiaxun Yang IPICore *s = opaque; 1656c8698a5SBibo Mao LoongsonIPICommonState *ipi = s->ipi; 166b4a12dfcSJiaxun Yang int index = 0; 167b4a12dfcSJiaxun Yang uint32_t cpuid; 168b4a12dfcSJiaxun Yang uint8_t vector; 169b4a12dfcSJiaxun Yang CPUState *cs; 170b4a12dfcSJiaxun Yang 171b4a12dfcSJiaxun Yang addr &= 0xff; 172b4a12dfcSJiaxun Yang trace_loongson_ipi_write(size, (uint64_t)addr, val); 173b4a12dfcSJiaxun Yang switch (addr) { 174b4a12dfcSJiaxun Yang case CORE_STATUS_OFF: 175b4a12dfcSJiaxun Yang qemu_log_mask(LOG_GUEST_ERROR, "can not be written"); 176b4a12dfcSJiaxun Yang break; 177b4a12dfcSJiaxun Yang case CORE_EN_OFF: 178b4a12dfcSJiaxun Yang s->en = val; 179b4a12dfcSJiaxun Yang break; 180b4a12dfcSJiaxun Yang case CORE_SET_OFF: 181b4a12dfcSJiaxun Yang s->status |= val; 182b4a12dfcSJiaxun Yang if (s->status != 0 && (s->status & s->en) != 0) { 183b4a12dfcSJiaxun Yang qemu_irq_raise(s->irq); 184b4a12dfcSJiaxun Yang } 185b4a12dfcSJiaxun Yang break; 186b4a12dfcSJiaxun Yang case CORE_CLEAR_OFF: 187b4a12dfcSJiaxun Yang s->status &= ~val; 188b4a12dfcSJiaxun Yang if (s->status == 0 && s->en != 0) { 189b4a12dfcSJiaxun Yang qemu_irq_lower(s->irq); 190b4a12dfcSJiaxun Yang } 191b4a12dfcSJiaxun Yang break; 192b4a12dfcSJiaxun Yang case CORE_BUF_20 ... CORE_BUF_38 + 4: 193b4a12dfcSJiaxun Yang index = (addr - CORE_BUF_20) >> 2; 194b4a12dfcSJiaxun Yang s->buf[index] = val; 195b4a12dfcSJiaxun Yang break; 196b4a12dfcSJiaxun Yang case IOCSR_IPI_SEND: 197b4a12dfcSJiaxun Yang cpuid = extract32(val, 16, 10); 198b4a12dfcSJiaxun Yang /* IPI status vector */ 199b4a12dfcSJiaxun Yang vector = extract8(val, 0, 5); 20003ca348bSJiaxun Yang cs = cpu_by_arch_id(cpuid); 20149eba52aSJiaxun Yang if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { 202b4a12dfcSJiaxun Yang return MEMTX_DECODE_ERROR; 203b4a12dfcSJiaxun Yang } 20449eba52aSJiaxun Yang loongson_ipi_core_writel(&ipi->cpu[cs->cpu_index], CORE_SET_OFF, 20549eba52aSJiaxun Yang BIT(vector), 4, attrs); 206b4a12dfcSJiaxun Yang break; 207b4a12dfcSJiaxun Yang default: 208b4a12dfcSJiaxun Yang qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); 209b4a12dfcSJiaxun Yang break; 210b4a12dfcSJiaxun Yang } 211b4a12dfcSJiaxun Yang 212b4a12dfcSJiaxun Yang return MEMTX_OK; 213b4a12dfcSJiaxun Yang } 214b4a12dfcSJiaxun Yang 21549eba52aSJiaxun Yang static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, 21649eba52aSJiaxun Yang uint64_t val, unsigned size, 21749eba52aSJiaxun Yang MemTxAttrs attrs) 21849eba52aSJiaxun Yang { 2196c8698a5SBibo Mao LoongsonIPICommonState *ipi = opaque; 22049eba52aSJiaxun Yang IPICore *s; 22149eba52aSJiaxun Yang 22249eba52aSJiaxun Yang if (attrs.requester_id >= ipi->num_cpu) { 22349eba52aSJiaxun Yang return MEMTX_DECODE_ERROR; 22449eba52aSJiaxun Yang } 22549eba52aSJiaxun Yang 22649eba52aSJiaxun Yang s = &ipi->cpu[attrs.requester_id]; 22749eba52aSJiaxun Yang return loongson_ipi_core_writel(s, addr, val, size, attrs); 22849eba52aSJiaxun Yang } 22949eba52aSJiaxun Yang 23049eba52aSJiaxun Yang static const MemoryRegionOps loongson_ipi_core_ops = { 23149eba52aSJiaxun Yang .read_with_attrs = loongson_ipi_core_readl, 23249eba52aSJiaxun Yang .write_with_attrs = loongson_ipi_core_writel, 23349eba52aSJiaxun Yang .impl.min_access_size = 4, 23449eba52aSJiaxun Yang .impl.max_access_size = 4, 23549eba52aSJiaxun Yang .valid.min_access_size = 4, 23649eba52aSJiaxun Yang .valid.max_access_size = 8, 23749eba52aSJiaxun Yang .endianness = DEVICE_LITTLE_ENDIAN, 23849eba52aSJiaxun Yang }; 23949eba52aSJiaxun Yang 24049eba52aSJiaxun Yang static const MemoryRegionOps loongson_ipi_iocsr_ops = { 24149eba52aSJiaxun Yang .read_with_attrs = loongson_ipi_iocsr_readl, 24249eba52aSJiaxun Yang .write_with_attrs = loongson_ipi_iocsr_writel, 243b4a12dfcSJiaxun Yang .impl.min_access_size = 4, 244b4a12dfcSJiaxun Yang .impl.max_access_size = 4, 245b4a12dfcSJiaxun Yang .valid.min_access_size = 4, 246b4a12dfcSJiaxun Yang .valid.max_access_size = 8, 247b4a12dfcSJiaxun Yang .endianness = DEVICE_LITTLE_ENDIAN, 248b4a12dfcSJiaxun Yang }; 249b4a12dfcSJiaxun Yang 250b4a12dfcSJiaxun Yang /* mail send and any send only support writeq */ 251b4a12dfcSJiaxun Yang static MemTxResult loongson_ipi_writeq(void *opaque, hwaddr addr, uint64_t val, 252b4a12dfcSJiaxun Yang unsigned size, MemTxAttrs attrs) 253b4a12dfcSJiaxun Yang { 254*ed722e0eSBibo Mao LoongsonIPICommonState *ipi = opaque; 255b4a12dfcSJiaxun Yang MemTxResult ret = MEMTX_OK; 256b4a12dfcSJiaxun Yang 257b4a12dfcSJiaxun Yang addr &= 0xfff; 258b4a12dfcSJiaxun Yang switch (addr) { 259b4a12dfcSJiaxun Yang case MAIL_SEND_OFFSET: 260*ed722e0eSBibo Mao ret = mail_send(ipi, val, attrs); 261b4a12dfcSJiaxun Yang break; 262b4a12dfcSJiaxun Yang case ANY_SEND_OFFSET: 263*ed722e0eSBibo Mao ret = any_send(ipi, val, attrs); 264b4a12dfcSJiaxun Yang break; 265b4a12dfcSJiaxun Yang default: 266b4a12dfcSJiaxun Yang break; 267b4a12dfcSJiaxun Yang } 268b4a12dfcSJiaxun Yang 269b4a12dfcSJiaxun Yang return ret; 270b4a12dfcSJiaxun Yang } 271b4a12dfcSJiaxun Yang 272b4a12dfcSJiaxun Yang static const MemoryRegionOps loongson_ipi64_ops = { 273b4a12dfcSJiaxun Yang .write_with_attrs = loongson_ipi_writeq, 274b4a12dfcSJiaxun Yang .impl.min_access_size = 8, 275b4a12dfcSJiaxun Yang .impl.max_access_size = 8, 276b4a12dfcSJiaxun Yang .valid.min_access_size = 8, 277b4a12dfcSJiaxun Yang .valid.max_access_size = 8, 278b4a12dfcSJiaxun Yang .endianness = DEVICE_LITTLE_ENDIAN, 279b4a12dfcSJiaxun Yang }; 280b4a12dfcSJiaxun Yang 281530e6dafSBibo Mao static void loongson_ipi_common_realize(DeviceState *dev, Error **errp) 282b4a12dfcSJiaxun Yang { 2836c8698a5SBibo Mao LoongsonIPICommonState *s = LOONGSON_IPI_COMMON(dev); 284b4a12dfcSJiaxun Yang SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 285b4a12dfcSJiaxun Yang int i; 286b4a12dfcSJiaxun Yang 287b4a12dfcSJiaxun Yang if (s->num_cpu == 0) { 288b4a12dfcSJiaxun Yang error_setg(errp, "num-cpu must be at least 1"); 289b4a12dfcSJiaxun Yang return; 290b4a12dfcSJiaxun Yang } 291b4a12dfcSJiaxun Yang 29249eba52aSJiaxun Yang memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), 29349eba52aSJiaxun Yang &loongson_ipi_iocsr_ops, 294b4a12dfcSJiaxun Yang s, "loongson_ipi_iocsr", 0x48); 295b4a12dfcSJiaxun Yang 296b4a12dfcSJiaxun Yang /* loongson_ipi_iocsr performs re-entrant IO through ipi_send */ 297b4a12dfcSJiaxun Yang s->ipi_iocsr_mem.disable_reentrancy_guard = true; 298b4a12dfcSJiaxun Yang 299b4a12dfcSJiaxun Yang sysbus_init_mmio(sbd, &s->ipi_iocsr_mem); 300b4a12dfcSJiaxun Yang 301b4a12dfcSJiaxun Yang memory_region_init_io(&s->ipi64_iocsr_mem, OBJECT(dev), 302b4a12dfcSJiaxun Yang &loongson_ipi64_ops, 303b4a12dfcSJiaxun Yang s, "loongson_ipi64_iocsr", 0x118); 304b4a12dfcSJiaxun Yang sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem); 305b4a12dfcSJiaxun Yang 306b4a12dfcSJiaxun Yang s->cpu = g_new0(IPICore, s->num_cpu); 307b4a12dfcSJiaxun Yang for (i = 0; i < s->num_cpu; i++) { 30849eba52aSJiaxun Yang s->cpu[i].ipi = s; 30949eba52aSJiaxun Yang 310b4a12dfcSJiaxun Yang qdev_init_gpio_out(dev, &s->cpu[i].irq, 1); 311b4a12dfcSJiaxun Yang } 312b4a12dfcSJiaxun Yang } 313b4a12dfcSJiaxun Yang 314530e6dafSBibo Mao static void loongson_ipi_realize(DeviceState *dev, Error **errp) 315530e6dafSBibo Mao { 3166c8698a5SBibo Mao LoongsonIPICommonState *sc = LOONGSON_IPI_COMMON(dev); 317530e6dafSBibo Mao LoongsonIPIState *s = LOONGSON_IPI(dev); 318530e6dafSBibo Mao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 319530e6dafSBibo Mao Error *local_err = NULL; 320530e6dafSBibo Mao 321530e6dafSBibo Mao loongson_ipi_common_realize(dev, &local_err); 322530e6dafSBibo Mao if (local_err) { 323530e6dafSBibo Mao error_propagate(errp, local_err); 324530e6dafSBibo Mao return; 325530e6dafSBibo Mao } 326530e6dafSBibo Mao 3276c8698a5SBibo Mao s->ipi_mmio_mem = g_new0(MemoryRegion, sc->num_cpu); 3286c8698a5SBibo Mao for (unsigned i = 0; i < sc->num_cpu; i++) { 329530e6dafSBibo Mao g_autofree char *name = g_strdup_printf("loongson_ipi_cpu%d_mmio", i); 3306c8698a5SBibo Mao 331a022e0deSBibo Mao memory_region_init_io(&s->ipi_mmio_mem[i], OBJECT(dev), 3326c8698a5SBibo Mao &loongson_ipi_core_ops, &sc->cpu[i], name, 0x48); 333a022e0deSBibo Mao sysbus_init_mmio(sbd, &s->ipi_mmio_mem[i]); 334530e6dafSBibo Mao } 335530e6dafSBibo Mao } 336530e6dafSBibo Mao 337530e6dafSBibo Mao static void loongson_ipi_common_unrealize(DeviceState *dev) 3380c2086bcSPhilippe Mathieu-Daudé { 3396c8698a5SBibo Mao LoongsonIPICommonState *s = LOONGSON_IPI_COMMON(dev); 3400c2086bcSPhilippe Mathieu-Daudé 3410c2086bcSPhilippe Mathieu-Daudé g_free(s->cpu); 3420c2086bcSPhilippe Mathieu-Daudé } 3430c2086bcSPhilippe Mathieu-Daudé 344530e6dafSBibo Mao static void loongson_ipi_unrealize(DeviceState *dev) 345530e6dafSBibo Mao { 346a022e0deSBibo Mao LoongsonIPIState *s = LOONGSON_IPI(dev); 347a022e0deSBibo Mao 348a022e0deSBibo Mao g_free(s->ipi_mmio_mem); 349a022e0deSBibo Mao 350530e6dafSBibo Mao loongson_ipi_common_unrealize(dev); 351530e6dafSBibo Mao } 352530e6dafSBibo Mao 353b4a12dfcSJiaxun Yang static void loongson_ipi_class_init(ObjectClass *klass, void *data) 354b4a12dfcSJiaxun Yang { 355b4a12dfcSJiaxun Yang DeviceClass *dc = DEVICE_CLASS(klass); 3567e555781SBibo Mao LoongsonIPIClass *lic = LOONGSON_IPI_CLASS(klass); 357b4a12dfcSJiaxun Yang 3587e555781SBibo Mao device_class_set_parent_realize(dc, loongson_ipi_realize, 3597e555781SBibo Mao &lic->parent_realize); 3607e555781SBibo Mao device_class_set_parent_unrealize(dc, loongson_ipi_unrealize, 3617e555781SBibo Mao &lic->parent_unrealize); 362b4a12dfcSJiaxun Yang } 363b4a12dfcSJiaxun Yang 36413e8ec6cSPhilippe Mathieu-Daudé static const TypeInfo loongson_ipi_types[] = { 36513e8ec6cSPhilippe Mathieu-Daudé { 366b4a12dfcSJiaxun Yang .name = TYPE_LOONGSON_IPI, 3677e555781SBibo Mao .parent = TYPE_LOONGSON_IPI_COMMON, 36840a0815eSBibo Mao .instance_size = sizeof(LoongsonIPIState), 3697e555781SBibo Mao .class_size = sizeof(LoongsonIPIClass), 370b4a12dfcSJiaxun Yang .class_init = loongson_ipi_class_init, 37113e8ec6cSPhilippe Mathieu-Daudé } 372b4a12dfcSJiaxun Yang }; 373b4a12dfcSJiaxun Yang 37413e8ec6cSPhilippe Mathieu-Daudé DEFINE_TYPES(loongson_ipi_types) 375