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

Commit 851c8c39 authored by Subhash Jadavani's avatar Subhash Jadavani Committed by David Keitel
Browse files

scsi: ufs-qcom: add support to control the device ref_clk



On Qualcomm platforms, there will be many consumers of the source clock
which also supply ref_clk to UFS Device. So even if generic UFS
driver (ufshcd) vote to turn off the source ref_clk, it's very likely that
device ref_clk is still running. Hence some of the qualcomm chipsets have
separate control bit to gate & ungate the UFS ref_clk to device. This
control bit is part of the TLMM register adddress space so it can't be
simulated at clock control bit which means UFS qcom driver has to manually
control this bit to gate or ungate the device ref_clk. This change adds
support for the same.

Change-Id: I3ee1187292eaadfdb552d33c2bb6f58922c9e501
[subhashj@codeaurora.org: resolved merge conflicts, dropped changes to
msm8994.dtsi]
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
[venkatg@codeaurora.org: resolved trivial merge conflicts,
drop changes to include/linux/phy/phy-qcom-ufs.h]
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
parent f1a31bce
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -10,7 +10,10 @@ Required properties:
- compatible        : compatible list, contains "qcom,ufs-phy-qmp-28nm"
                      or "qcom,ufs-phy-qmp-20nm" according to the relevant
                      phy in use
- reg               : <registers mapping>
- reg               : should contain PHY register address space (mandatory),
                      device PHY control register map (optional).
- reg-names         : indicates various resources passed to driver (via reg proptery) by name.
                      Required "reg-names" is "phy_mem" and "dev_ref_clk_ctrl_mem" is optional.
- #phy-cells        : This property shall be set to 0
- vdda-phy-supply   : phandle to main PHY supply for analog domain
- vdda-pll-supply   : phandle to PHY PLL and Power-Gen block power supply
@@ -23,7 +26,8 @@ Example:

	ufsphy1: ufsphy@0xfc597000 {
		compatible = "qcom,ufs-phy-qmp-28nm";
		reg = <0xfc597000 0x800>;
		reg = <0xfc597000 0x800>, <0xfd512074 0x4>;
		reg-names = "phy_mem", "dev_ref_clk_ctrl_mem";
		#phy-cells = <0>;
		vdda-phy-supply = <&pma8084_l4>;
		vdda-pll-supply = <&pma8084_l12>;
+34 −3
Original line number Diff line number Diff line
@@ -131,10 +131,9 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev,
	struct resource *res;
	int err = 0;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
	if (!res) {
		dev_err(dev, "%s: platform_get_resource() failed. returned NULL\n",
			__func__);
		dev_err(dev, "%s: phy_mem resource not found\n", __func__);
		err = -ENOMEM;
		goto out;
	}
@@ -446,6 +445,38 @@ void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy)
	}
}

#define UFS_REF_CLK_EN	(1 << 5)

static void ufs_qcom_phy_dev_ref_clk_ctrl(struct phy *generic_phy, bool enable)
{
	struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);

	if (phy->dev_ref_clk_ctrl_mmio &&
	    (enable ^ phy->is_dev_ref_clk_enabled)) {
		u32 temp = readl_relaxed(phy->dev_ref_clk_ctrl_mmio);

		if (enable)
			temp |= UFS_REF_CLK_EN;
		else
			temp &= ~UFS_REF_CLK_EN;

		writel_relaxed(temp, phy->dev_ref_clk_ctrl_mmio);
		/* ensure that ref_clk is enabled/disabled before we return */
		wmb();
		phy->is_dev_ref_clk_enabled = enable;
	}
}

void ufs_qcom_phy_enable_dev_ref_clk(struct phy *generic_phy)
{
	ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true);
}

void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
{
	ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false);
}

void ufs_qcom_phy_restore_swi_regs(struct phy *generic_phy)
{
	int i;
+7 −3
Original line number Diff line number Diff line
@@ -963,16 +963,20 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
			ufs_qcom_phy_disable_iface_clk(host->generic_phy);
			goto out;
		}

		/* enable the device ref clock */
		ufs_qcom_phy_enable_dev_ref_clk(host->generic_phy);
		vote = host->bus_vote.saved_vote;
		if (vote == host->bus_vote.min_bw_vote)
			ufs_qcom_update_bus_bw_vote(host);
	} else {
		/* M-PHY RMMI interface clocks can be turned off */
		ufs_qcom_phy_disable_iface_clk(host->generic_phy);
		/* If link is not active, turn off UFS local PHY ref_clk */
		if (!ufs_qcom_is_link_active(hba))
		if (!ufs_qcom_is_link_active(hba)) {
			/* turn off UFS local PHY ref_clk */
			ufs_qcom_phy_disable_ref_clk(host->generic_phy);
			/* disable device ref_clk */
			ufs_qcom_phy_disable_dev_ref_clk(host->generic_phy);
		}
		vote = host->bus_vote.min_bw_vote;
	}