gpio-sch: set output level after configuration of direction

According to the datasheet, writing to the level register has no effect
when GPIO is programmed as input. Actually the the level register is
read-only when configured as input. Thus presetting the output level
before switching to output is _NOT_ possible. Any writes are lost!
Hence we set the level after configuring the GPIO as output.
But we cannot prevent a short low pulse if direction is set to high and
an external  pull-up is connected.

Signed-off-by: Daniel Krueger <daniel.krueger@systec-electronic.com>
Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Daniel Krueger 2014-04-07 14:20:32 +02:00 committed by Linus Walleij
parent 9ea8d8102b
commit 1e0d982317
1 changed files with 22 additions and 4 deletions

View File

@ -97,8 +97,6 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
u8 curr_dirs; u8 curr_dirs;
unsigned short offset, bit; unsigned short offset, bit;
sch_gpio_core_set(gc, gpio_num, val);
spin_lock(&gpio_lock); spin_lock(&gpio_lock);
offset = CGIO + gpio_num / 8; offset = CGIO + gpio_num / 8;
@ -109,6 +107,17 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
outb(curr_dirs & ~(1 << bit), gpio_ba + offset); outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
spin_unlock(&gpio_lock); spin_unlock(&gpio_lock);
/*
* according to the datasheet, writing to the level register has no
* effect when GPIO is programmed as input.
* Actually the the level register is read-only when configured as input.
* Thus presetting the output level before switching to output is _NOT_ possible.
* Hence we set the level after configuring the GPIO as output.
* But we cannot prevent a short low pulse if direction is set to high
* and an external pull-up is connected.
*/
sch_gpio_core_set(gc, gpio_num, val);
return 0; return 0;
} }
@ -178,8 +187,6 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
u8 curr_dirs; u8 curr_dirs;
unsigned short offset, bit; unsigned short offset, bit;
sch_gpio_resume_set(gc, gpio_num, val);
offset = RGIO + gpio_num / 8; offset = RGIO + gpio_num / 8;
bit = gpio_num % 8; bit = gpio_num % 8;
@ -190,6 +197,17 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
outb(curr_dirs & ~(1 << bit), gpio_ba + offset); outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
spin_unlock(&gpio_lock); spin_unlock(&gpio_lock);
/*
* according to the datasheet, writing to the level register has no
* effect when GPIO is programmed as input.
* Actually the the level register is read-only when configured as input.
* Thus presetting the output level before switching to output is _NOT_ possible.
* Hence we set the level after configuring the GPIO as output.
* But we cannot prevent a short low pulse if direction is set to high
* and an external pull-up is connected.
*/
sch_gpio_resume_set(gc, gpio_num, val);
return 0; return 0;
} }