@@ -95,7 +95,7 @@ static bool sh_pfc_gpio_is_pin(struct sh_pfc *pfc, unsigned int gpio)
(pfc->info->gpios[gpio].enum_id != 0);
}
-static bool sh_pfc_gpio_is_function(struct sh_pfc *pfc, unsigned int gpio)
+bool sh_pfc_gpio_is_function(struct sh_pfc *pfc, unsigned int gpio)
{
return (gpio >= pfc->info->nr_pins) && (gpio < pfc->info->nr_gpios) &&
(pfc->info->gpios[gpio].enum_id != 0);
@@ -47,6 +47,7 @@ void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
unsigned long value);
int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio,
struct pinmux_data_reg **drp, int *bitp);
+bool sh_pfc_gpio_is_function(struct sh_pfc *pfc, unsigned int gpio);
int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
pinmux_enum_t *enum_idp);
int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
@@ -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);
@@ -116,21 +116,6 @@ static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func,
{
}
-static int sh_pfc_config_function(struct sh_pfc *pfc, unsigned offset)
-{
- if (sh_pfc_config_gpio(pfc, offset,
- PINMUX_TYPE_FUNCTION,
- GPIO_CFG_DRYRUN) != 0)
- return -EINVAL;
-
- if (sh_pfc_config_gpio(pfc, offset,
- PINMUX_TYPE_FUNCTION,
- GPIO_CFG_REQ) != 0)
- return -EINVAL;
-
- return 0;
-}
-
static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset,
int new_type)
{
@@ -198,19 +183,11 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE;
switch (pinmux_type) {
- case PINMUX_TYPE_FUNCTION:
- pr_notice_once("Use of GPIO API for function requests is "
- "deprecated, convert to pinctrl\n");
- /* handle for now */
- ret = sh_pfc_config_function(pfc, offset);
- if (unlikely(ret < 0))
- goto err;
-
- break;
case PINMUX_TYPE_GPIO:
case PINMUX_TYPE_INPUT:
case PINMUX_TYPE_OUTPUT:
break;
+ case PINMUX_TYPE_FUNCTION:
default:
pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
ret = -ENOTSUPP;
@@ -400,7 +377,7 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
pmx->range.name = DRV_NAME,
pmx->range.id = 0;
- pmx->range.npins = pfc->info->nr_gpios;
+ pmx->range.npins = pfc->info->nr_pins;
pmx->range.base = 0;
pmx->range.pin_base = 0;