Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52d54747 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: Delay low-power mode entry after USB bus suspend"

parents 474e8cf4 70588795
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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
@@ -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;

@@ -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;

	/*
+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
@@ -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;
+25 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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);
@@ -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.
@@ -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);
		/*
@@ -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;