public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 0/5] Enable ICE clock scaling
@ 2026-04-09 11:44 Abhinaba Rakshit
  2026-04-09 11:44 ` [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE Abhinaba Rakshit
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-09 11:44 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Abhinaba Rakshit, Konrad Dybcio

Introduce support for dynamic clock scaling of the ICE (Inline Crypto Engine)
using the OPP framework. During ICE device probe, the driver now attempts to
parse an optional OPP table from the ICE-specific device tree node for
DVFS-aware operations. API qcom_ice_scale_clk is exposed by ICE driver
and is invoked by UFS host controller driver in response to clock scaling
requests, ensuring coordination between ICE and host controller.

For MMC controllers that do not support clock scaling, the ICE clock frequency
is kept aligned with the MMC controller’s clock rate (TURBO) to ensure
consistent operation.

Dynamic clock scaling based on OPP tables enables better power-performance
trade-offs. By adjusting ICE clock frequencies according to workload and power
constraints, the system can achieve higher throughput when needed and
reduce power consumption during idle or low-load conditions.

The OPP table remains optional, absence of the table will not cause
probe failure. However, in the absence of an OPP table, ICE clocks will
remain at their default rates, which may limit performance under
high-load scenarios or prevent performance optimizations during idle periods.

Testing:
* dtbs_check
* Validated on Rb3Gen2 and qcs8300-ride-sx

Merge Order and Dependencies
============================

Patch 2 is dependent on patch 1 for the qcom_ice_scale_clk API to be available.
Patch 3 is dependent on patch 1 for the qcom_ice_scale_clk API to be available.

Due to dependency, all patches should go through Qcom SoC tree.

This patchset supersedes earlier ICE clock scaling series (v1–v7) with updated dependencies.
Hence, this patchset also *Depends-On* the following patchseries:

[1] Add explicit clock vote and enable power-domain for QCOM-ICE
    https://lore.kernel.org/linux-arm-msm/20260323-qcom_ice_power_and_clk_vote-v4-0-e36044bbdfe9@oss.qualcomm.com

[2] Enable Inline crypto engine for kodiak and monaco
    https://lore.kernel.org/lkml/20260310113557.348502-1-neeraj.soni@oss.qualcomm.com/

[3] Enable iface clock and power domain for kodiak and monaco ice sdhc
    https://lore.kernel.org/linux-arm-msm/20260409-ice_emmc_clock_addition-v2-0-90bbcc057361@oss.qualcomm.com/

Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
---
Changes in v8:
- Instead of scaling to TURBO in ICE probe, sdhci_msm_ice_init calls qcom_ice_scale_clk for setting freq to max.
- Fix error handling in qcom_ice_scale_clk.
- Fix error handling in ufs_qcom_clk_scale_notify for the call to qcom_ice_scale_clk.
- Move the registering of OPP-table to qcom_ice_probe and remove passing legacy_bindings argument to qcom_ice_create.
- Add OPP-table for kodiak and monaco ICE eMMC and UFS device nodes.
- Link to v7: https://lore.kernel.org/r/20260302-enable-ufs-ice-clock-scaling-v7-0-669b96ecadd8@oss.qualcomm.com

Changes in v7:
- Replace the custom rounding flags with 'bool round_ceil' as suggested.
- Update the dev_info log-line.
- Dropped dt-bindings patch (already applied by in previous patchseries).
- Add merge order and dependencies as suggested.
- Link to v6: https://lore.kernel.org/r/20260219-enable-ufs-ice-clock-scaling-v6-0-0c5245117d45@oss.qualcomm.com

Changes in v6:
- Remove scale_up parameter from qcom_ice_scale_clk API.
- Remove having max_freq and min_freq as the checks for overclocking and underclocking is no-longer needed.
- UFS driver passes rounding flags depending on scale_up value.
- Ensure UFS driver does not fail devfreq requests if ICE OPP is not supported.
- Link to v5: https://lore.kernel.org/all/20260211-enable-ufs-ice-clock-scaling-v5-0-221c520a1f2e@oss.qualcomm.com/

Changes in v5:
- Update operating-points-v2 property in dtbindings as suggested.
- Fix comment styles.
- Add argument in qcom_ice_create to distinguish between legacy bindings and newer bindings.
- Ensure to drop votes in suspend and enable the last vote in resume.
- Link to v4: https://lore.kernel.org/r/20260128-enable-ufs-ice-clock-scaling-v4-0-260141e8fce6@oss.qualcomm.com

Changes in v4:
- Enable multiple frequency scaling based OPP-entries as suggested in v3 patchset.
- Include bindings change: https://lore.kernel.org/all/20260123-add-operating-points-v2-property-for-qcom-ice-bindings-v1-1-2155f7aacc28@oss.qualcomm.com/.
- Link to v3: https://lore.kernel.org/r/20260123-enable-ufs-ice-clock-scaling-v3-0-d0d8532abd98@oss.qualcomm.com

Changes in v3:
- Avoid clock scaling in case of legacy bindings as suggested.
- Use of_device_is_compatible to distinguish between legacy and non-legacy bindings.
- Link to v2: https://lore.kernel.org/r/20251121-enable-ufs-ice-clock-scaling-v2-0-66cb72998041@oss.qualcomm.com

Changes in v2:
- Use OPP-table instead of freq-table-hz for clock scaling.
- Enable clock scaling for legacy targets as well, by fetching frequencies from storage opp-table.
- Introduce has_opp variable in qcom_ice structure to keep track, if ICE instance has dedicated OPP-table registered.
- Combined the changes for patch-series <20251001-set-ice-clock-to-turbo-v1-1-7b802cf61dda@oss.qualcomm.com> as suggested.
- Link to v1: https://lore.kernel.org/r/20251001-enable-ufs-ice-clock-scaling-v1-0-ec956160b696@oss.qualcomm.com

---
Abhinaba Rakshit (5):
      soc: qcom: ice: Add OPP-based clock scaling support for ICE
      ufs: host: Add ICE clock scaling during UFS clock changes
      mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init
      arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes
      arm64: dts: qcom: monaco: Add OPP-table for ICE UFS and ICE eMMC nodes

 arch/arm64/boot/dts/qcom/kodiak.dtsi | 42 ++++++++++++++++
 arch/arm64/boot/dts/qcom/monaco.dtsi | 32 +++++++++++++
 drivers/mmc/host/sdhci-msm.c         | 24 ++++++++++
 drivers/soc/qcom/ice.c               | 92 ++++++++++++++++++++++++++++++++++++
 drivers/ufs/host/ufs-qcom.c          | 22 ++++++++-
 include/soc/qcom/ice.h               |  2 +
 6 files changed, 213 insertions(+), 1 deletion(-)
---
base-commit: 95c541ddfb0815a0ea8477af778bb13bb075079a
change-id: 20260408-enable-ice-clock-scaling-5ca54ed63179
prerequisite-message-id: <20260323-qcom_ice_power_and_clk_vote-v4-0-e36044bbdfe9@oss.qualcomm.com>
prerequisite-patch-id: 1750aded4cac0105fbf943c5bfd9f844acf4f227
prerequisite-patch-id: 8cf945709b92296c73859515bb67820360d785a2
prerequisite-patch-id: bc8821cbbe222f208c5d86d96f3640c169b972d6
prerequisite-patch-id: a1baf04d3cce803fcb47b1a80591bf7759de8a76
prerequisite-patch-id: b7de0f216e54e264e054f6333b3067abce8d05c5
prerequisite-patch-id: 57f21e8a9505564caebbf89cafa9bd80be1dfe9f
prerequisite-patch-id: 5128586130e3f5847e0417de47ef755b2e2fba93
prerequisite-patch-id: fa46b7d6710907c5eb5ad01e84d28f09a0b26e5a
prerequisite-patch-id: e375d6e54a55c055f5d8673c65d35073df396646
prerequisite-patch-id: ec670d98300863c4b68155a3b0feeace56a4a55a
prerequisite-patch-id: c5ee690afd7f7105963e991dff760de62a403d9b
prerequisite-message-id: <20260310113557.348502-1-neeraj.soni@oss.qualcomm.com>
prerequisite-patch-id: ab9cc8bd28b2e1e27df6e44907e8d758dfeee3df
prerequisite-patch-id: 40f239f7f06573ed45452249f444e54e3565ada7
prerequisite-patch-id: 59129ed0aeba84f6b50f42261d51fe323806a240
prerequisite-message-id: <20260409-ice_emmc_clock_addition-v2-0-90bbcc057361@oss.qualcomm.com>
prerequisite-patch-id: 5b6a436bd949a93e44f912d2565103f6bf0ef55a
prerequisite-patch-id: 7f9ff2b708418a77578e154102f72f0da243eb71

Best regards,
-- 
Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE
  2026-04-09 11:44 [PATCH v8 0/5] Enable ICE clock scaling Abhinaba Rakshit
@ 2026-04-09 11:44 ` Abhinaba Rakshit
  2026-04-17 13:25   ` Harshal Dev
  2026-04-09 11:44 ` [PATCH v8 2/5] ufs: host: Add ICE clock scaling during UFS clock changes Abhinaba Rakshit
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-09 11:44 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Abhinaba Rakshit

