From 8941234ea13024ce27b2b952ba2d9ed4d1a1ceb1 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Mon, 3 Aug 2020 20:15:55 -0700 Subject: [PATCH] scsi: ufs: Add UFS_DEVICE_QUIRK_PA_HIBER8TIME quirk This adds the quirk to increase the hibern8 timeout on the host. Change-Id: I716124224d67942e257e17e7482ce9f32b8a5744 Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufs-qcom.c | 27 +++++++++++++++++++++++++++ drivers/scsi/ufs/ufs_quirks.h | 9 ++++++++- drivers/scsi/ufs/ufshcd.c | 6 ++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 75abd3d5b974..7e3f51e5bf74 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1620,6 +1620,29 @@ static void ufshcd_parse_pm_levels(struct ufs_hba *hba) hba->spm_lvl = spm_lvl; } +#if defined(CONFIG_SCSI_UFSHCD_QTI) +static void ufs_qcom_override_pa_h8time(struct ufs_hba *hba) +{ + int ret; + u32 loc_tx_h8time_cap = 0; + + ret = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(TX_HIBERN8TIME_CAPABILITY, + UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)), + &loc_tx_h8time_cap); + if (ret) { + dev_err(hba->dev, "Failed getting max h8 time: %d\n", ret); + return; + } + + /* 1 implies 100 us */ + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), + loc_tx_h8time_cap + 1); + if (ret) + dev_err(hba->dev, "Failed updating PA_HIBERN8TIME: %d\n", ret); + +} +#endif + static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba) { unsigned long flags; @@ -1646,6 +1669,10 @@ static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba) if (hba->dev_info.wmanufacturerid == UFS_VENDOR_MICRON) hba->dev_quirks |= UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM; +#if defined(CONFIG_SCSI_UFSHCD_QTI) + if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_HIBER8TIME) + ufs_qcom_override_pa_h8time(hba); +#endif return err; } diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index f06d313d4c9c..a4696808e886 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #ifndef _UFS_QUIRKS_H_ @@ -159,5 +159,12 @@ struct ufs_dev_fix { * supported features on such devices. */ #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 14) +#if defined(CONFIG_SCSI_UFSHCD_QTI) +/* + * Some ufs devices may need more time to be in hibern8 before exiting. + * Enable this quirk to give it an additional 100us. + */ +#define UFS_DEVICE_QUIRK_PA_HIBER8TIME (1 << 15) +#endif #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 42c6d6cd0b56..b17b0bd3b94e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -240,6 +240,12 @@ static struct ufs_dev_fix ufs_fixups[] = { UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/, UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME), +#if defined(CONFIG_SCSI_UFSHCD_QTI) + UFS_FIX(UFS_VENDOR_SAMSUNG, "KLUEG8UHDB-C2D1", + UFS_DEVICE_QUIRK_PA_HIBER8TIME), + UFS_FIX(UFS_VENDOR_SAMSUNG, "KLUDG4UHDB-B2D1", + UFS_DEVICE_QUIRK_PA_HIBER8TIME), +#endif END_FIX };