Date: Thu, 28 Aug 2003 01:41:03 -0400 From: Anish Mistry <mistry.7@osu.edu> To: freebsd-current@freebsd.org Subject: [patch] usb ohci suspend/resume Message-ID: <200308280141.15917.mistry.7@osu.edu>
next in thread | raw e-mail | index | archive | help
--Boundary-03=_7XZT/u1uHkPwsle Content-Type: multipart/mixed; boundary="Boundary-01=_vXZT/wFeAdpzUH5" Content-Transfer-Encoding: 7bit Content-Description: signed data Content-Disposition: inline --Boundary-01=_vXZT/wFeAdpzUH5 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Content-Description: body text Content-Disposition: inline If you have trouble with suspend/resume killing your usb devices try out th= e=20 attached patch (ohci only, unless someone want to adapt to uhci). I think = I=20 finally got it working, at least it works with my mouse and no panics if yo= u=20 leave devices plugged during a suspend/resume cycle. Same as attached in case it gets stripped. http://am-productions.biz/docs/ohci-usb-suspend.patch =2D-=20 Anish Mistry --Boundary-01=_vXZT/wFeAdpzUH5 Content-Type: text/x-diff; charset="us-ascii"; name="ohci-usb-suspend.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ohci-usb-suspend.patch" diff -u usb.orig/ohci.c usb/ohci.c =2D-- usb.orig/ohci.c Thu Aug 28 00:54:09 2003 +++ usb/ohci.c Thu Aug 28 01:04:43 2003 @@ -1020,7 +1020,7 @@ DPRINTF(("ohci_shutdown: stopping the HC\n")); OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); } =2D +#endif /* * Handle suspend/resume. * @@ -1028,6 +1028,86 @@ * called from an intterupt context. This is all right since we * are almost suspended anyway. */ +usbd_status ohci_resume(struct ohci_softc *sc) +{ +/* return ohci_init(sc);*/ + int s; + u_int32_t ctl, ival, hcr, fm, per, rev, desca; + s =3D splusb(); + DPRINTF(("ohci_resume: start\n")); +#if defined(__OpenBSD__) + printf(","); +#else + printf("%s:", USBDEVNAME(sc->sc_bus.bdev)); +#endif + rev =3D OREAD4(sc, OHCI_REVISION); + printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev), + OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); + /* Some broken BIOSes do not recover these values */ + OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); + OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); + OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); + if (sc->sc_intre) + OWRITE4(sc, OHCI_INTERRUPT_ENABLE, + sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); + if (sc->sc_control) + ctl =3D sc->sc_control; + else + ctl =3D OREAD4(sc, OHCI_CONTROL); + ctl |=3D OHCI_HCFS_RESUME; + OWRITE4(sc, OHCI_CONTROL, ctl); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); + ctl =3D (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; + OWRITE4(sc, OHCI_CONTROL, ctl); + usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); + sc->sc_control =3D sc->sc_intre =3D 0; + /* disable all interrupts and then switch on all desired interrupts */ + OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); + OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE); + /* switch on desired functional features */ + ctl =3D OREAD4(sc, OHCI_CONTROL); + ctl &=3D ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR); + ctl |=3D OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE | + OHCI_RATIO_1_4 | OHCI_HCFS_OPERATIONAL; + /* And finally start it! */ + OWRITE4(sc, OHCI_CONTROL, ctl); + + /* + * The controller is now OPERATIONAL. Set a some final + * registers that should be set earlier, but that the + * controller ignores when in the SUSPEND state. + */ + fm =3D (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT; + fm |=3D OHCI_FSMPS(ival) | ival; + OWRITE4(sc, OHCI_FM_INTERVAL, fm); + per =3D OHCI_PERIODIC(ival); /* 90% periodic */ + OWRITE4(sc, OHCI_PERIODIC_START, per); + + /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */ + desca =3D OREAD4(sc, OHCI_RH_DESCRIPTOR_A); + OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP); + OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */ + usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY); + OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca); + splx(s); + return (USBD_NORMAL_COMPLETION); +} + +usbd_status ohci_suspend(struct ohci_softc *sc) +{ + u_int32_t ctl,i; + int s; + + s =3D splhardusb(); + ctl =3D OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; + ctl |=3D OHCI_HCFS_SUSPEND; + OWRITE4(sc, OHCI_CONTROL, ctl); + splx(s); + + return (USBD_NORMAL_COMPLETION); +} + +#if defined(__NetBSD__) || defined(__OpenBSD__) void ohci_power(int why, void *v) { diff -u usb.orig/ohci_pci.c usb/ohci_pci.c =2D-- usb.orig/ohci_pci.c Thu Aug 28 00:54:09 2003 +++ usb/ohci_pci.c Thu Aug 28 01:16:47 2003 @@ -295,11 +295,43 @@ return 0; } =20 +/* implement suspend and resume */ +static int +ohci_pci_suspend(device_t self) +{ + int err; + ohci_softc_t *sc =3D device_get_softc(self); + device_printf(self, "ohci_pci_suspend: power_state =3D 0x%08x\n", + pci_get_powerstate(self)); + err =3D bus_generic_suspend(self); + if (err) + return err; + ohci_suspend(sc); + /*usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);*/ + return 0; +} + +static int +ohci_pci_resume(device_t self) +{ + ohci_softc_t *sc =3D device_get_softc(self); + device_printf(self, "ohci_pci_resume: power_state =3D 0x%08x\n", + pci_get_powerstate(self)); + ohci_resume(sc); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); + usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); + bus_generic_resume(self); + + return 0; +} + static device_method_t ohci_methods[] =3D { /* Device interface */ DEVMETHOD(device_probe, ohci_pci_probe), DEVMETHOD(device_attach, ohci_pci_attach), =2D DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, ohci_pci_suspend), + DEVMETHOD(device_resume, ohci_pci_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), =20 /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), diff -u usb.orig/ohcivar.h usb/ohcivar.h =2D-- usb.orig/ohcivar.h Thu Aug 28 00:54:09 2003 +++ usb/ohcivar.h Wed Aug 27 19:36:47 2003 @@ -158,6 +158,8 @@ #define OXFER(xfer) ((struct ohci_xfer *)(xfer)) =20 usbd_status ohci_init(ohci_softc_t *); +usbd_status ohci_suspend(ohci_softc_t *); +usbd_status ohci_resume(ohci_softc_t *); int ohci_intr(void *); #if defined(__NetBSD__) || defined(__OpenBSD__) int ohci_detach(ohci_softc_t *, int); --Boundary-01=_vXZT/wFeAdpzUH5-- --Boundary-03=_7XZT/u1uHkPwsle Content-Type: application/pgp-signature Content-Description: signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (FreeBSD) iD8DBQA/TZX7xqA5ziudZT0RAkvCAKCVFiITB88SzGA4n3mtGnQRq97B4QCePJb8 61dQkS9Z5NP5Sj+l88GXdhM= =9M5u -----END PGP SIGNATURE----- --Boundary-03=_7XZT/u1uHkPwsle--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308280141.15917.mistry.7>