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

Commit b9cb896b authored by Mayank Rana's avatar Mayank Rana
Browse files

dwc3: Use otg_sm_work state machine for host and device only mode



This change starts using OTG state machine for host only mode or
device only mode functionality.
There are couple of motivations for this:
1. To make sure host only mode related usb hardware initialization
sequence remains same as OTG mode based host mode functionality
2. To avoid having two different path to support same host mode
functionality or device only mode functionality

Change-Id: I64ab823f6a9b4c1a4918f0eb63bfb03359010c1c
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 925f5828
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -961,23 +961,29 @@ static int dwc3_probe(struct platform_device *pdev)
	dwc->num_in_eps = 16;
	dwc->num_out_eps = 16;

	if (dwc->dr_mode == USB_DR_MODE_OTG ||
		dwc->dr_mode == USB_DR_MODE_PERIPHERAL) {
		ret = dwc3_gadget_init(dwc);
		if (ret) {
			dev_err(dev, "failed to initialize gadget\n");
			goto err_usb3phy_power;
		}
	}

	if (dwc->dr_mode == USB_DR_MODE_OTG ||
		dwc->dr_mode ==  USB_DR_MODE_HOST) {
		ret = dwc3_host_init(dwc);
		if (ret) {
			dev_err(dev, "failed to initialize host\n");
			goto err_gadget_exit;
		}

	}
	dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_INITIALIZATION_EVENT);

	return 0;

err_gadget_exit:
	if (dwc->dr_mode == USB_DR_MODE_OTG)
		dwc3_gadget_exit(dwc);
err_usb3phy_power:
	phy_power_off(dwc->usb3_generic_phy);
+30 −40
Original line number Diff line number Diff line
@@ -222,6 +222,7 @@ struct dwc3_msm {
	int  pwr_event_irq;
	atomic_t                in_p3;
	unsigned int		lpm_to_suspend_delay;
	bool			init;
};

#define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -1575,10 +1576,8 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
 */
static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
{
	static bool init;

	/* Flush processing any pending events before handling new ones */
	if (init)
	if (mdwc->init)
		flush_delayed_work(&mdwc->sm_work);

	if (mdwc->id_state == DWC3_ID_FLOAT) {
@@ -1605,8 +1604,8 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
		clear_bit(B_SUSPEND, &mdwc->inputs);
	}

	if (!init) {
		init = true;
	if (!mdwc->init) {
		mdwc->init = true;
		if (!work_busy(&mdwc->sm_work.work))
			schedule_delayed_work(&mdwc->sm_work, 0);

@@ -1645,11 +1644,7 @@ static void dwc3_resume_work(struct work_struct *w)
	}

	dbg_event(0xFF, "RWrk", dwc->is_drd);
	if (dwc->is_drd)
	dwc3_ext_event_notify(mdwc);
	else if (mdwc->in_host_mode)
		/* host-only mode: resume xhci directly */
		pm_runtime_resume(&dwc->xhci->dev);
}

static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc)
@@ -2349,24 +2344,6 @@ static int dwc3_msm_probe(struct platform_device *pdev)
	}

	host_mode = of_usb_get_dr_mode(dwc3_node) == USB_DR_MODE_HOST;
	if (host_mode && of_get_property(pdev->dev.of_node, "vbus_dwc3-supply",
									NULL)) {
		mdwc->vbus_reg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
		if (IS_ERR(mdwc->vbus_reg)) {
			dev_err(&pdev->dev, "Failed to get vbus regulator\n");
			ret = PTR_ERR(mdwc->vbus_reg);
			of_node_put(dwc3_node);
			goto err;
		}
		ret = regulator_enable(mdwc->vbus_reg);
		if (ret) {
			mdwc->vbus_reg = 0;
			dev_err(&pdev->dev, "Failed to enable vbus_reg\n");
			of_node_put(dwc3_node);
			goto err;
		}
	}

	/* usb_psy required only for vbus_notifications */
	if (!host_mode) {
		mdwc->usb_psy.name = "usb";
@@ -2442,18 +2419,6 @@ static int dwc3_msm_probe(struct platform_device *pdev)
	}

	dwc->vbus_active = of_property_read_bool(node, "qcom,vbus-present");

	if (!dwc->is_drd) {
		if (host_mode) {
			dev_dbg(&pdev->dev, "DWC3 in host only mode\n");
			mdwc->in_host_mode = true;
			mdwc->hs_phy->flags |= PHY_HOST_MODE;
			mdwc->ss_phy->flags |= PHY_HOST_MODE;
		} else {
			dev_dbg(&pdev->dev, "DWC3 in device-only mode\n");
		}
	}

	mdwc->irq_to_affin = platform_get_irq(mdwc->dwc3, 0);
	mdwc->dwc3_cpu_notifier.notifier_call = dwc3_cpu_notifier_cb;

