summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/i2c/pm_smbus.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 6fc3923f56..ec060d58cc 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -63,6 +63,9 @@ static void smb_transaction(PMSMBus *s)
I2CBus *bus = s->smbus;
int ret;
+ 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) {
@@ -135,6 +138,13 @@ error:
}
+static void smb_transaction_start(PMSMBus *s)
+{
+ /* Do not execute immediately the command ; it will be
+ * executed when guest will read SMB_STAT register */
+ s->smb_stat |= STS_HOST_BUSY;
+}
+
static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
unsigned width)
{
@@ -150,7 +160,7 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
case SMBHSTCNT:
s->smb_ctl = val;
if (val & 0x40)
- smb_transaction(s);
+ smb_transaction_start(s);
break;
case SMBHSTCMD:
s->smb_cmd = val;
@@ -182,6 +192,10 @@ static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
switch(addr) {
case SMBHSTSTS:
val = s->smb_stat;
+ if (s->smb_stat & STS_HOST_BUSY) {
+ /* execute command now */
+ smb_transaction(s);
+ }
break;
case SMBHSTCNT:
s->smb_index = 0;