From: Daniel Krueger Date: Mon, 7 Apr 2014 12:20:32 +0000 (+0200) Subject: gpio-sch: set output level after configuration of direction X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=1e0d9823178f8793dec7d1e9cd08f9bee5123871;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git 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 Signed-off-by: Alexander Stein Signed-off-by: Linus Walleij --- diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 5af65719b95d..a9b1cd16c848 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -97,8 +97,6 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc, u8 curr_dirs; unsigned short offset, bit; - sch_gpio_core_set(gc, gpio_num, val); - spin_lock(&gpio_lock); 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); 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; } @@ -178,8 +187,6 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc, u8 curr_dirs; unsigned short offset, bit; - sch_gpio_resume_set(gc, gpio_num, val); - offset = RGIO + 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); 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; }