Register optional operation-points-v2 table for ICE device
during device probe. Attach the OPP-table with only the ICE
core clock. Since, dtbinding is on a trasition phase to include
iface clock and clock-names, attaching the opp-table to core clock
remains options such that it does not cause probe failures.

Introduce clock scaling API qcom_ice_scale_clk which scale ICE
core clock based on the target frequency provided and if a valid
OPP-table is registered. Use round_ceil passed to decide on the
rounding of the clock freq against OPP-table. Clock scaling is
disabled when a valid OPP-table is not registered.

This ensures when an ICE-device specific OPP table is available,
use the PM OPP framework to manage frequency scaling and maintain
proper power-domain constraints.

Also, ensure to drop the votes in suspend to prevent power/thermal
retention. Subsequently restore the frequency in resume from
core_clk_freq which stores the last ICE core clock operating frequency.

Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
---
 drivers/soc/qcom/ice.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/soc/qcom/ice.h |  2 ++
 2 files changed, 94 insertions(+)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index bf4ab2d9e5c0360d8fe6135cc35f93b6b09e7a0e..9e869e6abc6300c7608b4d9a18e7f3e80c93f5e7 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 
 #include <linux/firmware/qcom/qcom_scm.h>
 
@@ -112,6 +113,8 @@ struct qcom_ice {
 	bool use_hwkm;
 	bool hwkm_init_complete;
 	u8 hwkm_version;
+	unsigned long core_clk_freq;
+	bool has_opp;
 };
 
 static bool qcom_ice_check_supported(struct qcom_ice *ice)
@@ -311,6 +314,10 @@ int qcom_ice_resume(struct qcom_ice *ice)
 	struct device *dev = ice->dev;
 	int err;
 
