mirror of https://gitee.com/openkylin/linux.git
usb: gadget: aspeed: Rework the reset logic
We had some dodgy code using the speed setting to decide whether a port reset would reset the device or just enable it. Instead, if the device is disabled and has a gadget attached, a reset will enable it. If it's already enabled, a reset will reset it. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
parent
155940a16d
commit
5f0625aaba
|
@ -50,7 +50,7 @@ void ast_vhub_dev_irq(struct ast_vhub_dev *d)
|
|||
|
||||
static void ast_vhub_dev_enable(struct ast_vhub_dev *d)
|
||||
{
|
||||
u32 reg, hmsk;
|
||||
u32 reg, hmsk, i;
|
||||
|
||||
if (d->enabled)
|
||||
return;
|
||||
|
@ -76,6 +76,20 @@ static void ast_vhub_dev_enable(struct ast_vhub_dev *d)
|
|||
/* Set EP0 DMA buffer address */
|
||||
writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA);
|
||||
|
||||
/* Clear stall on all EPs */
|
||||
for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) {
|
||||
struct ast_vhub_ep *ep = d->epns[i];
|
||||
|
||||
if (ep && (ep->epn.stalled || ep->epn.wedged)) {
|
||||
ep->epn.stalled = false;
|
||||
ep->epn.wedged = false;
|
||||
ast_vhub_update_epn_stall(ep);
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional cleanups */
|
||||
d->wakeup_en = false;
|
||||
d->suspended = false;
|
||||
d->enabled = true;
|
||||
}
|
||||
|
||||
|
@ -477,46 +491,28 @@ void ast_vhub_dev_resume(struct ast_vhub_dev *d)
|
|||
|
||||
void ast_vhub_dev_reset(struct ast_vhub_dev *d)
|
||||
{
|
||||
/*
|
||||
* If speed is not set, we enable the port. If it is,
|
||||
* send reset to the gadget and reset "speed".
|
||||
*
|
||||
* Speed is an indication that we have got the first
|
||||
* setup packet to the device.
|
||||
*/
|
||||
if (d->gadget.speed == USB_SPEED_UNKNOWN && !d->enabled) {
|
||||
DDBG(d, "Reset at unknown speed of disabled device, enabling...\n");
|
||||
ast_vhub_dev_enable(d);
|
||||
d->suspended = false;
|
||||
/* No driver, just disable the device and return */
|
||||
if (!d->driver) {
|
||||
ast_vhub_dev_disable(d);
|
||||
return;
|
||||
}
|
||||
if (d->gadget.speed != USB_SPEED_UNKNOWN && d->driver) {
|
||||
unsigned int i;
|
||||
|
||||
DDBG(d, "Reset at known speed of bound device, resetting...\n");
|
||||
/* If the port isn't enabled, just enable it */
|
||||
if (!d->enabled) {
|
||||
DDBG(d, "Reset of disabled device, enabling...\n");
|
||||
ast_vhub_dev_enable(d);
|
||||
} else {
|
||||
DDBG(d, "Reset of enabled device, resetting...\n");
|
||||
spin_unlock(&d->vhub->lock);
|
||||
d->driver->reset(&d->gadget);
|
||||
usb_gadget_udc_reset(&d->gadget, d->driver);
|
||||
spin_lock(&d->vhub->lock);
|
||||
|
||||
/*
|
||||
* Disable/re-enable HW, this will clear the address
|
||||
* Disable and maybe re-enable HW, this will clear the address
|
||||
* and speed setting.
|
||||
*/
|
||||
ast_vhub_dev_disable(d);
|
||||
ast_vhub_dev_enable(d);
|
||||
|
||||
/* Clear stall on all EPs */
|
||||
for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) {
|
||||
struct ast_vhub_ep *ep = d->epns[i];
|
||||
|
||||
if (ep && ep->epn.stalled) {
|
||||
ep->epn.stalled = false;
|
||||
ast_vhub_update_epn_stall(ep);
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional cleanups */
|
||||
d->wakeup_en = false;
|
||||
d->suspended = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue