Skip to content

Commit

Permalink
pinctrl: Allow configuration of pins from gpiolib based drivers
Browse files Browse the repository at this point in the history
When a GPIO driver is backed by a pinctrl driver the GPIO driver
sometimes needs to call the pinctrl driver to configure certain things,
like whether the pin is used as input or output. In addition to this
there are other configurations applicable to GPIOs such as setting
debounce time of the GPIO.

To support this we introduce a new function pinctrl_gpio_set_config()
that can be used by gpiolib based driver to pass configuration requests
to the backing pinctrl driver.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Mika Westerberg authored and Linus Walleij committed Jan 26, 2017
1 parent 58957d2 commit 15381bc
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 0 deletions.
29 changes: 29 additions & 0 deletions drivers/pinctrl/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,35 @@ int pinctrl_gpio_direction_output(unsigned gpio)
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);

/**
* pinctrl_gpio_set_config() - Apply config to given GPIO pin
* @gpio: the GPIO pin number from the GPIO subsystem number space
* @config: the configuration to apply to the GPIO
*
* This function should *ONLY* be used from gpiolib-based GPIO drivers, if
* they need to call the underlying pin controller to change GPIO config
* (for example set debounce time).
*/
int pinctrl_gpio_set_config(unsigned gpio, unsigned long config)
{
unsigned long configs[] = { config };
struct pinctrl_gpio_range *range;
struct pinctrl_dev *pctldev;
int ret, pin;

ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret)
return ret;

mutex_lock(&pctldev->mutex);
pin = gpio_to_pin(range, gpio);
ret = pinconf_set_config(pctldev, pin, configs, ARRAY_SIZE(configs));
mutex_unlock(&pctldev->mutex);

return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_set_config);

static struct pinctrl_state *find_state(struct pinctrl *p,
const char *name)
{
Expand Down
12 changes: 12 additions & 0 deletions drivers/pinctrl/pinconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,18 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0;
}

int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs)
{
const struct pinconf_ops *ops;

ops = pctldev->desc->confops;
if (!ops)
return -ENOTSUPP;

return ops->pin_config_set(pctldev, pin, configs, nconfigs);
}

#ifdef CONFIG_DEBUG_FS

static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,
Expand Down
9 changes: 9 additions & 0 deletions drivers/pinctrl/pinconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ int pinconf_map_to_setting(struct pinctrl_map const *map,
void pinconf_free_setting(struct pinctrl_setting const *setting);
int pinconf_apply_setting(struct pinctrl_setting const *setting);

int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs);

/*
* You will only be interested in these if you're using PINCONF
* so don't supply any stubs for these.
Expand Down Expand Up @@ -56,6 +59,12 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0;
}

static inline int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs)
{
return -ENOTSUPP;
}

#endif

#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)
Expand Down
6 changes: 6 additions & 0 deletions include/linux/pinctrl/consumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern int pinctrl_request_gpio(unsigned gpio);
extern void pinctrl_free_gpio(unsigned gpio);
extern int pinctrl_gpio_direction_input(unsigned gpio);
extern int pinctrl_gpio_direction_output(unsigned gpio);
extern int pinctrl_gpio_set_config(unsigned gpio, unsigned long config);

extern struct pinctrl * __must_check pinctrl_get(struct device *dev);
extern void pinctrl_put(struct pinctrl *p);
Expand Down Expand Up @@ -80,6 +81,11 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio)
return 0;
}

static inline int pinctrl_gpio_set_config(unsigned gpio, unsigned long config)
{
return 0;
}

static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
{
return NULL;
Expand Down

0 comments on commit 15381bc

Please sign in to comment.