diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-12-13 12:17:59 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-12-13 12:17:59 -0800 |
commit | 6243ed9ad2f0045bbe72886583447bd56da6526c (patch) | |
tree | c64f911b73fc5d71044e540aae363df727b930ff /drivers/usb/dwc3 | |
parent | d18c993351c3c3d13efb35eb8d2ca05f2435e7c9 (diff) | |
parent | 7d34e0758877f819ed933d8f72b589cfae429343 (diff) |
Merge "usb: dwc3-msm: Set PROP_BOOST_CURRENT for direct attach devices"
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/dwc3-msm.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index bb6afb6a7d6d..3be207a42cb0 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -210,6 +210,8 @@ struct dwc3_msm { struct notifier_block vbus_nb; struct notifier_block id_nb; + struct notifier_block host_nb; + int pwr_event_irq; atomic_t in_p3; unsigned int lpm_to_suspend_delay; @@ -3023,6 +3025,53 @@ static int dwc3_msm_remove(struct platform_device *pdev) return 0; } +static int dwc3_msm_host_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct dwc3_msm *mdwc = container_of(nb, struct dwc3_msm, host_nb); + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + struct usb_device *udev = ptr; + union power_supply_propval pval; + unsigned max_power; + + if (event != USB_DEVICE_ADD && event != USB_DEVICE_REMOVE) + return NOTIFY_DONE; + + if (!mdwc->usb_psy) { + mdwc->usb_psy = power_supply_get_by_name("usb"); + if (!mdwc->usb_psy) + return NOTIFY_DONE; + } + + /* + * For direct-attach devices, new udev is direct child of root hub + * i.e. dwc -> xhci -> root_hub -> udev + * root_hub's udev->parent==NULL, so traverse struct device hierarchy + */ + if (udev->parent && !udev->parent->parent && + udev->dev.parent->parent == &dwc->xhci->dev) { + if (event == USB_DEVICE_ADD && udev->actconfig) { + if (udev->speed >= USB_SPEED_SUPER) + max_power = udev->actconfig->desc.bMaxPower * 8; + else + max_power = udev->actconfig->desc.bMaxPower * 2; + dev_dbg(mdwc->dev, "%s configured bMaxPower:%d (mA)\n", + dev_name(&udev->dev), max_power); + + /* inform PMIC of max power so it can optimize boost */ + pval.intval = max_power * 1000; + power_supply_set_property(mdwc->usb_psy, + POWER_SUPPLY_PROP_BOOST_CURRENT, &pval); + } else { + pval.intval = 0; + power_supply_set_property(mdwc->usb_psy, + POWER_SUPPLY_PROP_BOOST_CURRENT, &pval); + } + } + + return NOTIFY_DONE; +} + #define VBUS_REG_CHECK_DELAY (msecs_to_jiffies(1000)) /** @@ -3083,6 +3132,9 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); + mdwc->host_nb.notifier_call = dwc3_msm_host_notifier; + usb_register_notify(&mdwc->host_nb); + /* * FIXME If micro A cable is disconnected during system suspend, * xhci platform device will be removed before runtime pm is @@ -3103,6 +3155,7 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) pm_runtime_put_sync(mdwc->dev); dbg_event(0xFF, "pdeverr psync", atomic_read(&mdwc->dev->power.usage_count)); + usb_unregister_notify(&mdwc->host_nb); return ret; } @@ -3139,6 +3192,7 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) mdwc->hs_phy->flags &= ~PHY_HOST_MODE; mdwc->ss_phy->flags &= ~PHY_HOST_MODE; platform_device_del(dwc->xhci); + usb_unregister_notify(&mdwc->host_nb); /* * Perform USB hardware RESET (both core reset and DBM reset) |