[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

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