]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
sim: bfin: separate port levels from isa levels in the CEC
authorMike Frysinger <vapier@gentoo.org>
Mon, 25 Apr 2011 23:12:51 +0000 (19:12 -0400)
committerMike Frysinger <vapier@gentoo.org>
Mon, 1 Jan 2024 23:23:25 +0000 (18:23 -0500)
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.

sim/bfin/dv-bfin_cec.c

index d2c955b3d0ef7de19d69c4a1cbe93b9a61da5fe8..54b6b2cb80e2b696052f604b44b901a2c3f8a9e7 100644 (file)
@@ -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.  */