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

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

Merge "usb: msm_otg: Fix BAM remote-wake up issue during USB low-power mode"

parents 308ead9d ce9e978d
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -197,6 +197,21 @@ static bool ci13xxx_msm_in_lpm(struct ci13xxx *udc)
	return (atomic_read(&otg->in_lpm) != 0);
}

static void ci13xxx_msm_set_fpr_flag(struct ci13xxx *udc)
{
	struct msm_otg *otg;

	if (udc == NULL)
		return;

	if (udc->transceiver == NULL)
		return;

	otg = container_of(udc->transceiver, struct msm_otg, phy);

	atomic_set(&otg->set_fpr_with_lpm_exit, 1);
}

static irqreturn_t ci13xxx_msm_resume_irq(int irq, void *data)
{
	struct ci13xxx *udc = _udc;
@@ -220,6 +235,7 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
	.nz_itc			= 0,
	.notify_event		= ci13xxx_msm_notify_event,
	.in_lpm                 = ci13xxx_msm_in_lpm,
	.set_fpr_flag           = ci13xxx_msm_set_fpr_flag,
};

static int ci13xxx_msm_install_wake_gpio(struct platform_device *pdev,
+26 −7
Original line number Diff line number Diff line
@@ -1612,6 +1612,7 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
{
	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
	unsigned long flags;
	bool skip_fpr = false;
	int ret = 0;

	trace();
@@ -1624,19 +1625,37 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
	}
	spin_unlock_irqrestore(udc->lock, flags);

	if ((udc->udc_driver->in_lpm != NULL) &&
	    (udc->udc_driver->in_lpm(udc))) {
		if (udc->udc_driver->set_fpr_flag) {
			/* When USB HW is in low-power mode we set a flag
			 * for the OTG layer to set the FPR bit during the
			 * low-power mode mode exit sequence.
			 */
			udc->udc_driver->set_fpr_flag(udc);
			skip_fpr = true;
		}
	}

	udc->udc_driver->notify_event(udc,
		CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);

	if (udc->transceiver)
		usb_phy_set_suspend(udc->transceiver, 0);

	while (udc->udc_driver->in_lpm(udc))
		usleep(1);

	spin_lock_irqsave(udc->lock, flags);
	if (!skip_fpr) {
		if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
			ret = -EINVAL;
			dbg_trace("port is not suspended\n");
			goto out;
		}
		hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
	}

out:
	spin_unlock_irqrestore(udc->lock, flags);
	return ret;
@@ -1970,7 +1989,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
	}

	/* MSM Specific: updating the request as required for
	 * SPS mode. Enable MSM proprietary DMA engine acording
	 * SPS mode. Enable MSM DMA engine acording
	 * to the UDC private data in the request.
	 */
	if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
@@ -2218,7 +2237,7 @@ __acquires(mEp->lock)
				   struct ci13xxx_req, queue);
		list_del_init(&mReq->queue);

		/* MSM Specific: Clear end point proprietary register */
		/* MSM Specific: Clear end point specific register */
		if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
			if (mReq->req.udc_priv & MSM_SPS_MODE) {
				val = hw_cread(CAP_ENDPTPIPEID +
+1 −0
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ struct ci13xxx_udc_driver {

	void	(*notify_event) (struct ci13xxx *udc, unsigned event);
	bool    (*in_lpm) (struct ci13xxx *udc);
	void    (*set_fpr_flag) (struct ci13xxx *udc);
};

/* CI13XXX UDC descriptor & global resources */
+6 −3
Original line number Diff line number Diff line
@@ -1206,9 +1206,10 @@ static int msm_otg_resume(struct msm_otg *motg)

	is_remote_wakeup = in_device_mode && bus_is_suspended;

	if (is_remote_wakeup && pdata->rw_during_lpm_workaround) {
		/*
		 * In some targets there is a HW issue with remote wakeup
	if (is_remote_wakeup &&
	    (atomic_read(&(motg->set_fpr_with_lpm_exit)) ||
	     pdata->rw_during_lpm_workaround)) {
		/* In some targets there is a HW issue with remote wakeup
		 * during low-power mode. As a workaround, the FPR bit
		 * is written simultaneously with the clearing of the
		 * PHCD bit.
@@ -1217,6 +1218,8 @@ static int msm_otg_resume(struct msm_otg *motg)
			(readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD) |
			PORTSC_FPR_MASK,
			USB_PORTSC);

		atomic_set(&(motg->set_fpr_with_lpm_exit), 0);
	} else {
		writel_relaxed(readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD,
			USB_PORTSC);
+7 −3
Original line number Diff line number Diff line
@@ -230,9 +230,12 @@ enum usb_vdd_value {
 * @l1_supported: enable link power management support.
 * @dpdm_pulldown_added: Indicates whether pull down resistors are
 *		connected on data lines or not.
 * @vddmin_gpio: dedictaed gpio in the platform that is used
 *		for pullup the D+ line in case of bus suspend
 *		with phy retention.
 * @vddmin_gpio: dedictaed gpio in the platform that is used for
 *		pullup the D+ line in case of bus suspend with
 *		phy retention.
 * @rw_during_lpm_workaround: Determines whether remote-wakeup
 *		during low-power mode workaround will be
 *		applied.
 */
struct msm_otg_platform_data {
	int *phy_init_seq;
@@ -383,6 +386,7 @@ struct msm_otg {
	bool sm_work_pending;
	atomic_t pm_suspended;
	atomic_t in_lpm;
	atomic_t set_fpr_with_lpm_exit;
	int async_int;
	unsigned cur_power;
	struct delayed_work chg_work;