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 static void aspeed_i3c_reset(DeviceState *dev) 157 { 158 AspeedI3CState *s = ASPEED_I3C(dev); 159 memset(s->regs, 0, sizeof(s->regs)); 160 } 161 162 static void aspeed_i3c_instance_init(Object *obj) 163 { 164 AspeedI3CState *s = ASPEED_I3C(obj); 165 int i; 166 167 for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { 168 object_initialize_child(obj, "device[*]", &s->devices[i], 169 TYPE_DW_I3C); 170 } 171 } 172 173 static void aspeed_i3c_realize(DeviceState *dev, Error **errp) 174 { 175 int i; 176 AspeedI3CState *s = ASPEED_I3C(dev); 177 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 178 179 memory_region_init(&s->iomem_container, OBJECT(s), 180 TYPE_ASPEED_I3C ".container", 0x8000); 181 182 sysbus_init_mmio(sbd, &s->iomem_container); 183 184 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i3c_ops, s, 185 TYPE_ASPEED_I3C ".regs", ASPEED_I3C_NR_REGS << 2); 186 187 memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem); 188 189 for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { 190 Object *i3c_dev = OBJECT(&s->devices[i]); 191 192 if (!object_property_set_uint(i3c_dev, "device-id", i, errp)) { 193 return; 194 } 195 196 if (!sysbus_realize(SYS_BUS_DEVICE(i3c_dev), errp)) { 197 return; 198 } 199 200 /* 201 * Register Address of I3CX Device = 202 * (Base Address of Global Register) + (Offset of I3CX) + Offset 203 * X = 0, 1, 2, 3, 4, 5 204 * Offset of I3C0 = 0x2000 205 * Offset of I3C1 = 0x3000 206 * Offset of I3C2 = 0x4000 207 * Offset of I3C3 = 0x5000 208 * Offset of I3C4 = 0x6000 209 * Offset of I3C5 = 0x7000 210 */ 211 memory_region_add_subregion(&s->iomem_container, 212 0x2000 + i * 0x1000, &s->devices[i].mr); 213 } 214 215 } 216 217 static const VMStateDescription vmstate_aspeed_i3c = { 218 .name = TYPE_ASPEED_I3C, 219 .version_id = 1, 220 .minimum_version_id = 1, 221 .fields = (const VMStateField[]) { 222 VMSTATE_UINT32_ARRAY(regs, AspeedI3CState, ASPEED_I3C_NR_REGS), 223 VMSTATE_STRUCT_ARRAY(devices, AspeedI3CState, ASPEED_I3C_NR_DEVICES, 1, 224 vmstate_dw_i3c, DWI3C), 225 VMSTATE_END_OF_LIST(), 226 } 227 }; 228 229 static void aspeed_i3c_class_init(ObjectClass *klass, const void *data) 230 { 231 DeviceClass *dc = DEVICE_CLASS(klass); 232 233 dc->realize = aspeed_i3c_realize; 234 device_class_set_legacy_reset(dc, aspeed_i3c_reset); 235 dc->desc = "Aspeed I3C Controller"; 236 dc->vmsd = &vmstate_aspeed_i3c; 237 } 238 239 static const TypeInfo aspeed_i3c_info = { 240 .name = TYPE_ASPEED_I3C, 241 .parent = TYPE_SYS_BUS_DEVICE, 242 .instance_init = aspeed_i3c_instance_init, 243 .instance_size = sizeof(AspeedI3CState), 244 .class_init = aspeed_i3c_class_init, 245 }; 246 247 static void aspeed_i3c_register_types(void) 248 { 249 type_register_static(&aspeed_i3c_info); 250 } 251 252 type_init(aspeed_i3c_register_types); 253