diff options
author | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-06-11 20:07:32 +0000 |
---|---|---|
committer | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-06-11 20:07:32 +0000 |
commit | 4ad2c971c07d8ffb4a29a65a12bbaf7b7fef1fa0 (patch) | |
tree | c209c5a3a316be82c3988277e30307e3d648d845 | |
parent | 7feb01df1ff711fdde4bd158d74ac20a4692183c (diff) |
When reading a GPIO pin, first determine if it is programmed for input
or output and then read the value from either the GPIO[x]_READ_BACK or
GPIO[x]_OUT_VAL register. This allows to read back LED (output) states
as well as input states (buttons).
Problem noticed by Rolf Sommerhalder, fix by me.
-rw-r--r-- | sys/arch/i386/pci/glxpcib.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/sys/arch/i386/pci/glxpcib.c b/sys/arch/i386/pci/glxpcib.c index c1da8e981d5..0c2a3eb4bd0 100644 --- a/sys/arch/i386/pci/glxpcib.c +++ b/sys/arch/i386/pci/glxpcib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: glxpcib.c,v 1.6 2007/11/17 17:02:47 mbalmer Exp $ */ +/* $OpenBSD: glxpcib.c,v 1.7 2008/06/11 20:07:31 mbalmer Exp $ */ /* * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org> @@ -19,7 +19,7 @@ */ /* - * AMD CS5536 series LPC bridge also containing timer, watchdog and GPIO. + * AMD CS5536 series LPC bridge also containing timer, watchdog, and GPIO. */ #include <sys/param.h> @@ -281,7 +281,7 @@ glxpcib_wdogctl_cb(void *v, int period) wrmsr(AMD5536_MFGPT_NR, rdmsr(AMD5536_MFGPT_NR) & ~AMD5536_MFGPT0_C2_RSTEN); - return (period); + return period; } int @@ -289,13 +289,21 @@ glxpcib_gpio_pin_read(void *arg, int pin) { struct glxpcib_softc *sc = arg; u_int32_t data; - int reg; + int reg, off = 0; - reg = AMD5536_GPIO_OUT_VAL; + reg = AMD5536_GPIO_IN_EN; if (pin > 15) { pin &= 0x0f; - reg += AMD5536_GPIOH_OFFSET; + off = AMD5536_GPIOH_OFFSET; } + reg += off; + data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); + + if (data & (1 << pin)) + reg = AMD5536_GPIO_READ_BACK + off; + else + reg = AMD5536_GPIO_OUT_VAL + off; + data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); return data & 1 << pin ? GPIO_PIN_HIGH : GPIO_PIN_LOW; |