aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 14:21:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 14:21:33 -0500
commit505cbedab9c7c565957e64af6348e5d84acd510e (patch)
tree4855caf82c434629432e22f03c96892d73383ba2 /drivers/gpio
parenta8936db7c2d9ef7f8e080d629301e448291f3b75 (diff)
parent7c8f86a451fe8c010eb93c62d4d69727ccdbe435 (diff)
Merge tag 'pinctrl-for-v3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pinctrl changes from Linus Walleij: "These are the first and major pinctrl changes for the v3.8 merge cycle. Some of this is used as merge base for other trees so I better be early on the trigger. As can be seen from the diffstat the major changes are: - A big conversion of the AT91 pinctrl driver and the associated ACKed platform changes under arch/arm/max-at91 and its device trees. This has been coordinated with the AT91 maintainers to go in through the pinctrl tree. - A larger chunk of changes to the SPEAr drivers and the addition of the "plgpio" driver for the SPEAr as well. - The removal of the remnants of the Nomadik driver from the arch/arm tree and fusion of that into the Nomadik driver and platform data header files. - Some local movement in the Marvell MVEBU drivers, these now have their own subdirectory. - The addition of a chunk of code to gpiolib under drivers/gpio to register gpio-to-pin range mappings from the GPIO side of things. This has been requested by Grant Likely and is now implemented, it is particularly useful for device tree work. Then we have incremental updates all over the place, many of these are cleanups and fixes from Axel Lin who has done a great job of removing minor mistakes and compilation annoyances." * tag 'pinctrl-for-v3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (114 commits) ARM: mmp: select PINCTRL for ARCH_MMP pinctrl: Drop selecting PINCONF for MMP2, PXA168 and PXA910 pinctrl: pinctrl-single: Fix error check condition pinctrl: SPEAr: Update error check for unsigned variables gpiolib: Fix use after free in gpiochip_add_pin_range gpiolib: rename pin range arguments pinctrl: single: support gpio request and free pinctrl: generic: add input schmitt disable parameter pinctrl/u300/coh901: stop spawning pinctrl from GPIO pinctrl/u300/coh901: let the gpio_chip register the range pinctrl: add function to retrieve range from pin gpiolib: return any error code from range creation pinctrl: make range registration defer properly gpiolib: rename find_pinctrl_* gpiolib: let gpiochip_add_pin_range() specify offset ARM: at91: pm9g45: add mmc support ARM: at91: Animeo IP: add mmc support ARM: at91: dt: add mmc pinctrl for Atmel reference boards ARM: at91: dt: at91sam9: add mmc pinctrl support ARM: at91/dts: add nodes for atmel hsmci controllers for atmel boards ...
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib-of.c52
-rw-r--r--drivers/gpio/gpiolib.c76
2 files changed, 128 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a45997aea8..d542a141811a 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,54 @@ err0:
216} 217}
217EXPORT_SYMBOL(of_mm_gpiochip_add); 218EXPORT_SYMBOL(of_mm_gpiochip_add);
218 219
220#ifdef CONFIG_PINCTRL
221static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
222{
223 struct device_node *np = chip->of_node;
224 struct of_phandle_args pinspec;
225 struct pinctrl_dev *pctldev;
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 pctldev = of_pinctrl_get(pinspec.np);
238 if (!pctldev)
239 break;
240
241 /*
242 * This assumes that the n GPIO pins are consecutive in the
243 * GPIO number space, and that the pins are also consecutive
244 * in their local number space. Currently it is not possible
245 * to add different ranges for one and the same GPIO chip,
246 * as the code assumes that we have one consecutive range
247 * on both, mapping 1-to-1.
248 *
249 * TODO: make the OF bindings handle multiple sparse ranges
250 * on the same GPIO chip.
251 */
252 ret = gpiochip_add_pin_range(chip,
253 pinctrl_dev_get_name(pctldev),
254 0, /* offset in gpiochip */
255 pinspec.args[0],
256 pinspec.args[1]);
257
258 if (ret)
259 break;
260
261 } while (index++);
262}
263
264#else
265static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
266#endif
267
219void of_gpiochip_add(struct gpio_chip *chip) 268void of_gpiochip_add(struct gpio_chip *chip)
220{ 269{
221 if ((!chip->of_node) && (chip->dev)) 270 if ((!chip->of_node) && (chip->dev))
@@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
229 chip->of_xlate = of_gpio_simple_xlate; 278 chip->of_xlate = of_gpio_simple_xlate;
230 } 279 }
231 280
281 of_gpiochip_add_pin_range(chip);
232 of_node_get(chip->of_node); 282 of_node_get(chip->of_node);
233} 283}
234 284
235void of_gpiochip_remove(struct gpio_chip *chip) 285void of_gpiochip_remove(struct gpio_chip *chip)
236{ 286{
287 gpiochip_remove_pin_ranges(chip);
288
237 if (chip->of_node) 289 if (chip->of_node)
238 of_node_put(chip->of_node); 290 of_node_put(chip->of_node);
239} 291}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1c8d9e3380e1..58b9838801c0 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:
@@ -1123,6 +1127,7 @@ int gpiochip_remove(struct gpio_chip *chip)
1123 1127
1124 spin_lock_irqsave(&gpio_lock, flags); 1128 spin_lock_irqsave(&gpio_lock, flags);
1125 1129
1130 gpiochip_remove_pin_ranges(chip);
1126 of_gpiochip_remove(chip); 1131 of_gpiochip_remove(chip);
1127 1132
1128 for (id = chip->base; id < chip->base + chip->ngpio; id++) { 1133 for (id = chip->base; id < chip->base + chip->ngpio; id++) {
@@ -1180,6 +1185,77 @@ struct gpio_chip *gpiochip_find(void *data,
1180} 1185}
1181EXPORT_SYMBOL_GPL(gpiochip_find); 1186EXPORT_SYMBOL_GPL(gpiochip_find);
1182 1187
1188#ifdef CONFIG_PINCTRL
1189
1190/**
1191 * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
1192 * @chip: the gpiochip to add the range for
1193 * @pinctrl_name: the dev_name() of the pin controller to map to
1194 * @gpio_offset: the start offset in the current gpio_chip number space
1195 * @pin_offset: the start offset in the pin controller number space
1196 * @npins: the number of pins from the offset of each pin space (GPIO and
1197 * pin controller) to accumulate in this range
1198 */
1199int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
1200 unsigned int gpio_offset, unsigned int pin_offset,
1201 unsigned int npins)
1202{
1203 struct gpio_pin_range *pin_range;
1204 int ret;
1205
1206 pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
1207 if (!pin_range) {
1208 pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
1209 chip->label);
1210 return -ENOMEM;
1211 }
1212
1213 /* Use local offset as range ID */
1214 pin_range->range.id = gpio_offset;
1215 pin_range->range.gc = chip;
1216 pin_range->range.name = chip->label;
1217 pin_range->range.base = chip->base + gpio_offset;
1218 pin_range->range.pin_base = pin_offset;
1219 pin_range->range.npins = npins;
1220 pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name,
1221 &pin_range->range);
1222 if (IS_ERR(pin_range->pctldev)) {
1223 ret = PTR_ERR(pin_range->pctldev);
1224 pr_err("%s: GPIO chip: could not create pin range\n",
1225 chip->label);
1226 kfree(pin_range);
1227 return ret;
1228 }
1229 pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n",
1230 chip->label, gpio_offset, gpio_offset + npins - 1,
1231 pinctl_name,
1232 pin_offset, pin_offset + npins - 1);
1233
1234 list_add_tail(&pin_range->node, &chip->pin_ranges);
1235
1236 return 0;
1237}
1238EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
1239
1240/**
1241 * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings
1242 * @chip: the chip to remove all the mappings for
1243 */
1244void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
1245{
1246 struct gpio_pin_range *pin_range, *tmp;
1247
1248 list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
1249 list_del(&pin_range->node);
1250 pinctrl_remove_gpio_range(pin_range->pctldev,
1251 &pin_range->range);
1252 kfree(pin_range);
1253 }
1254}
1255EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
1256
1257#endif /* CONFIG_PINCTRL */
1258
1183/* These "optional" allocation calls help prevent drivers from stomping 1259/* These "optional" allocation calls help prevent drivers from stomping
1184 * on each other, and help provide better diagnostics in debugfs. 1260 * on each other, and help provide better diagnostics in debugfs.
1185 * They're called even less than the "set direction" calls. 1261 * They're called even less than the "set direction" calls.