aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib-of.c
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 /drivers/gpio/gpiolib-of.c
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>
Diffstat (limited to 'drivers/gpio/gpiolib-of.c')
-rw-r--r--drivers/gpio/gpiolib-of.c56
1 files changed, 56 insertions, 0 deletions
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}