[PATCH V1 3/3] ufs: ufs-qcom: Add support for firmware-managed resource abstraction

Ram Kumar Dwivedi posted 3 patches 2 months, 3 weeks ago
There is a newer version of this series
[PATCH V1 3/3] ufs: ufs-qcom: Add support for firmware-managed resource abstraction
Posted by Ram Kumar Dwivedi 2 months, 3 weeks ago
From: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>

Add a compatible string for SA8255p platforms where resources such as
PHY, clocks, regulators, and resets are managed by firmware through an
SCMI server. Use the SCMI power protocol to abstract these resources and
invoke power operations via runtime PM APIs (pm_runtime_get/put_sync).

Introduce vendor operations (vops) for SA8255p targets to enable SCMI-
based resource control. In this model, capabilities like clock scaling
and gating are not yet supported; these will be added incrementally.

Co-developed-by: Anjana Hari <quic_ahari@quicinc.com>
Signed-off-by: Anjana Hari <quic_ahari@quicinc.com>
Co-developed-by: Shazad Hussain <quic_shazhuss@quicinc.com>
Signed-off-by: Shazad Hussain <quic_shazhuss@quicinc.com>
Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
---
 drivers/ufs/host/ufs-qcom.c | 161 +++++++++++++++++++++++++++++++++++-
 drivers/ufs/host/ufs-qcom.h |   1 +
 2 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 8d119b3223cb..13ccf1fb2ebf 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -14,6 +14,7 @@
 #include <linux/of.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/reset-controller.h>
 #include <linux/time.h>
 #include <linux/unaligned.h>
@@ -619,6 +620,27 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
 	return err;
 }
 
+static int ufs_qcom_fw_managed_hce_enable_notify(struct ufs_hba *hba,
+						 enum ufs_notify_change_status status)
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	switch (status) {
+	case PRE_CHANGE:
+		ufs_qcom_select_unipro_mode(host);
+		break;
+	case POST_CHANGE:
+		ufs_qcom_enable_hw_clk_gating(hba);
+		ufs_qcom_ice_enable(host);
+		break;
+	default:
+		dev_err(hba->dev, "Invalid status %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
  *
@@ -789,6 +811,38 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 	return ufs_qcom_ice_resume(host);
 }
 
+static int ufs_qcom_fw_managed_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
+				       enum ufs_notify_change_status status)
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	if (status == PRE_CHANGE)
+		return 0;
+
+	if (hba->spm_lvl != UFS_PM_LVL_5) {
+		dev_err(hba->dev, "Unsupported spm level %d\n", hba->spm_lvl);
+		return -EINVAL;
+	}
+
+	pm_runtime_put_sync(hba->dev);
+
+	return ufs_qcom_ice_suspend(host);
+}
+
+static int ufs_qcom_fw_managed_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+	int err;
+
+	err = pm_runtime_resume_and_get(hba->dev);
+	if (err) {
+		dev_err(hba->dev, "PM runtime resume failed: %d\n", err);
+		return err;
+	}
+
+	return ufs_qcom_ice_resume(host);
+}
+
 static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
 {
 	if (host->dev_ref_clk_ctrl_mmio &&
@@ -1421,6 +1475,52 @@ static void ufs_qcom_exit(struct ufs_hba *hba)
 	phy_exit(host->generic_phy);
 }
 
+static int ufs_qcom_fw_managed_init(struct ufs_hba *hba)
+{
+	struct device *dev = hba->dev;
+	struct ufs_qcom_host *host;
+	int err;
+
+	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	host->hba = hba;
+	ufshcd_set_variant(hba, host);
+
+	ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
+					 &host->hw_ver.minor, &host->hw_ver.step);
+
+	err = ufs_qcom_ice_init(host);
+	if (err)
+		goto out_variant_clear;
+
+	ufs_qcom_get_default_testbus_cfg(host);
+	err = ufs_qcom_testbus_config(host);
+	if (err)
+		/* Failure is non-fatal */
+		dev_warn(dev, "Failed to configure the testbus %d\n", err);
+
+	hba->caps |= UFSHCD_CAP_WB_EN;
+
+	ufs_qcom_advertise_quirks(hba);
+	host->hba->quirks &= ~UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
+
+	ufs_qcom_set_host_params(hba);
+	ufs_qcom_parse_gear_limits(hba);
+
+	return 0;
+
+out_variant_clear:
+	ufshcd_set_variant(hba, NULL);
+	return err;
+}
+
+static void ufs_qcom_fw_managed_exit(struct ufs_hba *hba)
+{
+	pm_runtime_put_sync(hba->dev);
+}
+
 /**
  * ufs_qcom_set_clk_40ns_cycles - Configure 40ns clk cycles
  *
@@ -1952,6 +2052,39 @@ static int ufs_qcom_device_reset(struct ufs_hba *hba)
 	return 0;
 }
 
+/**
+ * ufs_qcom_fw_managed_device_reset - Reset UFS device under FW-managed design
+ * @hba: pointer to UFS host bus adapter
+ *
+ * In the firmware-managed reset model, cold boot power-on is handled
+ * automatically by the PM domain framework during SCMI protocol init,
+ * before ufshcd_device_reset() is reached. For subsequent resets
+ * (such as suspend/resume or recovery), the UFS driver must explicitly
+ * invoke PM runtime operations to reset the subsystem.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+static int ufs_qcom_fw_managed_device_reset(struct ufs_hba *hba)
+{
+	static bool is_boot = true;
+	int err;
+
+	/* Skip reset on cold boot; perform it on subsequent calls */
+	if (is_boot) {
+		is_boot = false;
+		return 0;
+	}
+
+	pm_runtime_put_sync(hba->dev);
+	err = pm_runtime_resume_and_get(hba->dev);
+	if (err < 0) {
+		dev_err(hba->dev, "PM runtime resume failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
 static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
 					struct devfreq_dev_profile *p,
 					struct devfreq_simple_ondemand_data *d)
@@ -2231,6 +2364,20 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
 	.freq_to_gear_speed	= ufs_qcom_freq_to_gear_speed,
 };
 
