Tobias Diedrich wrote:
> John Crispin wrote:
> > On 06/04/13 18:47, Tobias Diedrich wrote:
> > >+
> > >+  gpio-leds {
> > >+          compatible = "gpio-leds";
> > >+          // Used to enable power-over-ethernet passthrough from port0 to 
> > >port1.
> > >+          // Disable passthrough by default to prevent accidental 
> > >equipment damage.
> > >+          poe {
> > >+                  label = "freestation:poe:passthrough";
> > >+                  gpios =<&gpio0 11 1>;
> > >+          };
> > >+          // The following leds are defined in the ArcOS firmware, but 
> > >reportedly
> > >+          // not present in the Freestation5 device.
> > 
> > Hi,
> > 
> > this should be done with an of_gpio_export node
> > -> 
> > https://dev.openwrt.org/browser/trunk/target/linux/ramips/dts/DIR-645.dts#L134
> 
> There's a bug in the gpio-export code. :)
> 
> But I'm rewriting it to use the following syntax:
> 
> gpio-export,name = "mario";
> gpio-export,flags = "out_init_high", "active_low", "changeable";
> gpio-export,gpios = <&gpio0 11 1>;
> 
> Which will support the following flags (had to add GPIOF_ACTIVE_LOW):
> 
> static struct of_gpio_flag of_gpio_flags[] = {
>         { "in", GPIOF_DIR_IN },
>         { "out_init_low", GPIOF_OUT_INIT_LOW },
>         { "out_init_high", GPIOF_OUT_INIT_HIGH },
>         { "open_drain", GPIOF_OPEN_DRAIN },
>         { "open_source", GPIOF_OPEN_SOURCE },
>         { "active_low", GPIOF_ACTIVE_LOW },
>         { "changeable", GPIOF_EXPORT_CHANGEABLE },
>         { /* sentinel */ }
> };

Something like this (WIP).

Also has a few consistency-changes:
- Changed gpio_export -> gpio-export for consistency with gpio-leds & friends.
- Changed gpio-export,name -> label for consistency

--- 
a/target/linux/ramips/patches-3.8/0209-owrt-GPIO-add-gpio_export_with_name.patch
+++ 
b/target/linux/ramips/patches-3.8/0209-owrt-GPIO-add-gpio_export_with_name.patch
@@ -91,7 +91,7 @@ Signed-off-by: John Crispin <blogic@open
  
  /* Private data structure for of_gpiochip_find_and_xlate */
  struct gg_data {
-@@ -289,3 +291,62 @@ void of_gpiochip_remove(struct gpio_chip
+@@ -289,3 +291,103 @@ void of_gpiochip_remove(struct gpio_chip
        if (chip->of_node)
                of_node_put(chip->of_node);
  }
@@ -101,6 +101,32 @@ Signed-off-by: John Crispin <blogic@open
 +      { /* sentinel */ }
 +};
 +
++/* Private data structure for of_gpio_flag_value */
++struct of_gpio_flag {
++      const char *name;
++      unsigned value;
++};
++
++static struct of_gpio_flag of_gpio_flags[] = {
++      { "in", GPIOF_DIR_IN },
++      { "out_init_low", GPIOF_OUT_INIT_LOW },
++      { "out_init_high", GPIOF_OUT_INIT_HIGH },
++      { "open_drain", GPIOF_OPEN_DRAIN },
++      { "open_source", GPIOF_OPEN_SOURCE },
++      { "active_low", GPIOF_ACTIVE_LOW },
++      { "changeable", GPIOF_EXPORT_CHANGEABLE },
++      { /* sentinel */ }
++};
++
++static unsigned __init of_gpio_flag_value(const char *name, struct 
of_gpio_flag *flags)
++{
++      for (; flags->name; flags++)
++              if (!strcmp(flags->name, name))
++                      return flags->value;
++
++      return 0;
++}
++
 +static int __init of_gpio_export_probe(struct platform_device *pdev)
 +{
 +      struct device_node *np = pdev->dev.of_node;
@@ -111,27 +137,42 @@ Signed-off-by: John Crispin <blogic@open
 +      for_each_child_of_node(np, cnp) {
 +              const char *name = NULL;
 +              int gpio;
-+              bool dmc;
 +              int max_gpio = 1;
 +              int i;
 +
-+              of_property_read_string(cnp, "gpio-export,name", &name);
++              of_property_read_string(cnp, "label", &name);
 +
 +              if (!name)
 +                      max_gpio = of_gpio_count(cnp);
 +
 +              for (i = 0; i < max_gpio; i++) {
++                      unsigned flags = GPIOF_EXPORT;
++                      struct property *prop;
++                      const char *flag;
++
 +                      gpio = of_get_gpio(cnp, i);
-+                      if (devm_gpio_request(&pdev->dev, gpio, name ? name : 
of_node_full_name(np)))
-+                              continue;
 +
-+                      if (!of_property_read_u32(cnp, "gpio-export,output", 
&val))
-+                              gpio_direction_output(gpio, val);
-+                      else
-+                              gpio_direction_input(gpio);
++                      /* Only use output/direction_may_change if flags isn't 
used. */
++                      if (!of_find_property(cnp, "gpio-export,flags", NULL)) {
++                              if (!of_property_read_u32(cnp, 
"gpio-export,output", &val)) {
++                                      if (val)
++                                              flags |= GPIOF_OUT_INIT_HIGH;
++                                      else
++                                              flags |= GPIOF_OUT_INIT_LOW;
++                              } else {
++                                      flags |= GPIOF_DIR_IN;
++                              }
++
++                              if (of_property_read_bool(cnp, 
"gpio-export,direction_may_change"))
++                                      flags |= GPIOF_EXPORT_CHANGEABLE;
++                      }
++
++                      of_property_for_each_string(cnp, "gpio-export,flags", 
prop, flag)
++                              flags |= of_gpio_flag_value(flag, 
of_gpio_flags);
++
++                      if (devm_gpio_request_one(&pdev->dev, gpio, flags, name 
? name : of_node_full_name(np)))
++                              continue;
 +
-+                      dmc = of_property_read_bool(np, 
"gpio-export,direction_may_change");
-+                      gpio_export_with_name(gpio, dmc, name);
 +                      nb++;
 +              }
 +      }
@@ -156,9 +197,11 @@ Signed-off-by: John Crispin <blogic@open
 +device_initcall(of_gpio_export_init);
 --- a/drivers/gpio/gpiolib.c
 +++ b/drivers/gpio/gpiolib.c
-@@ -714,9 +714,10 @@ static struct class gpio_class = {
- 
+@@ -712,11 +712,11 @@ static struct class gpio_class = {
+       .class_attrs =  gpio_class_attrs,
+ };
  
+-
  /**
 - * gpio_export - export a GPIO through sysfs
 + * gpio_export_with_name - export a GPIO through sysfs
@@ -168,7 +211,7 @@ Signed-off-by: John Crispin <blogic@open
   * Context: arch_initcall or later
   *
   * When drivers want to make a GPIO accessible to userspace after they
-@@ -728,7 +729,7 @@ static struct class gpio_class = {
+@@ -728,7 +728,7 @@ static struct class gpio_class = {
   *
   * Returns zero on success, else an error.
   */
@@ -177,16 +220,18 @@ Signed-off-by: John Crispin <blogic@open
  {
        unsigned long           flags;
        struct gpio_desc        *desc;
-@@ -762,6 +763,8 @@ int gpio_export(unsigned gpio, bool dire
+@@ -762,6 +762,10 @@ int gpio_export(unsigned gpio, bool dire
                goto fail_unlock;
        }
  
 +      if (name)
 +              ioname = name;
++      if (!ioname && desc->label)
++              ioname = desc->label;
        if (!desc->chip->direction_input || !desc->chip->direction_output)
                direction_may_change = false;
        spin_unlock_irqrestore(&gpio_lock, flags);
-@@ -804,7 +807,7 @@ fail_unlock:
+@@ -804,7 +808,7 @@ fail_unlock:
        pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
        return status;
  }
@@ -195,6 +240,16 @@ Signed-off-by: John Crispin <blogic@open
  
  static int match_export(struct device *dev, void *data)
  {
+@@ -1418,6 +1422,9 @@ int gpio_request_one(unsigned gpio, unsi
+       if (flags & GPIOF_OPEN_SOURCE)
+               set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags);
+ 
++      if (flags & GPIOF_ACTIVE_LOW)
++              set_bit(FLAG_ACTIVE_LOW, &gpio_desc[gpio].flags);
++
+       if (flags & GPIOF_DIR_IN)
+               err = gpio_direction_input(gpio);
+       else
 --- a/include/asm-generic/gpio.h
 +++ b/include/asm-generic/gpio.h
 @@ -204,7 +204,8 @@ void devm_gpio_free(struct device *dev,
@@ -219,7 +274,17 @@ Signed-off-by: John Crispin <blogic@open
  }
 --- a/include/linux/gpio.h
 +++ b/include/linux/gpio.h
-@@ -189,7 +189,8 @@ static inline void gpio_set_value_cansle
+@@ -27,6 +27,9 @@
+ #define GPIOF_EXPORT_DIR_FIXED        (GPIOF_EXPORT)
+ #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+ 
++#define GPIOF_ACTIVE_HIGH     (0 << 6)
++#define GPIOF_ACTIVE_LOW      (1 << 6)
++
+ /**
+  * struct gpio - a structure describing a GPIO with configuration
+  * @gpio:     the GPIO number
+@@ -189,7 +192,8 @@ static inline void gpio_set_value_cansle
        WARN_ON(1);
  }
  
@@ -229,7 +294,7 @@ Signed-off-by: John Crispin <blogic@open
  {
        /* GPIO can never have been requested or set as {in,out}put */
        WARN_ON(1);
-@@ -248,4 +249,24 @@ gpiochip_remove_pin_ranges(struct gpio_c
+@@ -248,4 +252,24 @@ gpiochip_remove_pin_ranges(struct gpio_c
  
  #endif /* ! CONFIG_GENERIC_GPIO */
  
--- a/target/linux/ramips/dts/DIR-645.dts
+++ b/target/linux/ramips/dts/DIR-645.dts
@@ -131,13 +131,13 @@
                };
        };
 
-       gpio_export {
+       gpio-export {
                compatible = "gpio-export";
                #size-cells = <0>;
 
                usb {
-                       gpio-export,name = "usb";
-                       gpio-export,output = <1>;
+                       label = "usb";
+                       gpio-export,flags = "out_init_high";
                        gpios = <&gpio1 6 0>;
                };
        };
--- a/target/linux/ramips/dts/OMNI-EMB-HPM.dts
+++ b/target/linux/ramips/dts/OMNI-EMB-HPM.dts
@@ -101,18 +101,18 @@
                };
        };
 
-       gpio_export {
+       gpio-export {
                compatible = "gpio-export";
                #size-cells = <0>;
                /* gpio 12 and 13 handle the OC input */
                usb0 {
-                       gpio-export,name = "usb0";
-                       gpio-export,output = <1>;
+                       label = "usb0";
+                       gpio-export,flags = "out_init_high";
                        gpios = <&gpio0 2 0>;
                };
                usb1 {
-                       gpio-export,name = "usb1";
-                       gpio-export,output = <1>;
+                       label = "usb1";
+                       gpio-export,flags = "out_init_high";
                        gpios = <&gpio0 1 0>;
                };
        };
--- a/target/linux/ramips/dts/WR6202.dts
+++ b/target/linux/ramips/dts/WR6202.dts
@@ -85,13 +85,13 @@
                status = "okay";
        };
 
-       gpio_export {
+       gpio-export {
                compatible = "gpio-export";
                #size-cells = <0>;
 
                usb {
-                       gpio-export,name = "usb";
-                       gpio-export,output = <0>;
+                       label = "usb";
+                       gpio-export,flags = "out_init_low";
                        gpios = <&gpio0 11 0>;
                };
        };

-- 
Tobias                                          PGP: http://8ef7ddba.uguu.de
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to