mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-21 10:29:14 +07:00
scsi: ufs-mediatek: Fix unbalanced clock on/off
MediaTek UFS clocks are separated to two parts and controlled by different modules: ufs-mediatek and phy-ufs-mediatek. If both Auto-Hibern8 and clk-gating feature are enabled, mphy power control is not balanced thus unbalanced control also happens to the clocks probed by phy-ufs-mediatek module. Fix this issue by: - Promise usage of phy_power_on/off balanced - Remove phy_power_on/off control in suspend/resume vops since both can be handled in setup_clock vops only Link: https://lore.kernel.org/r/20200601104646.15436-5-stanley.chu@mediatek.com Reviewed-by: Peter Wang <peter.wang@mediatek.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:
parent
488edafb11
commit
561e3a8726
@ -205,6 +205,23 @@ int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on)
|
||||
{
|
||||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
struct phy *mphy = host->mphy;
|
||||
|
||||
if (!mphy)
|
||||
return;
|
||||
|
||||
if (on && !host->mphy_powered_on)
|
||||
phy_power_on(mphy);
|
||||
else if (!on && host->mphy_powered_on)
|
||||
phy_power_off(mphy);
|
||||
else
|
||||
return;
|
||||
host->mphy_powered_on = on;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufs_mtk_setup_clocks - enables/disable clocks
|
||||
* @hba: host controller instance
|
||||
@ -218,6 +235,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
|
||||
{
|
||||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
int ret = 0;
|
||||
bool clk_pwr_off = false;
|
||||
|
||||
/*
|
||||
* In case ufs_mtk_init() is not yet done, simply ignore.
|
||||
@ -228,25 +246,29 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
|
||||
return 0;
|
||||
|
||||
if (!on && status == PRE_CHANGE) {
|
||||
if (!ufshcd_is_link_active(hba)) {
|
||||
ufs_mtk_setup_ref_clk(hba, on);
|
||||
ret = phy_power_off(host->mphy);
|
||||
} else {
|
||||
if (ufshcd_is_link_off(hba)) {
|
||||
clk_pwr_off = true;
|
||||
} else if (ufshcd_is_link_hibern8(hba) ||
|
||||
(!ufshcd_can_hibern8_during_gating(hba) &&
|
||||
ufshcd_is_auto_hibern8_enabled(hba))) {
|
||||
/*
|
||||
* Gate ref-clk if link state is in Hibern8
|
||||
* triggered by Auto-Hibern8.
|
||||
* Gate ref-clk and poweroff mphy if link state is in
|
||||
* OFF or Hibern8 by either Auto-Hibern8 or
|
||||
* ufshcd_link_state_transition().
|
||||
*/
|
||||
if (!ufshcd_can_hibern8_during_gating(hba) &&
|
||||
ufshcd_is_auto_hibern8_enabled(hba)) {
|
||||
ret = ufs_mtk_wait_link_state(hba,
|
||||
VS_LINK_HIBERN8,
|
||||
15);
|
||||
if (!ret)
|
||||
ufs_mtk_setup_ref_clk(hba, on);
|
||||
}
|
||||
ret = ufs_mtk_wait_link_state(hba,
|
||||
VS_LINK_HIBERN8,
|
||||
15);
|
||||
if (!ret)
|
||||
clk_pwr_off = true;
|
||||
}
|
||||
|
||||
if (clk_pwr_off) {
|
||||
ufs_mtk_setup_ref_clk(hba, on);
|
||||
ufs_mtk_mphy_power_on(hba, on);
|
||||
}
|
||||
} else if (on && status == POST_CHANGE) {
|
||||
ret = phy_power_on(host->mphy);
|
||||
ufs_mtk_mphy_power_on(hba, on);
|
||||
ufs_mtk_setup_ref_clk(hba, on);
|
||||
}
|
||||
|
||||
@ -538,7 +560,6 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
|
||||
static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
{
|
||||
int err;
|
||||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
|
||||
if (ufshcd_is_link_hibern8(hba)) {
|
||||
err = ufs_mtk_link_set_lpm(hba);
|
||||
@ -559,20 +580,13 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
ufs_mtk_vreg_set_lpm(hba, true);
|
||||
}
|
||||
|
||||
if (!ufshcd_is_link_active(hba))
|
||||
phy_power_off(host->mphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
{
|
||||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
int err;
|
||||
|
||||
if (!ufshcd_is_link_active(hba))
|
||||
phy_power_on(host->mphy);
|
||||
|
||||
if (ufshcd_is_link_hibern8(hba)) {
|
||||
ufs_mtk_vreg_set_lpm(hba, false);
|
||||
err = ufs_mtk_link_set_hpm(hba);
|
||||
|
@ -91,6 +91,7 @@ enum {
|
||||
struct ufs_mtk_host {
|
||||
struct ufs_hba *hba;
|
||||
struct phy *mphy;
|
||||
bool mphy_powered_on;
|
||||
bool unipro_lpm;
|
||||
bool ref_clk_enabled;
|
||||
u16 ref_clk_ungating_wait_us;
|
||||
|
Loading…
Reference in New Issue
Block a user