@@ -2475,6 +2440,16 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		local_irq_restore(flags);
		enable_irq_wake(mdwc->pmic_id_irq);
	}

	if (!dwc->is_drd && host_mode) {
		dev_dbg(&pdev->dev, "DWC3 in host only mode\n");
		mdwc->in_host_mode = true;
		mdwc->hs_phy->flags |= PHY_HOST_MODE;
		mdwc->ss_phy->flags |= PHY_HOST_MODE;
		mdwc->id_state = DWC3_ID_GROUND;
		dwc3_ext_event_notify(mdwc);
	}

	return 0;

put_dwc3:
@@ -2892,8 +2867,22 @@ static void dwc3_otg_sm_work(struct work_struct *w)
	switch (mdwc->otg_state) {
	case OTG_STATE_UNDEFINED:
		dwc3_init_sm(mdwc);
		if (!test_bit(ID, &mdwc->inputs)) {
			dbg_event(0xFF, "undef_host", 0);
			atomic_set(&dwc->in_lpm, 0);
			pm_runtime_set_active(mdwc->dev);
			pm_runtime_enable(mdwc->dev);
			pm_runtime_get_noresume(mdwc->dev);
			dwc3_initialize(mdwc);
			mdwc->otg_state = OTG_STATE_A_HOST;
			dwc3_otg_start_host(mdwc, 1);
			pm_runtime_put_noidle(mdwc->dev);
			return;
		}

		if (test_bit(B_SESS_VLD, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "b_sess_vld\n");
			dbg_event(0xFF, "undef_b_sess_vld", 0);
			switch (mdwc->chg_type) {
			case DWC3_DCP_CHARGER:
			case DWC3_PROPRIETARY_CHARGER:
@@ -2923,6 +2912,7 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		}

		if (!test_bit(B_SESS_VLD, &mdwc->inputs)) {
			dbg_event(0xFF, "undef_!b_sess_vld", 0);
			atomic_set(&dwc->in_lpm, 0);
			pm_runtime_set_active(mdwc->dev);
			pm_runtime_enable(mdwc->dev);
+0 −17
Original line number Diff line number Diff line
@@ -2177,26 +2177,9 @@ static int dwc3_gadget_start(struct usb_gadget *g,
	 * device-specific initialization until device mode is activated.
	 * In that case dwc3_gadget_restart() will handle it.
	 */
	if (!dwc->is_drd) {
		spin_unlock_irqrestore(&dwc->lock, flags);
		pm_runtime_get_sync(dwc->dev);
		dbg_event(0xFF, "GdgStrt Begin",
			atomic_read(&dwc->dev->power.usage_count));
		spin_lock_irqsave(&dwc->lock, flags);
		ret = __dwc3_gadget_start(dwc);
		pm_runtime_put(dwc->dev);
		dbg_event(0xFF, "GdgStrt End",
			atomic_read(&dwc->dev->power.usage_count));
		if (ret)
			goto err2;
	}

	spin_unlock_irqrestore(&dwc->lock, flags);
	return 0;

err2:
	dwc->gadget_driver = NULL;

err1:
	spin_unlock_irqrestore(&dwc->lock, flags);
	free_irq(irq, dwc);
+1 −9
Original line number Diff line number Diff line
@@ -60,15 +60,7 @@ int dwc3_host_init(struct dwc3 *dwc)
		goto err1;
	}

	/* Add XHCI device if not Dual-Role, else it is added dynamically */
	if (!dwc->is_drd) {
		ret = platform_device_add(xhci);
		if (ret) {
			dev_err(dwc->dev, "failed to register xHCI device\n");
			goto err1;
		}
	}

	/* Platform device gets added as part of state machine */
	return 0;

err1: