diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2013-02-15 04:33:38 +0400 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2013-03-15 16:33:39 +0400 |
commit | 63d573835f835aab4c44d0e0342cf5976fb14b35 (patch) | |
tree | d5998a6c0cb914d85c246b0464b2b7e7db959d2a /drivers/pinctrl/sh-pfc/gpio.c | |
parent | 247127f90ba1fcc234008e00e937537a89eef9ca (diff) | |
download | linux-63d573835f835aab4c44d0e0342cf5976fb14b35.tar.xz |
sh-pfc: Add support for sparse pin numbers
The PFC driver assumes that the value of the GPIO_PORTxxx enumeration
names are equal to the port number. This isn't true when the port number
space is sparse, as with the SH73A0.
Fix the issue by adding support for pin numbers ranges specified through
SoC data. When no range is specified the driver considers that the PFC
implements a single contiguous range for all pins.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/sh-pfc/gpio.c')
-rw-r--r-- | drivers/pinctrl/sh-pfc/gpio.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 32a9c7870a16..806e2dd62137 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -45,7 +45,7 @@ static int gpio_pin_request(struct gpio_chip *gc, unsigned offset) struct sh_pfc *pfc = gpio_to_pfc(gc); struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, offset); - if (pin->enum_id == 0) + if (pin == NULL || pin->enum_id == 0) return -EINVAL; return pinctrl_request_gpio(offset); @@ -127,7 +127,7 @@ static void gpio_pin_setup(struct sh_pfc_chip *chip) gc->dev = pfc->dev; gc->owner = THIS_MODULE; gc->base = 0; - gc->ngpio = pfc->info->nr_pins; + gc->ngpio = pfc->nr_pins; } /* ----------------------------------------------------------------------------- @@ -184,7 +184,7 @@ static void gpio_function_setup(struct sh_pfc_chip *chip) gc->label = pfc->info->name; gc->owner = THIS_MODULE; - gc->base = pfc->info->nr_pins; + gc->base = pfc->nr_pins; gc->ngpio = pfc->info->nr_func_gpios; } @@ -219,20 +219,43 @@ sh_pfc_add_gpiochip(struct sh_pfc *pfc, void(*setup)(struct sh_pfc_chip *)) int sh_pfc_register_gpiochip(struct sh_pfc *pfc) { + const struct pinmux_range *ranges; + struct pinmux_range def_range; struct sh_pfc_chip *chip; + unsigned int nr_ranges; + unsigned int i; int ret; + /* Register the real GPIOs chip. */ chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup); if (IS_ERR(chip)) return PTR_ERR(chip); pfc->gpio = chip; - ret = gpiochip_add_pin_range(&chip->gpio_chip, dev_name(pfc->dev), 0, 0, - chip->gpio_chip.ngpio); - if (ret < 0) - return ret; + /* Register the GPIO to pin mappings. */ + if (pfc->info->ranges == NULL) { + def_range.begin = 0; + def_range.end = pfc->info->nr_pins - 1; + ranges = &def_range; + nr_ranges = 1; + } else { + ranges = pfc->info->ranges; + nr_ranges = pfc->info->nr_ranges; + } + + for (i = 0; i < nr_ranges; ++i) { + const struct pinmux_range *range = &ranges[i]; + + ret = gpiochip_add_pin_range(&chip->gpio_chip, + dev_name(pfc->dev), + range->begin, range->begin, + range->end - range->begin + 1); + if (ret < 0) + return ret; + } + /* Register the function GPIOs chip. */ chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup); if (IS_ERR(chip)) return PTR_ERR(chip); |