+static const struct ufs_hba_variant_ops ufs_hba_qcom_sa8255p_vops = {
+	.name                   = "qcom-sa8255p",
+	.init                   = ufs_qcom_fw_managed_init,
+	.exit                   = ufs_qcom_fw_managed_exit,
+	.hce_enable_notify      = ufs_qcom_fw_managed_hce_enable_notify,
+	.pwr_change_notify      = ufs_qcom_pwr_change_notify,
+	.apply_dev_quirks       = ufs_qcom_apply_dev_quirks,
+	.fixup_dev_quirks       = ufs_qcom_fixup_dev_quirks,
+	.suspend                = ufs_qcom_fw_managed_suspend,
+	.resume                 = ufs_qcom_fw_managed_resume,
+	.dbg_register_dump      = ufs_qcom_dump_dbg_regs,
+	.device_reset           = ufs_qcom_fw_managed_device_reset,
+};
+
 /**
  * ufs_qcom_probe - probe routine of the driver
  * @pdev: pointer to Platform device handle
@@ -2241,9 +2388,16 @@ static int ufs_qcom_probe(struct platform_device *pdev)
 {
 	int err;
 	struct device *dev = &pdev->dev;
+	const struct ufs_hba_variant_ops *vops;
+	const struct ufs_qcom_drvdata *drvdata = device_get_match_data(dev);
+
+	if (drvdata && drvdata->vops)
+		vops = drvdata->vops;
+	else
+		vops = &ufs_hba_qcom_vops;
 
 	/* Perform generic probe */
-	err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops);
+	err = ufshcd_pltfrm_init(pdev, vops);
 	if (err)
 		return dev_err_probe(dev, err, "ufshcd_pltfrm_init() failed\n");
 
@@ -2271,10 +2425,15 @@ static const struct ufs_qcom_drvdata ufs_qcom_sm8550_drvdata = {
 	.no_phy_retention = true,
 };
 
