diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-07-26 15:05:35 +1000 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2019-08-12 08:54:49 +0300 |
commit | 5f0625aaba5e4c0db75e942ff3c76516465a77d9 (patch) | |
tree | 300a1439496631227cb9e8d9d7518a0e898e16b5 /drivers | |
parent | 155940a16d688b5376f7c955a5f53259c6fe5689 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/udc/aspeed-vhub/dev.c | 58 |
1 files changed, 27 insertions, 31 deletions
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 5f7e3b6de531..79d3cb6bd2e7 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -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; } } |