[BACK]Return to pxa2x0_ohci.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / xscale

Annotation of sys/arch/arm/xscale/pxa2x0_ohci.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pxa2x0_ohci.c,v 1.21 2007/06/14 19:18:49 deraadt Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #include <sys/param.h>
        !            20: #include <sys/systm.h>
        !            21: #include <sys/device.h>
        !            22: #include <sys/kernel.h>
        !            23: #include <sys/timeout.h>
        !            24:
        !            25: #include <machine/intr.h>
        !            26: #include <machine/bus.h>
        !            27:
        !            28: #include <arm/xscale/pxa2x0reg.h>
        !            29: #include <arm/xscale/pxa2x0var.h>
        !            30: #include <arm/xscale/pxa2x0_gpio.h>
        !            31:
        !            32: #include <dev/usb/usb.h>
        !            33: #include <dev/usb/usbdi.h>
        !            34: #include <dev/usb/usbdivar.h>
        !            35: #include <dev/usb/usb_mem.h>
        !            36:
        !            37: #include <dev/usb/ohcireg.h>
        !            38: #include <dev/usb/ohcivar.h>
        !            39:
        !            40: int    pxaohci_match(struct device *, void *, void *);
        !            41: void   pxaohci_attach(struct device *, struct device *, void *);
        !            42: int    pxaohci_detach(struct device *, int);
        !            43: void   pxaohci_power(int, void *);
        !            44:
        !            45: struct pxaohci_softc {
        !            46:        ohci_softc_t    sc;
        !            47:        void            *sc_ih;
        !            48: };
        !            49:
        !            50: void   pxaohci_enable(struct pxaohci_softc *);
        !            51: void   pxaohci_disable(struct pxaohci_softc *);
        !            52:
        !            53: struct cfattach pxaohci_ca = {
        !            54:         sizeof (struct pxaohci_softc), pxaohci_match, pxaohci_attach,
        !            55:        pxaohci_detach, ohci_activate
        !            56: };
        !            57:
        !            58: int
        !            59: pxaohci_match(struct device *parent, void *match, void *aux)
        !            60: {
        !            61:        if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) != CPU_ID_PXA27X)
        !            62:                return (0);
        !            63:
        !            64:        return (1);
        !            65: }
        !            66:
        !            67: void
        !            68: pxaohci_attach(struct device *parent, struct device *self, void *aux)
        !            69: {
        !            70:        struct pxaohci_softc            *sc = (struct pxaohci_softc *)self;
        !            71:        struct pxaip_attach_args        *pxa = aux;
        !            72:        usbd_status                     r;
        !            73:
        !            74:        sc->sc.iot = pxa->pxa_iot;
        !            75:        sc->sc.sc_bus.dmatag = pxa->pxa_dmat;
        !            76:        sc->sc_ih = NULL;
        !            77:        sc->sc.sc_size = 0;
        !            78:
        !            79:        /* Map I/O space */
        !            80:        if (bus_space_map(sc->sc.iot, PXA2X0_USBHC_BASE, PXA2X0_USBHC_SIZE, 0,
        !            81:            &sc->sc.ioh)) {
        !            82:                printf(": cannot map mem space\n");
        !            83:                return;
        !            84:        }
        !            85:        sc->sc.sc_size = PXA2X0_USBHC_SIZE;
        !            86:
        !            87:        /* XXX copied from ohci_pci.c. needed? */
        !            88:        bus_space_barrier(sc->sc.iot, sc->sc.ioh, 0, sc->sc.sc_size,
        !            89:            BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
        !            90:
        !            91:        /* start the usb clock */
        !            92:        pxa2x0_clkman_config(CKEN_USBHC, 1);
        !            93:        pxaohci_enable(sc);
        !            94:
        !            95:        /* Disable interrupts, so we don't get any spurious ones. */
        !            96:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
        !            97:            OHCI_MIE);
        !            98:
        !            99:        sc->sc_ih = pxa2x0_intr_establish(PXA2X0_INT_USBH1, IPL_USB,
        !           100:            ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
        !           101:        if (sc->sc_ih == NULL) {
        !           102:                printf(": unable to establish interrupt\n");
        !           103:                pxaohci_disable(sc);
        !           104:                pxa2x0_clkman_config(CKEN_USBHC, 0);
        !           105:                bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
        !           106:                sc->sc.sc_size = 0;
        !           107:                return;
        !           108:        }
        !           109:
        !           110:        strlcpy(sc->sc.sc_vendor, "PXA27x", sizeof(sc->sc.sc_vendor));
        !           111:
        !           112:        if (ohci_checkrev(&sc->sc) != USBD_NORMAL_COMPLETION)
        !           113:                goto unsupported;
        !           114:
        !           115:        r = ohci_init(&sc->sc);
        !           116:        if (r != USBD_NORMAL_COMPLETION) {
        !           117:                printf("%s: init failed, error=%d\n",
        !           118:                    sc->sc.sc_bus.bdev.dv_xname, r);
        !           119: unsupported:
        !           120:                pxa2x0_intr_disestablish(sc->sc_ih);
        !           121:                sc->sc_ih = NULL;
        !           122:                pxaohci_disable(sc);
        !           123:                pxa2x0_clkman_config(CKEN_USBHC, 0);
        !           124:                bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
        !           125:                sc->sc.sc_size = 0;
        !           126:                return;
        !           127:        }
        !           128:
        !           129:        sc->sc.sc_powerhook = powerhook_establish(pxaohci_power, sc);
        !           130:        if (sc->sc.sc_powerhook == NULL)
        !           131:                printf("%s: cannot establish powerhook\n",
        !           132:                    sc->sc.sc_bus.bdev.dv_xname);
        !           133:
        !           134:        sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus,
        !           135:            usbctlprint);
        !           136: }
        !           137:
        !           138: int
        !           139: pxaohci_detach(struct device *self, int flags)
        !           140: {
        !           141:        struct pxaohci_softc            *sc = (struct pxaohci_softc *)self;
        !           142:        int                             rv;
        !           143:
        !           144:        rv = ohci_detach(&sc->sc, flags);
        !           145:        if (rv)
        !           146:                return (rv);
        !           147:
        !           148:        if (sc->sc.sc_powerhook != NULL) {
        !           149:                powerhook_disestablish(sc->sc.sc_powerhook);
        !           150:                sc->sc.sc_powerhook = NULL;
        !           151:        }
        !           152:
        !           153:        if (sc->sc_ih != NULL) {
        !           154:                pxa2x0_intr_disestablish(sc->sc_ih);
        !           155:                sc->sc_ih = NULL;
        !           156:        }
        !           157:
        !           158:        pxaohci_disable(sc);
        !           159:
        !           160:        /* stop clock */
        !           161:        pxa2x0_clkman_config(CKEN_USBHC, 0);
        !           162:
        !           163:        if (sc->sc.sc_size) {
        !           164:                bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
        !           165:                sc->sc.sc_size = 0;
        !           166:        }
        !           167:
        !           168:        return (0);
        !           169: }
        !           170:
        !           171:
        !           172: void
        !           173: pxaohci_power(int why, void *arg)
        !           174: {
        !           175:        struct pxaohci_softc            *sc = (struct pxaohci_softc *)arg;
        !           176:        int                             s;
        !           177:
        !           178:        s = splhardusb();
        !           179:        sc->sc.sc_bus.use_polling++;
        !           180:        switch (why) {
        !           181:        case PWR_STANDBY:
        !           182:        case PWR_SUSPEND:
        !           183:                ohci_power(why, &sc->sc);
        !           184:                pxa2x0_clkman_config(CKEN_USBHC, 0);
        !           185:                break;
        !           186:
        !           187:        case PWR_RESUME:
        !           188:                pxa2x0_clkman_config(CKEN_USBHC, 1);
        !           189:                pxaohci_enable(sc);
        !           190:                ohci_power(why, &sc->sc);
        !           191:                break;
        !           192:        }
        !           193:        sc->sc.sc_bus.use_polling--;
        !           194:        splx(s);
        !           195: }
        !           196:
        !           197: void
        !           198: pxaohci_enable(struct pxaohci_softc *sc)
        !           199: {
        !           200:        u_int32_t                       hr;
        !           201:
        !           202:        /* Full host reset */
        !           203:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           204:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           205:            (hr & USBHC_HR_MASK) | USBHC_HR_FHR);
        !           206:
        !           207:        DELAY(USBHC_RST_WAIT);
        !           208:
        !           209:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           210:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           211:            (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR));
        !           212:
        !           213:        /* Force system bus interface reset */
        !           214:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           215:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           216:            (hr & USBHC_HR_MASK) | USBHC_HR_FSBIR);
        !           217:
        !           218:        while (bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR) & \
        !           219:            USBHC_HR_FSBIR)
        !           220:                DELAY(3);
        !           221:
        !           222:        /* Enable the ports (physically only one, only enable that one?) */
        !           223:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           224:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           225:            (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSE));
        !           226:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           227:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           228:            (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSEP2));
        !           229: }
        !           230:
        !           231: void
        !           232: pxaohci_disable(struct pxaohci_softc *sc)
        !           233: {
        !           234:        u_int32_t                       hr;
        !           235:
        !           236:        /* Full host reset */
        !           237:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           238:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           239:            (hr & USBHC_HR_MASK) | USBHC_HR_FHR);
        !           240:
        !           241:        DELAY(USBHC_RST_WAIT);
        !           242:
        !           243:        hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
        !           244:        bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
        !           245:            (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR));
        !           246: }

CVSweb