aboutsummaryrefslogtreecommitdiff
path: root/sim/bfin/dv-bfin_gpio.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-04-26 05:46:02 +0000
committerMike Frysinger <vapier@gentoo.org>2011-04-26 05:46:02 +0000
commit5e0ba1a39e6fd114a5557a674c6834d6dc1cca08 (patch)
tree3fdd1ba35c7d6ef843f7ce63eff3f1bebfd4de65 /sim/bfin/dv-bfin_gpio.c
parenta9c5be0fb781178f8c68a9418c2a90c23f2f3f25 (diff)
downloadgdb-5e0ba1a39e6fd114a5557a674c6834d6dc1cca08.zip
gdb-5e0ba1a39e6fd114a5557a674c6834d6dc1cca08.tar.gz
gdb-5e0ba1a39e6fd114a5557a674c6834d6dc1cca08.tar.bz2
sim: gpio: update mask a/b signals better
When the mask a/b MMRs are written, the output signal might change levels (as pins are [un]masked), so make sure we update the output level. Further, make sure we handle edge ints correctly by first sending a high signal followed by a low signal. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'sim/bfin/dv-bfin_gpio.c')
-rw-r--r--sim/bfin/dv-bfin_gpio.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/sim/bfin/dv-bfin_gpio.c b/sim/bfin/dv-bfin_gpio.c
index 23d2610..7a6acb6 100644
--- a/sim/bfin/dv-bfin_gpio.c
+++ b/sim/bfin/dv-bfin_gpio.c
@@ -28,6 +28,8 @@ struct bfin_gpio
{
bu32 base;
+ bu16 int_state;
+
/* Order after here is important -- matches hardware MMR layout. */
bu16 BFIN_MMR_16(data);
bu16 BFIN_MMR_16(clear);
@@ -60,6 +62,20 @@ static const char * const mmr_names[] =
};
#define mmr_name(off) mmr_names[(off) / 4]
+static void
+bfin_gpio_forward_int (struct hw *me, struct bfin_gpio *port, bu32 mask,
+ int dst_port)
+{
+ HW_TRACE ((me, "resending levels on port %c", 'a' + dst_port));
+ hw_port_event (me, dst_port, !!(port->int_state & mask));
+}
+static void
+bfin_gpio_forward_ints (struct hw *me, struct bfin_gpio *port)
+{
+ bfin_gpio_forward_int (me, port, port->maska, 0);
+ bfin_gpio_forward_int (me, port, port->maskb, 1);
+}
+
static unsigned
bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
address_word addr, unsigned nr_bytes)
@@ -115,6 +131,17 @@ bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
break;
}
+ /* If updating masks, make sure we send updated port info. */
+ switch (mmr_off)
+ {
+ case mmr_offset(maska) ... mmr_offset(maska_toggle):
+ bfin_gpio_forward_int (me, port, port->maska, 0);
+ break;
+ case mmr_offset(maskb) ... mmr_offset(maskb_toggle):
+ bfin_gpio_forward_int (me, port, port->maskb, 1);
+ break;
+ }
+
return nr_bytes;
}
@@ -250,6 +277,11 @@ bfin_gpio_port_event (struct hw *me, int my_port, struct hw *source,
return;
}
}
+
+ /* Send the signal up, and then fall through to clear it. */
+ port->int_state |= bit;
+ bfin_gpio_forward_ints (me, port);
+ port->int_state &= ~bit;
}
else
{
@@ -258,21 +290,14 @@ bfin_gpio_port_event (struct hw *me, int my_port, struct hw *source,
{
HW_TRACE ((me, "ignoring int due to EDGE=%i POLAR=%i lvl=%i",
!!(port->edge & bit), !!(port->polar & bit), nlvl));
- return;
+ /* We still need to signal SIC to clear the int, so don't return. */
+ port->int_state &= ~bit;
}
+ else
+ port->int_state |= bit;
}
- /* If the masks allow it, push the interrupt even higher. */
- if (port->maska & bit)
- {
- HW_TRACE ((me, "pin %i triggered an int via mask a", my_port));
- hw_port_event (me, 0, 1);
- }
- if (port->maskb & bit)
- {
- HW_TRACE ((me, "pin %i triggered an int via mask b", my_port));
- hw_port_event (me, 1, 1);
- }
+ bfin_gpio_forward_ints (me, port);
}
static void