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

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

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

parents 03e31afa 25b2d8ab
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
@@ -28,7 +31,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>;
+1 −0
Original line number Diff line number Diff line
@@ -1048,6 +1048,7 @@
	ufsphy1: ufsphy@fc597000 {
			compatible = "qcom,ufs-phy-qmp-20nm";
			reg = <0xfc597000 0xda8>;
			reg-names = "phy_mem";
			#phy-cells = <0>;
			vdda-phy-supply = <&pm8994_l28>;
			vdda-pll-supply = <&pm8994_l12>;
+55 −4
Original line number Diff line number Diff line
@@ -124,10 +124,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;
	}
@@ -135,7 +134,27 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev,
	phy_common->mmio = devm_ioremap_resource(dev, res);
	if (IS_ERR(phy_common->mmio)) {
		err = PTR_ERR(phy_common->mmio);
		dev_err(dev, "ioremap resource failed %d\n", err);
		phy_common->mmio = NULL;
		dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n",
			__func__, err);
		goto out;
	}

	/* "dev_ref_clk_ctrl_mem" is optional resource */
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
					   "dev_ref_clk_ctrl_mem");
	if (!res) {
		dev_dbg(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n",
			__func__);
		goto out;
	}

	phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res);
	if (IS_ERR(phy_common->dev_ref_clk_ctrl_mmio)) {
		err = PTR_ERR(phy_common->dev_ref_clk_ctrl_mmio);
		phy_common->dev_ref_clk_ctrl_mmio = NULL;
		dev_err(dev, "%s: ioremap for dev_ref_clk_ctrl_mem resource failed %d\n",
			__func__, err);
	}

out:
@@ -434,6 +453,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
@@ -871,16 +871,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;
	}

+4 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct ufs_qcom_phy {
	struct list_head list;
	struct device *dev;
	void __iomem *mmio;
	void __iomem *dev_ref_clk_ctrl_mmio;
	struct clk *tx_iface_clk;
	struct clk *rx_iface_clk;
	bool is_iface_clk_enabled;
@@ -68,6 +69,7 @@ struct ufs_qcom_phy {
	struct clk *ref_clk_parent;
	struct clk *ref_clk;
	bool is_ref_clk_enabled;
	bool is_dev_ref_clk_enabled;
	struct ufs_qcom_phy_vreg vdda_pll;
	struct ufs_qcom_phy_vreg vdda_phy;
	unsigned int quirks;
@@ -167,6 +169,8 @@ int ufs_qcom_phy_disable_vreg(struct phy *phy,
			struct ufs_qcom_phy_vreg *vreg);
int ufs_qcom_phy_enable_ref_clk(struct phy *phy);
void ufs_qcom_phy_disable_ref_clk(struct phy *phy);
void ufs_qcom_phy_enable_dev_ref_clk(struct phy *);
void ufs_qcom_phy_disable_dev_ref_clk(struct phy *);
int ufs_qcom_phy_enable_iface_clk(struct phy *phy);
void ufs_qcom_phy_disable_iface_clk(struct phy *phy);
void ufs_qcom_phy_restore_swi_regs(struct phy *phy);