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

Commit 5841594b authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "phy: usb: qmp: Add com_aux_clk related support" into msm-4.9

parents 7f073cb3 561d0441
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -43,7 +43,7 @@ Optional properties:
 - clocks: a list of phandles to the PHY clocks. Use as per
 - clocks: a list of phandles to the PHY clocks. Use as per
   Documentation/devicetree/bindings/clock/clock-bindings.txt
   Documentation/devicetree/bindings/clock/clock-bindings.txt
 - clock-names: Names of the clocks in 1-1 correspondence with the "clocks"
 - clock-names: Names of the clocks in 1-1 correspondence with the "clocks"
   property. "cfg_ahb_clk" is an optional clock.
   property. "cfg_ahb_clk" and "com_aux_clk" are an optional clocks.
 - qcom,vbus-valid-override: If present, indicates VBUS pin is not connected to
 - 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
   the USB PHY and the controller must rely on external VBUS notification in
   order to manually relay the notification to the SSPHY.
   order to manually relay the notification to the SSPHY.
+93 −55
Original line number Original line Diff line number Diff line
@@ -84,6 +84,7 @@ struct msm_ssphy_qmp {
	struct clk		*ref_clk_src;
	struct clk		*ref_clk_src;
	struct clk		*ref_clk;
	struct clk		*ref_clk;
	struct clk		*aux_clk;
	struct clk		*aux_clk;
	struct clk		*com_aux_clk;
	struct clk		*cfg_ahb_clk;
	struct clk		*cfg_ahb_clk;
	struct clk		*pipe_clk;
	struct clk		*pipe_clk;
	struct reset_control	*phy_reset;
	struct reset_control	*phy_reset;
@@ -114,6 +115,8 @@ static const struct of_device_id msm_usb_id_table[] = {
};
};
MODULE_DEVICE_TABLE(of, msm_usb_id_table);
MODULE_DEVICE_TABLE(of, msm_usb_id_table);


static void msm_ssphy_qmp_enable_clks(struct msm_ssphy_qmp *phy, bool on);

static inline char *get_cable_status_str(struct msm_ssphy_qmp *phy)
static inline char *get_cable_status_str(struct msm_ssphy_qmp *phy)
{
{
	return phy->cable_connected ? "connected" : "disconnected";
	return phy->cable_connected ? "connected" : "disconnected";
@@ -292,17 +295,7 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy)
		return ret;
		return ret;
	}
	}


	if (!phy->clk_enabled) {
	msm_ssphy_qmp_enable_clks(phy, true);
		if (phy->ref_clk_src)
			clk_prepare_enable(phy->ref_clk_src);
		if (phy->ref_clk)
			clk_prepare_enable(phy->ref_clk);
		clk_prepare_enable(phy->aux_clk);
		clk_prepare_enable(phy->cfg_ahb_clk);
		clk_set_rate(phy->pipe_clk, 125000000);
		clk_prepare_enable(phy->pipe_clk);
		phy->clk_enabled = true;
	}


	writel_relaxed(0x01,
	writel_relaxed(0x01,
		phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]);
		phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]);
@@ -469,29 +462,13 @@ static int msm_ssphy_qmp_set_suspend(struct usb_phy *uphy, int suspend)
		/* Make sure above write completed with PHY */
		/* Make sure above write completed with PHY */
		wmb();
		wmb();


		clk_disable_unprepare(phy->cfg_ahb_clk);
		msm_ssphy_qmp_enable_clks(phy, false);
		clk_disable_unprepare(phy->aux_clk);
		clk_disable_unprepare(phy->pipe_clk);
		if (phy->ref_clk)
			clk_disable_unprepare(phy->ref_clk);
		if (phy->ref_clk_src)
			clk_disable_unprepare(phy->ref_clk_src);
		phy->clk_enabled = false;
		phy->in_suspend = true;
		phy->in_suspend = true;
		msm_ssphy_power_enable(phy, 0);
		msm_ssphy_power_enable(phy, 0);
		dev_dbg(uphy->dev, "QMP PHY is suspend\n");
		dev_dbg(uphy->dev, "QMP PHY is suspend\n");
	} else {
	} else {
		msm_ssphy_power_enable(phy, 1);
		msm_ssphy_power_enable(phy, 1);
		clk_prepare_enable(phy->pipe_clk);
		msm_ssphy_qmp_enable_clks(phy, true);
		if (!phy->clk_enabled) {
			if (phy->ref_clk_src)
				clk_prepare_enable(phy->ref_clk_src);
			if (phy->ref_clk)
				clk_prepare_enable(phy->ref_clk);
			clk_prepare_enable(phy->aux_clk);
			clk_prepare_enable(phy->cfg_ahb_clk);
			phy->clk_enabled = true;
		}
		if (!phy->cable_connected) {
		if (!phy->cable_connected) {
			writel_relaxed(0x01,
			writel_relaxed(0x01,
			phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]);
			phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]);
@@ -533,16 +510,9 @@ static int msm_ssphy_qmp_notify_disconnect(struct usb_phy *uphy,
	return 0;
	return 0;
}
}


