diff options
| -rw-r--r-- | drivers/usb/dwc3/core.c | 19 | ||||
| -rw-r--r-- | drivers/usb/dwc3/core.h | 4 | ||||
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 8 |
3 files changed, 25 insertions, 6 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 45c9a399f8a5..11b938fd9de0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1892,6 +1892,20 @@ static int dwc3_get_clocks(struct dwc3 *dwc) return 0; } +static void dwc3_vbus_draw_work(struct work_struct *work) +{ + struct dwc3 *dwc = container_of(work, struct dwc3, vbus_draw_work); + union power_supply_propval val = {0}; + int ret; + + val.intval = 1000 * (dwc->current_limit); + ret = power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); + + if (ret < 0) + dev_dbg(dwc->dev, "Error (%d) setting vbus draw (%d mA)\n", + ret, dwc->current_limit); +} + static struct power_supply *dwc3_get_usb_power_supply(struct dwc3 *dwc) { struct power_supply *usb_psy; @@ -1906,6 +1920,7 @@ static struct power_supply *dwc3_get_usb_power_supply(struct dwc3 *dwc) if (!usb_psy) return ERR_PTR(-EPROBE_DEFER); + INIT_WORK(&dwc->vbus_draw_work, dwc3_vbus_draw_work); return usb_psy; } @@ -2097,8 +2112,10 @@ static void dwc3_remove(struct platform_device *pdev) dwc3_free_event_buffers(dwc); - if (dwc->usb_psy) + if (dwc->usb_psy) { + cancel_work_sync(&dwc->vbus_draw_work); power_supply_put(dwc->usb_psy); + } } #ifdef CONFIG_PM diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9fc91f5c0bdb..45084ca66806 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1034,6 +1034,8 @@ struct dwc3_scratchpad_array { * @role_switch_default_mode: default operation mode of controller while * usb role is USB_ROLE_NONE. * @usb_psy: pointer to power supply interface. + * @vbus_draw_work: Work to set the vbus drawing limit + * @current_limit: How much current to draw from vbus, in milliAmperes. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1202,6 +1204,8 @@ struct dwc3 { enum usb_dr_mode role_switch_default_mode; struct power_supply *usb_psy; + struct work_struct vbus_draw_work; + unsigned int current_limit; u32 fladj; u32 ref_clk_per; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8781ebeaab90..7e6661781aff 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3139,8 +3139,6 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g, static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) { struct dwc3 *dwc = gadget_to_dwc(g); - union power_supply_propval val = {0}; - int ret; if (dwc->usb2_phy) return usb_phy_set_power(dwc->usb2_phy, mA); @@ -3148,10 +3146,10 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) if (!dwc->usb_psy) return -EOPNOTSUPP; - val.intval = 1000 * mA; - ret = power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); + dwc->current_limit = mA; + schedule_work(&dwc->vbus_draw_work); - return ret; + return 0; } /** |
