Patchwork qe_lib: Set gpio data before changing the direction to output

login
register
mail settings
Submitter Michael Barkowski
Date Aug. 18, 2009, 8:59 p.m.
Message ID <4A8B164E.6030704@ruggedcom.com>
Download mbox | patch
Permalink /patch/31587/
State Superseded
Delegated to: Kumar Gala
Headers show

Comments

Michael Barkowski - Aug. 18, 2009, 8:59 p.m.
This avoids having a short glitch if the desired initial value is not
the same as what was previously in the data register.

Signed-off-by: Michael Barkowski <michaelbarkowski@ruggedcom.com>
---
I can't think of a reason not to do this.  The data register has no
effect except when the pin is configured as an output, right?

Please enlighten me if this is not correct. The behaviour I see gels
with my thinking, but there may be a case I haven't thought of.

 arch/powerpc/sysdev/qe_lib/gpio.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
Michael Barkowski - Aug. 18, 2009, 9:23 p.m.
Timur Tabi wrote:
> Michael Barkowski wrote:
> 
>> diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
>> index 3485288..e7bf136 100644
>> --- a/arch/powerpc/sysdev/qe_lib/gpio.c
>> +++ b/arch/powerpc/sysdev/qe_lib/gpio.c
>> @@ -107,12 +107,11 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
>>  
>>  	spin_lock_irqsave(&qe_gc->lock, flags);
>>  
>> +	qe_gpio_set(gc, gpio, val);
> 
> qe_gpio_set already calls spin_lock_irqsave(), so you'll have nested spinlocks, which will lock up on SMP.
> 
> Let me guess, you didn't test this on a dual-core system?

That is correct.  See v2 and please test, YMMV, etc

Patch

diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
index 3485288..e7bf136 100644
--- a/arch/powerpc/sysdev/qe_lib/gpio.c
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -107,12 +107,11 @@  static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 
 	spin_lock_irqsave(&qe_gc->lock, flags);
 
+	qe_gpio_set(gc, gpio, val);
 	__par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0);
 
 	spin_unlock_irqrestore(&qe_gc->lock, flags);
 
-	qe_gpio_set(gc, gpio, val);
-
 	return 0;
 }