sim: gpio: add output support
authorMike Frysinger <vapier@gentoo.org>
Tue, 26 Apr 2011 05:47:14 +0000 (05:47 +0000)
committerMike Frysinger <vapier@gentoo.org>
Tue, 26 Apr 2011 05:47:14 +0000 (05:47 +0000)
Make all of the pins bidirectional, and support sending signals when
software drives the pins as outputs.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
sim/bfin/ChangeLog
sim/bfin/dv-bfin_gpio.c

index a7e80b1ad35564d6957f413d98f04fcb79413618..6314e9755ad12970adbe116ccff4408ca8ff6ef6 100644 (file)
@@ -1,3 +1,11 @@
+2011-04-26  Mike Frysinger  <vapier@gentoo.org>
+
+       * dv-bfin_gpio.c (bfin_gpio_forward_ouput): New function.
+       (bfin_gpio_io_write_buffer): Store the current port state into
+       "data", and call bfin_gpio_forward_ouput when the data or dir
+       MMRs are updated.
+       (bfin_gpio_ports): Change p0..p15 to bidirect_port.
+
 2011-04-26  Mike Frysinger  <vapier@gentoo.org>
 
        * dv-bfin_gpio.c (bfin_gpio): Add "int_state" member.
index 7a6acb6e1641f57aca40a833957ae53aa1365e92..4d944406fb227c6f81c3d4b9ae32021a42b858a5 100644 (file)
@@ -76,6 +76,30 @@ bfin_gpio_forward_ints (struct hw *me, struct bfin_gpio *port)
   bfin_gpio_forward_int (me, port, port->maskb, 1);
 }
 
+static void
+bfin_gpio_forward_ouput (struct hw *me, struct bfin_gpio *port, bu32 odata)
+{
+  int pin, value, ovalue, bit;
+
+  for (pin = 0; pin < 16; ++pin)
+    {
+      bit = 1 << pin;
+
+      /* Make sure this is an output pin.  */
+      if (!(port->dir & bit))
+       continue;
+
+      /* Only signal port if the pin changes value.  */
+      value = !!(port->data & bit);
+      ovalue = !!(odata & bit);
+      if (value == ovalue)
+       continue;
+
+      HW_TRACE ((me, "outputting gpio %i changed to %i", pin, value));
+      hw_port_event (me, pin, value);
+    }
+}
+
 static unsigned
 bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
                           address_word addr, unsigned nr_bytes)
@@ -84,6 +108,7 @@ bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
   bu32 mmr_off;
   bu16 value;
   bu16 *valuep;
+  bu32 data = port->data;
 
   value = dv_load_2 (source);
   mmr_off = addr - port->base;
@@ -134,6 +159,10 @@ bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space,
   /* If updating masks, make sure we send updated port info.  */
   switch (mmr_off)
     {
+    case mmr_offset(dir):
+    case mmr_offset(data) ... mmr_offset(toggle):
+      bfin_gpio_forward_ouput (me, port, data);
+      break;
     case mmr_offset(maska) ... mmr_offset(maska_toggle):
       bfin_gpio_forward_int (me, port, port->maska, 0);
       break;
@@ -199,22 +228,22 @@ static const struct hw_port_descriptor bfin_gpio_ports[] =
 {
   { "mask_a", 0, 0, output_port, },
   { "mask_b", 1, 0, output_port, },
-  { "p0",     0, 0, input_port, },
-  { "p1",     1, 0, input_port, },
-  { "p2",     2, 0, input_port, },
-  { "p3",     3, 0, input_port, },
-  { "p4",     4, 0, input_port, },
-  { "p5",     5, 0, input_port, },
-  { "p6",     6, 0, input_port, },
-  { "p7",     7, 0, input_port, },
-  { "p8",     8, 0, input_port, },
-  { "p9",     9, 0, input_port, },
-  { "p10",   10, 0, input_port, },
-  { "p11",   11, 0, input_port, },
-  { "p12",   12, 0, input_port, },
-  { "p13",   13, 0, input_port, },
-  { "p14",   14, 0, input_port, },
-  { "p15",   15, 0, input_port, },
+  { "p0",     0, 0, bidirect_port, },
+  { "p1",     1, 0, bidirect_port, },
+  { "p2",     2, 0, bidirect_port, },
+  { "p3",     3, 0, bidirect_port, },
+  { "p4",     4, 0, bidirect_port, },
+  { "p5",     5, 0, bidirect_port, },
+  { "p6",     6, 0, bidirect_port, },
+  { "p7",     7, 0, bidirect_port, },
+  { "p8",     8, 0, bidirect_port, },
+  { "p9",     9, 0, bidirect_port, },
+  { "p10",   10, 0, bidirect_port, },
+  { "p11",   11, 0, bidirect_port, },
+  { "p12",   12, 0, bidirect_port, },
+  { "p13",   13, 0, bidirect_port, },
+  { "p14",   14, 0, bidirect_port, },
+  { "p15",   15, 0, bidirect_port, },
   { NULL, 0, 0, 0, },
 };