[PATCH v2 6/7] drivers: ufs: qcom: Initialize and enable clocks before hardware access

Sumit Garg sumit.garg at kernel.org
Fri May 1 09:43:23 CEST 2026


On Mon, Apr 27, 2026 at 02:56:10PM +0530, Balaji Selvanathan wrote:
> Move UFS clock initialization and enabling before hardware setup
> to ensure clocks are running when accessing UFS registers.
> 
> Previously, U-Boot depended on earlier bootloader stages to
> initialize UFS clocks. When these bootloaders failed to do so,
> UFS registers became inaccessible, causing initialization to fail.
> This change makes U-Boot initialize and enable UFS clocks early
> in the init sequence, removing the dependency on previous
> bootloaders.
> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan at oss.qualcomm.com>
> ---
> Changes in v2:
> - Remove ufs_qcom_init_clks function and move the clock enabling and
>       rate set codes to ufs_qcom_init
> - Add clk_release_bulk if ufs_qcom_enable_clks fails
> ---
>  drivers/ufs/ufs-qcom.c | 53 ++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 36 insertions(+), 17 deletions(-)

Reviewed-by: Sumit Garg <sumit.garg at oss.qualcomm.com>

-Sumit

> 
> diff --git a/drivers/ufs/ufs-qcom.c b/drivers/ufs/ufs-qcom.c
> index dc40ee62daf..ae33f62fbee 100644
> --- a/drivers/ufs/ufs-qcom.c
> +++ b/drivers/ufs/ufs-qcom.c
> @@ -30,6 +30,7 @@
>  #define UFS_CPU_MAX_BANDWIDTH	819200
>  
>  static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_hba *hba, bool enable);
> +static u32 ufs_qcom_get_core_clk_unipro_max_freq(struct ufs_hba *hba);
>  
>  static int ufs_qcom_enable_clks(struct ufs_qcom_priv *priv)
>  {
> @@ -47,17 +48,6 @@ static int ufs_qcom_enable_clks(struct ufs_qcom_priv *priv)
>  	return 0;
>  }
>  
> -static int ufs_qcom_init_clks(struct ufs_qcom_priv *priv)
> -{
> -	int err;
> -	struct udevice *dev = priv->hba->dev;
> -
> -	err = clk_get_bulk(dev, &priv->clks);
> -	if (err)
> -		return err;
> -
> -	return 0;
> -}
>  
>  static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>  {
> @@ -557,10 +547,45 @@ 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);
> +	struct udevice *dev = hba->dev;
> +	struct clk clk;
> +	u32 max_freq;
> +	long rate;
>  	int err;
>  
>  	priv->hba = hba;
>  
> +	/* Get maximum frequency for core_clk_unipro from device tree */
> +	max_freq = ufs_qcom_get_core_clk_unipro_max_freq(hba);
> +
> +	/* Get and configure core_clk_unipro */
> +	err = clk_get_by_name(dev, "core_clk_unipro", &clk);
> +	if (err) {
> +		dev_err(dev, "Failed to get core_clk_unipro: %d\n", err);
> +		return err;
> +	}
> +
> +	rate = clk_set_rate(&clk, max_freq);
> +	if (rate < 0) {
> +		dev_err(dev, "Failed to set core_clk_unipro rate to %u Hz: %ld\n",
> +			max_freq, rate);
> +	}
> +
> +	/* Get all clocks */
> +	err = clk_get_bulk(dev, &priv->clks);
> +	if (err) {
> +		dev_err(dev, "clk_get_bulk failed: %d\n", err);
> +		return err;
> +	}
> +
> +	/* Enable clocks */
> +	err = ufs_qcom_enable_clks(priv);
> +	if (err) {
> +		dev_err(dev, "failed to enable clocks: %d\n", err);
> +		clk_release_bulk(&priv->clks);
> +		return err;
> +	}
> +
>  	/* setup clocks */
>  	ufs_qcom_setup_clocks(hba, true, PRE_CHANGE);
>  
> @@ -579,12 +604,6 @@ static int ufs_qcom_init(struct ufs_hba *hba)
>  		 priv->hw_ver.minor,
>  		 priv->hw_ver.step);
>  
> -	err = ufs_qcom_init_clks(priv);
> -	if (err) {
> -		dev_err(hba->dev, "failed to initialize clocks, err:%d\n", err);
> -		return err;
> -	}
> -
>  	ufs_qcom_advertise_quirks(hba);
>  	ufs_qcom_setup_clocks(hba, true, POST_CHANGE);
>  
> 
> -- 
> 2.34.1
> 


More information about the U-Boot mailing list