Device trees allow mixing different kinds of GPIOs in one property. For
that it is usefull to only provide a pointer to an arbitrary location in
the property and initialize a GPIO from that.
---
 bsps/arm/include/bsp/imx-gpio.h | 26 ++++++++++++++++
 bsps/arm/shared/pins/imx-gpio.c | 55 ++++++++++++++++++++++++++-------
 2 files changed, 69 insertions(+), 12 deletions(-)

diff --git a/bsps/arm/include/bsp/imx-gpio.h b/bsps/arm/include/bsp/imx-gpio.h
index 148f62a56e..5cda22972f 100644
--- a/bsps/arm/include/bsp/imx-gpio.h
+++ b/bsps/arm/include/bsp/imx-gpio.h
@@ -76,6 +76,32 @@ struct imx_gpio_pin {
  */
 void imx_gpio_init (struct imx_gpio_pin *pin);
 
+/**
+ * Initialize a GPIO pin from the fields in an FDT property.
+ *
+ * If you have for example the following property in an FDT node:
+ *
+ *     some-node {
+ *         mixed-stuff = <0>, <&some_node 1>, <&gpio4 22 GPIO_ACTIVE_LOW>, 
<17>;
+ *     };
+ *
+ * You can get the property using fdt_getprop(...) in your code, somehow find
+ * the right start position (the phandle &gpio4) and then pass it to this
+ * function.
+ *
+ * If you pass something != NULL to @a next_prop_pointer, you will get a 
pointer
+ * to the next part in the attribute. In the example above, that will be a
+ * pointer to the <17>.
+ *
+ * NOTE: The information from the third parameter in the FDT (GPIO_ACTIVE_LOW 
in
+ * the example) is currently ignored.
+ */
+rtems_status_code imx_gpio_init_from_fdt_property_pointer(
+  struct imx_gpio_pin *pin,
+  const uint32_t *prop_pointer,
+  enum imx_gpio_mode mode,
+  const uint32_t **next_prop_pointer);
+
 /**
  * Initialize a GPIO pin from a FDT property.
  *
diff --git a/bsps/arm/shared/pins/imx-gpio.c b/bsps/arm/shared/pins/imx-gpio.c
index 8b7d09e864..1e39822b93 100644
--- a/bsps/arm/shared/pins/imx-gpio.c
+++ b/bsps/arm/shared/pins/imx-gpio.c
@@ -191,12 +191,11 @@ static void imx_gpio_set_interrupt_mode(struct 
imx_gpio_pin *pin, uint32_t mode)
   }
 }
 
-rtems_status_code imx_gpio_init_from_fdt_property (
+rtems_status_code imx_gpio_init_from_fdt_property_pointer (
   struct imx_gpio_pin *pin,
-  int node_offset,
-  const char *property,
+  const uint32_t *prop_pointer,
   enum imx_gpio_mode mode,
-  size_t index
+  const uint32_t **next_prop_pointer
 )
 {
   int len;
@@ -205,7 +204,6 @@ rtems_status_code imx_gpio_init_from_fdt_property (
   const void *fdt;
   uint32_t gpio_regs;
   const unsigned pin_length_dwords = 3;
-  const unsigned pin_length_bytes = (pin_length_dwords * sizeof(uint32_t));
   uint32_t gpio_phandle;
   uint32_t pin_nr;
   int cfgnode;
@@ -213,16 +211,12 @@ rtems_status_code imx_gpio_init_from_fdt_property (
   memset(pin, 0, sizeof(*pin));
 
   fdt = bsp_fdt_get();
-  val = fdt_getprop(fdt, node_offset, property, &len);
-  if (val == NULL || (len % pin_length_bytes != 0) ||
-      (index >= len / pin_length_bytes)) {
-    sc = RTEMS_UNSATISFIED;
-  }
   if (sc == RTEMS_SUCCESSFUL) {
-    pin_nr = fdt32_to_cpu(val[1 + index * pin_length_dwords]);
-    gpio_phandle = fdt32_to_cpu(val[0 + index * pin_length_dwords]);
+    pin_nr = fdt32_to_cpu(prop_pointer[1]);
+    gpio_phandle = fdt32_to_cpu(prop_pointer[0]);
 
     cfgnode = fdt_node_offset_by_phandle(fdt, gpio_phandle);
+    /* FIXME: Check compatible strings here. */
     val = fdt_getprop(fdt, cfgnode, "reg", &len);
     if (len > 0) {
       gpio_regs = fdt32_to_cpu(val[0]);
@@ -239,6 +233,43 @@ rtems_status_code imx_gpio_init_from_fdt_property (
   if (sc == RTEMS_SUCCESSFUL) {
     imx_gpio_init(pin);
   }
+  if (sc == RTEMS_SUCCESSFUL && next_prop_pointer != NULL) {
+    *next_prop_pointer = prop_pointer + pin_length_dwords;
+  }
+
+  return sc;
+}
+
+rtems_status_code imx_gpio_init_from_fdt_property (
+  struct imx_gpio_pin *pin,
+  int node_offset,
+  const char *property,
+  enum imx_gpio_mode mode,
+  size_t index
+)
+{
+  int len;
+  const uint32_t *val;
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  const void *fdt;
+  const unsigned pin_length_dwords = 3;
+  const unsigned pin_length_bytes = pin_length_dwords * 4;
+
+  memset(pin, 0, sizeof(*pin));
+
+  fdt = bsp_fdt_get();
+  val = fdt_getprop(fdt, node_offset, property, &len);
+  if (val == NULL || (len % pin_length_bytes != 0) ||
+      (index >= len / pin_length_bytes)) {
+    sc = RTEMS_UNSATISFIED;
+  }
+  if (sc == RTEMS_SUCCESSFUL) {
+    sc = imx_gpio_init_from_fdt_property_pointer(
+      pin,
+      val + index * pin_length_dwords,
+      mode,
+      NULL);
+  }
 
   return sc;
 }
-- 
2.35.3

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to