summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/sh-pfc/gpio.c
diff options
context:
space:
mode:
authorLaurent Pinchart2012-11-29 13:03:53 +0100
committerLaurent Pinchart2013-03-15 13:33:37 +0100
commit2119f7c9afaf4c5fe88e9ffec1f34c5bc6b02f78 (patch)
tree5532cf79efc3378e5642784371c530a9b20458fa /drivers/pinctrl/sh-pfc/gpio.c
parentsh-pfc: Make struct pinmux_gpio enum_id field const (diff)
downloadkernel-qcow2-linux-2119f7c9afaf4c5fe88e9ffec1f34c5bc6b02f78.tar.gz
kernel-qcow2-linux-2119f7c9afaf4c5fe88e9ffec1f34c5bc6b02f78.tar.xz
kernel-qcow2-linux-2119f7c9afaf4c5fe88e9ffec1f34c5bc6b02f78.zip
sh-pfc: Shrink the pinctrl GPIO range to include real GPIOs only
As a step towards GPIO function removal, shorten the GPIO range registered with the pinctrl core. Function GPIOs are now handled in the GPIO handlers directly instead of going through the pinctrl API. 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.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index f46f06997b99..80a50d8a50e7 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -38,12 +38,51 @@ static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)
static int sh_gpio_request(struct gpio_chip *gc, unsigned offset)
{
- return pinctrl_request_gpio(offset);
+ struct sh_pfc *pfc = gpio_to_pfc(gc);
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (offset < pfc->info->nr_pins)
+ return pinctrl_request_gpio(offset);
+
+ pr_notice_once("Use of GPIO API for function requests is deprecated, convert to pinctrl\n");
+
+ spin_lock_irqsave(&pfc->lock, flags);
+
+ if (!sh_pfc_gpio_is_function(pfc, offset))
+ goto done;
+
+ if (sh_pfc_config_gpio(pfc, offset, PINMUX_TYPE_FUNCTION,
+ GPIO_CFG_DRYRUN))
+ goto done;
+
+ if (sh_pfc_config_gpio(pfc, offset, PINMUX_TYPE_FUNCTION,
+ GPIO_CFG_REQ))
+ goto done;
+
+ ret = 0;
+
+done:
+ spin_unlock_irqrestore(&pfc->lock, flags);
+ return ret;
}
static void sh_gpio_free(struct gpio_chip *gc, unsigned offset)
{
- pinctrl_free_gpio(offset);
+ struct sh_pfc *pfc = gpio_to_pfc(gc);
+ unsigned long flags;
+ int pinmux_type;
+
+ if (offset < pfc->info->nr_pins)
+ return pinctrl_free_gpio(offset);
+
+ spin_lock_irqsave(&pfc->lock, flags);
+
+ pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE;
+
+ sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE);
+
+ spin_unlock_irqrestore(&pfc->lock, flags);
}
static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value)
@@ -70,12 +109,26 @@ static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio)
static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
+ struct sh_pfc *pfc = gpio_to_pfc(gc);
+
+ if (offset >= pfc->info->nr_pins) {
+ /* Function GPIOs can only be requested, never configured. */
+ return -EINVAL;
+ }
+
return pinctrl_gpio_direction_input(offset);
}
static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
+ struct sh_pfc *pfc = gpio_to_pfc(gc);
+
+ if (offset >= pfc->info->nr_pins) {
+ /* Function GPIOs can only be requested, never configured. */
+ return -EINVAL;
+ }
+
sh_gpio_set_value(gpio_to_pfc(gc), offset, value);
return pinctrl_gpio_direction_output(offset);