Commit 5f0625aa authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Felipe Balbi
Browse files

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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 155940a1
Loading
Loading
Loading
Loading
+27 −31
Original line number Diff line number Diff line
@@ -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;
	}
}