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>
Šī revīzija ir iekļauta:
Christian Ruppert
2013-10-15 15:37:54 +02:00
revīziju iesūtīja Linus Walleij
vecāks c8ce878206
revīzija 586a87e6ed
7 mainīti faili ar 176 papildinājumiem un 9 dzēšanām

Parādīt failu

@@ -190,10 +190,15 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
struct of_phandle_args pinspec;
struct pinctrl_dev *pctldev;
int index = 0, ret;
const char *name;
static const char group_names_propname[] = "gpio-ranges-group-names";
struct property *group_names;
if (!np)
return;
group_names = of_find_property(np, group_names_propname, NULL);
for (;; index++) {
ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
index, &pinspec);
@@ -204,14 +209,56 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
if (!pctldev)
break;
ret = gpiochip_add_pin_range(chip,
pinctrl_dev_get_devname(pctldev),
pinspec.args[0],
pinspec.args[1],
pinspec.args[2]);
if (pinspec.args[2]) {
if (group_names) {
ret = of_property_read_string_index(np,
group_names_propname,
index, &name);
if (strlen(name)) {
pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n",
np->full_name);
break;
}
}
/* npins != 0: linear range */
ret = gpiochip_add_pin_range(chip,
pinctrl_dev_get_devname(pctldev),
pinspec.args[0],
pinspec.args[1],
pinspec.args[2]);
if (ret)
break;
} else {
/* npins == 0: special range */
if (pinspec.args[1]) {
pr_err("%s: Illegal gpio-range format.\n",
np->full_name);
break;
}
if (ret)
break;
if (!group_names) {
pr_err("%s: GPIO group range requested but no %s property.\n",
np->full_name, group_names_propname);
break;
}
ret = of_property_read_string_index(np,
group_names_propname,
index, &name);
if (ret)
break;
if (!strlen(name)) {
pr_err("%s: Group name of GPIO group range cannot be the empty string.\n",
np->full_name);
break;
}
ret = gpiochip_add_pingroup_range(chip, pctldev,
pinspec.args[0], name);
if (ret)
break;
}
}
}

Parādīt failu

@@ -1319,6 +1319,53 @@ EXPORT_SYMBOL_GPL(gpiochip_find);
#ifdef CONFIG_PINCTRL
/**
* gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping
* @chip: the gpiochip to add the range for
* @pinctrl: the dev_name() of the pin controller to map to
* @gpio_offset: the start offset in the current gpio_chip number space
* @pin_group: name of the pin group inside the pin controller
*/
int gpiochip_add_pingroup_range(struct gpio_chip *chip,
struct pinctrl_dev *pctldev,
unsigned int gpio_offset, const char *pin_group)
{
struct gpio_pin_range *pin_range;
int ret;
pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
if (!pin_range) {
pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
chip->label);
return -ENOMEM;
}
/* Use local offset as range ID */
pin_range->range.id = gpio_offset;
pin_range->range.gc = chip;
pin_range->range.name = chip->label;
pin_range->range.base = chip->base + gpio_offset;
pin_range->pctldev = pctldev;
ret = pinctrl_get_group_pins(pctldev, pin_group,
&pin_range->range.pins,
&pin_range->range.npins);
if (ret < 0)
return ret;
pinctrl_add_gpio_range(pctldev, &pin_range->range);
pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n",
chip->label, gpio_offset,
gpio_offset + pin_range->range.npins - 1,
pinctrl_dev_get_devname(pctldev), pin_group);
list_add_tail(&pin_range->node, &chip->pin_ranges);
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
/**
* gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
* @chip: the gpiochip to add the range for