[BACK]Return to gscpcib.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / pci

Annotation of sys/arch/i386/pci/gscpcib.c, Revision 1.1

1.1     ! nbrk        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 */

CVSweb