+static const struct ufs_qcom_drvdata ufs_qcom_sa8255p_drvdata = {
+	.vops = &ufs_hba_qcom_sa8255p_vops
+};
+
 static const struct of_device_id ufs_qcom_of_match[] __maybe_unused = {
 	{ .compatible = "qcom,ufshc" },
 	{ .compatible = "qcom,sm8550-ufshc", .data = &ufs_qcom_sm8550_drvdata },
 	{ .compatible = "qcom,sm8650-ufshc", .data = &ufs_qcom_sm8550_drvdata },
+	{ .compatible = "qcom,sa8255p-ufshc", .data = &ufs_qcom_sa8255p_drvdata },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ufs_qcom_of_match);
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 380d02333d38..1111ab34da01 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -313,6 +313,7 @@ struct ufs_qcom_host {
 struct ufs_qcom_drvdata {
 	enum ufshcd_quirks quirks;
 	bool no_phy_retention;
+	const struct ufs_hba_variant_ops *vops;
 };
 
 static inline u32
-- 
2.34.1
Re: [PATCH V1 3/3] ufs: ufs-qcom: Add support for firmware-managed resource abstraction
Posted by Manivannan Sadhasivam 2 months, 3 weeks ago
On Fri, Nov 14, 2025 at 08:26:46PM +0530, Ram Kumar Dwivedi wrote:
> From: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> 
> Add a compatible string for SA8255p platforms where resources such as
> PHY, clocks, regulators, and resets are managed by firmware through an
> SCMI server. Use the SCMI power protocol to abstract these resources and
> invoke power operations via runtime PM APIs (pm_runtime_get/put_sync).
> 
> Introduce vendor operations (vops) for SA8255p targets to enable SCMI-
> based resource control. In this model, capabilities like clock scaling
> and gating are not yet supported; these will be added incrementally.
> 
> Co-developed-by: Anjana Hari <quic_ahari@quicinc.com>
> Signed-off-by: Anjana Hari <quic_ahari@quicinc.com>
> Co-developed-by: Shazad Hussain <quic_shazhuss@quicinc.com>
> Signed-off-by: Shazad Hussain <quic_shazhuss@quicinc.com>
> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> ---
>  drivers/ufs/host/ufs-qcom.c | 161 +++++++++++++++++++++++++++++++++++-
>  drivers/ufs/host/ufs-qcom.h |   1 +
>  2 files changed, 161 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
> index 8d119b3223cb..13ccf1fb2ebf 100644
> --- a/drivers/ufs/host/ufs-qcom.c
> +++ b/drivers/ufs/host/ufs-qcom.c
> @@ -14,6 +14,7 @@
>  #include <linux/of.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
>  #include <linux/reset-controller.h>
>  #include <linux/time.h>
>  #include <linux/unaligned.h>
> @@ -619,6 +620,27 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
>  	return err;
>  }
>  
> +static int ufs_qcom_fw_managed_hce_enable_notify(struct ufs_hba *hba,
> +						 enum ufs_notify_change_status status)
> +{
> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> +
> +	switch (status) {
> +	case PRE_CHANGE:
> +		ufs_qcom_select_unipro_mode(host);
> +		break;
> +	case POST_CHANGE:
> +		ufs_qcom_enable_hw_clk_gating(hba);
> +		ufs_qcom_ice_enable(host);
> +		break;
> +	default:
> +		dev_err(hba->dev, "Invalid status %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
>   *
> @@ -789,6 +811,38 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  	return ufs_qcom_ice_resume(host);
>  }
>  
> +static int ufs_qcom_fw_managed_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
> +				       enum ufs_notify_change_status status)
> +{
> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> +
> +	if (status == PRE_CHANGE)
> +		return 0;
> +
> +	if (hba->spm_lvl != UFS_PM_LVL_5) {
> +		dev_err(hba->dev, "Unsupported spm level %d\n", hba->spm_lvl);
> +		return -EINVAL;
> +	}

You should consider moving this check to ufs-sysfs.c where the sysfs write is
handled. Failing due to unsupported suspend level at the last moment could be
avoided.

> +
> +	pm_runtime_put_sync(hba->dev);
> +
> +	return ufs_qcom_ice_suspend(host);
> +}
> +
> +static int ufs_qcom_fw_managed_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
> +{
> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> +	int err;
> +
> +	err = pm_runtime_resume_and_get(hba->dev);
> +	if (err) {
> +		dev_err(hba->dev, "PM runtime resume failed: %d\n", err);
> +		return err;
> +	}
> +
> +	return ufs_qcom_ice_resume(host);
> +}
> +
>  static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
>  {
>  	if (host->dev_ref_clk_ctrl_mmio &&
> @@ -1421,6 +1475,52 @@ static void ufs_qcom_exit(struct ufs_hba *hba)
>  	phy_exit(host->generic_phy);
>  }
>  
> +static int ufs_qcom_fw_managed_init(struct ufs_hba *hba)
> +{
> +	struct device *dev = hba->dev;
> +	struct ufs_qcom_host *host;
> +	int err;
> +
> +	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
> +	if (!host)
> +		return -ENOMEM;
> +
> +	host->hba = hba;
> +	ufshcd_set_variant(hba, host);
> +
> +	ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
> +					 &host->hw_ver.minor, &host->hw_ver.step);
> +
> +	err = ufs_qcom_ice_init(host);
> +	if (err)
> +		goto out_variant_clear;
> +
> +	ufs_qcom_get_default_testbus_cfg(host);
> +	err = ufs_qcom_testbus_config(host);
> +	if (err)
> +		/* Failure is non-fatal */
> +		dev_warn(dev, "Failed to configure the testbus %d\n", err);
> +
> +	hba->caps |= UFSHCD_CAP_WB_EN;
> +
> +	ufs_qcom_advertise_quirks(hba);
> +	host->hba->quirks &= ~UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
> +
> +	ufs_qcom_set_host_params(hba);
> +	ufs_qcom_parse_gear_limits(hba);
> +
> +	return 0;
> +
> +out_variant_clear:
> +	ufshcd_set_variant(hba, NULL);
> +	return err;
> +}
> +
> +static void ufs_qcom_fw_managed_exit(struct ufs_hba *hba)
> +{
> +	pm_runtime_put_sync(hba->dev);
> +}
> +
>  /**
>   * ufs_qcom_set_clk_40ns_cycles - Configure 40ns clk cycles
>   *
> @@ -1952,6 +2052,39 @@ static int ufs_qcom_device_reset(struct ufs_hba *hba)
>  	return 0;
>  }
>  
> +/**
> + * ufs_qcom_fw_managed_device_reset - Reset UFS device under FW-managed design

I believe this is not just device reset but both controller + device reset. So
not pretty sure that this is the right place to reset both.

- Mani

-- 
மணிவண்ணன் சதாசிவம்
Re: [PATCH V1 3/3] ufs: ufs-qcom: Add support for firmware-managed resource abstraction
Posted by Ram Kumar Dwivedi 2 months ago

On 20-Nov-25 11:23 AM, Manivannan Sadhasivam wrote:
> On Fri, Nov 14, 2025 at 08:26:46PM +0530, Ram Kumar Dwivedi wrote:
>> From: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>>
>> Add a compatible string for SA8255p platforms where resources such as
>> PHY, clocks, regulators, and resets are managed by firmware through an
>> SCMI server. Use the SCMI power protocol to abstract these resources and
>> invoke power operations via runtime PM APIs (pm_runtime_get/put_sync).
>>
>> Introduce vendor operations (vops) for SA8255p targets to enable SCMI-
>> based resource control. In this model, capabilities like clock scaling
>> and gating are not yet supported; these will be added incrementally.
>>
>> Co-developed-by: Anjana Hari <quic_ahari@quicinc.com>
>> Signed-off-by: Anjana Hari <quic_ahari@quicinc.com>
>> Co-developed-by: Shazad Hussain <quic_shazhuss@quicinc.com>
>> Signed-off-by: Shazad Hussain <quic_shazhuss@quicinc.com>
>> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>> ---
>>  drivers/ufs/host/ufs-qcom.c | 161 +++++++++++++++++++++++++++++++++++-
>>  drivers/ufs/host/ufs-qcom.h |   1 +
>>  2 files changed, 161 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
>> index 8d119b3223cb..13ccf1fb2ebf 100644
>> --- a/drivers/ufs/host/ufs-qcom.c
>> +++ b/drivers/ufs/host/ufs-qcom.c
>> @@ -14,6 +14,7 @@
>>  #include <linux/of.h>
>>  #include <linux/phy/phy.h>
>>  #include <linux/platform_device.h>
>> +#include <linux/pm_domain.h>
>>  #include <linux/reset-controller.h>
>>  #include <linux/time.h>
>>  #include <linux/unaligned.h>
>> @@ -619,6 +620,27 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
>>  	return err;
>>  }
>>  
>> +static int ufs_qcom_fw_managed_hce_enable_notify(struct ufs_hba *hba,
>> +						 enum ufs_notify_change_status status)
>> +{
>> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> +
>> +	switch (status) {
>> +	case PRE_CHANGE:
>> +		ufs_qcom_select_unipro_mode(host);
>> +		break;
>> +	case POST_CHANGE:
>> +		ufs_qcom_enable_hw_clk_gating(hba);
>> +		ufs_qcom_ice_enable(host);
>> +		break;
>> +	default:
>> +		dev_err(hba->dev, "Invalid status %d\n", status);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  /**
>>   * ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
>>   *
>> @@ -789,6 +811,38 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>>  	return ufs_qcom_ice_resume(host);
>>  }
>>  
>> +static int ufs_qcom_fw_managed_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
>> +				       enum ufs_notify_change_status status)
>> +{
>> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> +
>> +	if (status == PRE_CHANGE)
>> +		return 0;
>> +
>> +	if (hba->spm_lvl != UFS_PM_LVL_5) {
>> +		dev_err(hba->dev, "Unsupported spm level %d\n", hba->spm_lvl);
>> +		return -EINVAL;
>> +	}
> 
> You should consider moving this check to ufs-sysfs.c where the sysfs write is
> handled. Failing due to unsupported suspend level at the last moment could be
> avoided.

Hi Mani,

We have planned to support other spm levels also in follow up series
once the basic UFS SCMI functionality is upstreamed.  This spm_lvl check
is intended as a temporary safeguard while we only support SPM level 5. 
If you'd still prefer a change, I caupdate this in the next patchset.

> 
>> +
>> +	pm_runtime_put_sync(hba->dev);
>> +
>> +	return ufs_qcom_ice_suspend(host);
>> +}
>> +
>> +static int ufs_qcom_fw_managed_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>> +{
>> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> +	int err;
>> +
>> +	err = pm_runtime_resume_and_get(hba->dev);
>> +	if (err) {
>> +		dev_err(hba->dev, "PM runtime resume failed: %d\n", err);
>> +		return err;
>> +	}
>> +
>> +	return ufs_qcom_ice_resume(host);
>> +}
>> +
>>  static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
>>  {
>>  	if (host->dev_ref_clk_ctrl_mmio &&
>> @@ -1421,6 +1475,52 @@ static void ufs_qcom_exit(struct ufs_hba *hba)
>>  	phy_exit(host->generic_phy);
>>  }
>>  
>> +static int ufs_qcom_fw_managed_init(struct ufs_hba *hba)
>> +{
>> +	struct device *dev = hba->dev;
>> +	struct ufs_qcom_host *host;
>> +	int err;
>> +
>> +	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
>> +	if (!host)
>> +		return -ENOMEM;
>> +
>> +	host->hba = hba;
>> +	ufshcd_set_variant(hba, host);
>> +
>> +	ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
>> +					 &host->hw_ver.minor, &host->hw_ver.step);
>> +
>> +	err = ufs_qcom_ice_init(host);
>> +	if (err)
>> +		goto out_variant_clear;
>> +
>> +	ufs_qcom_get_default_testbus_cfg(host);
>> +	err = ufs_qcom_testbus_config(host);
>> +	if (err)
>> +		/* Failure is non-fatal */
>> +		dev_warn(dev, "Failed to configure the testbus %d\n", err);
>> +
>> +	hba->caps |= UFSHCD_CAP_WB_EN;
>> +
>> +	ufs_qcom_advertise_quirks(hba);
>> +	host->hba->quirks &= ~UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
>> +
>> +	ufs_qcom_set_host_params(hba);
>> +	ufs_qcom_parse_gear_limits(hba);
>> +
>> +	return 0;
>> +
>> +out_variant_clear:
>> +	ufshcd_set_variant(hba, NULL);
>> +	return err;
>> +}
>> +
>> +static void ufs_qcom_fw_managed_exit(struct ufs_hba *hba)
>> +{
>> +	pm_runtime_put_sync(hba->dev);
>> +}
>> +
>>  /**
>>   * ufs_qcom_set_clk_40ns_cycles - Configure 40ns clk cycles
>>   *
>> @@ -1952,6 +2052,39 @@ static int ufs_qcom_device_reset(struct ufs_hba *hba)
>>  	return 0;
>>  }
>>  
>> +/**
>> + * ufs_qcom_fw_managed_device_reset - Reset UFS device under FW-managed design
> 
> I believe this is not just device reset but both controller + device reset. So
> not pretty sure that this is the right place to reset both.

Hi Mani,

This is as per our ufs controller design where we reset the host before the device
to stop the TX burst.


Thanks,
Ram.


> 
> - Mani
>
Re: [PATCH V1 3/3] ufs: ufs-qcom: Add support for firmware-managed resource abstraction
Posted by Manivannan Sadhasivam 1 month, 4 weeks ago
On Wed, Dec 10, 2025 at 09:33:08PM +0530, Ram Kumar Dwivedi wrote:
> 
> 
> On 20-Nov-25 11:23 AM, Manivannan Sadhasivam wrote:
> > On Fri, Nov 14, 2025 at 08:26:46PM +0530, Ram Kumar Dwivedi wrote:
> >> From: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> >>
> >> Add a compatible string for SA8255p platforms where resources such as
> >> PHY, clocks, regulators, and resets are managed by firmware through an
> >> SCMI server. Use the SCMI power protocol to abstract these resources and
> >> invoke power operations via runtime PM APIs (pm_runtime_get/put_sync).
> >>
> >> Introduce vendor operations (vops) for SA8255p targets to enable SCMI-
> >> based resource control. In this model, capabilities like clock scaling
> >> and gating are not yet supported; these will be added incrementally.
> >>
> >> Co-developed-by: Anjana Hari <quic_ahari@quicinc.com>
> >> Signed-off-by: Anjana Hari <quic_ahari@quicinc.com>
> >> Co-developed-by: Shazad Hussain <quic_shazhuss@quicinc.com>
> >> Signed-off-by: Shazad Hussain <quic_shazhuss@quicinc.com>
> >> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> >> ---
> >>  drivers/ufs/host/ufs-qcom.c | 161 +++++++++++++++++++++++++++++++++++-
> >>  drivers/ufs/host/ufs-qcom.h |   1 +
> >>  2 files changed, 161 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
> >> index 8d119b3223cb..13ccf1fb2ebf 100644
> >> --- a/drivers/ufs/host/ufs-qcom.c
> >> +++ b/drivers/ufs/host/ufs-qcom.c
> >> @@ -14,6 +14,7 @@
> >>  #include <linux/of.h>
> >>  #include <linux/phy/phy.h>
> >>  #include <linux/platform_device.h>
> >> +#include <linux/pm_domain.h>
> >>  #include <linux/reset-controller.h>
> >>  #include <linux/time.h>
> >>  #include <linux/unaligned.h>
> >> @@ -619,6 +620,27 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
> >>  	return err;
> >>  }
> >>  
> >> +static int ufs_qcom_fw_managed_hce_enable_notify(struct ufs_hba *hba,
> >> +						 enum ufs_notify_change_status status)
> >> +{
> >> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> >> +
> >> +	switch (status) {
> >> +	case PRE_CHANGE:
> >> +		ufs_qcom_select_unipro_mode(host);
> >> +		break;
> >> +	case POST_CHANGE:
> >> +		ufs_qcom_enable_hw_clk_gating(hba);
> >> +		ufs_qcom_ice_enable(host);
> >> +		break;
> >> +	default:
> >> +		dev_err(hba->dev, "Invalid status %d\n", status);
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >>  /**
> >>   * ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
> >>   *
> >> @@ -789,6 +811,38 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
> >>  	return ufs_qcom_ice_resume(host);
> >>  }
> >>  
> >> +static int ufs_qcom_fw_managed_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
> >> +				       enum ufs_notify_change_status status)
> >> +{
> >> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> >> +
> >> +	if (status == PRE_CHANGE)
> >> +		return 0;
> >> +
> >> +	if (hba->spm_lvl != UFS_PM_LVL_5) {
> >> +		dev_err(hba->dev, "Unsupported spm level %d\n", hba->spm_lvl);
> >> +		return -EINVAL;
> >> +	}
> > 
> > You should consider moving this check to ufs-sysfs.c where the sysfs write is
> > handled. Failing due to unsupported suspend level at the last moment could be
> > avoided.
> 
> Hi Mani,
> 
> We have planned to support other spm levels also in follow up series
> once the basic UFS SCMI functionality is upstreamed.  This spm_lvl check
> is intended as a temporary safeguard while we only support SPM level 5. 
> If you'd still prefer a change, I caupdate this in the next patchset.
> 

Please do it now as I don't see it logical to error out in suspend callback.

- Mani

-- 
மணிவண்ணன் சதாசிவம்
Re: [PATCH V1 3/3] ufs: ufs-qcom: Add support for firmware-managed resource abstraction
Posted by Ram Kumar Dwivedi 1 month, 1 week ago

On 12-Dec-25 6:15 AM, Manivannan Sadhasivam wrote:
> On Wed, Dec 10, 2025 at 09:33:08PM +0530, Ram Kumar Dwivedi wrote:
>>
>>
>> On 20-Nov-25 11:23 AM, Manivannan Sadhasivam wrote:
>>> On Fri, Nov 14, 2025 at 08:26:46PM +0530, Ram Kumar Dwivedi wrote:
>>>> From: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>>>>
>>>> Add a compatible string for SA8255p platforms where resources such as
>>>> PHY, clocks, regulators, and resets are managed by firmware through an
>>>> SCMI server. Use the SCMI power protocol to abstract these resources and
>>>> invoke power operations via runtime PM APIs (pm_runtime_get/put_sync).
>>>>
>>>> Introduce vendor operations (vops) for SA8255p targets to enable SCMI-
>>>> based resource control. In this model, capabilities like clock scaling
>>>> and gating are not yet supported; these will be added incrementally.
>>>>
>>>> Co-developed-by: Anjana Hari <quic_ahari@quicinc.com>
>>>> Signed-off-by: Anjana Hari <quic_ahari@quicinc.com>
>>>> Co-developed-by: Shazad Hussain <quic_shazhuss@quicinc.com>
>>>> Signed-off-by: Shazad Hussain <quic_shazhuss@quicinc.com>
>>>> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>>>> ---
>>>>  drivers/ufs/host/ufs-qcom.c | 161 +++++++++++++++++++++++++++++++++++-
>>>>  drivers/ufs/host/ufs-qcom.h |   1 +
>>>>  2 files changed, 161 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
>>>> index 8d119b3223cb..13ccf1fb2ebf 100644
>>>> --- a/drivers/ufs/host/ufs-qcom.c
>>>> +++ b/drivers/ufs/host/ufs-qcom.c
>>>> @@ -14,6 +14,7 @@
>>>>  #include <linux/of.h>
>>>>  #include <linux/phy/phy.h>
>>>>  #include <linux/platform_device.h>
>>>> +#include <linux/pm_domain.h>
>>>>  #include <linux/reset-controller.h>
>>>>  #include <linux/time.h>
>>>>  #include <linux/unaligned.h>
>>>> @@ -619,6 +620,27 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
>>>>  	return err;
>>>>  }
>>>>  
>>>> +static int ufs_qcom_fw_managed_hce_enable_notify(struct ufs_hba *hba,
>>>> +						 enum ufs_notify_change_status status)
>>>> +{
>>>> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>>>> +
>>>> +	switch (status) {
>>>> +	case PRE_CHANGE:
>>>> +		ufs_qcom_select_unipro_mode(host);
>>>> +		break;
>>>> +	case POST_CHANGE:
>>>> +		ufs_qcom_enable_hw_clk_gating(hba);
>>>> +		ufs_qcom_ice_enable(host);
>>>> +		break;
>>>> +	default:
>>>> +		dev_err(hba->dev, "Invalid status %d\n", status);
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>  /**
>>>>   * ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
>>>>   *
>>>> @@ -789,6 +811,38 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>>>>  	return ufs_qcom_ice_resume(host);
>>>>  }
>>>>  
>>>> +static int ufs_qcom_fw_managed_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
>>>> +				       enum ufs_notify_change_status status)
>>>> +{
>>>> +	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>>>> +
>>>> +	if (status == PRE_CHANGE)
>>>> +		return 0;
>>>> +
>>>> +	if (hba->spm_lvl != UFS_PM_LVL_5) {
>>>> +		dev_err(hba->dev, "Unsupported spm level %d\n", hba->spm_lvl);
>>>> +		return -EINVAL;
>>>> +	}
>>>
>>> You should consider moving this check to ufs-sysfs.c where the sysfs write is
>>> handled. Failing due to unsupported suspend level at the last moment could be
>>> avoided.
>>
>> Hi Mani,
>>
>> We have planned to support other spm levels also in follow up series
>> once the basic UFS SCMI functionality is upstreamed.  This spm_lvl check
>> is intended as a temporary safeguard while we only support SPM level 5. 
>> If you'd still prefer a change, I caupdate this in the next patchset.
>>
> 
> Please do it now as I don't see it logical to error out in suspend callback.
Hi Mani,

I have addressed the issue in latest patchset.

Thanks,
Ram.


> 
> - Mani
>