From b0e3c5571afc5464acb80d301c9019ec48650565 Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Thu, 19 Sep 2019 11:16:46 +0530 Subject: [PATCH 1/2] scsi: ufs: Update UFS ICE clock enable/disable sequence As per latest hardware programming guide, during Hibern8 enter with power collapse: SW should disable HW clock control for UFS ICE clock (GCC_UFS_ICE_CORE_CBCR.HW_CTL=0), before ufs_ice_core_clk is turned off (i.e GCC_UFS_*_ICE_CORE_CBCR[CLK_ENABLE]=0) and vice versa during hibern8 exit. This change updates UFS ICE clock disable sequence as per recommended steps. Change-Id: Ibe2036bb20a4e0ec368fc203da9553c10c02200d Signed-off-by: Sayali Lokhande Signed-off-by: Ram Prakash Gupta --- drivers/scsi/ufs/ufs-qcom.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 7bff6414e6a6..5f9373b8b4a2 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1995,6 +1995,8 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, { struct ufs_qcom_host *host = ufshcd_get_variant(hba); int err = 0; + struct list_head *head = &hba->clk_list_head; + struct ufs_clk_info *clki; /* * In case ufs_qcom_init() is not yet done, simply ignore. @@ -2021,6 +2023,33 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, return err; } } + + if (list_empty(head)) { + dev_err(hba->dev, "%s: clk list is empty\n", __func__); + return err; + } + /* + * As per the latest hardware programming guide, + * during Hibern8 enter with power collapse : + * SW should disable HW clock control for UFS ICE + * clock (GCC_UFS_ICE_CORE_CBCR.HW_CTL=0) + * before ufs_ice_core_clk is turned off. + * In device tree, we need to add UFS ICE clocks + * in below fixed order: + * clock-names = + * "core_clk_ice"; + * "core_clk_ice_hw_ctl"; + * This way no extra check is required in UFS + * clock enable path as clk enable order will be + * already taken care in ufshcd_setup_clocks(). + */ + list_for_each_entry(clki, head, list) { + if (!IS_ERR_OR_NULL(clki->clk) && + !strcmp(clki->name, "core_clk_ice_hw_ctl")) { + clk_disable_unprepare(clki->clk); + clki->enabled = on; + } + } } break; case POST_CHANGE: From 64d3d9b49e6e623ea5d0be3784b45f135f5afcc9 Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Thu, 12 Dec 2019 12:07:39 +0530 Subject: [PATCH 2/2] scsi: ufs: remove voting for hw ice clk We would only enable/disable hw ice clk, we won't set the frequency of this clk from ufs driver. Change-Id: I25a482387facbf3fbbeb201d9513c4c042f10a0e Signed-off-by: Nitin Rawat --- drivers/scsi/ufs/ufshcd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d365dc3fa9ce..2e837f20fb88 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1014,7 +1014,8 @@ static int ufshcd_set_clk_freq(struct ufs_hba *hba, bool scale_up) list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { if (scale_up && clki->max_freq) { - if (clki->curr_freq == clki->max_freq) + if ((clki->curr_freq == clki->max_freq) || + (!strcmp(clki->name, "core_clk_ice_hw_ctl"))) continue; ret = clk_set_rate(clki->clk, clki->max_freq); @@ -1032,7 +1033,8 @@ static int ufshcd_set_clk_freq(struct ufs_hba *hba, bool scale_up) clki->curr_freq = clki->max_freq; } else if (!scale_up && clki->min_freq) { - if (clki->curr_freq == clki->min_freq) + if ((clki->curr_freq == clki->min_freq) || + (!strcmp(clki->name, "core_clk_ice_hw_ctl"))) continue; ret = clk_set_rate(clki->clk, clki->min_freq); @@ -8316,7 +8318,8 @@ static int ufshcd_init_clocks(struct ufs_hba *hba) goto out; list_for_each_entry(clki, head, list) { - if (!clki->name) + if ((!clki->name) || + (!strcmp(clki->name, "core_clk_ice_hw_ctl"))) continue; clki->clk = devm_clk_get(dev, clki->name);