Re: [PATCH 8/8] i3c: mipi-i3c-hci: Add Hot-Join support

Frank Li <[email protected]>
Newsgroups org.infradead.lists.linux-i3c,org.kernel.vger.linux-kernel
Message-ID <agNWmjBlVcOj7wJm@lizhi-Precision-Tower-5810>
On Tue, May 12, 2026 at 03:17:32PM +0300, Adrian Hunter wrote:
> Wire the MIPI I3C HCI driver into the I3C core Hot-Join framework to
> allow targets to dynamically join the bus after initial DAA.
>
> HCI hardware ACKs or NACKs Hot-Join requests based on
> HC_CONTROL.HOT_JOIN_CTRL.  This was previously left in the
> NACK-and-DISEC state, effectively preventing Hot-Join.  Implement
> the ->enable_hotjoin() and ->disable_hotjoin() master operations
> so the core and user space can control this policy at runtime.
>
> Also issue broadcast ENEC HJ when enabling Hot-Join.  This is required
> because the controller may have previously DISEC'ed the Hot-Join
> event, causing targets that were NACKed once to never retry.
>
> Acknowledged Hot-Join requests are delivered as IBIs on the reserved
> address 0x02.  Update both the DMA and PIO IBI paths to recognise this
> address and forward the event to i3c_master_queue_hotjoin().
>
> To make Hot-Join usable by default, enable it once after the initial
> DAA.  This is gated by rpm_ibi_allowed, since otherwise keeping Hot-Join
> enabled prevents runtime suspend.  A new hj_init_done flag ensures this
> one-time enablement is not repeated on subsequent DAAs.
>
> Signed-off-by: Adrian Hunter <[email protected]>
> ---

Reviewed-by: Frank Li <[email protected]>

>  drivers/i3c/master/mipi-i3c-hci/core.c | 50 ++++++++++++++++++++++++--
>  drivers/i3c/master/mipi-i3c-hci/dma.c  |  5 +++
>  drivers/i3c/master/mipi-i3c-hci/hci.h  |  1 +
>  drivers/i3c/master/mipi-i3c-hci/pio.c  |  5 +++
>  4 files changed, 58 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index 2866d599612a..f8b399d16598 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -392,11 +392,52 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
>  	return ret;
>  }
>
> +static int i3c_hci_enable_hotjoin(struct i3c_master_controller *m)
> +{
> +	struct i3c_hci *hci = to_i3c_hci(m);
> +	int ret;
> +
> +	reg_clear(HC_CONTROL, HC_CONTROL_HOT_JOIN_CTRL);
> +
> +	/*
> +	 * Broadcast Hot_join enable, so that an I3C device that has previously
> +	 * had its Hot-Join request NACK'ed knows to try again.
> +	 */
> +	ret = i3c_master_enec_disec_locked(m, I3C_BROADCAST_ADDR, true, I3C_CCC_EVENT_HJ, true);
> +	if (ret) {
> +		reg_set(HC_CONTROL, HC_CONTROL_HOT_JOIN_CTRL);
> +		dev_err(&hci->master.dev, "Hot-Join ENEC CCC failed\n");
> +	}
> +
> +	return ret;
> +}
> +
> +static int i3c_hci_disable_hotjoin(struct i3c_master_controller *m)
> +{
> +	struct i3c_hci *hci = to_i3c_hci(m);
> +
> +	reg_set(HC_CONTROL, HC_CONTROL_HOT_JOIN_CTRL);
> +	return 0;
> +}
> +
>  static int i3c_hci_daa(struct i3c_master_controller *m)
>  {
>  	struct i3c_hci *hci = to_i3c_hci(m);
> +	int ret;
>
> -	return hci->cmd->perform_daa(hci);
> +	ret = hci->cmd->perform_daa(hci);
> +
> +	if (!hci->hj_init_done) {
> +		hci->hj_init_done = true;
> +		/*
> +		 * Enable Hot-Join by default after initial DAA if it does not
> +		 * prevent runtime suspend.
> +		 */
> +		if (m->rpm_ibi_allowed && !ret)
> +			m->hotjoin = !i3c_hci_enable_hotjoin(m);
> +	}
> +
> +	return ret;
>  }
>
>  static int i3c_hci_i3c_xfers(struct i3c_dev_desc *dev,
> @@ -652,6 +693,8 @@ static const struct i3c_master_controller_ops i3c_hci_ops = {
>  	.enable_ibi		= i3c_hci_enable_ibi,
>  	.disable_ibi		= i3c_hci_disable_ibi,
>  	.recycle_ibi_slot	= i3c_hci_recycle_ibi_slot,
> +	.enable_hotjoin		= i3c_hci_enable_hotjoin,
> +	.disable_hotjoin	= i3c_hci_disable_hotjoin,
>  };
>
>  static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
> @@ -833,8 +876,9 @@ static int i3c_hci_do_reset_and_restore(struct i3c_hci *hci)
>  	scoped_guard(spinlock_irqsave, &hci->lock)
>  		hci->irq_inactive = false;
>
> -	/* Enable bus with Hot-Join disabled */
> -	reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL);
> +	/* Enable bus, restoring hot-join state */
> +	reg_set(HC_CONTROL,
> +		HC_CONTROL_BUS_ENABLE | (hci->master.hotjoin ? 0 : HC_CONTROL_HOT_JOIN_CTRL));
>
>  	return 0;
>  }
> diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
> index e5deeba0aa4e..34129ac039dc 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/dma.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
> @@ -971,6 +971,11 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
>  	}
>
>  	/* determine who this is for */
> +	if (ibi_addr == I3C_HOT_JOIN_ADDR) {
> +		i3c_master_queue_hotjoin(&hci->master);
> +		goto done;
> +	}
> +
>  	dev = i3c_hci_addr_to_dev(hci, ibi_addr);
>  	if (!dev) {
>  		dev_err(&hci->master.dev,
> diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
> index 243d7a67f6f6..591eea040b01 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/hci.h
> +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
> @@ -57,6 +57,7 @@ struct i3c_hci {
>  	bool irq_inactive;
>  	bool enqueue_blocked;
>  	bool recovery_needed;
> +	bool hj_init_done;
>  	wait_queue_head_t enqueue_wait_queue;
>  	u32 caps;
>  	unsigned int quirks;
> diff --git a/drivers/i3c/master/mipi-i3c-hci/pio.c b/drivers/i3c/master/mipi-i3c-hci/pio.c
> index 6b8cc5f2b4d2..b5ae1cfaa9e0 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/pio.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/pio.c
> @@ -862,6 +862,11 @@ static bool hci_pio_prep_new_ibi(struct i3c_hci *hci, struct hci_pio_data *pio)
>  	ibi->seg_len = FIELD_GET(IBI_DATA_LENGTH, ibi_status);
>  	ibi->seg_cnt = ibi->seg_len;
>
> +	if (ibi->addr == I3C_HOT_JOIN_ADDR) {
> +		i3c_master_queue_hotjoin(&hci->master);
> +		return true;
> +	}
> +
>  	dev = i3c_hci_addr_to_dev(hci, ibi->addr);
>  	if (!dev) {
>  		dev_err(&hci->master.dev,
> --
> 2.51.0
>

-- 
linux-i3c mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-i3c
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.