diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-i.h b/drivers/phy/qualcomm/phy-qcom-ufs-i.h index 282afa4b5561..5e0c9fc7282c 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs-i.h +++ b/drivers/phy/qualcomm/phy-qcom-ufs-i.h @@ -66,6 +66,7 @@ struct ufs_qcom_phy { struct clk *ref_clk_src; struct clk *ref_clk_parent; struct clk *ref_clk; + struct clk *ref_aux_clk; bool is_ref_clk_enabled; bool is_dev_ref_clk_enabled; struct ufs_qcom_phy_vreg vdda_pll; diff --git a/drivers/phy/qualcomm/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c index 29806f20f6f1..5baa68ba2401 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs.c @@ -211,7 +211,15 @@ skip_txrx_clk: err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk", &phy_common->ref_clk); + if (err) + goto out; + /* + * "ref_aux_clk" is optional and only supported by certain + * phy versions, don't abort init if it's not found. + */ + __ufs_qcom_phy_clk_get(phy_common->dev, "ref_aux_clk", + &phy_common->ref_aux_clk, false); out: return err; } @@ -389,9 +397,26 @@ static int ufs_qcom_phy_enable_ref_clk(struct ufs_qcom_phy *phy) goto out_disable_parent; } + /* + * "ref_aux_clk" is optional clock and only supported by certain + * phy versions, hence make sure that clk reference is available + * before trying to enable the clock. + */ + if (phy->ref_aux_clk) { + ret = clk_prepare_enable(phy->ref_aux_clk); + if (ret) { + dev_err(phy->dev, "%s: ref_aux_clk enable failed %d\n", + __func__, ret); + goto out_disable_ref; + } + } + phy->is_ref_clk_enabled = true; goto out; +out_disable_ref: + if (phy->ref_clk) + clk_disable_unprepare(phy->ref_clk); out_disable_parent: if (phy->ref_clk_parent) clk_disable_unprepare(phy->ref_clk_parent); @@ -426,6 +451,13 @@ out: static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy) { if (phy->is_ref_clk_enabled) { + /* + * "ref_aux_clk" is optional clock and only supported by + * certain phy versions, hence make sure that clk reference + * is available before trying to disable the clock. + */ + if (phy->ref_aux_clk) + clk_disable_unprepare(phy->ref_aux_clk); clk_disable_unprepare(phy->ref_clk); /* * "ref_clk_parent" is optional clock hence make sure that clk