diff options
Diffstat (limited to 'drivers/gpio/gpiolib-of.c')
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 0dfaf20e4dad..e78760921bd7 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
@@ -190,10 +190,15 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) | |||
190 | struct of_phandle_args pinspec; | 190 | struct of_phandle_args pinspec; |
191 | struct pinctrl_dev *pctldev; | 191 | struct pinctrl_dev *pctldev; |
192 | int index = 0, ret; | 192 | int index = 0, ret; |
193 | const char *name; | ||
194 | static const char group_names_propname[] = "gpio-ranges-group-names"; | ||
195 | struct property *group_names; | ||
193 | 196 | ||
194 | if (!np) | 197 | if (!np) |
195 | return; | 198 | return; |
196 | 199 | ||
200 | group_names = of_find_property(np, group_names_propname, NULL); | ||
201 | |||
197 | for (;; index++) { | 202 | for (;; index++) { |
198 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, | 203 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, |
199 | index, &pinspec); | 204 | index, &pinspec); |
@@ -204,14 +209,56 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) | |||
204 | if (!pctldev) | 209 | if (!pctldev) |
205 | break; | 210 | break; |
206 | 211 | ||
207 | ret = gpiochip_add_pin_range(chip, | 212 | if (pinspec.args[2]) { |
208 | pinctrl_dev_get_devname(pctldev), | 213 | if (group_names) { |
209 | pinspec.args[0], | 214 | ret = of_property_read_string_index(np, |
210 | pinspec.args[1], | 215 | group_names_propname, |
211 | pinspec.args[2]); | 216 | index, &name); |
212 | 217 | if (strlen(name)) { | |
213 | if (ret) | 218 | pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n", |
214 | break; | 219 | np->full_name); |
220 | break; | ||
221 | } | ||
222 | } | ||
223 | /* npins != 0: linear range */ | ||
224 | ret = gpiochip_add_pin_range(chip, | ||
225 | pinctrl_dev_get_devname(pctldev), | ||
226 | pinspec.args[0], | ||
227 | pinspec.args[1], | ||
228 | pinspec.args[2]); | ||
229 | if (ret) | ||
230 | break; | ||
231 | } else { | ||
232 | /* npins == 0: special range */ | ||
233 | if (pinspec.args[1]) { | ||
234 | pr_err("%s: Illegal gpio-range format.\n", | ||
235 | np->full_name); | ||
236 | break; | ||
237 | } | ||
238 | |||
239 | if (!group_names) { | ||
240 | pr_err("%s: GPIO group range requested but no %s property.\n", | ||
241 | np->full_name, group_names_propname); | ||
242 | break; | ||
243 | } | ||
244 | |||
245 | ret = of_property_read_string_index(np, | ||
246 | group_names_propname, | ||
247 | index, &name); | ||
248 | if (ret) | ||
249 | break; | ||
250 | |||
251 | if (!strlen(name)) { | ||
252 | pr_err("%s: Group name of GPIO group range cannot be the empty string.\n", | ||
253 | np->full_name); | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | ret = gpiochip_add_pingroup_range(chip, pctldev, | ||
258 | pinspec.args[0], name); | ||
259 | if (ret) | ||
260 | break; | ||
261 | } | ||
215 | } | 262 | } |
216 | } | 263 | } |
217 | 264 | ||