[PATCH 02/17] i3c: mipi-i3c-hci: Ensure proper bus clean-up

Frank Li Frank.li at nxp.com
Fri Dec 19 08:22:08 PST 2025


On Fri, Dec 19, 2025 at 04:45:19PM +0200, Adrian Hunter wrote:
> Wait for the bus to fully disable before proceeding, ensuring that no
> operations are still in progress.  Synchronize the IRQ handler only after
> interrupt signals have been disabled.  This approach also handles cases
> where bus disable might fail, preventing race conditions and ensuring a
> consistent shutdown sequence.
>
> Signed-off-by: Adrian Hunter <adrian.hunter at intel.com>
> ---

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>  drivers/i3c/master/mipi-i3c-hci/core.c | 32 +++++++++++++++++++++++---
>  drivers/i3c/master/mipi-i3c-hci/dma.c  |  7 ++++++
>  drivers/i3c/master/mipi-i3c-hci/hci.h  |  1 +
>  drivers/i3c/master/mipi-i3c-hci/pio.c  |  2 ++
>  4 files changed, 39 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index 6da5daf18166..0d3ec674878d 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -151,13 +151,39 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
>  	return 0;
>  }
>
> +/* Bus disable should never fail, so be generous with the timeout */
> +#define BUS_DISABLE_TIMEOUT_US (500 * USEC_PER_MSEC)
> +
> +static int i3c_hci_bus_disable(struct i3c_hci *hci)
> +{
> +	u32 regval;
> +	int ret;
> +
> +	reg_clear(HC_CONTROL, HC_CONTROL_BUS_ENABLE);
> +
> +	/* Ensure controller is disabled */
> +	ret = readx_poll_timeout(reg_read, HC_CONTROL, regval,
> +				 !(regval & HC_CONTROL_BUS_ENABLE), 0, BUS_DISABLE_TIMEOUT_US);
> +	if (ret)
> +		dev_err(&hci->master.dev, "%s: Failed to disable bus\n", __func__);
> +
> +	return ret;
> +}
> +
> +void i3c_hci_sync_irq_inactive(struct i3c_hci *hci)
> +{
> +	struct platform_device *pdev = to_platform_device(hci->master.dev.parent);
> +	int irq = platform_get_irq(pdev, 0);
> +
> +	reg_write(INTR_SIGNAL_ENABLE, 0x0);
> +	synchronize_irq(irq);
> +}
> +
>  static void i3c_hci_bus_cleanup(struct i3c_master_controller *m)
>  {
>  	struct i3c_hci *hci = to_i3c_hci(m);
> -	struct platform_device *pdev = to_platform_device(m->dev.parent);
>
> -	reg_clear(HC_CONTROL, HC_CONTROL_BUS_ENABLE);
> -	synchronize_irq(platform_get_irq(pdev, 0));
> +	i3c_hci_bus_disable(hci);
>  	hci->io->cleanup(hci);
>  	if (hci->cmd == &mipi_i3c_hci_cmd_v1)
>  		mipi_i3c_hci_dat_v1.cleanup(hci);
> diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
> index 5515ed740ca4..54849aa98fad 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/dma.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
> @@ -160,6 +160,13 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
>
>  		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
>  		rh_reg_write(RING_CONTROL, 0);
> +	}
> +
> +	i3c_hci_sync_irq_inactive(hci);
> +
> +	for (i = 0; i < rings->total; i++) {
> +		rh = &rings->headers[i];
> +
>  		rh_reg_write(CR_SETUP, 0);
>  		rh_reg_write(IBI_SETUP, 0);
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
> index 3f88b67bc5cc..fd08b701d094 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/hci.h
> +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
> @@ -142,5 +142,6 @@ void mipi_i3c_hci_pio_reset(struct i3c_hci *hci);
>  void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci);
>  void amd_set_od_pp_timing(struct i3c_hci *hci);
>  void amd_set_resp_buf_thld(struct i3c_hci *hci);
> +void i3c_hci_sync_irq_inactive(struct i3c_hci *hci);
>
>  #endif
> diff --git a/drivers/i3c/master/mipi-i3c-hci/pio.c b/drivers/i3c/master/mipi-i3c-hci/pio.c
> index 109c6c5d83d6..90dca56fc0c5 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/pio.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/pio.c
> @@ -211,6 +211,8 @@ static void hci_pio_cleanup(struct i3c_hci *hci)
>
>  	pio_reg_write(INTR_SIGNAL_ENABLE, 0x0);
>
> +	i3c_hci_sync_irq_inactive(hci);
> +
>  	if (pio) {
>  		dev_dbg(&hci->master.dev, "status = %#x/%#x",
>  			pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE));
> --
> 2.51.0
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c



More information about the linux-i3c mailing list