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

Commit 55761962 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 bb950eb8 d759a98e
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
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
		interrupts = <0 25 0>, <0 319 0>;
		interrupt-names = "pwr_event_irq", "hs_phy_irq";

		dpdm-supply = <&usb2_phy0>;
		clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
			 <&clock_gcc GCC_SYS_NOC_USB3_CLK>,
			 <&clock_gcc GCC_USB30_SLEEP_CLK>,
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
		qcom,use-pdc-interrupts;

		USB3_GDSC-supply = <&usb30_prim_gdsc>;
		dpdm-supply = <&usb2_phy0>;
		clocks = <&clock_gcc GCC_USB30_PRIM_MASTER_CLK>,
			<&clock_gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
			<&clock_gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
+76 −1
Original line number Diff line number Diff line
@@ -37,6 +37,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>
@@ -150,6 +151,7 @@ enum dwc3_drd_state {
};

static const char *const state_names[] = {
	[DRD_STATE_UNDEFINED] = "undefined",
	[DRD_STATE_IDLE] = "idle",
	[DRD_STATE_PERIPHERAL] = "peripheral",
	[DRD_STATE_PERIPHERAL_SUSPEND] = "peripheral_suspend",
@@ -160,7 +162,7 @@ static const char *const state_names[] = {
const char *dwc3_drd_state_string(enum dwc3_drd_state state)
{
	if (state < 0 || state >= ARRAY_SIZE(state_names))
		return "UNDEFINED";
		return "UNKNOWN";

	return state_names[state];
}
@@ -320,6 +322,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 */
@@ -2769,6 +2775,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
@@ -3382,6 +3399,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;
@@ -3689,6 +3729,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 ((dwc->dr_mode == USB_DR_MODE_OTG &&
		     !of_property_read_bool(node, "qcom,default-mode-host")) ||
@@ -3736,6 +3799,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);

@@ -4298,6 +4367,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)) {