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

Commit 2017be12 authored by Gilad Broner's avatar Gilad Broner
Browse files

usb: phy: msm: Disable LDOs when suspending with cable disconnected



When the phy does not handle the vbus and id changes by itself
acting as a device and going into suspend with the cable disconnected,
turning off the phy's LDOs can also be performed to conserve more
power. This is already done by the HS phy.
To support this additional device tree property 'qcom,ext-vbus-id' was
added to the ss-phy node to indicate the phy does not handle vbus
and id changes.

Change-Id: Ia79459f95359a6c1b9de32ab9735640d6510cc0d
Signed-off-by: default avatarGilad Broner <gbroner@codeaurora.org>
parent c433c688
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ Optional properties:
		bits 6-12  PARAMETER_OVERRIDE_B
		bits 13-19 PARAMETER_OVERRIDE_C
		bits 20-25 PARAMETER_OVERRIDE_D
 - qcom,ext-vbus-id: If present then PHY does not handle VBUS and ID changes.
 - qcom,ext-vbus-id: If present, indicates that the PHY does not handle VBUS and ID changes.
 - qcom,vbus-valid-override: If present, indicates VBUS pin is not connected to
   the USB PHY and the controller must rely on external VBUS notification in
   order to manually enable the D+ pull-up resistor.
@@ -96,6 +96,7 @@ Optional properties:
 - qcom,vbus-valid-override: If present, indicates VBUS pin is not connected to
   the USB PHY and the controller must rely on external VBUS notification in
   order to manually relay the notification to the SSPHY.
 - qcom,ext-vbus-id: If present, indicates that the PHY does not handle VBUS and ID changes.

Example:
	ssphy0: ssphy@f9b38000 {
+16 −6
Original line number Diff line number Diff line
@@ -1502,10 +1502,13 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
	dcp = ((mdwc->charger.chg_type == DWC3_DCP_CHARGER) ||
	      (mdwc->charger.chg_type == DWC3_PROPRIETARY_CHARGER) ||
	      (mdwc->charger.chg_type == DWC3_FLOATED_CHARGER));
	if (dcp)
	if (dcp) {
		mdwc->hs_phy->flags |= PHY_CHARGER_CONNECTED;
	else
		mdwc->ss_phy->flags |= PHY_CHARGER_CONNECTED;
	} else {
		mdwc->hs_phy->flags &= ~PHY_CHARGER_CONNECTED;
		mdwc->ss_phy->flags &= ~PHY_CHARGER_CONNECTED;
	}

	host_bus_suspend = (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM);
	can_suspend_ssphy = !(host_bus_suspend && host_ss_active);
@@ -1611,10 +1614,13 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
	dcp = ((mdwc->charger.chg_type == DWC3_DCP_CHARGER) ||
	      (mdwc->charger.chg_type == DWC3_PROPRIETARY_CHARGER) ||
	      (mdwc->charger.chg_type == DWC3_FLOATED_CHARGER));
	if (dcp)
	if (dcp) {
		mdwc->hs_phy->flags |= PHY_CHARGER_CONNECTED;
	else
		mdwc->ss_phy->flags |= PHY_CHARGER_CONNECTED;
	} else {
		mdwc->hs_phy->flags &= ~PHY_CHARGER_CONNECTED;
		mdwc->ss_phy->flags &= ~PHY_CHARGER_CONNECTED;
	}

	host_bus_suspend = (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM);

@@ -1934,10 +1940,13 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy,
	switch (psp) {
	case POWER_SUPPLY_PROP_SCOPE:
		mdwc->scope = val->intval;
		if (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM)
		if (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM) {
			mdwc->hs_phy->flags |= PHY_HOST_MODE;
		else
			mdwc->ss_phy->flags |= PHY_HOST_MODE;
		} else {
			mdwc->hs_phy->flags &= ~PHY_HOST_MODE;
			mdwc->ss_phy->flags &= ~PHY_HOST_MODE;
		}
		break;
	/* Process PMIC notification in PRESENT prop */
	case POWER_SUPPLY_PROP_PRESENT:
@@ -2857,6 +2866,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		dev_dbg(&pdev->dev, "No OTG, DWC3 running in host only mode\n");
		mdwc->scope = POWER_SUPPLY_SCOPE_SYSTEM;
		mdwc->hs_phy->flags |= PHY_HOST_MODE;
		mdwc->ss_phy->flags |= PHY_HOST_MODE;
	} else {
		dev_err(&pdev->dev, "DWC3 device-only mode not supported\n");
		ret = -ENODEV;
+47 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct msm_ssphy_qmp {
	bool			clk_enabled;
	bool			cable_connected;
	bool			in_suspend;
	bool			ext_vbus_id;
};

static inline char *get_cable_status_str(struct msm_ssphy_qmp *phy)
@@ -427,6 +428,47 @@ static int msm_ssphy_qmp_set_params(struct usb_phy *uphy)
	return 0;
}

static int msm_ssphy_power_enable(struct msm_ssphy_qmp *phy, bool on)
{
	bool host = phy->phy.flags & PHY_HOST_MODE;
	bool chg_connected = phy->phy.flags & PHY_CHARGER_CONNECTED;
	int ret = 0;

	/*
	 * Turn off the phy's LDOs when cable is disconnected for device mode
	 * with external vbus_id indication.
	 */
	if (!host && !chg_connected && phy->ext_vbus_id &&
		!phy->cable_connected) {
		if (on) {
			ret = regulator_enable(phy->vdd);
			if (ret)
				dev_err(phy->phy.dev,
					"regulator_enable(phy->vdd) failed, ret=%d",
					ret);

			ret = msm_ssusb_qmp_ldo_enable(phy, 1);
			if (ret)
				dev_err(phy->phy.dev,
				"msm_ssusb_qmp_ldo_enable(1) failed, ret=%d\n",
				ret);
		} else {
			ret = msm_ssusb_qmp_ldo_enable(phy, 0);
			if (ret)
				dev_err(phy->phy.dev,
					"msm_ssusb_qmp_ldo_enable(0) failed, ret=%d\n",
					ret);

			ret = regulator_disable(phy->vdd);
			if (ret)
				dev_err(phy->phy.dev, "regulator_disable(phy->vdd) failed, ret=%d",
					ret);
		}
	}

	return ret;
}

/**
 * Performs QMP PHY suspend/resume functionality.
 *
@@ -465,8 +507,10 @@ static int msm_ssphy_qmp_set_suspend(struct usb_phy *uphy, int suspend)
		clk_disable_unprepare(phy->cfg_ahb_clk);
		clk_disable_unprepare(phy->aux_clk);
		phy->in_suspend = true;
		msm_ssphy_power_enable(phy, 0);
		dev_dbg(uphy->dev, "QMP PHY is suspend\n");
	} else {
		msm_ssphy_power_enable(phy, 1);
		clk_prepare_enable(phy->aux_clk);
		clk_prepare_enable(phy->cfg_ahb_clk);
		if (!phy->cable_connected)
@@ -536,6 +580,9 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
		return ret;
	}

	phy->ext_vbus_id =
		of_property_read_bool(dev->of_node, "qcom,ext-vbus-id");

	phy->vdd = devm_regulator_get(dev, "vdd");
	if (IS_ERR(phy->vdd)) {
		dev_err(dev, "unable to get vdd supply\n");