Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save EmbeddedAndroid/3c389ec10b7b21ceb15cad38469d7de9 to your computer and use it in GitHub Desktop.

Select an option

Save EmbeddedAndroid/3c389ec10b7b21ceb15cad38469d7de9 to your computer and use it in GitHub Desktop.
scsi: ufs: qcom: defer probe before the device supplies are on (Kaanapali LDO4 OCP, against next-20261022)
From 86d688bbf6797301ff9a4f5af324be904bba0031 Mon Sep 17 00:00:00 2001
From: Tyler Baker <tyler.baker@oss.qualcomm.com>
Date: Mon, 2 Nov 2026 08:11:58 -0500
Subject: [PATCH] scsi: ufs: qcom: defer probe before the device supplies are
on
ufshcd_pltfrm_init() enables vcc and vccq in ufshcd_hba_init() before
ufs_qcom_init() looks up the PHY and the interconnect paths. When one of
them defers, the error path disables the supplies and drops their load
votes under a UFS device the bootloader left running.
On the Kaanapali MTP fw_devlink cannot order the controller after its
PHY (a dependency cycle with GCC and the interconnect), so this happens
on some boots. Another RPMh voter keeps the vccq LDO enabled, the zero
load vote puts it into low power mode, and the PMIC resets the SoC on
over-current:
PM: Reset by PMIC_D OCP
PM: OCP Occured: Bus ID: 0; PMIC: 3; LDO: 4; Status: 0x28
Look up the PHY and the interconnect paths in ufs_qcom_probe(), before
ufshcd_pltfrm_init(), and defer there. Other lookup errors are still
handled by ufs_qcom_init().
Signed-off-by: Tyler Baker <tyler.baker@oss.qualcomm.com>
---
drivers/ufs/host/ufs-qcom.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index fee9b54ba5e1a..33bd2b5526f7d 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -2996,6 +2996,37 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_sa8255p_vops = {
.config_esi = ufs_qcom_config_esi,
};
+/*
+ * Defer before ufshcd_pltfrm_init() turns the device supplies on: deferring
+ * from ufs_qcom_init() drops their votes under a running device.
+ */
+static int ufs_qcom_check_suppliers(struct device *dev)
+{
+ static const char * const paths[] = { "ufs-ddr", "cpu-ufs" };
+ struct icc_path *path;
+ struct phy *phy;
+ int i;
+
+ if (!has_acpi_companion(dev)) {
+ phy = phy_get(dev, "ufsphy");
+ if (PTR_ERR(phy) == -EPROBE_DEFER)
+ return dev_err_probe(dev, -EPROBE_DEFER, "PHY not ready\n");
+ if (!IS_ERR(phy))
+ phy_put(dev, phy);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(paths); i++) {
+ path = of_icc_get(dev, paths[i]);
+ if (PTR_ERR(path) == -EPROBE_DEFER)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "interconnect %s not ready\n", paths[i]);
+ if (!IS_ERR(path))
+ icc_put(path);
+ }
+
+ return 0;
+}
+
/**
* ufs_qcom_probe - probe routine of the driver
* @pdev: pointer to Platform device handle
@@ -3014,6 +3045,10 @@ static int ufs_qcom_probe(struct platform_device *pdev)
else
vops = &ufs_hba_qcom_vops;
+ err = ufs_qcom_check_suppliers(dev);
+ if (err)
+ return err;
+
/* Perform generic probe */
err = ufshcd_pltfrm_init(pdev, vops);
if (err)
--
2.47.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment