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