1*7d87775fSJoe Komlodi /* 2*7d87775fSJoe Komlodi * ASPEED I3C Controller 3*7d87775fSJoe Komlodi * 4*7d87775fSJoe Komlodi * Copyright (C) 2021 ASPEED Technology Inc. 5*7d87775fSJoe Komlodi * 6*7d87775fSJoe Komlodi * This code is licensed under the GPL version 2 or later. See 7*7d87775fSJoe Komlodi * the COPYING file in the top-level directory. 8*7d87775fSJoe Komlodi */ 9*7d87775fSJoe Komlodi 10*7d87775fSJoe Komlodi #include "qemu/osdep.h" 11*7d87775fSJoe Komlodi #include "qemu/log.h" 12*7d87775fSJoe Komlodi #include "qemu/error-report.h" 13*7d87775fSJoe Komlodi #include "hw/i3c/aspeed_i3c.h" 14*7d87775fSJoe Komlodi #include "hw/registerfields.h" 15*7d87775fSJoe Komlodi #include "hw/qdev-properties.h" 16*7d87775fSJoe Komlodi #include "qapi/error.h" 17*7d87775fSJoe Komlodi #include "migration/vmstate.h" 18*7d87775fSJoe Komlodi #include "trace.h" 19*7d87775fSJoe Komlodi 20*7d87775fSJoe Komlodi /* I3C Controller Registers */ 21*7d87775fSJoe Komlodi REG32(I3C1_REG0, 0x10) 22*7d87775fSJoe Komlodi REG32(I3C1_REG1, 0x14) 23*7d87775fSJoe Komlodi FIELD(I3C1_REG1, I2C_MODE, 0, 1) 24*7d87775fSJoe Komlodi FIELD(I3C1_REG1, SA_EN, 15, 1) 25*7d87775fSJoe Komlodi REG32(I3C2_REG0, 0x20) 26*7d87775fSJoe Komlodi REG32(I3C2_REG1, 0x24) 27*7d87775fSJoe Komlodi FIELD(I3C2_REG1, I2C_MODE, 0, 1) 28*7d87775fSJoe Komlodi FIELD(I3C2_REG1, SA_EN, 15, 1) 29*7d87775fSJoe Komlodi REG32(I3C3_REG0, 0x30) 30*7d87775fSJoe Komlodi REG32(I3C3_REG1, 0x34) 31*7d87775fSJoe Komlodi FIELD(I3C3_REG1, I2C_MODE, 0, 1) 32*7d87775fSJoe Komlodi FIELD(I3C3_REG1, SA_EN, 15, 1) 33*7d87775fSJoe Komlodi REG32(I3C4_REG0, 0x40) 34*7d87775fSJoe Komlodi REG32(I3C4_REG1, 0x44) 35*7d87775fSJoe Komlodi FIELD(I3C4_REG1, I2C_MODE, 0, 1) 36*7d87775fSJoe Komlodi FIELD(I3C4_REG1, SA_EN, 15, 1) 37*7d87775fSJoe Komlodi REG32(I3C5_REG0, 0x50) 38*7d87775fSJoe Komlodi REG32(I3C5_REG1, 0x54) 39*7d87775fSJoe Komlodi FIELD(I3C5_REG1, I2C_MODE, 0, 1) 40*7d87775fSJoe Komlodi FIELD(I3C5_REG1, SA_EN, 15, 1) 41*7d87775fSJoe Komlodi REG32(I3C6_REG0, 0x60) 42*7d87775fSJoe Komlodi REG32(I3C6_REG1, 0x64) 43*7d87775fSJoe Komlodi FIELD(I3C6_REG1, I2C_MODE, 0, 1) 44*7d87775fSJoe Komlodi FIELD(I3C6_REG1, SA_EN, 15, 1) 45*7d87775fSJoe Komlodi 46*7d87775fSJoe Komlodi /* I3C Device Registers */ 47*7d87775fSJoe Komlodi REG32(DEVICE_CTRL, 0x00) 48*7d87775fSJoe Komlodi REG32(DEVICE_ADDR, 0x04) 49*7d87775fSJoe Komlodi REG32(HW_CAPABILITY, 0x08) 50*7d87775fSJoe Komlodi REG32(COMMAND_QUEUE_PORT, 0x0c) 51*7d87775fSJoe Komlodi REG32(RESPONSE_QUEUE_PORT, 0x10) 52*7d87775fSJoe Komlodi REG32(RX_TX_DATA_PORT, 0x14) 53*7d87775fSJoe Komlodi REG32(IBI_QUEUE_STATUS, 0x18) 54*7d87775fSJoe Komlodi REG32(IBI_QUEUE_DATA, 0x18) 55*7d87775fSJoe Komlodi REG32(QUEUE_THLD_CTRL, 0x1c) 56*7d87775fSJoe Komlodi REG32(DATA_BUFFER_THLD_CTRL, 0x20) 57*7d87775fSJoe Komlodi REG32(IBI_QUEUE_CTRL, 0x24) 58*7d87775fSJoe Komlodi REG32(IBI_MR_REQ_REJECT, 0x2c) 59*7d87775fSJoe Komlodi REG32(IBI_SIR_REQ_REJECT, 0x30) 60*7d87775fSJoe Komlodi REG32(RESET_CTRL, 0x34) 61*7d87775fSJoe Komlodi REG32(SLV_EVENT_CTRL, 0x38) 62*7d87775fSJoe Komlodi REG32(INTR_STATUS, 0x3c) 63*7d87775fSJoe Komlodi REG32(INTR_STATUS_EN, 0x40) 64*7d87775fSJoe Komlodi REG32(INTR_SIGNAL_EN, 0x44) 65*7d87775fSJoe Komlodi REG32(INTR_FORCE, 0x48) 66*7d87775fSJoe Komlodi REG32(QUEUE_STATUS_LEVEL, 0x4c) 67*7d87775fSJoe Komlodi REG32(DATA_BUFFER_STATUS_LEVEL, 0x50) 68*7d87775fSJoe Komlodi REG32(PRESENT_STATE, 0x54) 69*7d87775fSJoe Komlodi REG32(CCC_DEVICE_STATUS, 0x58) 70*7d87775fSJoe Komlodi REG32(DEVICE_ADDR_TABLE_POINTER, 0x5c) 71*7d87775fSJoe Komlodi FIELD(DEVICE_ADDR_TABLE_POINTER, DEPTH, 16, 16) 72*7d87775fSJoe Komlodi FIELD(DEVICE_ADDR_TABLE_POINTER, ADDR, 0, 16) 73*7d87775fSJoe Komlodi REG32(DEV_CHAR_TABLE_POINTER, 0x60) 74*7d87775fSJoe Komlodi REG32(VENDOR_SPECIFIC_REG_POINTER, 0x6c) 75*7d87775fSJoe Komlodi REG32(SLV_MIPI_PID_VALUE, 0x70) 76*7d87775fSJoe Komlodi REG32(SLV_PID_VALUE, 0x74) 77*7d87775fSJoe Komlodi REG32(SLV_CHAR_CTRL, 0x78) 78*7d87775fSJoe Komlodi REG32(SLV_MAX_LEN, 0x7c) 79*7d87775fSJoe Komlodi REG32(MAX_READ_TURNAROUND, 0x80) 80*7d87775fSJoe Komlodi REG32(MAX_DATA_SPEED, 0x84) 81*7d87775fSJoe Komlodi REG32(SLV_DEBUG_STATUS, 0x88) 82*7d87775fSJoe Komlodi REG32(SLV_INTR_REQ, 0x8c) 83*7d87775fSJoe Komlodi REG32(DEVICE_CTRL_EXTENDED, 0xb0) 84*7d87775fSJoe Komlodi REG32(SCL_I3C_OD_TIMING, 0xb4) 85*7d87775fSJoe Komlodi REG32(SCL_I3C_PP_TIMING, 0xb8) 86*7d87775fSJoe Komlodi REG32(SCL_I2C_FM_TIMING, 0xbc) 87*7d87775fSJoe Komlodi REG32(SCL_I2C_FMP_TIMING, 0xc0) 88*7d87775fSJoe Komlodi REG32(SCL_EXT_LCNT_TIMING, 0xc8) 89*7d87775fSJoe Komlodi REG32(SCL_EXT_TERMN_LCNT_TIMING, 0xcc) 90*7d87775fSJoe Komlodi REG32(BUS_FREE_TIMING, 0xd4) 91*7d87775fSJoe Komlodi REG32(BUS_IDLE_TIMING, 0xd8) 92*7d87775fSJoe Komlodi REG32(I3C_VER_ID, 0xe0) 93*7d87775fSJoe Komlodi REG32(I3C_VER_TYPE, 0xe4) 94*7d87775fSJoe Komlodi REG32(EXTENDED_CAPABILITY, 0xe8) 95*7d87775fSJoe Komlodi REG32(SLAVE_CONFIG, 0xec) 96*7d87775fSJoe Komlodi 97*7d87775fSJoe Komlodi static const uint32_t ast2600_i3c_device_resets[ASPEED_I3C_DEVICE_NR_REGS] = { 98*7d87775fSJoe Komlodi [R_HW_CAPABILITY] = 0x000e00bf, 99*7d87775fSJoe Komlodi [R_QUEUE_THLD_CTRL] = 0x01000101, 100*7d87775fSJoe Komlodi [R_I3C_VER_ID] = 0x3130302a, 101*7d87775fSJoe Komlodi [R_I3C_VER_TYPE] = 0x6c633033, 102*7d87775fSJoe Komlodi [R_DEVICE_ADDR_TABLE_POINTER] = 0x00080280, 103*7d87775fSJoe Komlodi [R_DEV_CHAR_TABLE_POINTER] = 0x00020200, 104*7d87775fSJoe Komlodi [A_VENDOR_SPECIFIC_REG_POINTER] = 0x000000b0, 105*7d87775fSJoe Komlodi [R_SLV_MAX_LEN] = 0x00ff00ff, 106*7d87775fSJoe Komlodi }; 107*7d87775fSJoe Komlodi 108*7d87775fSJoe Komlodi static uint64_t aspeed_i3c_device_read(void *opaque, hwaddr offset, 109*7d87775fSJoe Komlodi unsigned size) 110*7d87775fSJoe Komlodi { 111*7d87775fSJoe Komlodi AspeedI3CDevice *s = ASPEED_I3C_DEVICE(opaque); 112*7d87775fSJoe Komlodi uint32_t addr = offset >> 2; 113*7d87775fSJoe Komlodi uint64_t value; 114*7d87775fSJoe Komlodi 115*7d87775fSJoe Komlodi switch (addr) { 116*7d87775fSJoe Komlodi case R_COMMAND_QUEUE_PORT: 117*7d87775fSJoe Komlodi value = 0; 118*7d87775fSJoe Komlodi break; 119*7d87775fSJoe Komlodi default: 120*7d87775fSJoe Komlodi value = s->regs[addr]; 121*7d87775fSJoe Komlodi break; 122*7d87775fSJoe Komlodi } 123*7d87775fSJoe Komlodi 124*7d87775fSJoe Komlodi trace_aspeed_i3c_device_read(s->id, offset, value); 125*7d87775fSJoe Komlodi 126*7d87775fSJoe Komlodi return value; 127*7d87775fSJoe Komlodi } 128*7d87775fSJoe Komlodi 129*7d87775fSJoe Komlodi static void aspeed_i3c_device_write(void *opaque, hwaddr offset, 130*7d87775fSJoe Komlodi uint64_t value, unsigned size) 131*7d87775fSJoe Komlodi { 132*7d87775fSJoe Komlodi AspeedI3CDevice *s = ASPEED_I3C_DEVICE(opaque); 133*7d87775fSJoe Komlodi uint32_t addr = offset >> 2; 134*7d87775fSJoe Komlodi 135*7d87775fSJoe Komlodi trace_aspeed_i3c_device_write(s->id, offset, value); 136*7d87775fSJoe Komlodi 137*7d87775fSJoe Komlodi switch (addr) { 138*7d87775fSJoe Komlodi case R_HW_CAPABILITY: 139*7d87775fSJoe Komlodi case R_RESPONSE_QUEUE_PORT: 140*7d87775fSJoe Komlodi case R_IBI_QUEUE_DATA: 141*7d87775fSJoe Komlodi case R_QUEUE_STATUS_LEVEL: 142*7d87775fSJoe Komlodi case R_PRESENT_STATE: 143*7d87775fSJoe Komlodi case R_CCC_DEVICE_STATUS: 144*7d87775fSJoe Komlodi case R_DEVICE_ADDR_TABLE_POINTER: 145*7d87775fSJoe Komlodi case R_VENDOR_SPECIFIC_REG_POINTER: 146*7d87775fSJoe Komlodi case R_SLV_CHAR_CTRL: 147*7d87775fSJoe Komlodi case R_SLV_MAX_LEN: 148*7d87775fSJoe Komlodi case R_MAX_READ_TURNAROUND: 149*7d87775fSJoe Komlodi case R_I3C_VER_ID: 150*7d87775fSJoe Komlodi case R_I3C_VER_TYPE: 151*7d87775fSJoe Komlodi case R_EXTENDED_CAPABILITY: 152*7d87775fSJoe Komlodi qemu_log_mask(LOG_GUEST_ERROR, 153*7d87775fSJoe Komlodi "%s: write to readonly register[0x%02" HWADDR_PRIx 154*7d87775fSJoe Komlodi "] = 0x%08" PRIx64 "\n", 155*7d87775fSJoe Komlodi __func__, offset, value); 156*7d87775fSJoe Komlodi break; 157*7d87775fSJoe Komlodi case R_RX_TX_DATA_PORT: 158*7d87775fSJoe Komlodi break; 159*7d87775fSJoe Komlodi case R_RESET_CTRL: 160*7d87775fSJoe Komlodi break; 161*7d87775fSJoe Komlodi default: 162*7d87775fSJoe Komlodi s->regs[addr] = value; 163*7d87775fSJoe Komlodi break; 164*7d87775fSJoe Komlodi } 165*7d87775fSJoe Komlodi } 166*7d87775fSJoe Komlodi 167*7d87775fSJoe Komlodi static const VMStateDescription aspeed_i3c_device_vmstate = { 168*7d87775fSJoe Komlodi .name = TYPE_ASPEED_I3C, 169*7d87775fSJoe Komlodi .version_id = 1, 170*7d87775fSJoe Komlodi .minimum_version_id = 1, 171*7d87775fSJoe Komlodi .fields = (const VMStateField[]){ 172*7d87775fSJoe Komlodi VMSTATE_UINT32_ARRAY(regs, AspeedI3CDevice, ASPEED_I3C_DEVICE_NR_REGS), 173*7d87775fSJoe Komlodi VMSTATE_END_OF_LIST(), 174*7d87775fSJoe Komlodi } 175*7d87775fSJoe Komlodi }; 176*7d87775fSJoe Komlodi 177*7d87775fSJoe Komlodi static const MemoryRegionOps aspeed_i3c_device_ops = { 178*7d87775fSJoe Komlodi .read = aspeed_i3c_device_read, 179*7d87775fSJoe Komlodi .write = aspeed_i3c_device_write, 180*7d87775fSJoe Komlodi .endianness = DEVICE_LITTLE_ENDIAN, 181*7d87775fSJoe Komlodi }; 182*7d87775fSJoe Komlodi 183*7d87775fSJoe Komlodi static void aspeed_i3c_device_reset(DeviceState *dev) 184*7d87775fSJoe Komlodi { 185*7d87775fSJoe Komlodi AspeedI3CDevice *s = ASPEED_I3C_DEVICE(dev); 186*7d87775fSJoe Komlodi 187*7d87775fSJoe Komlodi memcpy(s->regs, ast2600_i3c_device_resets, sizeof(s->regs)); 188*7d87775fSJoe Komlodi } 189*7d87775fSJoe Komlodi 190*7d87775fSJoe Komlodi static void aspeed_i3c_device_realize(DeviceState *dev, Error **errp) 191*7d87775fSJoe Komlodi { 192*7d87775fSJoe Komlodi AspeedI3CDevice *s = ASPEED_I3C_DEVICE(dev); 193*7d87775fSJoe Komlodi g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I3C_DEVICE ".%d", 194*7d87775fSJoe Komlodi s->id); 195*7d87775fSJoe Komlodi 196*7d87775fSJoe Komlodi sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); 197*7d87775fSJoe Komlodi 198*7d87775fSJoe Komlodi memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i3c_device_ops, 199*7d87775fSJoe Komlodi s, name, ASPEED_I3C_DEVICE_NR_REGS << 2); 200*7d87775fSJoe Komlodi } 201*7d87775fSJoe Komlodi 202*7d87775fSJoe Komlodi static uint64_t aspeed_i3c_read(void *opaque, hwaddr addr, unsigned int size) 203*7d87775fSJoe Komlodi { 204*7d87775fSJoe Komlodi AspeedI3CState *s = ASPEED_I3C(opaque); 205*7d87775fSJoe Komlodi uint64_t val = 0; 206*7d87775fSJoe Komlodi 207*7d87775fSJoe Komlodi val = s->regs[addr >> 2]; 208*7d87775fSJoe Komlodi 209*7d87775fSJoe Komlodi trace_aspeed_i3c_read(addr, val); 210*7d87775fSJoe Komlodi 211*7d87775fSJoe Komlodi return val; 212*7d87775fSJoe Komlodi } 213*7d87775fSJoe Komlodi 214*7d87775fSJoe Komlodi static void aspeed_i3c_write(void *opaque, 215*7d87775fSJoe Komlodi hwaddr addr, 216*7d87775fSJoe Komlodi uint64_t data, 217*7d87775fSJoe Komlodi unsigned int size) 218*7d87775fSJoe Komlodi { 219*7d87775fSJoe Komlodi AspeedI3CState *s = ASPEED_I3C(opaque); 220*7d87775fSJoe Komlodi 221*7d87775fSJoe Komlodi trace_aspeed_i3c_write(addr, data); 222*7d87775fSJoe Komlodi 223*7d87775fSJoe Komlodi addr >>= 2; 224*7d87775fSJoe Komlodi 225*7d87775fSJoe Komlodi /* I3C controller register */ 226*7d87775fSJoe Komlodi switch (addr) { 227*7d87775fSJoe Komlodi case R_I3C1_REG1: 228*7d87775fSJoe Komlodi case R_I3C2_REG1: 229*7d87775fSJoe Komlodi case R_I3C3_REG1: 230*7d87775fSJoe Komlodi case R_I3C4_REG1: 231*7d87775fSJoe Komlodi case R_I3C5_REG1: 232*7d87775fSJoe Komlodi case R_I3C6_REG1: 233*7d87775fSJoe Komlodi if (data & R_I3C1_REG1_I2C_MODE_MASK) { 234*7d87775fSJoe Komlodi qemu_log_mask(LOG_UNIMP, 235*7d87775fSJoe Komlodi "%s: Unsupported I2C mode [0x%08" HWADDR_PRIx 236*7d87775fSJoe Komlodi "]=%08" PRIx64 "\n", 237*7d87775fSJoe Komlodi __func__, addr << 2, data); 238*7d87775fSJoe Komlodi break; 239*7d87775fSJoe Komlodi } 240*7d87775fSJoe Komlodi if (data & R_I3C1_REG1_SA_EN_MASK) { 241*7d87775fSJoe Komlodi qemu_log_mask(LOG_UNIMP, 242*7d87775fSJoe Komlodi "%s: Unsupported slave mode [%08" HWADDR_PRIx 243*7d87775fSJoe Komlodi "]=0x%08" PRIx64 "\n", 244*7d87775fSJoe Komlodi __func__, addr << 2, data); 245*7d87775fSJoe Komlodi break; 246*7d87775fSJoe Komlodi } 247*7d87775fSJoe Komlodi s->regs[addr] = data; 248*7d87775fSJoe Komlodi break; 249*7d87775fSJoe Komlodi default: 250*7d87775fSJoe Komlodi s->regs[addr] = data; 251*7d87775fSJoe Komlodi break; 252*7d87775fSJoe Komlodi } 253*7d87775fSJoe Komlodi } 254*7d87775fSJoe Komlodi 255*7d87775fSJoe Komlodi static const MemoryRegionOps aspeed_i3c_ops = { 256*7d87775fSJoe Komlodi .read = aspeed_i3c_read, 257*7d87775fSJoe Komlodi .write = aspeed_i3c_write, 258*7d87775fSJoe Komlodi .endianness = DEVICE_LITTLE_ENDIAN, 259*7d87775fSJoe Komlodi .valid = { 260*7d87775fSJoe Komlodi .min_access_size = 1, 261*7d87775fSJoe Komlodi .max_access_size = 4, 262*7d87775fSJoe Komlodi } 263*7d87775fSJoe Komlodi }; 264*7d87775fSJoe Komlodi 265*7d87775fSJoe Komlodi static void aspeed_i3c_reset(DeviceState *dev) 266*7d87775fSJoe Komlodi { 267*7d87775fSJoe Komlodi AspeedI3CState *s = ASPEED_I3C(dev); 268*7d87775fSJoe Komlodi memset(s->regs, 0, sizeof(s->regs)); 269*7d87775fSJoe Komlodi } 270*7d87775fSJoe Komlodi 271*7d87775fSJoe Komlodi static void aspeed_i3c_instance_init(Object *obj) 272*7d87775fSJoe Komlodi { 273*7d87775fSJoe Komlodi AspeedI3CState *s = ASPEED_I3C(obj); 274*7d87775fSJoe Komlodi int i; 275*7d87775fSJoe Komlodi 276*7d87775fSJoe Komlodi for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { 277*7d87775fSJoe Komlodi object_initialize_child(obj, "device[*]", &s->devices[i], 278*7d87775fSJoe Komlodi TYPE_ASPEED_I3C_DEVICE); 279*7d87775fSJoe Komlodi } 280*7d87775fSJoe Komlodi } 281*7d87775fSJoe Komlodi 282*7d87775fSJoe Komlodi static void aspeed_i3c_realize(DeviceState *dev, Error **errp) 283*7d87775fSJoe Komlodi { 284*7d87775fSJoe Komlodi int i; 285*7d87775fSJoe Komlodi AspeedI3CState *s = ASPEED_I3C(dev); 286*7d87775fSJoe Komlodi SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 287*7d87775fSJoe Komlodi 288*7d87775fSJoe Komlodi memory_region_init(&s->iomem_container, OBJECT(s), 289*7d87775fSJoe Komlodi TYPE_ASPEED_I3C ".container", 0x8000); 290*7d87775fSJoe Komlodi 291*7d87775fSJoe Komlodi sysbus_init_mmio(sbd, &s->iomem_container); 292*7d87775fSJoe Komlodi 293*7d87775fSJoe Komlodi memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i3c_ops, s, 294*7d87775fSJoe Komlodi TYPE_ASPEED_I3C ".regs", ASPEED_I3C_NR_REGS << 2); 295*7d87775fSJoe Komlodi 296*7d87775fSJoe Komlodi memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem); 297*7d87775fSJoe Komlodi 298*7d87775fSJoe Komlodi for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { 299*7d87775fSJoe Komlodi Object *i3c_dev = OBJECT(&s->devices[i]); 300*7d87775fSJoe Komlodi 301*7d87775fSJoe Komlodi if (!object_property_set_uint(i3c_dev, "device-id", i, errp)) { 302*7d87775fSJoe Komlodi return; 303*7d87775fSJoe Komlodi } 304*7d87775fSJoe Komlodi 305*7d87775fSJoe Komlodi if (!sysbus_realize(SYS_BUS_DEVICE(i3c_dev), errp)) { 306*7d87775fSJoe Komlodi return; 307*7d87775fSJoe Komlodi } 308*7d87775fSJoe Komlodi 309*7d87775fSJoe Komlodi /* 310*7d87775fSJoe Komlodi * Register Address of I3CX Device = 311*7d87775fSJoe Komlodi * (Base Address of Global Register) + (Offset of I3CX) + Offset 312*7d87775fSJoe Komlodi * X = 0, 1, 2, 3, 4, 5 313*7d87775fSJoe Komlodi * Offset of I3C0 = 0x2000 314*7d87775fSJoe Komlodi * Offset of I3C1 = 0x3000 315*7d87775fSJoe Komlodi * Offset of I3C2 = 0x4000 316*7d87775fSJoe Komlodi * Offset of I3C3 = 0x5000 317*7d87775fSJoe Komlodi * Offset of I3C4 = 0x6000 318*7d87775fSJoe Komlodi * Offset of I3C5 = 0x7000 319*7d87775fSJoe Komlodi */ 320*7d87775fSJoe Komlodi memory_region_add_subregion(&s->iomem_container, 321*7d87775fSJoe Komlodi 0x2000 + i * 0x1000, &s->devices[i].mr); 322*7d87775fSJoe Komlodi } 323*7d87775fSJoe Komlodi 324*7d87775fSJoe Komlodi } 325*7d87775fSJoe Komlodi 326*7d87775fSJoe Komlodi static Property aspeed_i3c_device_properties[] = { 327*7d87775fSJoe Komlodi DEFINE_PROP_UINT8("device-id", AspeedI3CDevice, id, 0), 328*7d87775fSJoe Komlodi DEFINE_PROP_END_OF_LIST(), 329*7d87775fSJoe Komlodi }; 330*7d87775fSJoe Komlodi 331*7d87775fSJoe Komlodi static void aspeed_i3c_device_class_init(ObjectClass *klass, void *data) 332*7d87775fSJoe Komlodi { 333*7d87775fSJoe Komlodi DeviceClass *dc = DEVICE_CLASS(klass); 334*7d87775fSJoe Komlodi 335*7d87775fSJoe Komlodi dc->desc = "Aspeed I3C Device"; 336*7d87775fSJoe Komlodi dc->realize = aspeed_i3c_device_realize; 337*7d87775fSJoe Komlodi device_class_set_legacy_reset(dc, aspeed_i3c_device_reset); 338*7d87775fSJoe Komlodi device_class_set_props(dc, aspeed_i3c_device_properties); 339*7d87775fSJoe Komlodi } 340*7d87775fSJoe Komlodi 341*7d87775fSJoe Komlodi static const TypeInfo aspeed_i3c_device_info = { 342*7d87775fSJoe Komlodi .name = TYPE_ASPEED_I3C_DEVICE, 343*7d87775fSJoe Komlodi .parent = TYPE_SYS_BUS_DEVICE, 344*7d87775fSJoe Komlodi .instance_size = sizeof(AspeedI3CDevice), 345*7d87775fSJoe Komlodi .class_init = aspeed_i3c_device_class_init, 346*7d87775fSJoe Komlodi }; 347*7d87775fSJoe Komlodi 348*7d87775fSJoe Komlodi static const VMStateDescription vmstate_aspeed_i3c = { 349*7d87775fSJoe Komlodi .name = TYPE_ASPEED_I3C, 350*7d87775fSJoe Komlodi .version_id = 1, 351*7d87775fSJoe Komlodi .minimum_version_id = 1, 352*7d87775fSJoe Komlodi .fields = (const VMStateField[]) { 353*7d87775fSJoe Komlodi VMSTATE_UINT32_ARRAY(regs, AspeedI3CState, ASPEED_I3C_NR_REGS), 354*7d87775fSJoe Komlodi VMSTATE_STRUCT_ARRAY(devices, AspeedI3CState, ASPEED_I3C_NR_DEVICES, 1, 355*7d87775fSJoe Komlodi aspeed_i3c_device_vmstate, AspeedI3CDevice), 356*7d87775fSJoe Komlodi VMSTATE_END_OF_LIST(), 357*7d87775fSJoe Komlodi } 358*7d87775fSJoe Komlodi }; 359*7d87775fSJoe Komlodi 360*7d87775fSJoe Komlodi static void aspeed_i3c_class_init(ObjectClass *klass, void *data) 361*7d87775fSJoe Komlodi { 362*7d87775fSJoe Komlodi DeviceClass *dc = DEVICE_CLASS(klass); 363*7d87775fSJoe Komlodi 364*7d87775fSJoe Komlodi dc->realize = aspeed_i3c_realize; 365*7d87775fSJoe Komlodi device_class_set_legacy_reset(dc, aspeed_i3c_reset); 366*7d87775fSJoe Komlodi dc->desc = "Aspeed I3C Controller"; 367*7d87775fSJoe Komlodi dc->vmsd = &vmstate_aspeed_i3c; 368*7d87775fSJoe Komlodi } 369*7d87775fSJoe Komlodi 370*7d87775fSJoe Komlodi static const TypeInfo aspeed_i3c_info = { 371*7d87775fSJoe Komlodi .name = TYPE_ASPEED_I3C, 372*7d87775fSJoe Komlodi .parent = TYPE_SYS_BUS_DEVICE, 373*7d87775fSJoe Komlodi .instance_init = aspeed_i3c_instance_init, 374*7d87775fSJoe Komlodi .instance_size = sizeof(AspeedI3CState), 375*7d87775fSJoe Komlodi .class_init = aspeed_i3c_class_init, 376*7d87775fSJoe Komlodi }; 377*7d87775fSJoe Komlodi 378*7d87775fSJoe Komlodi static void aspeed_i3c_register_types(void) 379*7d87775fSJoe Komlodi { 380*7d87775fSJoe Komlodi type_register_static(&aspeed_i3c_device_info); 381*7d87775fSJoe Komlodi type_register_static(&aspeed_i3c_info); 382*7d87775fSJoe Komlodi } 383*7d87775fSJoe Komlodi 384*7d87775fSJoe Komlodi type_init(aspeed_i3c_register_types); 385