コード例 #1
0
/**
 * exynos_drd_switch_start_host -  helper function for starting/stoping the host
 * controller driver.
 *
 * @otg: Pointer to the usb_otg structure.
 * @on: start / stop the host controller driver.
 *
 * Returns 0 on success otherwise negative errno.
 */
static int exynos_drd_switch_start_host(struct usb_otg *otg, int on)
{
    struct exynos_drd_switch *drd_switch = container_of(otg,
                                           struct exynos_drd_switch, otg);
    struct usb_hcd *hcd;
    struct device *xhci_dev;
    int ret = 0;

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

    dev_dbg(otg->phy->dev, "Turn %s host %s\n",
            on ? "on" : "off", otg->host->bus_name);

    hcd = bus_to_hcd(otg->host);
    xhci_dev = hcd->self.controller;

    if (on) {
#if !defined(CONFIG_USB_HOST_NOTIFY)
        wake_lock(&drd_switch->wakelock);
#endif
        /*
         * Clear runtime_error flag. The flag could be
         * set when user space accessed the host while DRD
         * was in B-Dev mode.
         */
        pm_runtime_disable(xhci_dev);
        if (pm_runtime_status_suspended(xhci_dev))
            pm_runtime_set_suspended(xhci_dev);
        else
            pm_runtime_set_active(xhci_dev);
        pm_runtime_enable(xhci_dev);

        ret = pm_runtime_get_sync(xhci_dev);
        if (ret < 0 && ret != -EINPROGRESS) {
            pm_runtime_put_noidle(xhci_dev);
            goto err;
        }

        exynos_drd_switch_ases_vbus_ctrl(drd_switch, 1);
    } else {
        exynos_drd_switch_ases_vbus_ctrl(drd_switch, 0);

        ret = pm_runtime_put_sync(xhci_dev);
        if (ret == -EAGAIN)
            pm_runtime_get_noresume(xhci_dev);
#if !defined(CONFIG_USB_HOST_NOTIFY)
        else
            wake_unlock(&drd_switch->wakelock);
#endif
    }

err:
    /* ret can be 1 after pm_runtime_get_sync */
    return (ret < 0) ? ret : 0;
}
コード例 #2
0
/**
 * exynos_drd_switch_start_host -  helper function for starting/stoping the host
 * controller driver.
 *
 * @otg: Pointer to the usb_otg structure.
 * @on: start / stop the host controller driver.
 *
 * Returns 0 on success otherwise negative errno.
 */
static int exynos_drd_switch_start_host(struct usb_otg *otg, int on)
{
	struct exynos_drd_switch *drd_switch = container_of(otg,
					struct exynos_drd_switch, otg);
	struct exynos_drd *drd = container_of(drd_switch->core,
						struct exynos_drd, core);
	struct device *xhci_dev = &drd->xhci->dev;
	int ret = 0;

	if (!drd->add_xhci_dev && drd->xhci) {
		ret = platform_device_add(drd->xhci);
		if (ret) {
			dev_err(drd->dev, "failed to register xhci device\n");
			return ret;
		}
		drd->add_xhci_dev = 1;
	}

	if (!otg->host) {
		dev_err(drd->dev, "failed binding host\n");
		return -EINVAL;
	}

	dev_dbg(otg->phy->dev, "Turn %s host %s\n",
			on ? "on" : "off", otg->host->bus_name);

	if (on) {
		wake_lock(&drd_switch->wakelock);
		/*
		 * Clear runtime_error flag. The flag could be
		 * set when user space accessed the host while DRD
		 * was in B-Dev mode.
		 */
		pm_runtime_disable(xhci_dev);
		if (pm_runtime_status_suspended(xhci_dev))
			pm_runtime_set_suspended(xhci_dev);
		else
			pm_runtime_set_active(xhci_dev);
		pm_runtime_enable(xhci_dev);

		ret = pm_runtime_get_sync(xhci_dev);
		if (ret < 0 && ret != -EINPROGRESS) {
			pm_runtime_put_noidle(xhci_dev);
			goto err;
		}

		exynos_drd_switch_ases_vbus_ctrl(drd_switch, 1);
	} else {
		exynos_drd_switch_ases_vbus_ctrl(drd_switch, 0);

		ret = pm_runtime_put_sync(xhci_dev);
		if (ret == -EAGAIN)
			pm_runtime_get_noresume(xhci_dev);
		else
			wake_unlock(&drd_switch->wakelock);
	}

err:
	/* ret can be 1 after pm_runtime_get_sync */
	return (ret < 0) ? ret : 0;
}