+	/* Restore the ICE core clk freq */
+	if (ice->has_opp && ice->core_clk_freq)
+		dev_pm_opp_set_rate(ice->dev, ice->core_clk_freq);
+
 	err = clk_prepare_enable(ice->core_clk);
 	if (err) {
 		dev_err(dev, "Failed to enable core clock: %d\n", err);
@@ -331,6 +338,11 @@ int qcom_ice_suspend(struct qcom_ice *ice)
 {
 	clk_disable_unprepare(ice->iface_clk);
 	clk_disable_unprepare(ice->core_clk);
+
+	/* Drop the clock votes while suspend */
+	if (ice->has_opp)
+		dev_pm_opp_set_rate(ice->dev, 0);
+
 	ice->hwkm_init_complete = false;
 
 	return 0;
@@ -556,6 +568,51 @@ int qcom_ice_import_key(struct qcom_ice *ice,
 }
 EXPORT_SYMBOL_GPL(qcom_ice_import_key);
 
+/**
+ * qcom_ice_scale_clk() - Scale ICE clock for DVFS-aware operations
+ * @ice: ICE driver data
+ * @target_freq: requested frequency in Hz
+ * @round_ceil: when true, selects nearest freq >= @target_freq;
+ *              otherwise, selects nearest freq <= @target_freq
+ *
+ * Selects an OPP frequency based on @target_freq and the rounding direction
+ * specified by @round_ceil, then programs it using dev_pm_opp_set_rate(),
+ * including any voltage or power-domain transitions handled by the OPP
+ * framework. Updates ice->core_clk_freq on success.
+ *
+ * Return: 0 on success; -EOPNOTSUPP if no OPP table; or error from
+ *         dev_pm_opp_set_rate()/OPP lookup.
+ */
+int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
+		       bool round_ceil)
+{
+	unsigned long ice_freq = target_freq;
+	struct dev_pm_opp *opp;
+	int ret;
+
+	if (!ice->has_opp)
+		return -EOPNOTSUPP;
+
+	if (round_ceil)
+		opp = dev_pm_opp_find_freq_ceil(ice->dev, &ice_freq);
+	else
+		opp = dev_pm_opp_find_freq_floor(ice->dev, &ice_freq);
+
+	if (IS_ERR(opp))
+		return PTR_ERR(opp);
+	dev_pm_opp_put(opp);
+
+	ret = dev_pm_opp_set_rate(ice->dev, ice_freq);
+	if (ret) {
+		dev_err(ice->dev, "Unable to scale ICE clock rate\n");
+		return ret;
+	}
+	ice->core_clk_freq = ice_freq;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_scale_clk);
+
 static struct qcom_ice *qcom_ice_create(struct device *dev,
 					void __iomem *base)
 {
@@ -731,6 +788,7 @@ static int qcom_ice_probe(struct platform_device *pdev)
 {
 	struct qcom_ice *engine;
 	void __iomem *base;
+	int err;
 
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base)) {
@@ -742,6 +800,40 @@ static int qcom_ice_probe(struct platform_device *pdev)
 	if (IS_ERR(engine))
 		return PTR_ERR(engine);
 
+	/* qcom_ice_create() may return NULL if scm calls are not available */
+	if (!engine)
+		return -EOPNOTSUPP;
+
+	err = devm_pm_opp_set_clkname(&pdev->dev, "core");
+	if (err && err != -ENOENT) {
+		dev_err(&pdev->dev, "Unable to set core clkname to OPP-table\n");
+		return err;
+	}
+
+	/* OPP table is optional */
+	err = devm_pm_opp_of_add_table(&pdev->dev);
+	if (err && err != -ENODEV) {
+		dev_err(&pdev->dev, "Invalid OPP table in Device tree\n");
+		return err;
+	}
+
+	/*
+	 * The OPP table is optional. devm_pm_opp_of_add_table() returns
+	 * -ENODEV when no OPP table is present in DT, which is not treated
+	 * as an error. Therefore, track successful OPP registration only
+	 * when the return value is 0.
+	 */
+	engine->has_opp = (err == 0);
+	if (!engine->has_opp)
+		dev_info(&pdev->dev, "ICE OPP table is not registered, please update your DT\n");
+
+	/*
+	 * Store the core clock rate for suspend resume cycles,
+	 * against OPP aware DVFS operations. core_clk_freq will
+	 * have a valid value only for non-legacy bindings.
+	 */
+	engine->core_clk_freq = clk_get_rate(engine->core_clk);
+
 	platform_set_drvdata(pdev, engine);
 
 	return 0;
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
index 4bee553f0a59d86ec6ce20f7c7b4bce28a706415..4eb58a264d416e71228ed4b13e7f53c549261fdc 100644
--- a/include/soc/qcom/ice.h
+++ b/include/soc/qcom/ice.h
@@ -30,5 +30,7 @@ int qcom_ice_import_key(struct qcom_ice *ice,
 			const u8 *raw_key, size_t raw_key_size,
 			u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
 struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
+int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
+		       bool round_ceil);
 
 #endif /* __QCOM_ICE_H__ */

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v8 2/5] ufs: host: Add ICE clock scaling during UFS clock changes
  2026-04-09 11:44 [PATCH v8 0/5] Enable ICE clock scaling Abhinaba Rakshit
  2026-04-09 11:44 ` [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE Abhinaba Rakshit
@ 2026-04-09 11:44 ` Abhinaba Rakshit
  2026-04-17 13:32   ` Harshal Dev
  2026-04-09 11:44 ` [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init Abhinaba Rakshit
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-09 11:44 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Abhinaba Rakshit

Implement ICE (Inline Crypto Engine) clock scaling in sync with
UFS controller clock scaling. This ensures that the ICE operates at
an appropriate frequency when the UFS clocks are scaled up or down,
improving performance and maintaining stability for crypto operations.

For scale_up operation ensure to pass ~round_ceil (round_floor)
and vice-versa for scale_down operations.

Incase of OPP scaling is not supported by ICE, ensure to not prevent
devfreq for UFS, as ICE OPP-table is optional.

Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
---
 drivers/ufs/host/ufs-qcom.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 375fd24ba458a7ef65d075ba98e5f99f4aa977c1..aceb2c42969b5d2dcddcddf0167f8824733998ec 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -306,6 +306,15 @@ static int ufs_qcom_ice_prepare_key(struct blk_crypto_profile *profile,
 	return qcom_ice_prepare_key(host->ice, lt_key, lt_key_size, eph_key);
 }
 
+static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
+				  bool round_ceil)
+{
+	if (host->hba->caps & UFSHCD_CAP_CRYPTO)
+		return qcom_ice_scale_clk(host->ice, target_freq, round_ceil);
+
+	return 0;
+}
+
 static const struct blk_crypto_ll_ops ufs_qcom_crypto_ops = {
 	.keyslot_program	= ufs_qcom_ice_keyslot_program,
 	.keyslot_evict		= ufs_qcom_ice_keyslot_evict,
@@ -340,6 +349,12 @@ static void ufs_qcom_config_ice_allocator(struct ufs_qcom_host *host)
 {
 }
 
+static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
+				  bool round_ceil)
+{
+	return 0;
+}
+
 #endif
 
 static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
@@ -1743,12 +1758,17 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
 		else
 			err = ufs_qcom_clk_scale_down_post_change(hba, target_freq);
 
-
 		if (err) {
 			ufshcd_uic_hibern8_exit(hba);
 			return err;
 		}
 
+		err = ufs_qcom_ice_scale_clk(host, target_freq, !scale_up);
+		if (err && err != -EOPNOTSUPP) {
+			ufshcd_uic_hibern8_exit(hba);
+			return err;
+		}
+
 		ufs_qcom_icc_update_bw(host);
 		ufshcd_uic_hibern8_exit(hba);
 	}

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init
  2026-04-09 11:44 [PATCH v8 0/5] Enable ICE clock scaling Abhinaba Rakshit
  2026-04-09 11:44 ` [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE Abhinaba Rakshit
  2026-04-09 11:44 ` [PATCH v8 2/5] ufs: host: Add ICE clock scaling during UFS clock changes Abhinaba Rakshit
@ 2026-04-09 11:44 ` Abhinaba Rakshit
  2026-04-17 13:29   ` Harshal Dev
  2026-04-09 11:44 ` [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes Abhinaba Rakshit
  2026-04-09 11:44 ` [PATCH v8 5/5] arm64: dts: qcom: monaco: " Abhinaba Rakshit
  4 siblings, 1 reply; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-09 11:44 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Abhinaba Rakshit, Konrad Dybcio

MMC controller lacks a clock scaling mechanism, unlike the UFS
controller. By default, the MMC controller is set to TURBO mode
during probe, but the ICE clock remains at XO frequency,
leading to read/write performance degradation on eMMC.

