diff options
| author | Chuanhong Guo <gch981213@gmail.com> | 2020-03-15 20:13:37 +0800 | 
|---|---|---|
| committer | Bartosz Golaszewski <bgolaszewski@baylibre.com> | 2020-03-25 09:50:45 +0100 | 
| commit | d19d2de61fb131abcd29f7c61d3f168f687bfd6e (patch) | |
| tree | fda8cb7a01b6d9df22d36c5c8e5b4c1a6feb5dc7 /drivers/gpio/gpio-mmio.c | |
| parent | d1ee7e1f5c9191afb69ce46cc7752e4257340a31 (diff) | |
gpio: mmio: introduce BGPIOF_NO_SET_ON_INPUT
Some gpio controllers ignores pin value writing when that pin is
configured as input mode. As a result, bgpio_dir_out should set
pin to output before configuring pin values or gpio pin values
can't be set up properly.
Introduce two variants of bgpio_dir_out: bgpio_dir_out_val_first
and bgpio_dir_out_dir_first, and assign direction_output according
to a new flag: BGPIOF_NO_SET_ON_INPUT.
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
Tested-by: René van Dorst <opensource@vdorst.com>
Reviewed-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Diffstat (limited to 'drivers/gpio/gpio-mmio.c')
| -rw-r--r-- | drivers/gpio/gpio-mmio.c | 23 | 
1 files changed, 19 insertions, 4 deletions
| diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index f729e3e9e983..b778f33cc6af 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -389,12 +389,10 @@ static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)  	return GPIO_LINE_DIRECTION_IN;  } -static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  {  	unsigned long flags; -	gc->set(gc, gpio, val); -  	spin_lock_irqsave(&gc->bgpio_lock, flags);  	gc->bgpio_dir |= bgpio_line2mask(gc, gpio); @@ -405,7 +403,21 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  		gc->write_reg(gc->reg_dir_out, gc->bgpio_dir);  	spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} +static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, +				   int val) +{ +	bgpio_dir_out(gc, gpio, val); +	gc->set(gc, gpio, val); +	return 0; +} + +static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, +				   int val) +{ +	gc->set(gc, gpio, val); +	bgpio_dir_out(gc, gpio, val);  	return 0;  } @@ -538,7 +550,10 @@ static int bgpio_setup_direction(struct gpio_chip *gc,  	if (dirout || dirin) {  		gc->reg_dir_out = dirout;  		gc->reg_dir_in = dirin; -		gc->direction_output = bgpio_dir_out; +		if (flags & BGPIOF_NO_SET_ON_INPUT) +			gc->direction_output = bgpio_dir_out_dir_first; +		else +			gc->direction_output = bgpio_dir_out_val_first;  		gc->direction_input = bgpio_dir_in;  		gc->get_direction = bgpio_get_dir;  	} else { | 
