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