[PATCH v2] ufs: ufs-qcom: Align programming sequence of Shared ICE for UFS controller v5
From: Palash Kambar
Date: Fri Aug 08 2025 - 04:53:38 EST
Disable of AES core in Shared ICE is not supported during power
collapse for UFS Host Controller V5.0.
Hence follow below steps to reset the ICE upon exiting power collapse
and align with Hw programming guide.
a. Write 0x18 to UFS_MEM_ICE_CFG
b. Write 0x0 to UFS_MEM_ICE_CFG
---
changes from V1
1) Incorporated feedback from Konrad and Manivannan by adding a delay
between ICE reset assertion and deassertion.
2) Removed magic numbers and replaced them with meaningful constants.
---
Signed-off-by: Palash Kambar <quic_pkambar@xxxxxxxxxxx>
---
drivers/ufs/host/ufs-qcom.c | 32 ++++++++++++++++++++++++++++++++
drivers/ufs/host/ufs-qcom.h | 2 ++
2 files changed, 34 insertions(+)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 444a09265ded..44252c05d1b2 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -38,6 +38,13 @@
#define DEEMPHASIS_3_5_dB 0x04
#define NO_DEEMPHASIS 0x0
+#define UFS_ICE_RESET_ASSERT_VALUE 0x18
+#define ICE_RESET_DEASSERT_VALUE 0x00
+#define UFS_HW_VER_MAJOR_FIVE 0x5
+#define UFS_HW_VER_MINOR_ZERO 0x0
+#define UFS_HW_VER_STEP_ZERO 0x0
+#define UFS_ICE_RESET_DELAY 0x5
+
enum {
TSTBUS_UAWM,
TSTBUS_UARM,
@@ -744,6 +751,8 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
if (ufs_qcom_is_link_off(hba) && host->device_reset)
ufs_qcom_device_reset_ctrl(hba, true);
+ host->ufs_power_collapse = true;
+
return ufs_qcom_ice_suspend(host);
}
@@ -759,6 +768,28 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
return ufs_qcom_ice_resume(host);
}
+static void ufs_qcom_hibern8_notify(struct ufs_hba *hba,
+ enum uic_cmd_dme uic_cmd,
+ enum ufs_notify_change_status status)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ /* Apply shared ICE WA */
+ if (uic_cmd == UIC_CMD_DME_HIBER_EXIT &&
+ status == POST_CHANGE &&
+ host->hw_ver.major == UFS_HW_VER_MAJOR_FIVE &&
+ host->hw_ver.minor == UFS_HW_VER_MINOR_ZERO &&
+ host->hw_ver.step == UFS_HW_VER_STEP_ZERO &&
+ host->ufs_power_collapse) {
+ host->ufs_power_collapse = false;
+ ufshcd_writel(hba, UFS_ICE_RESET_ASSERT_VALUE, UFS_MEM_ICE);
+ ufshcd_readl(hba, UFS_MEM_ICE);
+ msleep(UFS_ICE_RESET_DELAY);
+ ufshcd_writel(hba, ICE_RESET_DEASSERT_VALUE, UFS_MEM_ICE);
+ ufshcd_readl(hba, UFS_MEM_ICE);
+ }
+}
+
static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
{
if (host->dev_ref_clk_ctrl_mmio &&
@@ -2258,6 +2289,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.hce_enable_notify = ufs_qcom_hce_enable_notify,
.link_startup_notify = ufs_qcom_link_startup_notify,
.pwr_change_notify = ufs_qcom_pwr_change_notify,
+ .hibern8_notify = ufs_qcom_hibern8_notify,
.apply_dev_quirks = ufs_qcom_apply_dev_quirks,
.fixup_dev_quirks = ufs_qcom_fixup_dev_quirks,
.suspend = ufs_qcom_suspend,
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 6840b7526cf5..6bd205804feb 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -60,6 +60,7 @@ enum {
UFS_AH8_CFG = 0xFC,
UFS_RD_REG_MCQ = 0xD00,
+ UFS_MEM_ICE = 0x2600,
REG_UFS_MEM_ICE_CONFIG = 0x260C,
REG_UFS_MEM_ICE_NUM_CORE = 0x2664,
@@ -290,6 +291,7 @@ struct ufs_qcom_host {
u32 phy_gear;
bool esi_enabled;
+ bool ufs_power_collapse;
unsigned long active_cmds;
};
--
2.34.1