Skip to content

Commit

Permalink
aspeed/i2c: Fix receive done interrupt handling
Browse files Browse the repository at this point in the history
The AST2500 datasheet says:

I2CD10 Interrupt Status Register
       bit 2 Receive Done Interrupt status
             S/W needs to clear this status bit to allow next data receiving

The Rx interrupt done interrupt status bit needs to be cleared
explicitly before the next byte can be received, and must therefore
not be auto-cleared. Also, receiving the next byte must be delayed
until the bit has been cleared.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180914063506.20815-4-clg@kaod.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
groeck authored and pm215 committed Sep 25, 2018
1 parent 7bd9c60 commit bb626e5
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion hw/i2c/aspeed_i2c.c
Expand Up @@ -252,7 +252,8 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
aspeed_i2c_set_state(bus, I2CD_MACTIVE);
}

if (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) {
if ((bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) &&
!(bus->intr_status & I2CD_INTR_RX_DONE)) {
aspeed_i2c_handle_rx_cmd(bus);
}

Expand All @@ -274,6 +275,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
AspeedI2CBus *bus = opaque;
bool handle_rx;

switch (offset) {
case I2CD_FUN_CTRL_REG:
Expand All @@ -294,11 +296,17 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
bus->intr_ctrl = value & 0x7FFF;
break;
case I2CD_INTR_STS_REG:
handle_rx = (bus->intr_status & I2CD_INTR_RX_DONE) &&
(value & I2CD_INTR_RX_DONE);
bus->intr_status &= ~(value & 0x7FFF);
if (!bus->intr_status) {
bus->controller->intr_status &= ~(1 << bus->id);
qemu_irq_lower(bus->controller->irq);
}
if (handle_rx && (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST))) {
aspeed_i2c_handle_rx_cmd(bus);
aspeed_i2c_bus_raise_interrupt(bus);
}
break;
case I2CD_DEV_ADDR_REG:
qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
Expand Down

0 comments on commit bb626e5

Please sign in to comment.