scsi: ufs: host: mediatek: Disable auto-hibern8 during power mode changes

Disable auto-hibern8 during power mode transitions to prevent unintended
entry into auto-hibern8. Restore the original auto-hibern8 timer value
after completing the power mode change to maintain system stability and
prevent potential issues during power state transitions.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Peter Wang 2025-09-03 10:44:42 +08:00 committed by Martin K. Petersen
parent c73cd5e298
commit f5ca8d0c7a

View File

@ -1429,19 +1429,49 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
return ret;
}
static int ufs_mtk_auto_hibern8_disable(struct ufs_hba *hba)
{
int ret;
/* disable auto-hibern8 */
ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
/* wait host return to idle state when auto-hibern8 off */
ufs_mtk_wait_idle_state(hba, 5);
ret = ufs_mtk_wait_link_state(hba, VS_LINK_UP, 100);
if (ret) {
dev_warn(hba->dev, "exit h8 state fail, ret=%d\n", ret);
ufshcd_force_error_recovery(hba);
/* trigger error handler and break suspend */
ret = -EBUSY;
}
return ret;
}
static int ufs_mtk_pwr_change_notify(struct ufs_hba *hba,
enum ufs_notify_change_status stage,
const struct ufs_pa_layer_attr *dev_max_params,
struct ufs_pa_layer_attr *dev_req_params)
{
int ret = 0;
static u32 reg;
switch (stage) {
case PRE_CHANGE:
if (ufshcd_is_auto_hibern8_supported(hba)) {
reg = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
ufs_mtk_auto_hibern8_disable(hba);
}
ret = ufs_mtk_pre_pwr_change(hba, dev_max_params,
dev_req_params);
break;
case POST_CHANGE:
if (ufshcd_is_auto_hibern8_supported(hba))
ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER);
break;
default:
ret = -EINVAL;
@ -1686,29 +1716,6 @@ static void ufs_mtk_dev_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
}
}
static int ufs_mtk_auto_hibern8_disable(struct ufs_hba *hba)
{
int ret;
/* disable auto-hibern8 */
ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
/* wait host return to idle state when auto-hibern8 off */
ufs_mtk_wait_idle_state(hba, 5);
ret = ufs_mtk_wait_link_state(hba, VS_LINK_UP, 100);
if (ret) {
dev_warn(hba->dev, "exit h8 state fail, ret=%d\n", ret);
ufshcd_force_error_recovery(hba);
/* trigger error handler and break suspend */
ret = -EBUSY;
}
return ret;
}
static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
enum ufs_notify_change_status status)
{