qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] pl061: implement input interrupt logic
@ 2014-08-30 22:27 Colin Leitner
  2014-09-05 16:43 ` Peter Maydell
  0 siblings, 1 reply; 2+ messages in thread
From: Colin Leitner @ 2014-08-30 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

This patch adds the missing input interrupt logic to the pl061 GPIO device. To
keep the floating output pins to stay high, the old state variable had to be
split into two separate ones for input and output - which brings the vmstate
version to 3.

Edge level interrupts and I/O were tested under Linux 3.14. Level interrupt
handling hasn't been tested.

Signed-off-by: Colin Leitner <colin.leitner@googlemail.com>
---
 hw/gpio/pl061.c |   59 ++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 45 insertions(+), 14 deletions(-)

diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index dd4ea29..bd03e99 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -37,7 +37,8 @@ typedef struct PL061State {
     MemoryRegion iomem;
     uint32_t locked;
     uint32_t data;
-    uint32_t old_data;
+    uint32_t old_out_data;
+    uint32_t old_in_data;
     uint32_t dir;
     uint32_t isense;
     uint32_t ibe;
@@ -63,12 +64,13 @@ typedef struct PL061State {

 static const VMStateDescription vmstate_pl061 = {
     .name = "pl061",
-    .version_id = 2,
-    .minimum_version_id = 1,
+    .version_id = 3,
+    .minimum_version_id = 3,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(locked, PL061State),
         VMSTATE_UINT32(data, PL061State),
-        VMSTATE_UINT32(old_data, PL061State),
+        VMSTATE_UINT32(old_out_data, PL061State),
+        VMSTATE_UINT32(old_in_data, PL061State),
         VMSTATE_UINT32(dir, PL061State),
         VMSTATE_UINT32(isense, PL061State),
         VMSTATE_UINT32(ibe, PL061State),
@@ -98,23 +100,52 @@ static void pl061_update(PL061State *s)
     uint8_t out;
     int i;

+    DPRINTF("dir = %d, data = %d\n", s->dir, s->data);
+
     /* Outputs float high.  */
     /* FIXME: This is board dependent.  */
     out = (s->data & s->dir) | ~s->dir;
-    changed = s->old_data ^ out;
-    if (!changed)
-        return;
+    changed = s->old_out_data ^ out;
+    if (changed) {
+        s->old_out_data = out;
+        for (i = 0; i < 8; i++) {
+            mask = 1 << i;
+            if (changed & mask) {
+                DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
+                qemu_set_irq(s->out[i], (out & mask) != 0);
+            }
+        }
+    }

-    s->old_data = out;
-    for (i = 0; i < 8; i++) {
-        mask = 1 << i;
-        if (changed & mask) {
-            DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
-            qemu_set_irq(s->out[i], (out & mask) != 0);
+    /* Inputs */
+    changed = (s->old_in_data ^ s->data) & ~s->dir;
+    if (changed) {
+        s->old_in_data = s->data;
+        for (i = 0; i < 8; i++) {
+            mask = 1 << i;
+            if (changed & mask) {
+                DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0);
+
+                if (!(s->isense & mask)) {
+                    /* Edge interrupt */
+                    if (s->ibe & mask) {
+                        /* Any edge triggers the interrupt */
+                        s->istate |= mask;
+                    } else {
+                        /* Edge is selected by IEV */
+                        s->istate |= ~(s->data ^ s->iev) & mask;
+                    }
+                }
+            }
         }
     }

-    /* FIXME: Implement input interrupts.  */
+    /* Level interrupt */
+    s->istate |= ~(s->data ^ s->iev) & s->isense;
+
+    DPRINTF("istate = %02X\n", s->istate);
+
+    qemu_set_irq(s->irq, (s->istate & s->im) != 0);
 }

 static uint64_t pl061_read(void *opaque, hwaddr offset,
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH] pl061: implement input interrupt logic
  2014-08-30 22:27 [Qemu-devel] [PATCH] pl061: implement input interrupt logic Colin Leitner
@ 2014-09-05 16:43 ` Peter Maydell
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Maydell @ 2014-09-05 16:43 UTC (permalink / raw)
  To: Colin Leitner; +Cc: QEMU Developers

On 30 August 2014 23:27, Colin Leitner <colin.leitner@googlemail.com> wrote:
> This patch adds the missing input interrupt logic to the pl061 GPIO device. To
> keep the floating output pins to stay high, the old state variable had to be
> split into two separate ones for input and output - which brings the vmstate
> version to 3.
>
> Edge level interrupts and I/O were tested under Linux 3.14. Level interrupt
> handling hasn't been tested.
>
> Signed-off-by: Colin Leitner <colin.leitner@googlemail.com>

Applied to target-arm.next, thanks.

-- PMM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2014-09-05 16:43 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-30 22:27 [Qemu-devel] [PATCH] pl061: implement input interrupt logic Colin Leitner
2014-09-05 16:43 ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).