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

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

Merge "usb: phy: qmp: Add support for fpc re-drive chipset"

parents 40436c01 ded9e84c
Loading
Loading
Loading
Loading
+112 −56
Original line number Diff line number Diff line
@@ -25,10 +25,10 @@
#include <linux/clk.h>
#include <linux/reset.h>

enum core_ldo_levels {
	CORE_LEVEL_NONE = 0,
	CORE_LEVEL_MIN,
	CORE_LEVEL_MAX,
enum ldo_levels {
	VOLTAGE_LEVEL_NONE = 0,
	VOLTAGE_LEVEL_MIN,
	VOLTAGE_LEVEL_MAX,
};

#define INIT_MAX_TIME_USEC			1000
@@ -38,6 +38,8 @@ enum core_ldo_levels {
#define USB_SSPHY_1P2_VOL_MAX		1200000 /* uV */
#define USB_SSPHY_HPM_LOAD		23000	/* uA */

#define USB_SSPHY_LOAD_DEFAULT		-1

/* USB3PHY_PCIE_USB3_PCS_PCS_STATUS bit */
#define PHYSTATUS				BIT(6)

@@ -119,6 +121,9 @@ struct msm_ssphy_qmp {
	int			vdd_levels[3]; /* none, low, high */
	struct regulator	*core_ldo;
	int			core_voltage_levels[3];
	struct regulator	*fpc_redrive_ldo;
	int			redrive_voltage_levels[3];
	int			redrive_load;
	struct clk		*ref_clk_src;
	struct clk		*ref_clk;
	struct clk		*aux_clk;
@@ -226,6 +231,33 @@ static void msm_ssusb_qmp_enable_autonomous(struct msm_ssphy_qmp *phy,
	}
}

static int msm_ldo_enable(struct msm_ssphy_qmp *phy,
		struct regulator *ldo, int *voltage_levels, int load)
{
	int ret = 0;

	dev_dbg(phy->phy.dev,
		"ldo: min_vol:%duV max_vol:%duV\n",
		voltage_levels[VOLTAGE_LEVEL_MIN],
		voltage_levels[VOLTAGE_LEVEL_MAX]);

	if (load > 0) {
		ret = regulator_set_load(ldo, load);
		if (ret < 0)
			return ret;
	}

	ret = regulator_set_voltage(ldo,
			voltage_levels[VOLTAGE_LEVEL_MIN],
			voltage_levels[VOLTAGE_LEVEL_MAX]);
	if (ret)
		return ret;

	ret = regulator_enable(ldo);

	return ret;
}

static int msm_ssusb_qmp_ldo_enable(struct msm_ssphy_qmp *phy, int on)
{
	int min, rc = 0;
@@ -245,74 +277,65 @@ static int msm_ssusb_qmp_ldo_enable(struct msm_ssphy_qmp *phy, int on)
	if (!on)
		goto disable_regulators;

	rc = regulator_set_voltage(phy->vdd, phy->vdd_levels[min],
				    phy->vdd_levels[2]);
	if (rc) {
		dev_err(phy->phy.dev, "unable to set voltage for ssusb vdd\n");
	if (phy->fpc_redrive_ldo) {
		rc = msm_ldo_enable(phy, phy->fpc_redrive_ldo,
				phy->redrive_voltage_levels,
				phy->redrive_load);
		if (rc < 0) {
			dev_err(phy->phy.dev,
				"enable phy->fpc_redrive_ldo failed\n");
			return rc;
		}

	dev_dbg(phy->phy.dev, "min_vol:%d max_vol:%d\n",
		phy->vdd_levels[min], phy->vdd_levels[2]);

	rc = regulator_enable(phy->vdd);
	if (rc) {
		dev_err(phy->phy.dev,
			"regulator_enable(phy->vdd) failed, ret=%d",
			rc);
		goto unconfig_vdd;
		dev_dbg(phy->phy.dev,
			"fpc redrive ldo: min_vol:%duV max_vol:%duV\n",
			phy->redrive_voltage_levels[VOLTAGE_LEVEL_MIN],
			phy->redrive_voltage_levels[VOLTAGE_LEVEL_MAX]);
	}

	rc = regulator_set_load(phy->core_ldo, USB_SSPHY_HPM_LOAD);
	rc = msm_ldo_enable(phy, phy->vdd, phy->vdd_levels,
			USB_SSPHY_LOAD_DEFAULT);
	if (rc < 0) {
		dev_err(phy->phy.dev, "Unable to set HPM of core_ldo\n");
		goto disable_vdd;
		dev_err(phy->phy.dev, "enable phy->vdd failed\n");
		goto disable_fpc_redrive;
	}

	rc = regulator_set_voltage(phy->core_ldo,
			phy->core_voltage_levels[CORE_LEVEL_MIN],
			phy->core_voltage_levels[CORE_LEVEL_MAX]);
	if (rc) {
		dev_err(phy->phy.dev, "unable to set voltage for core_ldo\n");
		goto put_core_ldo_lpm;
	}
	dev_dbg(phy->phy.dev,
		"vdd ldo: min_vol:%duV max_vol:%duV\n",
		phy->vdd_levels[VOLTAGE_LEVEL_MIN],
		phy->vdd_levels[VOLTAGE_LEVEL_MAX]);

	rc = regulator_enable(phy->core_ldo);
	if (rc) {
		dev_err(phy->phy.dev, "Unable to enable core_ldo\n");
		goto unset_core_ldo;
	rc = msm_ldo_enable(phy, phy->core_ldo, phy->core_voltage_levels,
			USB_SSPHY_HPM_LOAD);
	if (rc < 0) {
		dev_err(phy->phy.dev, "enable phy->core_ldo failed\n");
		goto disable_vdd;
	}

	dev_dbg(phy->phy.dev,
		"core ldo: min_vol:%duV max_vol:%duV\n",
		phy->core_voltage_levels[VOLTAGE_LEVEL_MIN],
		phy->core_voltage_levels[VOLTAGE_LEVEL_MAX]);

	return 0;

disable_regulators:
	rc = regulator_disable(phy->core_ldo);
	if (rc)
		dev_err(phy->phy.dev, "Unable to disable core_ldo\n");

unset_core_ldo:
	rc = regulator_set_voltage(phy->core_ldo,
			phy->core_voltage_levels[CORE_LEVEL_NONE],
			phy->core_voltage_levels[CORE_LEVEL_MAX]);
	if (rc)
		dev_err(phy->phy.dev, "unable to set voltage for core_ldo\n");

put_core_ldo_lpm:
	rc = regulator_set_load(phy->core_ldo, 0);
	if (rc < 0)
		dev_err(phy->phy.dev, "Unable to set LPM of core_ldo\n");
		dev_err(phy->phy.dev, "disable phy->core_ldo failed\n");

disable_vdd:
	rc = regulator_disable(phy->vdd);
	if (rc)
		dev_err(phy->phy.dev, "regulator_disable(phy->vdd) failed, ret=%d",
			rc);
		dev_err(phy->phy.dev, "disable phy->vdd failed\n");

unconfig_vdd:
	rc = regulator_set_voltage(phy->vdd, phy->vdd_levels[min],
				    phy->vdd_levels[2]);
disable_fpc_redrive:
	if (phy->fpc_redrive_ldo) {
		rc = regulator_disable(phy->fpc_redrive_ldo);
		if (rc)
		dev_err(phy->phy.dev, "unable to set voltage for ssusb vdd\n");
			dev_err(phy->phy.dev,
				"disable phy->fpc_redrive_ldo failed\n");
	}

	return rc < 0 ? rc : 0;
}
@@ -944,9 +967,9 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
	}

	/* Set default core voltage values */
	phy->core_voltage_levels[CORE_LEVEL_NONE] = 0;
	phy->core_voltage_levels[CORE_LEVEL_MIN] = USB_SSPHY_1P2_VOL_MIN;
	phy->core_voltage_levels[CORE_LEVEL_MAX] = USB_SSPHY_1P2_VOL_MAX;
	phy->core_voltage_levels[VOLTAGE_LEVEL_NONE] = 0;
	phy->core_voltage_levels[VOLTAGE_LEVEL_MIN] = USB_SSPHY_1P2_VOL_MIN;
	phy->core_voltage_levels[VOLTAGE_LEVEL_MAX] = USB_SSPHY_1P2_VOL_MAX;

	if (of_get_property(dev->of_node, "qcom,core-voltage-level", &len) &&
		len == sizeof(phy->core_voltage_levels)) {
@@ -990,6 +1013,39 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
		goto err;
	}

	phy->fpc_redrive_ldo = devm_regulator_get_optional(dev, "fpc-redrive");
	if (IS_ERR(phy->fpc_redrive_ldo)) {
		phy->fpc_redrive_ldo = NULL;
		dev_dbg(dev, "no FPC re-drive ldo regulator\n");
	} else {
		if (of_get_property(dev->of_node,
				"qcom,redrive-voltage-level", &len) &&
				len == sizeof(phy->redrive_voltage_levels)) {
			ret = of_property_read_u32_array(dev->of_node,
					"qcom,redrive-voltage-level",
					(u32 *) phy->redrive_voltage_levels,
					len / sizeof(u32));
			if (ret) {
				dev_err(dev,
					"err qcom,redrive-voltage-level\n");
				goto err;
			}
		} else {
			ret = -EINVAL;
			dev_err(dev, "err inputs for redrive-voltage-level\n");
			goto err;
		}

		ret = of_property_read_u32(dev->of_node, "qcom,redrive-load",
				&phy->redrive_load);
		if (ret) {
			dev_err(&pdev->dev, "unable to read redrive load\n");
			goto err;
		}

		dev_dbg(dev, "Get FPC re-drive ldo regulator\n");
	}

	platform_set_drvdata(pdev, phy);

	if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override"))