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

Commit 78268042 authored by Bar Weiner's avatar Bar Weiner
Browse files

usb: dwc3: gadget: Allow pullup on/off during LPM



gadget_pullup is currently used as part of dynamic
usb composition switch. If the user try to switch
composition while the core is in low power mode, it
results in unclocked access to usb core registers.
This change insures that the core is not in LPM
during the pullup on/off sequence.

Change-Id: I0b0913674a8fbf5af3d9be40fa749bac251b075a
Signed-off-by: default avatarBar Weiner <bweiner@codeaurora.org>
parent e9afe3e0
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -72,6 +72,7 @@ static void _dwc3_gadget_wakeup(struct dwc3 *dwc);


struct dwc3_usb_gadget {
struct dwc3_usb_gadget {
	struct work_struct wakeup_work;
	struct work_struct wakeup_work;
	bool disable_during_lpm;
	struct dwc3 *dwc;
	struct dwc3 *dwc;
};
};


@@ -1789,6 +1790,7 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned mA)
static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
{
{
	struct dwc3		*dwc = gadget_to_dwc(g);
	struct dwc3		*dwc = gadget_to_dwc(g);
	struct dwc3_usb_gadget *dwc3_gadget = g->private;
	unsigned long		flags;
	unsigned long		flags;
	int			ret;
	int			ret;


@@ -1810,6 +1812,24 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
		return 0;
		return 0;
	}
	}


	/*
	 * This insures that the core is not in LPM during the pullup
	 * on/off toggling.
	 */
	spin_unlock_irqrestore(&dwc->lock, flags);
	if (atomic_read(&dwc->in_lpm) && !is_on) {
		pm_runtime_get_sync(dwc->dev);
		if (dwc3_gadget)
			dwc3_gadget->disable_during_lpm = true;
	}

	if (is_on && dwc3_gadget && dwc3_gadget->disable_during_lpm) {
		pm_runtime_put_sync(dwc->dev);
		if (dwc3_gadget)
			dwc3_gadget->disable_during_lpm = false;
	}
	spin_lock_irqsave(&dwc->lock, flags);

	ret = dwc3_gadget_run_stop(dwc, is_on);
	ret = dwc3_gadget_run_stop(dwc, is_on);


	spin_unlock_irqrestore(&dwc->lock, flags);
	spin_unlock_irqrestore(&dwc->lock, flags);
@@ -3279,6 +3299,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
		return -ENOMEM;
		return -ENOMEM;
	}
	}
	dwc3_gadget->dwc = dwc;
	dwc3_gadget->dwc = dwc;
	dwc3_gadget->disable_during_lpm = false;
	INIT_WORK(&dwc3_gadget->wakeup_work, dwc3_gadget_wakeup_work);
	INIT_WORK(&dwc3_gadget->wakeup_work, dwc3_gadget_wakeup_work);


	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),