diff options
Diffstat (limited to 'drivers/gpio/gpiolib-of.c')
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 4650bf830d6b..a6c67c6b4680 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/of_gpio.h> | 22 | #include <linux/of_gpio.h> |
23 | #include <linux/pinctrl/pinctrl.h> | 23 | #include <linux/pinctrl/pinctrl.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/gpio/machine.h> | ||
25 | 26 | ||
26 | #include "gpiolib.h" | 27 | #include "gpiolib.h" |
27 | 28 | ||
@@ -118,6 +119,114 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, | |||
118 | EXPORT_SYMBOL(of_get_named_gpio_flags); | 119 | EXPORT_SYMBOL(of_get_named_gpio_flags); |
119 | 120 | ||
120 | /** | 121 | /** |
122 | * of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API | ||
123 | * @np: device node to get GPIO from | ||
124 | * @name: GPIO line name | ||
125 | * @lflags: gpio_lookup_flags - returned from of_find_gpio() or | ||
126 | * of_get_gpio_hog() | ||
127 | * @dflags: gpiod_flags - optional GPIO initialization flags | ||
128 | * | ||
129 | * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno | ||
130 | * value on the error condition. | ||
131 | */ | ||
132 | static struct gpio_desc *of_get_gpio_hog(struct device_node *np, | ||
133 | const char **name, | ||
134 | enum gpio_lookup_flags *lflags, | ||
135 | enum gpiod_flags *dflags) | ||
136 | { | ||
137 | struct device_node *chip_np; | ||
138 | enum of_gpio_flags xlate_flags; | ||
139 | struct gpio_desc *desc; | ||
140 | struct gg_data gg_data = { | ||
141 | .flags = &xlate_flags, | ||
142 | }; | ||
143 | u32 tmp; | ||
144 | int i, ret; | ||
145 | |||
146 | chip_np = np->parent; | ||
147 | if (!chip_np) | ||
148 | return ERR_PTR(-EINVAL); | ||
149 | |||
150 | xlate_flags = 0; | ||
151 | *lflags = 0; | ||
152 | *dflags = 0; | ||
153 | |||
154 | ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp); | ||
155 | if (ret) | ||
156 | return ERR_PTR(ret); | ||
157 | |||
158 | if (tmp > MAX_PHANDLE_ARGS) | ||
159 | return ERR_PTR(-EINVAL); | ||
160 | |||
161 | gg_data.gpiospec.args_count = tmp; | ||
162 | gg_data.gpiospec.np = chip_np; | ||
163 | for (i = 0; i < tmp; i++) { | ||
164 | ret = of_property_read_u32_index(np, "gpios", i, | ||
165 | &gg_data.gpiospec.args[i]); | ||
166 | if (ret) | ||
167 | return ERR_PTR(ret); | ||
168 | } | ||
169 | |||
170 | gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); | ||
171 | if (!gg_data.out_gpio) { | ||
172 | if (np->parent == np) | ||
173 | return ERR_PTR(-ENXIO); | ||
174 | else | ||
175 | return ERR_PTR(-EINVAL); | ||
176 | } | ||
177 | |||
178 | if (xlate_flags & OF_GPIO_ACTIVE_LOW) | ||
179 | *lflags |= GPIO_ACTIVE_LOW; | ||
180 | |||
181 | if (of_property_read_bool(np, "input")) | ||
182 | *dflags |= GPIOD_IN; | ||
183 | else if (of_property_read_bool(np, "output-low")) | ||
184 | *dflags |= GPIOD_OUT_LOW; | ||
185 | else if (of_property_read_bool(np, "output-high")) | ||
186 | *dflags |= GPIOD_OUT_HIGH; | ||
187 | else { | ||
188 | pr_warn("GPIO line %d (%s): no hogging state specified, bailing out\n", | ||
189 | desc_to_gpio(gg_data.out_gpio), np->name); | ||
190 | return ERR_PTR(-EINVAL); | ||
191 | } | ||
192 | |||
193 | if (name && of_property_read_string(np, "line-name", name)) | ||
194 | *name = np->name; | ||
195 | |||
196 | desc = gg_data.out_gpio; | ||
197 | |||
198 | return desc; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * of_gpiochip_scan_hogs - Scan gpio-controller and apply GPIO hog as requested | ||
203 | * @chip: gpio chip to act on | ||
204 | * | ||
205 | * This is only used by of_gpiochip_add to request/set GPIO initial | ||
206 | * configuration. | ||
207 | */ | ||
208 | static void of_gpiochip_scan_hogs(struct gpio_chip *chip) | ||
209 | { | ||
210 | struct gpio_desc *desc = NULL; | ||
211 | struct device_node *np; | ||
212 | const char *name; | ||
213 | enum gpio_lookup_flags lflags; | ||
214 | enum gpiod_flags dflags; | ||
215 | |||
216 | for_each_child_of_node(chip->of_node, np) { | ||
217 | if (!of_property_read_bool(np, "gpio-hog")) | ||
218 | continue; | ||
219 | |||
220 | desc = of_get_gpio_hog(np, &name, &lflags, &dflags); | ||
221 | if (IS_ERR(desc)) | ||
222 | continue; | ||
223 | |||
224 | if (gpiod_hog(desc, name, lflags, dflags)) | ||
225 | continue; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /** | ||
121 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags | 230 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags |
122 | * @gc: pointer to the gpio_chip structure | 231 | * @gc: pointer to the gpio_chip structure |
123 | * @np: device node of the GPIO chip | 232 | * @np: device node of the GPIO chip |
@@ -326,6 +435,8 @@ void of_gpiochip_add(struct gpio_chip *chip) | |||
326 | 435 | ||
327 | of_gpiochip_add_pin_range(chip); | 436 | of_gpiochip_add_pin_range(chip); |
328 | of_node_get(chip->of_node); | 437 | of_node_get(chip->of_node); |
438 | |||
439 | of_gpiochip_scan_hogs(chip); | ||
329 | } | 440 | } |
330 | 441 | ||
331 | void of_gpiochip_remove(struct gpio_chip *chip) | 442 | void of_gpiochip_remove(struct gpio_chip *chip) |