gpio-sch: set output level after configuration of direction
authorDaniel Krueger <daniel.krueger@systec-electronic.com>
Mon, 7 Apr 2014 12:20:32 +0000 (14:20 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 28 Apr 2014 19:35:08 +0000 (12:35 -0700)
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>
drivers/gpio/gpio-sch.c

index 5af65719b95dafad605fb8f1f733ead623b78bf5..a9b1cd16c848317e887523363516bb465788180c 100644 (file)
@@ -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;
 }