gpiolib: separation of pin concerns

The fact that of_gpiochip_add_pin_range() and
gpiochip_add_pin_range() share too much code is fragile and
will invariably mean that bugs need to be fixed in two places
instead of one.

So separate the concerns of gpiolib.c and gpiolib-of.c and
have the latter call the former as back-end. This is necessary
also when going forward with other device descriptions such
as ACPI.

This is done by:

- Adding a return code to gpiochip_add_pin_range() so we can
  reliably check whether this succeeds.

- Get rid of the custom of_pinctrl_add_gpio_range() from
  pinctrl. Instead create of_pinctrl_get() to just retrive the
  pin controller per se from an OF node. This composite
  function was just begging to be deleted, it was way to
  purpose-specific.

- Use pinctrl_dev_get_name() to get the name of the retrieved
  pin controller and use that to call back into the generic
  gpiochip_add_pin_range().

Now the pin range is only allocated and tied to a pin
controller from the core implementation in gpiolib.c.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Linus Walleij 2012-11-06 16:03:35 +01:00
parent 9ef0d6f762
commit 1e63d7b936
6 changed files with 20 additions and 28 deletions

View file

@ -221,8 +221,8 @@ EXPORT_SYMBOL(of_mm_gpiochip_add);
static void of_gpiochip_add_pin_range(struct gpio_chip *chip) static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{ {
struct device_node *np = chip->of_node; struct device_node *np = chip->of_node;
struct gpio_pin_range *pin_range;
struct of_phandle_args pinspec; struct of_phandle_args pinspec;
struct pinctrl_dev *pctldev;
int index = 0, ret; int index = 0, ret;
if (!np) if (!np)
@ -234,22 +234,17 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
if (ret) if (ret)
break; break;
pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), pctldev = of_pinctrl_get(pinspec.np);
GFP_KERNEL); if (!pctldev)
if (!pin_range) {
pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
chip->label);
break; break;
}
pin_range->range.name = chip->label; ret = gpiochip_add_pin_range(chip,
pin_range->range.base = chip->base; pinctrl_dev_get_name(pctldev),
pin_range->range.pin_base = pinspec.args[0]; pinspec.args[0],
pin_range->range.npins = pinspec.args[1]; pinspec.args[1]);
pin_range->pctldev = of_pinctrl_add_gpio_range(pinspec.np,
&pin_range->range);
list_add_tail(&pin_range->node, &chip->pin_ranges); if (ret)
break;
} while (index++); } while (index++);
} }

View file

@ -1187,7 +1187,7 @@ EXPORT_SYMBOL_GPL(gpiochip_find);
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins) unsigned int pin_base, unsigned int npins)
{ {
struct gpio_pin_range *pin_range; struct gpio_pin_range *pin_range;
@ -1196,7 +1196,7 @@ void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
if (!pin_range) { if (!pin_range) {
pr_err("%s: GPIO chip: failed to allocate pin ranges\n", pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
chip->label); chip->label);
return; return -ENOMEM;
} }
pin_range->range.name = chip->label; pin_range->range.name = chip->label;
@ -1207,6 +1207,8 @@ void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
&pin_range->range); &pin_range->range);
list_add_tail(&pin_range->node, &chip->pin_ranges); list_add_tail(&pin_range->node, &chip->pin_ranges);
return 0;
} }
EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);

View file

@ -106,8 +106,7 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
return NULL; return NULL;
} }
struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np, struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
struct pinctrl_gpio_range *range)
{ {
struct pinctrl_dev *pctldev; struct pinctrl_dev *pctldev;
@ -115,7 +114,6 @@ struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
if (!pctldev) if (!pctldev)
return NULL; return NULL;
pinctrl_add_gpio_range(pctldev, range);
return pctldev; return pctldev;
} }

View file

@ -63,7 +63,7 @@ struct gpio_pin_range {
struct pinctrl_gpio_range range; struct pinctrl_gpio_range range;
}; };
void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins); unsigned int pin_base, unsigned int npins);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip); void gpiochip_remove_pin_ranges(struct gpio_chip *chip);

View file

@ -233,7 +233,7 @@ static inline int irq_to_gpio(unsigned irq)
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
static inline void static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins) unsigned int pin_base, unsigned int npins)
{ {

View file

@ -141,16 +141,13 @@ extern struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
struct pinctrl_gpio_range *range); struct pinctrl_gpio_range *range);
#ifdef CONFIG_OF #ifdef CONFIG_OF
extern struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np, extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
struct pinctrl_gpio_range *range);
#else #else
static inline static inline
struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np, struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
struct pinctrl_gpio_range *range)
{ {
return NULL; return NULL;
} }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev); extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);