From: Peter Wang peter.wang@mediatek.com
[ Upstream commit 77b96ef70b6ba46e3473e5e3a66095c4bc0e93a4 ]
Refine the system power management (PM) flow by skipping low power mode (LPM) and MTCMOS settings if runtime PM is already applied. Prevent redundant operations to ensure a more efficient PM process.
Signed-off-by: Peter Wang peter.wang@mediatek.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
- Fixes a real PM logic bug. Without this change, the Mediatek UFS driver forces VSx/regulators out of LPM and re-enables MTCMOS during system resume even if the device is runtime-suspended, which violates the runtime PM state and can wake hardware spuriously (extra power draw or mis-ordered bring-up). The core UFS system PM paths already skip work if the device is runtime-suspended; the Mediatek vendor code must mirror that behavior. - Aligns vendor flow with core UFS PM semantics. Core checks `pm_runtime_suspended(hba->dev)` and bails from system PM work in both suspend and resume (drivers/ufs/core/ufshcd.c:10284, drivers/ufs/core/ufshcd.c:10311). This patch adds the same guards to the Mediatek hooks so vendor-specific toggles are not performed on a runtime-suspended device. - Corrects ordering on resume. It powers the MTCMOS domain before changing device regulator LPM, matching the already-correct runtime PM path and avoiding SMC/PM operations while the domain is off.
Key code changes and impact: - Add guard in system suspend to skip vendor LPM/MTCMOS when runtime- suspended: - `if (pm_runtime_suspended(hba->dev)) goto out;` drivers/ufs/host/ufs-mediatek.c:2380 - Prevents redundant `ufs_mtk_dev_vreg_set_lpm(hba, true)` and `ufs_mtk_mtcmos_ctrl(false, ...)` calls when runtime PM already put the device in low power (drivers/ufs/host/ufs-mediatek.c:2383, drivers/ufs/host/ufs-mediatek.c:2386). - Add guard in system resume to preserve runtime-suspended state: - `if (pm_runtime_suspended(hba->dev)) goto out;` drivers/ufs/host/ufs-mediatek.c:2398 - Avoids powering on MTCMOS and clearing LPM when device should remain runtime-suspended. - Fix resume sequencing to match runtime resume: - Enable MTCMOS before clearing LPM: `ufs_mtk_mtcmos_ctrl(true, ...)` then `ufs_mtk_dev_vreg_set_lpm(hba, false)` (drivers/ufs/host/ufs- mediatek.c:2401, drivers/ufs/host/ufs-mediatek.c:2404). - Mirrors the runtime path order (drivers/ufs/host/ufs- mediatek.c:2442, drivers/ufs/host/ufs-mediatek.c:2448). - Always invoke core system resume for tracing/consistency (drivers/ufs/host/ufs-mediatek.c:2406).
Why it fits stable: - Small, contained fix limited to Mediatek UFS host. - No API changes; just conditionalizing existing operations and correcting order. - Prevents incorrect power-state transitions and redundant SMC/PM ops; low regression risk. - Aligns with core driver’s established PM behavior, reducing divergence and surprises.
Given these factors, this is an important behavioral fix with minimal risk and should be backported.
drivers/ufs/host/ufs-mediatek.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 6bdbbee1f0708..91081d2aabe44 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -2264,27 +2264,38 @@ static int ufs_mtk_system_suspend(struct device *dev)
ret = ufshcd_system_suspend(dev); if (ret) - return ret; + goto out; + + if (pm_runtime_suspended(hba->dev)) + goto out;
ufs_mtk_dev_vreg_set_lpm(hba, true);
if (ufs_mtk_is_rtff_mtcmos(hba)) ufs_mtk_mtcmos_ctrl(false, res);
- return 0; +out: + return ret; }
static int ufs_mtk_system_resume(struct device *dev) { + int ret = 0; struct ufs_hba *hba = dev_get_drvdata(dev); struct arm_smccc_res res;
+ if (pm_runtime_suspended(hba->dev)) + goto out; + ufs_mtk_dev_vreg_set_lpm(hba, false);
if (ufs_mtk_is_rtff_mtcmos(hba)) ufs_mtk_mtcmos_ctrl(true, res);
- return ufshcd_system_resume(dev); +out: + ret = ufshcd_system_resume(dev); + + return ret; } #endif