summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Balmer <mbalmer@cvs.openbsd.org>2008-06-11 20:07:32 +0000
committerMarc Balmer <mbalmer@cvs.openbsd.org>2008-06-11 20:07:32 +0000
commit4ad2c971c07d8ffb4a29a65a12bbaf7b7fef1fa0 (patch)
treec209c5a3a316be82c3988277e30307e3d648d845
parent7feb01df1ff711fdde4bd158d74ac20a4692183c (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.c20
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;