xref: /openbmc/qemu/include/hw/i3c/i3c.h (revision c2339f050b8230402628bf0a66f7c6b408653f86)
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