1*53f18b3eSNicholas Piggin /* 2*53f18b3eSNicholas Piggin * QEMU PowerPC PowerNV ADU unit 3*53f18b3eSNicholas Piggin * 4*53f18b3eSNicholas Piggin * The ADU unit actually implements XSCOM, which is the bridge between MMIO 5*53f18b3eSNicholas Piggin * and PIB. However it also includes control and status registers and other 6*53f18b3eSNicholas Piggin * functions that are exposed as PIB (xscom) registers. 7*53f18b3eSNicholas Piggin * 8*53f18b3eSNicholas Piggin * To keep things simple, pnv_xscom.c remains the XSCOM bridge 9*53f18b3eSNicholas Piggin * implementation, and pnv_adu.c implements the ADU registers and other 10*53f18b3eSNicholas Piggin * functions. 11*53f18b3eSNicholas Piggin * 12*53f18b3eSNicholas Piggin * Copyright (c) 2024, IBM Corporation. 13*53f18b3eSNicholas Piggin * 14*53f18b3eSNicholas Piggin * SPDX-License-Identifier: GPL-2.0-or-later 15*53f18b3eSNicholas Piggin */ 16*53f18b3eSNicholas Piggin 17*53f18b3eSNicholas Piggin #include "qemu/osdep.h" 18*53f18b3eSNicholas Piggin #include "qemu/log.h" 19*53f18b3eSNicholas Piggin 20*53f18b3eSNicholas Piggin #include "hw/qdev-properties.h" 21*53f18b3eSNicholas Piggin #include "hw/ppc/pnv.h" 22*53f18b3eSNicholas Piggin #include "hw/ppc/pnv_adu.h" 23*53f18b3eSNicholas Piggin #include "hw/ppc/pnv_chip.h" 24*53f18b3eSNicholas Piggin #include "hw/ppc/pnv_xscom.h" 25*53f18b3eSNicholas Piggin #include "trace.h" 26*53f18b3eSNicholas Piggin 27*53f18b3eSNicholas Piggin static uint64_t pnv_adu_xscom_read(void *opaque, hwaddr addr, unsigned width) 28*53f18b3eSNicholas Piggin { 29*53f18b3eSNicholas Piggin uint32_t offset = addr >> 3; 30*53f18b3eSNicholas Piggin uint64_t val = 0; 31*53f18b3eSNicholas Piggin 32*53f18b3eSNicholas Piggin switch (offset) { 33*53f18b3eSNicholas Piggin case 0x18: /* Receive status reg */ 34*53f18b3eSNicholas Piggin case 0x12: /* log register */ 35*53f18b3eSNicholas Piggin case 0x13: /* error register */ 36*53f18b3eSNicholas Piggin break; 37*53f18b3eSNicholas Piggin 38*53f18b3eSNicholas Piggin default: 39*53f18b3eSNicholas Piggin qemu_log_mask(LOG_UNIMP, "ADU Unimplemented read register: Ox%08x\n", 40*53f18b3eSNicholas Piggin offset); 41*53f18b3eSNicholas Piggin } 42*53f18b3eSNicholas Piggin 43*53f18b3eSNicholas Piggin trace_pnv_adu_xscom_read(addr, val); 44*53f18b3eSNicholas Piggin 45*53f18b3eSNicholas Piggin return val; 46*53f18b3eSNicholas Piggin } 47*53f18b3eSNicholas Piggin 48*53f18b3eSNicholas Piggin static void pnv_adu_xscom_write(void *opaque, hwaddr addr, uint64_t val, 49*53f18b3eSNicholas Piggin unsigned width) 50*53f18b3eSNicholas Piggin { 51*53f18b3eSNicholas Piggin uint32_t offset = addr >> 3; 52*53f18b3eSNicholas Piggin 53*53f18b3eSNicholas Piggin trace_pnv_adu_xscom_write(addr, val); 54*53f18b3eSNicholas Piggin 55*53f18b3eSNicholas Piggin switch (offset) { 56*53f18b3eSNicholas Piggin case 0x18: /* Receive status reg */ 57*53f18b3eSNicholas Piggin case 0x12: /* log register */ 58*53f18b3eSNicholas Piggin case 0x13: /* error register */ 59*53f18b3eSNicholas Piggin break; 60*53f18b3eSNicholas Piggin 61*53f18b3eSNicholas Piggin default: 62*53f18b3eSNicholas Piggin qemu_log_mask(LOG_UNIMP, "ADU Unimplemented write register: Ox%08x\n", 63*53f18b3eSNicholas Piggin offset); 64*53f18b3eSNicholas Piggin } 65*53f18b3eSNicholas Piggin } 66*53f18b3eSNicholas Piggin 67*53f18b3eSNicholas Piggin const MemoryRegionOps pnv_adu_xscom_ops = { 68*53f18b3eSNicholas Piggin .read = pnv_adu_xscom_read, 69*53f18b3eSNicholas Piggin .write = pnv_adu_xscom_write, 70*53f18b3eSNicholas Piggin .valid.min_access_size = 8, 71*53f18b3eSNicholas Piggin .valid.max_access_size = 8, 72*53f18b3eSNicholas Piggin .impl.min_access_size = 8, 73*53f18b3eSNicholas Piggin .impl.max_access_size = 8, 74*53f18b3eSNicholas Piggin .endianness = DEVICE_BIG_ENDIAN, 75*53f18b3eSNicholas Piggin }; 76*53f18b3eSNicholas Piggin 77*53f18b3eSNicholas Piggin static void pnv_adu_realize(DeviceState *dev, Error **errp) 78*53f18b3eSNicholas Piggin { 79*53f18b3eSNicholas Piggin PnvADU *adu = PNV_ADU(dev); 80*53f18b3eSNicholas Piggin 81*53f18b3eSNicholas Piggin /* XScom regions for ADU registers */ 82*53f18b3eSNicholas Piggin pnv_xscom_region_init(&adu->xscom_regs, OBJECT(dev), 83*53f18b3eSNicholas Piggin &pnv_adu_xscom_ops, adu, "xscom-adu", 84*53f18b3eSNicholas Piggin PNV9_XSCOM_ADU_SIZE); 85*53f18b3eSNicholas Piggin } 86*53f18b3eSNicholas Piggin 87*53f18b3eSNicholas Piggin static void pnv_adu_class_init(ObjectClass *klass, void *data) 88*53f18b3eSNicholas Piggin { 89*53f18b3eSNicholas Piggin DeviceClass *dc = DEVICE_CLASS(klass); 90*53f18b3eSNicholas Piggin 91*53f18b3eSNicholas Piggin dc->realize = pnv_adu_realize; 92*53f18b3eSNicholas Piggin dc->desc = "PowerNV ADU"; 93*53f18b3eSNicholas Piggin dc->user_creatable = false; 94*53f18b3eSNicholas Piggin } 95*53f18b3eSNicholas Piggin 96*53f18b3eSNicholas Piggin static const TypeInfo pnv_adu_type_info = { 97*53f18b3eSNicholas Piggin .name = TYPE_PNV_ADU, 98*53f18b3eSNicholas Piggin .parent = TYPE_DEVICE, 99*53f18b3eSNicholas Piggin .instance_size = sizeof(PnvADU), 100*53f18b3eSNicholas Piggin .class_init = pnv_adu_class_init, 101*53f18b3eSNicholas Piggin .interfaces = (InterfaceInfo[]) { 102*53f18b3eSNicholas Piggin { TYPE_PNV_XSCOM_INTERFACE }, 103*53f18b3eSNicholas Piggin { } }, 104*53f18b3eSNicholas Piggin }; 105*53f18b3eSNicholas Piggin 106*53f18b3eSNicholas Piggin static void pnv_adu_register_types(void) 107*53f18b3eSNicholas Piggin { 108*53f18b3eSNicholas Piggin type_register_static(&pnv_adu_type_info); 109*53f18b3eSNicholas Piggin } 110*53f18b3eSNicholas Piggin 111*53f18b3eSNicholas Piggin type_init(pnv_adu_register_types); 112