mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 04:00:07 +08:00
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>
This commit is contained in:
@ -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>
|
2011-04-16 Mike Frysinger <vapier@gentoo.org>
|
||||||
|
|
||||||
* bfin-sim.c (decode_dsp32alu_0): Call STORE instead of SET_DREG for
|
* bfin-sim.c (decode_dsp32alu_0): Call STORE instead of SET_DREG for
|
||||||
|
@ -28,6 +28,8 @@ struct bfin_gpio
|
|||||||
{
|
{
|
||||||
bu32 base;
|
bu32 base;
|
||||||
|
|
||||||
|
bu16 int_state;
|
||||||
|
|
||||||
/* Order after here is important -- matches hardware MMR layout. */
|
/* Order after here is important -- matches hardware MMR layout. */
|
||||||
bu16 BFIN_MMR_16(data);
|
bu16 BFIN_MMR_16(data);
|
||||||
bu16 BFIN_MMR_16(clear);
|
bu16 BFIN_MMR_16(clear);
|
||||||
@ -60,6 +62,20 @@ static const char * const mmr_names[] =
|
|||||||
};
|
};
|
||||||
#define mmr_name(off) mmr_names[(off) / 4]
|
#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
|
static unsigned
|
||||||
bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
|
bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
|
||||||
address_word addr, unsigned nr_bytes)
|
address_word addr, unsigned nr_bytes)
|
||||||
@ -115,6 +131,17 @@ bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
|
|||||||
break;
|
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;
|
return nr_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +277,11 @@ bfin_gpio_port_event (struct hw *me, int my_port, struct hw *source,
|
|||||||
return;
|
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
|
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",
|
HW_TRACE ((me, "ignoring int due to EDGE=%i POLAR=%i lvl=%i",
|
||||||
!!(port->edge & bit), !!(port->polar & bit), nlvl));
|
!!(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. */
|
bfin_gpio_forward_ints (me, port);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Reference in New Issue
Block a user