From: Federico Amedeo Izzo <[email protected]>

The qcom UFS driver works without touching the regulators on most platforms
as ABL leaves them already configured and enabled.
On some SC7280 phones with UFS 3.1 like nothing-spacewar, vcc regulator is
not enabled by ABL, so we need to configure and enable it to use the UFS
storage.

Tested on nothing-spacewar and motorola-dubai using Tauchgang U-Boot.

Signed-off-by: Federico Amedeo Izzo <[email protected]>
---
 drivers/ufs/ufs-qcom.c | 33 +++++++++++++++++++++++++++++++++
 drivers/ufs/ufs-qcom.h |  4 ++++
 2 files changed, 37 insertions(+)

diff --git a/drivers/ufs/ufs-qcom.c b/drivers/ufs/ufs-qcom.c
index dc40ee62daf..376be2eeaaf 100644
--- a/drivers/ufs/ufs-qcom.c
+++ b/drivers/ufs/ufs-qcom.c
@@ -16,6 +16,7 @@
 #include <generic-phy.h>
 #include <asm/gpio.h>
 #include <interconnect.h>
+#include <power/regulator.h>
 
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -557,10 +558,31 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_hba 
*hba, bool enable)
 static int ufs_qcom_init(struct ufs_hba *hba)
 {
        struct ufs_qcom_priv *priv = dev_get_priv(hba->dev);
+       int mode;
        int err;
 
        priv->hba = hba;
 
+       /* Apply regulator initial-mode from dts */
+       err = dev_read_u32(priv->vcc, "regulator-initial-mode", &mode);
+       if (!err) {
+               err = regulator_set_mode(priv->vcc, mode);
+               if (err && err != -ENOSYS)
+                       dev_warn(hba->dev, "failed to set vcc-supply 
mode:%d\n", err);
+       }
+
+       err = regulator_set_enable(priv->vcc, true);
+       if (err && err != -ENOSYS)
+               dev_warn(hba->dev, "failed to enable regulator 
vcc-supply:%d\n", err);
+
+       err = regulator_set_enable(priv->vccq, true);
+       if (err && err != -ENOSYS)
+               dev_warn(hba->dev, "failed to enable regulator 
vccq-supply:%d\n", err);
+
+       err = regulator_set_enable(priv->vccq2, true);
+       if (err && err != -ENOSYS)
+               dev_warn(hba->dev, "failed to enable regulator 
vccq2-supply:%d\n", err);
+
        /* setup clocks */
        ufs_qcom_setup_clocks(hba, true, PRE_CHANGE);
 
@@ -651,6 +673,17 @@ static int ufs_qcom_probe(struct udevice *dev)
                dev_err(dev, "Warning: cannot get reset GPIO\n");
        }
 
+       ret = device_get_supply_regulator(dev, "vcc-supply", &priv->vcc);
+       if (ret)
+               dev_warn(dev, "failed to get regulator vcc-supply:%d\n", ret);
+
+       ret = device_get_supply_regulator(dev, "vccq-supply", &priv->vccq);
+       if (ret)
+               dev_warn(dev, "failed to get regulator vccq-supply:%d\n", ret);
+
+       /* vccq2 is optional on UFS2 and missing on UFS3 and later */
+       device_get_supply_regulator(dev, "vccq2-supply", &priv->vccq2);
+
        ret = ufshcd_probe(dev, &ufs_qcom_hba_ops);
        if (ret) {
                dev_err(dev, "ufshcd_probe() failed, ret:%d\n", ret);
diff --git a/drivers/ufs/ufs-qcom.h b/drivers/ufs/ufs-qcom.h
index de957ae60f3..115565db7e9 100644
--- a/drivers/ufs/ufs-qcom.h
+++ b/drivers/ufs/ufs-qcom.h
@@ -134,6 +134,10 @@ struct ufs_qcom_priv {
        struct clk_bulk clks;
        bool is_clks_enabled;
 
+       struct udevice *vcc;
+       struct udevice *vccq;
+       struct udevice *vccq2;
+
        struct ufs_hw_version hw_ver;
 
        /* Reset control of HCI */

-- 
2.54.0


Reply via email to