From 2e1417489338b971e5fd599ff48b5f65df9e8d3b Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 14 Dec 2011 00:28:54 +0000 Subject: [PATCH] Implement better support for USB controller suspend and resume. This patch should remove the need for kldunload of USB controller drivers at suspend and kldload of USB controller drivers at resume. This patch also fixes some build issues in avr32dci.c MFC after: 2 weeks --- sys/arm/econa/ehci_ebus.c | 55 +--- sys/arm/econa/ohci_ec.c | 8 +- sys/dev/usb/controller/at91dci.c | 29 ++- sys/dev/usb/controller/at91dci.h | 2 - sys/dev/usb/controller/at91dci_atmelarm.c | 26 +- sys/dev/usb/controller/atmegadci.c | 29 ++- sys/dev/usb/controller/atmegadci.h | 2 - sys/dev/usb/controller/atmegadci_atmelarm.c | 26 +- sys/dev/usb/controller/avr32dci.c | 86 ++++--- sys/dev/usb/controller/avr32dci.h | 3 +- sys/dev/usb/controller/ehci.c | 266 +++++++------------- sys/dev/usb/controller/ehci.h | 5 - sys/dev/usb/controller/ehci_ixp4xx.c | 48 +--- sys/dev/usb/controller/ehci_mv.c | 48 +--- sys/dev/usb/controller/ehci_pci.c | 82 ++---- sys/dev/usb/controller/musb_otg.c | 29 ++- sys/dev/usb/controller/musb_otg.h | 2 - sys/dev/usb/controller/musb_otg_atmelarm.c | 26 +- sys/dev/usb/controller/ohci.c | 100 +++----- sys/dev/usb/controller/ohci.h | 4 - sys/dev/usb/controller/ohci_atmelarm.c | 8 +- sys/dev/usb/controller/ohci_pci.c | 55 ++-- sys/dev/usb/controller/ohci_s3c24x0.c | 8 +- sys/dev/usb/controller/uhci.c | 60 ++--- sys/dev/usb/controller/uhci.h | 4 - sys/dev/usb/controller/uhci_pci.c | 54 ++-- sys/dev/usb/controller/usb_controller.c | 247 ++++++++++++++++-- sys/dev/usb/controller/uss820dci.c | 29 ++- sys/dev/usb/controller/uss820dci.h | 2 - sys/dev/usb/controller/uss820dci_atmelarm.c | 50 +--- sys/dev/usb/controller/xhci_pci.c | 59 +---- sys/dev/usb/usb_bus.h | 6 +- sys/dev/usb/usb_controller.h | 14 +- sys/dev/usb/usb_if.m | 10 + sys/mips/atheros/ar71xx_ehci.c | 54 +--- sys/mips/atheros/ar71xx_ohci.c | 8 +- sys/mips/cavium/usb/octusb.c | 29 ++- sys/mips/cavium/usb/octusb.h | 2 - sys/mips/cavium/usb/octusb_octeon.c | 25 +- sys/mips/rmi/xls_ehci.c | 58 +---- sys/mips/rt305x/rt305x_dotg.c | 26 +- sys/modules/usb/Makefile | 6 +- sys/modules/usb/avr32dci/Makefile | 38 +++ sys/powerpc/ps3/ehci_ps3.c | 9 +- sys/powerpc/ps3/ohci_ps3.c | 9 +- 45 files changed, 805 insertions(+), 941 deletions(-) create mode 100644 sys/modules/usb/avr32dci/Makefile diff --git a/sys/arm/econa/ehci_ebus.c b/sys/arm/econa/ehci_ebus.c index ee201485f0c..4b72b7f6cae 100644 --- a/sys/arm/econa/ehci_ebus.c +++ b/sys/arm/econa/ehci_ebus.c @@ -75,55 +75,12 @@ __FBSDID("$FreeBSD$"); static device_attach_t ehci_ebus_attach; static device_detach_t ehci_ebus_detach; -static device_shutdown_t ehci_ebus_shutdown; -static device_suspend_t ehci_ebus_suspend; -static device_resume_t ehci_ebus_resume; - static void *ih_err; #define EHCI_HC_DEVSTR "CNS11XX USB EHCI" #define USB_BRIDGE_INTR_MASK 0x214 -static int -ehci_ebus_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_suspend(sc); - return (0); -} - -static int -ehci_ebus_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -ehci_ebus_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - - return (0); -} - static int ehci_ebus_probe(device_t self) { @@ -277,17 +234,17 @@ static device_method_t ehci_methods[] = { DEVMETHOD(device_probe, ehci_ebus_probe), DEVMETHOD(device_attach, ehci_ebus_attach), DEVMETHOD(device_detach, ehci_ebus_detach), - DEVMETHOD(device_suspend, ehci_ebus_suspend), - DEVMETHOD(device_resume, ehci_ebus_resume), - DEVMETHOD(device_shutdown, ehci_ebus_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(ehci_softc_t), + .name = "ehci", + .methods = ehci_methods, + .size = sizeof(ehci_softc_t), }; static devclass_t ehci_devclass; diff --git a/sys/arm/econa/ohci_ec.c b/sys/arm/econa/ohci_ec.c index ee449602ade..543aae13815 100644 --- a/sys/arm/econa/ohci_ec.c +++ b/sys/arm/econa/ohci_ec.c @@ -220,15 +220,17 @@ static device_method_t ohci_methods[] = { DEVMETHOD(device_probe, ohci_ec_probe), DEVMETHOD(device_attach, ohci_ec_attach), DEVMETHOD(device_detach, ohci_ec_detach), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ohci_driver = { - "ohci", - ohci_methods, - sizeof(struct ec_ohci_softc), + .name = "ohci", + .methods = ohci_methods, + .size = sizeof(struct ec_ohci_softc), }; static devclass_t ohci_devclass; diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c index f831115b6cf..d3258127dc1 100644 --- a/sys/dev/usb/controller/at91dci.c +++ b/sys/dev/usb/controller/at91dci.c @@ -1461,16 +1461,16 @@ at91dci_uninit(struct at91dci_softc *sc) USB_BUS_UNLOCK(&sc->sc_bus); } -void +static void at91dci_suspend(struct at91dci_softc *sc) { - return; + /* TODO */ } -void +static void at91dci_resume(struct at91dci_softc *sc) { - return; + /* TODO */ } static void @@ -2306,6 +2306,26 @@ at91dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, } } +static void +at91dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + at91dci_suspend(sc); + break; + case USB_HW_POWER_SHUTDOWN: + at91dci_uninit(sc); + break; + case USB_HW_POWER_RESUME: + at91dci_resume(sc); + break; + default: + break; + } +} + struct usb_bus_methods at91dci_bus_methods = { .endpoint_init = &at91dci_ep_init, @@ -2316,4 +2336,5 @@ struct usb_bus_methods at91dci_bus_methods = .clear_stall = &at91dci_clear_stall, .roothub_exec = &at91dci_roothub_exec, .xfer_poll = &at91dci_do_poll, + .set_hw_power_sleep = &at91dci_set_hw_power_sleep, }; diff --git a/sys/dev/usb/controller/at91dci.h b/sys/dev/usb/controller/at91dci.h index a1603aa660a..b079eb5b272 100644 --- a/sys/dev/usb/controller/at91dci.h +++ b/sys/dev/usb/controller/at91dci.h @@ -235,8 +235,6 @@ struct at91dci_softc { usb_error_t at91dci_init(struct at91dci_softc *sc); void at91dci_uninit(struct at91dci_softc *sc); -void at91dci_suspend(struct at91dci_softc *sc); -void at91dci_resume(struct at91dci_softc *sc); void at91dci_interrupt(struct at91dci_softc *sc); void at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on); diff --git a/sys/dev/usb/controller/at91dci_atmelarm.c b/sys/dev/usb/controller/at91dci_atmelarm.c index 1e8e39494b9..da9ba36e639 100644 --- a/sys/dev/usb/controller/at91dci_atmelarm.c +++ b/sys/dev/usb/controller/at91dci_atmelarm.c @@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$"); static device_probe_t at91_udp_probe; static device_attach_t at91_udp_attach; static device_detach_t at91_udp_detach; -static device_shutdown_t at91_udp_shutdown; struct at91_udp_softc { struct at91dci_softc sc_dci; /* must be first */ @@ -324,35 +323,22 @@ at91_udp_detach(device_t dev) return (0); } -static int -at91_udp_shutdown(device_t dev) -{ - struct at91_udp_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_shutdown(dev); - if (err) - return (err); - - at91dci_uninit(&sc->sc_dci); - - return (0); -} - static device_method_t at91_udp_methods[] = { /* Device interface */ DEVMETHOD(device_probe, at91_udp_probe), DEVMETHOD(device_attach, at91_udp_attach), DEVMETHOD(device_detach, at91_udp_detach), - DEVMETHOD(device_shutdown, at91_udp_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t at91_udp_driver = { - "at91_udp", - at91_udp_methods, - sizeof(struct at91_udp_softc), + .name = "at91_udp", + .methods = at91_udp_methods, + .size = sizeof(struct at91_udp_softc), }; static devclass_t at91_udp_devclass; diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c index ad53fc328a9..7db3bdbb44d 100644 --- a/sys/dev/usb/controller/atmegadci.c +++ b/sys/dev/usb/controller/atmegadci.c @@ -1352,16 +1352,16 @@ atmegadci_uninit(struct atmegadci_softc *sc) USB_BUS_UNLOCK(&sc->sc_bus); } -void +static void atmegadci_suspend(struct atmegadci_softc *sc) { - return; + /* TODO */ } -void +static void atmegadci_resume(struct atmegadci_softc *sc) { - return; + /* TODO */ } static void @@ -2126,6 +2126,26 @@ atmegadci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc } } +static void +atmegadci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct atmegadci_softc *sc = ATMEGA_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + atmegadci_suspend(sc); + break; + case USB_HW_POWER_SHUTDOWN: + atmegadci_uninit(sc); + break; + case USB_HW_POWER_RESUME: + atmegadci_resume(sc); + break; + default: + break; + } +} + struct usb_bus_methods atmegadci_bus_methods = { .endpoint_init = &atmegadci_ep_init, @@ -2136,4 +2156,5 @@ struct usb_bus_methods atmegadci_bus_methods = .clear_stall = &atmegadci_clear_stall, .roothub_exec = &atmegadci_roothub_exec, .xfer_poll = &atmegadci_do_poll, + .set_hw_power_sleep = &atmegadci_set_hw_power_sleep, }; diff --git a/sys/dev/usb/controller/atmegadci.h b/sys/dev/usb/controller/atmegadci.h index 68613af3e5e..91ba030661f 100644 --- a/sys/dev/usb/controller/atmegadci.h +++ b/sys/dev/usb/controller/atmegadci.h @@ -278,8 +278,6 @@ struct atmegadci_softc { usb_error_t atmegadci_init(struct atmegadci_softc *sc); void atmegadci_uninit(struct atmegadci_softc *sc); -void atmegadci_suspend(struct atmegadci_softc *sc); -void atmegadci_resume(struct atmegadci_softc *sc); void atmegadci_interrupt(struct atmegadci_softc *sc); #endif /* _ATMEGADCI_H_ */ diff --git a/sys/dev/usb/controller/atmegadci_atmelarm.c b/sys/dev/usb/controller/atmegadci_atmelarm.c index c68101ca2b0..6c380b6076d 100644 --- a/sys/dev/usb/controller/atmegadci_atmelarm.c +++ b/sys/dev/usb/controller/atmegadci_atmelarm.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); static device_probe_t atmegadci_probe; static device_attach_t atmegadci_attach; static device_detach_t atmegadci_detach; -static device_shutdown_t atmegadci_shutdown; struct atmegadci_super_softc { struct atmegadci_softc sc_otg; /* must be first */ @@ -193,35 +192,22 @@ atmegadci_detach(device_t dev) return (0); } -static int -atmegadci_shutdown(device_t dev) -{ - struct atmegadci_super_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_shutdown(dev); - if (err) - return (err); - - atmegadci_uninit(&sc->sc_otg); - - return (0); -} - static device_method_t atmegadci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, atmegadci_probe), DEVMETHOD(device_attach, atmegadci_attach), DEVMETHOD(device_detach, atmegadci_detach), - DEVMETHOD(device_shutdown, atmegadci_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t atmegadci_driver = { - "atmegadci", - atmegadci_methods, - sizeof(struct atmegadci_super_softc), + .name = "atmegadci", + .methods = atmegadci_methods, + .size = sizeof(struct atmegadci_super_softc), }; static devclass_t atmegadci_devclass; diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c index 26785a3542a..9494c301640 100644 --- a/sys/dev/usb/controller/avr32dci.c +++ b/sys/dev/usb/controller/avr32dci.c @@ -265,7 +265,7 @@ avr32dci_set_address(struct avr32dci_softc *sc, uint8_t addr) { DPRINTFN(5, "addr=%d\n", addr); - avr32dci_mod_ctrl(sc, AVR32_UDADDR_ADDEN | addr, 0); + avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_FADDR_EN | addr, 0); } static uint8_t @@ -501,7 +501,7 @@ repeat: } /* allocate FIFO bank */ - AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(td->ep_no), AVR32_EPTSTA_TX_BK_RDY); + AVR32_WRITE_4(sc, AVR32_EPTCTL(td->ep_no), AVR32_EPTCTL_TX_PK_RDY); /* check remainder */ if (td->remainder == 0) { @@ -754,7 +754,7 @@ avr32dci_setup_standard_chain(struct usb_xfer *xfer) uint8_t need_sync; DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n", - xfer->address, UE_GET_ADDR(xfer->endpoint), + xfer->address, UE_GET_ADDR(xfer->endpointno), xfer->sumlen, usbd_get_speed(xfer->xroot->udev)); temp.max_frame_size = xfer->max_frame_size; @@ -773,7 +773,7 @@ avr32dci_setup_standard_chain(struct usb_xfer *xfer) temp.did_stall = !xfer->flags_int.control_stall; sc = AVR32_BUS2SC(xfer->xroot->bus); - ep_no = (xfer->endpoint & UE_ADDR); + ep_no = (xfer->endpointno & UE_ADDR); /* check if we should prepend a setup message */ @@ -798,7 +798,7 @@ avr32dci_setup_standard_chain(struct usb_xfer *xfer) } if (x != xfer->nframes) { - if (xfer->endpoint & UE_DIR_IN) { + if (xfer->endpointno & UE_DIR_IN) { temp.func = &avr32dci_data_tx; need_sync = 1; } else { @@ -872,7 +872,7 @@ avr32dci_setup_standard_chain(struct usb_xfer *xfer) * Send a DATA1 message and invert the current * endpoint direction. */ - if (xfer->endpoint & UE_DIR_IN) { + if (xfer->endpointno & UE_DIR_IN) { temp.func = &avr32dci_data_rx; need_sync = 0; } else { @@ -913,7 +913,8 @@ avr32dci_start_standard_chain(struct usb_xfer *xfer) /* poll one time - will turn on interrupts */ if (avr32dci_xfer_do_fifo(xfer)) { - uint8_t ep_no = xfer->endpoint & UE_ADDR_MASK; + uint8_t ep_no = xfer->endpointno & UE_ADDR; + struct avr32dci_softc *sc = AVR32_BUS2SC(xfer->xroot->bus); avr32dci_mod_ien(sc, AVR32_INT_EPT_INT(ep_no), 0); @@ -1012,7 +1013,7 @@ avr32dci_standard_done(struct usb_xfer *xfer) usb_error_t err = 0; DPRINTFN(13, "xfer=%p pipe=%p transfer done\n", - xfer, xfer->pipe); + xfer, xfer->endpoint); /* reset scanner */ @@ -1064,10 +1065,10 @@ avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error) USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); DPRINTFN(9, "xfer=%p, pipe=%p, error=%d\n", - xfer, xfer->pipe, error); + xfer, xfer->endpoint, error); if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { - ep_no = (xfer->endpoint & UE_ADDR); + ep_no = (xfer->endpointno & UE_ADDR); /* disable endpoint interrupt */ avr32dci_mod_ien(sc, 0, AVR32_INT_EPT_INT(ep_no)); @@ -1080,7 +1081,7 @@ avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error) static void avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, - struct usb_endpoint *ep, uint8_t *did_stall) + struct usb_endpoint *pipe, uint8_t *did_stall) { struct avr32dci_softc *sc; uint8_t ep_no; @@ -1166,7 +1167,7 @@ avr32dci_clear_stall_sub(struct avr32dci_softc *sc, uint8_t ep_no, } static void -avr32dci_clear_stall(struct usb_device *udev, struct usb_endpoint *ep) +avr32dci_clear_stall(struct usb_device *udev, struct usb_endpoint *pipe) { struct avr32dci_softc *sc; struct usb_endpoint_descriptor *ed; @@ -1226,8 +1227,7 @@ avr32dci_init(struct avr32dci_softc *sc) AVR32_INT_ENDRESET, 0); /* reset all endpoints */ -/**INDENT** Warning@1207: Extra ) */ - AVR32_WRITE_4(sc, AVR32_EPTRST, (1 << AVR32_EP_MAX) - 1)); + AVR32_WRITE_4(sc, AVR32_EPTRST, (1 << AVR32_EP_MAX) - 1); /* disable all endpoints */ for (n = 0; n != AVR32_EP_MAX; n++) { @@ -1262,8 +1262,7 @@ avr32dci_uninit(struct avr32dci_softc *sc) avr32dci_mod_ien(sc, 0, 0xFFFFFFFF); /* reset all endpoints */ -/**INDENT** Warning@1242: Extra ) */ - AVR32_WRITE_4(sc, AVR32_EPTRST, (1 << AVR32_EP_MAX) - 1)); + AVR32_WRITE_4(sc, AVR32_EPTRST, (1 << AVR32_EP_MAX) - 1); /* disable all endpoints */ for (n = 0; n != AVR32_EP_MAX; n++) { @@ -1284,16 +1283,16 @@ avr32dci_uninit(struct avr32dci_softc *sc) USB_BUS_UNLOCK(&sc->sc_bus); } -void +static void avr32dci_suspend(struct avr32dci_softc *sc) { - return; + /* TODO */ } -void +static void avr32dci_resume(struct avr32dci_softc *sc) { - return; + /* TODO */ } static void @@ -1369,10 +1368,10 @@ avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) uint8_t ep_no; DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", - xfer, xfer->pipe->isoc_next, xfer->nframes); + xfer, xfer->endpoint->isoc_next, xfer->nframes); /* get the current frame index */ - ep_no = xfer->endpoint & UE_ADDR_MASK; + ep_no = xfer->endpointno & UE_ADDR; nframes = (AVR32_READ_4(sc, AVR32_FNUM) / 8); nframes &= AVR32_FRAME_MASK; @@ -1381,9 +1380,9 @@ avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) * check if the frame index is within the window where the frames * will be inserted */ - temp = (nframes - xfer->pipe->isoc_next) & AVR32_FRAME_MASK; + temp = (nframes - xfer->endpoint->isoc_next) & AVR32_FRAME_MASK; - if ((xfer->pipe->is_synced == 0) || + if ((xfer->endpoint->is_synced == 0) || (temp < xfer->nframes)) { /* * If there is data underflow or the pipe queue is @@ -1391,15 +1390,15 @@ avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) * of the current frame position. Else two isochronous * transfers might overlap. */ - xfer->pipe->isoc_next = (nframes + 3) & AVR32_FRAME_MASK; - xfer->pipe->is_synced = 1; - DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next); + xfer->endpoint->isoc_next = (nframes + 3) & AVR32_FRAME_MASK; + xfer->endpoint->is_synced = 1; + DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); } /* * compute how many milliseconds the insertion is ahead of the * current frame position: */ - temp = (xfer->pipe->isoc_next - nframes) & AVR32_FRAME_MASK; + temp = (xfer->endpoint->isoc_next - nframes) & AVR32_FRAME_MASK; /* * pre-compute when the isochronous transfer will be finished: @@ -1409,7 +1408,7 @@ avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) xfer->nframes; /* compute frame number for next insertion */ - xfer->pipe->isoc_next += xfer->nframes; + xfer->endpoint->isoc_next += xfer->nframes; /* setup TDs */ avr32dci_setup_standard_chain(xfer); @@ -1832,7 +1831,7 @@ tr_handle_clear_port_feature: AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(0), AVR32_EPTSTA_FRCESTALL); /* configure */ - AVR32_WRITE_4(sc, AVR32_EPTCFG(0), AVR32_EPTCFG_TYPE_CONTROL | + AVR32_WRITE_4(sc, AVR32_EPTCFG(0), AVR32_EPTCFG_TYPE_CTRL | AVR32_EPTCFG_NBANK(1) | AVR32_EPTCFG_EPSIZE(6)); temp = AVR32_READ_4(sc, AVR32_EPTCFG(0)); @@ -1974,7 +1973,7 @@ avr32dci_xfer_setup(struct usb_setup_params *parm) /* * compute maximum number of TDs */ - if ((xfer->pipe->edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) { + if ((xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) { ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */ + 1 /* SYNC 2 */ ; @@ -1997,7 +1996,7 @@ avr32dci_xfer_setup(struct usb_setup_params *parm) /* * get profile stuff */ - ep_no = xfer->endpoint & UE_ADDR; + ep_no = xfer->endpointno & UE_ADDR; avr32dci_get_hw_ep_profile(parm->udev, &pf, ep_no); if (pf == NULL) { @@ -2045,7 +2044,7 @@ avr32dci_xfer_unsetup(struct usb_xfer *xfer) static void avr32dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, - struct usb_endpoint *ep) + struct usb_endpoint *pipe) { struct avr32dci_softc *sc = AVR32_BUS2SC(udev->bus); @@ -2072,6 +2071,26 @@ avr32dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, } } +static void +avr32dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct avr32dci_softc *sc = AVR32_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + avr32dci_suspend(sc); + break; + case USB_HW_POWER_SHUTDOWN: + avr32dci_uninit(sc); + break; + case USB_HW_POWER_RESUME: + avr32dci_resume(sc); + break; + default: + break; + } +} + struct usb_bus_methods avr32dci_bus_methods = { .endpoint_init = &avr32dci_ep_init, @@ -2082,4 +2101,5 @@ struct usb_bus_methods avr32dci_bus_methods = .clear_stall = &avr32dci_clear_stall, .roothub_exec = &avr32dci_roothub_exec, .xfer_poll = &avr32dci_do_poll, + .set_hw_power_sleep = &avr32dci_set_hw_power_sleep, }; diff --git a/sys/dev/usb/controller/avr32dci.h b/sys/dev/usb/controller/avr32dci.h index 6672fa76afb..2d80344fd48 100644 --- a/sys/dev/usb/controller/avr32dci.h +++ b/sys/dev/usb/controller/avr32dci.h @@ -166,6 +166,7 @@ struct avr32dci_td { uint32_t offset; uint32_t remainder; uint16_t max_packet_size; + uint8_t bank_shift; uint8_t error:1; uint8_t alt_next:1; uint8_t short_pkt:1; @@ -246,8 +247,6 @@ struct avr32dci_softc { usb_error_t avr32dci_init(struct avr32dci_softc *sc); void avr32dci_uninit(struct avr32dci_softc *sc); -void avr32dci_suspend(struct avr32dci_softc *sc); -void avr32dci_resume(struct avr32dci_softc *sc); void avr32dci_interrupt(struct avr32dci_softc *sc); void avr32dci_vbus_interrupt(struct avr32dci_softc *sc, uint8_t is_on); diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c index 7e682f4fcbb..f59c801dacd 100644 --- a/sys/dev/usb/controller/ehci.c +++ b/sys/dev/usb/controller/ehci.c @@ -188,7 +188,7 @@ ehci_reset(ehci_softc_t *sc) EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); for (i = 0; i < 100; i++) { - usb_pause_mtx(NULL, hz / 1000); + usb_pause_mtx(NULL, hz / 128); hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; if (!hcr) { if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) { @@ -212,7 +212,7 @@ ehci_reset(ehci_softc_t *sc) return (0); } } - device_printf(sc->sc_bus.bdev, "reset timeout\n"); + device_printf(sc->sc_bus.bdev, "Reset timeout\n"); return (USB_ERR_IOERROR); } @@ -224,7 +224,7 @@ ehci_hcreset(ehci_softc_t *sc) EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ for (i = 0; i < 100; i++) { - usb_pause_mtx(NULL, hz / 1000); + usb_pause_mtx(NULL, hz / 128); hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; if (hcr) break; @@ -237,7 +237,60 @@ ehci_hcreset(ehci_softc_t *sc) */ device_printf(sc->sc_bus.bdev, "stop timeout\n"); - return ehci_reset(sc); + return (ehci_reset(sc)); +} + +static int +ehci_init_sub(struct ehci_softc *sc) +{ + struct usb_page_search buf_res; + uint32_t cparams; + uint32_t hcr; + uint8_t i; + + cparams = EREAD4(sc, EHCI_HCCPARAMS); + + DPRINTF("cparams=0x%x\n", cparams); + + if (EHCI_HCC_64BIT(cparams)) { + DPRINTF("HCC uses 64-bit structures\n"); + + /* MUST clear segment register if 64 bit capable */ + EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); + } + + usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res); + EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr); + + usbd_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res); + EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH); + + /* enable interrupts */ + EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); + + /* turn on controller */ + EOWRITE4(sc, EHCI_USBCMD, + EHCI_CMD_ITC_1 | /* 1 microframes interrupt delay */ + (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) | + EHCI_CMD_ASE | + EHCI_CMD_PSE | + EHCI_CMD_RS); + + /* Take over port ownership */ + EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF); + + for (i = 0; i < 100; i++) { + usb_pause_mtx(NULL, hz / 128); + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (!hcr) { + break; + } + } + if (hcr) { + device_printf(sc->sc_bus.bdev, "Run timeout\n"); + return (USB_ERR_IOERROR); + } + return (USB_ERR_NORMAL_COMPLETION); } usb_error_t @@ -246,8 +299,6 @@ ehci_init(ehci_softc_t *sc) struct usb_page_search buf_res; uint32_t version; uint32_t sparams; - uint32_t cparams; - uint32_t hcr; uint16_t i; uint16_t x; uint16_t y; @@ -279,15 +330,6 @@ ehci_init(ehci_softc_t *sc) DPRINTF("sparams=0x%x\n", sparams); sc->sc_noport = EHCI_HCS_N_PORTS(sparams); - cparams = EREAD4(sc, EHCI_HCCPARAMS); - DPRINTF("cparams=0x%x\n", cparams); - - if (EHCI_HCC_64BIT(cparams)) { - DPRINTF("HCC uses 64-bit structures\n"); - - /* MUST clear segment register if 64 bit capable */ - EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - } sc->sc_bus.usbrev = USB_REV_2_0; /* Reset the controller */ @@ -464,9 +506,6 @@ ehci_init(ehci_softc_t *sc) [i & (EHCI_VIRTUAL_FRAMELIST_COUNT - 1)]->itd_self; } } - /* setup sync list pointer */ - EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr); - usbd_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res); if (1) { @@ -511,35 +550,8 @@ ehci_init(ehci_softc_t *sc) } #endif - /* setup async list pointer */ - EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH); - - - /* enable interrupts */ - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - - /* turn on controller */ - EOWRITE4(sc, EHCI_USBCMD, - EHCI_CMD_ITC_1 | /* 1 microframes interrupt delay */ - (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) | - EHCI_CMD_ASE | - EHCI_CMD_PSE | - EHCI_CMD_RS); - - /* Take over port ownership */ - EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF); - - for (i = 0; i < 100; i++) { - usb_pause_mtx(NULL, hz / 1000); - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (!hcr) { - break; - } - } - if (hcr) { - device_printf(sc->sc_bus.bdev, "run timeout\n"); - return (USB_ERR_IOERROR); - } + /* finial setup */ + err = ehci_init_sub(sc); if (!err) { /* catch any lost interrupts */ @@ -573,135 +585,26 @@ ehci_detach(ehci_softc_t *sc) usb_callout_drain(&sc->sc_tmo_poll); } -void +static void ehci_suspend(ehci_softc_t *sc) -{ - uint32_t cmd; - uint32_t hcr; - uint8_t i; - - USB_BUS_LOCK(&sc->sc_bus); - - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if (((cmd & EHCI_PS_PO) == 0) && - ((cmd & EHCI_PS_PE) == EHCI_PS_PE)) { - EOWRITE4(sc, EHCI_PORTSC(i), - cmd | EHCI_PS_SUSP); - } - } - - sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD); - - cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE); - EOWRITE4(sc, EHCI_USBCMD, cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & - (EHCI_STS_ASS | EHCI_STS_PSS); - - if (hcr == 0) { - break; - } - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000); - } - - if (hcr != 0) { - device_printf(sc->sc_bus.bdev, "reset timeout\n"); - } - cmd &= ~EHCI_CMD_RS; - EOWRITE4(sc, EHCI_USBCMD, cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr == EHCI_STS_HCH) { - break; - } - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000); - } - - if (hcr != EHCI_STS_HCH) { - device_printf(sc->sc_bus.bdev, - "config timeout\n"); - } - USB_BUS_UNLOCK(&sc->sc_bus); -} - -void -ehci_resume(ehci_softc_t *sc) -{ - struct usb_page_search buf_res; - uint32_t cmd; - uint32_t hcr; - uint8_t i; - - USB_BUS_LOCK(&sc->sc_bus); - - /* restore things in case the bios doesn't */ - EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - - usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res); - EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr); - - usbd_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res); - EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH); - - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - - hcr = 0; - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if (((cmd & EHCI_PS_PO) == 0) && - ((cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP)) { - EOWRITE4(sc, EHCI_PORTSC(i), - cmd | EHCI_PS_FPR); - hcr = 1; - } - } - - if (hcr) { - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(USB_RESUME_WAIT)); - - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if (((cmd & EHCI_PS_PO) == 0) && - ((cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP)) { - EOWRITE4(sc, EHCI_PORTSC(i), - cmd & ~EHCI_PS_FPR); - } - } - } - EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr != EHCI_STS_HCH) { - break; - } - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000); - } - if (hcr == EHCI_STS_HCH) { - device_printf(sc->sc_bus.bdev, "config timeout\n"); - } - - USB_BUS_UNLOCK(&sc->sc_bus); - - usb_pause_mtx(NULL, - USB_MS_TO_TICKS(USB_RESUME_WAIT)); - - /* catch any lost interrupts */ - ehci_do_poll(&sc->sc_bus); -} - -void -ehci_shutdown(ehci_softc_t *sc) { DPRINTF("stopping the HC\n"); - if (ehci_hcreset(sc)) { - DPRINTF("reset failed!\n"); - } + /* reset HC */ + ehci_hcreset(sc); +} + +static void +ehci_resume(ehci_softc_t *sc) +{ + /* reset HC */ + ehci_hcreset(sc); + + /* setup HC */ + ehci_init_sub(sc); + + /* catch any lost interrupts */ + ehci_do_poll(&sc->sc_bus); } #ifdef USB_DEBUG @@ -3908,8 +3811,24 @@ ehci_device_suspend(struct usb_device *udev) } USB_BUS_UNLOCK(udev->bus); +} - return; +static void +ehci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct ehci_softc *sc = EHCI_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + case USB_HW_POWER_SHUTDOWN: + ehci_suspend(sc); + break; + case USB_HW_POWER_RESUME: + ehci_resume(sc); + break; + default: + break; + } } static void @@ -3955,6 +3874,7 @@ struct usb_bus_methods ehci_bus_methods = .device_resume = ehci_device_resume, .device_suspend = ehci_device_suspend, .set_hw_power = ehci_set_hw_power, + .set_hw_power_sleep = ehci_set_hw_power_sleep, .roothub_exec = ehci_roothub_exec, .xfer_poll = ehci_do_poll, }; diff --git a/sys/dev/usb/controller/ehci.h b/sys/dev/usb/controller/ehci.h index a8aa514a006..b8b6985df74 100644 --- a/sys/dev/usb/controller/ehci.h +++ b/sys/dev/usb/controller/ehci.h @@ -333,8 +333,6 @@ typedef struct ehci_softc { uint32_t sc_terminate_self; /* TD short packet termination pointer */ uint32_t sc_eintrs; - uint32_t sc_cmd; /* shadow of cmd register during - * suspend */ uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT]; uint16_t sc_id_vendor; /* vendor ID for root hub */ @@ -445,9 +443,6 @@ usb_bus_mem_cb_t ehci_iterate_hw_softc; usb_error_t ehci_reset(ehci_softc_t *sc); usb_error_t ehci_init(ehci_softc_t *sc); void ehci_detach(struct ehci_softc *sc); -void ehci_suspend(struct ehci_softc *sc); -void ehci_resume(struct ehci_softc *sc); -void ehci_shutdown(ehci_softc_t *sc); void ehci_interrupt(ehci_softc_t *sc); #endif /* _EHCI_H_ */ diff --git a/sys/dev/usb/controller/ehci_ixp4xx.c b/sys/dev/usb/controller/ehci_ixp4xx.c index 7327fdefa12..45113d9f4e2 100644 --- a/sys/dev/usb/controller/ehci_ixp4xx.c +++ b/sys/dev/usb/controller/ehci_ixp4xx.c @@ -78,9 +78,6 @@ struct ixp_ehci_softc { static device_attach_t ehci_ixp_attach; static device_detach_t ehci_ixp_detach; -static device_shutdown_t ehci_ixp_shutdown; -static device_suspend_t ehci_ixp_suspend; -static device_resume_t ehci_ixp_resume; static uint8_t ehci_bs_r_1(void *, bus_space_handle_t, bus_size_t); static void ehci_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t); @@ -89,45 +86,6 @@ static void ehci_bs_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t); static uint32_t ehci_bs_r_4(void *, bus_space_handle_t, bus_size_t); static void ehci_bs_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t); -static int -ehci_ixp_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_suspend(sc); - return (0); -} - -static int -ehci_ixp_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -ehci_ixp_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - - return (0); -} - static int ehci_ixp_probe(device_t self) { @@ -335,9 +293,9 @@ static device_method_t ehci_methods[] = { DEVMETHOD(device_probe, ehci_ixp_probe), DEVMETHOD(device_attach, ehci_ixp_attach), DEVMETHOD(device_detach, ehci_ixp_detach), - DEVMETHOD(device_suspend, ehci_ixp_suspend), - DEVMETHOD(device_resume, ehci_ixp_resume), - DEVMETHOD(device_shutdown, ehci_ixp_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; diff --git a/sys/dev/usb/controller/ehci_mv.c b/sys/dev/usb/controller/ehci_mv.c index f12cb14ce5c..a47e253841c 100644 --- a/sys/dev/usb/controller/ehci_mv.c +++ b/sys/dev/usb/controller/ehci_mv.c @@ -81,9 +81,6 @@ __FBSDID("$FreeBSD$"); static device_attach_t mv_ehci_attach; static device_detach_t mv_ehci_detach; -static device_shutdown_t mv_ehci_shutdown; -static device_suspend_t mv_ehci_suspend; -static device_resume_t mv_ehci_resume; static int err_intr(void *arg); @@ -102,45 +99,6 @@ static void *ih_err; #define MV_USB_HOST_OVERFLOW (1 << 2) #define MV_USB_DEVICE_UNDERFLOW (1 << 3) -static int -mv_ehci_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_suspend(sc); - return (0); -} - -static int -mv_ehci_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -mv_ehci_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - - return (0); -} - static int mv_ehci_probe(device_t self) { @@ -372,9 +330,9 @@ static device_method_t ehci_methods[] = { DEVMETHOD(device_probe, mv_ehci_probe), DEVMETHOD(device_attach, mv_ehci_attach), DEVMETHOD(device_detach, mv_ehci_detach), - DEVMETHOD(device_suspend, mv_ehci_suspend), - DEVMETHOD(device_resume, mv_ehci_resume), - DEVMETHOD(device_shutdown, mv_ehci_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c index 8c19b2a1f9d..e293ec8d2c2 100644 --- a/sys/dev/usb/controller/ehci_pci.c +++ b/sys/dev/usb/controller/ehci_pci.c @@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include "usb_if.h" #define PCI_EHCI_VENDORID_ACERLABS 0x10b9 #define PCI_EHCI_VENDORID_AMD 0x1022 @@ -92,54 +93,10 @@ __FBSDID("$FreeBSD$"); #define PCI_EHCI_VENDORID_NVIDIA2 0x10DE #define PCI_EHCI_VENDORID_VIA 0x1106 -static void ehci_pci_takecontroller(device_t self); - static device_probe_t ehci_pci_probe; static device_attach_t ehci_pci_attach; static device_detach_t ehci_pci_detach; -static device_suspend_t ehci_pci_suspend; -static device_resume_t ehci_pci_resume; -static device_shutdown_t ehci_pci_shutdown; - -static int -ehci_pci_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_suspend(sc); - return (0); -} - -static int -ehci_pci_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_pci_takecontroller(self); - ehci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -ehci_pci_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - - return (0); -} +static usb_take_controller_t ehci_pci_take_controller; static const char * ehci_pci_match(device_t self) @@ -418,7 +375,7 @@ ehci_pci_attach(device_t self) sc->sc_intr_hdl = NULL; goto error; } - ehci_pci_takecontroller(self); + ehci_pci_take_controller(self); /* Undocumented quirks taken from Linux */ @@ -530,8 +487,8 @@ ehci_pci_detach(device_t self) return (0); } -static void -ehci_pci_takecontroller(device_t self) +static int +ehci_pci_take_controller(device_t self) { ehci_softc_t *sc = device_get_softc(self); uint32_t cparams; @@ -573,22 +530,25 @@ ehci_pci_takecontroller(device_t self) usb_pause_mtx(NULL, hz / 100); /* wait 10ms */ } } + return (0); } -static driver_t ehci_driver = -{ - .name = "ehci", - .methods = (device_method_t[]){ - /* device interface */ - DEVMETHOD(device_probe, ehci_pci_probe), - DEVMETHOD(device_attach, ehci_pci_attach), - DEVMETHOD(device_detach, ehci_pci_detach), - DEVMETHOD(device_suspend, ehci_pci_suspend), - DEVMETHOD(device_resume, ehci_pci_resume), - DEVMETHOD(device_shutdown, ehci_pci_shutdown), +static device_method_t ehci_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ehci_pci_probe), + DEVMETHOD(device_attach, ehci_pci_attach), + DEVMETHOD(device_detach, ehci_pci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(usb_take_controller, ehci_pci_take_controller), - DEVMETHOD_END - }, + DEVMETHOD_END +}; + +static driver_t ehci_driver = { + .name = "ehci", + .methods = ehci_pci_methods, .size = sizeof(struct ehci_softc), }; diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c index be32b2b5feb..d463052d0ef 100644 --- a/sys/dev/usb/controller/musb_otg.c +++ b/sys/dev/usb/controller/musb_otg.c @@ -1910,16 +1910,16 @@ musbotg_uninit(struct musbotg_softc *sc) USB_BUS_UNLOCK(&sc->sc_bus); } -void +static void musbotg_suspend(struct musbotg_softc *sc) { - return; + /* TODO */ } -void +static void musbotg_resume(struct musbotg_softc *sc) { - return; + /* TODO */ } static void @@ -2776,6 +2776,26 @@ musbotg_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, } } +static void +musbotg_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct musbotg_softc *sc = MUSBOTG_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + musbotg_suspend(sc); + break; + case USB_HW_POWER_SHUTDOWN: + musbotg_uninit(sc); + break; + case USB_HW_POWER_RESUME: + musbotg_resume(sc); + break; + default: + break; + } +} + struct usb_bus_methods musbotg_bus_methods = { .endpoint_init = &musbotg_ep_init, @@ -2786,4 +2806,5 @@ struct usb_bus_methods musbotg_bus_methods = .clear_stall = &musbotg_clear_stall, .roothub_exec = &musbotg_roothub_exec, .xfer_poll = &musbotg_do_poll, + .set_hw_power_sleep = &musbotg_set_hw_power_sleep, }; diff --git a/sys/dev/usb/controller/musb_otg.h b/sys/dev/usb/controller/musb_otg.h index e8eafca6fb1..3b889a9dfe1 100644 --- a/sys/dev/usb/controller/musb_otg.h +++ b/sys/dev/usb/controller/musb_otg.h @@ -398,8 +398,6 @@ struct musbotg_softc { usb_error_t musbotg_init(struct musbotg_softc *sc); void musbotg_uninit(struct musbotg_softc *sc); -void musbotg_suspend(struct musbotg_softc *sc); -void musbotg_resume(struct musbotg_softc *sc); void musbotg_interrupt(struct musbotg_softc *sc); void musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on); diff --git a/sys/dev/usb/controller/musb_otg_atmelarm.c b/sys/dev/usb/controller/musb_otg_atmelarm.c index b301e09d48a..bb3e60a6d45 100644 --- a/sys/dev/usb/controller/musb_otg_atmelarm.c +++ b/sys/dev/usb/controller/musb_otg_atmelarm.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); static device_probe_t musbotg_probe; static device_attach_t musbotg_attach; static device_detach_t musbotg_detach; -static device_shutdown_t musbotg_shutdown; struct musbotg_super_softc { struct musbotg_softc sc_otg; /* must be first */ @@ -218,35 +217,22 @@ musbotg_detach(device_t dev) return (0); } -static int -musbotg_shutdown(device_t dev) -{ - struct musbotg_super_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_shutdown(dev); - if (err) - return (err); - - musbotg_uninit(&sc->sc_otg); - - return (0); -} - static device_method_t musbotg_methods[] = { /* Device interface */ DEVMETHOD(device_probe, musbotg_probe), DEVMETHOD(device_attach, musbotg_attach), DEVMETHOD(device_detach, musbotg_detach), - DEVMETHOD(device_shutdown, musbotg_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t musbotg_driver = { - "musbotg", - musbotg_methods, - sizeof(struct musbotg_super_softc), + .name = "musbotg", + .methods = musbotg_methods, + .size = sizeof(struct musbotg_super_softc), }; static devclass_t musbotg_devclass; diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c index fa2d6070798..93c2bb22091 100644 --- a/sys/dev/usb/controller/ohci.c +++ b/sys/dev/usb/controller/ohci.c @@ -166,7 +166,7 @@ ohci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb) } static usb_error_t -ohci_controller_init(ohci_softc_t *sc) +ohci_controller_init(ohci_softc_t *sc, int do_suspend) { struct usb_page_search buf_res; uint32_t i; @@ -233,6 +233,11 @@ reset: } #endif + if (do_suspend) { + OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_SUSPEND); + return (USB_ERR_NORMAL_COMPLETION); + } + /* The controller is now in SUSPEND state, we have 2ms to finish. */ /* set up HC registers */ @@ -415,13 +420,12 @@ ohci_init(ohci_softc_t *sc) sc->sc_bus.usbrev = USB_REV_1_0; - if (ohci_controller_init(sc)) { + if (ohci_controller_init(sc, 0) != 0) return (USB_ERR_INVAL); - } else { - /* catch any lost interrupts */ - ohci_do_poll(&sc->sc_bus); - return (USB_ERR_NORMAL_COMPLETION); - } + + /* catch any lost interrupts */ + ohci_do_poll(&sc->sc_bus); + return (USB_ERR_NORMAL_COMPLETION); } /* @@ -445,75 +449,32 @@ ohci_detach(struct ohci_softc *sc) usb_callout_drain(&sc->sc_tmo_rhsc); } -/* NOTE: suspend/resume is called from - * interrupt context and cannot sleep! - */ -void +static void ohci_suspend(ohci_softc_t *sc) { - uint32_t ctl; - - USB_BUS_LOCK(&sc->sc_bus); + DPRINTF("\n"); #ifdef USB_DEBUG - DPRINTF("\n"); - if (ohcidebug > 2) { + if (ohcidebug > 2) ohci_dumpregs(sc); - } #endif - ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; - if (sc->sc_control == 0) { - /* - * Preserve register values, in case that APM BIOS - * does not recover them. - */ - sc->sc_control = ctl; - sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE); - } - ctl |= OHCI_HCFS_SUSPEND; - OWRITE4(sc, OHCI_CONTROL, ctl); - - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(USB_RESUME_WAIT)); - - USB_BUS_UNLOCK(&sc->sc_bus); + /* reset HC and leave it suspended */ + ohci_controller_init(sc, 1); } -void +static void ohci_resume(ohci_softc_t *sc) { - uint32_t ctl; + DPRINTF("\n"); #ifdef USB_DEBUG - DPRINTF("\n"); - if (ohcidebug > 2) { + if (ohcidebug > 2) ohci_dumpregs(sc); - } #endif + /* some broken BIOSes never initialize the Controller chip */ - ohci_controller_init(sc); - - USB_BUS_LOCK(&sc->sc_bus); - if (sc->sc_intre) { - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, - sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); - } - if (sc->sc_control) - ctl = sc->sc_control; - else - ctl = OREAD4(sc, OHCI_CONTROL); - ctl |= OHCI_HCFS_RESUME; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(USB_RESUME_DELAY)); - ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(USB_RESUME_RECOVERY)); - sc->sc_control = sc->sc_intre = 0; - - USB_BUS_UNLOCK(&sc->sc_bus); + ohci_controller_init(sc, 0); /* catch any lost interrupts */ ohci_do_poll(&sc->sc_bus); @@ -2712,6 +2673,24 @@ ohci_device_suspend(struct usb_device *udev) return; } +static void +ohci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct ohci_softc *sc = OHCI_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + case USB_HW_POWER_SHUTDOWN: + ohci_suspend(sc); + break; + case USB_HW_POWER_RESUME: + ohci_resume(sc); + break; + default: + break; + } +} + static void ohci_set_hw_power(struct usb_bus *bus) { @@ -2756,6 +2735,7 @@ struct usb_bus_methods ohci_bus_methods = .device_resume = ohci_device_resume, .device_suspend = ohci_device_suspend, .set_hw_power = ohci_set_hw_power, + .set_hw_power_sleep = ohci_set_hw_power_sleep, .roothub_exec = ohci_roothub_exec, .xfer_poll = ohci_do_poll, }; diff --git a/sys/dev/usb/controller/ohci.h b/sys/dev/usb/controller/ohci.h index d85c2c940e1..9d8ac7dc832 100644 --- a/sys/dev/usb/controller/ohci.h +++ b/sys/dev/usb/controller/ohci.h @@ -241,8 +241,6 @@ typedef struct ohci_softc { bus_space_handle_t sc_io_hdl; uint32_t sc_eintrs; /* enabled interrupts */ - uint32_t sc_control; /* Preserved during suspend/standby */ - uint32_t sc_intre; uint16_t sc_intr_stat[OHCI_NO_EDS]; uint16_t sc_id_vendor; @@ -260,8 +258,6 @@ usb_bus_mem_cb_t ohci_iterate_hw_softc; usb_error_t ohci_init(ohci_softc_t *sc); void ohci_detach(struct ohci_softc *sc); -void ohci_suspend(ohci_softc_t *sc); -void ohci_resume(ohci_softc_t *sc); void ohci_interrupt(ohci_softc_t *sc); #endif /* _OHCI_H_ */ diff --git a/sys/dev/usb/controller/ohci_atmelarm.c b/sys/dev/usb/controller/ohci_atmelarm.c index 177c926c01c..643b4d17bc4 100644 --- a/sys/dev/usb/controller/ohci_atmelarm.c +++ b/sys/dev/usb/controller/ohci_atmelarm.c @@ -221,15 +221,17 @@ static device_method_t ohci_methods[] = { DEVMETHOD(device_probe, ohci_atmelarm_probe), DEVMETHOD(device_attach, ohci_atmelarm_attach), DEVMETHOD(device_detach, ohci_atmelarm_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ohci_driver = { - "ohci", - ohci_methods, - sizeof(struct at91_ohci_softc), + .name = "ohci", + .methods = ohci_methods, + .size = sizeof(struct at91_ohci_softc), }; static devclass_t ohci_devclass; diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c index c8690c99f41..864376b9204 100644 --- a/sys/dev/usb/controller/ohci_pci.c +++ b/sys/dev/usb/controller/ohci_pci.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include "usb_if.h" #define PCI_OHCI_VENDORID_ACERLABS 0x10b9 #define PCI_OHCI_VENDORID_AMD 0x1022 @@ -92,28 +93,13 @@ __FBSDID("$FreeBSD$"); static device_probe_t ohci_pci_probe; static device_attach_t ohci_pci_attach; static device_detach_t ohci_pci_detach; -static device_suspend_t ohci_pci_suspend; -static device_resume_t ohci_pci_resume; +static usb_take_controller_t ohci_pci_take_controller; static int -ohci_pci_suspend(device_t self) +ohci_pci_take_controller(device_t self) { - ohci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) { - return (err); - } - ohci_suspend(sc); - return (0); -} - -static int -ohci_pci_resume(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - uint32_t reg, int_line; + uint32_t reg; + uint32_t int_line; if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) { device_printf(self, "chip is in D%d mode " @@ -124,9 +110,6 @@ ohci_pci_resume(device_t self) pci_write_config(self, PCI_CBMEM, reg, 4); pci_write_config(self, PCIR_INTLINE, int_line, 4); } - ohci_resume(sc); - - bus_generic_resume(self); return (0); } @@ -381,20 +364,22 @@ ohci_pci_detach(device_t self) return (0); } -static driver_t ohci_driver = -{ - .name = "ohci", - .methods = (device_method_t[]){ - /* device interface */ - DEVMETHOD(device_probe, ohci_pci_probe), - DEVMETHOD(device_attach, ohci_pci_attach), - DEVMETHOD(device_detach, ohci_pci_detach), - DEVMETHOD(device_suspend, ohci_pci_suspend), - DEVMETHOD(device_resume, ohci_pci_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), +static device_method_t ohci_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ohci_pci_probe), + DEVMETHOD(device_attach, ohci_pci_attach), + DEVMETHOD(device_detach, ohci_pci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(usb_take_controller, ohci_pci_take_controller), - DEVMETHOD_END - }, + DEVMETHOD_END +}; + +static driver_t ohci_driver = { + .name = "ohci", + .methods = ohci_pci_methods, .size = sizeof(struct ohci_softc), }; diff --git a/sys/dev/usb/controller/ohci_s3c24x0.c b/sys/dev/usb/controller/ohci_s3c24x0.c index b0907ad8006..225a2d201e3 100644 --- a/sys/dev/usb/controller/ohci_s3c24x0.c +++ b/sys/dev/usb/controller/ohci_s3c24x0.c @@ -198,15 +198,17 @@ static device_method_t ohci_methods[] = { DEVMETHOD(device_probe, ohci_s3c24x0_probe), DEVMETHOD(device_attach, ohci_s3c24x0_attach), DEVMETHOD(device_detach, ohci_s3c24x0_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ohci_driver = { - "ohci", - ohci_methods, - sizeof(struct ohci_softc), + .name = "ohci", + .methods = ohci_methods, + .size = sizeof(struct ohci_softc), }; static devclass_t ohci_devclass; diff --git a/sys/dev/usb/controller/uhci.c b/sys/dev/usb/controller/uhci.c index c365e01c30a..d9091c98e48 100644 --- a/sys/dev/usb/controller/uhci.c +++ b/sys/dev/usb/controller/uhci.c @@ -373,9 +373,10 @@ done_1: done_2: - /* reload the configuration */ - UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); - UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); + /* reset frame number */ + UWRITE2(sc, UHCI_FRNUM, 0); + /* set default SOF value */ + UWRITE1(sc, UHCI_SOF, 0x40); USB_BUS_UNLOCK(&sc->sc_bus); @@ -463,9 +464,6 @@ uhci_init(uhci_softc_t *sc) uhci_dumpregs(sc); } #endif - sc->sc_saved_sof = 0x40; /* default value */ - sc->sc_saved_frnum = 0; /* default frame number */ - /* * Setup QH's */ @@ -658,24 +656,16 @@ uhci_init(uhci_softc_t *sc) return (0); } -/* NOTE: suspend/resume is called from - * interrupt context and cannot sleep! - */ - -void +static void uhci_suspend(uhci_softc_t *sc) { - USB_BUS_LOCK(&sc->sc_bus); - #ifdef USB_DEBUG if (uhcidebug > 2) { uhci_dumpregs(sc); } #endif - /* save some state if BIOS doesn't */ - sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); - sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); + USB_BUS_LOCK(&sc->sc_bus); /* stop the controller */ @@ -685,13 +675,10 @@ uhci_suspend(uhci_softc_t *sc) UHCICMD(sc, UHCI_CMD_EGSM); - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(USB_RESUME_WAIT)); - USB_BUS_UNLOCK(&sc->sc_bus); } -void +static void uhci_resume(uhci_softc_t *sc) { USB_BUS_LOCK(&sc->sc_bus); @@ -704,21 +691,17 @@ uhci_resume(uhci_softc_t *sc) UHCICMD(sc, UHCI_CMD_FGR); - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(USB_RESUME_DELAY)); - /* and start traffic again */ uhci_start(sc); -#ifdef USB_DEBUG - if (uhcidebug > 2) { - uhci_dumpregs(sc); - } -#endif - USB_BUS_UNLOCK(&sc->sc_bus); +#ifdef USB_DEBUG + if (uhcidebug > 2) + uhci_dumpregs(sc); +#endif + /* catch lost interrupts */ uhci_do_poll(&sc->sc_bus); } @@ -3178,6 +3161,24 @@ uhci_device_suspend(struct usb_device *udev) return; } +static void +uhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct uhci_softc *sc = UHCI_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + case USB_HW_POWER_SHUTDOWN: + uhci_suspend(sc); + break; + case USB_HW_POWER_RESUME: + uhci_resume(sc); + break; + default: + break; + } +} + static void uhci_set_hw_power(struct usb_bus *bus) { @@ -3225,6 +3226,7 @@ struct usb_bus_methods uhci_bus_methods = .device_resume = uhci_device_resume, .device_suspend = uhci_device_suspend, .set_hw_power = uhci_set_hw_power, + .set_hw_power_sleep = uhci_set_hw_power_sleep, .roothub_exec = uhci_roothub_exec, .xfer_poll = uhci_do_poll, }; diff --git a/sys/dev/usb/controller/uhci.h b/sys/dev/usb/controller/uhci.h index 0878e798e74..8a6ce447031 100644 --- a/sys/dev/usb/controller/uhci.h +++ b/sys/dev/usb/controller/uhci.h @@ -230,13 +230,11 @@ typedef struct uhci_softc { uint32_t sc_loops; /* number of QHs that wants looping */ uint16_t sc_intr_stat[UHCI_IFRAMELIST_COUNT]; - uint16_t sc_saved_frnum; uint8_t sc_addr; /* device address */ uint8_t sc_conf; /* device configuration */ uint8_t sc_isreset; /* bits set if a root hub is reset */ uint8_t sc_isresumed; /* bits set if a port was resumed */ - uint8_t sc_saved_sof; uint8_t sc_hub_idata[1]; char sc_vendor[16]; /* vendor string for root hub */ @@ -245,8 +243,6 @@ typedef struct uhci_softc { usb_bus_mem_cb_t uhci_iterate_hw_softc; usb_error_t uhci_init(uhci_softc_t *sc); -void uhci_suspend(uhci_softc_t *sc); -void uhci_resume(uhci_softc_t *sc); void uhci_reset(uhci_softc_t *sc); void uhci_interrupt(uhci_softc_t *sc); diff --git a/sys/dev/usb/controller/uhci_pci.c b/sys/dev/usb/controller/uhci_pci.c index 4b04f255a54..454b904de81 100644 --- a/sys/dev/usb/controller/uhci_pci.c +++ b/sys/dev/usb/controller/uhci_pci.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include "usb_if.h" #define PCI_UHCI_VENDORID_INTEL 0x8086 #define PCI_UHCI_VENDORID_VIA 0x1106 @@ -83,33 +84,13 @@ __FBSDID("$FreeBSD$"); static device_probe_t uhci_pci_probe; static device_attach_t uhci_pci_attach; static device_detach_t uhci_pci_detach; -static device_suspend_t uhci_pci_suspend; -static device_resume_t uhci_pci_resume; +static usb_take_controller_t uhci_pci_take_controller; static int -uhci_pci_suspend(device_t self) +uhci_pci_take_controller(device_t self) { - uhci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) { - return (err); - } - uhci_suspend(sc); - return (0); -} - -static int -uhci_pci_resume(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); - uhci_resume(sc); - - bus_generic_resume(self); return (0); } @@ -446,21 +427,22 @@ uhci_pci_detach(device_t self) return (0); } -static driver_t uhci_driver = -{ +static device_method_t uhci_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uhci_pci_probe), + DEVMETHOD(device_attach, uhci_pci_attach), + DEVMETHOD(device_detach, uhci_pci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(usb_take_controller, uhci_pci_take_controller), + + DEVMETHOD_END +}; + +static driver_t uhci_driver = { .name = "uhci", - .methods = (device_method_t[]){ - /* device interface */ - DEVMETHOD(device_probe, uhci_pci_probe), - DEVMETHOD(device_attach, uhci_pci_attach), - DEVMETHOD(device_detach, uhci_pci_detach), - - DEVMETHOD(device_suspend, uhci_pci_suspend), - DEVMETHOD(device_resume, uhci_pci_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - DEVMETHOD_END - }, + .methods = uhci_pci_methods, .size = sizeof(struct uhci_softc), }; diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c index 7ff0bc0faf3..f31ab5b49ab 100644 --- a/sys/dev/usb/controller/usb_controller.c +++ b/sys/dev/usb/controller/usb_controller.c @@ -61,12 +61,16 @@ #include #include #include +#include "usb_if.h" /* function prototypes */ static device_probe_t usb_probe; static device_attach_t usb_attach; static device_detach_t usb_detach; +static device_suspend_t usb_suspend; +static device_resume_t usb_resume; +static device_shutdown_t usb_shutdown; static void usb_attach_sub(device_t, struct usb_bus *); @@ -91,9 +95,9 @@ static device_method_t usb_methods[] = { DEVMETHOD(device_probe, usb_probe), DEVMETHOD(device_attach, usb_attach), DEVMETHOD(device_detach, usb_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, usb_suspend), + DEVMETHOD(device_resume, usb_resume), + DEVMETHOD(device_shutdown, usb_shutdown), {0, 0} }; @@ -182,12 +186,12 @@ usb_detach(device_t dev) usb_root_mount_rel(bus); USB_BUS_LOCK(bus); - if (usb_proc_msignal(&bus->explore_proc, - &bus->detach_msg[0], &bus->detach_msg[1])) { - /* ignore */ - } - /* Wait for detach to complete */ + /* Queue detach job */ + usb_proc_msignal(&bus->explore_proc, + &bus->detach_msg[0], &bus->detach_msg[1]); + + /* Wait for detach to complete */ usb_proc_mwait(&bus->explore_proc, &bus->detach_msg[0], &bus->detach_msg[1]); @@ -212,6 +216,75 @@ usb_detach(device_t dev) return (0); } +/*------------------------------------------------------------------------* + * usb_suspend + *------------------------------------------------------------------------*/ +static int +usb_suspend(device_t dev) +{ + struct usb_bus *bus = device_get_softc(dev); + + DPRINTF("\n"); + + if (bus == NULL) { + /* was never setup properly */ + return (0); + } + + USB_BUS_LOCK(bus); + usb_proc_msignal(&bus->explore_proc, + &bus->suspend_msg[0], &bus->suspend_msg[1]); + USB_BUS_UNLOCK(bus); + + return (0); +} + +/*------------------------------------------------------------------------* + * usb_resume + *------------------------------------------------------------------------*/ +static int +usb_resume(device_t dev) +{ + struct usb_bus *bus = device_get_softc(dev); + + DPRINTF("\n"); + + if (bus == NULL) { + /* was never setup properly */ + return (0); + } + + USB_BUS_LOCK(bus); + usb_proc_msignal(&bus->explore_proc, + &bus->resume_msg[0], &bus->resume_msg[1]); + USB_BUS_UNLOCK(bus); + + return (0); +} + +/*------------------------------------------------------------------------* + * usb_shutdown + *------------------------------------------------------------------------*/ +static int +usb_shutdown(device_t dev) +{ + struct usb_bus *bus = device_get_softc(dev); + + DPRINTF("\n"); + + if (bus == NULL) { + /* was never setup properly */ + return (0); + } + + USB_BUS_LOCK(bus); + usb_proc_msignal(&bus->explore_proc, + &bus->shutdown_msg[0], &bus->shutdown_msg[1]); + USB_BUS_UNLOCK(bus); + + return (0); +} + /*------------------------------------------------------------------------* * usb_bus_explore * @@ -226,6 +299,9 @@ usb_bus_explore(struct usb_proc_msg *pm) bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; + if (bus->no_explore != 0) + return; + if (udev && udev->hub) { if (bus->do_probe) { @@ -296,6 +372,133 @@ usb_bus_detach(struct usb_proc_msg *pm) bus->bdev = NULL; } +/*------------------------------------------------------------------------* + * usb_bus_suspend + * + * This function is used to suspend the USB contoller. + *------------------------------------------------------------------------*/ +static void +usb_bus_suspend(struct usb_proc_msg *pm) +{ + struct usb_bus *bus; + struct usb_device *udev; + usb_error_t err; + + bus = ((struct usb_bus_msg *)pm)->bus; + udev = bus->devices[USB_ROOT_HUB_ADDR]; + + if (udev == NULL || bus->bdev == NULL) + return; + + bus_generic_shutdown(bus->bdev); + + usbd_enum_lock(udev); + + err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); + if (err) + device_printf(bus->bdev, "Could not unconfigure root HUB\n"); + + USB_BUS_LOCK(bus); + bus->hw_power_state = 0; + bus->no_explore = 1; + USB_BUS_UNLOCK(bus); + + if (bus->methods->set_hw_power != NULL) + (bus->methods->set_hw_power) (bus); + + if (bus->methods->set_hw_power_sleep != NULL) + (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND); + + usbd_enum_unlock(udev); +} + +/*------------------------------------------------------------------------* + * usb_bus_resume + * + * This function is used to resume the USB contoller. + *------------------------------------------------------------------------*/ +static void +usb_bus_resume(struct usb_proc_msg *pm) +{ + struct usb_bus *bus; + struct usb_device *udev; + usb_error_t err; + + bus = ((struct usb_bus_msg *)pm)->bus; + udev = bus->devices[USB_ROOT_HUB_ADDR]; + + if (udev == NULL || bus->bdev == NULL) + return; + + usbd_enum_lock(udev); +#if 0 + DEVMETHOD(usb_take_controller, NULL); /* dummy */ +#endif + USB_TAKE_CONTROLLER(device_get_parent(bus->bdev)); + + USB_BUS_LOCK(bus); + bus->hw_power_state = + USB_HW_POWER_CONTROL | + USB_HW_POWER_BULK | + USB_HW_POWER_INTERRUPT | + USB_HW_POWER_ISOC | + USB_HW_POWER_NON_ROOT_HUB; + bus->no_explore = 0; + USB_BUS_UNLOCK(bus); + + if (bus->methods->set_hw_power_sleep != NULL) + (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_RESUME); + + if (bus->methods->set_hw_power != NULL) + (bus->methods->set_hw_power) (bus); + + err = usbd_set_config_index(udev, 0); + if (err) + device_printf(bus->bdev, "Could not configure root HUB\n"); + + usbd_enum_unlock(udev); +} + +/*------------------------------------------------------------------------* + * usb_bus_shutdown + * + * This function is used to shutdown the USB contoller. + *------------------------------------------------------------------------*/ +static void +usb_bus_shutdown(struct usb_proc_msg *pm) +{ + struct usb_bus *bus; + struct usb_device *udev; + usb_error_t err; + + bus = ((struct usb_bus_msg *)pm)->bus; + udev = bus->devices[USB_ROOT_HUB_ADDR]; + + if (udev == NULL || bus->bdev == NULL) + return; + + bus_generic_shutdown(bus->bdev); + + usbd_enum_lock(udev); + + err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); + if (err) + device_printf(bus->bdev, "Could not unconfigure root HUB\n"); + + USB_BUS_LOCK(bus); + bus->hw_power_state = 0; + bus->no_explore = 1; + USB_BUS_UNLOCK(bus); + + if (bus->methods->set_hw_power != NULL) + (bus->methods->set_hw_power) (bus); + + if (bus->methods->set_hw_power_sleep != NULL) + (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN); + + usbd_enum_unlock(udev); +} + static void usb_power_wdog(void *arg) { @@ -374,8 +577,6 @@ usb_bus_attach(struct usb_proc_msg *pm) return; } - USB_BUS_UNLOCK(bus); - /* default power_mask value */ bus->hw_power_state = USB_HW_POWER_CONTROL | @@ -384,13 +585,15 @@ usb_bus_attach(struct usb_proc_msg *pm) USB_HW_POWER_ISOC | USB_HW_POWER_NON_ROOT_HUB; + USB_BUS_UNLOCK(bus); + /* make sure power is set at least once */ if (bus->methods->set_hw_power != NULL) { (bus->methods->set_hw_power) (bus); } - /* Allocate the Root USB device */ + /* allocate the Root USB device */ child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1, speed, USB_MODE_HOST); @@ -456,6 +659,21 @@ usb_attach_sub(device_t dev, struct usb_bus *bus) bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach; bus->attach_msg[1].bus = bus; + bus->suspend_msg[0].hdr.pm_callback = &usb_bus_suspend; + bus->suspend_msg[0].bus = bus; + bus->suspend_msg[1].hdr.pm_callback = &usb_bus_suspend; + bus->suspend_msg[1].bus = bus; + + bus->resume_msg[0].hdr.pm_callback = &usb_bus_resume; + bus->resume_msg[0].bus = bus; + bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume; + bus->resume_msg[1].bus = bus; + + bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown; + bus->shutdown_msg[0].bus = bus; + bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown; + bus->shutdown_msg[1].bus = bus; + /* Create USB explore and callback processes */ if (usb_proc_create(&bus->giant_callback_proc, @@ -477,10 +695,8 @@ usb_attach_sub(device_t dev, struct usb_bus *bus) } else { /* Get final attach going */ USB_BUS_LOCK(bus); - if (usb_proc_msignal(&bus->explore_proc, - &bus->attach_msg[0], &bus->attach_msg[1])) { - /* ignore */ - } + usb_proc_msignal(&bus->explore_proc, + &bus->attach_msg[0], &bus->attach_msg[1]); USB_BUS_UNLOCK(bus); /* Do initial explore */ @@ -602,4 +818,3 @@ usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb) mtx_destroy(&bus->bus_mtx); } - diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c index b98043e5155..612bc81bb20 100644 --- a/sys/dev/usb/controller/uss820dci.c +++ b/sys/dev/usb/controller/uss820dci.c @@ -1513,16 +1513,16 @@ uss820dci_uninit(struct uss820dci_softc *sc) USB_BUS_UNLOCK(&sc->sc_bus); } -void +static void uss820dci_suspend(struct uss820dci_softc *sc) { - return; + /* TODO */ } -void +static void uss820dci_resume(struct uss820dci_softc *sc) { - return; + /* TODO */ } static void @@ -2360,6 +2360,26 @@ uss820dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc } } +static void +uss820dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + uss820dci_suspend(sc); + break; + case USB_HW_POWER_SHUTDOWN: + uss820dci_uninit(sc); + break; + case USB_HW_POWER_RESUME: + uss820dci_resume(sc); + break; + default: + break; + } +} + struct usb_bus_methods uss820dci_bus_methods = { .endpoint_init = &uss820dci_ep_init, @@ -2370,4 +2390,5 @@ struct usb_bus_methods uss820dci_bus_methods = .clear_stall = &uss820dci_clear_stall, .roothub_exec = &uss820dci_roothub_exec, .xfer_poll = &uss820dci_do_poll, + .set_hw_power_sleep = uss820dci_set_hw_power_sleep, }; diff --git a/sys/dev/usb/controller/uss820dci.h b/sys/dev/usb/controller/uss820dci.h index e158c1c10f9..8a27f15144d 100644 --- a/sys/dev/usb/controller/uss820dci.h +++ b/sys/dev/usb/controller/uss820dci.h @@ -349,8 +349,6 @@ struct uss820dci_softc { usb_error_t uss820dci_init(struct uss820dci_softc *sc); void uss820dci_uninit(struct uss820dci_softc *sc); -void uss820dci_suspend(struct uss820dci_softc *sc); -void uss820dci_resume(struct uss820dci_softc *sc); void uss820dci_interrupt(struct uss820dci_softc *sc); #endif /* _USS820_DCI_H_ */ diff --git a/sys/dev/usb/controller/uss820dci_atmelarm.c b/sys/dev/usb/controller/uss820dci_atmelarm.c index e3742b85fb5..7fd83a229cc 100644 --- a/sys/dev/usb/controller/uss820dci_atmelarm.c +++ b/sys/dev/usb/controller/uss820dci_atmelarm.c @@ -63,18 +63,15 @@ __FBSDID("$FreeBSD$"); static device_probe_t uss820_atmelarm_probe; static device_attach_t uss820_atmelarm_attach; static device_detach_t uss820_atmelarm_detach; -static device_suspend_t uss820_atmelarm_suspend; -static device_resume_t uss820_atmelarm_resume; -static device_shutdown_t uss820_atmelarm_shutdown; static device_method_t uss820dci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uss820_atmelarm_probe), DEVMETHOD(device_attach, uss820_atmelarm_attach), DEVMETHOD(device_detach, uss820_atmelarm_detach), - DEVMETHOD(device_suspend, uss820_atmelarm_suspend), - DEVMETHOD(device_resume, uss820_atmelarm_resume), - DEVMETHOD(device_shutdown, uss820_atmelarm_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; @@ -92,47 +89,6 @@ MODULE_DEPEND(uss820, usb, 1, 1, 1); static const char *const uss820_desc = "USS820 USB Device Controller"; -static int -uss820_atmelarm_suspend(device_t dev) -{ - struct uss820dci_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_suspend(dev); - if (err == 0) { - uss820dci_suspend(sc); - } - return (err); -} - -static int -uss820_atmelarm_resume(device_t dev) -{ - struct uss820dci_softc *sc = device_get_softc(dev); - int err; - - uss820dci_resume(sc); - - err = bus_generic_resume(dev); - - return (err); -} - -static int -uss820_atmelarm_shutdown(device_t dev) -{ - struct uss820dci_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_shutdown(dev); - if (err) - return (err); - - uss820dci_uninit(sc); - - return (0); -} - static int uss820_atmelarm_probe(device_t dev) { diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index 75b3af82833..80877acabd5 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -58,23 +58,22 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include "usb_if.h" static device_probe_t xhci_pci_probe; static device_attach_t xhci_pci_attach; static device_detach_t xhci_pci_detach; -static device_suspend_t xhci_pci_suspend; -static device_resume_t xhci_pci_resume; -static device_shutdown_t xhci_pci_shutdown; -static void xhci_pci_takecontroller(device_t); +static usb_take_controller_t xhci_pci_take_controller; static device_method_t xhci_device_methods[] = { /* device interface */ DEVMETHOD(device_probe, xhci_pci_probe), DEVMETHOD(device_attach, xhci_pci_attach), DEVMETHOD(device_detach, xhci_pci_detach), - DEVMETHOD(device_suspend, xhci_pci_suspend), - DEVMETHOD(device_resume, xhci_pci_resume), - DEVMETHOD(device_shutdown, xhci_pci_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(usb_take_controller, xhci_pci_take_controller), DEVMETHOD_END }; @@ -90,45 +89,6 @@ static devclass_t xhci_devclass; DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, 0, 0); MODULE_DEPEND(xhci, usb, 1, 1, 1); -static int -xhci_pci_suspend(device_t self) -{ - struct xhci_softc *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - xhci_suspend(sc); - return (0); -} - -static int -xhci_pci_resume(device_t self) -{ - struct xhci_softc *sc = device_get_softc(self); - - xhci_pci_takecontroller(self); - xhci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -xhci_pci_shutdown(device_t self) -{ - struct xhci_softc *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - xhci_shutdown(sc); - - return (0); -} static const char * xhci_pci_match(device_t self) @@ -209,7 +169,7 @@ xhci_pci_attach(device_t self) sc->sc_intr_hdl = NULL; goto error; } - xhci_pci_takecontroller(self); + xhci_pci_take_controller(self); err = xhci_halt_controller(sc); @@ -268,8 +228,8 @@ xhci_pci_detach(device_t self) return (0); } -static void -xhci_pci_takecontroller(device_t self) +static int +xhci_pci_take_controller(device_t self) { struct xhci_softc *sc = device_get_softc(self); uint32_t cparams; @@ -312,4 +272,5 @@ xhci_pci_takecontroller(device_t self) usb_pause_mtx(NULL, hz / 100); /* wait 10ms */ } } + return (0); } diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h index 1dd9d6a1f8c..07207cf6190 100644 --- a/sys/dev/usb/usb_bus.h +++ b/sys/dev/usb/usb_bus.h @@ -69,6 +69,9 @@ struct usb_bus { struct usb_bus_msg explore_msg[2]; struct usb_bus_msg detach_msg[2]; struct usb_bus_msg attach_msg[2]; + struct usb_bus_msg suspend_msg[2]; + struct usb_bus_msg resume_msg[2]; + struct usb_bus_msg shutdown_msg[2]; /* * This mutex protects the USB hardware: */ @@ -98,7 +101,8 @@ struct usb_bus { enum usb_revision usbrev; /* USB revision. See "USB_REV_XXX". */ uint8_t devices_max; /* maximum number of USB devices */ - uint8_t do_probe; /* set if USB BUS should be re-probed */ + uint8_t do_probe; /* set if USB should be re-probed */ + uint8_t no_explore; /* don't explore USB ports */ /* * The scratch area can only be used inside the explore thread diff --git a/sys/dev/usb/usb_controller.h b/sys/dev/usb/usb_controller.h index 6b15dab993d..4ffc041ebb4 100644 --- a/sys/dev/usb/usb_controller.h +++ b/sys/dev/usb/usb_controller.h @@ -66,7 +66,7 @@ struct usb_bus_methods { void (*device_suspend) (struct usb_device *); void (*device_resume) (struct usb_device *); void (*set_hw_power) (struct usb_bus *); - + void (*set_hw_power_sleep) (struct usb_bus *, uint32_t); /* * The following flag is set if one or more control transfers are * active: @@ -92,6 +92,18 @@ struct usb_bus_methods { * are present on the given USB bus: */ #define USB_HW_POWER_NON_ROOT_HUB 0x10 + /* + * The following flag is set if we are suspending + */ +#define USB_HW_POWER_SUSPEND 0x20 + /* + * The following flag is set if we are resuming + */ +#define USB_HW_POWER_RESUME 0x40 + /* + * The following flag is set if we are shutting down + */ +#define USB_HW_POWER_SHUTDOWN 0x60 /* USB Device mode only - Mandatory */ diff --git a/sys/dev/usb/usb_if.m b/sys/dev/usb/usb_if.m index 926a2377006..b24fc2b386a 100644 --- a/sys/dev/usb/usb_if.m +++ b/sys/dev/usb/usb_if.m @@ -54,3 +54,13 @@ METHOD int handle_request { uint16_t offset; /* data offset */ uint8_t *pstate; /* set if transfer is complete, see USB_HR_XXX */ }; + +# Take controller from BIOS +# +# Return values: +# 0: Success +# Else: Failure +# +METHOD int take_controller { + device_t dev; +}; diff --git a/sys/mips/atheros/ar71xx_ehci.c b/sys/mips/atheros/ar71xx_ehci.c index 1f24d7cc949..c04e069b83a 100644 --- a/sys/mips/atheros/ar71xx_ehci.c +++ b/sys/mips/atheros/ar71xx_ehci.c @@ -65,52 +65,10 @@ struct ar71xx_ehci_softc { static device_attach_t ar71xx_ehci_attach; static device_detach_t ar71xx_ehci_detach; -static device_shutdown_t ar71xx_ehci_shutdown; -static device_suspend_t ar71xx_ehci_suspend; -static device_resume_t ar71xx_ehci_resume; bs_r_1_proto(reversed); bs_w_1_proto(reversed); -static int -ar71xx_ehci_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_suspend(sc); - return (0); -} - -static int -ar71xx_ehci_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -ar71xx_ehci_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - - return (0); -} - static int ar71xx_ehci_probe(device_t self) { @@ -280,17 +238,17 @@ static device_method_t ehci_methods[] = { DEVMETHOD(device_probe, ar71xx_ehci_probe), DEVMETHOD(device_attach, ar71xx_ehci_attach), DEVMETHOD(device_detach, ar71xx_ehci_detach), - DEVMETHOD(device_suspend, ar71xx_ehci_suspend), - DEVMETHOD(device_resume, ar71xx_ehci_resume), - DEVMETHOD(device_shutdown, ar71xx_ehci_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(struct ar71xx_ehci_softc), + .name = "ehci", + .methods = ehci_methods, + .size = sizeof(struct ar71xx_ehci_softc), }; static devclass_t ehci_devclass; diff --git a/sys/mips/atheros/ar71xx_ohci.c b/sys/mips/atheros/ar71xx_ohci.c index 9e0a63f075e..629237211f5 100644 --- a/sys/mips/atheros/ar71xx_ohci.c +++ b/sys/mips/atheros/ar71xx_ohci.c @@ -194,15 +194,17 @@ static device_method_t ohci_methods[] = { DEVMETHOD(device_probe, ar71xx_ohci_probe), DEVMETHOD(device_attach, ar71xx_ohci_attach), DEVMETHOD(device_detach, ar71xx_ohci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ohci_driver = { - "ohci", - ohci_methods, - sizeof(struct ar71xx_ohci_softc), + .name = "ohci", + .methods = ohci_methods, + .size = sizeof(struct ar71xx_ohci_softc), }; static devclass_t ohci_devclass; diff --git a/sys/mips/cavium/usb/octusb.c b/sys/mips/cavium/usb/octusb.c index d8ea9fbce75..9d6884bea1b 100644 --- a/sys/mips/cavium/usb/octusb.c +++ b/sys/mips/cavium/usb/octusb.c @@ -913,16 +913,16 @@ octusb_uninit(struct octusb_softc *sc) } -void +static void octusb_suspend(struct octusb_softc *sc) { - + /* TODO */ } -void +static void octusb_resume(struct octusb_softc *sc) { - + /* TODO */ } /*------------------------------------------------------------------------* @@ -1908,6 +1908,26 @@ octusb_set_hw_power(struct usb_bus *bus) DPRINTF("Nothing to do.\n"); } +static void +octusb_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) +{ + struct octusb_softc *sc = OCTUSB_BUS2SC(bus); + + switch (state) { + case USB_HW_POWER_SUSPEND: + octusb_suspend(sc); + break; + case USB_HW_POWER_SHUTDOWN: + octusb_uninit(sc); + break; + case USB_HW_POWER_RESUME: + octusb_resume(sc); + break; + default: + break; + } +} + struct usb_bus_methods octusb_bus_methods = { .endpoint_init = octusb_ep_init, .xfer_setup = octusb_xfer_setup, @@ -1916,6 +1936,7 @@ struct usb_bus_methods octusb_bus_methods = { .device_resume = octusb_device_resume, .device_suspend = octusb_device_suspend, .set_hw_power = octusb_set_hw_power, + .set_hw_power_sleep = octusb_set_hw_power_sleep, .roothub_exec = octusb_roothub_exec, .xfer_poll = octusb_do_poll, }; diff --git a/sys/mips/cavium/usb/octusb.h b/sys/mips/cavium/usb/octusb.h index 31f4fc0835b..41320ef1d1a 100644 --- a/sys/mips/cavium/usb/octusb.h +++ b/sys/mips/cavium/usb/octusb.h @@ -140,8 +140,6 @@ struct octusb_softc { usb_bus_mem_cb_t octusb_iterate_hw_softc; usb_error_t octusb_init(struct octusb_softc *); usb_error_t octusb_uninit(struct octusb_softc *); -void octusb_suspend(struct octusb_softc *); -void octusb_resume(struct octusb_softc *); void octusb_interrupt(struct octusb_softc *); #endif /* _OCTUSB_H_ */ diff --git a/sys/mips/cavium/usb/octusb_octeon.c b/sys/mips/cavium/usb/octusb_octeon.c index d160eda9a5f..4448f4e5090 100644 --- a/sys/mips/cavium/usb/octusb_octeon.c +++ b/sys/mips/cavium/usb/octusb_octeon.c @@ -182,36 +182,23 @@ octusb_octeon_detach(device_t dev) return (0); } -static int -octusb_octeon_shutdown(device_t dev) -{ - struct octusb_octeon_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_shutdown(dev); - if (err) - return (err); - - octusb_uninit(&sc->sc_dci); - - return (0); -} - static device_method_t octusb_octeon_methods[] = { /* Device interface */ DEVMETHOD(device_identify, octusb_octeon_identify), DEVMETHOD(device_probe, octusb_octeon_probe), DEVMETHOD(device_attach, octusb_octeon_attach), DEVMETHOD(device_detach, octusb_octeon_detach), - DEVMETHOD(device_shutdown, octusb_octeon_shutdown), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t octusb_octeon_driver = { - "octusb", - octusb_octeon_methods, - sizeof(struct octusb_octeon_softc), + .name = "octusb", + .methods = octusb_octeon_methods, + .size = sizeof(struct octusb_octeon_softc), }; static devclass_t octusb_octeon_devclass; diff --git a/sys/mips/rmi/xls_ehci.c b/sys/mips/rmi/xls_ehci.c index 48708722819..c4ae06562ad 100644 --- a/sys/mips/rmi/xls_ehci.c +++ b/sys/mips/rmi/xls_ehci.c @@ -69,50 +69,8 @@ __FBSDID("$FreeBSD$"); #include #include -static int ehci_xls_attach(device_t self); -static int ehci_xls_detach(device_t self); -static int ehci_xls_shutdown(device_t self); -static int ehci_xls_suspend(device_t self); -static int ehci_xls_resume(device_t self); - -static int -ehci_xls_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_suspend(sc); - return (0); -} - -static int -ehci_xls_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_resume(sc); - - bus_generic_resume(self); - - return (0); -} - -static int -ehci_xls_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - - return (0); -} +static device_attach_t ehci_xls_attach; +static device_detach_t ehci_xls_detach; static const char *xlr_usb_dev_desc = "RMI XLR USB 2.0 controller"; static const char *xlr_vendor_desc = "RMI Corp"; @@ -248,17 +206,17 @@ static device_method_t ehci_methods[] = { DEVMETHOD(device_probe, ehci_xls_probe), DEVMETHOD(device_attach, ehci_xls_attach), DEVMETHOD(device_detach, ehci_xls_detach), - DEVMETHOD(device_suspend, ehci_xls_suspend), - DEVMETHOD(device_resume, ehci_xls_resume), - DEVMETHOD(device_shutdown, ehci_xls_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(struct ehci_softc), + .name = "ehci", + .methods = ehci_methods, + .size = sizeof(struct ehci_softc), }; static devclass_t ehci_devclass; diff --git a/sys/mips/rt305x/rt305x_dotg.c b/sys/mips/rt305x/rt305x_dotg.c index 67666f70aae..89b493321da 100644 --- a/sys/mips/rt305x/rt305x_dotg.c +++ b/sys/mips/rt305x/rt305x_dotg.c @@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$"); static device_probe_t dotg_obio_probe; static device_attach_t dotg_obio_attach; static device_detach_t dotg_obio_detach; -static device_shutdown_t dotg_obio_shutdown; struct dotg_obio_softc { struct dotg_softc sc_dci; /* must be first */ @@ -208,35 +207,22 @@ dotg_obio_detach(device_t dev) return (0); } -static int -dotg_obio_shutdown(device_t dev) -{ - struct dotg_obio_softc *sc = device_get_softc(dev); - int err; - - err = bus_generic_shutdown(dev); - if (err) - return (err); - - dotg_uninit(&sc->sc_dci); - - return (0); -} - static device_method_t dotg_obio_methods[] = { /* Device interface */ DEVMETHOD(device_probe, dotg_obio_probe), DEVMETHOD(device_attach, dotg_obio_attach), DEVMETHOD(device_detach, dotg_obio_detach), - DEVMETHOD(device_shutdown, dotg_obio_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t dotg_obio_driver = { - "dotg", - dotg_obio_methods, - sizeof(struct dotg_obio_softc), + .name = "dotg", + .methods = dotg_obio_methods, + .size = sizeof(struct dotg_obio_softc), }; static devclass_t dotg_obio_devclass; diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile index abcfcbebc25..3df35bc7985 100644 --- a/sys/modules/usb/Makefile +++ b/sys/modules/usb/Makefile @@ -26,7 +26,7 @@ # SUBDIR = usb -SUBDIR += ehci musb ohci uhci xhci uss820dci ${_at91dci} ${_atmegadci} +SUBDIR += ehci musb ohci uhci xhci uss820dci ${_at91dci} ${_atmegadci} ${_avr32dci} SUBDIR += rum run uath upgt usie ural zyd ${_urtw} SUBDIR += atp uhid ukbd ums udbp ufm uep SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \ @@ -48,4 +48,8 @@ _atmegadci= atmegadci _urtw= urtw .endif +.if ${MACHINE_CPUARCH} == "avr32" +_avr32dci= avr32dci +.endif + .include diff --git a/sys/modules/usb/avr32dci/Makefile b/sys/modules/usb/avr32dci/Makefile new file mode 100644 index 00000000000..ea7d9c280ec --- /dev/null +++ b/sys/modules/usb/avr32dci/Makefile @@ -0,0 +1,38 @@ +# +# $FreeBSD$ +# +# Copyright (c) 2011 Hans Petter Selasky. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +S= ${.CURDIR}/../../.. + +.PATH: $S/dev/usb/controller + +KMOD= avr32dci +SRCS= bus_if.h device_if.h usb_if.h \ + opt_bus.h opt_usb.h \ + avr32dci.c \ + pci_if.h + +.include diff --git a/sys/powerpc/ps3/ehci_ps3.c b/sys/powerpc/ps3/ehci_ps3.c index c85c9bb4d1a..d5161609cc9 100644 --- a/sys/powerpc/ps3/ehci_ps3.c +++ b/sys/powerpc/ps3/ehci_ps3.c @@ -152,14 +152,17 @@ static device_method_t ehci_ps3_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ehci_ps3_probe), DEVMETHOD(device_attach, ehci_ps3_attach), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ehci_ps3_driver = { - "ehci", - ehci_ps3_methods, - sizeof(ehci_softc_t), + .name = "ehci", + .methods = ehci_ps3_methods, + .size = sizeof(ehci_softc_t), }; static devclass_t ehci_ps3_devclass; diff --git a/sys/powerpc/ps3/ohci_ps3.c b/sys/powerpc/ps3/ohci_ps3.c index c16daba1333..a047617c56a 100644 --- a/sys/powerpc/ps3/ohci_ps3.c +++ b/sys/powerpc/ps3/ohci_ps3.c @@ -150,14 +150,17 @@ static device_method_t ohci_ps3_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ohci_ps3_probe), DEVMETHOD(device_attach, ohci_ps3_attach), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static driver_t ohci_ps3_driver = { - "ohci", - ohci_ps3_methods, - sizeof(ohci_softc_t), + .name = "ohci", + .methods = ohci_ps3_methods, + .size = sizeof(ohci_softc_t), }; static devclass_t ohci_ps3_devclass;