mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
hw/i2c: add asynchronous send
Add an asynchronous version of i2c_send() that requires the slave to explicitly acknowledge on the bus with i2c_ack(). The current master must use the new i2c_start_send_async() to indicate that it wants to do an asynchronous transfer. This allows the i2c core to check if the target slave supports this or not. This approach relies on adding a new enum i2c_event member, which is why a bunch of other devices needs changes in their event handling switches. Signed-off-by: Klaus Jensen <k.jensen@samsung.com> Message-Id: <20220601210831.67259-5-its@irrelevant.dk> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220630045133.32251-6-me@pjd.dev> Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
parent
37fa5ca426
commit
a78e9839ae
9 changed files with 67 additions and 1 deletions
|
@ -161,7 +161,8 @@ static int i2c_do_start_transfer(I2CBus *bus, uint8_t address,
|
|||
start condition. */
|
||||
|
||||
if (sc->event) {
|
||||
trace_i2c_event("start", s->address);
|
||||
trace_i2c_event(event == I2C_START_SEND ? "start" : "start_async",
|
||||
s->address);
|
||||
rv = sc->event(s, event);
|
||||
if (rv && !bus->broadcast) {
|
||||
if (bus_scanned) {
|
||||
|
@ -212,6 +213,11 @@ int i2c_start_send(I2CBus *bus, uint8_t address)
|
|||
return i2c_do_start_transfer(bus, address, I2C_START_SEND);
|
||||
}
|
||||
|
||||
int i2c_start_send_async(I2CBus *bus, uint8_t address)
|
||||
{
|
||||
return i2c_do_start_transfer(bus, address, I2C_START_SEND_ASYNC);
|
||||
}
|
||||
|
||||
void i2c_end_transfer(I2CBus *bus)
|
||||
{
|
||||
I2CSlaveClass *sc;
|
||||
|
@ -261,6 +267,23 @@ int i2c_send(I2CBus *bus, uint8_t data)
|
|||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
int i2c_send_async(I2CBus *bus, uint8_t data)
|
||||
{
|
||||
I2CNode *node = QLIST_FIRST(&bus->current_devs);
|
||||
I2CSlave *slave = node->elt;
|
||||
I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(slave);
|
||||
|
||||
if (!sc->send_async) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
trace_i2c_send_async(slave->address, data);
|
||||
|
||||
sc->send_async(slave, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t i2c_recv(I2CBus *bus)
|
||||
{
|
||||
uint8_t data = 0xff;
|
||||
|
@ -297,6 +320,17 @@ void i2c_nack(I2CBus *bus)
|
|||
}
|
||||
}
|
||||
|
||||
void i2c_ack(I2CBus *bus)
|
||||
{
|
||||
if (!bus->bh) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_i2c_ack();
|
||||
|
||||
qemu_bh_schedule(bus->bh);
|
||||
}
|
||||
|
||||
static int i2c_slave_post_load(void *opaque, int version_id)
|
||||
{
|
||||
I2CSlave *dev = opaque;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue