diff options
author | Christian Ruppert <christian.ruppert@abilis.com> | 2013-10-15 09:37:54 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-10-16 09:33:50 -0400 |
commit | 586a87e6edc936d6d3c3585af504b33b9c3f0a06 (patch) | |
tree | e3a8b9960ef9b6f9e28eaf235790889f5ddf886e | |
parent | c8ce878206076b159ee9488133aa51314570da38 (diff) |
pinctrl/gpio: non-linear GPIO ranges accesible from gpiolib
This patch adds the infrastructure required to register non-linear gpio
ranges through gpiolib and the standard GPIO device tree bindings.
Signed-off-by: Christian Ruppert <christian.ruppert@abilis.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/gpio/gpio.txt | 40 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 63 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 47 | ||||
-rw-r--r-- | drivers/pinctrl/core.c | 14 | ||||
-rw-r--r-- | include/asm-generic/gpio.h | 10 | ||||
-rw-r--r-- | include/linux/gpio.h | 10 | ||||
-rw-r--r-- | include/linux/pinctrl/pinctrl.h | 3 |
7 files changed, 177 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 6cec6ff20d2e..0c85bb6e3a80 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt | |||
@@ -87,8 +87,10 @@ controllers. The gpio-ranges property described below represents this, and | |||
87 | contains information structures as follows: | 87 | contains information structures as follows: |
88 | 88 | ||
89 | gpio-range-list ::= <single-gpio-range> [gpio-range-list] | 89 | gpio-range-list ::= <single-gpio-range> [gpio-range-list] |
90 | single-gpio-range ::= | 90 | single-gpio-range ::= <numeric-gpio-range> | <named-gpio-range> |
91 | numeric-gpio-range ::= | ||
91 | <pinctrl-phandle> <gpio-base> <pinctrl-base> <count> | 92 | <pinctrl-phandle> <gpio-base> <pinctrl-base> <count> |
93 | named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>' | ||
92 | gpio-phandle : phandle to pin controller node. | 94 | gpio-phandle : phandle to pin controller node. |
93 | gpio-base : Base GPIO ID in the GPIO controller | 95 | gpio-base : Base GPIO ID in the GPIO controller |
94 | pinctrl-base : Base pinctrl pin ID in the pin controller | 96 | pinctrl-base : Base pinctrl pin ID in the pin controller |
@@ -97,6 +99,19 @@ contains information structures as follows: | |||
97 | The "pin controller node" mentioned above must conform to the bindings | 99 | The "pin controller node" mentioned above must conform to the bindings |
98 | described in ../pinctrl/pinctrl-bindings.txt. | 100 | described in ../pinctrl/pinctrl-bindings.txt. |
99 | 101 | ||
102 | In case named gpio ranges are used (ranges with both <pinctrl-base> and | ||
103 | <count> set to 0), the property gpio-ranges-group-names contains one string | ||
104 | for every single-gpio-range in gpio-ranges: | ||
105 | gpiorange-names-list ::= <gpiorange-name> [gpiorange-names-list] | ||
106 | gpiorange-name : Name of the pingroup associated to the GPIO range in | ||
107 | the respective pin controller. | ||
108 | |||
109 | Elements of gpiorange-names-list corresponding to numeric ranges contain | ||
110 | the empty string. Elements of gpiorange-names-list corresponding to named | ||
111 | ranges contain the name of a pin group defined in the respective pin | ||
112 | controller. The number of pins/GPIOs in the range is the number of pins in | ||
113 | that pin group. | ||
114 | |||
100 | Previous versions of this binding required all pin controller nodes that | 115 | Previous versions of this binding required all pin controller nodes that |
101 | were referenced by any gpio-ranges property to contain a property named | 116 | were referenced by any gpio-ranges property to contain a property named |
102 | #gpio-range-cells with value <3>. This requirement is now deprecated. | 117 | #gpio-range-cells with value <3>. This requirement is now deprecated. |
@@ -104,7 +119,7 @@ However, that property may still exist in older device trees for | |||
104 | compatibility reasons, and would still be required even in new device | 119 | compatibility reasons, and would still be required even in new device |
105 | trees that need to be compatible with older software. | 120 | trees that need to be compatible with older software. |
106 | 121 | ||
107 | Example: | 122 | Example 1: |
108 | 123 | ||
109 | qe_pio_e: gpio-controller@1460 { | 124 | qe_pio_e: gpio-controller@1460 { |
110 | #gpio-cells = <2>; | 125 | #gpio-cells = <2>; |
@@ -117,3 +132,24 @@ Example: | |||
117 | Here, a single GPIO controller has GPIOs 0..9 routed to pin controller | 132 | Here, a single GPIO controller has GPIOs 0..9 routed to pin controller |
118 | pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's | 133 | pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's |
119 | pins 50..59. | 134 | pins 50..59. |
135 | |||
136 | Example 2: | ||
137 | |||
138 | gpio_pio_i: gpio-controller@14B0 { | ||
139 | #gpio-cells = <2>; | ||
140 | compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; | ||
141 | reg = <0x1480 0x18>; | ||
142 | gpio-controller; | ||
143 | gpio-ranges = <&pinctrl1 0 20 10>, | ||
144 | <&pinctrl2 10 0 0>, | ||
145 | <&pinctrl1 15 0 10>, | ||
146 | <&pinctrl2 25 0 0>; | ||
147 | gpio-ranges-group-names = "", | ||
148 | "foo", | ||
149 | "", | ||
150 | "bar"; | ||
151 | }; | ||
152 | |||
153 | Here, three GPIO ranges are defined wrt. two pin controllers. pinctrl1 GPIO | ||
154 | ranges are defined using pin numbers whereas the GPIO ranges wrt. pinctrl2 | ||
155 | are named "foo" and "bar". | ||
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 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 86ef3461ec06..b83b7e491f76 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -1320,6 +1320,53 @@ EXPORT_SYMBOL_GPL(gpiochip_find); | |||
1320 | #ifdef CONFIG_PINCTRL | 1320 | #ifdef CONFIG_PINCTRL |
1321 | 1321 | ||
1322 | /** | 1322 | /** |
1323 | * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping | ||
1324 | * @chip: the gpiochip to add the range for | ||
1325 | * @pinctrl: the dev_name() of the pin controller to map to | ||
1326 | * @gpio_offset: the start offset in the current gpio_chip number space | ||
1327 | * @pin_group: name of the pin group inside the pin controller | ||
1328 | */ | ||
1329 | int gpiochip_add_pingroup_range(struct gpio_chip *chip, | ||
1330 | struct pinctrl_dev *pctldev, | ||
1331 | unsigned int gpio_offset, const char *pin_group) | ||
1332 | { | ||
1333 | struct gpio_pin_range *pin_range; | ||
1334 | int ret; | ||
1335 | |||
1336 | pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); | ||
1337 | if (!pin_range) { | ||
1338 | pr_err("%s: GPIO chip: failed to allocate pin ranges\n", | ||
1339 | chip->label); | ||
1340 | return -ENOMEM; | ||
1341 | } | ||
1342 | |||
1343 | /* Use local offset as range ID */ | ||
1344 | pin_range->range.id = gpio_offset; | ||
1345 | pin_range->range.gc = chip; | ||
1346 | pin_range->range.name = chip->label; | ||
1347 | pin_range->range.base = chip->base + gpio_offset; | ||
1348 | pin_range->pctldev = pctldev; | ||
1349 | |||
1350 | ret = pinctrl_get_group_pins(pctldev, pin_group, | ||
1351 | &pin_range->range.pins, | ||
1352 | &pin_range->range.npins); | ||
1353 | if (ret < 0) | ||
1354 | return ret; | ||
1355 | |||
1356 | pinctrl_add_gpio_range(pctldev, &pin_range->range); | ||
1357 | |||
1358 | pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n", | ||
1359 | chip->label, gpio_offset, | ||
1360 | gpio_offset + pin_range->range.npins - 1, | ||
1361 | pinctrl_dev_get_devname(pctldev), pin_group); | ||
1362 | |||
1363 | list_add_tail(&pin_range->node, &chip->pin_ranges); | ||
1364 | |||
1365 | return 0; | ||
1366 | } | ||
1367 | EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); | ||
1368 | |||
1369 | /** | ||
1323 | * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping | 1370 | * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping |
1324 | * @chip: the gpiochip to add the range for | 1371 | * @chip: the gpiochip to add the range for |
1325 | * @pinctrl_name: the dev_name() of the pin controller to map to | 1372 | * @pinctrl_name: the dev_name() of the pin controller to map to |
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 92f86ab30a13..5ee61a470016 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -462,6 +462,20 @@ struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname, | |||
462 | } | 462 | } |
463 | EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range); | 463 | EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range); |
464 | 464 | ||
465 | int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group, | ||
466 | const unsigned **pins, unsigned *num_pins) | ||
467 | { | ||
468 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | ||
469 | int gs; | ||
470 | |||
471 | gs = pinctrl_get_group_selector(pctldev, pin_group); | ||
472 | if (gs < 0) | ||
473 | return gs; | ||
474 | |||
475 | return pctlops->get_group_pins(pctldev, gs, pins, num_pins); | ||
476 | } | ||
477 | EXPORT_SYMBOL_GPL(pinctrl_get_group_pins); | ||
478 | |||
465 | /** | 479 | /** |
466 | * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin | 480 | * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin |
467 | * @pctldev: the pin controller device to look in | 481 | * @pctldev: the pin controller device to look in |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index bde646995d10..523f40525535 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
@@ -228,6 +228,9 @@ struct gpio_pin_range { | |||
228 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | 228 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, |
229 | unsigned int gpio_offset, unsigned int pin_offset, | 229 | unsigned int gpio_offset, unsigned int pin_offset, |
230 | unsigned int npins); | 230 | unsigned int npins); |
231 | int gpiochip_add_pingroup_range(struct gpio_chip *chip, | ||
232 | struct pinctrl_dev *pctldev, | ||
233 | unsigned int gpio_offset, const char *pin_group); | ||
231 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip); | 234 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip); |
232 | 235 | ||
233 | #else | 236 | #else |
@@ -239,6 +242,13 @@ gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | |||
239 | { | 242 | { |
240 | return 0; | 243 | return 0; |
241 | } | 244 | } |
245 | static inline int | ||
246 | gpiochip_add_pingroup_range(struct gpio_chip *chip, | ||
247 | struct pinctrl_dev *pctldev, | ||
248 | unsigned int gpio_offset, const char *pin_group) | ||
249 | { | ||
250 | return 0; | ||
251 | } | ||
242 | 252 | ||
243 | static inline void | 253 | static inline void |
244 | gpiochip_remove_pin_ranges(struct gpio_chip *chip) | 254 | gpiochip_remove_pin_ranges(struct gpio_chip *chip) |
diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 552e3f46e4a3..b8d0e53a802f 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h | |||
@@ -80,6 +80,7 @@ static inline int irq_to_gpio(unsigned int irq) | |||
80 | #include <linux/types.h> | 80 | #include <linux/types.h> |
81 | #include <linux/errno.h> | 81 | #include <linux/errno.h> |
82 | #include <linux/bug.h> | 82 | #include <linux/bug.h> |
83 | #include <linux/pinctrl/pinctrl.h> | ||
83 | 84 | ||
84 | struct device; | 85 | struct device; |
85 | struct gpio_chip; | 86 | struct gpio_chip; |
@@ -220,6 +221,15 @@ gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | |||
220 | return -EINVAL; | 221 | return -EINVAL; |
221 | } | 222 | } |
222 | 223 | ||
224 | static inline int | ||
225 | gpiochip_add_pingroup_range(struct gpio_chip *chip, | ||
226 | struct pinctrl_dev *pctldev, | ||
227 | unsigned int gpio_offset, const char *pin_group) | ||
228 | { | ||
229 | WARN_ON(1); | ||
230 | return -EINVAL; | ||
231 | } | ||
232 | |||
223 | static inline void | 233 | static inline void |
224 | gpiochip_remove_pin_ranges(struct gpio_chip *chip) | 234 | gpiochip_remove_pin_ranges(struct gpio_chip *chip) |
225 | { | 235 | { |
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 5979147d2bda..fefb88663975 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h | |||
@@ -144,6 +144,9 @@ extern struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname, | |||
144 | extern struct pinctrl_gpio_range * | 144 | extern struct pinctrl_gpio_range * |
145 | pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, | 145 | pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, |
146 | unsigned int pin); | 146 | unsigned int pin); |
147 | extern int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, | ||
148 | const char *pin_group, const unsigned **pins, | ||
149 | unsigned *num_pins); | ||
147 | 150 | ||
148 | #ifdef CONFIG_OF | 151 | #ifdef CONFIG_OF |
149 | extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np); | 152 | extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np); |