[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <aQowRfxaH3bdqPXP@lizhi-Precision-Tower-5810>
Date: Tue, 4 Nov 2025 11:56:37 -0500
From: Frank Li <Frank.li@....com>
To: adrianhoyin.ng@...era.com
Cc: alexandre.belloni@...tlin.com, wsa+renesas@...g-engineering.com,
robh@...nel.org, krzk+dt@...nel.org, conor+dt@...nel.org,
dinguyen@...nel.org, linux-i3c@...ts.infradead.org,
devicetree@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v5 3/3] i3c: dw: Disable runtime PM on Agilex5 to avoid
bus hang on IBI
On Tue, Nov 04, 2025 at 03:29:08PM +0800, adrianhoyin.ng@...era.com wrote:
> From: Adrian Ng Ho Yin <adrianhoyin.ng@...era.com>
>
> 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@...era.com>
Reviewed-by: Frank Li <Frank.Li@....com>
---
> drivers/i3c/master/dw-i3c-master.c | 31 +++++++++++++++++++++++++++++-
> 1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
> index 9ceedf09c3b6..276592a8222e 100644
> --- a/drivers/i3c/master/dw-i3c-master.c
> +++ b/drivers/i3c/master/dw-i3c-master.c
> @@ -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
>
Powered by blists - more mailing lists