xref: /openbmc/qemu/hw/i3c/core.c (revision d4cd70c28ec3b51f136053340662df6744b5f76d)
1 /*
2  * QEMU I3C bus interface.
3  *
4  * Copyright 2025 Google LLC
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include "qemu/log.h"
11 #include "qapi/error.h"
12 #include "trace.h"
13 #include "hw/i3c/i3c.h"
14 #include "hw/hotplug.h"
15 #include "hw/qdev-properties.h"
16 
17 /*
18  * In test mode (enabled by ENTTM CCC) we're supposed to send a random PID
19  * during ENTDAA, so we'll just send "QEMU".
20  */
21 #define TEST_MODE_PROVISIONED_ID 0x0000554d4551ULL
22 
23 static const Property i3c_props[] = {
24     DEFINE_PROP_UINT8("static-address", struct I3CTarget, static_address, 0),
25     DEFINE_PROP_UINT8("dcr", struct I3CTarget, dcr, 0),
26     DEFINE_PROP_UINT8("bcr", struct I3CTarget, bcr, 0),
27     DEFINE_PROP_UINT64("pid", struct I3CTarget, pid, 0),
28 };
29 
i3c_realize(BusState * bus,Error ** errp)30 static void i3c_realize(BusState *bus, Error **errp)
31 {
32     qbus_set_bus_hotplug_handler(bus);
33 }
34 
i3c_class_init(ObjectClass * klass,const void * data)35 static void i3c_class_init(ObjectClass *klass, const void *data)
36 {
37     BusClass *k = BUS_CLASS(klass);
38     k->realize = i3c_realize;
39 }
40 
41 static const TypeInfo i3c_bus_info = {
42     .name = TYPE_I3C_BUS,
43     .parent = TYPE_BUS,
44     .instance_size = sizeof(I3CBus),
45     .class_size = sizeof(I3CBusClass),
46     .class_init = i3c_class_init,
47     .interfaces = (InterfaceInfo[]) {
48         { TYPE_HOTPLUG_HANDLER },
49         { }
50     }
51 };
52 
i3c_init_bus(DeviceState * parent,const char * name)53 I3CBus *i3c_init_bus(DeviceState *parent, const char *name)
54 {
55     return i3c_init_bus_type(TYPE_I3C_BUS, parent, name);
56 }
57 
i3c_init_bus_type(const char * type,DeviceState * parent,const char * name)58 I3CBus *i3c_init_bus_type(const char *type, DeviceState *parent,
59                           const char *name)
60 {
61     I3CBus *bus;
62 
63     bus = I3C_BUS(qbus_new(type, parent, name));
64     QLIST_INIT(&bus->current_devs);
65     bus->broadcast = false;
66     bus->in_entdaa = false;
67     bus->in_ccc = false;
68 
69     /* I2C init. */
70     g_autofree gchar *i2c_bus_name = g_strdup_printf("%s-legacy-i2c", name);
71     bus->i2c_bus = i2c_init_bus(parent, i2c_bus_name);
72 
73     return bus;
74 }
75 
i3c_bus_busy(I3CBus * bus)76 bool i3c_bus_busy(I3CBus *bus)
77 {
78     return !QLIST_EMPTY(&bus->current_devs);
79 }
80 
i3c_target_match(I3CTarget * candidate,uint8_t address,bool is_recv,bool broadcast,bool in_entdaa)81 static bool i3c_target_match(I3CTarget *candidate, uint8_t address,
82                              bool is_recv, bool broadcast, bool in_entdaa)
83 {
84     /* Once a target has a dynamic address, it only responds to that. */
85     uint8_t targ_addr = candidate->address ? candidate->address :
86                                              candidate->static_address;
87 
88     if (in_entdaa) {
89         if (address != I3C_BROADCAST) {
90             g_autofree char *path =
91                 object_get_canonical_path(OBJECT(candidate));
92             qemu_log_mask(LOG_GUEST_ERROR, "%s: I3C Address 0x%.2x sent during "
93                           "ENTDAA instead of a broadcast address\n",
94                           path, address);
95             return false;
96         }
97 
98         /*
99          * Targets should only ACK ENTDAA broadcasts if they have no dynamic
100          * address.
101          */
102         return candidate->address == 0;
103     }
104 
105     /* Return if our addresses match, or if it's a broadcast. */
106     return targ_addr == address || broadcast;
107 }
108 
i3c_target_match_and_add(I3CBus * bus,I3CTarget * target,uint8_t address,enum I3CEvent event)109 bool i3c_target_match_and_add(I3CBus *bus, I3CTarget *target, uint8_t address,
110                               enum I3CEvent event)
111 {
112     I3CTargetClass *tc = I3C_TARGET_GET_CLASS(target);
113     bool matched = tc->target_match(target, address, event == I3C_START_RECV,
114                                     bus->broadcast, bus->in_entdaa);
115 
116     if (matched) {
117         I3CNode *node = g_new(struct I3CNode, 1);
118         node->target = target;
119         QLIST_INSERT_HEAD(&bus->current_devs, node, next);
120     }
121     return matched;
122 }
123 
i3c_scan_bus(I3CBus * bus,uint8_t address,enum I3CEvent event)124 bool i3c_scan_bus(I3CBus *bus, uint8_t address, enum I3CEvent event)
125 {
126     BusChild *child;
127     I3CNode *node, *next;
128 
129     /* Clear out any devices from a previous (re-)START. */
130     QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
131         QLIST_REMOVE(node, next);
132         g_free(node);
133     }
134 
135     QTAILQ_FOREACH(child, &bus->qbus.children, sibling) {
136         DeviceState *qdev = child->child;
137         I3CTarget *target = I3C_TARGET(qdev);
138 
139         if (i3c_target_match_and_add(bus, target, address, event)) {
140             return true;
141         }
142     }
143 
144     /* No one on the bus could respond. */
145     return false;
146 }
147 
148 /* Class-level event handling, since we do some CCCs at the class level. */
i3c_target_event(I3CTarget * t,enum I3CEvent event)149 static int i3c_target_event(I3CTarget *t, enum I3CEvent event)
150 {
151     I3CTargetClass *tc = I3C_TARGET_GET_CLASS(t);
152     trace_i3c_target_event(t->address, event);
153 
154     if (event == I3C_STOP) {
155         t->curr_ccc = 0;
156         t->ccc_byte_offset = 0;
157         t->in_ccc = false;
158     }
159     return tc->event(t, event);
160 }
161 
162 /*
163  * Sends a START or repeated START and the address for an I3C transaction.
164  *
165  * This function returns 0 if a device on the bus was able to respond to the
166  * address, and non-zero otherwise.
167  * A non-zero return represents a NACK.
168  */
i3c_do_start_transfer(I3CBus * bus,uint8_t address,enum I3CEvent event)169 static int i3c_do_start_transfer(I3CBus *bus, uint8_t address,
170                                  enum I3CEvent event)
171 {
172     I3CTargetClass *tc;
173     I3CNode *node;
174 
175     if (address == I3C_BROADCAST) {
176         bus->broadcast = true;
177         /* If we're not in ENTDAA, a broadcast is the start of a new CCC. */
178         if (!bus->in_entdaa) {
179             bus->in_ccc = false;
180         }
181     } else {
182         bus->broadcast = false;
183     }
184 
185     /* No one responded to the address, NACK it. */
186     if (!i3c_scan_bus(bus, address, event)) {
187         return -1;
188     }
189 
190     QLIST_FOREACH(node, &bus->current_devs, next) {
191         I3CTarget *t = node->target;
192 
193         tc = I3C_TARGET_GET_CLASS(t);
194         if (tc->event) {
195             int rv = i3c_target_event(t, event);
196             if (rv && !bus->broadcast) {
197                 return rv;
198             }
199         }
200     }
201 
202     return 0;
203 }
204 
i3c_start_transfer(I3CBus * bus,uint8_t address,bool is_recv)205 int i3c_start_transfer(I3CBus *bus, uint8_t address, bool is_recv)
206 {
207     trace_i3c_start_transfer(address, is_recv);
208     return i3c_do_start_transfer(bus, address, is_recv
209                                                ? I3C_START_RECV
210                                                : I3C_START_SEND);
211 }
212 
i3c_start_recv(I3CBus * bus,uint8_t address)213 int i3c_start_recv(I3CBus *bus, uint8_t address)
214 {
215     trace_i3c_start_transfer(address, true);
216     return i3c_do_start_transfer(bus, address, I3C_START_RECV);
217 }
218 
i3c_start_send(I3CBus * bus,uint8_t address)219 int i3c_start_send(I3CBus *bus, uint8_t address)
220 {
221     trace_i3c_start_transfer(address, false);
222     return i3c_do_start_transfer(bus, address, I3C_START_SEND);
223 }
224 
i3c_end_transfer(I3CBus * bus)225 void i3c_end_transfer(I3CBus *bus)
226 {
227     I3CTargetClass *tc;
228     I3CNode *node, *next;
229 
230     trace_i3c_end_transfer();
231 
232     /*
233      * If we're in ENTDAA, we need to notify all devices when ENTDAA is done.
234      * This is because everyone initially participates due to the broadcast,
235      * but gradually drops out as they get assigned addresses.
236      * Since the current_devs list only stores who's currently participating,
237      * and not everyone who previously participated, we send the STOP to all
238      * children.
239      */
240     if (bus->in_entdaa) {
241         BusChild *child;
242 
243         QTAILQ_FOREACH(child, &bus->qbus.children, sibling) {
244             DeviceState *qdev = child->child;
245             I3CTarget *t = I3C_TARGET(qdev);
246             tc = I3C_TARGET_GET_CLASS(t);
247             if (tc->event) {
248                 i3c_target_event(t, I3C_STOP);
249             }
250         }
251     } else {
252         QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
253             I3CTarget *t = node->target;
254             tc = I3C_TARGET_GET_CLASS(t);
255             if (tc->event) {
256                 i3c_target_event(t, I3C_STOP);
257             }
258             QLIST_REMOVE(node, next);
259             g_free(node);
260         }
261     }
262     bus->broadcast = false;
263     bus->in_entdaa = false;
264     bus->in_ccc = false;
265 }
266 
267 /*
268  * Any CCCs that are universal across all I3C devices should be handled here.
269  * Once they're handled, we pass the CCC up to the I3C target to do anything
270  * else it may want with the bytes.
271  */
i3c_target_handle_ccc_write(I3CTarget * t,const uint8_t * data,uint32_t num_to_send,uint32_t * num_sent)272 static int i3c_target_handle_ccc_write(I3CTarget *t, const uint8_t *data,
273                                        uint32_t num_to_send, uint32_t *num_sent)
274 {
275     I3CTargetClass *tc = I3C_TARGET_GET_CLASS(t);
276     *num_sent = 0;
277 
278     /* Is this the start of a new CCC? */
279     if (!t->in_ccc) {
280         t->curr_ccc = *data;
281         t->in_ccc = true;
282         *num_sent = 1;
283         trace_i3c_target_handle_ccc(t->address, t->curr_ccc);
284     }
285 
286     switch (t->curr_ccc) {
287     case I3C_CCC_ENTDAA:
288         /*
289          * This is the last byte of ENTDAA, the controller is assigning us an
290          * address.
291          */
292         if (t->ccc_byte_offset == 8) {
293             t->address = *data;
294             t->in_ccc = false;
295             t->curr_ccc = 0;
296             t->ccc_byte_offset = 0;
297             *num_sent = 1;
298         }
299         break;
300     case I3C_CCCD_SETDASA:
301         t->address = t->static_address;
302         break;
303     case I3C_CCC_SETAASA:
304         t->address = t->static_address;
305         break;
306     case I3C_CCC_RSTDAA:
307         t->address = 0;
308         break;
309     case I3C_CCCD_SETNEWDA:
310         /* If this isn't the CCC byte, it's our new address. */
311         if (*num_sent == 0) {
312             t->address = *data;
313             *num_sent = 1;
314         }
315         break;
316     case I3C_CCC_ENTTM:
317         /*
318          * If there are still more to look at, the next byte is the test mode
319          * byte.
320          */
321         if (*num_sent != num_to_send) {
322             /* Enter test mode if the byte is non-zero. Otherwise exit. */
323             t->in_test_mode = !!data[*num_sent];
324             ++*num_sent;
325         }
326         break;
327     /* Ignore other CCCs it's better to handle on a device-by-device basis. */
328     default:
329         break;
330     }
331     return tc->handle_ccc_write(t, data, num_to_send, num_sent);
332 }
333 
i3c_send_byte(I3CBus * bus,uint8_t data)334 int i3c_send_byte(I3CBus *bus, uint8_t data)
335 {
336     /*
337      * Ignored, the caller can determine how many were sent based on if this was
338      * ACKed/NACKed.
339      */
340     uint32_t num_sent;
341     return i3c_send(bus, &data, 1, &num_sent);
342 }
343 
i3c_send(I3CBus * bus,const uint8_t * data,uint32_t num_to_send,uint32_t * num_sent)344 int i3c_send(I3CBus *bus, const uint8_t *data, uint32_t num_to_send,
345              uint32_t *num_sent)
346 {
347     I3CTargetClass *tc;
348     I3CTarget *t;
349     I3CNode *node;
350     int ret = 0;
351 
352     /* If this message is a broadcast and no CCC has been found, grab it. */
353     if (bus->broadcast && !bus->in_ccc) {
354         bus->ccc = *data;
355         bus->in_ccc = true;
356         /*
357          * We need to keep track if we're currently in ENTDAA.
358          * On any other CCC, the CCC is over on a RESTART or STOP, but ENTDAA
359          * is only over on a STOP.
360          */
361         if (bus->ccc == I3C_CCC_ENTDAA) {
362             bus->in_entdaa = true;
363         }
364     }
365 
366     QLIST_FOREACH(node, &bus->current_devs, next) {
367         t = node->target;
368         tc = I3C_TARGET_GET_CLASS(t);
369         if (bus->in_ccc) {
370             if (!tc->handle_ccc_write) {
371                 ret = -1;
372                 continue;
373             }
374             ret = i3c_target_handle_ccc_write(t, data, num_to_send, num_sent);
375             /* Targets should only NACK on a direct CCC. */
376             if (ret && !CCC_IS_DIRECT(bus->ccc)) {
377                 ret = 0;
378             }
379         } else {
380             if (tc->send) {
381                 ret = ret || tc->send(t, data, num_to_send, num_sent);
382             } else {
383                 ret = -1;
384             }
385         }
386     }
387 
388     trace_i3c_send(*num_sent, num_to_send, ret == 0);
389 
390     return ret ? -1 : 0;
391 }
392 
i3c_target_handle_ccc_read(I3CTarget * t,uint8_t * data,uint32_t num_to_read,uint32_t * num_read)393 static int i3c_target_handle_ccc_read(I3CTarget *t, uint8_t *data,
394                                       uint32_t num_to_read, uint32_t *num_read)
395 {
396     I3CTargetClass *tc = I3C_TARGET_GET_CLASS(t);
397     uint8_t read_count = 0;
398     uint64_t pid;
399 
400     switch (t->curr_ccc) {
401     case I3C_CCC_ENTDAA:
402         if (t->in_test_mode) {
403             pid = TEST_MODE_PROVISIONED_ID;
404         } else {
405             pid = t->pid;
406         }
407         /* Return the 6-byte PID, followed by BCR then DCR. */
408         while (t->ccc_byte_offset < 6) {
409             if (read_count >= num_to_read) {
410                 break;
411             }
412             data[read_count] = (pid >> (t->ccc_byte_offset * 8)) & 0xff;
413             t->ccc_byte_offset++;
414             read_count++;
415         }
416         if (read_count < num_to_read) {
417             data[read_count] = t->bcr;
418             t->ccc_byte_offset++;
419             read_count++;
420         }
421         if (read_count < num_to_read) {
422             data[read_count] = t->dcr;
423             t->ccc_byte_offset++;
424             read_count++;
425         }
426         *num_read = read_count;
427         break;
428     case I3C_CCCD_GETPID:
429         while (t->ccc_byte_offset < 6) {
430             if (read_count >= num_to_read) {
431                 break;
432             }
433             data[read_count] = (t->pid >> (t->ccc_byte_offset * 8)) & 0xff;
434             t->ccc_byte_offset++;
435             read_count++;
436         }
437         *num_read = read_count;
438         break;
439     case I3C_CCCD_GETBCR:
440         *data = t->bcr;
441         *num_read = 1;
442         break;
443     case I3C_CCCD_GETDCR:
444         *data = t->dcr;
445         *num_read = 1;
446         break;
447     default:
448         /* Unhandled on the I3CTarget class level. */
449         break;
450     }
451 
452     return tc->handle_ccc_read(t, data, num_to_read, num_read);
453 }
454 
i3c_recv_byte(I3CBus * bus,uint8_t * data)455 int i3c_recv_byte(I3CBus *bus, uint8_t *data)
456 {
457      /*
458       * Ignored, the caller can determine how many bytes were read based on if
459       * this is ACKed/NACKed.
460       */
461     uint32_t num_read;
462     return i3c_recv(bus, data, 1, &num_read);
463 }
464 
i3c_recv(I3CBus * bus,uint8_t * data,uint32_t num_to_read,uint32_t * num_read)465 int i3c_recv(I3CBus *bus, uint8_t *data, uint32_t num_to_read,
466              uint32_t *num_read)
467 {
468     int ret = 0;
469     I3CTargetClass *tc;
470     I3CTarget *t;
471 
472     *data = 0xff;
473     if (!QLIST_EMPTY(&bus->current_devs)) {
474         tc = I3C_TARGET_GET_CLASS(QLIST_FIRST(&bus->current_devs)->target);
475         t = QLIST_FIRST(&bus->current_devs)->target;
476         if (bus->in_ccc) {
477             if (!tc->handle_ccc_read) {
478                 return -1;
479             }
480             ret = i3c_target_handle_ccc_read(t, data, num_to_read, num_read);
481         } else {
482             if (tc->recv) {
483                 /*
484                  * Targets cannot NACK on a direct transfer, so the data
485                  * is returned directly.
486                  */
487                 *num_read = tc->recv(t, data, num_to_read);
488             }
489         }
490     }
491 
492     trace_i3c_recv(*num_read, num_to_read, ret == 0);
493 
494     return ret;
495 }
496 
i3c_nack(I3CBus * bus)497 void i3c_nack(I3CBus *bus)
498 {
499     I3CTargetClass *tc;
500     I3CNode *node;
501 
502     if (QLIST_EMPTY(&bus->current_devs)) {
503         return;
504     }
505 
506     QLIST_FOREACH(node, &bus->current_devs, next) {
507         tc = I3C_TARGET_GET_CLASS(node->target);
508         if (tc->event) {
509             i3c_target_event(node->target, I3C_NACK);
510         }
511     }
512 }
513 
i3c_target_send_ibi(I3CTarget * t,uint8_t addr,bool is_recv)514 int i3c_target_send_ibi(I3CTarget *t, uint8_t addr, bool is_recv)
515 {
516     I3CBus *bus = I3C_BUS(t->qdev.parent_bus);
517     I3CBusClass *bc = I3C_BUS_GET_CLASS(bus);
518     trace_i3c_target_send_ibi(addr, is_recv);
519     return bc->ibi_handle(bus, addr, is_recv);
520 }
521 
i3c_target_send_ibi_bytes(I3CTarget * t,uint8_t data)522 int i3c_target_send_ibi_bytes(I3CTarget *t, uint8_t data)
523 {
524     I3CBus *bus = I3C_BUS(t->qdev.parent_bus);
525     I3CBusClass *bc = I3C_BUS_GET_CLASS(bus);
526     trace_i3c_target_send_ibi_bytes(data);
527     return bc->ibi_recv(bus, data);
528 }
529 
i3c_target_ibi_finish(I3CTarget * t,uint8_t data)530 int i3c_target_ibi_finish(I3CTarget *t, uint8_t data)
531 {
532     I3CBus *bus = I3C_BUS(t->qdev.parent_bus);
533     I3CBusClass *bc = I3C_BUS_GET_CLASS(bus);
534     trace_i3c_target_ibi_finish();
535     return bc->ibi_finish(bus);
536 }
537 
i3c_addr_is_rsvd(uint8_t addr)538 static bool i3c_addr_is_rsvd(uint8_t addr)
539 {
540     const bool is_rsvd[255] = {
541         [0x00] = true,
542         [0x01] = true,
543         [0x02] = true,
544         [0x3e] = true,
545         [0x5e] = true,
546         [0x6e] = true,
547         [0x76] = true,
548         [0x7a] = true,
549         [0x7c] = true,
550         [0x7e] = true,
551         [0x7f] = true,
552     };
553 
554     return is_rsvd[addr];
555 }
556 
i3c_target_new(const char * name,uint8_t addr,uint8_t dcr,uint8_t bcr,uint64_t pid)557 I3CTarget *i3c_target_new(const char *name, uint8_t addr, uint8_t dcr,
558                           uint8_t bcr, uint64_t pid)
559 {
560     DeviceState *dev;
561 
562     dev = qdev_new(name);
563     qdev_prop_set_uint8(dev, "static-address", addr);
564     qdev_prop_set_uint8(dev, "dcr", dcr);
565     qdev_prop_set_uint8(dev, "bcr", bcr);
566     qdev_prop_set_uint64(dev, "pid", pid);
567 
568     if (i3c_addr_is_rsvd(addr)) {
569         g_autofree char *path = object_get_canonical_path(OBJECT(dev));
570         qemu_log_mask(LOG_GUEST_ERROR, "%s: I3C target created with reserved "
571                       "address 0x%.2x\n", path, addr);
572     }
573     return I3C_TARGET(dev);
574 }
575 
i3c_target_realize_and_unref(I3CTarget * dev,I3CBus * bus,Error ** errp)576 bool i3c_target_realize_and_unref(I3CTarget *dev, I3CBus *bus, Error **errp)
577 {
578     return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp);
579 }
580 
i3c_target_create_simple(I3CBus * bus,const char * name,uint8_t addr,uint8_t dcr,uint8_t bcr,uint64_t pid)581 I3CTarget *i3c_target_create_simple(I3CBus *bus, const char *name, uint8_t addr,
582                                     uint8_t dcr, uint8_t bcr, uint64_t pid)
583 {
584     I3CTarget *dev = i3c_target_new(name, addr, dcr, bcr, pid);
585     dev->address = 0;
586     i3c_target_realize_and_unref(dev, bus, &error_abort);
587 
588     return dev;
589 }
590 
591 /* Legacy I2C functions. */
legacy_i2c_nack(I3CBus * bus)592 void legacy_i2c_nack(I3CBus *bus)
593 {
594     trace_legacy_i2c_nack();
595     i2c_nack(bus->i2c_bus);
596 }
597 
legacy_i2c_recv(I3CBus * bus)598 uint8_t legacy_i2c_recv(I3CBus *bus)
599 {
600     uint8_t byte = i2c_recv(bus->i2c_bus);
601     trace_legacy_i2c_recv(byte);
602     return byte;
603 }
604 
legacy_i2c_send(I3CBus * bus,uint8_t data)605 int legacy_i2c_send(I3CBus *bus, uint8_t data)
606 {
607     trace_legacy_i2c_send(data);
608     return i2c_send(bus->i2c_bus, data);
609 }
610 
legacy_i2c_start_transfer(I3CBus * bus,uint8_t address,bool is_recv)611 int legacy_i2c_start_transfer(I3CBus *bus, uint8_t address, bool is_recv)
612 {
613     trace_legacy_i2c_start_transfer(address, is_recv);
614     return i2c_start_transfer(bus->i2c_bus, address, is_recv);
615 }
616 
legacy_i2c_start_recv(I3CBus * bus,uint8_t address)617 int legacy_i2c_start_recv(I3CBus *bus, uint8_t address)
618 {
619     trace_legacy_i2c_start_transfer(address, true);
620     return i2c_start_transfer(bus->i2c_bus, address, /*is_recv=*/true);
621 }
622 
legacy_i2c_start_send(I3CBus * bus,uint8_t address)623 int legacy_i2c_start_send(I3CBus *bus, uint8_t address)
624 {
625     trace_legacy_i2c_start_transfer(address, false);
626     return i2c_start_transfer(bus->i2c_bus, address, /*is_recv=*/false);
627 }
628 
legacy_i2c_end_transfer(I3CBus * bus)629 void legacy_i2c_end_transfer(I3CBus *bus)
630 {
631     trace_legacy_i2c_end_transfer();
632     i2c_end_transfer(bus->i2c_bus);
633 }
634 
legacy_i2c_device_create_simple(I3CBus * bus,const char * name,uint8_t addr)635 I2CSlave *legacy_i2c_device_create_simple(I3CBus *bus, const char *name,
636                                           uint8_t addr)
637 {
638     I2CSlave *dev = i2c_slave_new(name, addr);
639 
640     i2c_slave_realize_and_unref(dev, bus->i2c_bus, &error_abort);
641     return dev;
642 }
643 
i3c_target_class_init(ObjectClass * klass,const void * data)644 static void i3c_target_class_init(ObjectClass *klass, const void *data)
645 {
646     DeviceClass *k = DEVICE_CLASS(klass);
647     I3CTargetClass *sc = I3C_TARGET_CLASS(klass);
648     set_bit(DEVICE_CATEGORY_MISC, k->categories);
649     k->bus_type = TYPE_I3C_BUS;
650     device_class_set_props(k, i3c_props);
651     sc->target_match = i3c_target_match;
652 }
653 
654 static const TypeInfo i3c_target_type_info = {
655     .name = TYPE_I3C_TARGET,
656     .parent = TYPE_DEVICE,
657     .instance_size = sizeof(I3CTarget),
658     .abstract = true,
659     .class_size = sizeof(I3CTargetClass),
660     .class_init = i3c_target_class_init,
661 };
662 
i3c_register_types(void)663 static void i3c_register_types(void)
664 {
665     type_register_static(&i3c_bus_info);
666     type_register_static(&i3c_target_type_info);
667 }
668 
669 type_init(i3c_register_types)
670