From 9e5b0cc19cebf6ed876c7eace13b887b46e518c0 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 14 Aug 2013 18:15:15 +0000 Subject: ramips: update v3.10 patches Sync the patches with those sent upstream for v3.12. Signed-off-by: John Crispin SVN-Revision: 37778 --- .../0200-owrt-GPIO-add-gpio_export_with_name.patch | 325 +++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 target/linux/ramips/patches-3.10/0200-owrt-GPIO-add-gpio_export_with_name.patch (limited to 'target/linux/ramips/patches-3.10/0200-owrt-GPIO-add-gpio_export_with_name.patch') diff --git a/target/linux/ramips/patches-3.10/0200-owrt-GPIO-add-gpio_export_with_name.patch b/target/linux/ramips/patches-3.10/0200-owrt-GPIO-add-gpio_export_with_name.patch new file mode 100644 index 0000000000..6ba536a893 --- /dev/null +++ b/target/linux/ramips/patches-3.10/0200-owrt-GPIO-add-gpio_export_with_name.patch @@ -0,0 +1,325 @@ +From 8f3ed1fffa35d18c2b20ebb866c71a22cc0589ff Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 23 Jun 2013 00:16:22 +0200 +Subject: [PATCH 29/33] owrt: GPIO: add gpio_export_with_name + +http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/133856.html + +Signed-off-by: John Crispin +--- + Documentation/devicetree/bindings/gpio/gpio.txt | 60 ++++++++++++++++++++ + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++ + drivers/gpio/gpiolib.c | 24 +++++--- + include/asm-generic/gpio.h | 6 +- + include/linux/gpio.h | 26 ++++++++- + 5 files changed, 172 insertions(+), 12 deletions(-) + +--- a/Documentation/devicetree/bindings/gpio/gpio.txt ++++ b/Documentation/devicetree/bindings/gpio/gpio.txt +@@ -112,3 +112,63 @@ where, + + The pinctrl node must have "#gpio-range-cells" property to show number of + arguments to pass with phandle from gpio controllers node. ++ ++3) gpio-export ++-------------- ++ ++gpio-export will allow you to automatically export gpio ++ ++required properties: ++- compatible: Should be "gpio-export" ++ ++in each child node will reprensent a gpio or if no name is specified ++a list of gpio to export ++ ++required properties: ++- gpios: gpio to export ++ ++optional properties: ++ - gpio-export,name: export name ++ - gpio-export,output: to set the as output with default value ++ if no present gpio as input ++ - pio-export,direction_may_change: boolean to allow the direction to be controllable ++ ++Example: ++ ++ ++gpio_export { ++ compatible = "gpio-export"; ++ #size-cells = <0>; ++ ++ in { ++ gpio-export,name = "in"; ++ gpios = <&pioC 20 0>; ++ }; ++ ++ out { ++ gpio-export,name = "out"; ++ gpio-export,output = <1>; ++ gpio-export,direction_may_change; ++ gpios = <&pioC 21 0>; ++ }; ++ ++ in_out { ++ gpio-export,name = "in_out"; ++ gpio-export,direction_may_change; ++ gpios = <&pioC 21 0>; ++ }; ++ ++ gpios_in { ++ gpios = <&pioB 0 0 ++ &pioB 3 0 ++ &pioC 4 0>; ++ gpio-export,direction_may_change; ++ }; ++ ++ gpios_out { ++ gpios = <&pioB 1 0 ++ &pioB 2 0 ++ &pioC 3 0>; ++ gpio-export,output = <1>; ++ }; ++}; +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -21,6 +21,8 @@ + #include + #include + #include ++#include ++#include + + /* Private data structure for of_gpiochip_find_and_xlate */ + struct gg_data { +@@ -242,3 +244,69 @@ void of_gpiochip_remove(struct gpio_chip + if (chip->of_node) + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int __init of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ 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); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++}; ++ ++static int __init of_gpio_export_init(void) ++{ ++ return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe); ++} ++device_initcall(of_gpio_export_init); +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -96,7 +96,7 @@ static int gpiod_get_value(const struct + static void gpiod_set_value(struct gpio_desc *desc, int value); + static int gpiod_cansleep(const struct gpio_desc *desc); + static int gpiod_to_irq(const struct gpio_desc *desc); +-static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); ++static int gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + static int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); + static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value); +@@ -674,7 +674,7 @@ static ssize_t export_store(struct class + status = -ENODEV; + goto done; + } +- status = gpiod_export(desc, true); ++ status = gpiod_export(desc, true, NULL); + if (status < 0) + gpiod_free(desc); + else +@@ -736,9 +736,10 @@ static struct class gpio_class = { + + + /** +- * gpio_export - export a GPIO through sysfs ++ * gpio_export_with_name - export a GPIO through sysfs + * @gpio: gpio to make available, already requested + * @direction_may_change: true if userspace may change gpio direction ++ * @name: gpio name + * Context: arch_initcall or later + * + * When drivers want to make a GPIO accessible to userspace after they +@@ -750,7 +751,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-static int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++static int gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + unsigned long flags; + int status; +@@ -783,6 +784,8 @@ static int gpiod_export(struct gpio_desc + goto fail_unlock; + } + ++ if (name) ++ ioname = name; + if (!desc->chip->direction_input || !desc->chip->direction_output) + direction_may_change = false; + spin_unlock_irqrestore(&gpio_lock, flags); +@@ -829,11 +832,11 @@ fail_unlock: + return status; + } + +-int gpio_export(unsigned gpio, bool direction_may_change) ++int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) + { +- return gpiod_export(gpio_to_desc(gpio), direction_may_change); ++ return gpiod_export(gpio_to_desc(gpio), direction_may_change, name); + } +-EXPORT_SYMBOL_GPL(gpio_export); ++EXPORT_SYMBOL_GPL(gpio_export_with_name); + + static int match_export(struct device *dev, const void *data) + { +@@ -1092,7 +1095,7 @@ static inline void gpiochip_unexport(str + } + + static inline int gpiod_export(struct gpio_desc *desc, +- bool direction_may_change) ++ bool direction_may_change, const char *name) + { + return -ENOSYS; + } +@@ -1521,6 +1524,9 @@ int gpio_request_one(unsigned gpio, unsi + if (flags & GPIOF_OPEN_SOURCE) + set_bit(FLAG_OPEN_SOURCE, &desc->flags); + ++ if (flags & GPIOF_ACTIVE_LOW) ++ set_bit(FLAG_ACTIVE_LOW, &gpio_desc[gpio].flags); ++ + if (flags & GPIOF_DIR_IN) + err = gpiod_direction_input(desc); + else +@@ -1531,7 +1537,7 @@ int gpio_request_one(unsigned gpio, unsi + goto free_gpio; + + if (flags & GPIOF_EXPORT) { +- err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE); ++ err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE, NULL); + if (err) + goto free_gpio; + } +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -202,7 +202,8 @@ extern void gpio_free_array(const struct + * A sysfs interface can be exported by individual drivers if they want, + * but more typically is configured entirely from userspace. + */ +-extern int gpio_export(unsigned gpio, bool direction_may_change); ++extern int gpio_export_with_name(unsigned gpio, bool direction_may_change, ++ const char *name); + extern int gpio_export_link(struct device *dev, const char *name, + unsigned gpio); + extern int gpio_sysfs_set_active_low(unsigned gpio, int value); +@@ -284,7 +285,8 @@ struct device; + + /* sysfs support is only available with gpiolib, where it's optional */ + +-static inline int gpio_export(unsigned gpio, bool direction_may_change) ++static inline int gpio_export_with_name(unsigned gpio, ++ bool direction_may_change, const char *name) + { + return -ENOSYS; + } +--- a/include/linux/gpio.h ++++ b/include/linux/gpio.h +@@ -27,6 +27,9 @@ + #define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT) + #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE) + ++#define GPIOF_ACTIVE_LOW (1 << 6) ++ ++ + /** + * struct gpio - a structure describing a GPIO with configuration + * @gpio: the GPIO number +@@ -169,7 +172,8 @@ static inline void gpio_set_value_cansle + WARN_ON(1); + } + +-static inline int gpio_export(unsigned gpio, bool direction_may_change) ++static inline int gpio_export_with_name(unsigned gpio, ++ bool direction_may_change, const char *name) + { + /* GPIO can never have been requested or set as {in,out}put */ + WARN_ON(1); +@@ -236,4 +240,24 @@ int devm_gpio_request_one(struct device + unsigned long flags, const char *label); + void devm_gpio_free(struct device *dev, unsigned int gpio); + ++/** ++ * gpio_export - export a GPIO through sysfs ++ * @gpio: gpio to make available, already requested ++ * @direction_may_change: true if userspace may change gpio direction ++ * Context: arch_initcall or later ++ * ++ * When drivers want to make a GPIO accessible to userspace after they ++ * have requested it -- perhaps while debugging, or as part of their ++ * public interface -- they may use this routine. If the GPIO can ++ * change direction (some can't) and the caller allows it, userspace ++ * will see "direction" sysfs attribute which may be used to change ++ * the gpio's direction. A "value" attribute will always be provided. ++ * ++ * Returns zero on success, else an error. ++ */ ++static inline int gpio_export(unsigned gpio,bool direction_may_change) ++{ ++ return gpio_export_with_name(gpio, direction_may_change, NULL); ++} ++ + #endif /* __LINUX_GPIO_H */ -- cgit v1.2.3