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 | |
parent | 1ecd922a40cf3efdd2f45cdc3bf870b7be0bd249 (diff) |
extra gunk to make ohci suspend and resume work on the zaurus
help from and ok uwe@
-rw-r--r-- | sys/arch/arm/xscale/pxa27x_udc.c | 62 | ||||
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.c | 10 | ||||
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_ohci.c | 96 |
3 files changed, 119 insertions, 49 deletions
diff --git a/sys/arch/arm/xscale/pxa27x_udc.c b/sys/arch/arm/xscale/pxa27x_udc.c index ef84c690935..94f843422e2 100644 --- a/sys/arch/arm/xscale/pxa27x_udc.c +++ b/sys/arch/arm/xscale/pxa27x_udc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa27x_udc.c,v 1.4 2005/02/21 07:46:48 dlg Exp $ */ +/* $OpenBSD: pxa27x_udc.c,v 1.5 2005/03/30 14:24:39 dlg Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -33,14 +33,19 @@ int pxaudc_match(struct device *, void *, void *); void pxaudc_attach(struct device *, struct device *, void *); int pxaudc_detach(struct device *, int); +void pxaudc_power(int, void *); struct pxaudc_softc { struct device sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; bus_size_t sc_size; + + void *sc_powerhook; }; +void pxaudc_enable(struct pxaudc_softc *); + struct cfattach pxaudc_ca = { sizeof(struct pxaudc_softc), pxaudc_match, pxaudc_attach, pxaudc_detach @@ -64,10 +69,10 @@ pxaudc_attach(struct device *parent, struct device *self, void *aux) { struct pxaudc_softc *sc = (struct pxaudc_softc *)self; struct pxaip_attach_args *pxa = aux; - u_int32_t hr; sc->sc_iot = pxa->pxa_iot; sc->sc_size = 0; + sc->sc_powerhook = NULL; if (bus_space_map(sc->sc_iot, PXA2X0_USBDC_BASE, PXA2X0_USBDC_SIZE, 0, &sc->sc_ioh)) { @@ -84,8 +89,46 @@ pxaudc_attach(struct device *parent, struct device *self, void *aux) pxa2x0_gpio_set_function(35, GPIO_ALT_FN_2_IN); /* USB_P2_1 */ pxa2x0_gpio_set_function(37, GPIO_ALT_FN_1_OUT); /* USB_P2_8 */ pxa2x0_gpio_set_function(41, GPIO_ALT_FN_2_IN); /* USB_P2_7 */ + pxa2x0_gpio_set_function(89, GPIO_ALT_FN_2_OUT); /* USBHPEN<1> */ + pxa2x0_gpio_set_function(120, GPIO_ALT_FN_2_OUT); /* USBHPEN<2> */ pxa2x0_clkman_config(CKEN_USBDC, 0); + pxaudc_enable(sc); + + pxa2x0_gpio_set_bit(37); /* USB_P2_8 */ + + sc->sc_powerhook = powerhook_establish(pxaudc_power, sc); +} + +int +pxaudc_detach(struct device *self, int flags) +{ + struct pxaudc_softc *sc = (struct pxaudc_softc *)self; + + if (sc->sc_powerhook != NULL) + powerhook_disestablish(sc->sc_powerhook); + + if (sc->sc_size) { + bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size); + sc->sc_size = 0; + } + + return (0); +} + +void +pxaudc_power(int why, void *arg) +{ + struct pxaudc_softc *sc = (struct pxaudc_softc *)arg; + + if (why == PWR_RESUME) + pxaudc_enable(sc); +} + +void +pxaudc_enable(struct pxaudc_softc *sc) +{ + u_int32_t hr; /* disable the controller */ hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UDCCR); @@ -106,19 +149,4 @@ pxaudc_attach(struct device *parent, struct device *self, void *aux) hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR); bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR, hr | USBDC_UP2OCR_DPPDE|USBDC_UP2OCR_DMPDE); - - pxa2x0_gpio_set_bit(37); /* USB_P2_8 */ -} - -int -pxaudc_detach(struct device *self, int flags) -{ - struct pxaudc_softc *sc = (struct pxaudc_softc *)self; - - if (sc->sc_size) { - bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size); - sc->sc_size = 0; - } - - return (0); } diff --git a/sys/arch/arm/xscale/pxa2x0_apm.c b/sys/arch/arm/xscale/pxa2x0_apm.c index b1b03b334ee..bf01f06e324 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.c +++ b/sys/arch/arm/xscale/pxa2x0_apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.c,v 1.9 2005/03/29 23:17:45 uwe Exp $ */ +/* $OpenBSD: pxa2x0_apm.c,v 1.10 2005/03/30 14:24:39 dlg Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -316,8 +316,14 @@ apm_suspend(struct pxa2x0_apm_softc *sc) void apm_resume(struct pxa2x0_apm_softc *sc) { - dopowerhooks(PWR_RESUME); + + /* + * Clear the OTG Peripheral hold after running the pxaudc and pxaohci + * powerhooks to re-enable their operation. See 3.8.1.2 + */ + /* XXX ifdef NPXAUDC > 0 */ + bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSSR, PSSR_OTGPH); } int 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)); +} + |