Skip to contentSkip to conversation

i3c: dw: Add Altera Agilex5 runtime PM disable quirk

PATCH Applied [email protected] 4 participants 7 messages Nov 4, 2025 – Nov 12, 2025

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v5 cover i3c: dw: Add Altera Agilex5 runtime PM disable quirk

From: Adrian Ng Ho Yin <[email protected]>

This patchset adds support for an Altera SoCFPGA-specific quirk in the Synopsys DesignWare I3C master driver.

While running the I3C compliance test suite on the Altera Agilex5 SoCFPGA, the I3C bus was observed to hang when a slave device issued an IBI after the Dynamic Address Assignment (DAA) process completed.

This issue occurs because the controller enters a suspended state after DAA due to runtime PM being enabled. When suspended, the controller stops driving the SCL line. As a result, an IBI transfer cannot complete, leaving the SDA line stuck low and the bus in a hung state.

To address this issue, a new compatible string, "altr,agilex5-dw-i3c-master", is introduced to identify the SoC variant. When this compatible string is matched, a new quirk (DW_I3C_DISABLE_RUNTIME_PM_QUIRK) is applied to keep the controller enabled by incrementing the runtime PM reference counter during probe. This ensures the controller remains active to reliably handle IBI transactions without requiring runtime PM checks throughout the driver.

---
changelog:
v4->v5:
*Update commit message for better clarity.
*Update implementation to use const struct for better extensibility. *Add ACPI and Device Tree match handling separation for quirks to maintain existing behavior consistency.
v3->v4:
*Add reviewed by tag for dt binding.
*Aligned compatible string in dtsi with previous line.
*Update commit message for better clarity.
*Updated implementation to increment the PM reference counter during probe instead of conditionally bypassing runtime PM APIs. This simplifies the logic and ensures consistent behavior when the disable-runtime-PM quirk is applied.
v2->v3:
*Dropped RFC tag.
*Update compatible string to "altr,agilex5-dw-i3c-master" to match actual SoC. *Update commit message to describe changes correctly.
v1->v2:
*Add new compatible string in dw i3c dt binding to validate against newly added compatible string.
*Added new compatible string for altr socfpga platform.
*Remove Kconfig that disables runtime PM added in v1.
*Update implementation to disable runtime PM via compatible string match so that the implementation can be tied to a specific compatible string so that it does impact the existing behavior for other users.

See previous patch series at:
https://lore.kernel.org/all/22286d459959f2a153ac59d7da46794c0f495c77.1760579799.git.adrianhoyin.ng@altera.com/
---

Adrian Ng Ho Yin (3):
dt-bindings: i3c: snps: Add Altera SoCFPGA compatible
arm64: dts: intel: agilex5: Add Altera compatible for I3C controllers
i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI

 .../bindings/i3c/snps,dw-i3c-master.yaml      |  6 +++-
 .../arm64/boot/dts/intel/socfpga_agilex5.dtsi |  6 ++--
 drivers/i3c/master/dw-i3c-master.c            | 31 ++++++++++++++++++-
 3 files changed, 39 insertions(+), 4 deletions(-)
Signature · 1 line
2.49.GIT
#1 lore raw

PATCH v5 1/3 dt-bindings: i3c: snps: Add Altera SoCFPGA compatible

From: Adrian Ng Ho Yin <[email protected]>

Add the "altr,agilex5-dw-i3c-master" compatible string to the Synopsys DesignWare I3C master binding. This allow Agilex5 to use the generic DW I3C master controller while applying any required platform-specific quirks.

---
 .../devicetree/bindings/i3c/snps,dw-i3c-master.yaml         | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml +5 -1
index 5f6467375811..e803457d3f55 100644
@@ -14,7 +14,11 @@ allOf:
 
 properties:
   compatible:
-    const: snps,dw-i3c-master-1.00a
+    oneOf:
+      - const: snps,dw-i3c-master-1.00a
+      - items:
+          - const: altr,agilex5-dw-i3c-master
+          - const: snps,dw-i3c-master-1.00a
 
   reg:
     maxItems: 1
Signature · 1 line
2.49.GIT
#2 lore raw

PATCH v5 2/3 arm64: dts: intel: agilex5: Add Altera compatible for I3C controllers

In reply to [email protected]

From: Adrian Ng Ho Yin <[email protected]>

Add the "altr,agilex5-dw-i3c-master" compatible string to the I3C controller nodes on the Agilex5 SoCFPGA platform.

---
 arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi +4 -2
