1 /* 2 * ASPEED I3C Controller 3 * 4 * Copyright (C) 2021 ASPEED Technology Inc. 5 * Copyright (C) 2025 Google, LLC. 6 * 7 * This code is licensed under the GPL version 2 or later. See 8 * the COPYING file in the top-level directory. 9 */ 10 11 #include "qemu/osdep.h" 12 #include "qemu/log.h" 13 #include "qemu/error-report.h" 14 #include "hw/i3c/aspeed_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 /* I3C Controller Registers */ 22 REG32(I3C1_REG0, 0x10) 23 REG32(I3C1_REG1, 0x14) 24 FIELD(I3C1_REG1, I2C_MODE, 0, 1) 25 FIELD(I3C1_REG1, SLV_TEST_MODE, 1, 1) 26 FIELD(I3C1_REG1, ACT_MODE, 2, 2) 27 FIELD(I3C1_REG1, PENDING_INT, 4, 4) 28 FIELD(I3C1_REG1, SA, 8, 7) 29 FIELD(I3C1_REG1, SA_EN, 15, 1) 30 FIELD(I3C1_REG1, INST_ID, 16, 4) 31 REG32(I3C2_REG0, 0x20) 32 REG32(I3C2_REG1, 0x24) 33 FIELD(I3C2_REG1, I2C_MODE, 0, 1) 34 FIELD(I3C2_REG1, SLV_TEST_MODE, 1, 1) 35 FIELD(I3C2_REG1, ACT_MODE, 2, 2) 36 FIELD(I3C2_REG1, PENDING_INT, 4, 4) 37 FIELD(I3C2_REG1, SA, 8, 7) 38 FIELD(I3C2_REG1, SA_EN, 15, 1) 39 FIELD(I3C2_REG1, INST_ID, 16, 4) 40 REG32(I3C3_REG0, 0x30) 41 REG32(I3C3_REG1, 0x34) 42 FIELD(I3C3_REG1, I2C_MODE, 0, 1) 43 FIELD(I3C3_REG1, SLV_TEST_MODE, 1, 1) 44 FIELD(I3C3_REG1, ACT_MODE, 2, 2) 45 FIELD(I3C3_REG1, PENDING_INT, 4, 4) 46 FIELD(I3C3_REG1, SA, 8, 7) 47 FIELD(I3C3_REG1, SA_EN, 15, 1) 48 FIELD(I3C3_REG1, INST_ID, 16, 4) 49 REG32(I3C4_REG0, 0x40) 50 REG32(I3C4_REG1, 0x44) 51 FIELD(I3C4_REG1, I2C_MODE, 0, 1) 52 FIELD(I3C4_REG1, SLV_TEST_MODE, 1, 1) 53 FIELD(I3C4_REG1, ACT_MODE, 2, 2) 54 FIELD(I3C4_REG1, PENDING_INT, 4, 4) 55 FIELD(I3C4_REG1, SA, 8, 7) 56 FIELD(I3C4_REG1, SA_EN, 15, 1) 57 FIELD(I3C4_REG1, INST_ID, 16, 4) 58 REG32(I3C5_REG0, 0x50) 59 REG32(I3C5_REG1, 0x54) 60 FIELD(I3C5_REG1, I2C_MODE, 0, 1) 61 FIELD(I3C5_REG1, SLV_TEST_MODE, 1, 1) 62 FIELD(I3C5_REG1, ACT_MODE, 2, 2) 63 FIELD(I3C5_REG1, PENDING_INT, 4, 4) 64 FIELD(I3C5_REG1, SA, 8, 7) 65 FIELD(I3C5_REG1, SA_EN, 15, 1) 66 FIELD(I3C5_REG1, INST_ID, 16, 4) 67 REG32(I3C6_REG0, 0x60) 68 REG32(I3C6_REG1, 0x64) 69 FIELD(I3C6_REG1, I2C_MODE, 0, 1) 70 FIELD(I3C6_REG1, SLV_TEST_MODE, 1, 1) 71 FIELD(I3C6_REG1, ACT_MODE, 2, 2) 72 FIELD(I3C6_REG1, PENDING_INT, 4, 4) 73 FIELD(I3C6_REG1, SA, 8, 7) 74 FIELD(I3C6_REG1, SA_EN, 15, 1) 75 FIELD(I3C6_REG1, INST_ID, 16, 4) 76 77 static const uint32_t ast2600_i3c_controller_ro[ASPEED_I3C_NR_REGS] = { 78 [R_I3C1_REG0] = 0xfc000000, 79 [R_I3C1_REG1] = 0xfff00000, 80 [R_I3C2_REG0] = 0xfc000000, 81 [R_I3C2_REG1] = 0xfff00000, 82 [R_I3C3_REG0] = 0xfc000000, 83 [R_I3C3_REG1] = 0xfff00000, 84 [R_I3C4_REG0] = 0xfc000000, 85 [R_I3C4_REG1] = 0xfff00000, 86 [R_I3C5_REG0] = 0xfc000000, 87 [R_I3C5_REG1] = 0xfff00000, 88 [R_I3C6_REG0] = 0xfc000000, 89 [R_I3C6_REG1] = 0xfff00000, 90 }; 91 92 static uint64_t aspeed_i3c_read(void *opaque, hwaddr addr, unsigned int size) 93 { 94 AspeedI3CState *s = ASPEED_I3C(opaque); 95 uint64_t val = 0; 96 97 val = s->regs[addr >> 2]; 98 99 trace_aspeed_i3c_read(addr, val); 100 101 return val; 102 } 103 104 static void aspeed_i3c_write(void *opaque, 105 hwaddr addr, 106 uint64_t data, 107 unsigned int size) 108 { 109 AspeedI3CState *s = ASPEED_I3C(opaque); 110 111 trace_aspeed_i3c_write(addr, data); 112 113 addr >>= 2; 114 115 data &= ~ast2600_i3c_controller_ro[addr]; 116 /* I3C controller register */ 117 switch (addr) { 118 case R_I3C1_REG1: 119 case R_I3C2_REG1: 120 case R_I3C3_REG1: 121 case R_I3C4_REG1: 122 case R_I3C5_REG1: 123 case R_I3C6_REG1: 124 if (data & R_I3C1_REG1_I2C_MODE_MASK) { 125 qemu_log_mask(LOG_UNIMP, 126 "%s: Unsupported I2C mode [0x%08" HWADDR_PRIx 127 "]=%08" PRIx64 "\n", 128 __func__, addr << 2, data); 129 break; 130 } 131 if (data & R_I3C1_REG1_SA_EN_MASK) { 132 qemu_log_mask(LOG_UNIMP, 133 "%s: Unsupported slave mode [%08" HWADDR_PRIx 134 "]=0x%08" PRIx64 "\n", 135 __func__, addr << 2, data); 136 break; 137 } 138 s->regs[addr] = data; 139 break; 140 default: 141 s->regs[addr] = data; 142 break; 143 } 144 } 145 146 static const MemoryRegionOps aspeed_i3c_ops = { 147 .read = aspeed_i3c_read, 148 .write = aspeed_i3c_write, 149 .endianness = DEVICE_LITTLE_ENDIAN, 150 .valid = { 151 .min_access_size = 1, 152 .max_access_size = 4, 153 } 154 }; 155 156 I3CBus *aspeed_i3c_get_bus(AspeedI3CState *s, uint8_t bus_num) 157 { 158 if (bus_num < ARRAY_SIZE(s->devices)) { 159 return s->devices[bus_num].bus; 160 } 161 /* Developer error, fail fast. */ 162 g_assert_not_reached(); 163 } 164 165 static void aspeed_i3c_reset(DeviceState *dev) 166 { 167 AspeedI3CState *s = ASPEED_I3C(dev); 168 memset(s->regs, 0, sizeof(s->regs)); 169 } 170 171 static void aspeed_i3c_instance_init(Object *obj) 172 { 173 AspeedI3CState *s = ASPEED_I3C(obj); 174 int i; 175 176 for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { 177 object_initialize_child(obj, "device[*]", &s->devices[i], 178 TYPE_DW_I3C); 179 } 180 } 181 182 static void aspeed_i3c_realize(DeviceState *dev, Error **errp) 183 { 184 int i; 185 AspeedI3CState *s = ASPEED_I3C(dev); 186 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 187 188 memory_region_init(&s->iomem_container, OBJECT(s), 189 TYPE_ASPEED_I3C ".container", 0x8000); 190 191 sysbus_init_mmio(sbd, &s->iomem_container); 192 193 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i3c_ops, s, 194 TYPE_ASPEED_I3C ".regs", ASPEED_I3C_NR_REGS << 2); 195 196 memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem); 197 198 for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { 199 Object *i3c_dev = OBJECT(&s->devices[i]); 200 201 if (!object_property_set_uint(i3c_dev, "device-id", i, errp)) { 202 return; 203 } 204 205 if (!sysbus_realize(SYS_BUS_DEVICE(i3c_dev), errp)) { 206 return; 207 } 208 209 /* 210 * Register Address of I3CX Device = 211 * (Base Address of Global Register) + (Offset of I3CX) + Offset 212 * X = 0, 1, 2, 3, 4, 5 213 * Offset of I3C0 = 0x2000 214 * Offset of I3C1 = 0x3000 215 * Offset of I3C2 = 0x4000 216 * Offset of I3C3 = 0x5000 217 * Offset of I3C4 = 0x6000 218 * Offset of I3C5 = 0x7000 219 */ 220 memory_region_add_subregion(&s->iomem_container, 221 0x2000 + i * 0x1000, &s->devices[i].mr); 222 } 223 224 } 225 226 static const VMStateDescription vmstate_aspeed_i3c = { 227 .name = TYPE_ASPEED_I3C, 228 .version_id = 1, 229 .minimum_version_id = 1, 230 .fields = (const VMStateField[]) { 231 VMSTATE_UINT32_ARRAY(regs, AspeedI3CState, ASPEED_I3C_NR_REGS), 232 VMSTATE_STRUCT_ARRAY(devices, AspeedI3CState, ASPEED_I3C_NR_DEVICES, 1, 233 vmstate_dw_i3c, DWI3C), 234 VMSTATE_END_OF_LIST(), 235 } 236 }; 237 238 static void aspeed_i3c_class_init(ObjectClass *klass, const void *data) 239 { 240 DeviceClass *dc = DEVICE_CLASS(klass); 241 242 dc->realize = aspeed_i3c_realize; 243 device_class_set_legacy_reset(dc, aspeed_i3c_reset); 244 dc->desc = "Aspeed I3C Controller"; 245 dc->vmsd = &vmstate_aspeed_i3c; 246 } 247 248 static const TypeInfo aspeed_i3c_info = { 249 .name = TYPE_ASPEED_I3C, 250 .parent = TYPE_SYS_BUS_DEVICE, 251 .instance_init = aspeed_i3c_instance_init, 252 .instance_size = sizeof(AspeedI3CState), 253 .class_init = aspeed_i3c_class_init, 254 }; 255 256 static void aspeed_i3c_register_types(void) 257 { 258 type_register_static(&aspeed_i3c_info); 259 } 260 261 type_init(aspeed_i3c_register_types); 262