summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2004-06-05 15:06:23 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2004-06-05 15:06:23 +0000
commit42f49c9281dfbaea39b28fca5d254ff5cfa7f7b9 (patch)
treee4dde5abe31c30292314c9a0d9523ffa2dfa0e82 /sys/arch
parentf614b159c3bebabad248000917a61df53cf95ffd (diff)
GPIO support for AMD Elan SC520 found on Soekris net45x1 boards.
Test and ok markus@.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/conf/GENERIC3
-rw-r--r--sys/arch/i386/conf/files.i3864
-rw-r--r--sys/arch/i386/pci/elan520.c101
-rw-r--r--sys/arch/i386/pci/elan520reg.h4
4 files changed, 107 insertions, 5 deletions
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index d6b4fb0c24a..d3ae3db56c5 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.367 2004/06/03 18:28:02 grange Exp $
+# $OpenBSD: GENERIC,v 1.368 2004/06/05 15:06:22 grange Exp $
#
# GENERIC -- everything that's currently supported
#
@@ -66,6 +66,7 @@ gpio* at gscpcib?
# power management and other environmental stuff
#amdpm* at pci? dev ? function ? # AMD768MPX
elansc* at pci? dev ? function ? # AMD Elan SC520 System Controller
+gpio* at elansc?
geodesc* at pci? dev ? function ? # Geode SC1100/SCx200 IAOC
# National Semiconductor LM7[89] and compatible hardware monitors
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index 71623e52636..02b5d8ee2c5 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.121 2004/06/03 18:22:21 grange Exp $
+# $OpenBSD: files.i386,v 1.122 2004/06/05 15:06:22 grange Exp $
#
# new style config file for i386 architecture
#
@@ -109,7 +109,7 @@ attach pchb at pci
file arch/i386/pci/pchb.c pchb
# AMD Elan SC520 System Controller (PCI-Host bridge)
-device elansc
+device elansc: gpiobus
attach elansc at pci
file arch/i386/pci/elan520.c elansc
diff --git a/sys/arch/i386/pci/elan520.c b/sys/arch/i386/pci/elan520.c
index 08cba992813..ea16605365b 100644
--- a/sys/arch/i386/pci/elan520.c
+++ b/sys/arch/i386/pci/elan520.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: elan520.c,v 1.7 2004/06/04 18:56:03 grange Exp $ */
+/* $OpenBSD: elan520.c,v 1.8 2004/06/05 15:06:22 grange Exp $ */
/* $NetBSD: elan520.c,v 1.4 2002/10/02 05:47:15 thorpej Exp $ */
/*-
@@ -46,6 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
+#include <sys/gpio.h>
#include <sys/sysctl.h>
#include <machine/bus.h>
@@ -53,12 +54,18 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <dev/gpio/gpiovar.h>
+
#include <arch/i386/pci/elan520reg.h>
struct elansc_softc {
struct device sc_dev;
bus_space_tag_t sc_memt;
bus_space_handle_t sc_memh;
+
+ /* GPIO interface */
+ struct gpio_chipset_tag sc_gpio_gc;
+ gpio_pin_t sc_gpio_pins[ELANSC_PIO_NPINS];
} *elansc;
int elansc_match(struct device *, void *, void *);
@@ -71,6 +78,10 @@ void elansc_wdogctl(struct elansc_softc *, int, uint16_t);
#define elansc_wdogctl_write(sc, val) elansc_wdogctl(sc, 0, val)
int elansc_wdogctl_cb(void *, int);
+int elansc_gpio_pin_read(void *, int);
+void elansc_gpio_pin_write(void *, int, int);
+void elansc_gpio_pin_ctl(void *, int, int);
+
struct cfattach elansc_ca = {
sizeof(struct elansc_softc), elansc_match, elansc_attach
};
@@ -105,8 +116,12 @@ elansc_attach(struct device *parent, struct device *self, void *aux)
{
struct elansc_softc *sc = (void *) self;
struct pci_attach_args *pa = aux;
+ struct gpiobus_attach_args gba;
uint16_t rev;
uint8_t ressta, cpuctl;
+ int pin;
+ int reg, shift;
+ u_int16_t data;
sc->sc_memt = pa->pa_memt;
if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, NBPG, 0,
@@ -145,6 +160,40 @@ elansc_attach(struct device *parent, struct device *self, void *aux)
elansc = sc;
cpu_cpuspeed = elansc_cpuspeed;
cpu_setperf = elansc_setperf;
+
+ /* Initialize GPIO pins array */
+ for (pin = 0; pin < ELANSC_PIO_NPINS; pin++) {
+ sc->sc_gpio_pins[pin].pin_num = pin;
+ sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT |
+ GPIO_PIN_OUTPUT;
+
+ /* Read initial state */
+ reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
+ shift = pin % 16;
+ data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
+ if ((data & (1 << shift)) == 0)
+ sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT;
+ else
+ sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT;
+ if (elansc_gpio_pin_read(sc, pin) == 0)
+ sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
+ else
+ sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
+ }
+
+ /* Create controller tag */
+ sc->sc_gpio_gc.gp_cookie = sc;
+ sc->sc_gpio_gc.gp_pin_read = elansc_gpio_pin_read;
+ sc->sc_gpio_gc.gp_pin_write = elansc_gpio_pin_write;
+ sc->sc_gpio_gc.gp_pin_ctl = elansc_gpio_pin_ctl;
+
+ gba.gba_name = "gpio";
+ gba.gba_gc = &sc->sc_gpio_gc;
+ gba.gba_pins = sc->sc_gpio_pins;
+ gba.gba_npins = ELANSC_PIO_NPINS;
+
+ /* Attach GPIO framework */
+ config_found(&sc->sc_dev, &gba, gpiobus_print);
}
void
@@ -253,3 +302,53 @@ elansc_setperf(int level)
return (0);
}
+
+int
+elansc_gpio_pin_read(void *arg, int pin)
+{
+ struct elansc_softc *sc = arg;
+ int reg, shift;
+ u_int16_t data;
+
+ reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16);
+ shift = pin % 16;
+ data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
+
+ return ((data >> shift) & 0x1);
+}
+
+void
+elansc_gpio_pin_write(void *arg, int pin, int value)
+{
+ struct elansc_softc *sc = arg;
+ int reg, shift;
+ u_int16_t data;
+
+ reg = (pin < 16 ? MMCR_PIODATA15_0 : MMCR_PIODATA31_16);
+ shift = pin % 16;
+ data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
+ if (value == 0)
+ data &= ~(1 << shift);
+ else if (value == 1)
+ data |= (1 << shift);
+
+ bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data);
+}
+
+void
+elansc_gpio_pin_ctl(void *arg, int pin, int flags)
+{
+ struct elansc_softc *sc = arg;
+ int reg, shift;
+ u_int16_t data;
+
+ reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16);
+ shift = pin % 16;
+ data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg);
+ if (flags & GPIO_PIN_INPUT)
+ data &= ~(1 << shift);
+ if (flags & GPIO_PIN_OUTPUT)
+ data |= (1 << shift);
+
+ bus_space_write_2(sc->sc_memt, sc->sc_memh, reg, data);
+}
diff --git a/sys/arch/i386/pci/elan520reg.h b/sys/arch/i386/pci/elan520reg.h
index d53d8decb43..2f954bdcaea 100644
--- a/sys/arch/i386/pci/elan520reg.h
+++ b/sys/arch/i386/pci/elan520reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: elan520reg.h,v 1.1 2003/01/21 17:02:29 markus Exp $ */
+/* $OpenBSD: elan520reg.h,v 1.2 2004/06/05 15:06:22 grange Exp $ */
/* $NetBSD: elan520reg.h,v 1.1 2002/08/12 01:03:14 thorpej Exp $ */
/*-
@@ -98,6 +98,8 @@
#define MMCR_PIOCLR15_0 0x0c38 /* PIO15-PIO0 clear */
#define MMCR_PIOCLR31_16 0x0c3a /* PIO31-PIO16 clear */
+#define ELANSC_PIO_NPINS 32 /* total number of PIO pins */
+
/*
* Watchdog Timer Registers.
*/