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