To address this, set the ICE clock to TURBO during sdhci_msm_ice_init
to align it with the controller clock. This ensures consistent
performance and avoids mismatches between the controller
and ICE clock frequencies.

For platforms where ICE is represented as a separate device,
use the OPP framework to vote for TURBO mode, maintaining
proper voltage and power domain constraints.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
---
 drivers/mmc/host/sdhci-msm.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index da356627d9de6a11ed5779bf057fa8eb23c38bc0..32e3f37fe425f66c00290a373e06e8ab6257824e 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1901,6 +1901,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 #ifdef CONFIG_MMC_CRYPTO
 
 static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops; /* forward decl */
+static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
+				   bool round_ceil); /* forward decl */
 
 static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
 			      struct cqhci_host *cq_host)
@@ -1964,6 +1966,11 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
 	}
 
 	mmc->caps2 |= MMC_CAP2_CRYPTO;
+
+	err = sdhci_msm_ice_scale_clk(msm_host, INT_MAX, false);
+	if (err && err != -EOPNOTSUPP)
+		dev_warn(dev, "Unable to boost ICE clock to TURBO\n");
+
 	return 0;
 }
 
@@ -1989,6 +1996,16 @@ static int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
 	return 0;
 }
 
+static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host,
+				   unsigned long target_freq,
+				   bool round_ceil)
+{
+	if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
+		return qcom_ice_scale_clk(msm_host->ice, target_freq, round_ceil);
+
+	return 0;
+}
+
 static inline struct sdhci_msm_host *
 sdhci_msm_host_from_crypto_profile(struct blk_crypto_profile *profile)
 {
@@ -2114,6 +2131,13 @@ sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
 {
 	return 0;
 }
+
+static inline int
+sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
+			bool round_ceil)
+{
+	return 0;
+}
 #endif /* !CONFIG_MMC_CRYPTO */
 
 /*****************************************************************************\

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes
  2026-04-09 11:44 [PATCH v8 0/5] Enable ICE clock scaling Abhinaba Rakshit
                   ` (2 preceding siblings ...)
  2026-04-09 11:44 ` [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init Abhinaba Rakshit
@ 2026-04-09 11:44 ` Abhinaba Rakshit
  2026-04-10 10:53   ` Kuldeep Singh
  2026-04-09 11:44 ` [PATCH v8 5/5] arm64: dts: qcom: monaco: " Abhinaba Rakshit
  4 siblings, 1 reply; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-09 11:44 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Abhinaba Rakshit

Qualcomm Inline Crypto Engine (ICE) platform driver now, supports
an optional OPP-table.

Add OPP-table for ICE UFS and ICE eMMC device nodes for Kodiak
platform.

Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/kodiak.dtsi | 42 ++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi
index c899a17026fd2a10ebc528a816629c88ee3bde5d..b0aa1970d42a3bb0b9d371e0e6cd09b8cd164dbe 100644
--- a/arch/arm64/boot/dts/qcom/kodiak.dtsi
+++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi
@@ -1087,6 +1087,27 @@ sdhc_ice: crypto@7c8000 {
 			clock-names = "core",
 				      "iface";
 			power-domains = <&rpmhpd SC7280_CX>;
+
+			operating-points-v2 = <&ice_mmc_opp_table>;
+
+			ice_mmc_opp_table: opp-table {
+				compatible = "operating-points-v2";
+
+				opp-100000000 {
+					opp-hz = /bits/ 64 <100000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+				};
+
+				opp-150000000 {
+					opp-hz = /bits/ 64 <150000000>;
+					required-opps = <&rpmhpd_opp_svs>;
+				};
+
+				opp-300000000 {
+					opp-hz = /bits/ 64 <300000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+				};
+			};
 		};
 
 		gpi_dma0: dma-controller@900000 {
@@ -2597,6 +2618,27 @@ ice: crypto@1d88000 {
 			clock-names = "core",
 				      "iface";
 			power-domains = <&gcc GCC_UFS_PHY_GDSC>;
+
+			operating-points-v2 = <&ice_opp_table>;
+
+			ice_opp_table: opp-table {
+				compatible = "operating-points-v2";
+
+				opp-75000000 {
+					opp-hz = /bits/ 64 <75000000>;
+					required-opps = <&rpmhpd_opp_low_svs>;
+				};
+
+				opp-150000000 {
+					opp-hz = /bits/ 64 <150000000>;
+					required-opps = <&rpmhpd_opp_svs>;
+				};
+
+				opp-300000000 {
+					opp-hz = /bits/ 64 <300000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+				};
+			};
 		};
 
 		cryptobam: dma-controller@1dc4000 {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v8 5/5] arm64: dts: qcom: monaco: Add OPP-table for ICE UFS and ICE eMMC nodes
  2026-04-09 11:44 [PATCH v8 0/5] Enable ICE clock scaling Abhinaba Rakshit
                   ` (3 preceding siblings ...)
  2026-04-09 11:44 ` [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes Abhinaba Rakshit
@ 2026-04-09 11:44 ` Abhinaba Rakshit
  2026-04-10 10:57   ` Kuldeep Singh
  4 siblings, 1 reply; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-09 11:44 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Abhinaba Rakshit

Qualcomm Inline Crypto Engine (ICE) platform driver now, supports
an optional OPP-table.

Add OPP-table for ICE UFS and ICE eMMC device nodes for Monaco
platform.

Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/monaco.dtsi | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
index 487bb682ae8620b819f022162edd11023ed07be8..cb0e554e94d237b0adccb55fa9ed967bae9eea05 100644
--- a/arch/arm64/boot/dts/qcom/monaco.dtsi
+++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
@@ -2730,6 +2730,22 @@ ice: crypto@1d88000 {
 			clock-names = "core",
 				      "iface";
 			power-domains = <&gcc GCC_UFS_PHY_GDSC>;
+
+			operating-points-v2 = <&ice_opp_table>;
+
+			ice_opp_table: opp-table {
+				compatible = "operating-points-v2";
+
+				opp-201600000 {
+					opp-hz = /bits/ 64 <201600000>;
+					required-opps = <&rpmhpd_opp_svs_l1>;
+				};
+
+				opp-403200000 {
+					opp-hz = /bits/ 64 <403200000>;
+					required-opps = <&rpmhpd_opp_nom>;
+				};
+			};
 		};
 
 		crypto: crypto@1dfa000 {
@@ -4797,6 +4813,22 @@ sdhc_ice: crypto@87c8000 {
 			clock-names = "core",
 				      "iface";
 			power-domains = <&rpmhpd RPMHPD_CX>;
+
+			operating-points-v2 = <&ice_mmc_opp_table>;
+
+			ice_mmc_opp_table: opp-table {
+				compatible = "operating-points-v2";
+
+				opp-150000000 {
+					opp-hz = /bits/ 64 <150000000>;
+					required-opps = <&rpmhpd_opp_svs_l1>;
+				};
+
+				opp-300000000 {
+					opp-hz = /bits/ 64 <300000000>;
+					required-opps = <&rpmhpd_opp_nom>;
+				};
+			};
 		};
 
 		usb_1_hsphy: phy@8904000 {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes
  2026-04-09 11:44 ` [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes Abhinaba Rakshit
@ 2026-04-10 10:53   ` Kuldeep Singh
  2026-04-21  5:58     ` Abhinaba Rakshit
  0 siblings, 1 reply; 15+ messages in thread
From: Kuldeep Singh @ 2026-04-10 10:53 UTC (permalink / raw)
  To: Abhinaba Rakshit, Bjorn Andersson, Konrad Dybcio,
	Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
	Adrian Hunter, Ulf Hansson, Neeraj Soni, Harshal Dev, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree

On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> Qualcomm Inline Crypto Engine (ICE) platform driver now, supports
> an optional OPP-table.
> 
> Add OPP-table for ICE UFS and ICE eMMC device nodes for Kodiak
> platform.
> 
> Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> ---
>  arch/arm64/boot/dts/qcom/kodiak.dtsi | 42 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi
> index c899a17026fd2a10ebc528a816629c88ee3bde5d..b0aa1970d42a3bb0b9d371e0e6cd09b8cd164dbe 100644
> --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi
> +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi
> @@ -1087,6 +1087,27 @@ sdhc_ice: crypto@7c8000 {
>  			clock-names = "core",
>  				      "iface";
>  			power-domains = <&rpmhpd SC7280_CX>;
> +
> +			operating-points-v2 = <&ice_mmc_opp_table>;
> +
> +			ice_mmc_opp_table: opp-table {
> +				compatible = "operating-points-v2";
> +
> +				opp-100000000 {
> +					opp-hz = /bits/ 64 <100000000>;
> +					required-opps = <&rpmhpd_opp_low_svs>;
> +				};
> +
> +				opp-150000000 {
> +					opp-hz = /bits/ 64 <150000000>;
> +					required-opps = <&rpmhpd_opp_svs>;
> +				};
> +
> +				opp-300000000 {
> +					opp-hz = /bits/ 64 <300000000>;
> +					required-opps = <&rpmhpd_opp_nom>;

As per hardware spec, 300MHz is supported by SVS_L1.

-- 
Regards
Kuldeep


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 5/5] arm64: dts: qcom: monaco: Add OPP-table for ICE UFS and ICE eMMC nodes
  2026-04-09 11:44 ` [PATCH v8 5/5] arm64: dts: qcom: monaco: " Abhinaba Rakshit
@ 2026-04-10 10:57   ` Kuldeep Singh
  2026-04-21  5:50     ` Abhinaba Rakshit
  0 siblings, 1 reply; 15+ messages in thread
From: Kuldeep Singh @ 2026-04-10 10:57 UTC (permalink / raw)
  To: Abhinaba Rakshit, Bjorn Andersson, Konrad Dybcio,
	Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
	Adrian Hunter, Ulf Hansson, Neeraj Soni, Harshal Dev, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree



On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> Qualcomm Inline Crypto Engine (ICE) platform driver now, supports
> an optional OPP-table.
> 
> Add OPP-table for ICE UFS and ICE eMMC device nodes for Monaco
> platform.
> 
> Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> ---
>  arch/arm64/boot/dts/qcom/monaco.dtsi | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
> index 487bb682ae8620b819f022162edd11023ed07be8..cb0e554e94d237b0adccb55fa9ed967bae9eea05 100644
> --- a/arch/arm64/boot/dts/qcom/monaco.dtsi
> +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
> @@ -2730,6 +2730,22 @@ ice: crypto@1d88000 {
>  			clock-names = "core",
>  				      "iface";
>  			power-domains = <&gcc GCC_UFS_PHY_GDSC>;
> +
> +			operating-points-v2 = <&ice_opp_table>;
> +
> +			ice_opp_table: opp-table {
> +				compatible = "operating-points-v2";
> +

75MHz is supported too. Please add that entry.

> +				opp-201600000 {
> +					opp-hz = /bits/ 64 <201600000>;
> +					required-opps = <&rpmhpd_opp_svs_l1>;
> +				};
> +
> +				opp-403200000 {
> +					opp-hz = /bits/ 64 <403200000>;
> +					required-opps = <&rpmhpd_opp_nom>;
> +				};
> +			};
>  		};

-- 
Regards
Kuldeep


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE
  2026-04-09 11:44 ` [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE Abhinaba Rakshit
@ 2026-04-17 13:25   ` Harshal Dev
  2026-04-21  6:06     ` Abhinaba Rakshit
  0 siblings, 1 reply; 15+ messages in thread
From: Harshal Dev @ 2026-04-17 13:25 UTC (permalink / raw)
  To: Abhinaba Rakshit, Bjorn Andersson, Konrad Dybcio,
	Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
	Adrian Hunter, Ulf Hansson, Neeraj Soni, Kuldeep Singh,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree



On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> Register optional operation-points-v2 table for ICE device
> during device probe. Attach the OPP-table with only the ICE
> core clock. Since, dtbinding is on a trasition phase to include
> iface clock and clock-names, attaching the opp-table to core clock
> remains options such that it does not cause probe failures.
> 
> Introduce clock scaling API qcom_ice_scale_clk which scale ICE
> core clock based on the target frequency provided and if a valid
> OPP-table is registered. Use round_ceil passed to decide on the
> rounding of the clock freq against OPP-table. Clock scaling is
> disabled when a valid OPP-table is not registered.
> 
> This ensures when an ICE-device specific OPP table is available,
> use the PM OPP framework to manage frequency scaling and maintain
> proper power-domain constraints.
> 
> Also, ensure to drop the votes in suspend to prevent power/thermal
> retention. Subsequently restore the frequency in resume from
> core_clk_freq which stores the last ICE core clock operating frequency.
> 
> Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> ---
>  drivers/soc/qcom/ice.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/soc/qcom/ice.h |  2 ++
>  2 files changed, 94 insertions(+)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index bf4ab2d9e5c0360d8fe6135cc35f93b6b09e7a0e..9e869e6abc6300c7608b4d9a18e7f3e80c93f5e7 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -16,6 +16,7 @@

[..]

> @@ -742,6 +800,40 @@ static int qcom_ice_probe(struct platform_device *pdev)
>  	if (IS_ERR(engine))
>  		return PTR_ERR(engine);
>  
> +	/* qcom_ice_create() may return NULL if scm calls are not available */
> +	if (!engine)
> +		return -EOPNOTSUPP;
> +
> +	err = devm_pm_opp_set_clkname(&pdev->dev, "core");
> +	if (err && err != -ENOENT) {
> +		dev_err(&pdev->dev, "Unable to set core clkname to OPP-table\n");
> +		return err;
> +	}
> +
> +	/* OPP table is optional */
> +	err = devm_pm_opp_of_add_table(&pdev->dev);
> +	if (err && err != -ENODEV) {
> +		dev_err(&pdev->dev, "Invalid OPP table in Device tree\n");
> +		return err;
> +	}
> +
> +	/*
> +	 * The OPP table is optional. devm_pm_opp_of_add_table() returns
> +	 * -ENODEV when no OPP table is present in DT, which is not treated
> +	 * as an error. Therefore, track successful OPP registration only
> +	 * when the return value is 0.
> +	 */
> +	engine->has_opp = (err == 0);
> +	if (!engine->has_opp)
> +		dev_info(&pdev->dev, "ICE OPP table is not registered, please update your DT\n");
> +
> +	/*
> +	 * Store the core clock rate for suspend resume cycles,
> +	 * against OPP aware DVFS operations. core_clk_freq will
> +	 * have a valid value only for non-legacy bindings.
> +	 */
> +	engine->core_clk_freq = clk_get_rate(engine->core_clk);
> +

