aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShiraz Hashim <shiraz.hashim@st.com>2012-10-27 05:51:36 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-11-11 13:06:00 -0500
commitf23f1516b6757c326cc638bed8c402c77e2a596e (patch)
treed1d17f111e57038c7ef6df43e79bb969c5844cd2
parent7e10ee68f8ccc62e0934ff02f39ce541f3879844 (diff)
gpiolib: provide provision to register pin ranges
pinctrl subsystem needs gpio chip base to prepare set of gpio pin ranges, which a given pinctrl driver can handle. This is important to handle pinctrl gpio request calls in order to program a given pin properly for gpio operation. As gpio base is allocated dynamically during gpiochip registration, presently there exists no clean way to pass this information to the pinctrl subsystem. After few discussions from [1], it was concluded that may be gpio controller reporting the pin range it supports, is a better way than pinctrl subsystem directly registering it. [1] http://comments.gmane.org/gmane.linux.ports.arm.kernel/184816 Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com> [Edited documentation a bit] Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio.txt36
-rw-r--r--Documentation/gpio.txt42
-rw-r--r--Documentation/pinctrl.txt3
-rw-r--r--drivers/gpio/gpiolib-of.c56
-rw-r--r--drivers/gpio/gpiolib.c43
-rw-r--r--drivers/pinctrl/core.c13
-rw-r--r--drivers/pinctrl/devicetree.c13
-rw-r--r--include/asm-generic/gpio.h25
-rw-r--r--include/linux/gpio.h3
-rw-r--r--include/linux/pinctrl/pinctrl.h17
10 files changed, 251 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index 4e16ba4feab0..a33628759d36 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
75 gpio-controller; 75 gpio-controller;
76 }; 76 };
77 77
782.1) gpio-controller and pinctrl subsystem
79------------------------------------------
78 80
81gpio-controller on a SOC might be tightly coupled with the pinctrl
82subsystem, in the sense that the pins can be used by other functions
83together with optional gpio feature.
84
85While the pin allocation is totally managed by the pin ctrl subsystem,
86gpio (under gpiolib) is still maintained by gpio drivers. It may happen
87that different pin ranges in a SoC is managed by different gpio drivers.
88
89This makes it logical to let gpio drivers announce their pin ranges to
90the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
91request the corresponding pin before any gpio usage.
92
93For this, the gpio controller can use a pinctrl phandle and pins to
94announce the pinrange to the pin ctrl subsystem. For example,
95
96 qe_pio_e: gpio-controller@1460 {
97 #gpio-cells = <2>;
98 compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
99 reg = <0x1460 0x18>;
100 gpio-controller;
101 gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
102
103 }
104
105where,
106 &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
107
108 Next values specify the base pin and number of pins for the range
109 handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
110 pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
111 by this gpio controller.
112
113The pinctrl node must have "#gpio-range-cells" property to show number of
114arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index e08a883de36e..77a1d11af723 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
439signaling rate accordingly. 439signaling rate accordingly.
440 440
441 441
442GPIO controllers and the pinctrl subsystem
443------------------------------------------
444
445A GPIO controller on a SOC might be tightly coupled with the pinctrl
446subsystem, in the sense that the pins can be used by other functions
447together with an optional gpio feature. We have already covered the
448case where e.g. a GPIO controller need to reserve a pin or set the
449direction of a pin by calling any of:
450
451pinctrl_request_gpio()
452pinctrl_free_gpio()
453pinctrl_gpio_direction_input()
454pinctrl_gpio_direction_output()
455
456But how does the pin control subsystem cross-correlate the GPIO
457numbers (which are a global business) to a certain pin on a certain
458pin controller?
459
460This is done by registering "ranges" of pins, which are essentially
461cross-reference tables. These are described in
462Documentation/pinctrl.txt
463
464While the pin allocation is totally managed by the pinctrl subsystem,
465gpio (under gpiolib) is still maintained by gpio drivers. It may happen
466that different pin ranges in a SoC is managed by different gpio drivers.
467
468This makes it logical to let gpio drivers announce their pin ranges to
469the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
470to request the corresponding pin to be prepared by the pinctrl subsystem
471before any gpio usage.
472
473For this, the gpio controller can register its pin range with pinctrl
474subsystem. There are two ways of doing it currently: with or without DT.
475
476For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
477
478For non-DT support, user can call gpiochip_add_pin_range() with appropriate
479parameters to register a range of gpio pins with a pinctrl driver. For this
480exact name string of pinctrl device has to be passed as one of the
481argument to this routine.
482
483
442What do these conventions omit? 484What do these conventions omit?
443=============================== 485===============================
444One of the biggest things these conventions omit is pin multiplexing, since 486One of the biggest things these conventions omit is pin multiplexing, since
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index a1cd2f9428d7..da40efbef6ec 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed
364the range ID value, so that the pin controller knows which range it should 364the range ID value, so that the pin controller knows which range it should
365deal with. 365deal with.
366 366
367Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
368section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
369pinctrl and gpio drivers.
367 370
368PINMUX interfaces 371PINMUX interfaces
369================= 372=================
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a45997aea8..a5b90c8e9844 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,7 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/of_gpio.h> 21#include <linux/of_gpio.h>
22#include <linux/pinctrl/pinctrl.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
23 24
24/* Private data structure for of_gpiochip_find_and_xlate */ 25/* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,58 @@ err0:
216} 217}
217EXPORT_SYMBOL(of_mm_gpiochip_add); 218EXPORT_SYMBOL(of_mm_gpiochip_add);
218 219
220#ifdef CONFIG_PINCTRL
221void of_gpiochip_add_pin_range(struct gpio_chip *chip)
222{
223 struct device_node *np = chip->of_node;
224 struct gpio_pin_range *pin_range;
225 struct of_phandle_args pinspec;
226 int index = 0, ret;
227
228 if (!np)
229 return;
230
231 do {
232 ret = of_parse_phandle_with_args(np, "gpio-ranges",
233 "#gpio-range-cells", index, &pinspec);
234 if (ret)
235 break;
236
237 pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range),
238 GFP_KERNEL);
239 if (!pin_range) {
240 pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
241 chip->label);
242 break;
243 }
244
245 pin_range->range.name = chip->label;
246 pin_range->range.base = chip->base;
247 pin_range->range.pin_base = pinspec.args[0];
248 pin_range->range.npins = pinspec.args[1];
249 pin_range->pctldev = of_pinctrl_add_gpio_range(pinspec.np,
250 &pin_range->range);
251
252 list_add_tail(&pin_range->node, &chip->pin_ranges);
253
254 } while (index++);
255}
256
257void of_gpiochip_remove_pin_range(struct gpio_chip *chip)
258{
259 struct gpio_pin_range *pin_range, *tmp;
260
261 list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
262 list_del(&pin_range->node);
263 pinctrl_remove_gpio_range(pin_range->pctldev,
264 &pin_range->range);
265 }
266}
267#else
268void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
269void of_gpiochip_remove_pin_range(struct gpio_chip *chip) {}
270#endif
271
219void of_gpiochip_add(struct gpio_chip *chip) 272void of_gpiochip_add(struct gpio_chip *chip)
220{ 273{
221 if ((!chip->of_node) && (chip->dev)) 274 if ((!chip->of_node) && (chip->dev))
@@ -229,11 +282,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
229 chip->of_xlate = of_gpio_simple_xlate; 282 chip->of_xlate = of_gpio_simple_xlate;
230 } 283 }
231 284
285 of_gpiochip_add_pin_range(chip);
232 of_node_get(chip->of_node); 286 of_node_get(chip->of_node);
233} 287}
234 288
235void of_gpiochip_remove(struct gpio_chip *chip) 289void of_gpiochip_remove(struct gpio_chip *chip)
236{ 290{
291 of_gpiochip_remove_pin_range(chip);
292
237 if (chip->of_node) 293 if (chip->of_node)
238 of_node_put(chip->of_node); 294 of_node_put(chip->of_node);
239} 295}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1c8d9e3380e1..f0b07bbfcc9a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1083,6 +1083,10 @@ int gpiochip_add(struct gpio_chip *chip)
1083 } 1083 }
1084 } 1084 }
1085 1085
1086#ifdef CONFIG_PINCTRL
1087 INIT_LIST_HEAD(&chip->pin_ranges);
1088#endif
1089
1086 of_gpiochip_add(chip); 1090 of_gpiochip_add(chip);
1087 1091
1088unlock: 1092unlock:
@@ -1180,6 +1184,45 @@ struct gpio_chip *gpiochip_find(void *data,
1180} 1184}
1181EXPORT_SYMBOL_GPL(gpiochip_find); 1185EXPORT_SYMBOL_GPL(gpiochip_find);
1182 1186
1187#ifdef CONFIG_PINCTRL
1188void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
1189 unsigned int pin_base, unsigned int npins)
1190{
1191 struct gpio_pin_range *pin_range;
1192
1193 pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL);
1194 if (!pin_range) {
1195 pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
1196 chip->label);
1197 return;
1198 }
1199
1200 pin_range->range.name = chip->label;
1201 pin_range->range.base = chip->base;
1202 pin_range->range.pin_base = pin_base;
1203 pin_range->range.npins = npins;
1204 pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name,
1205 &pin_range->range);
1206
1207 list_add_tail(&pin_range->node, &chip->pin_ranges);
1208}
1209
1210void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
1211{
1212 struct gpio_pin_range *pin_range, *tmp;
1213
1214 list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
1215 list_del(&pin_range->node);
1216 pinctrl_remove_gpio_range(pin_range->pctldev,
1217 &pin_range->range);
1218 }
1219}
1220#else
1221void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
1222 unsigned int pin_base, unsigned int npins) {}
1223void gpiochip_remove_pin_ranges(struct gpio_chip *chip) {}
1224#endif
1225
1183/* These "optional" allocation calls help prevent drivers from stomping 1226/* These "optional" allocation calls help prevent drivers from stomping
1184 * on each other, and help provide better diagnostics in debugfs. 1227 * on each other, and help provide better diagnostics in debugfs.
1185 * They're called even less than the "set direction" calls. 1228 * They're called even less than the "set direction" calls.
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b1086dcde15d..71db586b2afd 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -345,6 +345,19 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
345} 345}
346EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges); 346EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
347 347
348struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
349 struct pinctrl_gpio_range *range)
350{
351 struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
352
353 if (!pctldev)
354 return NULL;
355
356 pinctrl_add_gpio_range(pctldev, range);
357 return pctldev;
358}
359EXPORT_SYMBOL_GPL(find_pinctrl_and_add_gpio_range);
360
348/** 361/**
349 * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller 362 * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
350 * @pctldev: pin controller device to remove the range from 363 * @pctldev: pin controller device to remove the range from
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fcb1de45473c..6728ec71cb65 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -106,6 +106,19 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
106 return NULL; 106 return NULL;
107} 107}
108 108
109struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
110 struct pinctrl_gpio_range *range)
111{
112 struct pinctrl_dev *pctldev;
113
114 pctldev = find_pinctrl_by_of_node(np);
115 if (!pctldev)
116 return NULL;
117
118 pinctrl_add_gpio_range(pctldev, range);
119 return pctldev;
120}
121
109static int dt_to_map_one_config(struct pinctrl *p, const char *statename, 122static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
110 struct device_node *np_config) 123 struct device_node *np_config)
111{ 124{
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a9432fc6b8ba..92e5c432421c 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -5,6 +5,7 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/errno.h> 6#include <linux/errno.h>
7#include <linux/of.h> 7#include <linux/of.h>
8#include <linux/pinctrl/pinctrl.h>
8 9
9#ifdef CONFIG_GPIOLIB 10#ifdef CONFIG_GPIOLIB
10 11
@@ -47,6 +48,21 @@ struct seq_file;
47struct module; 48struct module;
48struct device_node; 49struct device_node;
49 50
51#ifdef CONFIG_PINCTRL
52/**
53 * struct gpio_pin_range - pin range controlled by a gpio chip
54 * @head: list for maintaining set of pin ranges, used internally
55 * @pctldev: pinctrl device which handles corresponding pins
56 * @range: actual range of pins controlled by a gpio controller
57 */
58
59struct gpio_pin_range {
60 struct list_head node;
61 struct pinctrl_dev *pctldev;
62 struct pinctrl_gpio_range range;
63};
64#endif
65
50/** 66/**
51 * struct gpio_chip - abstract a GPIO controller 67 * struct gpio_chip - abstract a GPIO controller
52 * @label: for diagnostics 68 * @label: for diagnostics
@@ -134,6 +150,15 @@ struct gpio_chip {
134 int (*of_xlate)(struct gpio_chip *gc, 150 int (*of_xlate)(struct gpio_chip *gc,
135 const struct of_phandle_args *gpiospec, u32 *flags); 151 const struct of_phandle_args *gpiospec, u32 *flags);
136#endif 152#endif
153#ifdef CONFIG_PINCTRL
154 /*
155 * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
156 * describe the actual pin range which they serve in an SoC. This
157 * information would be used by pinctrl subsystem to configure
158 * corresponding pins for gpio usage.
159 */
160 struct list_head pin_ranges;
161#endif
137}; 162};
138 163
139extern const char *gpiochip_is_requested(struct gpio_chip *chip, 164extern const char *gpiochip_is_requested(struct gpio_chip *chip,
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 2e31e8b3a190..a28445992b7f 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -231,6 +231,9 @@ static inline int irq_to_gpio(unsigned irq)
231 return -EINVAL; 231 return -EINVAL;
232} 232}
233 233
234void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
235 unsigned int pin_base, unsigned int npins);
236void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
234#endif 237#endif
235 238
236#endif /* __LINUX_GPIO_H */ 239#endif /* __LINUX_GPIO_H */
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index eda04674633d..434e5a94e131 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -136,6 +136,23 @@ extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
136 unsigned nranges); 136 unsigned nranges);
137extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, 137extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
138 struct pinctrl_gpio_range *range); 138 struct pinctrl_gpio_range *range);
139
140extern struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
141 struct pinctrl_gpio_range *range);
142
143#ifdef CONFIG_OF
144extern struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
145 struct pinctrl_gpio_range *range);
146#else
147static inline
148struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
149 struct pinctrl_gpio_range *range)
150{
151 return NULL;
152}
153
154#endif /* CONFIG_OF */
155
139extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev); 156extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
140extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); 157extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
141#else 158#else