lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20241204105249.3544114-3-quic_ziyuzhan@quicinc.com>
Date: Wed,  4 Dec 2024 18:52:48 +0800
From: Ziyue Zhang <quic_ziyuzhan@...cinc.com>
To: vkoul@...nel.org, kishon@...nel.org, dmitry.baryshkov@...aro.org,
        abel.vesa@...aro.org, neil.armstrong@...aro.org,
        manivannan.sadhasivam@...aro.org, andersson@...nel.org,
        konradybcio@...nel.org, robh@...nel.org, krzk+dt@...nel.org,
        conor+dt@...nel.org
Cc: linux-arm-msm@...r.kernel.org, linux-phy@...ts.infradead.org,
        linux-kernel@...r.kernel.org, devicetree@...r.kernel.org,
        Ziyue Zhang <quic_ziyuzhan@...cinc.com>
Subject: [PATCH 2/3] phy: qcom: qmp-pcie: add current load vote/devote for PCIe PHY

On some platform (eg.qcs615), the current that phy consumes will exceed
the maximum current the regulator can provide in LPM mode, leading to
over current protection and system boot up stuck. Fix this issue by
setting regulator load to an expected value getting from phy device tree
node during init so that the regulator can scale up to HPM to allow a
larger current load.
This change will also set load to zero during deinit to let regulator
scale down to LPM mode to reduce itself's power consumptionif PCIe
suspend.

Signed-off-by: Ziyue Zhang <quic_ziyuzhan@...cinc.com>
---
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 35 ++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index c8e39c147ba4..782d51ab5cf1 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -39,6 +39,7 @@
 #include "phy-qcom-qmp-pcie-qhp.h"
 
 #define PHY_INIT_COMPLETE_TIMEOUT		10000
+#define MAX_PROP_SIZE		   32
 
 /* set of registers with offsets different per-PHY */
 enum qphy_reg_layout {
@@ -2905,6 +2906,7 @@ struct qmp_pcie {
 	struct reset_control_bulk_data *resets;
 	struct reset_control *nocsr_reset;
 	struct regulator_bulk_data *vregs;
+	u32 *max_current_load;
 
 	struct phy *phy;
 	int mode;
@@ -4087,6 +4089,17 @@ static int qmp_pcie_init(struct phy *phy)
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
 	int ret;
 
+	for (int i = 0; i < cfg->num_vregs; i++) {
+		if (qmp->max_current_load[i]) {
+			ret = regulator_set_load(qmp->vregs[i].consumer, qmp->max_current_load[i]);
+			if (ret) {
+				dev_err(&phy->dev,
+					"failed to set load at %s\n", qmp->vregs[i].supply);
+				return ret;
+			}
+		}
+	}
+
 	ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
 	if (ret) {
 		dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
@@ -4129,6 +4142,7 @@ static int qmp_pcie_init(struct phy *phy)
 
 static int qmp_pcie_exit(struct phy *phy)
 {
+	int ret;
 	struct qmp_pcie *qmp = phy_get_drvdata(phy);
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
 
@@ -4137,7 +4151,16 @@ static int qmp_pcie_exit(struct phy *phy)
 	clk_bulk_disable_unprepare(ARRAY_SIZE(qmp_pciephy_clk_l), qmp->clks);
 
 	regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-
+	for (int i = 0; i < cfg->num_vregs; i++) {
+		if (qmp->max_current_load[i]) {
+			ret = regulator_set_load(qmp->vregs[i].consumer, 0);
+			if (ret) {
+				dev_err(&phy->dev,
+					"failed to set load at %s\n", qmp->vregs[i].supply);
+				return ret;
+			}
+		}
+	}
 	return 0;
 }
 
@@ -4274,14 +4297,22 @@ static int qmp_pcie_vreg_init(struct qmp_pcie *qmp)
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
 	struct device *dev = qmp->dev;
 	int num = cfg->num_vregs;
+	char prop_name[MAX_PROP_SIZE];
 	int i;
 
 	qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
 	if (!qmp->vregs)
 		return -ENOMEM;
 
-	for (i = 0; i < num; i++)
+	qmp->max_current_load = devm_kcalloc(dev, num, sizeof(*qmp->max_current_load), GFP_KERNEL);
+	if (!qmp->max_current_load)
+		return -ENOMEM;
+
+	for (i = 0; i < num; i++) {
 		qmp->vregs[i].supply = cfg->vreg_list[i];
+		snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", qmp->vregs[i].supply);
+		of_property_read_u32(qmp->dev->of_node, prop_name, &qmp->max_current_load[i]);
+	}
 
 	return devm_regulator_bulk_get(dev, num, qmp->vregs);
 }
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