From 1e0d9823178f8793dec7d1e9cd08f9bee5123871 Mon Sep 17 00:00:00 2001 From: Daniel Krueger Date: Mon, 7 Apr 2014 14:20:32 +0200 Subject: [PATCH] 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 --- drivers/gpio/gpio-sch.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) 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; } -- 2.20.1