scsi: ufs: ufs-mediatek: gate ref-clk during Auto-Hibern8
authorStanley Chu <stanley.chu@mediatek.com>
Wed, 29 Jan 2020 10:52:51 +0000 (18:52 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 11 Feb 2020 03:46:54 +0000 (22:46 -0500)
In current UFS driver design, hba->uic_link_state will not be changed after
link enters Hibern8 state by Auto-Hibern8 mechanism.  In this case,
reference clock gating will be skipped unless special handling is
implemented in vendor's callbacks.

Support reference clock gating during Auto-Hibern8 period in MediaTek
Chipsets: If link state is already in Hibern8 while Auto-Hibern8 feature is
enabled, gate reference clock in setup_clocks callback.

Link: https://lore.kernel.org/r/20200129105251.12466-5-stanley.chu@mediatek.com
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: Bean Huo <beanhuo@micron.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
drivers/scsi/ufs/ufs-mediatek.h

index d78897a1490542232bf4687a74262ea8c5bb1dc6..0ce08872d6718a0549129bf9da6172d35e99fa9e 100644 (file)
@@ -143,6 +143,17 @@ out:
        return 0;
 }
 
+static u32 ufs_mtk_link_get_state(struct ufs_hba *hba)
+{
+       u32 val;
+
+       ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL);
+       val = ufshcd_readl(hba, REG_UFS_PROBE);
+       val = val >> 28;
+
+       return val;
+}
+
 /**
  * ufs_mtk_setup_clocks - enables/disable clocks
  * @hba: host controller instance
@@ -155,7 +166,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
                                enum ufs_notify_change_status status)
 {
        struct ufs_mtk_host *host = ufshcd_get_variant(hba);
-       int ret = -EINVAL;
+       int ret = 0;
 
        /*
         * In case ufs_mtk_init() is not yet done, simply ignore.
@@ -165,19 +176,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
        if (!host)
                return 0;
 
-       switch (status) {
-       case PRE_CHANGE:
-               if (!on && !ufshcd_is_link_active(hba)) {
+       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 {
+                       /*
+                        * Gate ref-clk if link state is in Hibern8
+                        * triggered by Auto-Hibern8.
+                        */
+                       if (!ufshcd_can_hibern8_during_gating(hba) &&
+                           ufshcd_is_auto_hibern8_enabled(hba) &&
+                           ufs_mtk_link_get_state(hba) ==
+                           VS_LINK_HIBERN8)
+                               ufs_mtk_setup_ref_clk(hba, on);
                }
-               break;
-       case POST_CHANGE:
-               if (on) {
-                       ret = phy_power_on(host->mphy);
-                       ufs_mtk_setup_ref_clk(hba, on);
-               }
-               break;
+       } else if (on && status == POST_CHANGE) {
+               ret = phy_power_on(host->mphy);
+               ufs_mtk_setup_ref_clk(hba, on);
        }
 
        return ret;
index fccdd979d6fb47dcd3d4cb71b4ed0da817899b74..492414e5f4813aba88d02f050169058ff7c6be55 100644 (file)
 #define VS_SAVEPOWERCONTROL         0xD0A6
 #define VS_UNIPROPOWERDOWNCONTROL   0xD0A8
 
+/*
+ * Vendor specific link state
+ */
+enum {
+       VS_LINK_DISABLED            = 0,
+       VS_LINK_DOWN                = 1,
+       VS_LINK_UP                  = 2,
+       VS_LINK_HIBERN8             = 3,
+       VS_LINK_LOST                = 4,
+       VS_LINK_CFG                 = 5,
+};
+
 /*
  * SiP commands
  */