typedef enum { I3C_ack = 0, I3C_noack } i3c_ack_t; SIM_INTERFACE(i3c_master) { void (*acknowledge)(conf_object_t *obj, i3c_ack_t ack); void (*read_response)(conf_object_t *obj, uint8 value, bool more); void (*daa_response)(conf_object_t *obj, uint64 id, uint8 bcr, uint8 dcr); void (*ibi_request)(conf_object_t *obj); void (*ibi_address)(conf_object_t *obj, uint8 address); }; #define I3C_MASTER_INTERFACE "i3c_master"
The interfaces i3c_master
i3c_slave
and i3c_daa_snoop
are used together to model
communication over an I3C bus.
There are four kinds of devices roles on the I3C bus: Main Master,
Secondary Master, Slave and Legacy I2C Slave. Exactly one device
must be the Main Master; this is typically configured statically.
Main Master should implement the i3c_master
interface,
while slave should implement the i3c_slave
interface.
Secondary Master should implement both.
Most calls to a method in the slave device interfaces expect a response
call to a method in the master device interfaces. One exception is the
method sdr_write in the i3c_slave interface, master
expects no response when calling it.
It is up to each device to find the caller's interfaces; usually it is
configured with attributes in both the master and slave device.
Two I3C devices can communicate directly if one implements the
i3c_master
interface and the other one implements the
i3c_slave
interface. An I3C bus with multiple masters
or slaves is typically modelled using an i3c-link object,
where each device is connected to an endpoint object.
An I3C bus consists of a number of master devices and a number of slave devices. Each I3C slave device listens to one or more 7-bit addresses. The slave devices can be I3C slave devices or Legacy I2C slave devices. This is because I3C protocol is compatible with I2C protocol, so that I3C master device can communicate with I2C slave devices. For legacy I2C slave device, the address it listens to is pre-configured by the device, i.e. static address. For I3C slave device, the address it listens to can be either static address or dynamic address. The dynamic address is assigned by master during Dynamic Address Assignment process. It is an error to connect two slave devices to the same bus if they listen to the same address. In a communication, the Current Master refers to the device who now drives the bus. It can be Main Master, or Secondary Master. Usually, communication over the bus is initiated by the Current Master, which can communicate with one or more slave devices at a time. A slave device can request to initiate an communication, i.e., issue an ibi_request, in three cases: Hot-Join, In-Band Interrupt and as a Secondary Master other than the Current Master requesting to become Current Master. Only one device on a bus can communicate at a time.
The start method starts a transfer. The address parameter is the address header combined with read/write bit encoded as an 8-bit number. The least significant bit is the read/write bit and the other bits is the 7-bit address header. If the start method is called from master, the address header can be address pattern 0x7E for broadcast, or specific slave address (either I2C slave static address or I3C slave dynamic address).
In I3C bus or link implementation, every start request will broadcast to all other devices. So does the stop request. This will monitor bus/link status to all devices.
Normally, master starts a transfer, then the slave responds to
start using the acknowledge method (implemented by
master side interface). The ack parameter may be
I3C_ack
or I3C_noack
if the start is acked or
noacked, respectively.
There are five types of different start requests:
Multiple I3C slave devices may acknowledge the start request. The master will conceive a request as being acknowledged if it was acknowledged by at least one of the slaves. Note that there will be a single acknowledge call in the master; the link or bus handles aggregation of acks.
Master sends the I3C Commands (Common Command Code, CCC) using sdr_write method after receiving ACK, showing to communicate with either all Slaves (Broadcast CCCs) or specific individual Slaves (Direct CCCs). This operation expects no response, and master will proceed.
If Broadcast CCC sent previously, master calls sdr_write method to transfer data to all slaves who acked the initial access.
After sending a number of reads or a number of writes, the master may choose to either call the stop method to issue a stop condition which terminates the transfer, or to call the start method again to issue a repeated start condition. The repeated start condition works like a normal start condition.
The start method and read method in the slave interfaces are allowed to respond synchronously; i.e., the acknowledge or read method may be called before the corresponding method in the slave interfaces has returned. A master that needs to connect directly to a slave device needs to take this into consideration; however, when communicating via an i3c-link object, the link guarantees that all responses are asynchronous.
The method daa_read and method daa_response are used in Dynamic Address Assignment process. Method daa_read is called from master to signal a daa read request. Method daa_response is called from slave to send slave specific 8-bytes data (48-bit Unique ID, BCR, DCR) to master. The parameter id, bcr and dcr in method daa_response represent the slave specific daa data. If multiple slaves response daa data, the slave with the lowest data wins and it will get the assigned address this time. Master calls method write in slave interfaces to send assigned dynamic address to the slave who wins. This operation expects a response call to method acknowledge in master side. Parameter data in method write stores the assigned address.
Master should implement the method stop in the interface
i3c_slave
in case there is secondary master in the
configuration which may issue start request.
Slave can request to start a communication through ibi_request. The request is sent to Current Master which drives the bus now. If the master chooses to continue the slave request, ibi_start is called, this ibi start will broadcast to all devices in the configuration. Then slave can send its address header with ibi_address argument address. The address header can be 0x02 for Hot-Join, or the address of the slave itself for IBI and secondary master with read/write bit 1 and 0 respectively. If more than one slave issues ibi_address, arbitration occurs, the slave with lowest address header wins and the winning address will be delivered to master by link or bus. At that time, master issues ibi_acknowledge to the slave who wins. Other slaves which do not receive ibi_acknowledge will consume it lost arbitration already.