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
This commit is contained in:
hselasky 2011-12-14 00:28:54 +00:00
parent 145914e3e7
commit 7076389cec
45 changed files with 805 additions and 941 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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,
};

View File

@ -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);

View File

@ -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;

View File

@ -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,
};

View File

@ -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_ */

View File

@ -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;

View File

@ -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 @@ avr32dci_data_tx(struct avr32dci_td *td)
}
/* 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 @@ avr32dci_roothub_exec(struct usb_device *udev,
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,
};

View File

@ -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);

View File

@ -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,
};

View File

@ -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_ */

View File

@ -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
};

View File

@ -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
};

View File

@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_pci.h>
#include <dev/usb/controller/ehci.h>
#include <dev/usb/controller/ehcireg.h>
#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),
};

View File

@ -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,
};

View File

@ -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);

View File

@ -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;

View File

@ -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 @@ ohci_controller_init(ohci_softc_t *sc)
}
#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,
};

View File

@ -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_ */

View File

@ -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;

View File

@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_pci.h>
#include <dev/usb/controller/ohci.h>
#include <dev/usb/controller/ohcireg.h>
#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),
};

View File

@ -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;

View File

@ -373,9 +373,10 @@ uhci_reset(uhci_softc_t *sc)
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,
};

View File

@ -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);

View File

@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_pci.h>
#include <dev/usb/controller/uhci.h>
#include <dev/usb/controller/uhcireg.h>
#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),
};

View File

@ -61,12 +61,16 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
#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);
}

View File

@ -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,
};

View File

@ -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_ */

View File

@ -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)
{

View File

@ -58,23 +58,22 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_pci.h>
#include <dev/usb/controller/xhci.h>
#include <dev/usb/controller/xhcireg.h>
#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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -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,
};

View File

@ -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_ */

View File

@ -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;

View File

@ -69,50 +69,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/controller/ehcireg.h>
#include <mips/rmi/pic.h>
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;

View File

@ -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;

View File

@ -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 <bsd.subdir.mk>

View File

@ -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 <bsd.kmod.mk>

View File

@ -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;

View File

@ -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;