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