diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2005-03-30 14:24:40 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2005-03-30 14:24:40 +0000 |
commit | 8887acff246fd9c44af093d31c0643b73d4b2184 (patch) | |
tree | 8e1008f108a9021f1ac6e80a615a803fbae8a948 /sys/arch/arm/xscale/pxa2x0_ohci.c | |
parent | 1ecd922a40cf3efdd2f45cdc3bf870b7be0bd249 (diff) |
extra gunk to make ohci suspend and resume work on the zaurus
help from and ok uwe@
Diffstat (limited to 'sys/arch/arm/xscale/pxa2x0_ohci.c')
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_ohci.c | 96 |
1 files changed, 66 insertions, 30 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_ohci.c b/sys/arch/arm/xscale/pxa2x0_ohci.c index a635a003e68..03f6bce7e78 100644 --- a/sys/arch/arm/xscale/pxa2x0_ohci.c +++ b/sys/arch/arm/xscale/pxa2x0_ohci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_ohci.c,v 1.14 2005/03/30 14:02:02 dlg Exp $ */ +/* $OpenBSD: pxa2x0_ohci.c,v 1.15 2005/03/30 14:24:39 dlg Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -39,12 +39,15 @@ int pxaohci_match(struct device *, void *, void *); void pxaohci_attach(struct device *, struct device *, void *); int pxaohci_detach(struct device *, int); +void pxaohci_power(int, void *); struct pxaohci_softc { ohci_softc_t sc; void *sc_ih; }; +void pxaohci_enable(struct pxaohci_softc *); + struct cfattach pxaohci_ca = { sizeof (struct pxaohci_softc), pxaohci_match, pxaohci_attach, pxaohci_detach, ohci_activate @@ -64,7 +67,6 @@ pxaohci_attach(struct device *parent, struct device *self, void *aux) { struct pxaohci_softc *sc = (struct pxaohci_softc *)self; struct pxaip_attach_args *pxa = aux; - u_int32_t hr; usbd_status r; sc->sc.iot = pxa->pxa_iot; @@ -86,34 +88,7 @@ pxaohci_attach(struct device *parent, struct device *self, void *aux) /* start the usb clock */ pxa2x0_clkman_config(CKEN_USBHC, 1); - - /* Full host reset */ - hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); - bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, - (hr & USBHC_HR_MASK) | USBHC_HR_FHR); - - DELAY(mstohz(USBHC_RST_WAIT)); - - hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); - bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, - (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR)); - - /* Force system bus interface reset */ - hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); - bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, - (hr & USBHC_HR_MASK) | USBHC_HR_FSBIR); - - while (bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR) & \ - USBHC_HR_FSBIR) - DELAY(3); - - /* Enable the ports (physically only one, only enable that one?) */ - hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); - bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, - (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSE)); - hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); - bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, - (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSEP2)); + pxaohci_enable(sc); /* Disable interrupts, so we don't get any spurious ones. */ bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE, @@ -178,3 +153,64 @@ pxaohci_detach(struct device *self, int flags) return (0); } + + +void +pxaohci_power(int why, void *arg) +{ + struct pxaohci_softc *sc = (struct pxaohci_softc *)arg; + int s; + + s = splhardusb(); + sc->sc.sc_bus.use_polling++; + switch (why) { + case PWR_STANDBY: + case PWR_SUSPEND: + ohci_power(why, arg); + pxa2x0_clkman_config(CKEN_USBHC, 0); + break; + + case PWR_RESUME: + pxa2x0_clkman_config(CKEN_USBHC, 1); + pxaohci_enable(sc); + ohci_power(why, arg); + break; + } + sc->sc.sc_bus.use_polling--; + splx(s); +} + +void +pxaohci_enable(struct pxaohci_softc *sc) +{ + u_int32_t hr; + + /* Full host reset */ + hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, + (hr & USBHC_HR_MASK) | USBHC_HR_FHR); + + DELAY(mstohz(USBHC_RST_WAIT)); + + hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, + (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR)); + + /* Force system bus interface reset */ + hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, + (hr & USBHC_HR_MASK) | USBHC_HR_FSBIR); + + while (bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR) & \ + USBHC_HR_FSBIR) + DELAY(3); + + /* Enable the ports (physically only one, only enable that one?) */ + hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, + (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSE)); + hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR, + (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSEP2)); +} + |