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

Commit 926ce420 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dwc3-msm: reset hardware on bootup if cable not connected"

parents cbb45fe7 433f059f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ Optional properties :
- vbus_dwc3-supply: phandle to the 5V VBUS supply regulator used for host mode.
- USB3_GDSC-supply : phandle to the globally distributed switch controller
  regulator node to the USB controller.
- dpdm-supply: phandle to dpdm supply which will be used to drive dp/dm lines
  in high-z state.
- qcom,dwc-usb3-msm-tx-fifo-size: If present, represents RAM size available for
		TX fifo allocation in bytes
- qcom,lpm-to-suspend-delay-ms: Indicates timeout (in milliseconds) to release wakeup source
+74 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/usb/gadget.h>
#include <linux/usb/of.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/pm_wakeup.h>
#include <linux/power_supply.h>
#include <linux/cdev.h>
@@ -313,6 +314,10 @@ struct dwc3_msm {
	enum usb_device_speed override_usb_speed;
	u32			*gsi_reg;
	int			gsi_reg_offset_cnt;

	struct notifier_block	dpdm_nb;
	struct regulator	*dpdm_reg;

};

#define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -2755,6 +2760,17 @@ static void dwc3_resume_work(struct work_struct *w)
			dwc->gadget.is_selfpowered = 0;
	}

	/*
	 * Skip scheduling sm work if no work is pending. When boot-up
	 * with USB cable connected, usb state m/c is skipped to avoid
	 * any changes to dp/dm lines. As PM supsend and resume can
	 * happen while charger is connected, scheduling sm work during
	 * pm resume will reset the controller and phy which might impact
	 * dp/dm lines (and charging voltage).
	 */
	if (mdwc->drd_state == DRD_STATE_UNDEFINED &&
		!edev && !mdwc->resume_pending)
		return;
	/*
	 * exit LPM first to meet resume timeline from device side.
	 * resume_pending flag would prevent calling
@@ -3368,6 +3384,29 @@ static ssize_t bus_vote_store(struct device *dev,
}
static DEVICE_ATTR_RW(bus_vote);

static int dwc_dpdm_cb(struct notifier_block *nb, unsigned long evt, void *p)
{
	struct dwc3_msm *mdwc = container_of(nb, struct dwc3_msm, dpdm_nb);

	switch (evt) {
	case REGULATOR_EVENT_ENABLE:
		dev_dbg(mdwc->dev, "%s: enable state:%s\n", __func__,
				dwc3_drd_state_string(mdwc->drd_state));
		break;
	case REGULATOR_EVENT_DISABLE:
		dev_dbg(mdwc->dev, "%s: disable state:%s\n", __func__,
				dwc3_drd_state_string(mdwc->drd_state));
		if (mdwc->drd_state == DRD_STATE_UNDEFINED)
			schedule_delayed_work(&mdwc->sm_work, 0);
		break;
	default:
		dev_dbg(mdwc->dev, "%s: unknown event state:%s\n", __func__,
				dwc3_drd_state_string(mdwc->drd_state));
		break;
	}

	return NOTIFY_OK;
}
static int dwc3_msm_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node, *dwc3_node;
@@ -3675,6 +3714,29 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		ret = dwc3_msm_extcon_register(mdwc);
		if (ret)
			goto put_dwc3;

		/*
		 * dpdm regulator will be turned on to perform apsd
		 * (automatic power source detection). dpdm regulator is
		 * used to float (or high-z) dp/dm lines. Do not reset
		 * controller/phy if regulator is turned on.
		 * if dpdm is not present controller can be reset
		 * as this controller may not be used for charger detection.
		 */
		mdwc->dpdm_reg = devm_regulator_get(&pdev->dev, "dpdm");
		if (IS_ERR(mdwc->dpdm_reg)) {
			dev_dbg(mdwc->dev, "assume cable is not connected\n");
			mdwc->dpdm_reg = NULL;
		}

		if (!mdwc->vbus_active && mdwc->dpdm_reg &&
				regulator_is_enabled(mdwc->dpdm_reg)) {
			mdwc->dpdm_nb.notifier_call = dwc_dpdm_cb;
			regulator_register_notifier(mdwc->dpdm_reg,
					&mdwc->dpdm_nb);
		} else {
			queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0);
		}
	} else {
		if ((dwc3_is_otg_or_drd(dwc) &&
		     !of_property_read_bool(node, "qcom,default-mode-host")) ||
@@ -3721,6 +3783,12 @@ static int dwc3_msm_remove(struct platform_device *pdev)
	int ret_pm;

	device_remove_file(&pdev->dev, &dev_attr_mode);

	if (mdwc->dpdm_nb.notifier_call) {
		regulator_unregister_notifier(mdwc->dpdm_reg, &mdwc->dpdm_nb);
		mdwc->dpdm_nb.notifier_call = NULL;
	}

	if (mdwc->usb_psy)
		power_supply_put(mdwc->usb_psy);

@@ -4271,6 +4339,12 @@ static void dwc3_otg_sm_work(struct work_struct *w)
	/* Check OTG state */
	switch (mdwc->drd_state) {
	case DRD_STATE_UNDEFINED:
		if (mdwc->dpdm_nb.notifier_call) {
			regulator_unregister_notifier(mdwc->dpdm_reg,
					&mdwc->dpdm_nb);
			mdwc->dpdm_nb.notifier_call = NULL;
		}

		/* put controller and phy in suspend if no cable connected */
		if (test_bit(ID, &mdwc->inputs) &&
				!test_bit(B_SESS_VLD, &mdwc->inputs)) {