diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-04-26 05:46:02 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-04-26 05:46:02 +0000 |
commit | 5e0ba1a39e6fd114a5557a674c6834d6dc1cca08 (patch) | |
tree | 3fdd1ba35c7d6ef843f7ce63eff3f1bebfd4de65 | |
parent | a9c5be0fb781178f8c68a9418c2a90c23f2f3f25 (diff) | |
download | fsf-binutils-gdb-5e0ba1a39e6fd114a5557a674c6834d6dc1cca08.zip fsf-binutils-gdb-5e0ba1a39e6fd114a5557a674c6834d6dc1cca08.tar.gz fsf-binutils-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>
-rw-r--r-- | sim/bfin/ChangeLog | 12 | ||||
-rw-r--r-- | sim/bfin/dv-bfin_gpio.c | 49 |
2 files changed, 49 insertions, 12 deletions
diff --git a/sim/bfin/ChangeLog b/sim/bfin/ChangeLog index 25944fd..a7e80b1 100644 --- a/sim/bfin/ChangeLog +++ b/sim/bfin/ChangeLog @@ -1,3 +1,15 @@ +2011-04-26 Mike Frysinger <vapier@gentoo.org> + + * dv-bfin_gpio.c (bfin_gpio): Add "int_state" member. + (bfin_gpio_forward_int, bfin_gpio_forward_ints): New functions. + (bfin_gpio_io_write_buffer): Call bfin_gpio_forward_int when the + mask a or mask b MMRs are written. + (bfin_gpio_port_event): When handling edge gpios, set the bit in + int_state, call bfin_gpio_forward_ints, and then clear the bit. + When handling level gpios, clear/set the bit in int_state rather + than returning immediately. Call bfin_gpio_forward_ints instead + of checking mask[ab] and calling HW_TRACE/hw_port_event directly. + 2011-04-16 Mike Frysinger <vapier@gentoo.org> * bfin-sim.c (decode_dsp32alu_0): Call STORE instead of SET_DREG for 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 |