index 04e99cd7e74b..5c8ad5e9b248 100644
@@ -203,7 +203,8 @@ i2c4: i2c@10c02c00 {
 		};
 
 		i3c0: i3c@10da0000 {
-			compatible = "snps,dw-i3c-master-1.00a";
+			compatible = "altr,agilex5-dw-i3c-master",
+				     "snps,dw-i3c-master-1.00a";
 			reg = <0x10da0000 0x1000>;
 			#address-cells = <3>;
 			#size-cells = <0>;
@@ -213,7 +214,8 @@ i3c0: i3c@10da0000 {
 		};
 
 		i3c1: i3c@10da1000 {
-			compatible = "snps,dw-i3c-master-1.00a";
+			compatible = "altr,agilex5-dw-i3c-master",
+				     "snps,dw-i3c-master-1.00a";
 			reg = <0x10da1000 0x1000>;
 			#address-cells = <3>;
 			#size-cells = <0>;
Signature · 1 line
2.49.GIT
Applied
#3 lore raw

Re: [PATCH v5 2/3] arm64: dts: intel: agilex5: Add Altera compatible for I3C controllers

arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi

Quoted 14 lines · On 11/4/25 01:29, [email protected] wrote:

From: Adrian Ng Ho Yin <[email protected]>

Add the "altr,agilex5-dw-i3c-master" compatible string to the I3C controller nodes on the Agilex5 SoCFPGA platform.

---
  arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi | 6 ++++--
  1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi +0 -0
index 04e99cd7e74b..5c8ad5e9b248 100644

Applied!

#4 lore raw

PATCH v5 3/3 i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI

In reply to [email protected]

From: Adrian Ng Ho Yin <[email protected]>

When running compliance tests on the Altera Agilex5 SoCFPGA platform, the I3C bus can hang when a slave issues an IBI after the DAA process completes. The DesignWare I3C master enters runtime suspend once DAA finishes and stops driving SCL, preventing the IBI transfer from completing and leaving SDA stuck low.

Add a new compatible string, "altr,agilex5-dw-i3c-master" and apply a quirk that keep runtime PM always active on this platform by calling pm_runtime_get_noresume() during probe.

Prevent bus hangs triggered by IBIs on Agilex5 while maintaining keep the same behavior on other platforms.

---
 drivers/i3c/master/dw-i3c-master.c | 31 +++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)
drivers/i3c/master/dw-i3c-master.c +30 -1
index 9ceedf09c3b6..276592a8222e 100644
@@ -228,6 +228,7 @@
 
 /* List of quirks */
 #define AMD_I3C_OD_PP_TIMING		BIT(1)
+#define DW_I3C_DISABLE_RUNTIME_PM_QUIRK	BIT(2)
 
 struct dw_i3c_cmd {
 	u32 cmd_lo;
@@ -252,6 +253,10 @@ struct dw_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
+struct dw_i3c_drvdata {
+	u32 flags;
+};
+
 static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
 					   const struct i3c_ccc_cmd *cmd)
 {
@@ -1535,6 +1540,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
 			struct platform_device *pdev)
 {
 	int ret, irq;
+	const struct dw_i3c_drvdata *drvdata;
+	unsigned long quirks = 0;
 
 	if (!master->platform_ops)
 		master->platform_ops = &dw_i3c_platform_ops_default;
@@ -1590,7 +1597,18 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
 	master->maxdevs = ret >> 16;
 	master->free_pos = GENMASK(master->maxdevs - 1, 0);
 
-	master->quirks = (unsigned long)device_get_match_data(&pdev->dev);
+	if (has_acpi_companion(&pdev->dev)) {
+		quirks = (unsigned long)device_get_match_data(&pdev->dev);
+	} else if (pdev->dev.of_node) {
+		drvdata = device_get_match_data(&pdev->dev);
+		if (drvdata)
+			quirks = drvdata->flags;
+	}
+	master->quirks = quirks;
+
+	/* Keep controller enabled by preventing runtime suspend */
+	if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
+		pm_runtime_get_noresume(&pdev->dev);
 
 	INIT_WORK(&master->hj_work, dw_i3c_hj_work);
 	ret = i3c_master_register(&master->base, &pdev->dev,
@@ -1617,6 +1635,10 @@ void dw_i3c_common_remove(struct dw_i3c_master *master)
 	cancel_work_sync(&master->hj_work);
 	i3c_master_unregister(&master->base);
 
+	/* Balance pm_runtime_get_noresume() from probe() */
+	if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
+		pm_runtime_put_noidle(master->dev);
+
 	pm_runtime_disable(master->dev);
 	pm_runtime_set_suspended(master->dev);
 	pm_runtime_dont_use_autosuspend(master->dev);
@@ -1759,8 +1781,15 @@ static void dw_i3c_shutdown(struct platform_device *pdev)
 	pm_runtime_put_autosuspend(master->dev);
 }
 
+static const struct dw_i3c_drvdata altr_agilex5_drvdata = {
+	.flags = DW_I3C_DISABLE_RUNTIME_PM_QUIRK,
+};
+
 static const struct of_device_id dw_i3c_master_of_match[] = {
 	{ .compatible = "snps,dw-i3c-master-1.00a", },
+	{ .compatible = "altr,agilex5-dw-i3c-master",
+	  .data = &altr_agilex5_drvdata,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);
Signature · 1 line
2.49.GIT
reviewer Reviewed-by on v5 3/3
#5 lore raw

Re: [PATCH v5 3/3] i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI

Quoted 8 lines · On Tue, Nov 04, 2025 at 03:29:08PM +0800, [email protected] wrote:

From: Adrian Ng Ho Yin <[email protected]>

When running compliance tests on the Altera Agilex5 SoCFPGA platform, the I3C bus can hang when a slave issues an IBI after the DAA process completes. The DesignWare I3C master enters runtime suspend once DAA finishes and stops driving SCL, preventing the IBI transfer from completing and leaving SDA stuck low.

Quoted 8 lines

Add a new compatible string, "altr,agilex5-dw-i3c-master" and apply a quirk that keep runtime PM always active on this platform by calling pm_runtime_get_noresume() during probe.

Prevent bus hangs triggered by IBIs on Agilex5 while maintaining keep the same behavior on other platforms.

---

Quoted 85 lines
 drivers/i3c/master/dw-i3c-master.c | 31 +++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)
drivers/i3c/master/dw-i3c-master.c +30 -2
index 9ceedf09c3b6..276592a8222e 100644
@@ -228,6 +228,7 @@
 
 /* List of quirks */
 #define AMD_I3C_OD_PP_TIMING		BIT(1)
+#define DW_I3C_DISABLE_RUNTIME_PM_QUIRK	BIT(2)
 
 struct dw_i3c_cmd {
 	u32 cmd_lo;
@@ -252,6 +253,10 @@ struct dw_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
+struct dw_i3c_drvdata {
+	u32 flags;
+};
+
 static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
 					   const struct i3c_ccc_cmd *cmd)
 {
@@ -1535,6 +1540,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
 			struct platform_device *pdev)
 {
 	int ret, irq;
+	const struct dw_i3c_drvdata *drvdata;
+	unsigned long quirks = 0;
 
 	if (!master->platform_ops)
 		master->platform_ops = &dw_i3c_platform_ops_default;
@@ -1590,7 +1597,18 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
 	master->maxdevs = ret >> 16;
 	master->free_pos = GENMASK(master->maxdevs - 1, 0);
 
-	master->quirks = (unsigned long)device_get_match_data(&pdev->dev);
+	if (has_acpi_companion(&pdev->dev)) {
+		quirks = (unsigned long)device_get_match_data(&pdev->dev);
+	} else if (pdev->dev.of_node) {
+		drvdata = device_get_match_data(&pdev->dev);
+		if (drvdata)
+			quirks = drvdata->flags;
+	}
+	master->quirks = quirks;
+
+	/* Keep controller enabled by preventing runtime suspend */
+	if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
+		pm_runtime_get_noresume(&pdev->dev);
 
 	INIT_WORK(&master->hj_work, dw_i3c_hj_work);
 	ret = i3c_master_register(&master->base, &pdev->dev,
@@ -1617,6 +1635,10 @@ void dw_i3c_common_remove(struct dw_i3c_master *master)
 	cancel_work_sync(&master->hj_work);
 	i3c_master_unregister(&master->base);
 
+	/* Balance pm_runtime_get_noresume() from probe() */
+	if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
+		pm_runtime_put_noidle(master->dev);
+
 	pm_runtime_disable(master->dev);
 	pm_runtime_set_suspended(master->dev);
 	pm_runtime_dont_use_autosuspend(master->dev);
@@ -1759,8 +1781,15 @@ static void dw_i3c_shutdown(struct platform_device *pdev)
 	pm_runtime_put_autosuspend(master->dev);
 }
 
+static const struct dw_i3c_drvdata altr_agilex5_drvdata = {
+	.flags = DW_I3C_DISABLE_RUNTIME_PM_QUIRK,
+};
+
 static const struct of_device_id dw_i3c_master_of_match[] = {
 	{ .compatible = "snps,dw-i3c-master-1.00a", },
+	{ .compatible = "altr,agilex5-dw-i3c-master",
+	  .data = &altr_agilex5_drvdata,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);
--

2.49.GIT

maintainer Applied
#6 lore raw

Re: (subset) [PATCH v5 0/3] i3c: dw: Add Altera Agilex5 runtime PM disable quirk

In reply to [email protected]
Quoted 10 lines · On Tue, 04 Nov 2025 15:29:05 +0800, [email protected] wrote:

From: Adrian Ng Ho Yin <[email protected]>

This patchset adds support for an Altera SoCFPGA-specific quirk in the Synopsys DesignWare I3C master driver.

While running the I3C compliance test suite on the Altera Agilex5 SoCFPGA, the I3C bus was observed to hang when a slave device issued an IBI after the Dynamic Address Assignment (DAA) process completed.

[...]

Applied, thanks!

[1/3] dt-bindings: i3c: snps: Add Altera SoCFPGA compatible

      https://git.kernel.org/abelloni/c/8d1d2c408cc0
[3/3] i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI
      https://git.kernel.org/abelloni/c/fba0e56ee752

Best regards,

Signature · 3 lines
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com