1*c52aaabdSJoe Komlodi /* 2*c52aaabdSJoe Komlodi * DesignWare I3C Controller 3*c52aaabdSJoe Komlodi * 4*c52aaabdSJoe Komlodi * Copyright (C) 2021 ASPEED Technology Inc. 5*c52aaabdSJoe Komlodi * Copyright (C) 2025 Google, LLC 6*c52aaabdSJoe Komlodi * 7*c52aaabdSJoe Komlodi * SPDX-License-Identifier: GPL-2.0-or-later 8*c52aaabdSJoe Komlodi */ 9*c52aaabdSJoe Komlodi 10*c52aaabdSJoe Komlodi #include "qemu/osdep.h" 11*c52aaabdSJoe Komlodi #include "qemu/log.h" 12*c52aaabdSJoe Komlodi #include "qemu/error-report.h" 13*c52aaabdSJoe Komlodi #include "hw/i3c/i3c.h" 14*c52aaabdSJoe Komlodi #include "hw/i3c/dw-i3c.h" 15*c52aaabdSJoe Komlodi #include "hw/registerfields.h" 16*c52aaabdSJoe Komlodi #include "hw/qdev-properties.h" 17*c52aaabdSJoe Komlodi #include "qapi/error.h" 18*c52aaabdSJoe Komlodi #include "migration/vmstate.h" 19*c52aaabdSJoe Komlodi #include "trace.h" 20*c52aaabdSJoe Komlodi 21*c52aaabdSJoe Komlodi REG32(DEVICE_CTRL, 0x00) 22*c52aaabdSJoe Komlodi REG32(DEVICE_ADDR, 0x04) 23*c52aaabdSJoe Komlodi REG32(HW_CAPABILITY, 0x08) 24*c52aaabdSJoe Komlodi REG32(COMMAND_QUEUE_PORT, 0x0c) 25*c52aaabdSJoe Komlodi REG32(RESPONSE_QUEUE_PORT, 0x10) 26*c52aaabdSJoe Komlodi REG32(RX_TX_DATA_PORT, 0x14) 27*c52aaabdSJoe Komlodi REG32(IBI_QUEUE_STATUS, 0x18) 28*c52aaabdSJoe Komlodi REG32(IBI_QUEUE_DATA, 0x18) 29*c52aaabdSJoe Komlodi REG32(QUEUE_THLD_CTRL, 0x1c) 30*c52aaabdSJoe Komlodi REG32(DATA_BUFFER_THLD_CTRL, 0x20) 31*c52aaabdSJoe Komlodi REG32(IBI_QUEUE_CTRL, 0x24) 32*c52aaabdSJoe Komlodi REG32(IBI_MR_REQ_REJECT, 0x2c) 33*c52aaabdSJoe Komlodi REG32(IBI_SIR_REQ_REJECT, 0x30) 34*c52aaabdSJoe Komlodi REG32(RESET_CTRL, 0x34) 35*c52aaabdSJoe Komlodi REG32(SLV_EVENT_CTRL, 0x38) 36*c52aaabdSJoe Komlodi REG32(INTR_STATUS, 0x3c) 37*c52aaabdSJoe Komlodi REG32(INTR_STATUS_EN, 0x40) 38*c52aaabdSJoe Komlodi REG32(INTR_SIGNAL_EN, 0x44) 39*c52aaabdSJoe Komlodi REG32(INTR_FORCE, 0x48) 40*c52aaabdSJoe Komlodi REG32(QUEUE_STATUS_LEVEL, 0x4c) 41*c52aaabdSJoe Komlodi REG32(DATA_BUFFER_STATUS_LEVEL, 0x50) 42*c52aaabdSJoe Komlodi REG32(PRESENT_STATE, 0x54) 43*c52aaabdSJoe Komlodi REG32(CCC_DEVICE_STATUS, 0x58) 44*c52aaabdSJoe Komlodi REG32(DEVICE_ADDR_TABLE_POINTER, 0x5c) 45*c52aaabdSJoe Komlodi FIELD(DEVICE_ADDR_TABLE_POINTER, DEPTH, 16, 16) 46*c52aaabdSJoe Komlodi FIELD(DEVICE_ADDR_TABLE_POINTER, ADDR, 0, 16) 47*c52aaabdSJoe Komlodi REG32(DEV_CHAR_TABLE_POINTER, 0x60) 48*c52aaabdSJoe Komlodi REG32(VENDOR_SPECIFIC_REG_POINTER, 0x6c) 49*c52aaabdSJoe Komlodi REG32(SLV_MIPI_PID_VALUE, 0x70) 50*c52aaabdSJoe Komlodi REG32(SLV_PID_VALUE, 0x74) 51*c52aaabdSJoe Komlodi REG32(SLV_CHAR_CTRL, 0x78) 52*c52aaabdSJoe Komlodi REG32(SLV_MAX_LEN, 0x7c) 53*c52aaabdSJoe Komlodi REG32(MAX_READ_TURNAROUND, 0x80) 54*c52aaabdSJoe Komlodi REG32(MAX_DATA_SPEED, 0x84) 55*c52aaabdSJoe Komlodi REG32(SLV_DEBUG_STATUS, 0x88) 56*c52aaabdSJoe Komlodi REG32(SLV_INTR_REQ, 0x8c) 57*c52aaabdSJoe Komlodi REG32(DEVICE_CTRL_EXTENDED, 0xb0) 58*c52aaabdSJoe Komlodi REG32(SCL_I3C_OD_TIMING, 0xb4) 59*c52aaabdSJoe Komlodi REG32(SCL_I3C_PP_TIMING, 0xb8) 60*c52aaabdSJoe Komlodi REG32(SCL_I2C_FM_TIMING, 0xbc) 61*c52aaabdSJoe Komlodi REG32(SCL_I2C_FMP_TIMING, 0xc0) 62*c52aaabdSJoe Komlodi REG32(SCL_EXT_LCNT_TIMING, 0xc8) 63*c52aaabdSJoe Komlodi REG32(SCL_EXT_TERMN_LCNT_TIMING, 0xcc) 64*c52aaabdSJoe Komlodi REG32(BUS_FREE_TIMING, 0xd4) 65*c52aaabdSJoe Komlodi REG32(BUS_IDLE_TIMING, 0xd8) 66*c52aaabdSJoe Komlodi REG32(I3C_VER_ID, 0xe0) 67*c52aaabdSJoe Komlodi REG32(I3C_VER_TYPE, 0xe4) 68*c52aaabdSJoe Komlodi REG32(EXTENDED_CAPABILITY, 0xe8) 69*c52aaabdSJoe Komlodi REG32(SLAVE_CONFIG, 0xec) 70*c52aaabdSJoe Komlodi 71*c52aaabdSJoe Komlodi static const uint32_t dw_i3c_resets[DW_I3C_NR_REGS] = { 72*c52aaabdSJoe Komlodi [R_HW_CAPABILITY] = 0x000e00bf, 73*c52aaabdSJoe Komlodi [R_QUEUE_THLD_CTRL] = 0x01000101, 74*c52aaabdSJoe Komlodi [R_I3C_VER_ID] = 0x3130302a, 75*c52aaabdSJoe Komlodi [R_I3C_VER_TYPE] = 0x6c633033, 76*c52aaabdSJoe Komlodi [R_DEVICE_ADDR_TABLE_POINTER] = 0x00080280, 77*c52aaabdSJoe Komlodi [R_DEV_CHAR_TABLE_POINTER] = 0x00020200, 78*c52aaabdSJoe Komlodi [A_VENDOR_SPECIFIC_REG_POINTER] = 0x000000b0, 79*c52aaabdSJoe Komlodi [R_SLV_MAX_LEN] = 0x00ff00ff, 80*c52aaabdSJoe Komlodi }; 81*c52aaabdSJoe Komlodi 82*c52aaabdSJoe Komlodi static uint64_t dw_i3c_read(void *opaque, hwaddr offset, unsigned size) 83*c52aaabdSJoe Komlodi { 84*c52aaabdSJoe Komlodi DWI3C *s = DW_I3C(opaque); 85*c52aaabdSJoe Komlodi uint32_t addr = offset >> 2; 86*c52aaabdSJoe Komlodi uint64_t value; 87*c52aaabdSJoe Komlodi 88*c52aaabdSJoe Komlodi switch (addr) { 89*c52aaabdSJoe Komlodi case R_COMMAND_QUEUE_PORT: 90*c52aaabdSJoe Komlodi value = 0; 91*c52aaabdSJoe Komlodi break; 92*c52aaabdSJoe Komlodi default: 93*c52aaabdSJoe Komlodi value = s->regs[addr]; 94*c52aaabdSJoe Komlodi break; 95*c52aaabdSJoe Komlodi } 96*c52aaabdSJoe Komlodi 97*c52aaabdSJoe Komlodi trace_dw_i3c_read(s->id, offset, value); 98*c52aaabdSJoe Komlodi 99*c52aaabdSJoe Komlodi return value; 100*c52aaabdSJoe Komlodi } 101*c52aaabdSJoe Komlodi 102*c52aaabdSJoe Komlodi static void dw_i3c_write(void *opaque, hwaddr offset, uint64_t value, 103*c52aaabdSJoe Komlodi unsigned size) 104*c52aaabdSJoe Komlodi { 105*c52aaabdSJoe Komlodi DWI3C *s = DW_I3C(opaque); 106*c52aaabdSJoe Komlodi uint32_t addr = offset >> 2; 107*c52aaabdSJoe Komlodi 108*c52aaabdSJoe Komlodi trace_dw_i3c_write(s->id, offset, value); 109*c52aaabdSJoe Komlodi 110*c52aaabdSJoe Komlodi switch (addr) { 111*c52aaabdSJoe Komlodi case R_HW_CAPABILITY: 112*c52aaabdSJoe Komlodi case R_RESPONSE_QUEUE_PORT: 113*c52aaabdSJoe Komlodi case R_IBI_QUEUE_DATA: 114*c52aaabdSJoe Komlodi case R_QUEUE_STATUS_LEVEL: 115*c52aaabdSJoe Komlodi case R_PRESENT_STATE: 116*c52aaabdSJoe Komlodi case R_CCC_DEVICE_STATUS: 117*c52aaabdSJoe Komlodi case R_DEVICE_ADDR_TABLE_POINTER: 118*c52aaabdSJoe Komlodi case R_VENDOR_SPECIFIC_REG_POINTER: 119*c52aaabdSJoe Komlodi case R_SLV_CHAR_CTRL: 120*c52aaabdSJoe Komlodi case R_SLV_MAX_LEN: 121*c52aaabdSJoe Komlodi case R_MAX_READ_TURNAROUND: 122*c52aaabdSJoe Komlodi case R_I3C_VER_ID: 123*c52aaabdSJoe Komlodi case R_I3C_VER_TYPE: 124*c52aaabdSJoe Komlodi case R_EXTENDED_CAPABILITY: 125*c52aaabdSJoe Komlodi qemu_log_mask(LOG_GUEST_ERROR, 126*c52aaabdSJoe Komlodi "%s: write to readonly register[0x%02" HWADDR_PRIx 127*c52aaabdSJoe Komlodi "] = 0x%08" PRIx64 "\n", 128*c52aaabdSJoe Komlodi __func__, offset, value); 129*c52aaabdSJoe Komlodi break; 130*c52aaabdSJoe Komlodi case R_RX_TX_DATA_PORT: 131*c52aaabdSJoe Komlodi break; 132*c52aaabdSJoe Komlodi case R_RESET_CTRL: 133*c52aaabdSJoe Komlodi break; 134*c52aaabdSJoe Komlodi default: 135*c52aaabdSJoe Komlodi s->regs[addr] = value; 136*c52aaabdSJoe Komlodi break; 137*c52aaabdSJoe Komlodi } 138*c52aaabdSJoe Komlodi } 139*c52aaabdSJoe Komlodi 140*c52aaabdSJoe Komlodi const VMStateDescription vmstate_dw_i3c = { 141*c52aaabdSJoe Komlodi .name = TYPE_DW_I3C, 142*c52aaabdSJoe Komlodi .version_id = 1, 143*c52aaabdSJoe Komlodi .minimum_version_id = 1, 144*c52aaabdSJoe Komlodi .fields = (VMStateField[]){ 145*c52aaabdSJoe Komlodi VMSTATE_UINT32_ARRAY(regs, DWI3C, DW_I3C_NR_REGS), 146*c52aaabdSJoe Komlodi VMSTATE_END_OF_LIST(), 147*c52aaabdSJoe Komlodi } 148*c52aaabdSJoe Komlodi }; 149*c52aaabdSJoe Komlodi 150*c52aaabdSJoe Komlodi static const MemoryRegionOps dw_i3c_ops = { 151*c52aaabdSJoe Komlodi .read = dw_i3c_read, 152*c52aaabdSJoe Komlodi .write = dw_i3c_write, 153*c52aaabdSJoe Komlodi .endianness = DEVICE_LITTLE_ENDIAN, 154*c52aaabdSJoe Komlodi }; 155*c52aaabdSJoe Komlodi 156*c52aaabdSJoe Komlodi static void dw_i3c_reset_enter(Object *obj, ResetType type) 157*c52aaabdSJoe Komlodi { 158*c52aaabdSJoe Komlodi DWI3C *s = DW_I3C(obj); 159*c52aaabdSJoe Komlodi 160*c52aaabdSJoe Komlodi memcpy(s->regs, dw_i3c_resets, sizeof(s->regs)); 161*c52aaabdSJoe Komlodi } 162*c52aaabdSJoe Komlodi 163*c52aaabdSJoe Komlodi static void dw_i3c_realize(DeviceState *dev, Error **errp) 164*c52aaabdSJoe Komlodi { 165*c52aaabdSJoe Komlodi DWI3C *s = DW_I3C(dev); 166*c52aaabdSJoe Komlodi g_autofree char *name = g_strdup_printf(TYPE_DW_I3C ".%d", s->id); 167*c52aaabdSJoe Komlodi 168*c52aaabdSJoe Komlodi sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); 169*c52aaabdSJoe Komlodi 170*c52aaabdSJoe Komlodi memory_region_init_io(&s->mr, OBJECT(s), &dw_i3c_ops, s, name, 171*c52aaabdSJoe Komlodi DW_I3C_NR_REGS << 2); 172*c52aaabdSJoe Komlodi sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr); 173*c52aaabdSJoe Komlodi } 174*c52aaabdSJoe Komlodi 175*c52aaabdSJoe Komlodi static const Property dw_i3c_properties[] = { 176*c52aaabdSJoe Komlodi DEFINE_PROP_UINT8("device-id", DWI3C, id, 0), 177*c52aaabdSJoe Komlodi }; 178*c52aaabdSJoe Komlodi 179*c52aaabdSJoe Komlodi static void dw_i3c_class_init(ObjectClass *klass, const void *data) 180*c52aaabdSJoe Komlodi { 181*c52aaabdSJoe Komlodi DeviceClass *dc = DEVICE_CLASS(klass); 182*c52aaabdSJoe Komlodi ResettableClass *rc = RESETTABLE_CLASS(klass); 183*c52aaabdSJoe Komlodi 184*c52aaabdSJoe Komlodi rc->phases.enter = dw_i3c_reset_enter; 185*c52aaabdSJoe Komlodi 186*c52aaabdSJoe Komlodi dc->desc = "DesignWare I3C Controller"; 187*c52aaabdSJoe Komlodi dc->realize = dw_i3c_realize; 188*c52aaabdSJoe Komlodi dc->vmsd = &vmstate_dw_i3c; 189*c52aaabdSJoe Komlodi device_class_set_props(dc, dw_i3c_properties); 190*c52aaabdSJoe Komlodi } 191*c52aaabdSJoe Komlodi 192*c52aaabdSJoe Komlodi static const TypeInfo dw_i3c_info = { 193*c52aaabdSJoe Komlodi .name = TYPE_DW_I3C, 194*c52aaabdSJoe Komlodi .parent = TYPE_SYS_BUS_DEVICE, 195*c52aaabdSJoe Komlodi .instance_size = sizeof(DWI3C), 196*c52aaabdSJoe Komlodi .class_init = dw_i3c_class_init, 197*c52aaabdSJoe Komlodi }; 198*c52aaabdSJoe Komlodi 199*c52aaabdSJoe Komlodi static void dw_i3c_register_types(void) 200*c52aaabdSJoe Komlodi { 201*c52aaabdSJoe Komlodi type_register_static(&dw_i3c_info); 202*c52aaabdSJoe Komlodi } 203*c52aaabdSJoe Komlodi 204*c52aaabdSJoe Komlodi type_init(dw_i3c_register_types); 205