OSDN Git Service

scsi: ufs-mediatek: Introduce low-power mode for device power supply
authorStanley Chu <stanley.chu@mediatek.com>
Mon, 1 Jun 2020 10:46:44 +0000 (18:46 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 16 Jun 2020 03:06:40 +0000 (23:06 -0400)
Allow device power supply to enter low-power mode.

Link: https://lore.kernel.org/r/20200601104646.15436-4-stanley.chu@mediatek.com
Reviewed-by: Pengshun Zhao <pengshun.zhao@mediatek.com>
Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/ufs/ufs-mediatek.c

index 3c85f5e..5f41b7b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/of_address.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/soc/mediatek/mtk_sip_svc.h>
 
 #include "ufshcd.h"
@@ -521,6 +522,19 @@ static int ufs_mtk_link_set_lpm(struct ufs_hba *hba)
        return 0;
 }
 
+static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
+{
+       if (!hba->vreg_info.vccq2)
+               return;
+
+       if (lpm & !hba->vreg_info.vcc->enabled)
+               regulator_set_mode(hba->vreg_info.vccq2->reg,
+                                  REGULATOR_MODE_IDLE);
+       else if (!lpm)
+               regulator_set_mode(hba->vreg_info.vccq2->reg,
+                                  REGULATOR_MODE_NORMAL);
+}
+
 static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 {
        int err;
@@ -537,6 +551,12 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                        ufshcd_set_link_off(hba);
                        return -EAGAIN;
                }
+               /*
+                * Make sure no error will be returned to prevent
+                * ufshcd_suspend() re-enabling regulators while vreg is still
+                * in low-power mode.
+                */
+               ufs_mtk_vreg_set_lpm(hba, true);
        }
 
        if (!ufshcd_is_link_active(hba))
@@ -554,6 +574,7 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                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);
                if (err) {
                        err = ufshcd_link_recovery(hba);