diff --git a/sim/bfin/ChangeLog b/sim/bfin/ChangeLog
index d4a36ca0eb6..953192f2d23 100644
--- a/sim/bfin/ChangeLog
+++ b/sim/bfin/ChangeLog
@@ -1,3 +1,9 @@
+2011-03-24  Mike Frysinger  <vapier@gentoo.org>
+
+	* dv-bfin_gpio.c (bfin_gpio_port_event): Split dir/inen bit checking.
+	Normalize "level" to 0/1 values.  Shift "level" over by "my_port".
+	Invert port->both bit check.
+
 2011-03-24  Mike Frysinger  <vapier@gentoo.org>
 
 	* dv-bfin_gpio.c (bfin_gpio_io_write_buffer): Subtract 2 from the
diff --git a/sim/bfin/dv-bfin_gpio.c b/sim/bfin/dv-bfin_gpio.c
index 6b18a4082c2..e9b79a80bb9 100644
--- a/sim/bfin/dv-bfin_gpio.c
+++ b/sim/bfin/dv-bfin_gpio.c
@@ -198,15 +198,21 @@ bfin_gpio_port_event (struct hw *me, int my_port, struct hw *source,
   bool olvl, nlvl;
   bu32 bit = (1 << my_port);
 
-  /* Only screw with state if this pin is set as an input.  */
-  if (!(port->dir & port->inen & bit))
+  /* Normalize the level value.  A simulated device can send any value
+     it likes to us, but in reality we only care about 0 and 1.  This
+     lets us assume only those two values below.  */
+  level = !!level;
+
+  /* Only screw with state if this pin is set as an input, and the
+     input is actually enabled.  */
+  if ((port->dir & bit) || !(port->inen & bit))
     return;
 
   /* Get the old pin state for calculating an interrupt.  */
   olvl = !!(port->data & bit);
 
   /* Update the new pin state.  */
-  port->data = (port->data & ~bit) | (level << bit);
+  port->data = (port->data & ~bit) | (level << my_port);
 
   /* See if this state transition will generate an interrupt.  */
   nlvl = !!(port->data & bit);
@@ -214,7 +220,7 @@ bfin_gpio_port_event (struct hw *me, int my_port, struct hw *source,
   if (port->edge & bit)
     {
       /* Pin is edge triggered.  */
-      if (!(port->both & bit))
+      if (port->both & bit)
 	{
 	  /* Both edges.  */
 	  if (olvl == nlvl)