static int msm_ssphy_qmp_probe(struct platform_device *pdev)
static int msm_ssphy_qmp_get_clks(struct msm_ssphy_qmp *phy, struct device *dev)
{
{
	struct msm_ssphy_qmp *phy;
	int ret = 0;
	struct device *dev = &pdev->dev;
	struct resource *res;
	int ret = 0, size = 0, len;

	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
	if (!phy)
		return -ENOMEM;


	phy->aux_clk = devm_clk_get(dev, "aux_clk");
	phy->aux_clk = devm_clk_get(dev, "aux_clk");
	if (IS_ERR(phy->aux_clk)) {
	if (IS_ERR(phy->aux_clk)) {
@@ -552,10 +522,9 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
			dev_err(dev, "failed to get aux_clk\n");
			dev_err(dev, "failed to get aux_clk\n");
		goto err;
		goto err;
	}
	}

	clk_set_rate(phy->aux_clk, clk_round_rate(phy->aux_clk, ULONG_MAX));
	clk_set_rate(phy->aux_clk, clk_round_rate(phy->aux_clk, ULONG_MAX));


	if (of_property_match_string(pdev->dev.of_node,
	if (of_property_match_string(dev->of_node,
			"clock-names", "cfg_ahb_clk") >= 0) {
			"clock-names", "cfg_ahb_clk") >= 0) {
		phy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk");
		phy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk");
		if (IS_ERR(phy->cfg_ahb_clk)) {
		if (IS_ERR(phy->cfg_ahb_clk)) {
@@ -576,6 +545,88 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
		goto err;
		goto err;
	}
	}


	phy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
	if (IS_ERR(phy->ref_clk_src))
		phy->ref_clk_src = NULL;

	phy->ref_clk = devm_clk_get(dev, "ref_clk");
	if (IS_ERR(phy->ref_clk))
		phy->ref_clk = NULL;

	if (of_property_match_string(dev->of_node,
			"clock-names", "com_aux_clk") >= 0) {
		phy->com_aux_clk = devm_clk_get(dev, "com_aux_clk");
		if (IS_ERR(phy->com_aux_clk)) {
			ret = PTR_ERR(phy->com_aux_clk);
			if (ret != -EPROBE_DEFER)
				dev_err(dev,
				"failed to get com_aux_clk ret %d\n", ret);
			goto err;
		}
	}

err:
	return ret;
}

static void msm_ssphy_qmp_enable_clks(struct msm_ssphy_qmp *phy, bool on)
{
	dev_dbg(phy->phy.dev, "%s(): clk_enabled:%d on:%d\n", __func__,
					phy->clk_enabled, on);

	if (!phy->clk_enabled && on) {
		if (phy->ref_clk_src)
			clk_prepare_enable(phy->ref_clk_src);

		if (phy->ref_clk)
			clk_prepare_enable(phy->ref_clk);

		if (phy->com_aux_clk)
			clk_prepare_enable(phy->com_aux_clk);

		clk_prepare_enable(phy->aux_clk);
		if (phy->cfg_ahb_clk)
			clk_prepare_enable(phy->cfg_ahb_clk);

		clk_prepare_enable(phy->pipe_clk);
		phy->clk_enabled = true;
	}

	if (phy->clk_enabled && !on) {
		clk_disable_unprepare(phy->pipe_clk);

		if (phy->cfg_ahb_clk)
			clk_disable_unprepare(phy->cfg_ahb_clk);

		clk_disable_unprepare(phy->aux_clk);
		if (phy->com_aux_clk)
			clk_disable_unprepare(phy->com_aux_clk);

		if (phy->ref_clk)
			clk_disable_unprepare(phy->ref_clk);

		if (phy->ref_clk_src)
			clk_disable_unprepare(phy->ref_clk_src);

		phy->clk_enabled = false;
	}
}

static int msm_ssphy_qmp_probe(struct platform_device *pdev)
{
	struct msm_ssphy_qmp *phy;
	struct device *dev = &pdev->dev;
	struct resource *res;
	int ret = 0, size = 0, len;

	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
	if (!phy)
		return -ENOMEM;

	ret = msm_ssphy_qmp_get_clks(phy, dev);
	if (ret)
		goto err;

	phy->phy_reset = devm_reset_control_get(dev, "phy_reset");
	phy->phy_reset = devm_reset_control_get(dev, "phy_reset");
	if (IS_ERR(phy->phy_reset)) {
	if (IS_ERR(phy->phy_reset)) {
		ret = PTR_ERR(phy->phy_reset);
		ret = PTR_ERR(phy->phy_reset);
@@ -726,13 +777,6 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
		goto err;
		goto err;
	}
	}


	phy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
	if (IS_ERR(phy->ref_clk_src))
		phy->ref_clk_src = NULL;
	phy->ref_clk = devm_clk_get(dev, "ref_clk");
	if (IS_ERR(phy->ref_clk))
		phy->ref_clk = NULL;

	platform_set_drvdata(pdev, phy);
	platform_set_drvdata(pdev, phy);


	if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override"))
	if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override"))
@@ -760,14 +804,8 @@ static int msm_ssphy_qmp_remove(struct platform_device *pdev)
		return 0;
		return 0;


	usb_remove_phy(&phy->phy);
	usb_remove_phy(&phy->phy);
	if (phy->ref_clk)
	msm_ssphy_qmp_enable_clks(phy, false);
		clk_disable_unprepare(phy->ref_clk);
	if (phy->ref_clk_src)
		clk_disable_unprepare(phy->ref_clk_src);
	msm_ssusb_qmp_ldo_enable(phy, 0);
	msm_ssusb_qmp_ldo_enable(phy, 0);
	clk_disable_unprepare(phy->aux_clk);
	clk_disable_unprepare(phy->cfg_ahb_clk);
	clk_disable_unprepare(phy->pipe_clk);
	kfree(phy);
	kfree(phy);
	return 0;
	return 0;
}
}