diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2004-06-05 15:06:23 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2004-06-05 15:06:23 +0000 |
commit | 42f49c9281dfbaea39b28fca5d254ff5cfa7f7b9 (patch) | |
tree | e4dde5abe31c30292314c9a0d9523ffa2dfa0e82 /sys/arch | |
parent | f614b159c3bebabad248000917a61df53cf95ffd (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/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 4 | ||||
-rw-r--r-- | sys/arch/i386/pci/elan520.c | 101 | ||||
-rw-r--r-- | sys/arch/i386/pci/elan520reg.h | 4 |
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. */ |