From patchwork Mon Dec 30 15:15:31 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Herv=C3=A9_Poussineau?= X-Patchwork-Id: 305784 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 45A992C00E2 for ; Tue, 31 Dec 2013 02:15:16 +1100 (EST) Received: from localhost ([::1]:58632 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VxeYj-0007wT-5v for incoming@patchwork.ozlabs.org; Mon, 30 Dec 2013 10:15:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42157) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VxeYO-0007w4-Ok for qemu-devel@nongnu.org; Mon, 30 Dec 2013 10:14:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VxeYJ-00068P-50 for qemu-devel@nongnu.org; Mon, 30 Dec 2013 10:14:52 -0500 Received: from smtp4-g21.free.fr ([2a01:e0c:1:1599::13]:42328) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VxeYI-000669-FA for qemu-devel@nongnu.org; Mon, 30 Dec 2013 10:14:47 -0500 Received: from localhost.localdomain (unknown [82.227.227.196]) by smtp4-g21.free.fr (Postfix) with ESMTP id CCC694C8042; Mon, 30 Dec 2013 16:14:32 +0100 (CET) From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= To: qemu-devel@nongnu.org Date: Mon, 30 Dec 2013 16:15:31 +0100 Message-Id: <1388416531-30504-1-git-send-email-hpoussin@reactos.org> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a01:e0c:1:1599::13 Cc: =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Anthony Liguori , "Michael S. Tsirkin" Subject: [Qemu-devel] [PATCH] smbus: do not immediately complete commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org PIIX4 errata says that "immediate polling of the Host Status Register BUSY bit may indicate that the SMBus is NOT busy." This fixes some code which does the following steps: (a) set parameters (b) start command (c) check for smbus busy bit set (to know that command started) (d) check for smbus busy bit not set (to know that command finished) Fix (c), by immediately setting the busy bit, and completing the command a little bit later. Signed-off-by: Hervé Poussineau --- This fixes a problem with a real bios, which can now properly initialize the PIIX4. Note also that load/save support is not yet implemented for this device. hw/i2c/pm_smbus.c | 16 +++++++++++++++- include/hw/i2c/pm_smbus.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c index 7d249ad..9de860e 100644 --- a/hw/i2c/pm_smbus.c +++ b/hw/i2c/pm_smbus.c @@ -53,14 +53,18 @@ #endif -static void smb_transaction(PMSMBus *s) +static void smb_transaction_timer(void *opaque) { + PMSMBus *s = opaque; uint8_t prot = (s->smb_ctl >> 2) & 0x07; uint8_t read = s->smb_addr & 0x01; uint8_t cmd = s->smb_cmd; uint8_t addr = s->smb_addr >> 1; i2c_bus *bus = s->smbus; + assert(s->smb_stat & STS_HOST_BUSY); + s->smb_stat &= ~STS_HOST_BUSY; + SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot); /* Transaction isn't exec if STS_DEV_ERR bit set */ if ((s->smb_stat & STS_DEV_ERR) != 0) { @@ -115,6 +119,14 @@ static void smb_transaction(PMSMBus *s) s->smb_stat |= STS_DEV_ERR; } +static void smb_transaction(PMSMBus *s) +{ + /* Do not execute immediately the command */ + s->smb_stat |= STS_HOST_BUSY; + timer_mod(s->result_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + (get_ticks_per_sec() / 1000)); +} + static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned width) { @@ -204,4 +216,6 @@ void pm_smbus_init(DeviceState *parent, PMSMBus *smb) smb->smbus = i2c_init_bus(parent, "i2c"); memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb, "pm-smbus", 64); + smb->result_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + smb_transaction_timer, smb); } diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h index e3069bf..f0db1d9 100644 --- a/include/hw/i2c/pm_smbus.h +++ b/include/hw/i2c/pm_smbus.h @@ -4,6 +4,7 @@ typedef struct PMSMBus { i2c_bus *smbus; MemoryRegion io; + QEMUTimer *result_timer; uint8_t smb_stat; uint8_t smb_ctl;