Skip to content

Commit fba0e56

Browse files
hoyin0722alexandrebelloni
authored andcommitted
i3c: dw: Disable runtime PM on Agilex5 to avoid bus hang on IBI
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. Signed-off-by: Adrian Ng Ho Yin <adrianhoyin.ng@altera.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/482d540722a98c2809d8275445aaa544b565bf85.1762237922.git.adrianhoyin.ng@altera.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent 8d1d2c4 commit fba0e56

1 file changed

Lines changed: 30 additions & 1 deletion

File tree

drivers/i3c/master/dw-i3c-master.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@
228228

229229
/* List of quirks */
230230
#define AMD_I3C_OD_PP_TIMING BIT(1)
231+
#define DW_I3C_DISABLE_RUNTIME_PM_QUIRK BIT(2)
231232

232233
struct dw_i3c_cmd {
233234
u32 cmd_lo;
@@ -252,6 +253,10 @@ struct dw_i3c_i2c_dev_data {
252253
struct i3c_generic_ibi_pool *ibi_pool;
253254
};
254255

256+
struct dw_i3c_drvdata {
257+
u32 flags;
258+
};
259+
255260
static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
256261
const struct i3c_ccc_cmd *cmd)
257262
{
@@ -1535,6 +1540,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
15351540
struct platform_device *pdev)
15361541
{
15371542
int ret, irq;
1543+
const struct dw_i3c_drvdata *drvdata;
1544+
unsigned long quirks = 0;
15381545

15391546
if (!master->platform_ops)
15401547
master->platform_ops = &dw_i3c_platform_ops_default;
@@ -1590,7 +1597,18 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
15901597
master->maxdevs = ret >> 16;
15911598
master->free_pos = GENMASK(master->maxdevs - 1, 0);
15921599

1593-
master->quirks = (unsigned long)device_get_match_data(&pdev->dev);
1600+
if (has_acpi_companion(&pdev->dev)) {
1601+
quirks = (unsigned long)device_get_match_data(&pdev->dev);
1602+
} else if (pdev->dev.of_node) {
1603+
drvdata = device_get_match_data(&pdev->dev);
1604+
if (drvdata)
1605+
quirks = drvdata->flags;
1606+
}
1607+
master->quirks = quirks;
1608+
1609+
/* Keep controller enabled by preventing runtime suspend */
1610+
if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
1611+
pm_runtime_get_noresume(&pdev->dev);
15941612

15951613
INIT_WORK(&master->hj_work, dw_i3c_hj_work);
15961614
ret = i3c_master_register(&master->base, &pdev->dev,
@@ -1617,6 +1635,10 @@ void dw_i3c_common_remove(struct dw_i3c_master *master)
16171635
cancel_work_sync(&master->hj_work);
16181636
i3c_master_unregister(&master->base);
16191637

1638+
/* Balance pm_runtime_get_noresume() from probe() */
1639+
if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
1640+
pm_runtime_put_noidle(master->dev);
1641+
16201642
pm_runtime_disable(master->dev);
16211643
pm_runtime_set_suspended(master->dev);
16221644
pm_runtime_dont_use_autosuspend(master->dev);
@@ -1759,8 +1781,15 @@ static void dw_i3c_shutdown(struct platform_device *pdev)
17591781
pm_runtime_put_autosuspend(master->dev);
17601782
}
17611783

1784+
static const struct dw_i3c_drvdata altr_agilex5_drvdata = {
1785+
.flags = DW_I3C_DISABLE_RUNTIME_PM_QUIRK,
1786+
};
1787+
17621788
static const struct of_device_id dw_i3c_master_of_match[] = {
17631789
{ .compatible = "snps,dw-i3c-master-1.00a", },
1790+
{ .compatible = "altr,agilex5-dw-i3c-master",
1791+
.data = &altr_agilex5_drvdata,
1792+
},
17641793
{},
17651794
};
17661795
MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);

0 commit comments

Comments
 (0)