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

Commit 20f42600 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "phy: qcom-ufs: Vote for qphy rpmh resource"

parents 32ce454c dfe39df3
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2016, 2019 Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -23,6 +23,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <soc/qcom/cmd-db.h>
#include <soc/qcom/rpmh.h>

#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
({ \
@@ -80,6 +82,12 @@ struct ufs_qcom_phy_vreg {
	bool is_always_on;
};

struct ufs_qcom_phy_rpmh_rsc {
	const char *qphy_rsc_name;
	u32 qphy_rsc_addr;
	bool enabled;
};

struct ufs_qcom_phy {
	struct list_head list;
	struct device *dev;
@@ -97,6 +105,7 @@ struct ufs_qcom_phy {
	struct ufs_qcom_phy_vreg vdda_pll;
	struct ufs_qcom_phy_vreg vdda_phy;
	struct ufs_qcom_phy_vreg vddp_ref_clk;
	struct ufs_qcom_phy_rpmh_rsc rpmh_rsc;

	/* Number of lanes available (1 or 2) for Rx/Tx */
	u32 lanes_per_direction;
+60 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2016, 2019 Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -146,6 +146,20 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
		common_cfg->lanes_per_direction =
			UFS_PHY_DEFAULT_LANES_PER_DIRECTION;

	if (of_property_read_string(dev->of_node, "qcom,rpmh-resource-name",
			     &common_cfg->rpmh_rsc.qphy_rsc_name))
		dev_dbg(dev, "%s rpmh-resource-name missing in DT node or n/a\n",
				__func__);

	if (common_cfg->rpmh_rsc.qphy_rsc_name) {
		err = cmd_db_ready();
		if (err) {
			dev_err(dev, "%s: Command DB not ready, err: %d\n",
				__func__, err);
			goto out;
		}
	}

	/*
	 * UFS PHY power management is managed by its parent (UFS host
	 * controller) hence set the no the no runtime PM callbacks flag
@@ -316,6 +330,15 @@ int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common)
	ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk,
		"vddp-ref-clk");

	if (phy_common->rpmh_rsc.qphy_rsc_name) {
		phy_common->rpmh_rsc.qphy_rsc_addr =
			cmd_db_read_addr(phy_common->rpmh_rsc.qphy_rsc_name);
		if (!phy_common->rpmh_rsc.qphy_rsc_addr) {
			dev_err(phy_common->dev, "%s: Invalid rpmh resource address\n",
					__func__);
			err = EINVAL;
		}
	}
out:
	return err;
}
@@ -526,6 +549,31 @@ static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy)
	}
}

static int ufs_qcom_phy_setup_rpmh_rsc(struct device *dev,
				struct ufs_qcom_phy_rpmh_rsc *rpmh_rsc,
				bool on)
{
	struct tcs_cmd cmd = {0};
	int err = 0;

	if (!rpmh_rsc->qphy_rsc_addr)
		goto out;

	if (rpmh_rsc->enabled == on)
		goto out;

	cmd.addr = rpmh_rsc->qphy_rsc_addr;
	cmd.data = on;
	cmd.wait = true;

	err = rpmh_write_async(dev, RPMH_ACTIVE_ONLY_STATE, &cmd, 1);
	if (!err)
		rpmh_rsc->enabled = on;

out:
	return err;
}

#define UFS_REF_CLK_EN	(1 << 5)

static void ufs_qcom_phy_dev_ref_clk_ctrl(struct phy *generic_phy, bool enable)
@@ -723,6 +771,13 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
	if (phy_common->is_powered_on)
		return 0;

	err = ufs_qcom_phy_setup_rpmh_rsc(dev, &phy_common->rpmh_rsc, 1);
	if (err) {
		dev_err(dev, "%s enable rpmh resource failed, err=%d\n",
			__func__, err);
		goto out;
	}

	err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
	if (err) {
		dev_err(dev, "%s enable vdda_phy failed, err=%d\n",
@@ -798,6 +853,10 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)

	ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll);
	ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy);

	ufs_qcom_phy_setup_rpmh_rsc(phy_common->dev,
				&phy_common->rpmh_rsc, 0);

	phy_common->is_powered_on = false;

	return 0;