summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2005-03-30 14:24:40 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2005-03-30 14:24:40 +0000
commit8887acff246fd9c44af093d31c0643b73d4b2184 (patch)
tree8e1008f108a9021f1ac6e80a615a803fbae8a948
parent1ecd922a40cf3efdd2f45cdc3bf870b7be0bd249 (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.c62
-rw-r--r--sys/arch/arm/xscale/pxa2x0_apm.c10
-rw-r--r--sys/arch/arm/xscale/pxa2x0_ohci.c96
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));
+}
+