master
h 284 lines 8.62 KB
Raw
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/core/qdev.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_class;
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 parent_obj;
136
137 uint8_t address;
138 uint8_t static_address;
139 uint8_t dcr;
140 uint8_t bcr;
141 /*
142 * Provisioned ID. Since core.c sends this LSB-first during ENTDAA
143 * via (pid >> (offset * 8)) & 0xff, targets must store it
144 * pre-reversed so that pid[47:40] goes on the wire first, as
145 * required by the I3C spec.
146 * e.g. for a device with pid 0xAABBCCDDEEFF, store 0xFFEEDDCCBBAA.
147 */
148 uint64_t pid;
149
150 /* CCC State tracking. */
151 I3CCCC curr_ccc;
152 uint8_t ccc_byte_offset;
153 bool in_ccc;
154 bool in_test_mode;
155 };
156
157 struct I3CNode {
158 I3CTarget *target;
159 QLIST_ENTRY(I3CNode) next;
160 };
161
162 typedef struct I3CNode I3CNode;
163
164 typedef QLIST_HEAD(I3CNodeList, I3CNode) I3CNodeList;
165
166 #define TYPE_I3C_BUS "i3c-bus"
167 OBJECT_DECLARE_TYPE(I3CBus, I3CBusClass, I3C_BUS)
168
169 struct I3CBus {
170 BusState parent_obj;
171
172 /* Legacy I2C. */
173 I2CBus *i2c_bus;
174
175 I3CNodeList current_devs;
176 bool broadcast;
177 uint8_t ccc;
178 bool in_ccc;
179 bool in_entdaa;
180 uint8_t saved_address;
181 };
182
183 struct I3CBusClass {
184 BusClass parent_class;
185
186 /* Handle an incoming IBI request from a target */
187 int (*ibi_handle) (I3CBus *bus, uint8_t addr, bool is_recv);
188 /* Receive data from an IBI request */
189 int (*ibi_recv) (I3CBus *bus, uint8_t data);
190 /* Do anything that needs to be done, since the IBI is finished. */
191 int (*ibi_finish) (I3CBus *bus);
192 };
193
194 I3CBus *i3c_init_bus(DeviceState *parent, const char *name);
195 I3CBus *i3c_init_bus_type(const char *type, DeviceState *parent,
196 const char *name);
197 void i3c_set_target_address(I3CTarget *dev, uint8_t address);
198 bool i3c_bus_busy(I3CBus *bus);
199
200 /*
201 * Start a transfer on an I3C bus.
202 * If is_recv is known at compile-time (i.e. a device will always be sending or
203 * will always be receiving at a certain point), prefer to use i3c_start_recv or
204 * i3c_start_send instead.
205 *
206 * Returns 0 on success, non-zero on an error.
207 */
208 int i3c_start_transfer(I3CBus *bus, uint8_t address, bool is_recv);
209
210 /*
211 * Start a receive transfer on an I3C bus.
212 *
213 * Returns 0 on success, non-zero on an error
214 */
215 int i3c_start_recv(I3CBus *bus, uint8_t address);
216
217 /*
218 * Start a send transfer on an I3C bus.
219 *
220 * Returns 0 on success, non-zero on an error
221 */
222 int i3c_start_send(I3CBus *bus, uint8_t address);
223
224 void i3c_end_transfer(I3CBus *bus);
225 void i3c_nack(I3CBus *bus);
226 int i3c_send_byte(I3CBus *bus, uint8_t data);
227 int i3c_send(I3CBus *bus, const uint8_t *data, uint32_t num_to_send,
228 uint32_t *num_sent);
229 /*
230 * I3C receives can only NACK on a CCC. The target should NACK a CCC it does not
231 * support.
232 */
233 int i3c_recv_byte(I3CBus *bus, uint8_t *data);
234 int i3c_recv(I3CBus *bus, uint8_t *data, uint32_t num_to_read,
235 uint32_t *num_read);
236 bool i3c_scan_bus(I3CBus *bus, uint8_t address, enum I3CEvent event);
237 int i3c_do_entdaa(I3CBus *bus, uint8_t address, uint64_t *pid, uint8_t *bcr,
238 uint8_t *dcr);
239 int i3c_start_device_transfer(I3CTarget *dev, int send_length);
240 bool i3c_target_match_and_add(I3CBus *bus, I3CTarget *target, uint8_t address,
241 enum I3CEvent event);
242 int i3c_target_send_ibi(I3CTarget *t, uint8_t addr, bool is_recv);
243 int i3c_target_send_ibi_bytes(I3CTarget *t, uint8_t data);
244 int i3c_target_ibi_finish(I3CTarget *t, uint8_t data);
245
246 /*
247 * Legacy I2C functions.
248 *
249 * These are wrapper for I2C functions that take in an I3C bus instead of an I2C
250 * bus. Internally they use the I2C bus (and devices attached to it) that's a
251 * part of the I3C bus
252 */
253 void legacy_i2c_nack(I3CBus *bus);
254 uint8_t legacy_i2c_recv(I3CBus *bus);
255 int legacy_i2c_send(I3CBus *bus, uint8_t data);
256 int legacy_i2c_start_transfer(I3CBus *bus, uint8_t address, bool is_recv);
257 int legacy_i2c_start_recv(I3CBus *bus, uint8_t address);
258 int legacy_i2c_start_send(I3CBus *bus, uint8_t address);
259 void legacy_i2c_end_transfer(I3CBus *bus);
260 I2CSlave *legacy_i2c_device_create_simple(I3CBus *bus, const char *name,
261 uint8_t addr);
262
263 /**
264 * Create an I3C Target.
265 *
266 * The target returned from this function still needs to be realized.
267 */
268 I3CTarget *i3c_target_new(const char *name, uint8_t addr, uint8_t dcr,
269 uint8_t bcr, uint64_t pid);
270
271 /**
272 * Create and realize an I3C target.
273 *
274 * Create the target, initialize it, put it on the specified I3C bus, and
275 * realize it.
276 */
277 I3CTarget *i3c_target_create_simple(I3CBus *bus, const char *name,
278 uint8_t addr, uint8_t dcr, uint8_t bcr,
279 uint64_t pid);
280
281 /* Realize and drop the reference count on an I3C target. */
282 bool i3c_target_realize_and_unref(I3CTarget *dev, I3CBus *bus, Error **errp);
283
284 #endif /* QEMU_INCLUDE_HW_I3C_I3C_H_ */