From e5183e91141567b40e818d014b5b545f2b515a6d Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Fri, 23 Jan 2026 15:18:28 +0530 Subject: [PATCH 1/5] FROMLIST: ufs: ufs-qcom: Fix sequential read variance The current devfreq downdifferential threshold of 5% causes overly aggressive frequency downscaling, leading to performance degradation sometimes during sequential read workloads. Update the UFS devfreq downdifferential threshold to 65. This widens the hysteresis window and prevents overly aggressive downscaling, ensuring that frequency is maintained for loads above 5% and scaling down occurs only when utilization falls below this level, while scale-up still triggers above the 70% threshold. Signed-off-by: Nitin Rawat Reviewed-by: Konrad Dybcio Signed-off-by: Pradeep P V K Link: https://lore.kernel.org/all/20260122141331.239354-4-nitin.rawat@oss.qualcomm.com/ --- drivers/ufs/host/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 291c434487648..6ccd162ab2ab0 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -2282,7 +2282,7 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, p->polling_ms = 60; p->timer = DEVFREQ_TIMER_DELAYED; d->upthreshold = 70; - d->downdifferential = 5; + d->downdifferential = 65; hba->clk_scaling.suspend_on_no_request = true; } From 6b862712451467650f1b56cfd3f4077d0553c488 Mon Sep 17 00:00:00 2001 From: Ram Prakash Gupta Date: Fri, 29 May 2026 13:40:45 +0530 Subject: [PATCH 2/5] FROMLIST: mmc: sdhci-msm: Set ice clk rate Set ice clk rate from sdhci msm platform driver, needed for target which are having legacy ice support, and need sdhci msm platform driver to set rate. Link: https://lore.kernel.org/all/20260529081045.2877910-2-ram.gupta@oss.qualcomm.com/ Signed-off-by: Ram Prakash Gupta Signed-off-by: Pradeep P V K --- drivers/mmc/host/sdhci-msm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 0882ce74e0c9b..82611364cbc62 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -286,6 +286,7 @@ struct sdhci_msm_host { /* core, iface, cal and sleep clocks */ struct clk_bulk_data bulk_clks[4]; #ifdef CONFIG_MMC_CRYPTO + struct clk *ice_clk; /* ICE clock */ struct qcom_ice *ice; #endif unsigned long clk_rate; @@ -2703,6 +2704,17 @@ static int sdhci_msm_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_MMC_CRYPTO + /* Setup ICE clock */ + msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice"); + if (!IS_ERR(msm_host->ice_clk)) { + /* Vote for max. clk rate for max. performance */ + ret = clk_set_rate(msm_host->ice_clk, INT_MAX); + if (ret) + dev_err(&pdev->dev, "ice clk set rate failed (%d)\n", ret); + } +#endif + /* Setup main peripheral bus clock */ clk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(clk)) { From 77c70de6cb7508ed0fcd11154e26a1aa283fea2a Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 1 Jun 2026 05:20:10 +0530 Subject: [PATCH 3/5] FROMLIST: scsi: ufs: core: Add UFSHCD_QUIRK_SKIP_DEVICE_RESET quirk Add a new host quirk UFSHCD_QUIRK_SKIP_DEVICE_RESET to allow host controller drivers to skip asserting device reset during UFS power down. When RST_N is asserted, the UFS device firmware wakes up and executes its internal reset routine. This routine initializes multiple hardware blocks and causing the device to draw a large curreny during this time. If the power rail transitions to LPM (Low Power Mode) while the device is still drawing this elevated current, it may trigger an OCP (Over Current Protection) fault in the regulator. For some UFS devices (e.g., Micron), the elevated current draw persists until the reset line is deasserted, making a fixed delay insufficient to prevent OCP. This quirk allows such devices to skip device reset during UFS power down. The device reset will instead be asserted as part of the platform shutdown sequence. Link: https://lore.kernel.org/linux-scsi/20260531235011.1052706-2-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Pradeep P V K --- include/ufs/ufshcd.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 248d0a5bef407..98ea715c03051 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -812,7 +812,22 @@ enum ufshcd_quirks { * (EQTR) using Adapt L0L1L2L3 length which is larger than what is * allowed by M-PHY spec ver 6.0. */ + UFSHCD_QUIRK_EXTENDED_TX_EQTR_ADAPT_LENGTH_L0L1L2L3 = 1 << 28, + /* + * Some UFS devices keep drawing larger current after reset is + * asserted until it is deasserted. Asserting device reset + * during UFS power down causes the device firmware to wake up and + * execute its reset routine, drawing current beyond the permissible + * limit for low-power mode (LPM). This may trigger an OCP fault on + * the regulator supplying power to UFS. + * + * Enable this quirk to skip asserting device reset during UFS power + * down. This is handled only in shutdown; the device reset will be + * asserted as part of the platform shutdown sequence. + */ + + UFSHCD_QUIRK_SKIP_DEVICE_RESET = 1 << 29, }; enum ufshcd_caps { From d86d915355ae0f4d79ec0223864f41cb1c30ab70 Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 1 Jun 2026 05:20:11 +0530 Subject: [PATCH 4/5] FROMLIST: scsi: ufs: ufs-qcom: Enable SKIP DEVICE RESET Quirk A previous fix [1] addressed an OCP (Over Current Protection) issue during UFS power down (PC=3) by adding a 10ms delay after asserting HWRST. The delay allows the UFS device to complete its reset routine before the power rail transitions to LPM (Low Power Mode). However, this fix is insufficient for certain Micron UFS parts. Unlike other vendors whose reset routine completes within ~10ms, Micron parts continue to draw current beyond the LPM threshold for a longer duration after reset is asserted, specifically until the reset is deasserted (RST_N goes high). No fixed delay can reliably cover this window since there is currently no mechanism for the host to query whether the device reset routine has completed. Enable the UFSHCD_QUIRK_SKIP_DEVICE_RESET quirk to skip device assert reset during UFS power down for Micron parts. For all other vendors, the existing behavior (assert reset + 10ms delay) is preserved. This quirk is applicable only during shutdown. The device reset will be asserted as part of the platform shutdown sequences. [1] commit 5127be409c6c ("scsi: ufs: ufs-qcom: Fix UFS OCP issue during UFS power down (PC=3)") Link: https://lore.kernel.org/linux-scsi/20260531235011.1052706-3-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Pradeep P V K --- drivers/ufs/host/ufs-qcom.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 6ccd162ab2ab0..f605b3c73114b 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -770,9 +770,17 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, if (!ufs_qcom_is_link_active(hba)) ufs_qcom_disable_lane_clks(host); - - /* reset the connected UFS device during power down */ - if (ufs_qcom_is_link_off(hba) && host->device_reset) { + /* + * For some UFS vendors, skip asserting device reset here. + * These vendor parts keep drawing larger current after reset + * is asserted until it is deasserted, and the 10ms delay is + * not sufficient to prevent OCP (Over Current Protection) + * on the regulator. This is for the powerdown case, so + * the device reset can be asserted later as part of the + * platform shutdown sequence. + */ + if (ufs_qcom_is_link_off(hba) && host->device_reset && + !(hba->quirks & UFSHCD_QUIRK_SKIP_DEVICE_RESET)) { ufs_qcom_device_reset_ctrl(hba, true); /* * After sending the SSU command, asserting the rst_n @@ -1288,6 +1296,19 @@ static struct ufs_dev_quirk ufs_qcom_dev_fixups[] = { static void ufs_qcom_fixup_dev_quirks(struct ufs_hba *hba) { ufshcd_fixup_dev_quirks(hba, ufs_qcom_dev_fixups); + + /* + * Some UFS parts keep drawing larger current after reset is asserted + * until it is deasserted. The 10ms delay added after asserting HWRST + * (as done for other vendors) is not sufficient for these parts. + * + * Skip asserting device reset during UFS power down for these parts + * to prevent OCP (Over Current Protection) fault on the regulator. + * This is handled only in shutdown; the device reset will be asserted + * as part of the platform shutdown sequence. + */ + if (hba->dev_info.wmanufacturerid == UFS_VENDOR_MICRON) + hba->quirks |= UFSHCD_QUIRK_SKIP_DEVICE_RESET; } static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) From d22b238353db143e0063135d2ce55f9d73991b9a Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 13 Jul 2026 23:04:34 +0530 Subject: [PATCH 5/5] FROMLIST: scsi: ufs: ufs-qcom: Enable only lane clocks in lane clock APIs ufs_qcom_enable_lane_clks() and ufs_qcom_disable_lane_clks() currently use clk_bulk_prepare_enable()/clk_bulk_disable_unprepare() on the entire host->clks array obtained from devm_clk_bulk_get_all(). This array contains all device clocks, not just lane symbol clocks. Since the UFS core framework already manages the non-lane clocks via the setup_clocks callback, the bulk enable/disable in the lane clock APIs resulted in duplicate reference count increments on those shared clocks. The extra enable counts were never balanced by a corresponding disable from the framework's clock gating path, preventing the clock reference counts from reaching zero and ultimately blocking CXO shutdown during low-power states. Fix this by restricting the lane clock APIs to only prepare/enable and disable/unprepare the three lane symbol clocks (tx_lane0_sync_clk, rx_lane0_sync_clk, rx_lane1_sync_clk), leaving the handling of all other clocks to the UFS core framework. The lane clocks are now acquired individually via devm_clk_get() instead of being looked up in the bulk clock array. Signed-off-by: Nitin Rawat Signed-off-by: Giri Prasad Goriparthi --- drivers/ufs/host/ufs-qcom.c | 41 ++++++++++++++++++++++++++++++++----- drivers/ufs/host/ufs-qcom.h | 3 +++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index f605b3c73114b..6f28d9685af02 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -347,7 +347,9 @@ static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host) if (!host->is_lane_clks_enabled) return; - clk_bulk_disable_unprepare(host->num_clks, host->clks); + clk_disable_unprepare(host->rx_lane1_sync_clk); + clk_disable_unprepare(host->rx_lane0_sync_clk); + clk_disable_unprepare(host->tx_lane0_sync_clk); host->is_lane_clks_enabled = false; } @@ -356,18 +358,35 @@ static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host) { int err; - err = clk_bulk_prepare_enable(host->num_clks, host->clks); + if (host->is_lane_clks_enabled) + return 0; + + err = clk_prepare_enable(host->tx_lane0_sync_clk); if (err) - return err; + goto out; - host->is_lane_clks_enabled = true; + err = clk_prepare_enable(host->rx_lane0_sync_clk); + if (err) + goto out_disable_tx_lane0; + + err = clk_prepare_enable(host->rx_lane1_sync_clk); + if (err) + goto out_disable_rx_lane0; + host->is_lane_clks_enabled = true; return 0; + +out_disable_rx_lane0: + clk_disable_unprepare(host->rx_lane0_sync_clk); +out_disable_tx_lane0: + clk_disable_unprepare(host->tx_lane0_sync_clk); +out: + return err; } static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host) { - int err; + int err, i; struct device *dev = host->hba->dev; if (has_acpi_companion(dev)) @@ -379,6 +398,18 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host) host->num_clks = err; + for (i = 0; i < host->num_clks; i++) { + if (!host->clks[i].id) + continue; + if (!strcmp(host->clks[i].id, "tx_lane0_sync_clk")) + host->tx_lane0_sync_clk = host->clks[i].clk; + else if (!strcmp(host->clks[i].id, "rx_lane0_sync_clk")) + host->rx_lane0_sync_clk = host->clks[i].clk; + else if (!strcmp(host->clks[i].id, "rx_lane1_sync_clk")) + if (host->hba->lanes_per_direction > 1) + host->rx_lane1_sync_clk = host->clks[i].clk; + } + return 0; } diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h index e20b3ca505775..2fcc3bc1133d1 100644 --- a/drivers/ufs/host/ufs-qcom.h +++ b/drivers/ufs/host/ufs-qcom.h @@ -331,6 +331,9 @@ struct ufs_qcom_host { struct ufs_hba *hba; struct ufs_pa_layer_attr dev_req_params; struct clk_bulk_data *clks; + struct clk *tx_lane0_sync_clk; + struct clk *rx_lane0_sync_clk; + struct clk *rx_lane1_sync_clk; u32 num_clks; bool is_lane_clks_enabled;