aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-04-25 19:12:51 -0400
committerMike Frysinger <vapier@gentoo.org>2024-01-01 18:23:25 -0500
commit7eb2c710983289b2b268c251de57ded08b12c23e (patch)
treee70197ea597ff53eac053a59fe7631bfcb2f2d17
parentd07460446a94b5a1a3b68c9cdaee2b6b25227d67 (diff)
downloadgdb-7eb2c710983289b2b268c251de57ded08b12c23e.zip
gdb-7eb2c710983289b2b268c251de57ded08b12c23e.tar.gz
gdb-7eb2c710983289b2b268c251de57ded08b12c23e.tar.bz2
sim: bfin: separate port levels from isa levels in the CEC
Since the input ports are level based (coming from the SIC/ctimer), make sure we keep those values separate from levels manually raised via insns (like RAISE and EXCPT) or cleared via MMRs (writes to ILAT). This way the peripherals can raise/lower their interrupt lines without affecting manual tweaking, and we get behavior that matches the hardware. Signed-off-by: Mike Frysinger <vapier@gentoo.org> 2011-04-25 Mike Frysinger <vapier@gentoo.org> * dv-bfin_cec.c (bfin_cec): Add "plat" member. (bfin_cec_io_read_buffer): Merge "plat" with "ilat" when reading the ILAT MMR. (bfin_cec_port_event): Use the incoming level to set/clear bits in "plat". When the bit isn't yet set, also call _cec_raise. (_cec_raise): Merge "plat" with "ilat" when calling __cec_get_ivg.
-rw-r--r--sim/bfin/dv-bfin_cec.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/sim/bfin/dv-bfin_cec.c b/sim/bfin/dv-bfin_cec.c
index d2c955b..54b6b2c 100644
--- a/sim/bfin/dv-bfin_cec.c
+++ b/sim/bfin/dv-bfin_cec.c
@@ -37,6 +37,9 @@ struct bfin_cec
struct hw *me;
struct hw_event *pending;
+ /* The port levels which latch into ilat. */
+ bu32 plat;
+
/* Order after here is important -- matches hardware MMR layout. */
bu32 evt_override, imask, ipend, ilat, iprio;
};
@@ -135,7 +138,15 @@ bfin_cec_io_read_buffer (struct hw *me, void *dest,
HW_TRACE_READ ();
- dv_store_4 (dest, *valuep);
+ switch (mmr_off)
+ {
+ case mmr_offset(ilat):
+ dv_store_4 (dest, *valuep | cec->plat);
+ break;
+ default:
+ dv_store_4 (dest, *valuep);
+ break;
+ }
return nr_bytes;
}
@@ -165,7 +176,18 @@ bfin_cec_port_event (struct hw *me, int my_port, struct hw *source,
int source_port, int level)
{
struct bfin_cec *cec = hw_data (me);
- _cec_raise (cec->cpu, cec, my_port);
+ bu32 bit = 1 << my_port;
+
+ if (level)
+ {
+ if (!(cec->plat & bit))
+ {
+ cec->plat |= bit;
+ _cec_raise (cec->cpu, cec, my_port);
+ }
+ }
+ else
+ cec->plat &= ~bit;
}
static void
@@ -507,7 +529,7 @@ _cec_raise (SIM_CPU *cpu, struct bfin_cec *cec, int ivg)
if (irpten)
goto done; /* All interrupts are masked anyways. */
- ivg = __cec_get_ivg (cec->ilat & cec->imask);
+ ivg = __cec_get_ivg ((cec->plat | cec->ilat) & cec->imask);
if (ivg < 0)
goto done; /* Nothing latched. */