diff options
| author | Linus Walleij <linus.walleij@linaro.org> | 2025-02-19 22:04:33 +0100 | 
|---|---|---|
| committer | Bartosz Golaszewski <bartosz.golaszewski@linaro.org> | 2025-02-24 20:49:20 +0100 | 
| commit | 2145ba374069ee8edc9d29c2a6b56fe4a28a6e2d (patch) | |
| tree | 4071a3ab0750bfeb3893ce833062b3759bb26282 /drivers/gpio/gpio-mmio.c | |
| parent | 45af02f06f6943d73cf9309fd2a63a908b587f57 (diff) | |
gpio: mmio: Add flag for calling pinctrl back-end
It turns out that with this flag we can switch over an entire
driver to use gpio-mmio instead of a bunch of custom code,
also providing get/set_multiple() to it in the process, so it
seems like a reasonable feature to add.
The generic pin control backend requires us to call the
gpiochip_generic_request(), gpiochip_generic_free(),
pinctrl_gpio_direction_output() and pinctrl_gpio_direction_input()
callbacks, so if the new flag for a pin control back-end
is set, we make sure these functions get called as
expected.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20250219-vf610-mmio-v3-1-588b64f0b689@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-mmio.c')
| -rw-r--r-- | drivers/gpio/gpio-mmio.c | 37 | 
1 files changed, 29 insertions, 8 deletions
| diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index d89e78f0ead3..4841e4ebe7a6 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -49,6 +49,7 @@ o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`  #include <linux/log2.h>  #include <linux/mod_devicetable.h>  #include <linux/module.h> +#include <linux/pinctrl/consumer.h>  #include <linux/platform_device.h>  #include <linux/property.h>  #include <linux/slab.h> @@ -323,9 +324,20 @@ static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,  		gc->write_reg(gc->reg_clr, clear_mask);  } +static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_out) +{ +	if (!gc->bgpio_pinctrl) +		return 0; + +	if (dir_out) +		return pinctrl_gpio_direction_output(gc, gpio); +	else +		return pinctrl_gpio_direction_input(gc, gpio); +} +  static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)  { -	return 0; +	return bgpio_dir_return(gc, gpio, false);  }  static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, @@ -339,7 +351,7 @@ static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,  {  	gc->set(gc, gpio, val); -	return 0; +	return bgpio_dir_return(gc, gpio, true);  }  static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) @@ -357,7 +369,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)  	raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); -	return 0; +	return bgpio_dir_return(gc, gpio, false);  }  static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) @@ -403,7 +415,7 @@ static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio,  {  	bgpio_dir_out(gc, gpio, val);  	gc->set(gc, gpio, val); -	return 0; +	return bgpio_dir_return(gc, gpio, true);  }  static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, @@ -411,7 +423,7 @@ static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio,  {  	gc->set(gc, gpio, val);  	bgpio_dir_out(gc, gpio, val); -	return 0; +	return bgpio_dir_return(gc, gpio, true);  }  static int bgpio_setup_accessors(struct device *dev, @@ -562,10 +574,13 @@ static int bgpio_setup_direction(struct gpio_chip *gc,  static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)  { -	if (gpio_pin < chip->ngpio) -		return 0; +	if (gpio_pin >= chip->ngpio) +		return -EINVAL; -	return -EINVAL; +	if (chip->bgpio_pinctrl) +		return gpiochip_generic_request(chip, gpio_pin); + +	return 0;  }  /** @@ -632,6 +647,12 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,  	if (ret)  		return ret; +	if (flags & BGPIOF_PINCTRL_BACKEND) { +		gc->bgpio_pinctrl = true; +		/* Currently this callback is only used for pincontrol */ +		gc->free = gpiochip_generic_free; +	} +  	gc->bgpio_data = gc->read_reg(gc->reg_dat);  	if (gc->set == bgpio_set_set &&  			!(flags & BGPIOF_UNREADABLE_REG_SET)) | 
