]> www.infradead.org Git - users/hch/misc.git/commitdiff
scsi: ufs: host: mediatek: Support UFS PHY runtime PM and correct sequence
authorPeter Wang <peter.wang@mediatek.com>
Wed, 3 Sep 2025 02:44:41 +0000 (10:44 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 10 Sep 2025 02:46:23 +0000 (22:46 -0400)
Add support for UFS PHY runtime power management by probing the PHY
device and enabling its runtime PM. Ensure the correct sequence of
operations during suspend and resume: PHY suspend -> UFS suspend -> UFS
resume -> PHY resume.  Improve power management efficiency and system
stability with this enhancement.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ufs/host/ufs-mediatek.c
drivers/ufs/host/ufs-mediatek.h

index a6196c77462ea54c528bb0b0b679a565fe98e817..f79b488498462cd1f2c23ea09e4c30d7875fff08 100644 (file)
@@ -2243,10 +2243,12 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = {
 static int ufs_mtk_probe(struct platform_device *pdev)
 {
        int err;
-       struct device *dev = &pdev->dev;
-       struct device_node *reset_node;
-       struct platform_device *reset_pdev;
+       struct device *dev = &pdev->dev, *phy_dev = NULL;
+       struct device_node *reset_node, *phy_node = NULL;
+       struct platform_device *reset_pdev, *phy_pdev = NULL;
        struct device_link *link;
+       struct ufs_hba *hba;
+       struct ufs_mtk_host *host;
 
        reset_node = of_find_compatible_node(NULL, NULL,
                                             "ti,syscon-reset");
@@ -2273,13 +2275,44 @@ static int ufs_mtk_probe(struct platform_device *pdev)
        }
 
 skip_reset:
+       /* find phy node */
+       phy_node = of_parse_phandle(dev->of_node, "phys", 0);
+
+       if (phy_node) {
+               phy_pdev = of_find_device_by_node(phy_node);
+               if (!phy_pdev)
+                       goto skip_phy;
+               phy_dev = &phy_pdev->dev;
+
+               pm_runtime_set_active(phy_dev);
+               pm_runtime_enable(phy_dev);
+               pm_runtime_get_sync(phy_dev);
+
+               put_device(phy_dev);
+               dev_info(dev, "phys node found\n");
+       } else {
+               dev_notice(dev, "phys node not found\n");
+       }
+
+skip_phy:
        /* perform generic probe */
        err = ufshcd_pltfrm_init(pdev, &ufs_hba_mtk_vops);
-
-out:
-       if (err)
+       if (err) {
                dev_err(dev, "probe failed %d\n", err);
+               goto out;
+       }
+
+       hba = platform_get_drvdata(pdev);
+       if (!hba)
+               goto out;
+
+       if (phy_node && phy_dev) {
+               host = ufshcd_get_variant(hba);
+               host->phy_dev = phy_dev;
+       }
 
+out:
+       of_node_put(phy_node);
        of_node_put(reset_node);
        return err;
 }
@@ -2343,6 +2376,7 @@ out:
 static int ufs_mtk_runtime_suspend(struct device *dev)
 {
        struct ufs_hba *hba = dev_get_drvdata(dev);
+       struct ufs_mtk_host *host = ufshcd_get_variant(hba);
        struct arm_smccc_res res;
        int ret = 0;
 
@@ -2355,17 +2389,24 @@ static int ufs_mtk_runtime_suspend(struct device *dev)
        if (ufs_mtk_is_rtff_mtcmos(hba))
                ufs_mtk_mtcmos_ctrl(false, res);
 
+       if (host->phy_dev)
+               pm_runtime_put_sync(host->phy_dev);
+
        return 0;
 }
 
 static int ufs_mtk_runtime_resume(struct device *dev)
 {
        struct ufs_hba *hba = dev_get_drvdata(dev);
+       struct ufs_mtk_host *host = ufshcd_get_variant(hba);
        struct arm_smccc_res res;
 
        if (ufs_mtk_is_rtff_mtcmos(hba))
                ufs_mtk_mtcmos_ctrl(true, res);
 
+       if (host->phy_dev)
+               pm_runtime_get_sync(host->phy_dev);
+
        ufs_mtk_dev_vreg_set_lpm(hba, false);
 
        return ufshcd_runtime_resume(dev);
index e46dc5fa209dd913e72b9b34c20e42889d62b1c4..dfbf78bd86648fc50160959b10be5fd1f42aa1c6 100644 (file)
@@ -193,6 +193,7 @@ struct ufs_mtk_host {
        bool is_mcq_intr_enabled;
        int mcq_nr_intr;
        struct ufs_mtk_mcq_intr_info mcq_intr_info[UFSHCD_MAX_Q_NR];
+       struct device *phy_dev;
 };
 
 /* MTK delay of autosuspend: 500 ms */