gpio: Avoid glitching 'out'-direction GPIOs
Change-Id: I42dafd3235d13ec57f7b15e043bc3fe82fdb4665
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/libopenbmc_intf/gpio.c b/libopenbmc_intf/gpio.c
index e48eff4..0dfb260 100644
--- a/libopenbmc_intf/gpio.c
+++ b/libopenbmc_intf/gpio.c
@@ -149,18 +149,36 @@
}
}
const char* file = "edge";
- if (strcmp(gpio->direction,"in")==0 || strcmp(gpio->direction,"out")==0)
+ const char* direction = gpio->direction;
+ if (strcmp(direction, "in") == 0)
{
file = "direction";
}
+ else if (strcmp(direction, "out") == 0)
+ {
+ file = "direction";
+
+ // Read current value, so we can set 'high' or 'low'.
+ // Setting direction directly to 'out' is the same as
+ // setting to 'low' which can change the value in the
+ // GPIO.
+ uint8_t value = 0;
+ rc = gpio_open(gpio);
+ if (rc) break;
+ rc = gpio_read(gpio, &value);
+ if (rc) break;
+ gpio_close(gpio);
+
+ direction = (value ? "high" : "low");
+ }
sprintf(dev,"%s/gpio%d/%s",gpio->dev,gpio->num,file);
fd = open(dev,O_WRONLY);
if (fd == GPIO_ERROR) {
rc = GPIO_WRITE_ERROR;
break;
}
- rc = write(fd,gpio->direction,strlen(gpio->direction));
- if (rc != strlen(gpio->direction)) {
+ rc = write(fd,direction,strlen(direction));
+ if (rc != strlen(direction)) {
rc = GPIO_WRITE_ERROR;
break;
}