static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on)
{
	struct usb_otg	*otg = fsm->otg;
	struct dwc3_otg	*dotg = container_of(otg, struct dwc3_otg, otg);
	struct device	*dev = dotg->dwc->dev;
	int		ret;

	if (!otg->gadget)
		return -EINVAL;

	dev_err(dev, "Turn %s gadget %s\n",
		on ? "on" : "off", otg->gadget->name);

	if (on) {
		wake_lock(&dotg->wakelock);
		pm_runtime_get_sync(dev);
		dwc3_otg_set_peripheral_mode(dotg);
		ret = usb_gadget_vbus_connect(otg->gadget);
	} else {
		/*
		 * Delay VBus OFF signal delivery to not miss Disconnect
		 * interrupt (80ms is minimum; ascertained by experiment)
		 */
		msleep(200);

		ret = usb_gadget_vbus_disconnect(otg->gadget);
		pm_runtime_put_sync(dev);
		wake_unlock(&dotg->wakelock);
	}

	return ret;
}
Exemplo n.º 2
0
Arquivo: otg.c Projeto: qkdang/m462
static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on)
{
	struct usb_otg	*otg = fsm->otg;
	struct dwc3_otg	*dotg = container_of(otg, struct dwc3_otg, otg);
	struct dwc3	*dwc = dotg->dwc;
	struct device	*dev = dotg->dwc->dev;
	int		ret = 0;

	if (!otg->gadget)
		return -EINVAL;

	dev_err(dev, "Turn %s gadget %s\n",
		on ? "on" : "off", otg->gadget->name);

	/* sync usb3 phy state with usb2 phy */
	dwc->usb3_phy->state = dwc->usb2_phy->state;
	if (on) {
		pm_runtime_get_sync(dev);
		ret = dwc3_core_init(dwc);
		if (ret) {
			dev_err(dwc->dev, "%s: failed to reinitialize core\n",
					__func__);
			goto err1;
		}
		dwc3_otg_set_peripheral_mode(dotg);
		ret = usb_gadget_vbus_connect(otg->gadget);
		if (ret) {
			dev_err(dwc->dev, "%s: vbus connect failed\n",
					__func__);
			goto err2;
		}
	} else {
		/* avoid missing disconnect interrupt */
		wait_for_completion_timeout(&dwc->disconnect,
					msecs_to_jiffies(200));
		ret = usb_gadget_vbus_disconnect(otg->gadget);
		if (ret)
			dev_err(dwc->dev, "%s: vbus disconnect failed\n",
					__func__);
err2:
		dwc3_core_exit(dwc);
err1:
		pm_runtime_put_sync(dev);
	}

	return ret;
}