Commit dd7143e2 authored by Can Guo's avatar Can Guo Committed by Martin K. Petersen

scsi: ufs: Put HBA into LPM during clk gating

During clock gating, after clocks are disabled, put HBA into LPM to save
more power.

Link: https://lore.kernel.org/r/52198e70bff750632740d78678a815256d697e43.1603825776.git.asutoshd@codeaurora.orgReviewed-by: default avatarAvri Altman <avri.altman@wdc.com>
Acked-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
Signed-off-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 3fb52041
...@@ -245,6 +245,8 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba); ...@@ -245,6 +245,8 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba);
static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable); static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable);
static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set); static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set);
static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable); static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable);
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba);
static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
{ {
...@@ -1548,6 +1550,7 @@ static void ufshcd_ungate_work(struct work_struct *work) ...@@ -1548,6 +1550,7 @@ static void ufshcd_ungate_work(struct work_struct *work)
} }
spin_unlock_irqrestore(hba->host->host_lock, flags); spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_hba_vreg_set_hpm(hba);
ufshcd_setup_clocks(hba, true); ufshcd_setup_clocks(hba, true);
ufshcd_enable_irq(hba); ufshcd_enable_irq(hba);
...@@ -1713,6 +1716,8 @@ static void ufshcd_gate_work(struct work_struct *work) ...@@ -1713,6 +1716,8 @@ static void ufshcd_gate_work(struct work_struct *work)
/* If link is active, device ref_clk can't be switched off */ /* If link is active, device ref_clk can't be switched off */
__ufshcd_setup_clocks(hba, false, true); __ufshcd_setup_clocks(hba, false, true);
/* Put the host controller in low power mode if possible */
ufshcd_hba_vreg_set_lpm(hba);
/* /*
* In case you are here to cancel this work the gating state * In case you are here to cancel this work the gating state
* would be marked as REQ_CLKS_ON. In this case keep the state * would be marked as REQ_CLKS_ON. In this case keep the state
...@@ -8405,13 +8410,13 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) ...@@ -8405,13 +8410,13 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba) static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba)
{ {
if (ufshcd_is_link_off(hba)) if (ufshcd_is_link_off(hba) || ufshcd_can_aggressive_pc(hba))
ufshcd_setup_hba_vreg(hba, false); ufshcd_setup_hba_vreg(hba, false);
} }
static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba) static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba)
{ {
if (ufshcd_is_link_off(hba)) if (ufshcd_is_link_off(hba) || ufshcd_can_aggressive_pc(hba))
ufshcd_setup_hba_vreg(hba, true); ufshcd_setup_hba_vreg(hba, true);
} }
......
...@@ -592,6 +592,13 @@ enum ufshcd_caps { ...@@ -592,6 +592,13 @@ enum ufshcd_caps {
* inline crypto engine, if it is present * inline crypto engine, if it is present
*/ */
UFSHCD_CAP_CRYPTO = 1 << 8, UFSHCD_CAP_CRYPTO = 1 << 8,
/*
* This capability allows the controller regulators to be put into
* lpm mode aggressively during clock gating.
* This would increase power savings.
*/
UFSHCD_CAP_AGGR_POWER_COLLAPSE = 1 << 9,
}; };
struct ufs_hba_variant_params { struct ufs_hba_variant_params {
...@@ -829,6 +836,12 @@ return true; ...@@ -829,6 +836,12 @@ return true;
#endif #endif
} }
static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba)
{
return !!(ufshcd_is_link_hibern8(hba) &&
(hba->caps & UFSHCD_CAP_AGGR_POWER_COLLAPSE));
}
static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba)
{ {
return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) && return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment