Skip to content

Commit

Permalink
staging: octeon-usb: try to recover from failed hardware reset
Browse files Browse the repository at this point in the history
On some hardware the USB fails to initialize to sane state after
cold boot. We can detect this based on some unexpected interrupt bits,
and recover by re-initializing.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Aaro Koskinen authored and Greg Kroah-Hartman committed Mar 24, 2015
1 parent f3b8edc commit 6ad9c95
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions drivers/staging/octeon-usb/octeon-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,15 +697,20 @@ static int cvmx_usb_shutdown(struct cvmx_usb_state *usb)
* other access to the Octeon USB port is made. The port starts
* off in the disabled state.
*
* @dev: Pointer to struct device for logging purposes.
* @usb: Pointer to struct cvmx_usb_state.
*
* Returns: 0 or a negative error code.
*/
static int cvmx_usb_initialize(struct cvmx_usb_state *usb)
static int cvmx_usb_initialize(struct device *dev,
struct cvmx_usb_state *usb)
{
int retries = 0;
union cvmx_usbnx_clk_ctl usbn_clk_ctl;
union cvmx_usbcx_gintsts usbc_gintsts;
union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;

retry:
/*
* Power On Reset and PHY Initialization
*
Expand Down Expand Up @@ -952,7 +957,26 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb)

cvmx_fifo_setup(usb);

return 0;
/*
* If the controller is getting port events right after the reset, it
* means the initialization failed. Try resetting the controller again
* in such case. This is seen to happen after cold boot on DSR-1000N.
*/
usbc_gintsts.u32 = cvmx_usb_read_csr32(usb,
CVMX_USBCX_GINTSTS(usb->index));
cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index),
usbc_gintsts.u32);
dev_dbg(dev, "gintsts after reset: 0x%x\n", (int)usbc_gintsts.u32);
if (!usbc_gintsts.s.disconnint && !usbc_gintsts.s.prtint)
return 0;
if (retries++ >= 5)
return -EAGAIN;
dev_info(dev, "controller reset failed (gintsts=0x%x) - retrying\n",
(int)usbc_gintsts.u32);
msleep(50);
cvmx_usb_shutdown(usb);
msleep(50);
goto retry;
}

/**
Expand Down Expand Up @@ -3690,7 +3714,7 @@ static int octeon_usb_probe(struct platform_device *pdev)
priv->usb.idle_hardware_channels = 0xff;
}

status = cvmx_usb_initialize(&priv->usb);
status = cvmx_usb_initialize(dev, &priv->usb);
if (status) {
dev_dbg(dev, "USB initialization failed with %d\n", status);
kfree(hcd);
Expand Down

0 comments on commit 6ad9c95

Please sign in to comment.