/** * 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; }
/** * 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; }