From: Peter Delevoryas <me@pjd.dev>
Cc: clg@kaod.org, peter.maydell@linaro.org, andrew@aj.id.au,
joel@jms.id.au, cminyard@mvista.com, titusr@google.com,
qemu-devel@nongnu.org, qemu-arm@nongnu.org, zhdaniel@fb.com,
pdel@fb.com
Subject: [PATCH v3 05/14] hw/i2c: add asynchronous send
Date: Wed, 29 Jun 2022 21:51:24 -0700 [thread overview]
Message-ID: <20220630045133.32251-6-me@pjd.dev> (raw)
In-Reply-To: <20220630045133.32251-1-me@pjd.dev>
From: Klaus Jensen <k.jensen@samsung.com>
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>
---
hw/arm/pxa2xx.c | 2 ++
hw/display/sii9022.c | 2 ++
hw/display/ssd0303.c | 2 ++
hw/i2c/core.c | 36 +++++++++++++++++++++++++++++++++++-
hw/i2c/smbus_slave.c | 4 ++++
hw/i2c/trace-events | 2 ++
hw/nvram/eeprom_at24c.c | 2 ++
hw/sensor/lsm303dlhc_mag.c | 2 ++
include/hw/i2c/i2c.h | 16 ++++++++++++++++
9 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index f4f687df68..93dda83d7a 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1305,6 +1305,8 @@ static int pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event)
case I2C_NACK:
s->status |= 1 << 1; /* set ACKNAK */
break;
+ default:
+ return -1;
}
pxa2xx_i2c_update(s);
diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
index b591a58789..664fd4046d 100644
--- a/hw/display/sii9022.c
+++ b/hw/display/sii9022.c
@@ -76,6 +76,8 @@ static int sii9022_event(I2CSlave *i2c, enum i2c_event event)
break;
case I2C_NACK:
break;
+ default:
+ return -1;
}
return 0;
diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
index aeae22da9c..d67b0ad7b5 100644
--- a/hw/display/ssd0303.c
+++ b/hw/display/ssd0303.c
@@ -196,6 +196,8 @@ static int ssd0303_event(I2CSlave *i2c, enum i2c_event event)
case I2C_NACK:
/* Nothing to do. */
break;
+ default:
+ return -1;
}
return 0;
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 145dce6078..d4ba8146bf 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -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;
diff --git a/hw/i2c/smbus_slave.c b/hw/i2c/smbus_slave.c
index 5d10e27664..feb3ec6333 100644
--- a/hw/i2c/smbus_slave.c
+++ b/hw/i2c/smbus_slave.c
@@ -143,6 +143,10 @@ static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
dev->mode = SMBUS_CONFUSED;
break;
}
+ break;
+
+ default:
+ return -1;
}
return 0;
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
index 209275ed2d..af181d43ee 100644
--- a/hw/i2c/trace-events
+++ b/hw/i2c/trace-events
@@ -4,7 +4,9 @@
i2c_event(const char *event, uint8_t address) "%s(addr:0x%02x)"
i2c_send(uint8_t address, uint8_t data) "send(addr:0x%02x) data:0x%02x"
+i2c_send_async(uint8_t address, uint8_t data) "send_async(addr:0x%02x) data:0x%02x"
i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
+i2c_ack(void) ""
# aspeed_i2c.c
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
index 01a3093600..d695f6ae89 100644
--- a/hw/nvram/eeprom_at24c.c
+++ b/hw/nvram/eeprom_at24c.c
@@ -75,6 +75,8 @@ int at24c_eeprom_event(I2CSlave *s, enum i2c_event event)
break;
case I2C_NACK:
break;
+ default:
+ return -1;
}
return 0;
}
diff --git a/hw/sensor/lsm303dlhc_mag.c b/hw/sensor/lsm303dlhc_mag.c
index 4c98ddbf20..bb8d48b2fd 100644
--- a/hw/sensor/lsm303dlhc_mag.c
+++ b/hw/sensor/lsm303dlhc_mag.c
@@ -427,6 +427,8 @@ static int lsm303dlhc_mag_event(I2CSlave *i2c, enum i2c_event event)
break;
case I2C_NACK:
break;
+ default:
+ return -1;
}
s->len = 0;
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index be8bb8b78a..9b9581d230 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -12,6 +12,7 @@
enum i2c_event {
I2C_START_RECV,
I2C_START_SEND,
+ I2C_START_SEND_ASYNC,
I2C_FINISH,
I2C_NACK /* Masker NACKed a receive byte. */
};
@@ -28,6 +29,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 (asynchronous). Receiving slave must call i2c_ack(). */
+ void (*send_async)(I2CSlave *s, uint8_t data);
+
/*
* Slave to master. This cannot fail, the device should always
* return something here.
@@ -127,11 +131,23 @@ int i2c_start_recv(I2CBus *bus, uint8_t address);
*/
int i2c_start_send(I2CBus *bus, uint8_t address);
+/**
+ * i2c_start_send_async: start an asynchronous 'send' transfer on an I2C bus.
+ *
+ * @bus: #I2CBus to be used
+ * @address: address of the slave
+ *
+ * Return: 0 on success, -1 on error
+ */
+int i2c_start_send_async(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);
--
2.37.0
next prev parent reply other threads:[~2022-06-30 4:54 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-30 4:51 [PATCH v3 00/14] hw/i2c/aspeed: I2C slave mode DMA RX w/ new regs Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 01/14] hw/i2c/aspeed: Fix R_I2CD_FUN_CTRL reference Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 02/14] hw/i2c/aspeed: Fix DMA len write-enable bit handling Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 03/14] hw/i2c/aspeed: Fix MASTER_EN missing error message Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 04/14] hw/i2c: support multiple masters Peter Delevoryas
2022-06-30 4:51 ` Peter Delevoryas [this message]
2022-06-30 4:51 ` [PATCH v3 06/14] hw/i2c/aspeed: add slave device in old register mode Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 07/14] hw/i2c/aspeed: Add new-registers DMA slave mode RX support Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 08/14] hw/i2c/pmbus: Add idle state to return 0xff's Peter Delevoryas
2022-06-30 19:18 ` Titus Rwantare
2022-06-30 4:51 ` [PATCH v3 09/14] hw/sensor: Add IC_DEVICE_ID to ISL voltage regulators Peter Delevoryas
2022-06-30 19:20 ` Titus Rwantare
2022-06-30 4:51 ` [PATCH v3 10/14] hw/sensor: Add Renesas ISL69259 device model Peter Delevoryas
2022-06-30 6:30 ` Cédric Le Goater
2022-06-30 19:16 ` Titus Rwantare
2022-07-01 5:35 ` Cédric Le Goater
2022-06-30 19:16 ` Titus Rwantare
2022-06-30 21:14 ` Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 11/14] hw/misc/aspeed: Add PECI controller Peter Delevoryas
2022-06-30 6:32 ` Cédric Le Goater
2022-06-30 4:51 ` [PATCH v3 12/14] hw/misc/aspeed: Add fby35-sb-cpld Peter Delevoryas
2022-06-30 6:47 ` Cédric Le Goater
2022-06-30 4:51 ` [PATCH v3 13/14] hw/misc/aspeed: Add intel-me Peter Delevoryas
2022-06-30 11:09 ` Cédric Le Goater
2022-06-30 16:20 ` Peter Delevoryas
2022-06-30 4:51 ` [PATCH v3 14/14] hw/arm/aspeed: Add oby35-cl machine Peter Delevoryas
2022-06-30 11:02 ` Cédric Le Goater
2022-06-30 16:15 ` Peter Delevoryas
2022-06-30 16:42 ` Cédric Le Goater
2022-06-30 17:48 ` Peter Delevoryas
2022-06-30 23:06 ` Peter Delevoryas
2022-07-01 5:39 ` Cédric Le Goater
2022-06-30 6:13 ` [PATCH v3 00/14] hw/i2c/aspeed: I2C slave mode DMA RX w/ new regs Cédric Le Goater
2022-06-30 7:50 ` Cédric Le Goater
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220630045133.32251-6-me@pjd.dev \
--to=me@pjd.dev \
--cc=andrew@aj.id.au \
--cc=clg@kaod.org \
--cc=cminyard@mvista.com \
--cc=joel@jms.id.au \
--cc=pdel@fb.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=titusr@google.com \
--cc=zhdaniel@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).