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