On 06/13/2013 02:55 PM, Christian Ruppert wrote:

> Traditionally, GPIO ranges are based on consecutive ranges of both GPIO
> and pin numbers. This patch allows for GPIO ranges with arbitrary lists
> of pin numbers.
> 
> Signed-off-by: Christian Ruppert <christian.rupp...@abilis.com>
> ---
>  drivers/pinctrl/core.c          |   59 ++++++++++++++++++++++++++++++++------
>  include/linux/pinctrl/pinctrl.h |    4 ++-
>  2 files changed, 52 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
> index 5327f35..25bb17e 100644
> --- a/drivers/pinctrl/core.c
> +++ b/drivers/pinctrl/core.c
> @@ -280,6 +280,29 @@ static int pinctrl_register_pins(struct pinctrl_dev 
> *pctldev,
>  }
>  
>  /**
> + * gpio_to_pin() - GPIO range GPIO number to pin number translation
> + * @range: GPIO range used for the translation
> + * @gpio: gpio pin to translate to a pin number
> + *
> + * Finds the pin number for a given GPIO using the specified GPIO range
> + * as a base for translation. The distinction between linear GPIO ranges
> + * and pin list based GPIO ranges is managed correctly by this function.
> + *
> + * This function assumes the gpio is part of the specified GPIO range, use
> + * only after making sure this is the case (e.g. by calling it on the
> + * result of successful pinctrl_get_device_gpio_range calls)!
> + */
> +static inline int gpio_to_pin(struct pinctrl_gpio_range *range,
> +                             unsigned int gpio)
> +{
> +     unsigned int offset = gpio - range->base;
> +     if (range->pins)
> +             return range->pins[offset];
> +     else
> +             return range->pin_base + offset;
> +}
> +
> +/**
>   * pinctrl_match_gpio_range() - check if a certain GPIO pin is in range
>   * @pctldev: pin controller device to check
>   * @gpio: gpio pin to check taken from the global GPIO pin space
> @@ -444,8 +467,14 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev 
> *pctldev,
>       /* Loop over the ranges */
>       list_for_each_entry(range, &pctldev->gpio_ranges, node) {
>               /* Check if we're in the valid range */
> -             if (pin >= range->pin_base &&
> -                 pin < range->pin_base + range->npins) {
> +             if (range->pins) {
> +                     int a;
> +                     for (a = 0; a < range->npins; a++) {
> +                             if (range->pins[a] == pin)
> +                                     return range;
> +                     }
> +             } else if (pin >= range->pin_base &&
> +                        pin < range->pin_base + range->npins) {
>                       mutex_unlock(&pctldev->mutex);
>                       return range;
>               }
> @@ -528,7 +557,7 @@ int pinctrl_request_gpio(unsigned gpio)
>       }
>  
>       /* Convert to the pin controllers number space */
> -     pin = gpio - range->base + range->pin_base;
> +     pin = gpio_to_pin(range, gpio);
>  
>       ret = pinmux_request_gpio(pctldev, range, pin, gpio);
>  
> @@ -562,7 +591,7 @@ void pinctrl_free_gpio(unsigned gpio)
>       mutex_lock(&pctldev->mutex);
>  
>       /* Convert to the pin controllers number space */
> -     pin = gpio - range->base + range->pin_base;
> +     pin = gpio_to_pin(range, gpio);
>  
>       pinmux_free_gpio(pctldev, pin, range);
>  
> @@ -589,7 +618,7 @@ static int pinctrl_gpio_direction(unsigned gpio, bool 
> input)
>       mutex_lock(&pctldev->mutex);
>  
>       /* Convert to the pin controllers number space */
> -     pin = gpio - range->base + range->pin_base;
> +     pin = gpio_to_pin(range, gpio);
>       ret = pinmux_gpio_direction(pctldev, range, pin, input);
>  
>       mutex_unlock(&pctldev->mutex);
> @@ -1296,11 +1325,21 @@ static int pinctrl_gpioranges_show(struct seq_file 
> *s, void *what)
>  
>       /* Loop over the ranges */
>       list_for_each_entry(range, &pctldev->gpio_ranges, node) {
> -             seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
> -                        range->id, range->name,
> -                        range->base, (range->base + range->npins - 1),
> -                        range->pin_base,
> -                        (range->pin_base + range->npins - 1));
> +             if (range->pins) {
> +                     int a;
> +                     seq_printf(s, "%u: %s GPIOS [%u - %u] PINS {",
> +                             range->id, range->name,
> +                             range->base, (range->base + range->npins - 1));
> +                     for (a = 0; a < range->npins - 1; a++)
> +                             seq_printf(s, "%u, ", range->pins[a]);
> +                     seq_printf(s, "%u}\n", range->pins[a]);
> +             }
> +             else
> +                     seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
> +                             range->id, range->name,
> +                             range->base, (range->base + range->npins - 1),
> +                             range->pin_base,
> +                             (range->pin_base + range->npins - 1));
>       }
>  
>       mutex_unlock(&pctldev->mutex);
> diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
> index 2c2a9e8..176a6c1 100644
> --- a/include/linux/pinctrl/pinctrl.h
> +++ b/include/linux/pinctrl/pinctrl.h
> @@ -49,7 +49,8 @@ struct pinctrl_pin_desc {
>   * @name: a name for the chip in this range
>   * @id: an ID number for the chip in this range
>   * @base: base offset of the GPIO range
> - * @pin_base: base pin number of the GPIO range
> + * @pin_base: base pin number of the GPIO range if pins != NULL



Hi Christian,

It seems that your comment is not correct, it should be :
* @pin_base: base pin number of the GPIO range if pins == NULL

Patrice

> + * @pins: enumeration of pins in GPIO range or NULL
>   * @npins: number of pins in the GPIO range, including the base number
>   * @gc: an optional pointer to a gpio_chip
>   */
> @@ -59,6 +60,7 @@ struct pinctrl_gpio_range {
>       unsigned int id;
>       unsigned int base;
>       unsigned int pin_base;
> +     unsigned const *pins;
>       unsigned int npins;
>       struct gpio_chip *gc;
>  };



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to