[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/6] aspeed/i2c: improve command handling
From: |
Cédric Le Goater |
Subject: |
[Qemu-devel] [PATCH 1/6] aspeed/i2c: improve command handling |
Date: |
Mon, 15 May 2017 07:51:11 +0200 |
Multiple I2C commands can be fired simultaneously and the controller
execute the commands following these priorities:
(1) Master Start Command
(2) Master Transmit Command
(3) Slave Transmit Command or Master Receive Command
(4) Master Stop Command
The current code is incorrect with respect to the above sequence and
needs to be reworked to handle each individual command.
Signed-off-by: Cédric Le Goater <address@hidden>
---
hw/i2c/aspeed_i2c.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index ce5b1f0fa493..56a4fdf5c542 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -171,6 +171,7 @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr
offset,
static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
{
+ bus->cmd &= ~0xFFFF;
bus->cmd |= value & 0xFFFF;
bus->intr_status = 0;
@@ -182,15 +183,27 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus,
uint64_t value)
bus->intr_status |= I2CD_INTR_TX_ACK;
}
- } else if (bus->cmd & I2CD_M_TX_CMD) {
+ /* START command is also a TX command, as the slave address is
+ * sent on the bus */
+ bus->cmd &= ~(I2CD_M_START_CMD | I2CD_M_TX_CMD);
+
+ /* No slave found */
+ if (!i2c_bus_busy(bus->bus)) {
+ return;
+ }
+ }
+
+ if (bus->cmd & I2CD_M_TX_CMD) {
if (i2c_send(bus->bus, bus->buf)) {
bus->intr_status |= (I2CD_INTR_TX_NAK | I2CD_INTR_ABNORMAL);
i2c_end_transfer(bus->bus);
} else {
bus->intr_status |= I2CD_INTR_TX_ACK;
}
+ bus->cmd &= ~I2CD_M_TX_CMD;
+ }
- } else if (bus->cmd & I2CD_M_RX_CMD) {
+ if (bus->cmd & I2CD_M_RX_CMD) {
int ret = i2c_recv(bus->bus);
if (ret < 0) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
@@ -199,6 +212,7 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus,
uint64_t value)
bus->intr_status |= I2CD_INTR_RX_DONE;
}
bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
+ bus->cmd &= ~I2CD_M_RX_CMD;
}
if (bus->cmd & (I2CD_M_STOP_CMD | I2CD_M_S_RX_CMD_LAST)) {
@@ -208,11 +222,8 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus,
uint64_t value)
i2c_end_transfer(bus->bus);
bus->intr_status |= I2CD_INTR_NORMAL_STOP;
}
+ bus->cmd &= ~I2CD_M_STOP_CMD;
}
-
- /* command is handled, reset it and check for interrupts */
- bus->cmd &= ~0xFFFF;
- aspeed_i2c_bus_raise_interrupt(bus);
}
static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
@@ -262,6 +273,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr
offset,
}
aspeed_i2c_bus_handle_cmd(bus, value);
+ aspeed_i2c_bus_raise_interrupt(bus);
break;
default:
--
2.7.4
- [Qemu-devel] [PATCH 0/6] aspeed: I2C controller fixes, Cédric Le Goater, 2017/05/15
- [Qemu-devel] [PATCH 2/6] aspeed/i2c: handle LAST command under the RX command, Cédric Le Goater, 2017/05/15
- [Qemu-devel] [PATCH 3/6] aspeed/i2c: introduce a state machine, Cédric Le Goater, 2017/05/15
- [Qemu-devel] [PATCH 1/6] aspeed/i2c: improve command handling,
Cédric Le Goater <=
- [Qemu-devel] [PATCH 4/6] aspeed: add some I2C devices to the Aspeed machines, Cédric Le Goater, 2017/05/15
- [Qemu-devel] [PATCH 5/6] hw/misc: add a TMP42{1,2,3} device model, Cédric Le Goater, 2017/05/15
- [Qemu-devel] [PATCH 6/6] aspeed: add a temp sensor device on I2C bus 3, Cédric Le Goater, 2017/05/15