Linux-ARM-MSM Archive mirror
 help / color / mirror / Atom feed
From: Udipto Goswami <quic_ugoswami@quicinc.com>
To: Bjorn Andersson <andersson@kernel.org>,
	Konrad Dybcio <konrad.dybcio@linaro.org>,
	Vinod Koul <vkoul@kernel.org>,
	"Kishon Vijay Abraham I" <kishon@kernel.org>
Cc: <linux-arm-msm@vger.kernel.org>, <linux-phy@lists.infradead.org>,
	<linux-kernel@vger.kernel.org>,
	Udipto Goswami <quic_ugoswami@quicinc.com>
Subject: [PATCH] phy: qcom-snps-femto-v2: Add load and voltage setting for LDO's used
Date: Thu, 2 May 2024 18:03:12 +0530	[thread overview]
Message-ID: <20240502123312.31083-1-quic_ugoswami@quicinc.com> (raw)

The Femto phy depends on 0.88/ 1.8/ 3.3V regulators for its operation.
If one of the regulators is not voted to the required minimum voltage
for phy to operate, then High speed mode of operation will fail.

On certain targets like (qcm6490_rb3gen2) where the minimum voltage
of the regulator is lower than the operating voltage of the phy.
If not voted properly, the phy supply would be limited to the min value
of the LDO thereby rendering the phy non-operational.

The current implementation of the regulators in the Femto PHY is not
setting the load and voltage for each LDO. The appropriate voltages and
loads required for the PHY to operate should be set.

Implement a bulk operation api to set load & voltages before doing bulk
enable. This will ensure that the PHY remains operational under all
conditions.

Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com>
---
 drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 121 +++++++++++++++++-
 1 file changed, 114 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
index eb0b0f61d98e..cbe9cdaa6849 100644
--- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
+++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
@@ -78,11 +78,39 @@
 
 #define LS_FS_OUTPUT_IMPEDANCE_MASK		GENMASK(3, 0)
 
