scsi: ufs: ufs-mediatek: gate ref-clk during Auto-Hibern8

In current UFS driver design, hba->uic_link_state will not be changed after
link enters Hibern8 state by Auto-Hibern8 mechanism.  In this case,
reference clock gating will be skipped unless special handling is
implemented in vendor's callbacks.

Support reference clock gating during Auto-Hibern8 period in MediaTek
Chipsets: If link state is already in Hibern8 while Auto-Hibern8 feature is
enabled, gate reference clock in setup_clocks callback.

Link: https://lore.kernel.org/r/20200129105251.12466-5-stanley.chu@mediatek.com
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: Bean Huo <beanhuo@micron.com>
Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Stanley Chu 2020-01-29 18:52:51 +08:00 committed by Martin K. Petersen
parent 5a244e0ea6
commit 722adbbd70
2 changed files with 39 additions and 11 deletions

View File

@ -143,6 +143,17 @@ out:
return 0;
}
static u32 ufs_mtk_link_get_state(struct ufs_hba *hba)
{
u32 val;
ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL);
val = ufshcd_readl(hba, REG_UFS_PROBE);
val = val >> 28;
return val;
}
/**
* ufs_mtk_setup_clocks - enables/disable clocks
* @hba: host controller instance
@ -155,7 +166,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
enum ufs_notify_change_status status)
{
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
int ret = -EINVAL;
int ret = 0;
/*
* In case ufs_mtk_init() is not yet done, simply ignore.
@ -165,19 +176,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
if (!host)
return 0;
switch (status) {
case PRE_CHANGE:
if (!on && !ufshcd_is_link_active(hba)) {
if (!on && status == PRE_CHANGE) {
if (!ufshcd_is_link_active(hba)) {
ufs_mtk_setup_ref_clk(hba, on);
ret = phy_power_off(host->mphy);
}
break;
case POST_CHANGE:
if (on) {
ret = phy_power_on(host->mphy);
} else {
/*
* Gate ref-clk if link state is in Hibern8
* triggered by Auto-Hibern8.
*/
if (!ufshcd_can_hibern8_during_gating(hba) &&
ufshcd_is_auto_hibern8_enabled(hba) &&
ufs_mtk_link_get_state(hba) ==
VS_LINK_HIBERN8)
ufs_mtk_setup_ref_clk(hba, on);
}
break;
} else if (on && status == POST_CHANGE) {
ret = phy_power_on(host->mphy);
ufs_mtk_setup_ref_clk(hba, on);
}
return ret;

View File

@ -53,6 +53,18 @@
#define VS_SAVEPOWERCONTROL 0xD0A6
#define VS_UNIPROPOWERDOWNCONTROL 0xD0A8
/*
* Vendor specific link state
*/
enum {
VS_LINK_DISABLED = 0,
VS_LINK_DOWN = 1,
VS_LINK_UP = 2,
VS_LINK_HIBERN8 = 3,
VS_LINK_LOST = 4,
VS_LINK_CFG = 5,
};
/*
* SiP commands
*/