Loading drivers/usb/dwc3/dwc3_otg.c +34 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,36 @@ static int dwc3_otg_set_peripheral(struct usb_otg *otg, return 0; } /** * dwc3_otg_set_suspend - Set or clear OTG suspend bit and schedule OTG state machine * work. * * @phy: Pointer to the phy structure. * @suspend: 1 - Ask OTG state machine to issue low power mode entry. * 0 - Cancel low-power mode entry request. * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_set_suspend(struct usb_phy *phy, int suspend) { const unsigned int lpm_after_suspend_delay = 500; struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg); if (!dotg->dwc->enable_bus_suspend) return 0; if (suspend) { set_bit(DWC3_OTG_SUSPEND, &dotg->inputs); queue_delayed_work(system_nrt_wq, &dotg->sm_work, msecs_to_jiffies(lpm_after_suspend_delay)); } else { clear_bit(DWC3_OTG_SUSPEND, &dotg->inputs); } return 0; } /** * dwc3_ext_chg_det_done - callback to handle charger detection completion * @otg: Pointer to the otg transceiver structure Loading Loading @@ -850,6 +880,9 @@ static void dwc3_otg_sm_work(struct work_struct *w) if (charger) charger->chg_type = DWC3_INVALID_CHARGER; work = 1; } else if (test_bit(DWC3_OTG_SUSPEND, &dotg->inputs) && test_bit(B_SESS_VLD, &dotg->inputs)) { pm_runtime_put_sync(phy->dev); } break; Loading Loading @@ -997,6 +1030,7 @@ int dwc3_otg_init(struct dwc3 *dwc) dotg->otg.phy->set_power = dwc3_otg_set_power; dotg->otg.set_peripheral = dwc3_otg_set_peripheral; dotg->otg.set_host = dwc3_otg_set_host; dotg->otg.phy->set_suspend = dwc3_otg_set_suspend; dotg->otg.phy->state = OTG_STATE_UNDEFINED; /* Loading drivers/usb/dwc3/dwc3_otg.h +4 −3 Original line number Diff line number Diff line /** * dwc3_otg.h - DesignWare USB3 DRD Controller OTG * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -46,6 +46,7 @@ struct dwc3_otg { struct dwc3_ext_xceiv *ext_xceiv; #define ID 0 #define B_SESS_VLD 1 #define DWC3_OTG_SUSPEND 2 unsigned long inputs; struct power_supply *psy; struct completion dwc3_xcvr_vbus_init; Loading drivers/usb/dwc3/gadget.c +25 −3 Original line number Diff line number Diff line Loading @@ -1705,7 +1705,6 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w) spin_unlock_irqrestore(&dwc->lock, flags); } static void _dwc3_gadget_wakeup(struct dwc3 *dwc) { u32 timeout = 0; Loading Loading @@ -2773,6 +2772,10 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dev_vdbg(dwc->dev, "%s\n", __func__); /* Clear OTG suspend state */ if (dwc->enable_bus_suspend) usb_phy_set_suspend(dwc->dotg->otg.phy, 0); reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_INITU1ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); Loading Loading @@ -2862,6 +2865,10 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_gadget_disconnect_interrupt(dwc); } /* Clear OTG suspend state */ if (dwc->enable_bus_suspend) usb_phy_set_suspend(dwc->dotg->otg.phy, 0); dbg_event(0xFF, "BUS RST", 0); /* after reset -> Default State */ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); Loading Loading @@ -3046,6 +3053,11 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) */ dbg_event(0xFF, "WAKEUP", 0); /* Clear OTG suspend state */ if (dwc->enable_bus_suspend) usb_phy_set_suspend(dwc->dotg->otg.phy, 0); /* * gadget_driver resume function might require some dwc3-gadget * operations, such as ep_enable. Hence, dwc->lock must be released. Loading Loading @@ -3144,6 +3156,8 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, { enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; dev_dbg(dwc->dev, "%s Entry\n", __func__); if (next == DWC3_LINK_STATE_U3) { dbg_event(0xFF, "SUSPEND", 0); /* Loading @@ -3163,8 +3177,16 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, dwc->gadget_driver->suspend(&dwc->gadget); spin_lock(&dwc->lock); if (dwc->enable_bus_suspend) pm_runtime_put(dwc->dev); if (dwc->enable_bus_suspend) { /* * Set OTG suspend state and schedule OTG state machine * work */ dev_dbg(dwc->dev, "%s: Triggering OTG suspend\n", __func__); usb_phy_set_suspend(dwc->dotg->otg.phy, 1); } } dwc->link_state = next; Loading Loading
drivers/usb/dwc3/dwc3_otg.c +34 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,36 @@ static int dwc3_otg_set_peripheral(struct usb_otg *otg, return 0; } /** * dwc3_otg_set_suspend - Set or clear OTG suspend bit and schedule OTG state machine * work. * * @phy: Pointer to the phy structure. * @suspend: 1 - Ask OTG state machine to issue low power mode entry. * 0 - Cancel low-power mode entry request. * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_set_suspend(struct usb_phy *phy, int suspend) { const unsigned int lpm_after_suspend_delay = 500; struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg); if (!dotg->dwc->enable_bus_suspend) return 0; if (suspend) { set_bit(DWC3_OTG_SUSPEND, &dotg->inputs); queue_delayed_work(system_nrt_wq, &dotg->sm_work, msecs_to_jiffies(lpm_after_suspend_delay)); } else { clear_bit(DWC3_OTG_SUSPEND, &dotg->inputs); } return 0; } /** * dwc3_ext_chg_det_done - callback to handle charger detection completion * @otg: Pointer to the otg transceiver structure Loading Loading @@ -850,6 +880,9 @@ static void dwc3_otg_sm_work(struct work_struct *w) if (charger) charger->chg_type = DWC3_INVALID_CHARGER; work = 1; } else if (test_bit(DWC3_OTG_SUSPEND, &dotg->inputs) && test_bit(B_SESS_VLD, &dotg->inputs)) { pm_runtime_put_sync(phy->dev); } break; Loading Loading @@ -997,6 +1030,7 @@ int dwc3_otg_init(struct dwc3 *dwc) dotg->otg.phy->set_power = dwc3_otg_set_power; dotg->otg.set_peripheral = dwc3_otg_set_peripheral; dotg->otg.set_host = dwc3_otg_set_host; dotg->otg.phy->set_suspend = dwc3_otg_set_suspend; dotg->otg.phy->state = OTG_STATE_UNDEFINED; /* Loading
drivers/usb/dwc3/dwc3_otg.h +4 −3 Original line number Diff line number Diff line /** * dwc3_otg.h - DesignWare USB3 DRD Controller OTG * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -46,6 +46,7 @@ struct dwc3_otg { struct dwc3_ext_xceiv *ext_xceiv; #define ID 0 #define B_SESS_VLD 1 #define DWC3_OTG_SUSPEND 2 unsigned long inputs; struct power_supply *psy; struct completion dwc3_xcvr_vbus_init; Loading
drivers/usb/dwc3/gadget.c +25 −3 Original line number Diff line number Diff line Loading @@ -1705,7 +1705,6 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w) spin_unlock_irqrestore(&dwc->lock, flags); } static void _dwc3_gadget_wakeup(struct dwc3 *dwc) { u32 timeout = 0; Loading Loading @@ -2773,6 +2772,10 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dev_vdbg(dwc->dev, "%s\n", __func__); /* Clear OTG suspend state */ if (dwc->enable_bus_suspend) usb_phy_set_suspend(dwc->dotg->otg.phy, 0); reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_INITU1ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); Loading Loading @@ -2862,6 +2865,10 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_gadget_disconnect_interrupt(dwc); } /* Clear OTG suspend state */ if (dwc->enable_bus_suspend) usb_phy_set_suspend(dwc->dotg->otg.phy, 0); dbg_event(0xFF, "BUS RST", 0); /* after reset -> Default State */ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); Loading Loading @@ -3046,6 +3053,11 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) */ dbg_event(0xFF, "WAKEUP", 0); /* Clear OTG suspend state */ if (dwc->enable_bus_suspend) usb_phy_set_suspend(dwc->dotg->otg.phy, 0); /* * gadget_driver resume function might require some dwc3-gadget * operations, such as ep_enable. Hence, dwc->lock must be released. Loading Loading @@ -3144,6 +3156,8 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, { enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; dev_dbg(dwc->dev, "%s Entry\n", __func__); if (next == DWC3_LINK_STATE_U3) { dbg_event(0xFF, "SUSPEND", 0); /* Loading @@ -3163,8 +3177,16 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, dwc->gadget_driver->suspend(&dwc->gadget); spin_lock(&dwc->lock); if (dwc->enable_bus_suspend) pm_runtime_put(dwc->dev); if (dwc->enable_bus_suspend) { /* * Set OTG suspend state and schedule OTG state machine * work */ dev_dbg(dwc->dev, "%s: Triggering OTG suspend\n", __func__); usb_phy_set_suspend(dwc->dotg->otg.phy, 1); } } dwc->link_state = next; Loading