OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From e058fa1969019c2f6705c53c4130e364a877d4e6 Mon Sep 17 00:00:00 2001 |
2 | From: Jonas Gorski <jonas.gorski@gmail.com> |
||
3 | Date: Sun, 26 Nov 2017 12:07:31 +0100 |
||
4 | Subject: [PATCH] gpio: fix device tree gpio hogs on dual role gpio/pincontrol |
||
5 | controllers |
||
6 | |||
7 | For dual role gpio and pincontrol controller, the device registration |
||
8 | path is often: |
||
9 | |||
10 | pinctrl_register(...); |
||
11 | gpiochip_add_data(...); |
||
12 | gpiochip_add_pin_range(...); |
||
13 | |||
14 | If the device tree node has any gpio-hogs, the code will try to apply them |
||
15 | in the gpiochip_add_data step, but fail as they cannot be requested, as the |
||
16 | ranges are missing. But we also cannot first add the pinranges, as the |
||
17 | appropriate data structures are only initialized in gpiochip_add_data. |
||
18 | |||
19 | To fix this, defer gpio-hogs to the time pin ranges get added instead of |
||
20 | directly at chip request time, if the gpio-chip has a request method. |
||
21 | |||
22 | Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> |
||
23 | --- |
||
24 | |||
25 | drivers/gpio/gpiolib-of.c | 20 +++++++++++++++----- |
||
26 | drivers/gpio/gpiolib.c | 5 +++-- |
||
27 | drivers/gpio/gpiolib.h | 8 ++++++++ |
||
28 | 3 files changed, 26 insertions(+), 7 deletions(-) |
||
29 | |||
30 | --- a/drivers/gpio/gpiolib-of.c |
||
31 | +++ b/drivers/gpio/gpiolib-of.c |
||
32 | @@ -274,19 +274,22 @@ static void of_gpiochip_set_names(struct |
||
33 | /** |
||
34 | * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions |
||
35 | * @chip: gpio chip to act on |
||
36 | + * @start: first gpio to check |
||
37 | + * @num: number of gpios to check |
||
38 | * |
||
39 | - * This is only used by of_gpiochip_add to request/set GPIO initial |
||
40 | - * configuration. |
||
41 | + * This is used by of_gpiochip_add, gpiochip_add_pingroup_range and |
||
42 | + * gpiochip_add_pin_range to request/set GPIO initial configuration. |
||
43 | * It retures error if it fails otherwise 0 on success. |
||
44 | */ |
||
45 | -static int of_gpiochip_scan_gpios(struct gpio_chip *chip) |
||
46 | +int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start, |
||
47 | + unsigned int num) |
||
48 | { |
||
49 | struct gpio_desc *desc = NULL; |
||
50 | struct device_node *np; |
||
51 | const char *name; |
||
52 | enum gpio_lookup_flags lflags; |
||
53 | enum gpiod_flags dflags; |
||
54 | - int ret; |
||
55 | + int ret, hwgpio; |
||
56 | |||
57 | for_each_available_child_of_node(chip->of_node, np) { |
||
58 | if (!of_property_read_bool(np, "gpio-hog")) |
||
59 | @@ -296,6 +299,10 @@ static int of_gpiochip_scan_gpios(struct |
||
60 | if (IS_ERR(desc)) |
||
61 | continue; |
||
62 | |||
63 | + hwgpio = gpio_chip_hwgpio(desc); |
||
64 | + if (hwgpio < start || hwgpio >= (start + num)) |
||
65 | + continue; |
||
66 | + |
||
67 | ret = gpiod_hog(desc, name, lflags, dflags); |
||
68 | if (ret < 0) |
||
69 | return ret; |
||
70 | @@ -531,7 +538,10 @@ int of_gpiochip_add(struct gpio_chip *ch |
||
71 | |||
72 | of_node_get(chip->of_node); |
||
73 | |||
74 | - return of_gpiochip_scan_gpios(chip); |
||
75 | + if (!chip->request) |
||
76 | + status = of_gpiochip_scan_gpios(chip, 0, chip->ngpio); |
||
77 | + |
||
78 | + return status; |
||
79 | } |
||
80 | |||
81 | void of_gpiochip_remove(struct gpio_chip *chip) |
||
82 | --- a/drivers/gpio/gpiolib.c |
||
83 | +++ b/drivers/gpio/gpiolib.c |
||
84 | @@ -1884,7 +1884,8 @@ int gpiochip_add_pingroup_range(struct g |
||
85 | |||
86 | list_add_tail(&pin_range->node, &gdev->pin_ranges); |
||
87 | |||
88 | - return 0; |
||
89 | + return of_gpiochip_scan_gpios(chip, gpio_offset, |
||
90 | + pin_range->range.npins); |
||
91 | } |
||
92 | EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); |
||
93 | |||
94 | @@ -1933,7 +1934,7 @@ int gpiochip_add_pin_range(struct gpio_c |
||
95 | |||
96 | list_add_tail(&pin_range->node, &gdev->pin_ranges); |
||
97 | |||
98 | - return 0; |
||
99 | + return of_gpiochip_scan_gpios(chip, gpio_offset, npins); |
||
100 | } |
||
101 | EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); |
||
102 | |||
103 | --- a/drivers/gpio/gpiolib.h |
||
104 | +++ b/drivers/gpio/gpiolib.h |
||
105 | @@ -96,6 +96,8 @@ struct gpio_desc *of_get_named_gpiod_fla |
||
106 | const char *list_name, int index, enum of_gpio_flags *flags); |
||
107 | int of_gpiochip_add(struct gpio_chip *gc); |
||
108 | void of_gpiochip_remove(struct gpio_chip *gc); |
||
109 | +int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start, |
||
110 | + unsigned int num); |
||
111 | #else |
||
112 | static inline struct gpio_desc *of_find_gpio(struct device *dev, |
||
113 | const char *con_id, |
||
114 | @@ -111,6 +113,12 @@ static inline struct gpio_desc *of_get_n |
||
115 | } |
||
116 | static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } |
||
117 | static inline void of_gpiochip_remove(struct gpio_chip *gc) { } |
||
118 | +static inline int of_gpiochip_scan_gpios(struct gpio_chip *chip, |
||
119 | + unsigned int start, |
||
120 | + unsigned int num) |
||
121 | +{ |
||
122 | + return 0; |
||
123 | +} |
||
124 | #endif /* CONFIG_OF_GPIO */ |
||
125 | |||
126 | #ifdef CONFIG_ACPI |