When you are calling 4-5 functions in a function, it's probably time to define another
function to keep things simple. Maybe qcom_ice_attach_opp_table().

Also, I still have issues with engine->has_opp = (err == 0), mostly because I don't
see this style used at other placed in the kernel. I would still suggest that you
make it simpler, but I won't hard-request it.

/* The same explanatory comment as before */
if (err == -ENODEV)
	engine->has_opp = false;
        dev_info(...);
else
	engine->has_opp = true;

With these optional suggestions, feel free to add:

Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>


>  	platform_set_drvdata(pdev, engine);
>  
>  	return 0;
> diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
> index 4bee553f0a59d86ec6ce20f7c7b4bce28a706415..4eb58a264d416e71228ed4b13e7f53c549261fdc 100644
> --- a/include/soc/qcom/ice.h
> +++ b/include/soc/qcom/ice.h
> @@ -30,5 +30,7 @@ int qcom_ice_import_key(struct qcom_ice *ice,
>  			const u8 *raw_key, size_t raw_key_size,
>  			u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
>  struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
> +int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
> +		       bool round_ceil);
>  
>  #endif /* __QCOM_ICE_H__ */
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init
  2026-04-09 11:44 ` [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init Abhinaba Rakshit
@ 2026-04-17 13:29   ` Harshal Dev
  2026-04-21  6:10     ` Abhinaba Rakshit
  0 siblings, 1 reply; 15+ messages in thread
From: Harshal Dev @ 2026-04-17 13:29 UTC (permalink / raw)
  To: Abhinaba Rakshit, Bjorn Andersson, Konrad Dybcio,
	Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
	Adrian Hunter, Ulf Hansson, Neeraj Soni, Kuldeep Singh,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree,
	Konrad Dybcio



On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> MMC controller lacks a clock scaling mechanism, unlike the UFS
> controller. By default, the MMC controller is set to TURBO mode
> during probe, but the ICE clock remains at XO frequency,
> leading to read/write performance degradation on eMMC.
> 
> To address this, set the ICE clock to TURBO during sdhci_msm_ice_init
> to align it with the controller clock. This ensures consistent
> performance and avoids mismatches between the controller
> and ICE clock frequencies.
> 
> For platforms where ICE is represented as a separate device,
> use the OPP framework to vote for TURBO mode, maintaining
> proper voltage and power domain constraints.
> 
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> ---
>  drivers/mmc/host/sdhci-msm.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 

[...]

>  
>  static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops; /* forward decl */
> +static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
> +				   bool round_ceil); /* forward decl */
>  
>  static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
>  			      struct cqhci_host *cq_host)
> @@ -1964,6 +1966,11 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
>  	}
>  
>  	mmc->caps2 |= MMC_CAP2_CRYPTO;
> +
> +	err = sdhci_msm_ice_scale_clk(msm_host, INT_MAX, false);

The 2nd parameter is an unsigned long, do you really want to pass INT_MAX here? I would go with
UINT_MAX. But still, why go with such a high value? Do we not have an upper bound for the clk
frequency that we know we can't ever exceed for any target across OPP tables? If not, then maybe
UINT_MAX is best we can do here.

Regards,
Harshal

> +	if (err && err != -EOPNOTSUPP)
> +		dev_warn(dev, "Unable to boost ICE clock to TURBO\n");
> +
>  	return 0;
>  }
>  
> @@ -1989,6 +1996,16 @@ static int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
>  	return 0;
>  }
>  
> +static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host,
> +				   unsigned long target_freq,
> +				   bool round_ceil)
> +{
> +	if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
> +		return qcom_ice_scale_clk(msm_host->ice, target_freq, round_ceil);
> +
> +	return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 2/5] ufs: host: Add ICE clock scaling during UFS clock changes
  2026-04-09 11:44 ` [PATCH v8 2/5] ufs: host: Add ICE clock scaling during UFS clock changes Abhinaba Rakshit
