From a621ee69e50deefb232429501269899f06afc285 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Juha=20Riihim=C3=A4ki?= Date: Tue, 17 Feb 2009 13:15:54 +0200 Subject: [PATCH] Fix XRDY/RRDY/XDR/RDR interrupt generation for OMAP3 I2C Patch for XRDY/RRDY/XDR/RDR interrupt generation in the OMAP3 I2C emulation. --- hw/omap_i2c.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c index c0997a4..cf15473 100644 --- a/hw/omap_i2c.c +++ b/hw/omap_i2c.c @@ -28,7 +28,7 @@ struct omap_i2c_s { i2c_bus *bus; uint8_t revision; - uint8_t mask; + uint16_t mask; uint16_t stat; uint16_t we; uint16_t dma; @@ -173,25 +173,27 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) } } else { if ((s->control >> 9) & 1) { /* TRX */ - TRACE("master transmit"); + TRACE("master transmit, count_cur=%d, txlen=%d", s->count_cur, s->txlen); /* this implementation actually always transfers everything in the FIFO if acknowledged by the slave; thus a situation where we would set XDR status never really happens */ for (i = 0; ack && s->count_cur && i < s->txlen; i++, s->count_cur--) ack = (i2c_send(s->bus, s->fifo[i]) >= 0); s->txlen -= i; - if (s->txlen) + if (s->txlen) /* happens only when NACK has been received */ memmove(s->fifo, s->fifo + i, s->txlen); s->stat &= ~0x4410; /* XDR | XUDF | XRDY */ if (ack && s->count_cur) { /* send more? */ - if (!s->txlen) - s->stat |= 1 << 10; /* XUDF */ - if (s->revision >= OMAP3_INTR_REV - && (s->mask & (1 << 14)) - && s->txlen >= s->fifosize - (s->dma & 0x3f)) /* XTRSH */ - s->stat |= 1 << 14; /* XDR */ - else + /* we know that FIFO is empty */ + s->stat |= 1 << 10; /* XUDF */ + if (s->revision < OMAP3_INTR_REV) s->stat |= 1 << 4; /* XRDY */ + else { + if (s->count_cur < (s->dma & 0x3f)) /* XTRSH */ + s->stat |= 1 << 14; + else + s->stat |= 1 << 4; + } } if (!s->count_cur) /* everything sent? */ s->stat |= 1 << 2; /* ARDY */ @@ -205,8 +207,7 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s) } s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */ if (s->rxlen) { - if (s->revision < OMAP3_INTR_REV - || !(s->mask & (1 << 13))) + if (s->revision < OMAP3_INTR_REV) s->stat |= 1 << 3; /* RRDY */ else { if (s->rxlen > ((s->dma >> 8) & 0x3f)) /* RTRSH */ @@ -364,8 +365,8 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) case 64: ret = 0xc000; break; default: ret = 0x0000; break; } - ret |= ((s->rxlen) & 0x3f) << 8; /* RXSTAT */ - ret |= s->txlen & 0x3f; /* TXSTAT */ + ret |= ((s->rxlen) & 0x3f) << 8; /* RXSTAT */ + ret |= (s->count_cur) & 0x3f; /* TXSTAT */ TRACE("BUFSTAT returns %04x", ret); return ret; } @@ -412,6 +413,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, s->mask = value & 0x63ff; else s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f); + omap_i2c_interrupts_update(s); break; case 0x08: /* I2C_STAT */ if (s->revision < OMAP2_INTR_REV) -- 1.7.9.5