xref: /openbmc/qemu/include/hw/i3c/i3c.h (revision 324ad9ab7071ffabc882a4f80195da6da3944e91)
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 #ifndef QEMU_INCLUDE_HW_I3C_I3C_H_
10 #define QEMU_INCLUDE_HW_I3C_I3C_H_
11 
12 #include "hw/qdev-core.h"
13 #include "qom/object.h"
14 #include "hw/i2c/i2c.h"
15 
16 #define TYPE_I3C_TARGET "i3c-target"
17 OBJECT_DECLARE_TYPE(I3CTarget, I3CTargetClass, I3C_TARGET)
18 
19 typedef enum I3CEvent {
20     I3C_START_RECV,
21     I3C_START_SEND,
22     I3C_STOP,
23     I3C_NACK,
24 } I3CEvent;
25 
26 typedef enum I3CCCC {
27     /* Broadcast CCCs */
28     I3C_CCC_ENEC      = 0x00,
29     I3C_CCC_DISEC     = 0x01,
30     I3C_CCC_ENTAS0    = 0x02,
31     I3C_CCC_ENTAS1    = 0x03,
32     I3C_CCC_ENTAS2    = 0x04,
33     I3C_CCC_ENTAS3    = 0x05,
34     I3C_CCC_RSTDAA    = 0x06,
35     I3C_CCC_ENTDAA    = 0x07,
36     I3C_CCC_DEFTGTS   = 0x08,
37     I3C_CCC_SETMWL    = 0x09,
38     I3C_CCC_SETMRL    = 0x0a,
39     I3C_CCC_ENTTM     = 0x0b,
40     I3C_CCC_SETBUSCON = 0x0c,
41     I3C_CCC_ENDXFER   = 0x12,
42     I3C_CCC_ENTHDR0   = 0x20,
43     I3C_CCC_ENTHDR1   = 0x21,
44     I3C_CCC_ENTHDR2   = 0x22,
45     I3C_CCC_ENTHDR3   = 0x23,
46     I3C_CCC_ENTHDR4   = 0x24,
47     I3C_CCC_ENTHDR5   = 0x25,
48     I3C_CCC_ENTHDR6   = 0x26,
49     I3C_CCC_ENTHDR7   = 0x27,
50     I3C_CCC_SETXTIME  = 0x28,
51     I3C_CCC_SETAASA   = 0x29,
52     I3C_CCC_RSTACT    = 0x2a,
53     I3C_CCC_DEFGRPA   = 0x2b,
54     I3C_CCC_RSTGRPA   = 0x2c,
55     I3C_CCC_MLANE     = 0x2d,
56     /* Direct CCCs */
57     I3C_CCCD_ENEC       = 0x80,
58     I3C_CCCD_DISEC      = 0x81,
59     I3C_CCCD_ENTAS0     = 0x82,
60     I3C_CCCD_ENTAS1     = 0x83,
61     I3C_CCCD_ENTAS2     = 0x84,
62     I3C_CCCD_ENTAS3     = 0x85,
63     I3C_CCCD_SETDASA    = 0x87,
64     I3C_CCCD_SETNEWDA   = 0x88,
65     I3C_CCCD_SETMWL     = 0x89,
66     I3C_CCCD_SETMRL     = 0x8a,
67     I3C_CCCD_GETMWL     = 0x8b,
68     I3C_CCCD_GETMRL     = 0x8c,
69     I3C_CCCD_GETPID     = 0x8d,
70     I3C_CCCD_GETBCR     = 0x8e,
71     I3C_CCCD_GETDCR     = 0x8f,
72     I3C_CCCD_GETSTATUS  = 0x90,
73     I3C_CCCD_GETACCCR   = 0x91,
74     I3C_CCCD_ENDXFER    = 0x92,
75     I3C_CCCD_SETBRGTGT  = 0x93,
76     I3C_CCCD_GETMXDS    = 0x94,
77     I3C_CCCD_GETCAPS    = 0x95,
78     I3C_CCCD_SETROUTE   = 0x96,
79     I3C_CCCD_SETXTIME   = 0x98,
80     I3C_CCCD_GETXTIME   = 0x99,
81     I3C_CCCD_RSTACT     = 0x9a,
82     I3C_CCCD_SETGRPA    = 0x9b,
83     I3C_CCCD_RSTGRPA    = 0x9c,
84     I3C_CCCD_MLANE      = 0x9d,
85 } I3CCCC;
86 
87 #define CCC_IS_DIRECT(_ccc) (_ccc & 0x80)
88 
89 #define I3C_BROADCAST 0x7e
90 #define I3C_HJ_ADDR 0x02
91 #define I3C_ENTDAA_SIZE 8
92 
93 struct I3CTargetClass {
94     DeviceClass parent;
95 
96     /*
97      * Controller to target. Returns 0 for success, non-zero for NAK or other
98      * error.
99      */
100     int (*send)(I3CTarget *s, const uint8_t *data, uint32_t num_to_send,
101                 uint32_t *num_sent);
102     /*
103      * Target to controller. I3C targets are able to terminate reads early, so
104      * this returns the number of bytes read from the target.
105      */
106     uint32_t (*recv)(I3CTarget *s, uint8_t *data, uint32_t num_to_read);
107     /* Notify the target of a bus state change. */
108     int (*event)(I3CTarget *s, enum I3CEvent event);
109     /*
110      * Handle a read CCC transmitted from a controller.
111      * CCCs are I3C commands that I3C targets support.
112      * The target can NACK the CCC if it does not support it.
113      */
114     int (*handle_ccc_read)(I3CTarget *s, uint8_t *data, uint32_t num_to_read,
115                            uint32_t *num_read);
116     /*
117      * Handle a write CCC transmitted from a controller.
118      * CCCs are I3C commands that I3C targets support.
119      * The target can NACK the CCC if it does not support it.
120      */
121     int (*handle_ccc_write)(I3CTarget *s, const uint8_t *data,
122                             uint32_t num_to_send, uint32_t *num_sent);
123 
124     /*
125      * Matches and adds the candidate if the address matches the candidate's
126      * address.
127      * Returns true if the address matched, or if this was a broadcast, and
128      * updates the device list. Otherwise returns false.
129      */
130     bool (*target_match)(I3CTarget *candidate, uint8_t address, bool is_read,
131                          bool broadcast, bool in_entdaa);
132 };
133 
134 struct I3CTarget {
135     DeviceState qdev;
136 
137     uint8_t address;
138     uint8_t static_address;
139     uint8_t dcr;
140     uint8_t bcr;
141     uint64_t pid;
142 
143     /* CCC State tracking. */
144     I3CCCC curr_ccc;
145     uint8_t ccc_byte_offset;
146     bool in_ccc;
147     bool in_test_mode;
148 };
149 
150 struct I3CNode {
151     I3CTarget *target;
152     QLIST_ENTRY(I3CNode) next;
153 };
154 
155 typedef struct I3CNode I3CNode;
156 
157 typedef QLIST_HEAD(I3CNodeList, I3CNode) I3CNodeList;
158 
159 #define TYPE_I3C_BUS "i3c-bus"
160 OBJECT_DECLARE_TYPE(I3CBus, I3CBusClass, I3C_BUS)
161 
162 struct I3CBus {
163     BusState qbus;
164 
165     /* Legacy I2C. */
166     I2CBus *i2c_bus;
167 
168     I3CNodeList current_devs;
169     bool broadcast;
170     uint8_t ccc;
171     bool in_ccc;
172     bool in_entdaa;
173     uint8_t saved_address;
174 };
175 
176 struct I3CBusClass {
177     DeviceClass parent;
178 
179     /* Handle an incoming IBI request from a target */
180     int (*ibi_handle) (I3CBus *bus, uint8_t addr, bool is_recv);
181     /* Receive data from an IBI request */
182     int (*ibi_recv) (I3CBus *bus, uint8_t data);
183     /* Do anything that needs to be done, since the IBI is finished. */
184     int (*ibi_finish) (I3CBus *bus);
185 };
186 
187 I3CBus *i3c_init_bus(DeviceState *parent, const char *name);
188 I3CBus *i3c_init_bus_type(const char *type, DeviceState *parent,
189                           const char *name);
190 void i3c_set_target_address(I3CTarget *dev, uint8_t address);
191 bool i3c_bus_busy(I3CBus *bus);
192 
193 /*
194  * Start a transfer on an I3C bus.
195  * If is_recv is known at compile-time (i.e. a device will always be sending or
196  * will always be receiving at a certain point), prefer to use i3c_start_recv or
197  * i3c_start_send instead.
198  *
199  * Returns 0 on success, non-zero on an error.
200  */
201 int i3c_start_transfer(I3CBus *bus, uint8_t address, bool is_recv);
202 
203 /*
204  * Start a receive transfer on an I3C bus.
205  *
206  * Returns 0 on success, non-zero on an error
207  */
208 int i3c_start_recv(I3CBus *bus, uint8_t address);
209 
210 /*
211  * Start a send transfer on an I3C bus.
212  *
213  * Returns 0 on success, non-zero on an error
214  */
215 int i3c_start_send(I3CBus *bus, uint8_t address);
216 
217 void i3c_end_transfer(I3CBus *bus);
218 void i3c_nack(I3CBus *bus);
219 int i3c_send_byte(I3CBus *bus, uint8_t data);
220 int i3c_send(I3CBus *bus, const uint8_t *data, uint32_t num_to_send,
221              uint32_t *num_sent);
222 /*
223  * I3C receives can only NACK on a CCC. The target should NACK a CCC it does not
224  * support.
225  */
226 int i3c_recv_byte(I3CBus *bus, uint8_t *data);
227 int i3c_recv(I3CBus *bus, uint8_t *data, uint32_t num_to_read,
228              uint32_t *num_read);
229 bool i3c_scan_bus(I3CBus *bus, uint8_t address, enum I3CEvent event);
230 int i3c_do_entdaa(I3CBus *bus, uint8_t address, uint64_t *pid, uint8_t *bcr,
231                   uint8_t *dcr);
232 int i3c_start_device_transfer(I3CTarget *dev, int send_length);
233 bool i3c_target_match_and_add(I3CBus *bus, I3CTarget *target, uint8_t address,
234                              enum I3CEvent event);
235 int i3c_target_send_ibi(I3CTarget *t, uint8_t addr, bool is_recv);
236 int i3c_target_send_ibi_bytes(I3CTarget *t, uint8_t data);
237 int i3c_target_ibi_finish(I3CTarget *t, uint8_t data);
238 
239 /*
240  * Legacy I2C functions.
241  *
242  * These are wrapper for I2C functions that take in an I3C bus instead of an I2C
243  * bus. Internally they use the I2C bus (and devices attached to it) that's a
244  * part of the I3C bus
245  */
246 void legacy_i2c_nack(I3CBus *bus);
247 uint8_t legacy_i2c_recv(I3CBus *bus);
248 int legacy_i2c_send(I3CBus *bus, uint8_t data);
249 int legacy_i2c_start_transfer(I3CBus *bus, uint8_t address, bool is_recv);
250 int legacy_i2c_start_recv(I3CBus *bus, uint8_t address);
251 int legacy_i2c_start_send(I3CBus *bus, uint8_t address);
252 void legacy_i2c_end_transfer(I3CBus *bus);
253 I2CSlave *legacy_i2c_device_create_simple(I3CBus *bus, const char *name,
254                                           uint8_t addr);
255 
256 /**
257  * Create an I3C Target.
258  *
259  * The target returned from this function still needs to be realized.
260  */
261 I3CTarget *i3c_target_new(const char *name, uint8_t addr, uint8_t dcr,
262                           uint8_t bcr, uint64_t pid);
263 
264 /**
265  * Create and realize an I3C target.
266  *
267  * Create the target, initialize it, put it on the specified I3C bus, and
268  * realize it.
269  */
270 I3CTarget *i3c_target_create_simple(I3CBus *bus, const char *name,
271                                     uint8_t addr, uint8_t dcr, uint8_t bcr,
272                                     uint64_t pid);
273 
274 /* Realize and drop the reference count on an I3C target. */
275 bool i3c_target_realize_and_unref(I3CTarget *dev, I3CBus *bus, Error **errp);
276 
277 #endif  /* QEMU_INCLUDE_HW_I3C_I3C_H_ */
278