@ 2026-04-17 13:32   ` Harshal Dev
  0 siblings, 0 replies; 15+ messages in thread
From: Harshal Dev @ 2026-04-17 13:32 UTC (permalink / raw)
  To: Abhinaba Rakshit, Bjorn Andersson, Konrad Dybcio,
	Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
	Adrian Hunter, Ulf Hansson, Neeraj Soni, Kuldeep Singh,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-kernel, linux-scsi, linux-mmc, devicetree



On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> Implement ICE (Inline Crypto Engine) clock scaling in sync with
> UFS controller clock scaling. This ensures that the ICE operates at
> an appropriate frequency when the UFS clocks are scaled up or down,
> improving performance and maintaining stability for crypto operations.
> 
> For scale_up operation ensure to pass ~round_ceil (round_floor)
> and vice-versa for scale_down operations.
> 
> Incase of OPP scaling is not supported by ICE, ensure to not prevent
> devfreq for UFS, as ICE OPP-table is optional.
> 
> Acked-by: Manivannan Sadhasivam <mani@kernel.org>
> Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> ---
Whoops, I mistakenly replied to v7 of this patch with a Reviewed-by, please
ignore that one.

Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>

Regards,
Harshal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 5/5] arm64: dts: qcom: monaco: Add OPP-table for ICE UFS and ICE eMMC nodes
  2026-04-10 10:57   ` Kuldeep Singh
