diff mbox series

[RFC,2/4] hw/i2c: add async send

Message ID 20220331165737.1073520-3-its@irrelevant.dk (mailing list archive)
State New, archived
Headers show
Series hw/i2c: i2c slave mode support | expand

Commit Message

Klaus Jensen March 31, 2022, 4:57 p.m. UTC
From: Klaus Jensen <k.jensen@samsung.com>

Add an asynchronous version of of i2c_send that requires an explicit
acknowledgement on the bus.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
 hw/i2c/core.c        | 23 +++++++++++++++++++++++
 include/hw/i2c/i2c.h |  5 +++++
 2 files changed, 28 insertions(+)
diff mbox series

Patch

diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 145dce60782a..344d764d7eaa 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -261,6 +261,20 @@  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) {
+        sc->send_async(slave, data);
+        return 0;
+    }
+
+    return -1;
+}
+
 uint8_t i2c_recv(I2CBus *bus)
 {
     uint8_t data = 0xff;
@@ -297,6 +311,15 @@  void i2c_nack(I2CBus *bus)
     }
 }
 
+void i2c_ack(I2CBus *bus)
+{
+    if (!bus->bh) {
+        return;
+    }
+
+    qemu_bh_schedule(bus->bh);
+}
+
 static int i2c_slave_post_load(void *opaque, int version_id)
 {
     I2CSlave *dev = opaque;
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index be8bb8b78a60..ae58e4151585 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -28,6 +28,9 @@  struct I2CSlaveClass {
     /* Master to slave. Returns non-zero for a NAK, 0 for success. */
     int (*send)(I2CSlave *s, uint8_t data);
 
+    /* Master to slave. */
+    void (*send_async)(I2CSlave *s, uint8_t data);
+
     /*
      * Slave to master.  This cannot fail, the device should always
      * return something here.
@@ -129,9 +132,11 @@  int i2c_start_send(I2CBus *bus, uint8_t address);
 
 void i2c_end_transfer(I2CBus *bus);
 void i2c_nack(I2CBus *bus);
+void i2c_ack(I2CBus *bus);
 void i2c_bus_master(I2CBus *bus, QEMUBH *bh);
 void i2c_bus_release(I2CBus *bus);
 int i2c_send(I2CBus *bus, uint8_t data);
+int i2c_send_async(I2CBus *bus, uint8_t data);
 uint8_t i2c_recv(I2CBus *bus);
 bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast,
                   I2CNodeList *current_devs);