From 777503501ed9e1639d8b449ebcbda5e29b27c149 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Tue, 27 Sep 2005 02:42:44 +0000 Subject: [PATCH] Add NS Geode PCI-ISA bridge GPIO support. --- sys/arch/i386/conf/files.i386 | 8 +- sys/arch/i386/pci/gscpcib.c | 202 +++++++++++++++++++++++++++++++++ sys/arch/i386/pci/gscpcibreg.h | 43 +++++++ 3 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 sys/arch/i386/pci/gscpcib.c create mode 100644 sys/arch/i386/pci/gscpcibreg.h diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index 6a4d68341cca..5265a52c77ba 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $NetBSD: files.i386,v 1.270 2005/09/22 07:09:35 dyoung Exp $ +# $NetBSD: files.i386,v 1.271 2005/09/27 02:42:44 jmcneill Exp $ # # new style config file for i386 architecture # @@ -197,13 +197,17 @@ file arch/i386/pci/pceb.c pceb # PCI-ISA bridges device pcib: isabus attach pcib at pci -file arch/i386/pci/pcib.c pcib | ichlpcib +file arch/i386/pci/pcib.c pcib | ichlpcib | gscpcib # PCI-LPC bridges device ichlpcib: isabus, sysmon_wdog attach ichlpcib at pci file arch/i386/pci/ichlpcib.c ichlpcib +device gscpcib: isabus, gpiobus +attach gscpcib at pci +file arch/i386/pci/gscpcib.c gscpcib + # PCI-MCA bridges device pcmb: mcabus attach pcmb at pci diff --git a/sys/arch/i386/pci/gscpcib.c b/sys/arch/i386/pci/gscpcib.c new file mode 100644 index 000000000000..10965642331f --- /dev/null +++ b/sys/arch/i386/pci/gscpcib.c @@ -0,0 +1,202 @@ +/* $NetBSD: gscpcib.c,v 1.1 2005/09/27 02:42:44 jmcneill Exp $ */ +/* $OpenBSD: gscpcib.c,v 1.3 2004/10/05 19:02:33 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Special driver for the National Semiconductor Geode SC1100 PCI-ISA bridge + * that attaches instead of pcib(4). In addition to the core pcib(4) + * functionality this driver provides support for the GPIO interface. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +struct gscpcib_softc { + struct device sc_dev; + + /* GPIO interface */ + bus_space_tag_t sc_gpio_iot; + bus_space_handle_t sc_gpio_ioh; + struct gpio_chipset_tag sc_gpio_gc; + gpio_pin_t sc_gpio_pins[GSCGPIO_NPINS]; +}; + +int gscpcib_match(struct device *, struct cfdata *, void *); +void gscpcib_attach(struct device *, struct device *, void *); + +int gscpcib_gpio_pin_read(void *, int); +void gscpcib_gpio_pin_write(void *, int, int); +void gscpcib_gpio_pin_ctl(void *, int, int); + +/* arch/i386/pci/pcib.c */ +void pcibattach(struct device *, struct device *, void *); + +CFATTACH_DECL(gscpcib, sizeof(struct gscpcib_softc), + gscpcib_match, gscpcib_attach, NULL, NULL); + +extern struct cfdriver gscpcib_cd; + +int +gscpcib_match(struct device *parent, struct cfdata *match, void *aux) +{ + struct pci_attach_args *pa = aux; + + if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE || + PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA) + return (0); + + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SC1100_ISA) + return (2); /* supersede pcib(4) */ + + return (0); +} + +void +gscpcib_attach(struct device *parent, struct device *self, void *aux) +{ +#ifndef SMALL_KERNEL + struct gscpcib_softc *sc = (struct gscpcib_softc *)self; + struct pci_attach_args *pa = aux; + struct gpiobus_attach_args gba; + pcireg_t gpiobase; + int i; + int gpio_present = 0; + + /* Map GPIO I/O space */ + gpiobase = pci_conf_read(pa->pa_pc, pa->pa_tag, GSCGPIO_BASE); + sc->sc_gpio_iot = pa->pa_iot; + if (bus_space_map(sc->sc_gpio_iot, PCI_MAPREG_IO_ADDR(gpiobase), + GSCGPIO_SIZE, 0, &sc->sc_gpio_ioh)) { + printf(": failed to map GPIO I/O space"); + goto corepcib; + } + + /* Initialize pins array */ + for (i = 0; i < GSCGPIO_NPINS; i++) { + sc->sc_gpio_pins[i].pin_num = i; + sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | + GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | + GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | + GPIO_PIN_PULLUP; + + /* safe defaults */ + sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_TRISTATE; + sc->sc_gpio_pins[i].pin_state = GPIO_PIN_LOW; + gscpcib_gpio_pin_ctl(sc, i, sc->sc_gpio_pins[i].pin_flags); + gscpcib_gpio_pin_write(sc, i, sc->sc_gpio_pins[i].pin_state); + } + + /* Create controller tag */ + sc->sc_gpio_gc.gp_cookie = sc; + sc->sc_gpio_gc.gp_pin_read = gscpcib_gpio_pin_read; + sc->sc_gpio_gc.gp_pin_write = gscpcib_gpio_pin_write; + sc->sc_gpio_gc.gp_pin_ctl = gscpcib_gpio_pin_ctl; + + gba.gba_name = "gpio"; + gba.gba_gc = &sc->sc_gpio_gc; + gba.gba_pins = sc->sc_gpio_pins; + gba.gba_npins = GSCGPIO_NPINS; + + gpio_present = 1; + +corepcib: +#endif /* !SMALL_KERNEL */ + /* Provide core pcib(4) functionality */ + pcibattach(parent, self, aux); + +#ifndef SMALL_KERNEL + /* Attach GPIO framework */ + if (gpio_present) + config_found(&sc->sc_dev, &gba, gpiobus_print); +#endif /* !SMALL_KERNEL */ +} + +#ifndef SMALL_KERNEL +static __inline void +gscpcib_gpio_pin_select(struct gscpcib_softc *sc, int pin) +{ + bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GSCGPIO_SEL, pin); +} + +int +gscpcib_gpio_pin_read(void *arg, int pin) +{ + struct gscpcib_softc *sc = arg; + int reg, shift; + u_int32_t data; + + reg = (pin < 32 ? GSCGPIO_GPDI0 : GSCGPIO_GPDI1); + shift = pin % 32; + data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); + + return ((data >> shift) & 0x1); +} + +void +gscpcib_gpio_pin_write(void *arg, int pin, int value) +{ + struct gscpcib_softc *sc = arg; + int reg, shift; + u_int32_t data; + + reg = (pin < 32 ? GSCGPIO_GPDO0 : GSCGPIO_GPDO1); + shift = pin % 32; + data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg); + if (value == 0) + data &= ~(1 << shift); + else if (value == 1) + data |= (1 << shift); + + bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data); +} + +void +gscpcib_gpio_pin_ctl(void *arg, int pin, int flags) +{ + struct gscpcib_softc *sc = arg; + u_int32_t conf; + + gscpcib_gpio_pin_select(sc, pin); + conf = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, + GSCGPIO_CONF); + + conf &= ~(GSCGPIO_CONF_OUTPUTEN | GSCGPIO_CONF_PUSHPULL | + GSCGPIO_CONF_PULLUP); + if ((flags & GPIO_PIN_TRISTATE) == 0) + conf |= GSCGPIO_CONF_OUTPUTEN; + if (flags & GPIO_PIN_PUSHPULL) + conf |= GSCGPIO_CONF_PUSHPULL; + if (flags & GPIO_PIN_PULLUP) + conf |= GSCGPIO_CONF_PULLUP; + bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, + GSCGPIO_CONF, conf); +} +#endif /* !SMALL_KERNEL */ diff --git a/sys/arch/i386/pci/gscpcibreg.h b/sys/arch/i386/pci/gscpcibreg.h new file mode 100644 index 000000000000..60e857c09a4e --- /dev/null +++ b/sys/arch/i386/pci/gscpcibreg.h @@ -0,0 +1,43 @@ +/* $NetBSD: gscpcibreg.h,v 1.1 2005/09/27 02:42:44 jmcneill Exp $ */ +/* $OpenBSD: gscpcibreg.h,v 1.1 2004/06/03 18:22:21 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _I386_PCI_GSCGPIOREG_H_ +#define _I386_PCI_GSCGPIOREG_H_ + +#define GSCGPIO_NPINS 64 + +#define GSCGPIO_BASE 0x10 +#define GSCGPIO_SIZE 64 + +#define GSCGPIO_GPDO0 0x00 +#define GSCGPIO_GPDI0 0x04 +#define GSCGPIO_GPIEN0 0x08 +#define GSCGPIO_GPST0 0x0c +#define GSCGPIO_GPDO1 0x10 +#define GSCGPIO_GPDI1 0x14 +#define GSCGPIO_GPIEN1 0x18 +#define GSCGPIO_GPST1 0x1c +#define GSCGPIO_SEL 0x20 +#define GSCGPIO_CONF 0x24 +#define GSCGPIO_RESET 0x28 + +#define GSCGPIO_CONF_OUTPUTEN (1 << 0) +#define GSCGPIO_CONF_PUSHPULL (1 << 1) +#define GSCGPIO_CONF_PULLUP (1 << 2) + +#endif /* !_I386_PCI_GSCGPIOREG_H_ */