@ 2026-04-21  5:50     ` Abhinaba Rakshit
  0 siblings, 0 replies; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-21  5:50 UTC (permalink / raw)
  To: Kuldeep Singh
  Cc: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, linux-kernel,
	linux-scsi, linux-mmc, devicetree

On Fri, Apr 10, 2026 at 04:27:35PM +0530, Kuldeep Singh wrote:
> 
> 
> On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> > Qualcomm Inline Crypto Engine (ICE) platform driver now, supports
> > an optional OPP-table.
> > 
> > Add OPP-table for ICE UFS and ICE eMMC device nodes for Monaco
> > platform.
> > 
> > Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> > ---
> >  arch/arm64/boot/dts/qcom/monaco.dtsi | 32 ++++++++++++++++++++++++++++++++
> >  1 file changed, 32 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
> > index 487bb682ae8620b819f022162edd11023ed07be8..cb0e554e94d237b0adccb55fa9ed967bae9eea05 100644
> > --- a/arch/arm64/boot/dts/qcom/monaco.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
> > @@ -2730,6 +2730,22 @@ ice: crypto@1d88000 {
> >  			clock-names = "core",
> >  				      "iface";
> >  			power-domains = <&gcc GCC_UFS_PHY_GDSC>;
> > +
> > +			operating-points-v2 = <&ice_opp_table>;
> > +
> > +			ice_opp_table: opp-table {
> > +				compatible = "operating-points-v2";
> > +
> 
> 75MHz is supported too. Please add that entry.

Sure, will add the entry in the next patchset.

Abhinaba Rakshit 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes
  2026-04-10 10:53   ` Kuldeep Singh
@ 2026-04-21  5:58     ` Abhinaba Rakshit
  0 siblings, 0 replies; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-21  5:58 UTC (permalink / raw)
  To: Kuldeep Singh
  Cc: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Harshal Dev, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, linux-kernel,
	linux-scsi, linux-mmc, devicetree

On Fri, Apr 10, 2026 at 04:23:51PM +0530, Kuldeep Singh wrote:
> On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> > Qualcomm Inline Crypto Engine (ICE) platform driver now, supports
> > an optional OPP-table.
> > 
> > Add OPP-table for ICE UFS and ICE eMMC device nodes for Kodiak
> > platform.
> > 
> > Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> > ---
> >  arch/arm64/boot/dts/qcom/kodiak.dtsi | 42 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 42 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi
> > index c899a17026fd2a10ebc528a816629c88ee3bde5d..b0aa1970d42a3bb0b9d371e0e6cd09b8cd164dbe 100644
> > --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi
> > @@ -1087,6 +1087,27 @@ sdhc_ice: crypto@7c8000 {
> >  			clock-names = "core",
> >  				      "iface";
> >  			power-domains = <&rpmhpd SC7280_CX>;
> > +
> > +			operating-points-v2 = <&ice_mmc_opp_table>;
> > +
> > +			ice_mmc_opp_table: opp-table {
> > +				compatible = "operating-points-v2";
> > +
> > +				opp-100000000 {
> > +					opp-hz = /bits/ 64 <100000000>;
> > +					required-opps = <&rpmhpd_opp_low_svs>;
> > +				};
> > +
> > +				opp-150000000 {
> > +					opp-hz = /bits/ 64 <150000000>;
> > +					required-opps = <&rpmhpd_opp_svs>;
> > +				};
> > +
> > +				opp-300000000 {
> > +					opp-hz = /bits/ 64 <300000000>;
> > +					required-opps = <&rpmhpd_opp_nom>;
> 
> As per hardware spec, 300MHz is supported by SVS_L1.

Sure, will update this in next patchset.

Abhinaba Rakshit

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE
  2026-04-17 13:25   ` Harshal Dev
