summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/sh-pfc/gpio.c
diff options
context:
space:
mode:
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);