From patchwork Mon May 15 05:51:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 762227 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wR8qv265Gz9s7w for ; Mon, 15 May 2017 15:52:43 +1000 (AEST) Received: from localhost ([::1]:34904 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dA8vw-0008JL-VU for incoming@patchwork.ozlabs.org; Mon, 15 May 2017 01:52:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55290) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dA8uy-0007zJ-50 for qemu-devel@nongnu.org; Mon, 15 May 2017 01:51:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dA8ut-0001Bj-HZ for qemu-devel@nongnu.org; Mon, 15 May 2017 01:51:40 -0400 Received: from 11.mo4.mail-out.ovh.net ([46.105.34.195]:48955) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dA8ut-00019O-B9 for qemu-devel@nongnu.org; Mon, 15 May 2017 01:51:35 -0400 Received: from player772.ha.ovh.net (b6.ovh.net [213.186.33.56]) by mo4.mail-out.ovh.net (Postfix) with ESMTP id C25756408E for ; Mon, 15 May 2017 07:51:26 +0200 (CEST) Received: from zorba.kaod.org (LFbn-1-10647-27.w90-89.abo.wanadoo.fr [90.89.233.27]) (Authenticated sender: clg@kaod.org) by player772.ha.ovh.net (Postfix) with ESMTPSA id A441474006B; Mon, 15 May 2017 07:51:22 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: Peter Maydell Date: Mon, 15 May 2017 07:51:11 +0200 Message-Id: <1494827476-1487-2-git-send-email-clg@kaod.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1494827476-1487-1-git-send-email-clg@kaod.org> References: <1494827476-1487-1-git-send-email-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 4746231059408194321 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeeljedruddvgddutdeiucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.34.195 Subject: [Qemu-devel] [PATCH 1/6] aspeed/i2c: improve command handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 --- 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: