root/arch/i386/pci/gscpcib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gscpcib_match
  2. gscpcib_attach
  3. gscpcib_gpio_pin_select
  4. gscpcib_gpio_pin_read
  5. gscpcib_gpio_pin_write
  6. gscpcib_gpio_pin_ctl

    1 /*      $OpenBSD: gscpcib.c,v 1.5 2006/12/11 20:57:40 deraadt Exp $     */
    2 /*
    3  * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
    4  *
    5  * Permission to use, copy, modify, and distribute this software for any
    6  * purpose with or without fee is hereby granted, provided that the above
    7  * copyright notice and this permission notice appear in all copies.
    8  *
    9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16  */
   17 
   18 /*
   19  * Special driver for the National Semiconductor Geode SC1100 PCI-ISA bridge
   20  * that attaches instead of pcib(4). In addition to the core pcib(4)
   21  * functionality this driver provides support for the GPIO interface.
   22  */
   23 
   24 #include <sys/param.h>
   25 #include <sys/systm.h>
   26 #include <sys/device.h>
   27 #include <sys/gpio.h>
   28 #include <sys/kernel.h>
   29 
   30 #include <machine/bus.h>
   31 
   32 #include <dev/pci/pcireg.h>
   33 #include <dev/pci/pcivar.h>
   34 #include <dev/pci/pcidevs.h>
   35 
   36 #include <dev/gpio/gpiovar.h>
   37 
   38 #include <i386/pci/gscpcibreg.h>
   39 
   40 struct gscpcib_softc {
   41         struct device sc_dev;
   42 
   43         /* GPIO interface */
   44         bus_space_tag_t sc_gpio_iot;
   45         bus_space_handle_t sc_gpio_ioh;
   46         struct gpio_chipset_tag sc_gpio_gc;
   47         gpio_pin_t sc_gpio_pins[GSCGPIO_NPINS];
   48 };
   49 
   50 int     gscpcib_match(struct device *, void *, void *);
   51 void    gscpcib_attach(struct device *, struct device *, void *);
   52 
   53 int     gscpcib_gpio_pin_read(void *, int);
   54 void    gscpcib_gpio_pin_write(void *, int, int);
   55 void    gscpcib_gpio_pin_ctl(void *, int, int);
   56 
   57 /* arch/i386/pci/pcib.c */
   58 void    pcibattach(struct device *, struct device *, void *);
   59 
   60 struct cfattach gscpcib_ca = {
   61         sizeof (struct gscpcib_softc),
   62         gscpcib_match,
   63         gscpcib_attach
   64 };
   65 
   66 struct cfdriver gscpcib_cd = {
   67         NULL, "gscpcib", DV_DULL
   68 };
   69 
   70 int
   71 gscpcib_match(struct device *parent, void *match, void *aux)
   72 {
   73         struct pci_attach_args *pa = aux;
   74 
   75         if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE ||
   76             PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA)
   77                 return (0);
   78 
   79         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS &&
   80             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SC1100_ISA)
   81                 return (2);     /* supersede pcib(4) */
   82 
   83         return (0);
   84 }
   85 
   86 void
   87 gscpcib_attach(struct device *parent, struct device *self, void *aux)
   88 {
   89 #ifndef SMALL_KERNEL
   90         struct gscpcib_softc *sc = (struct gscpcib_softc *)self;
   91         struct pci_attach_args *pa = aux;
   92         struct gpiobus_attach_args gba;
   93         pcireg_t gpiobase;
   94         int i;
   95         int gpio_present = 0;
   96 
   97         /* Map GPIO I/O space */
   98         gpiobase = pci_conf_read(pa->pa_pc, pa->pa_tag, GSCGPIO_BASE);
   99         sc->sc_gpio_iot = pa->pa_iot;
  100         if (PCI_MAPREG_IO_ADDR(gpiobase) == 0 ||
  101             bus_space_map(sc->sc_gpio_iot, PCI_MAPREG_IO_ADDR(gpiobase),
  102             GSCGPIO_SIZE, 0, &sc->sc_gpio_ioh)) {
  103                 printf(": failed to map GPIO I/O space");
  104                 goto corepcib;
  105         }
  106 
  107         /* Initialize pins array */
  108         for (i = 0; i < GSCGPIO_NPINS; i++) {
  109                 sc->sc_gpio_pins[i].pin_num = i;
  110                 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
  111                     GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
  112                     GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
  113                     GPIO_PIN_PULLUP;
  114 
  115                 /* Read initial state */
  116                 sc->sc_gpio_pins[i].pin_state = gscpcib_gpio_pin_read(sc, i) ?
  117                     GPIO_PIN_HIGH : GPIO_PIN_LOW;
  118         }
  119 
  120         /* Create controller tag */
  121         sc->sc_gpio_gc.gp_cookie = sc;
  122         sc->sc_gpio_gc.gp_pin_read = gscpcib_gpio_pin_read;
  123         sc->sc_gpio_gc.gp_pin_write = gscpcib_gpio_pin_write;
  124         sc->sc_gpio_gc.gp_pin_ctl = gscpcib_gpio_pin_ctl;
  125 
  126         gba.gba_name = "gpio";
  127         gba.gba_gc = &sc->sc_gpio_gc;
  128         gba.gba_pins = sc->sc_gpio_pins;
  129         gba.gba_npins = GSCGPIO_NPINS;
  130 
  131         gpio_present = 1;
  132 
  133 corepcib:
  134 #endif  /* !SMALL_KERNEL */
  135         /* Provide core pcib(4) functionality */
  136         pcibattach(parent, self, aux);
  137 
  138 #ifndef SMALL_KERNEL
  139         /* Attach GPIO framework */
  140         if (gpio_present)
  141                 config_found(&sc->sc_dev, &gba, gpiobus_print);
  142 #endif  /* !SMALL_KERNEL */
  143 }
  144 
  145 #ifndef SMALL_KERNEL
  146 static __inline void
  147 gscpcib_gpio_pin_select(struct gscpcib_softc *sc, int pin)
  148 {
  149         bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GSCGPIO_SEL, pin);
  150 }
  151 
  152 int
  153 gscpcib_gpio_pin_read(void *arg, int pin)
  154 {
  155         struct gscpcib_softc *sc = arg;
  156         int reg, shift;
  157         u_int32_t data;
  158 
  159         reg = (pin < 32 ? GSCGPIO_GPDI0 : GSCGPIO_GPDI1);
  160         shift = pin % 32;
  161         data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
  162 
  163         return ((data >> shift) & 0x1);
  164 }
  165 
  166 void
  167 gscpcib_gpio_pin_write(void *arg, int pin, int value)
  168 {
  169         struct gscpcib_softc *sc = arg;
  170         int reg, shift;
  171         u_int32_t data;
  172 
  173         reg = (pin < 32 ? GSCGPIO_GPDO0 : GSCGPIO_GPDO1);
  174         shift = pin % 32;
  175         data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
  176         if (value == 0)
  177                 data &= ~(1 << shift);
  178         else if (value == 1)
  179                 data |= (1 << shift);
  180 
  181         bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data);
  182 }
  183 
  184 void
  185 gscpcib_gpio_pin_ctl(void *arg, int pin, int flags)
  186 {
  187         struct gscpcib_softc *sc = arg;
  188         u_int32_t conf;
  189 
  190         gscpcib_gpio_pin_select(sc, pin);
  191         conf = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
  192             GSCGPIO_CONF);
  193 
  194         conf &= ~(GSCGPIO_CONF_OUTPUTEN | GSCGPIO_CONF_PUSHPULL |
  195             GSCGPIO_CONF_PULLUP);
  196         if ((flags & GPIO_PIN_TRISTATE) == 0)
  197                 conf |= GSCGPIO_CONF_OUTPUTEN;
  198         if (flags & GPIO_PIN_PUSHPULL)
  199                 conf |= GSCGPIO_CONF_PUSHPULL;
  200         if (flags & GPIO_PIN_PULLUP)
  201                 conf |= GSCGPIO_CONF_PULLUP;
  202         bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
  203             GSCGPIO_CONF, conf);
  204 }
  205 #endif  /* !SMALL_KERNEL */

/* [<][>][^][v][top][bottom][index][help] */