From: Greg Kroah-Hartman <gre...@linuxfoundation.org>

From: Kiwoong Kim <kwmad....@samsung.com>

[ Upstream commit b1d0d2eb89d4e3a25b212a9d836587503537067e ]

The UniPro specification states that attribute IDs of the following
parameters are vendor-specific so some SoCs could have no regions at the
defined addresses:

 - DME_LocalFC0ProtectionTimeOutVal
 - DME_LocalTC0ReplayTimeOutVal
 - DME_LocalAFC0ReqTimeOutVal

In addition, the following parameters should be set considering the
compatibility between host and device.

 - PA_PWRMODEUSERDATA0
 - PA_PWRMODEUSERDATA1
 - PA_PWRMODEUSERDATA2
 - PA_PWRMODEUSERDATA3
 - PA_PWRMODEUSERDATA4
 - PA_PWRMODEUSERDATA5

Introduce a quirk to allow vendor drivers to override the UniPro defaults.

Link: 
https://lore.kernel.org/r/1fedd3dea0ccc980913a5995a10510d86a5b01b9.1608513782.git.kwmad....@samsung.com
Acked-by: Avri Altman <avri.alt...@wdc.com>
Signed-off-by: Kiwoong Kim <kwmad....@samsung.com>
Signed-off-by: Martin K. Petersen <martin.peter...@oracle.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/scsi/ufs/ufshcd.c | 40 ++++++++++++++++++++-------------------
 drivers/scsi/ufs/ufshcd.h |  6 ++++++
 2 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 813289328467..379d44d6b9eb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4153,25 +4153,27 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
                ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES),
                                                pwr_mode->hs_rate);
 
-       ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0),
-                       DL_FC0ProtectionTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1),
-                       DL_TC0ReplayTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2),
-                       DL_AFC0ReqTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA3),
-                       DL_FC1ProtectionTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA4),
-                       DL_TC1ReplayTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA5),
-                       DL_AFC1ReqTimeOutVal_Default);
-
-       ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalFC0ProtectionTimeOutVal),
-                       DL_FC0ProtectionTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalTC0ReplayTimeOutVal),
-                       DL_TC0ReplayTimeOutVal_Default);
-       ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalAFC0ReqTimeOutVal),
-                       DL_AFC0ReqTimeOutVal_Default);
+       if (!(hba->quirks & UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING)) {
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0),
+                               DL_FC0ProtectionTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1),
+                               DL_TC0ReplayTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2),
+                               DL_AFC0ReqTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA3),
+                               DL_FC1ProtectionTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA4),
+                               DL_TC1ReplayTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA5),
+                               DL_AFC1ReqTimeOutVal_Default);
+
+               ufshcd_dme_set(hba, 
UIC_ARG_MIB(DME_LocalFC0ProtectionTimeOutVal),
+                               DL_FC0ProtectionTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalTC0ReplayTimeOutVal),
+                               DL_TC0ReplayTimeOutVal_Default);
+               ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalAFC0ReqTimeOutVal),
+                               DL_AFC0ReqTimeOutVal_Default);
+       }
 
        ret = ufshcd_uic_change_pwr_mode(hba, pwr_mode->pwr_rx << 4
                        | pwr_mode->pwr_tx);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6c62a281c863..fcca4e15c8cd 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -544,6 +544,12 @@ enum ufshcd_quirks {
         */
        UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL          = 1 << 12,
 
+       /*
+        * This quirk needs to disable unipro timeout values
+        * before power mode change
+        */
+       UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13,
+
 };
 
 enum ufshcd_caps {
-- 
2.30.1



Reply via email to