Commit 7bd9c60d authored by Guenter Roeck's avatar Guenter Roeck Committed by Peter Maydell
Browse files

aspeed/i2c: Handle receive command in separate function



Receive command handling may have to be deferred if a previous receive
done interrupt was not yet acknowledged. Move receive command handling
into a separate function to prepare for the necessary changes.

Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarCédric Le Goater <clg@kaod.org>
Message-id: 20180914063506.20815-3-clg@kaod.org
Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 5540cb97
Loading
Loading
Loading
Loading
+21 −16
Original line number Diff line number Diff line
@@ -187,6 +187,26 @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus)
    return (bus->cmd >> I2CD_TX_STATE_SHIFT) & I2CD_TX_STATE_MASK;
}

static void aspeed_i2c_handle_rx_cmd(AspeedI2CBus *bus)
{
    int ret;

    aspeed_i2c_set_state(bus, I2CD_MRXD);
    ret = i2c_recv(bus->bus);
    if (ret < 0) {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
        ret = 0xff;
    } else {
        bus->intr_status |= I2CD_INTR_RX_DONE;
    }
    bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
    if (bus->cmd & I2CD_M_S_RX_CMD_LAST) {
        i2c_nack(bus->bus);
    }
    bus->cmd &= ~(I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST);
    aspeed_i2c_set_state(bus, I2CD_MACTIVE);
}

/*
 * The state machine needs some refinement. It is only used to track
 * invalid STOP commands for the moment.
@@ -233,22 +253,7 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
    }

    if (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) {
        int ret;

        aspeed_i2c_set_state(bus, I2CD_MRXD);
        ret = i2c_recv(bus->bus);
        if (ret < 0) {
            qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
            ret = 0xff;
        } else {
            bus->intr_status |= I2CD_INTR_RX_DONE;
        }
        bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
        if (bus->cmd & I2CD_M_S_RX_CMD_LAST) {
            i2c_nack(bus->bus);
        }
        bus->cmd &= ~(I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST);
        aspeed_i2c_set_state(bus, I2CD_MACTIVE);
        aspeed_i2c_handle_rx_cmd(bus);
    }

    if (bus->cmd & I2CD_M_STOP_CMD) {