scsi: ufs-qcom: enable host controller hardware clock gating
The UTP controller has a number of internal clock gating cells (CGCs). Internal hardware sub-modules within the UTP controller control the CGCs. Hardware CGCs disable the clock to inactivate UTP sub-modules not involved in a specific operation, UTP controller CGCs are by default disabled and this change enables them (after every UFS link startup) to save some power leakage. Change-Id: I47bba62436c5913eb6755e59c36a11fea2e9468f Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
8c17ea4d5b
commit
9d89b6c4c8
2 changed files with 34 additions and 0 deletions
|
@ -264,6 +264,24 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The UTP controller has a number of internal clock gating cells (CGCs).
|
||||||
|
* Internal hardware sub-modules within the UTP controller control the CGCs.
|
||||||
|
* Hardware CGCs disable the clock to inactivate UTP sub-modules not involved
|
||||||
|
* in a specific operation, UTP controller CGCs are by default disabled and
|
||||||
|
* this function enables them (after every UFS link startup) to save some power
|
||||||
|
* leakage.
|
||||||
|
*/
|
||||||
|
static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba)
|
||||||
|
{
|
||||||
|
ufshcd_writel(hba,
|
||||||
|
ufshcd_readl(hba, REG_UFS_CFG2) | REG_UFS_CFG2_CGC_EN_ALL,
|
||||||
|
REG_UFS_CFG2);
|
||||||
|
|
||||||
|
/* Ensure that HW clock gating is enabled before next operations */
|
||||||
|
mb();
|
||||||
|
}
|
||||||
|
|
||||||
static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
|
static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
|
||||||
{
|
{
|
||||||
struct ufs_qcom_host *host = hba->priv;
|
struct ufs_qcom_host *host = hba->priv;
|
||||||
|
@ -282,6 +300,7 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
|
||||||
case POST_CHANGE:
|
case POST_CHANGE:
|
||||||
/* check if UFS PHY moved from DISABLED to HIBERN8 */
|
/* check if UFS PHY moved from DISABLED to HIBERN8 */
|
||||||
err = ufs_qcom_check_hibern8(hba);
|
err = ufs_qcom_check_hibern8(hba);
|
||||||
|
ufs_qcom_enable_hw_clk_gating(hba);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(hba->dev, "%s: invalid status %d\n", __func__, status);
|
dev_err(hba->dev, "%s: invalid status %d\n", __func__, status);
|
||||||
|
|
|
@ -60,6 +60,21 @@ enum {
|
||||||
REG_UFS_HW_VERSION = 0xE4,
|
REG_UFS_HW_VERSION = 0xE4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* bit definitions for REG_UFS_CFG2 register */
|
||||||
|
#define UAWM_HW_CGC_EN (1 << 0)
|
||||||
|
#define UARM_HW_CGC_EN (1 << 1)
|
||||||
|
#define TXUC_HW_CGC_EN (1 << 2)
|
||||||
|
#define RXUC_HW_CGC_EN (1 << 3)
|
||||||
|
#define DFC_HW_CGC_EN (1 << 4)
|
||||||
|
#define TRLUT_HW_CGC_EN (1 << 5)
|
||||||
|
#define TMRLUT_HW_CGC_EN (1 << 6)
|
||||||
|
#define OCSC_HW_CGC_EN (1 << 7)
|
||||||
|
|
||||||
|
#define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\
|
||||||
|
TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\
|
||||||
|
DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\
|
||||||
|
TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN)
|
||||||
|
|
||||||
/* bit offset */
|
/* bit offset */
|
||||||
enum {
|
enum {
|
||||||
OFFSET_UFS_PHY_SOFT_RESET = 1,
|
OFFSET_UFS_PHY_SOFT_RESET = 1,
|
||||||
|
|
Loading…
Add table
Reference in a new issue