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