Re: [PATCH v2 2/3] i3c: mipi-i3c-hci: Add PIO queue management support for HCI v1.2

Adrian Hunter <[email protected]>
Newsgroups org.infradead.lists.linux-i3c
Organization Intel Finland Oy, Registered Address: c/o Alberga Business Park, 6 krs, Bertel Jungin Aukio 5, 02600 Espoo, Business Identity Code: 0357606 - 4, Domiciled in Helsinki
Message-ID <[email protected]>
On 28/07/2026 12:32, Jian-Ming Liao wrote:
> Support explicit enablement and starting of PIO queues as required by
> HCI v1.2.
> Handle alternate PIO queue sizes via ALT_QUEUE_SIZE register.
> Implement explicit PIO queue stopping/disabling and restart logic after
> errors.
> 
> Co-developed-by: Patrick Yen <[email protected]>
> Signed-off-by: Patrick Yen <[email protected]>
> Signed-off-by: Jian-Ming Liao <[email protected]>

./scripts/checkpatch.pl warning:

WARNING: From:/Signed-off-by: email address mismatch: 'From: Jian-Ming Liao <[email protected]>' != 'Signed-off-by: Jian-Ming Liao <[email protected]>

> ---
> v2:
>   - Removed '-' prefixes from commit message per maintainer's suggestion.
>   - Aligned GENMASK bit definitions with existing macro styles.
>   - Reverted unnecessary dev_dbg line movements to keep the diff clean.
>   - Removed manual kfree(pio) as pio is managed by devm_kzalloc.
>   - Introduced/used helper macro for HCI version checks instead of hardcoding.
> 
>  drivers/i3c/master/mipi-i3c-hci/core.c |  1 +
>  drivers/i3c/master/mipi-i3c-hci/hci.h  |  5 ++
>  drivers/i3c/master/mipi-i3c-hci/pio.c  | 67 ++++++++++++++++++++++++--
>  3 files changed, 69 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index e80aa1f5722e..dccc974ef15a 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -1031,6 +1031,7 @@ static int i3c_hci_init(struct i3c_hci *hci)
>  	switch (regval & ~0xf) {
>  	case 0x100:	/* version 1.0 */
>  	case 0x110:	/* version 1.1 */
> +	case 0x120:	/* version 1.2 */
>  	case 0x200:	/* version 2.0 */
>  		break;
>  	default:
> diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
> index b3d9803b1968..becccb1a8cf5 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/hci.h
> +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
> @@ -30,6 +30,11 @@
>  #define reg_set(r, v)		reg_write(r, reg_read(r) | (v))
>  #define reg_clear(r, v)		reg_write(r, reg_read(r) & ~(v))
>  
> +/* helper macro for HCI version check */
> +#define hci_version_at_least(hci, maj, min) \
> +	((hci)->version_major > (maj) || \
> +	((hci)->version_major == (maj) && (hci)->version_minor >= (min)))
> +
>  struct hci_cmd_ops;
>  
>  struct dat_words {
> diff --git a/drivers/i3c/master/mipi-i3c-hci/pio.c b/drivers/i3c/master/mipi-i3c-hci/pio.c
> index 9df114ef0278..43ef05468cc4 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/pio.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/pio.c
> @@ -45,6 +45,11 @@
>  #define IBI_STATUS_SIZE			GENMASK(15, 8)
>  #define CR_QUEUE_SIZE			GENMASK(7, 0)
>  
> +#define PIO_ALT_QUEUE_SIZE		0x1C
> +#define EXT_IBI_QUEUE_EN		BIT(28)
> +#define ALT_RESP_QUEUE_EN		BIT(24)
> +#define ALT_RESP_QUEUE_SIZE		GENMASK(7, 0)
> +
>  #define PIO_INTR_STATUS			0x20
>  #define PIO_INTR_STATUS_ENABLE		0x24
>  #define PIO_INTR_SIGNAL_ENABLE		0x28
> @@ -72,6 +77,11 @@
>  #define STAT_RX_THLD			BIT(1)
>  #define STAT_TX_THLD			BIT(0)
>  
> +#define PIO_CONTROL			0x30
> +#define PIO_CONTROL_ABORT		BIT(2)
> +#define PIO_CONTROL_RS			BIT(1)
> +#define PIO_CONTROL_ENABLE		BIT(0)
> +
>  #define PIO_QUEUE_CUR_STATUS		0x38
>  #define CUR_IBI_Q_LEVEL			GENMASK(28, 20)
>  #define CUR_RESP_Q_LEVEL		GENMASK(18, 10)
> @@ -173,6 +183,14 @@ static void __hci_pio_init(struct i3c_hci *hci, u32 *size_val_ptr)
>  	 * IBI queue size within allowed bounds.
>  	 */
>  	ibi_val = FIELD_GET(IBI_STATUS_SIZE, size_val);
> +	/* Adjust actual IBI queue size based on v1.2 ALT_QUEUE_SIZE */
> +	if (hci_version_at_least(hci, 1, 2)) {
> +		u32 alt_val = pio_reg_read(ALT_QUEUE_SIZE);
> +
> +		if (alt_val & EXT_IBI_QUEUE_EN)
> +			ibi_val *= 8;
> +	}
> +
>  	pio->max_ibi_thresh = clamp_val(ibi_val/2, 1, 63);
>  	val = FIELD_PREP(QUEUE_IBI_STATUS_THLD, 1) |
>  	      FIELD_PREP(QUEUE_IBI_DATA_THLD, pio->max_ibi_thresh) |
> @@ -192,6 +210,17 @@ static void __hci_pio_init(struct i3c_hci *hci, u32 *size_val_ptr)
>  	 * IBI routing yet.
>  	 */
>  	pio->enabled_irqs = STAT_ALL_ERRORS | STAT_IBI_STATUS_THLD;
> +
> +	/* MIPI I3C HCI v1.2 requires explicitly enabling and starting PIO queues */
> +	if (hci_version_at_least(hci, 1, 2)) {
> +		u32 ctl_val = pio_reg_read(CONTROL);
> +
> +		if (!(ctl_val & PIO_CONTROL_ENABLE)) {
> +			ctl_val |= PIO_CONTROL_ENABLE;
> +			pio_reg_write(CONTROL, ctl_val);
> +		}
> +		pio_reg_write(CONTROL, ctl_val | PIO_CONTROL_RS);
> +	}
>  }
>  
>  static void hci_pio_suspend(struct i3c_hci *hci)
> @@ -210,6 +239,7 @@ static int hci_pio_init(struct i3c_hci *hci)
>  {
>  	struct hci_pio_data *pio;
>  	u32 size_val;
> +	u32 cmd_sz, resp_sz, ibi_val;
>  
>  	pio = devm_kzalloc(hci->master.dev.parent, sizeof(*pio), GFP_KERNEL);
>  	if (!pio)
> @@ -219,10 +249,24 @@ static int hci_pio_init(struct i3c_hci *hci)
>  
>  	__hci_pio_init(hci, &size_val);
>  
> -	dev_dbg(&hci->master.dev, "CMD/RESP FIFO = %ld entries\n",
> -		FIELD_GET(CR_QUEUE_SIZE, size_val));
> -	dev_dbg(&hci->master.dev, "IBI FIFO = %ld bytes\n",
> -		4 * FIELD_GET(IBI_STATUS_SIZE, size_val));
> +	cmd_sz = FIELD_GET(CR_QUEUE_SIZE, size_val);
> +	resp_sz = cmd_sz;
> +	ibi_val = FIELD_GET(IBI_STATUS_SIZE, size_val);
> +
> +	/* MIPI I3C HCI v1.2 supports alternate RESP/IBI queue size */
> +	if (hci_version_at_least(hci, 1, 2)) {
> +		u32 alt_val = pio_reg_read(ALT_QUEUE_SIZE);
> +
> +		if (alt_val & ALT_RESP_QUEUE_EN)
> +			resp_sz = FIELD_GET(ALT_RESP_QUEUE_SIZE, alt_val);
> +		if (alt_val & EXT_IBI_QUEUE_EN)
> +			ibi_val *= 8;
> +	}
> +
> +	dev_dbg(&hci->master.dev, "CMD FIFO = %u, RESP FIFO = %u entries\n",
> +		cmd_sz, resp_sz);
> +	dev_dbg(&hci->master.dev, "IBI FIFO = %u bytes\n",
> +		4 * ibi_val);
>  	dev_dbg(&hci->master.dev, "RX data FIFO = %d bytes\n",
>  		4 * (2 << FIELD_GET(RX_DATA_BUFFER_SIZE, size_val)));
>  	dev_dbg(&hci->master.dev, "TX data FIFO = %d bytes\n",
> @@ -246,6 +290,9 @@ static void hci_pio_cleanup(struct i3c_hci *hci)
>  		BUG_ON(pio->curr_rx);
>  		BUG_ON(pio->curr_tx);
>  		BUG_ON(pio->curr_resp);
> +		/* MIPI I3C HCI v1.2 requires explicitly stopping and disabling PIO queues */
> +		if (hci_version_at_least(hci, 1, 2))
> +			pio_reg_write(CONTROL, 0x0);
>  	}
>  }
>  
> @@ -766,6 +813,18 @@ static void hci_pio_err(struct i3c_hci *hci, struct hci_pio_data *pio,
>  		hci_pio_dequeue_xfer_common(hci, pio, pio->curr_tx, 1);
>  	/* then reset the hardware */
>  	mipi_i3c_hci_pio_reset(hci);
> +
> +	/* MIPI I3C HCI v1.2 requires explicitly restarting PIO queues after error/abort */
> +	if (hci_version_at_least(hci, 1, 2)) {
> +		u32 ctl_val = pio_reg_read(CONTROL);
> +
> +		if (!(ctl_val & PIO_CONTROL_ENABLE)) {
> +			ctl_val |= PIO_CONTROL_ENABLE;
> +			pio_reg_write(CONTROL, ctl_val);
> +		}
> +		pio_reg_write(CONTROL, ctl_val | PIO_CONTROL_RS);
> +	}
> +
>  	mipi_i3c_hci_resume(hci);
>  
>  	dev_dbg(&hci->master.dev, "status=%#x/%#x",


-- 
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.