-static const char * const qcom_snps_hsphy_vreg_names[] = {
-	"vdda-pll", "vdda33", "vdda18",
+
+struct qcom_snps_hsphy_regulator_data {
+	const char *name;
+	unsigned int enable_load;
+	unsigned int min_voltage;
+	unsigned int max_voltage;
+};
+
+static const struct qcom_snps_hsphy_regulator_data hsphy_vreg_l[] = {
+	{
+		.name = "vdda-pll",
+		.enable_load = 30000,
+		.min_voltage = 825000,
+		.max_voltage = 925000,
+	},
+
+	{
+		.name = "vdda18",
+		.enable_load = 19000,
+		.min_voltage = 1704000,
+		.max_voltage = 1800000
+	},
+
+	{
+		.name = "vdda33",
+		.enable_load = 16000,
+		.min_voltage = 3050000,
+		.max_voltage = 3300000
+	},
+
 };
 
-#define SNPS_HS_NUM_VREGS		ARRAY_SIZE(qcom_snps_hsphy_vreg_names)
+#define SNPS_HS_NUM_VREGS		ARRAY_SIZE(hsphy_vreg_l)
 
 struct override_param {
 	s32	value;
@@ -132,12 +160,90 @@ struct qcom_snps_hsphy {
 	struct clk_bulk_data *clks;
 	struct reset_control *phy_reset;
 	struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
+	const struct qcom_snps_hsphy_regulator_data *vreg_list;
 
 	bool phy_initialized;
 	enum phy_mode mode;
 	struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
 };
 
+static int __vdda_phy_bulk_enable_disable(struct qcom_snps_hsphy *hsphy, bool on)
+{
+	int ret = 0;
+	int i;
+
+	if (!on)
+		goto disable_vdd;
+
+	for (i = 0; i < SNPS_HS_NUM_VREGS; i++) {
+
+		ret = regulator_set_load(hsphy->vregs[i].consumer,
+					 hsphy->vreg_list[i].enable_load);
+
+		if (ret < 0) {
+			dev_err(hsphy->dev, "unable to set HPM of %s %d\n",
+						hsphy->vregs[i].supply, ret);
+			goto err_vdd;
+		}
+	}
+
+	for (i = 0; i < SNPS_HS_NUM_VREGS; i++) {
+		ret = regulator_set_voltage(hsphy->vregs[i].consumer,
+					    hsphy->vreg_list[i].min_voltage,
+					    hsphy->vreg_list[i].max_voltage);
+		if (ret) {
+			dev_err(hsphy->dev,
+				"unable to set voltage of regulator %s %d\n",
+						hsphy->vregs[i].supply, ret);
+			goto put_vdd_lpm;
+		}
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
+	if (ret)
+		goto unconfig_vdd;
+
+	return ret;
+
+disable_vdd:
+	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
+
+unconfig_vdd:
+	for (i = 0; i < SNPS_HS_NUM_VREGS; i++) {
+		ret = regulator_set_voltage(hsphy->vregs[i].consumer, 0,
+					    hsphy->vreg_list[i].max_voltage);
+		if (ret) {
+			dev_err(hsphy->dev,
+			"unable to set voltage of regulator %s %d\n",
+					hsphy->vregs[i].supply, ret);
+		}
+	}
+
+put_vdd_lpm:
+	for (i = 0; i < SNPS_HS_NUM_VREGS; i++) {
+		ret = regulator_set_load(hsphy->vregs[i].consumer, 0);
+
+		if (ret < 0) {
+			dev_err(hsphy->dev, "unable to set LPM of %s %d\n",
+						hsphy->vregs[i].supply, ret);
+		}
+	}
+
+err_vdd:
+	return ret;
+
+}
+
+static int vdda_phy_bulk_enable(struct qcom_snps_hsphy *hsphy)
+{
+	return __vdda_phy_bulk_enable_disable(hsphy, true);
+}
+
+static int vdda_phy_bulk_disable(struct qcom_snps_hsphy *hsphy)
+{
+	return __vdda_phy_bulk_enable_disable(hsphy, false);
+}
+
 static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
 {
 	struct device *dev = hsphy->dev;
@@ -390,7 +496,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
 
 	dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__);
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
+	ret = vdda_phy_bulk_enable(hsphy);
 	if (ret)
 		return ret;
 
@@ -471,7 +577,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
 disable_clks:
 	clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
 poweroff_phy:
-	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
+	ret = vdda_phy_bulk_disable(hsphy);
 
 	return ret;
 }
@@ -482,7 +588,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
 
 	reset_control_assert(hsphy->phy_reset);
 	clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
-	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
+	vdda_phy_bulk_disable(hsphy);
 	hsphy->phy_initialized = false;
 
 	return 0;
@@ -592,8 +698,9 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
 
 	num = ARRAY_SIZE(hsphy->vregs);
 	for (i = 0; i < num; i++)
-		hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i];
+		hsphy->vregs[i].supply = hsphy_vreg_l[i].name;
 
+	hsphy->vreg_list  = hsphy_vreg_l;
 	ret = devm_regulator_bulk_get(dev, num, hsphy->vregs);
 	if (ret)
 		return dev_err_probe(dev, ret,
-- 
2.17.1


             reply	other threads:[~2024-05-02 12:33 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-02 12:33 Udipto Goswami [this message]
2024-05-02 13:12 ` [PATCH] phy: qcom-snps-femto-v2: Add load and voltage setting for LDO's used Dmitry Baryshkov
2024-05-03  5:23   ` Udipto Goswami
2024-05-03 18:29     ` Dmitry Baryshkov
2024-05-07 11:43   ` Konrad Dybcio
2024-05-07 11:55     ` Dmitry Baryshkov
2024-05-07 13:41       ` Konrad Dybcio
2024-05-03  5:37 ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240502123312.31083-1-quic_ugoswami@quicinc.com \
    --to=quic_ugoswami@quicinc.com \
    --cc=andersson@kernel.org \
    --cc=kishon@kernel.org \
    --cc=konrad.dybcio@linaro.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).