[PATCH] ufs: qcom: Add UFS host regulator support

Casey Connolly casey.connolly at linaro.org
Fri May 22 16:04:08 CEST 2026



On 21/05/2026 20:39, Federico Amedeo Izzo via B4 Relay wrote:
> From: Federico Amedeo Izzo <federico at izzo.pro>
> 
> 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 <federico at izzo.pro>
> ---
> Add support to qcom-ufs driver for vcc-supply and vccq-supply
> regulators to enable UFS support on SC7280 devices with UFS3.1.
> SC7280 devices with UFS2.2 were already working.
> 
> The root cause was ABL leaving vcc-supply regulator disabled on UFS3.1
> devices, and enabled on UFS2.2 devices that worked fine without
> regulator support.
> 
> The tricky part was enabling the regulator in HPM mode (3), which required
> setting LPM mode (1) first, otherwise reg would stay in LPM mode.
> I discovered this by changing the regulator settings from U-Boot
> console. Enabling the regulator in LPM mode resets the phone.

Huhh well that's weird, could this be a bug in the regulator driver? If
you run "regulator status -a" the regulator states are actually read out
from rpmh so they should be accurate but maybe the numerical mapping
isn't correct so logging those as numbers might help.

I'm curious what the default voltage is for that rail (vreg_l7b_2p96
right?) since it seems to have a large range on that device from 2.4v to
3.5v. If it gets enabled without setting the voltage then it could be
set too low and brownout in LPM.

It might be worth double checking if the voltage range is correct for
that device by comparing to the Android devicetree.

I'd suggest raising the minimum voltage for that rail to the 2.96v (or
at least 2.8v or something) that it's labelled as and see if that helps.
The fact that setting LPM first and then changing it to HPM resolves the
issue definitely suggests something weird going on with the rpmh and/or
that the voltage is too low.

Sorry I can't take this as-is, I'm totally fine with having regulator
support here but a hack like this definitely requires more
research/discussion.

Thanks,

fwiw I'd also very much like to get my hands on one of these devices...
We can talk about that off-list :P

> ---
>  drivers/ufs/ufs-qcom.c | 22 +++++++++++++++++++++-
>  drivers/ufs/ufs-qcom.h |  3 +++
>  2 files changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/ufs/ufs-qcom.c b/drivers/ufs/ufs-qcom.c
> index dc40ee62daf..6c4599a6453 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,21 @@ 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 err;
> +	int ret, err;
>  
>  	priv->hba = hba;
>  
> +	/* Set regulator to LPM mode first otherwise HPM does not get applied */
> +	ret = regulator_set_mode(priv->vcc, 1);
> +	ret = regulator_set_mode(priv->vcc, 3);
> +	ret = regulator_set_enable(priv->vcc, true);
> +	if (ret && ret != -ENOSYS)
> +		dev_warn(hba->dev, "failed to enable regulator vcc-supply:%d\n", ret);
> +
> +	ret = regulator_set_enable(priv->vccq, true);
> +	if (ret && ret != -ENOSYS)
> +		dev_warn(hba->dev, "failed to enable regulator vccq-supply:%d\n", ret);
> +
>  	/* setup clocks */
>  	ufs_qcom_setup_clocks(hba, true, PRE_CHANGE);
>  
> @@ -651,6 +663,14 @@ 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);
> +
>  	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..4e502e7b3ca 100644
> --- a/drivers/ufs/ufs-qcom.h
> +++ b/drivers/ufs/ufs-qcom.h
> @@ -134,6 +134,9 @@ struct ufs_qcom_priv {
>  	struct clk_bulk clks;
>  	bool is_clks_enabled;
>  
> +	struct udevice *vcc;
> +	struct udevice *vccq;
> +
>  	struct ufs_hw_version hw_ver;
>  
>  	/* Reset control of HCI */
> 
> ---
> base-commit: 744cf5d4e398c5f657e5c3eeb44d00fa5175dc85
> change-id: 20260521-dpu-add-dspp-gc-driver-0c9ec8b0f127
> 
> Best regards,
> --  
> Federico Amedeo Izzo <federico at izzo.pro>
> 
> 

-- 
// Casey (she/her)



More information about the U-Boot mailing list