@ 2026-04-21  6:06     ` Abhinaba Rakshit
  0 siblings, 0 replies; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-21  6:06 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, linux-kernel,
	linux-scsi, linux-mmc, devicetree

On Fri, Apr 17, 2026 at 06:55:14PM +0530, Harshal Dev wrote:
> 
> 
> On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> > Register optional operation-points-v2 table for ICE device
> > during device probe. Attach the OPP-table with only the ICE
> > core clock. Since, dtbinding is on a trasition phase to include
> > iface clock and clock-names, attaching the opp-table to core clock
> > remains options such that it does not cause probe failures.
> > 
> > Introduce clock scaling API qcom_ice_scale_clk which scale ICE
> > core clock based on the target frequency provided and if a valid
> > OPP-table is registered. Use round_ceil passed to decide on the
> > rounding of the clock freq against OPP-table. Clock scaling is
> > disabled when a valid OPP-table is not registered.
> > 
> > This ensures when an ICE-device specific OPP table is available,
> > use the PM OPP framework to manage frequency scaling and maintain
> > proper power-domain constraints.
> > 
> > Also, ensure to drop the votes in suspend to prevent power/thermal
> > retention. Subsequently restore the frequency in resume from
> > core_clk_freq which stores the last ICE core clock operating frequency.
> > 
> > Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> > ---
> >  drivers/soc/qcom/ice.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/soc/qcom/ice.h |  2 ++
> >  2 files changed, 94 insertions(+)
> > 
> > diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> > index bf4ab2d9e5c0360d8fe6135cc35f93b6b09e7a0e..9e869e6abc6300c7608b4d9a18e7f3e80c93f5e7 100644
> > --- a/drivers/soc/qcom/ice.c
> > +++ b/drivers/soc/qcom/ice.c
> > @@ -16,6 +16,7 @@
> 
> [..]
> 
> > @@ -742,6 +800,40 @@ static int qcom_ice_probe(struct platform_device *pdev)
> >  	if (IS_ERR(engine))
> >  		return PTR_ERR(engine);
> >  
> > +	/* qcom_ice_create() may return NULL if scm calls are not available */
> > +	if (!engine)
> > +		return -EOPNOTSUPP;
> > +
> > +	err = devm_pm_opp_set_clkname(&pdev->dev, "core");
> > +	if (err && err != -ENOENT) {
> > +		dev_err(&pdev->dev, "Unable to set core clkname to OPP-table\n");
> > +		return err;
> > +	}
> > +
> > +	/* OPP table is optional */
> > +	err = devm_pm_opp_of_add_table(&pdev->dev);
> > +	if (err && err != -ENODEV) {
> > +		dev_err(&pdev->dev, "Invalid OPP table in Device tree\n");
> > +		return err;
> > +	}
> > +
> > +	/*
> > +	 * The OPP table is optional. devm_pm_opp_of_add_table() returns
> > +	 * -ENODEV when no OPP table is present in DT, which is not treated
> > +	 * as an error. Therefore, track successful OPP registration only
> > +	 * when the return value is 0.
> > +	 */
> > +	engine->has_opp = (err == 0);
> > +	if (!engine->has_opp)
> > +		dev_info(&pdev->dev, "ICE OPP table is not registered, please update your DT\n");
> > +
> > +	/*
> > +	 * Store the core clock rate for suspend resume cycles,
> > +	 * against OPP aware DVFS operations. core_clk_freq will
> > +	 * have a valid value only for non-legacy bindings.
> > +	 */
> > +	engine->core_clk_freq = clk_get_rate(engine->core_clk);
> > +
> 
> When you are calling 4-5 functions in a function, it's probably time to define another
> function to keep things simple. Maybe qcom_ice_attach_opp_table().
> 
> Also, I still have issues with engine->has_opp = (err == 0), mostly because I don't
> see this style used at other placed in the kernel. I would still suggest that you
> make it simpler, but I won't hard-request it.
> 
> /* The same explanatory comment as before */
> if (err == -ENODEV)
> 	engine->has_opp = false;
>         dev_info(...);
> else
> 	engine->has_opp = true;
> 
> With these optional suggestions, feel free to add:
> 
> Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>

Thanks for the review.

Regarding the points you mentioned:
At the moment, not much is happening here beyond registering the OPP table and
caching the core clock rate. This is executed once per device probe, and the logic
is fairly localized to the ICE probe path. Because of that, it didn’t feel like its
reusable or demands its own helper.
That said, I do see your point about modularity. If this logic grows further, or if
we end up needing the same sequence elsewhere, I agree it would make sense to factor
it out into a separate function at that time.

Regarding engine->has_opp = (err == 0), I understand your concern.
However, I intend to keep it this way, as it keeps the flow consise avoiding much of
if-else branching and also serves the purpose.

Abhinaba Rakshit

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init
  2026-04-17 13:29   ` Harshal Dev
@ 2026-04-21  6:10     ` Abhinaba Rakshit
  0 siblings, 0 replies; 15+ messages in thread
From: Abhinaba Rakshit @ 2026-04-21  6:10 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Bjorn Andersson, Konrad Dybcio, Manivannan Sadhasivam,
	James E.J. Bottomley, Martin K. Petersen, Adrian Hunter,
	Ulf Hansson, Neeraj Soni, Kuldeep Singh, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, linux-kernel,
	linux-scsi, linux-mmc, devicetree, Konrad Dybcio

On Fri, Apr 17, 2026 at 06:59:42PM +0530, Harshal Dev wrote:
> 
> 
> On 4/9/2026 5:14 PM, Abhinaba Rakshit wrote:
> > MMC controller lacks a clock scaling mechanism, unlike the UFS
> > controller. By default, the MMC controller is set to TURBO mode
> > during probe, but the ICE clock remains at XO frequency,
> > leading to read/write performance degradation on eMMC.
> > 
> > To address this, set the ICE clock to TURBO during sdhci_msm_ice_init
> > to align it with the controller clock. This ensures consistent
> > performance and avoids mismatches between the controller
> > and ICE clock frequencies.
> > 
> > For platforms where ICE is represented as a separate device,
> > use the OPP framework to vote for TURBO mode, maintaining
> > proper voltage and power domain constraints.
> > 
> > Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> > Signed-off-by: Abhinaba Rakshit <abhinaba.rakshit@oss.qualcomm.com>
> > ---
> >  drivers/mmc/host/sdhci-msm.c | 24 ++++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> > 
> 
> [...]
> 
> >  
> >  static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops; /* forward decl */
> > +static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
> > +				   bool round_ceil); /* forward decl */
> >  
> >  static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
> >  			      struct cqhci_host *cq_host)
> > @@ -1964,6 +1966,11 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
> >  	}
> >  
> >  	mmc->caps2 |= MMC_CAP2_CRYPTO;
> > +
> > +	err = sdhci_msm_ice_scale_clk(msm_host, INT_MAX, false);
> 
> The 2nd parameter is an unsigned long, do you really want to pass INT_MAX here? I would go with
> UINT_MAX. But still, why go with such a high value? Do we not have an upper bound for the clk
> frequency that we know we can't ever exceed for any target across OPP tables? If not, then maybe
> UINT_MAX is best we can do here.

Ack.
The scaling functions along with the OPP-helpers clamps the requested frequency to the
maximum supported rate based on the clock/OPP table, so any sufficiently large value serves
the purpose here.
Frequencies are better represented as unsigned long values hence, will update it with
something ULONG_MAX in the next patchset.

Abhinaba Rakshit

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-04-21  6:10 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-09 11:44 [PATCH v8 0/5] Enable ICE clock scaling Abhinaba Rakshit
2026-04-09 11:44 ` [PATCH v8 1/5] soc: qcom: ice: Add OPP-based clock scaling support for ICE Abhinaba Rakshit
2026-04-17 13:25   ` Harshal Dev
2026-04-21  6:06     ` Abhinaba Rakshit
2026-04-09 11:44 ` [PATCH v8 2/5] ufs: host: Add ICE clock scaling during UFS clock changes Abhinaba Rakshit
2026-04-17 13:32   ` Harshal Dev
2026-04-09 11:44 ` [PATCH v8 3/5] mmc: sdhci-msm: Set ICE clk to TURBO at sdhci ICE init Abhinaba Rakshit
2026-04-17 13:29   ` Harshal Dev
2026-04-21  6:10     ` Abhinaba Rakshit
2026-04-09 11:44 ` [PATCH v8 4/5] arm64: dts: qcom: kodiak: Add OPP-table for ICE UFS and ICE eMMC nodes Abhinaba Rakshit
2026-04-10 10:53   ` Kuldeep Singh
2026-04-21  5:58     ` Abhinaba Rakshit
2026-04-09 11:44 ` [PATCH v8 5/5] arm64: dts: qcom: monaco: " Abhinaba Rakshit
2026-04-10 10:57   ` Kuldeep Singh
2026-04-21  5:50     ` Abhinaba Rakshit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox