Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [net-next] net: airoha: Wait for TX to complete in airoha_dev_stop()
From: Paolo Abeni @ 2026-04-14  8:29 UTC (permalink / raw)
  To: lorenzo
  Cc: edumazet, kuba, davem, netdev, andrew+netdev, pabeni,
	linux-arm-kernel, linux-mediatek
In-Reply-To: <20260411-airoha-fix-ndo_stop-v1-1-caddaa181739@kernel.org>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.

For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
net: airoha: Wait for TX to complete in airoha_dev_stop()

Wait for TX to complete in airoha_dev_stop routine before stopping the
TX DMA and run airoha_qdma_cleanup_tx_queue routine. Moreover,
start/stop TX/RX NAPIs in ndo_open()/ndo_stop() callbacks in order to be
sure the TX NAPIs have completed before stopping the TX DMA engine in
airoha_dev_stop routine.

> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 8e4b043af4bc..9e40c8f375c1 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c

[ ... ]

> @@ -1684,18 +1686,26 @@ static int airoha_dev_stop(struct net_device *dev)
>  	struct airoha_qdma *qdma = port->qdma;
>  	int i, err;
>
> -	netif_tx_disable(dev);
>  	err = airoha_set_vip_for_gdm_port(port, false);
>  	if (err)
>  		return err;
>
> -	for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
> -		netdev_tx_reset_subqueue(dev, i);
> -
>  	airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
>  				    FE_PSE_PORT_DROP);
>
> +	netif_tx_disable(dev);
>  	if (atomic_dec_and_test(&qdma->users)) {
> +		u32 val;
> +
> +		/* Wait for TX to complete */
> +		err = read_poll_timeout(airoha_qdma_rr, val,
> +					!(val & GLOBAL_CFG_TX_DMA_BUSY_MASK),
> +					USEC_PER_MSEC, 100 * USEC_PER_MSEC,
> +					false, qdma, REG_QDMA_GLOBAL_CFG);
> +		if (err)
> +			return err;
>                   ^^^^^^^^^^

Can this leave the device in an inconsistent state? When read_poll_timeout()
fails (TX DMA busy for more than 100ms), airoha_dev_stop() returns an error
immediately. However, atomic_dec_and_test(&qdma->users) has already
decremented qdma->users to 0, but airoha_qdma_stop_napi() was never called,
so all NAPIs remain enabled.

The networking core (__dev_close_many in net/core/dev.c) ignores the
ndo_stop return value and marks the device as down regardless. When the
device is later brought up again, airoha_dev_open() sees atomic_fetch_inc()
return 0 (old value) and calls airoha_qdma_start_napi() -> napi_enable(),
which hits BUG_ON(!test_bit(NAPI_STATE_SCHED, &val)) in napi_enable_locked()
because the NAPI was never disabled.

The early return also skips the netdev_tx_reset_subqueue() calls at the end
of the function.

Should the code either continue with cleanup on timeout (don't return), or
ensure NAPI and DMA state are properly cleaned up before returning?

> +
> +		airoha_qdma_stop_napi(qdma);
>  		airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
>  				  GLOBAL_CFG_TX_DMA_EN_MASK |
>  				  GLOBAL_CFG_RX_DMA_EN_MASK);

[ ... ]



^ permalink raw reply

* [PATCH v2 2/2] mmc: dw_mmc: exynos: increase DMA threshold value for exynos7870
From: Kaustabh Chakraborty @ 2026-04-14  8:36 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jaehoon Chung, Shawn Lin, Krzysztof Kozlowski, Alim Akhtar
  Cc: linux-mmc, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc, Kaustabh Chakraborty
In-Reply-To: <20260414-dwmmc-dma-thr-v2-0-4058078f5361@disroot.org>

Exynos 7870 compatible controllers, such as SDIO ones are not able to
perform DMA transfers for small sizes of data (~16 to ~512 bytes),
resulting in cache issues in subsequent transfers. Increase the DMA
transfer threshold to 512 to allow the shorter transfers to take place,
bypassing DMA.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/mmc/host/dw_mmc-exynos.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 261344d3a8cfe..4b76b997ddc15 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -141,6 +141,7 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
 		priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) {
 		/* Quirk needed for certain Exynos SoCs */
 		host->quirks |= DW_MMC_QUIRK_FIFO64_32;
+		host->dma_threshold = 512;
 	}
 
 	if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) {

-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 0/2] Configuring DMA threshold value for DW-MMC controllers
From: Kaustabh Chakraborty @ 2026-04-14  8:35 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jaehoon Chung, Shawn Lin, Krzysztof Kozlowski, Alim Akhtar
  Cc: linux-mmc, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc, Kaustabh Chakraborty

In Samsung Exynos 7870 devices with Broadcom Wi-Fi, it has been observed
that small sized DMA transfers are unreliable and are not written
properly, which renders the cache incoherent.

Experimental observations say that DMA transfer sizes of somewhere
around 64 to 512 are intolerable. We must thus implement a mechanism to
fall back to PIO transfer in this case. One such approach, which this
series implements is allowing the DMA transfer threshold, which is
already defined in the driver, to be configurable.

Note that this patch is likely to be labelled as a workaround. These
smaller transfers seem to be successful from downstream kernels,
however efforts to figure out how so went in vain. It is also very
possible that the downstream Broadcom Wi-Fi SDIO driver uses PIO
transfers as well.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
Changes in v2:
- Remove dt-binding to set DMA threshold (Krzysztof Kozlowski)
- Add comment to describe struct dw_mci::dma_threshold (Shawn Lin)
- Set DMA threshold in Exynos 7870 DW-MMC driver (Krzysztof Kozlowski)
- Link to v1: https://lore.kernel.org/r/20260412-dwmmc-dma-thr-v1-0-75a2f658eee3@disroot.org

---
Kaustabh Chakraborty (2):
      mmc: dw_mmc: implement option for configuring DMA threshold
      mmc: dw_mmc: exynos: increase DMA threshold value for exynos7870

 drivers/mmc/host/dw_mmc-exynos.c | 1 +
 drivers/mmc/host/dw_mmc.c        | 5 +++--
 drivers/mmc/host/dw_mmc.h        | 2 ++
 3 files changed, 6 insertions(+), 2 deletions(-)
---
base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
change-id: 20260412-dwmmc-dma-thr-1090d8285ea7

Best regards,
-- 
Kaustabh Chakraborty <kauschluss@disroot.org>



^ permalink raw reply

* [PATCH v2 1/2] mmc: dw_mmc: implement option for configuring DMA threshold
From: Kaustabh Chakraborty @ 2026-04-14  8:36 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jaehoon Chung, Shawn Lin, Krzysztof Kozlowski, Alim Akhtar
  Cc: linux-mmc, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc, Kaustabh Chakraborty
In-Reply-To: <20260414-dwmmc-dma-thr-v2-0-4058078f5361@disroot.org>

Some controllers, such as certain Exynos SDIO ones, are unable to
perform DMA transfers of small amount of bytes properly. Following the
device tree schema, implement the property to define the DMA transfer
threshold (from a hard coded value of 16 bytes) so that lesser number of
bytes can be transferred safely skipping DMA in such controllers. The
value of 16 bytes stays as the default for controllers which do not
define it. This value can be overridden by implementation-specific init
sequences.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/mmc/host/dw_mmc.c | 5 +++--
 drivers/mmc/host/dw_mmc.h | 2 ++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 20193ee7b73eb..9dd9fed4ccf49 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -40,7 +40,6 @@
 				 SDMMC_INT_RESP_ERR | SDMMC_INT_HLE)
 #define DW_MCI_ERROR_FLAGS	(DW_MCI_DATA_ERROR_FLAGS | \
 				 DW_MCI_CMD_ERROR_FLAGS)
-#define DW_MCI_DMA_THRESHOLD	16
 
 #define DW_MCI_FREQ_MAX	200000000	/* unit: HZ */
 #define DW_MCI_FREQ_MIN	100000		/* unit: HZ */
@@ -821,7 +820,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
 	 * non-word-aligned buffers or lengths. Also, we don't bother
 	 * with all the DMA setup overhead for short transfers.
 	 */
-	if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
+	if (data->blocks * data->blksz < host->dma_threshold)
 		return -EINVAL;
 
 	if (data->blksz & 3)
@@ -3245,6 +3244,8 @@ int dw_mci_probe(struct dw_mci *host)
 		goto err_clk_ciu;
 	}
 
+	host->dma_threshold = 16;
+
 	if (host->rstc) {
 		reset_control_assert(host->rstc);
 		usleep_range(10, 50);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 42e58be74ce09..fc7601fba849f 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -164,6 +164,8 @@ struct dw_mci {
 	void __iomem		*fifo_reg;
 	u32			data_addr_override;
 	bool			wm_aligned;
+	/* Configurable data byte threshold value for DMA transfer. */
+	u32			dma_threshold;
 
 	struct scatterlist	*sg;
 	struct sg_mapping_iter	sg_miter;

-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH v2 1/2] mmc: dw_mmc: implement option for configuring DMA threshold
From: Shawn Lin @ 2026-04-14  8:50 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Ulf Hansson, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jaehoon Chung,
	Krzysztof Kozlowski, Alim Akhtar
  Cc: shawn.lin, linux-mmc, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc
In-Reply-To: <20260414-dwmmc-dma-thr-v2-1-4058078f5361@disroot.org>

在 2026/04/14 星期二 16:36, Kaustabh Chakraborty 写道:
> Some controllers, such as certain Exynos SDIO ones, are unable to
> perform DMA transfers of small amount of bytes properly. Following the
> device tree schema, implement the property to define the DMA transfer
> threshold (from a hard coded value of 16 bytes) so that lesser number of
> bytes can be transferred safely skipping DMA in such controllers. The
> value of 16 bytes stays as the default for controllers which do not
> define it. This value can be overridden by implementation-specific init
> sequences.
> 
> Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
> ---
>   drivers/mmc/host/dw_mmc.c | 5 +++--
>   drivers/mmc/host/dw_mmc.h | 2 ++
>   2 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 20193ee7b73eb..9dd9fed4ccf49 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -40,7 +40,6 @@
>   				 SDMMC_INT_RESP_ERR | SDMMC_INT_HLE)
>   #define DW_MCI_ERROR_FLAGS	(DW_MCI_DATA_ERROR_FLAGS | \
>   				 DW_MCI_CMD_ERROR_FLAGS)
> -#define DW_MCI_DMA_THRESHOLD	16
>   
>   #define DW_MCI_FREQ_MAX	200000000	/* unit: HZ */
>   #define DW_MCI_FREQ_MIN	100000		/* unit: HZ */
> @@ -821,7 +820,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
>   	 * non-word-aligned buffers or lengths. Also, we don't bother
>   	 * with all the DMA setup overhead for short transfers.
>   	 */
> -	if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
> +	if (data->blocks * data->blksz < host->dma_threshold)
>   		return -EINVAL;
>   
>   	if (data->blksz & 3)
> @@ -3245,6 +3244,8 @@ int dw_mci_probe(struct dw_mci *host)
>   		goto err_clk_ciu;
>   	}
>   
> +	host->dma_threshold = 16;

I'd prefer to set it in dw_mci_alloc_host() instead of picking up
a random place to put it, for better code management.

> +
>   	if (host->rstc) {
>   		reset_control_assert(host->rstc);
>   		usleep_range(10, 50);
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 42e58be74ce09..fc7601fba849f 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -164,6 +164,8 @@ struct dw_mci {
>   	void __iomem		*fifo_reg;
>   	u32			data_addr_override;
>   	bool			wm_aligned;
> +	/* Configurable data byte threshold value for DMA transfer. */

No here, there is a long section of comment before struct dw_mci{ } that
describes each member of it, please add it there.

> +	u32			dma_threshold;
>   
>   	struct scatterlist	*sg;
>   	struct sg_mapping_iter	sg_miter;
> 


^ permalink raw reply

* Re: [net-next] net: airoha: Wait for TX to complete in airoha_dev_stop()
From: Lorenzo Bianconi @ 2026-04-14  8:57 UTC (permalink / raw)
  To: Paolo Abeni
  Cc: edumazet, kuba, davem, netdev, andrew+netdev, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260414082949.104611-1-pabeni@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 3065 bytes --]

> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> 
> For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
> ---
> net: airoha: Wait for TX to complete in airoha_dev_stop()
> 
> Wait for TX to complete in airoha_dev_stop routine before stopping the
> TX DMA and run airoha_qdma_cleanup_tx_queue routine. Moreover,
> start/stop TX/RX NAPIs in ndo_open()/ndo_stop() callbacks in order to be
> sure the TX NAPIs have completed before stopping the TX DMA engine in
> airoha_dev_stop routine.
> 
> > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> > index 8e4b043af4bc..9e40c8f375c1 100644
> > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> 
> [ ... ]
> 
> > @@ -1684,18 +1686,26 @@ static int airoha_dev_stop(struct net_device *dev)
> >  	struct airoha_qdma *qdma = port->qdma;
> >  	int i, err;
> >
> > -	netif_tx_disable(dev);
> >  	err = airoha_set_vip_for_gdm_port(port, false);
> >  	if (err)
> >  		return err;
> >
> > -	for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
> > -		netdev_tx_reset_subqueue(dev, i);
> > -
> >  	airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
> >  				    FE_PSE_PORT_DROP);
> >
> > +	netif_tx_disable(dev);
> >  	if (atomic_dec_and_test(&qdma->users)) {
> > +		u32 val;
> > +
> > +		/* Wait for TX to complete */
> > +		err = read_poll_timeout(airoha_qdma_rr, val,
> > +					!(val & GLOBAL_CFG_TX_DMA_BUSY_MASK),
> > +					USEC_PER_MSEC, 100 * USEC_PER_MSEC,
> > +					false, qdma, REG_QDMA_GLOBAL_CFG);
> > +		if (err)
> > +			return err;
> >                   ^^^^^^^^^^
> 
> Can this leave the device in an inconsistent state? When read_poll_timeout()
> fails (TX DMA busy for more than 100ms), airoha_dev_stop() returns an error
> immediately. However, atomic_dec_and_test(&qdma->users) has already
> decremented qdma->users to 0, but airoha_qdma_stop_napi() was never called,
> so all NAPIs remain enabled.
> 
> The networking core (__dev_close_many in net/core/dev.c) ignores the
> ndo_stop return value and marks the device as down regardless. When the
> device is later brought up again, airoha_dev_open() sees atomic_fetch_inc()
> return 0 (old value) and calls airoha_qdma_start_napi() -> napi_enable(),
> which hits BUG_ON(!test_bit(NAPI_STATE_SCHED, &val)) in napi_enable_locked()
> because the NAPI was never disabled.
> 
> The early return also skips the netdev_tx_reset_subqueue() calls at the end
> of the function.
> 
> Should the code either continue with cleanup on timeout (don't return), or
> ensure NAPI and DMA state are properly cleaned up before returning?

ack, I will fix it in v2.

Regards,
Lorenzo

> 
> > +
> > +		airoha_qdma_stop_napi(qdma);
> >  		airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
> >  				  GLOBAL_CFG_TX_DMA_EN_MASK |
> >  				  GLOBAL_CFG_RX_DMA_EN_MASK);
> 
> [ ... ]
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v2] Bluetooth: Add Broadcom channel priority commands
From: Neal Gompa @ 2026-04-14  8:59 UTC (permalink / raw)
  To: fnkl.kernel
  Cc: Sven Peter, Janne Grunau, Marcel Holtmann, Luiz Augusto von Dentz,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, linux-kernel, asahi, linux-arm-kernel,
	linux-bluetooth, netdev
In-Reply-To: <20260407-brcm-prio-v2-1-3f745edf49af@gmail.com>

On Tue, Apr 7, 2026 at 1:46 PM Sasha Finkelstein via B4 Relay
<devnull+fnkl.kernel.gmail.com@kernel.org> wrote:
>
> From: Sasha Finkelstein <fnkl.kernel@gmail.com>
>
> Certain Broadcom bluetooth chips (bcm4377/bcm4378/bcm438) need ACL
> streams carrying audio to be set as "high priority" using a vendor
> specific command to prevent 10-ish second-long dropouts whenever
> something does a device scan. This patch sends the command when the
> socket priority is set to TC_PRIO_INTERACTIVE, as BlueZ does for audio.
>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel@gmail.com>
> ---
> Changes in v2:
> - new ioctl got nack-ed, so let's use sk_priority as the trigger
> - Link to v1: https://lore.kernel.org/r/20260407-brcm-prio-v1-1-f38b17376640@gmail.com
> ---

Thank you so much for this!

Reviewed-by: Neal Gompa <neal@gompa.dev>


-- 
真実はいつも一つ!/ Always, there's only one truth!


^ permalink raw reply

* Re: [PATCH] arm64: dts: exynos850: Add SRAM node
From: Alexey Klimov @ 2026-04-14  9:00 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Alexey Klimov, Sam Protsenko, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Alim Akhtar
  Cc: linux-samsung-soc, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <2ff077e1-8983-4a41-bb21-5e4140545aa3@kernel.org>

On Mon Apr 13, 2026 at 4:23 PM BST, Krzysztof Kozlowski wrote:
> On 13/04/2026 16:52, Alexey Klimov wrote:
>> SRAM is used by the ACPM protocol to retrieve the ACPM channels
>> information and configuration data. Add the SRAM node.
>> 
>> Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
>> ---
>>  arch/arm64/boot/dts/exynos/exynos850.dtsi | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>> 
>> diff --git a/arch/arm64/boot/dts/exynos/exynos850.dtsi b/arch/arm64/boot/dts/exynos/exynos850.dtsi
>> index cb55015c8dce..cf4a6168846c 100644
>> --- a/arch/arm64/boot/dts/exynos/exynos850.dtsi
>> +++ b/arch/arm64/boot/dts/exynos/exynos850.dtsi
>> @@ -910,6 +910,14 @@ spi_2: spi@11d20000 {
>>  			};
>>  		};
>>  	};
>> +
>> +	apm_sram: sram@2039000 {
>> +		compatible = "mmio-sram";
>> +		reg = <0x0 0x2039000 0x40000>;
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		ranges = <0x0 0x0 0x2039000 0x40000>;
>
> You miss here children.

Thank you! I guess I should convert it to smth like this:

apm_sram: sram@2039000 {
		compatible = "mmio-sram";
		reg = <0x0 0x2039000 0x40000>;
		ranges = <0x0 0x0 0x2039000 0x40000>;
		#address-cells = <1>;
		#size-cells = <1>;

		acpm_sram_region: sram-section@0 {
			reg = <0x0 0x40000>;
		};
	};

And then later reference shmem = &acpm_sram_region from acpm node.

> Also, 'ranges' should be after 'reg'.

Thanks, will fix this.

FWIW this commit is a copy of commit 48e7821b26904
https://lore.kernel.org/r/20250207-gs101-acpm-dt-v4-1-230ba8663a2d@linaro.org

Best regards,
Alexey



^ permalink raw reply

* Re: [RFC PATCH 00/12] Add Linux RISC-V trace support via CoreSight
From: Zane Leung @ 2026-04-14  9:04 UTC (permalink / raw)
  To: Anup Patel
  Cc: robh, krzk+dt, conor+dt, palmer, pjw, gregkh, alexander.shishkin,
	irogers, coresight, peterz, mingo, namhyung, mark.rutland, jolsa,
	adrian.hunter, mchitale, atish.patra, andrew.jones, sunilvl,
	linux-riscv, linux-kernel, anup.patel, mayuresh.chitale,
	zhuangqiubin, suzuki.poulose, mike.leach, james.clark,
	alexander.shishkin, linux-arm-kernel
In-Reply-To: <CAAhSdy2Sx98qcCMBVF+_BV1G-syrO74Y_S298hMwkW+vgLtb5Q@mail.gmail.com>


On 4/14/2026 3:23 PM, Anup Patel wrote:
> On Tue, Apr 14, 2026 at 9:12 AM Zane Leung <liangzhen@linux.spacemit.com> wrote:
>> From: liangzhen <zhen.liang@spacemit.com>
>>
>> This series adds Linux RISC-V trace support via CoreSight, implementing RISC-V
>> trace drivers within the CoreSight framework and integrating them with perf tools.
>> The K3 SoC contains RISC-V Encoder, Funnel, ATB, CoreSight Funnel, and CoreSight TMC
>> components, which can be directly leveraged through the existing CoreSight infrastructure.
>>
>> Linux RISC-V trace support form Anup Patel:
>> (https://patchwork.kernel.org/project/linux-riscv/cover/20260225062448.4027948-1-anup.patel@oss.qualcomm.com/)
>> which currently lacks ATB component support and guidance on reusing CoreSight components.
> What stops you from adding RISC-V trace funnel and ATB bridge drivers
> on top of this series ?
>
Firstly, my works started much earlier than this series. Secondly, it is difficult to add the coresight funnel and coresight tmc components to this series. Based on the coresight framework, I can directly reuse them.

>
>> The series includes:
>> - RISC-V trace driver implementation within the CoreSight framework
> The RISC-V trace very different from the CoreSight framework in many ways:
> 1) Types of components supported
> 2) Trace packet formats
> 3) The way MMIO based components are discoverd
> 4) ... and more ...
1) I believe that RISC-V tracing is coresight-alike, where have encoders/funnel/sink/bridge that are described through DT and controlled by MMIO. 
2) I think the difference in package format is nothing more than the coresight frame generated by the ATB component to distinguish the trace source. After removing it, it becomes riscv trace data.
3) The current CoreSight framework code does not introduce this mechanism, it is described through DT.
>> - RISC-V Trace Encoder, Funnel, and ATB Bridge drivers as CoreSight devices
>> - RISC-V trace PMU record capabilities and parsing events in perf.
>> - RISC-V Nexus Trace decoder for perf tools
>>
>> Any comments or suggestions are welcome.
>>
>> Verification on K3 SoC:
>> To verify this patch series on K3 hardware, the following device tree are required:
>> 1. RISC-V Trace Encoder node (8)
>> 2. RISC-V ATB Bridge node (8)
>> 3. RISC-V Trace Funnel node (2)
>> 3. CoreSight Funnel configuration for RISC-V (1)
>> 4. CoreSight TMC configuration for trace buffer (1)
>>
>> /{
>>         dummy_clk: apb-pclk {
>>                 compatible = "fixed-clock";
>>                 #clock-cells = <0x0>;
>>                 clock-output-names = "clk14mhz";
>>                 clock-frequency = <14000000>;
>>         };
>>
>>
>>         soc: soc {
>>                 #address-cells = <2>;
>>                 #size-cells = <2>;
>>
>>                 encoder0: encoder@d9002000 {
>>                         compatible = "riscv,trace-encoder";
>>                         reg = <0x0 0xd9002000 0x0 0x1000>;
>>                         cpus = <&cpu_0>;
>>                         out-ports {
>>                                 port {
>>                                         cluster0_encoder0_out_port: endpoint {
>>                                                 remote-endpoint = <&cluster0_bridge0_in_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>
>>                 bridge0: bridge@d9003000 {
>>                         compatible = "riscv,trace-atbbridge";
>>                         reg = <0x0 0xd9003000 0x0 0x1000>;
>>                         cpus = <&cpu_0>;
>>                         out-ports {
>>                                 port {
>>                                         cluster0_bridge0_out_port: endpoint {
>>                                                 remote-endpoint = <&cluster0_funnel_in_port0>;
>>                                         };
>>                                 };
>>                         };
>>                         in-ports {
>>                                 port {
>>                                         cluster0_bridge0_in_port: endpoint {
>>                                                 remote-endpoint = <&cluster0_encoder0_out_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>
>> ...
>>
>>                 cluster0_funnel: funnel@d9000000 {
>>                         compatible = "riscv,trace-funnel";
>>                         reg = <0x0 0xd9000000 0x0 0x1000>;
>>                         cpus = <&cpu_0>, <&cpu_1>, <&cpu_2>, <&cpu_3>;
>>                         riscv,timestamp-present;
>>                         out-ports {
>>                                 port {
>>                                         cluster0_funnel_out_port: endpoint {
>>                                                 remote-endpoint = <&main_funnel_in_port0>;
>>                                         };
>>                                 };
>>                         };
>>                         in-ports {
>>                                 #address-cells = <1>;
>>                                 #size-cells = <0>;
>>
>>                                 port@0 {
>>                                         reg = <0>;
>>                                         cluster0_funnel_in_port0: endpoint {
>>                                                 remote-endpoint = <&cluster0_bridge0_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@1 {
>>                                         reg = <1>;
>>                                         cluster0_funnel_in_port1: endpoint {
>>                                                 remote-endpoint = <&cluster0_bridge1_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@2 {
>>                                         reg = <2>;
>>                                         cluster0_funnel_in_port2: endpoint {
>>                                                 remote-endpoint = <&cluster0_bridge2_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@3 {
>>                                         reg = <3>;
>>                                         cluster0_funnel_in_port3: endpoint {
>>                                                 remote-endpoint = <&cluster0_bridge3_out_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>
>>                 cluster1_funnel: funnel@d9010000 {
>>                         compatible = "riscv,trace-funnel";
>>                         reg = <0x0 0xd9010000 0x0 0x1000>;
>>                         cpus = <&cpu_4>, <&cpu_5>, <&cpu_6>, <&cpu_7>;
>>                         riscv,timestamp-present;
>>                         out-ports {
>>                                 port {
>>                                         cluster1_funnel_out_port: endpoint {
>>                                                 remote-endpoint = <&main_funnel_in_port1>;
>>                                         };
>>                                 };
>>                         };
>>                         in-ports {
>>                                 #address-cells = <1>;
>>                                 #size-cells = <0>;
>>
>>                                 port@0 {
>>                                         reg = <0>;
>>                                         cluster1_funnel_in_port0: endpoint {
>>                                                 remote-endpoint = <&cluster1_bridge0_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@1 {
>>                                         reg = <1>;
>>                                         cluster1_funnel_in_port1: endpoint {
>>                                                 remote-endpoint = <&cluster1_bridge1_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@2 {
>>                                         reg = <2>;
>>                                         cluster1_funnel_in_port2: endpoint {
>>                                                 remote-endpoint = <&cluster1_bridge2_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@3 {
>>                                         reg = <3>;
>>                                         cluster1_funnel_in_port3: endpoint {
>>                                                 remote-endpoint = <&cluster1_bridge3_out_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>
>>                 main_funnel: funnel@d9042000 {
>>                         compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
> Is it legally allowed to mix and match ARM coresight IPs with
> RISC-V trace components at hardware level ?
The ATB Bridge allows sending RISC-V trace to Arm CoreSight infrastructure (instead of RISC-V compliant sink defined in this document) as an ATB initiator.  see: 
https://github.com/riscv-non-isa/riscv-nexus-trace/blob/105dc1c349556622e4d202d22b584a887ded462f/docs/RISC-V-Trace-Control-Interface.adoc#L184
For ATB Bridge, read trace using Coresight components (ETB/TMC/TPIU). see:
https://github.com/riscv-non-isa/riscv-nexus-trace/blob/105dc1c349556622e4d202d22b584a887ded462f/docs/RISC-V-Trace-Control-Interface.adoc#L1684
>
>>                         reg = <0x0 0xd9042000 0x0 0x1000>;
>>                         clocks = <&dummy_clk>;
>>                         clock-names = "apb_pclk";
>>                         out-ports {
>>                                 port {
>>                                         main_funnel_out_port: endpoint {
>>                                                 remote-endpoint = <&etf_in_port>;
>>                                         };
>>                                 };
>>                         };
>>                         in-ports {
>>                                 #address-cells = <1>;
>>                                 #size-cells = <0>;
>>
>>                                 port@0 {
>>                                         reg = <0>;
>>                                         main_funnel_in_port0: endpoint {
>>                                                 remote-endpoint = <&cluster0_funnel_out_port>;
>>                                         };
>>                                 };
>>
>>                                 port@1 {
>>                                         reg = <1>;
>>                                         main_funnel_in_port1: endpoint {
>>                                                 remote-endpoint = <&cluster1_funnel_out_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>
>>                 etf: etf@d9043000 {
>>                         compatible = "arm,coresight-tmc", "arm,primecell";
>>                         reg = <0x0 0xd9043000 0x0 0x1000>;
>>                         clocks = <&dummy_clk>;
>>                         clock-names = "apb_pclk";
>>                         out-ports {
>>                                 port {
>>                                         etf_out_port: endpoint {
>>                                                 remote-endpoint = <&etr_in_port>;
>>                                         };
>>                                 };
>>                         };
>>                         in-ports {
>>                                 port {
>>                                         etf_in_port: endpoint {
>>                                                 remote-endpoint = <&main_funnel_out_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>
>>                 etr: etr@d9044000 {
>>                         compatible = "arm,coresight-tmc", "arm,primecell";
>>                         reg = <0x0 0xd9044000 0x0 0x1000>;
>>                         clocks = <&dummy_clk>;
>>                         clock-names = "apb_pclk";
>>                         arm,scatter-gather;
>>                         in-ports {
>>                                 port {
>>                                         etr_in_port: endpoint {
>>                                                 remote-endpoint = <&etf_out_port>;
>>                                         };
>>                                 };
>>                         };
>>                 };
>>         };
>> };
>>
>> Verification case:
>>
>> ~ # perf list pmu
>>   rvtrace//                                          [Kernel PMU event]
>>
>> ~ # perf record -e rvtrace/@tmc_etr0/ --per-thread uname
>> Linux
>> [ perf record: Woken up 1 times to write data ]
>> [ perf record: Captured and wrote 0.191 MB perf.data ]
>> ~ # perf script
>>            uname     137 [003]          1           branches:  ffffffff80931470 rvtrace_poll_bit+0x38 ([kernel.kallsyms]) => ffffffff80931492 rvtrace_poll_bit+0x5a ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff809328a6 encoder_enable_hw+0x252 ([kernel.kallsyms]) => ffffffff809328ba encoder_enable_hw+0x266 ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff80932c4a encoder_enable+0x82 ([kernel.kallsyms]) => ffffffff80932c36 encoder_enable+0x6e ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff80928198 etm_event_start+0xf0 ([kernel.kallsyms]) => ffffffff809281aa etm_event_start+0x102 ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff809281e6 etm_event_start+0x13e ([kernel.kallsyms]) => ffffffff8092755e coresight_get_sink_id+0x16 ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff8092820e etm_event_start+0x166 ([kernel.kallsyms]) => ffffffff80928226 etm_event_start+0x17e ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff801c3bb4 perf_report_aux_output_id+0x0 ([kernel.kallsyms]) => ffffffff801c3bd6 perf_report_aux_output_id+0x22 ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff801c3c5a perf_report_aux_output_id+0xa6 ([kernel.kallsyms]) => ffffffff801c3bf0 perf_report_aux_output_id+0x3c ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff801c3c40 perf_report_aux_output_id+0x8c ([kernel.kallsyms]) => ffffffff801c3aea __perf_event_header__init_id+0x2a ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff801c3b42 __perf_event_header__init_id+0x82 ([kernel.kallsyms]) => ffffffff801c3b4a __perf_event_header__init_id+0x8a ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff801c3bb0 __perf_event_header__init_id+0xf0 ([kernel.kallsyms]) => ffffffff801c3b58 __perf_event_header__init_id+0x98 ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff8004c658 __task_pid_nr_ns+0x0 ([kernel.kallsyms]) => ffffffff8004c696 __task_pid_nr_ns+0x3e ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff8004c71e __task_pid_nr_ns+0xc6 ([kernel.kallsyms]) => ffffffff8004c6a4 __task_pid_nr_ns+0x4c ([kernel.kallsyms])
>>            uname     137 [003]          1           branches:  ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms]) => ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms])
>> ...
>>
>> liangzhen (12):
>>   coresight: Add RISC-V support to CoreSight tracing
>>   coresight: Initial implementation of RISC-V trace driver
>>   coresight: Add RISC-V Trace Encoder driver
>>   coresight: Add RISC-V Trace Funnel driver
>>   coresight: Add RISC-V Trace ATB Bridge driver
>>   coresight rvtrace: Add timestamp component support for encoder and
>>     funnel
>>   coresight: Add RISC-V PMU name support
>>   perf tools: riscv: making rvtrace PMU listable
>>   perf tools: Add RISC-V trace PMU record capabilities
>>   perf tools: Add Nexus RISC-V Trace decoder
>>   perf symbols: Add RISC-V PLT entry sizes
>>   perf tools: Integrate RISC-V trace decoder into auxtrace
>>
>>  drivers/hwtracing/Kconfig                     |    2 +
>>  drivers/hwtracing/coresight/Kconfig           |   46 +-
>>  drivers/hwtracing/coresight/Makefile          |    6 +
>>  drivers/hwtracing/coresight/coresight-core.c  |    8 +
>>  .../hwtracing/coresight/coresight-etm-perf.c  |    1 -
>>  .../hwtracing/coresight/coresight-etm-perf.h  |   21 +
>>  .../hwtracing/coresight/coresight-platform.c  |    1 -
>>  .../hwtracing/coresight/coresight-tmc-etf.c   |    4 +
>>  .../hwtracing/coresight/coresight-tmc-etr.c   |    4 +
>>  .../hwtracing/coresight/rvtrace-atbbridge.c   |  239 +++
>>  drivers/hwtracing/coresight/rvtrace-core.c    |  135 ++
>>  .../coresight/rvtrace-encoder-core.c          |  562 +++++++
>>  .../coresight/rvtrace-encoder-sysfs.c         |  363 +++++
>>  drivers/hwtracing/coresight/rvtrace-encoder.h |  151 ++
>>  drivers/hwtracing/coresight/rvtrace-funnel.c  |  337 ++++
>>  drivers/hwtracing/coresight/rvtrace-funnel.h  |   39 +
>>  .../hwtracing/coresight/rvtrace-timestamp.c   |  278 ++++
>>  .../hwtracing/coresight/rvtrace-timestamp.h   |   64 +
>>  include/linux/coresight-pmu.h                 |    4 +
>>  include/linux/rvtrace.h                       |  116 ++
>>  tools/arch/riscv/include/asm/insn.h           |  645 ++++++++
>>  tools/perf/arch/riscv/util/Build              |    2 +
>>  tools/perf/arch/riscv/util/auxtrace.c         |  490 ++++++
>>  tools/perf/arch/riscv/util/pmu.c              |   20 +
>>  tools/perf/util/Build                         |    3 +
>>  tools/perf/util/auxtrace.c                    |    4 +
>>  tools/perf/util/auxtrace.h                    |    1 +
>>  tools/perf/util/nexus-rv-decoder/Build        |    1 +
>>  .../util/nexus-rv-decoder/nexus-rv-decoder.c  | 1364 +++++++++++++++++
>>  .../util/nexus-rv-decoder/nexus-rv-decoder.h  |  139 ++
>>  .../perf/util/nexus-rv-decoder/nexus-rv-msg.h |  190 +++
>>  tools/perf/util/rvtrace-decoder.c             | 1039 +++++++++++++
>>  tools/perf/util/rvtrace.h                     |   40 +
>>  tools/perf/util/symbol-elf.c                  |    4 +
>>  34 files changed, 6320 insertions(+), 3 deletions(-)
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-atbbridge.c
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-core.c
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-core.c
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-sysfs.c
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder.h
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.c
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.h
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.c
>>  create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.h
>>  create mode 100644 include/linux/rvtrace.h
>>  create mode 100644 tools/arch/riscv/include/asm/insn.h
>>  create mode 100644 tools/perf/arch/riscv/util/auxtrace.c
>>  create mode 100644 tools/perf/arch/riscv/util/pmu.c
>>  create mode 100644 tools/perf/util/nexus-rv-decoder/Build
>>  create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.c
>>  create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.h
>>  create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-msg.h
>>  create mode 100644 tools/perf/util/rvtrace-decoder.c
>>  create mode 100644 tools/perf/util/rvtrace.h
>>
>> --
>> 2.34.1
>>
> NACK to this approach of retrofitting RISC-V trace into ARM coresight.
I agree that integrating RISC-V trace directly into CoreSight is not a good approach, so I think we should abstract some of the logic of coresight and reuse it in RISC-V Trace.
>
> Regards,
> Anup

Thanks,
Zane


^ permalink raw reply

* Re: [PATCH] arm64: dts: exynos850: Add SRAM node
From: Krzysztof Kozlowski @ 2026-04-14  9:08 UTC (permalink / raw)
  To: Alexey Klimov, Sam Protsenko, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alim Akhtar
  Cc: linux-samsung-soc, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <DHSR70EGYY4N.2EA2HWIXJR7QR@linaro.org>

On 14/04/2026 11:00, Alexey Klimov wrote:
> On Mon Apr 13, 2026 at 4:23 PM BST, Krzysztof Kozlowski wrote:
>> On 13/04/2026 16:52, Alexey Klimov wrote:
>>> SRAM is used by the ACPM protocol to retrieve the ACPM channels
>>> information and configuration data. Add the SRAM node.
>>>
>>> Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
>>> ---
>>>  arch/arm64/boot/dts/exynos/exynos850.dtsi | 8 ++++++++
>>>  1 file changed, 8 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/exynos/exynos850.dtsi b/arch/arm64/boot/dts/exynos/exynos850.dtsi
>>> index cb55015c8dce..cf4a6168846c 100644
>>> --- a/arch/arm64/boot/dts/exynos/exynos850.dtsi
>>> +++ b/arch/arm64/boot/dts/exynos/exynos850.dtsi
>>> @@ -910,6 +910,14 @@ spi_2: spi@11d20000 {
>>>  			};
>>>  		};
>>>  	};
>>> +
>>> +	apm_sram: sram@2039000 {
>>> +		compatible = "mmio-sram";
>>> +		reg = <0x0 0x2039000 0x40000>;
>>> +		#address-cells = <1>;
>>> +		#size-cells = <1>;
>>> +		ranges = <0x0 0x0 0x2039000 0x40000>;
>>
>> You miss here children.
> 
> Thank you! I guess I should convert it to smth like this:
> 
> apm_sram: sram@2039000 {
> 		compatible = "mmio-sram";
> 		reg = <0x0 0x2039000 0x40000>;
> 		ranges = <0x0 0x0 0x2039000 0x40000>;
> 		#address-cells = <1>;
> 		#size-cells = <1>;
> 
> 		acpm_sram_region: sram-section@0 {
> 			reg = <0x0 0x40000>;

This covers entire block, so feels pointless. Maybe requirement of
children should be dropped. What's the point of having children? Why
does the driver need them?

> 		};
> 	};
> 
> And then later reference shmem = &acpm_sram_region from acpm node.
> 
>> Also, 'ranges' should be after 'reg'.
> 
> Thanks, will fix this.
> 
> FWIW this commit is a copy of commit 48e7821b26904
> https://lore.kernel.org/r/20250207-gs101-acpm-dt-v4-1-230ba8663a2d@linaro.org


Huh, we should fix that one as well.


Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 0/3] mm: split the file's i_mmap tree for NUMA
From: Huang Shijie @ 2026-04-14  9:11 UTC (permalink / raw)
  To: Mateusz Guzik
  Cc: akpm, viro, brauner, linux-mm, linux-kernel, linux-arm-kernel,
	linux-fsdevel, muchun.song, osalvador, linux-trace-kernel,
	linux-perf-users, linux-parisc, nvdimm, zhongyuan, fangbaoshun,
	yingzhiwei
In-Reply-To: <76pfiwabdgsej6q2yxfh3efuqvsyg7mt7rvl5itzzjyhdrto5r@53viaxsackzv>

On Mon, Apr 13, 2026 at 05:33:21PM +0200, Mateusz Guzik wrote:
> On Mon, Apr 13, 2026 at 02:20:39PM +0800, Huang Shijie wrote:
> >   In NUMA, there are maybe many NUMA nodes and many CPUs.
> > For example, a Hygon's server has 12 NUMA nodes, and 384 CPUs.
> > In the UnixBench tests, there is a test "execl" which tests
> > the execve system call.
> > 
> >   When we test our server with "./Run -c 384 execl",
> > the test result is not good enough. The i_mmap locks contended heavily on
> > "libc.so" and "ld.so". For example, the i_mmap tree for "libc.so" can have 
> > over 6000 VMAs, all the VMAs can be in different NUMA mode.
> > The insert/remove operations do not run quickly enough.
> > 
> > patch 1 & patch 2 are try to hide the direct access of i_mmap.
> > patch 3 splits the i_mmap into sibling trees, and we can get better 
> > performance with this patch set:
> >     we can get 77% performance improvement(10 times average)
> > 
> 
> To my reading you kept the lock as-is and only distributed the protected
> state.
> 
> While I don't doubt the improvement, I'm confident should you take a
> look at the profile you are going to find this still does not scale with
> rwsem being one of the problems (there are other global locks, some of
> which have experimental patches for).
IMHO, when the number of VMAs in the i_mmap is very large, only optimise the rwsem
lock does not help too much for our NUMA case.

In our NUMA server, the remote access could be the major issue.


> 
> Apart from that this does nothing to help high core systems which are
> all one node, which imo puts another question mark on this specific
> proposal.
Yes, this patch set only focus on the NUMA case.
The one-node case should use the original i_mmap.

Maybe I can add a new config, CONFIG_SPILT_I_MMAP. The config is disabled
by default, and enabled when the NUMA node is not one.

> 
> Of course one may question whether a RB tree is the right choice here,
> it may be the lock-protected cost can go way down with merely a better
> data structure.
> 
> Regardless of that, for actual scalability, there will be no way around
> decentralazing locking around this and partitioning per some core count
> (not just by numa awareness).
> 
> Decentralizing locking is definitely possible, but I have not looked
> into specifics of how problematic it is. Best case scenario it will
> merely with separate locks. Worst case scenario something needs a fully
> stabilized state for traversal, in that case another rw lock can be
Yes. 

The traversal may need to hold many locks.

> slapped around this, creating locking order read lock -> per-subset
> write lock -- this will suffer scalability due to the read locking, but
> it will still scale drastically better as apart from that there will be
> no serialization. In this setting the problematic consumer will write
> lock the new thing to stabilize the state.
> 
> So my non-maintainer opinion is that the patchset is not worth it as it
> fails to address anything for significantly more common and already
> affected setups.
This patch set is to reduce the remote access latency for insert/remove VMA
in NUMA.

> 
> Have you looked into splitting the lock?
> 
I ever tried. 

But there are two disadvantages:
  1.) The traversal may need to hold many locks which makes the
      code very horrible.

  2.) Even we split the locks. Each lock protects a tree, when the tree becomes
      big enough, the VMA insert/remove will also become slow in NUMA.
      The reason is that the tree has VMAs in different NUMA nodes.
      

Thanks
Huang Shijie



^ permalink raw reply

* [PATCH 0/3] iio: adc: xilinx-ams: refactor alarm handling to table-driven design
From: Guilherme Ivo Bozi @ 2026-04-14  9:29 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi

This series addresses significant code duplication in alarm handling
logic across the Xilinx AMS IIO driver.

An analysis of the codebase (ArKanjo explorer) revealed multiple
duplicated mappings between scan_index, alarm bits, and register
offsets.

To address this, the series introduces a centralized table-driven
mapping (alarm_map) that replaces multiple switch statements spread
across the driver.

This improves:
- maintainability (single source of truth for mappings)
- readability (removes repeated switch logic)
- extensibility (new alarms require only table updates)

No functional changes are intended.

Series overview:
- Patch 1: fix out-of-bounds channel lookup 
- Patch 2: convert mutex handling to guard(mutex) 
- Patch 3: introduce table-driven alarm mapping

Guilherme Ivo Bozi (3):
  iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event
    handling
  iio: adc: xilinx-ams: use guard(mutex) for automatic locking
  iio: adc: xilinx-ams: refactor alarm mapping to table-driven approach

 drivers/iio/adc/xilinx-ams.c | 192 +++++++++++++----------------------
 1 file changed, 73 insertions(+), 119 deletions(-)

-- 
2.47.3



^ permalink raw reply

* [PATCH 1/3] iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event handling
From: Guilherme Ivo Bozi @ 2026-04-14  9:29 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi
In-Reply-To: <20260414093018.7153-1-guilherme.bozi@usp.br>

ams_event_to_channel() may return a pointer past the end of
dev->channels when no matching scan_index is found. This can lead
to invalid memory access in ams_handle_event().

Add a bounds check in ams_event_to_channel() and return NULL when
no channel is found. Also guard the caller to safely handle this
case.

Fixes: <d5c70627a79455154f5f636096abe6fe57510605>
Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
---
 drivers/iio/adc/xilinx-ams.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index 124470c92529..f364e69a5a0d 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -871,6 +871,9 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
 		if (dev->channels[i].scan_index == scan_index)
 			break;
 
+	if (i >= dev->num_channels)
+		return NULL;
+
 	return &dev->channels[i];
 }
 
@@ -1012,6 +1015,8 @@ static void ams_handle_event(struct iio_dev *indio_dev, u32 event)
 	const struct iio_chan_spec *chan;
 
 	chan = ams_event_to_channel(indio_dev, event);
+	if (!chan)
+		return;
 
 	if (chan->type == IIO_TEMP) {
 		/*
-- 
2.47.3



^ permalink raw reply related

* [PATCH 2/3] iio: adc: xilinx-ams: use guard(mutex) for automatic locking
From: Guilherme Ivo Bozi @ 2026-04-14  9:29 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi
In-Reply-To: <20260414093018.7153-1-guilherme.bozi@usp.br>

Replace open-coded mutex_lock()/mutex_unlock() pairs with
guard(mutex) to simplify locking and ensure proper unlock on
all control flow paths.

This removes explicit unlock handling, reduces boilerplate,
and avoids potential mistakes in error paths while keeping
the behavior unchanged.

Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
---
 drivers/iio/adc/xilinx-ams.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index f364e69a5a0d..1d84310b61a9 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -720,22 +720,20 @@ static int ams_read_raw(struct iio_dev *indio_dev,
 	int ret;
 
 	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&ams->lock);
+	case IIO_CHAN_INFO_RAW: {
+		guard(mutex)(&ams->lock);
 		if (chan->scan_index >= AMS_CTRL_SEQ_BASE) {
 			ret = ams_read_vcc_reg(ams, chan->address, val);
 			if (ret)
-				goto unlock_mutex;
+				return ret;
 			ams_enable_channel_sequence(indio_dev);
 		} else if (chan->scan_index >= AMS_PS_SEQ_MAX)
 			*val = readl(ams->pl_base + chan->address);
 		else
 			*val = readl(ams->ps_base + chan->address);
 
-		ret = IIO_VAL_INT;
-unlock_mutex:
-		mutex_unlock(&ams->lock);
-		return ret;
+		return IIO_VAL_INT;
+	}
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -939,7 +937,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
 
 	alarm = ams_get_alarm_mask(chan->scan_index);
 
-	mutex_lock(&ams->lock);
+	guard(mutex)(&ams->lock);
 
 	if (state)
 		ams->alarm_mask |= alarm;
@@ -948,8 +946,6 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
 
 	ams_update_alarm(ams, ams->alarm_mask);
 
-	mutex_unlock(&ams->lock);
-
 	return 0;
 }
 
@@ -962,15 +958,13 @@ static int ams_read_event_value(struct iio_dev *indio_dev,
 	struct ams *ams = iio_priv(indio_dev);
 	unsigned int offset = ams_get_alarm_offset(chan->scan_index, dir);
 
-	mutex_lock(&ams->lock);
+	guard(mutex)(&ams->lock);
 
 	if (chan->scan_index >= AMS_PS_SEQ_MAX)
 		*val = readl(ams->pl_base + offset);
 	else
 		*val = readl(ams->ps_base + offset);
 
-	mutex_unlock(&ams->lock);
-
 	return IIO_VAL_INT;
 }
 
@@ -983,7 +977,7 @@ static int ams_write_event_value(struct iio_dev *indio_dev,
 	struct ams *ams = iio_priv(indio_dev);
 	unsigned int offset;
 
-	mutex_lock(&ams->lock);
+	guard(mutex)(&ams->lock);
 
 	/* Set temperature channel threshold to direct threshold */
 	if (chan->type == IIO_TEMP) {
@@ -1005,8 +999,6 @@ static int ams_write_event_value(struct iio_dev *indio_dev,
 	else
 		writel(val, ams->ps_base + offset);
 
-	mutex_unlock(&ams->lock);
-
 	return 0;
 }
 
-- 
2.47.3



^ permalink raw reply related

* [PATCH 3/3] iio: adc: xilinx-ams: refactor alarm mapping to table-driven approach
From: Guilherme Ivo Bozi @ 2026-04-14  9:29 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi
In-Reply-To: <20260414093018.7153-1-guilherme.bozi@usp.br>

Replace multiple open-coded switch statements that map between
scan_index, alarm bits, and register offsets with a centralized
table-driven approach.

Introduce a struct-based alarm_map to describe the relationship
between scan indices and alarm offsets, and add a helper to
translate scan_index to event IDs. This removes duplicated logic
across ams_get_alarm_offset(), ams_event_to_channel(), and
ams_get_alarm_mask().

The new approach improves maintainability, reduces code size,
and makes it easier to extend or modify alarm mappings in the
future, while preserving existing behavior.

Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
---
 drivers/iio/adc/xilinx-ams.c | 163 +++++++++++++----------------------
 1 file changed, 60 insertions(+), 103 deletions(-)

diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index 1d84310b61a9..d5ed2e787641 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -102,6 +102,7 @@
 #define AMS_PS_SEQ_MASK			GENMASK(21, 0)
 #define AMS_PL_SEQ_MASK			GENMASK_ULL(59, 22)
 
+#define AMS_ALARM_INVALID		-1
 #define AMS_ALARM_TEMP			0x140
 #define AMS_ALARM_SUPPLY1		0x144
 #define AMS_ALARM_SUPPLY2		0x148
@@ -763,9 +764,51 @@ static int ams_read_raw(struct iio_dev *indio_dev,
 	}
 }
 
+struct ams_alarm_map {
+	enum ams_ps_pl_seq scan_index;
+	int base_offset;
+};
+
+/*
+ * Array index matches enum ams_alarm_bit.
+ * Entries with base_offset == AMS_ALARM_INVALID are unused/invalid
+ * (e.g. RESERVED) and must be skipped.
+ */
+static const struct ams_alarm_map alarm_map[] = {
+	[AMS_ALARM_BIT_TEMP] = { AMS_SEQ_TEMP, AMS_ALARM_TEMP },
+	[AMS_ALARM_BIT_SUPPLY1] = { AMS_SEQ_SUPPLY1, AMS_ALARM_SUPPLY1 },
+	[AMS_ALARM_BIT_SUPPLY2] = { AMS_SEQ_SUPPLY2, AMS_ALARM_SUPPLY2 },
+	[AMS_ALARM_BIT_SUPPLY3] = { AMS_SEQ_SUPPLY3, AMS_ALARM_SUPPLY3 },
+	[AMS_ALARM_BIT_SUPPLY4] = { AMS_SEQ_SUPPLY4, AMS_ALARM_SUPPLY4 },
+	[AMS_ALARM_BIT_SUPPLY5] = { AMS_SEQ_SUPPLY5, AMS_ALARM_SUPPLY5 },
+	[AMS_ALARM_BIT_SUPPLY6] = { AMS_SEQ_SUPPLY6, AMS_ALARM_SUPPLY6 },
+	[AMS_ALARM_BIT_RESERVED] = { 0, AMS_ALARM_INVALID },
+	[AMS_ALARM_BIT_SUPPLY7] = { AMS_SEQ_SUPPLY7, AMS_ALARM_SUPPLY7 },
+	[AMS_ALARM_BIT_SUPPLY8] = { AMS_SEQ_SUPPLY8, AMS_ALARM_SUPPLY8 },
+	[AMS_ALARM_BIT_SUPPLY9] = { AMS_SEQ_SUPPLY9, AMS_ALARM_SUPPLY9 },
+	[AMS_ALARM_BIT_SUPPLY10] = { AMS_SEQ_SUPPLY10, AMS_ALARM_SUPPLY10 },
+	[AMS_ALARM_BIT_VCCAMS] = { AMS_SEQ_VCCAMS, AMS_ALARM_VCCAMS },
+	[AMS_ALARM_BIT_TEMP_REMOTE] = { AMS_SEQ_TEMP_REMOTE, AMS_ALARM_TEMP_REMOTE }
+};
+
+static int ams_scan_index_to_event(int scan_index)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(alarm_map); i++) {
+		if (alarm_map[i].base_offset == AMS_ALARM_INVALID)
+			continue;
+
+		if (alarm_map[i].scan_index == scan_index)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
 static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir)
 {
-	int offset;
+	int offset, event;
 
 	if (scan_index >= AMS_PS_SEQ_MAX)
 		scan_index -= AMS_PS_SEQ_MAX;
@@ -779,36 +822,11 @@ static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir)
 		offset = 0;
 	}
 
-	switch (scan_index) {
-	case AMS_SEQ_TEMP:
-		return AMS_ALARM_TEMP + offset;
-	case AMS_SEQ_SUPPLY1:
-		return AMS_ALARM_SUPPLY1 + offset;
-	case AMS_SEQ_SUPPLY2:
-		return AMS_ALARM_SUPPLY2 + offset;
-	case AMS_SEQ_SUPPLY3:
-		return AMS_ALARM_SUPPLY3 + offset;
-	case AMS_SEQ_SUPPLY4:
-		return AMS_ALARM_SUPPLY4 + offset;
-	case AMS_SEQ_SUPPLY5:
-		return AMS_ALARM_SUPPLY5 + offset;
-	case AMS_SEQ_SUPPLY6:
-		return AMS_ALARM_SUPPLY6 + offset;
-	case AMS_SEQ_SUPPLY7:
-		return AMS_ALARM_SUPPLY7 + offset;
-	case AMS_SEQ_SUPPLY8:
-		return AMS_ALARM_SUPPLY8 + offset;
-	case AMS_SEQ_SUPPLY9:
-		return AMS_ALARM_SUPPLY9 + offset;
-	case AMS_SEQ_SUPPLY10:
-		return AMS_ALARM_SUPPLY10 + offset;
-	case AMS_SEQ_VCCAMS:
-		return AMS_ALARM_VCCAMS + offset;
-	case AMS_SEQ_TEMP_REMOTE:
-		return AMS_ALARM_TEMP_REMOTE + offset;
-	default:
+	event = ams_scan_index_to_event(scan_index);
+	if (event < 0 || alarm_map[event].base_offset == AMS_ALARM_INVALID)
 		return 0;
-	}
+
+	return alarm_map[event].base_offset + offset;
 }
 
 static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
@@ -821,49 +839,13 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
 		scan_index = AMS_PS_SEQ_MAX;
 	}
 
-	switch (event) {
-	case AMS_ALARM_BIT_TEMP:
-		scan_index += AMS_SEQ_TEMP;
-		break;
-	case AMS_ALARM_BIT_SUPPLY1:
-		scan_index += AMS_SEQ_SUPPLY1;
-		break;
-	case AMS_ALARM_BIT_SUPPLY2:
-		scan_index += AMS_SEQ_SUPPLY2;
-		break;
-	case AMS_ALARM_BIT_SUPPLY3:
-		scan_index += AMS_SEQ_SUPPLY3;
-		break;
-	case AMS_ALARM_BIT_SUPPLY4:
-		scan_index += AMS_SEQ_SUPPLY4;
-		break;
-	case AMS_ALARM_BIT_SUPPLY5:
-		scan_index += AMS_SEQ_SUPPLY5;
-		break;
-	case AMS_ALARM_BIT_SUPPLY6:
-		scan_index += AMS_SEQ_SUPPLY6;
-		break;
-	case AMS_ALARM_BIT_SUPPLY7:
-		scan_index += AMS_SEQ_SUPPLY7;
-		break;
-	case AMS_ALARM_BIT_SUPPLY8:
-		scan_index += AMS_SEQ_SUPPLY8;
-		break;
-	case AMS_ALARM_BIT_SUPPLY9:
-		scan_index += AMS_SEQ_SUPPLY9;
-		break;
-	case AMS_ALARM_BIT_SUPPLY10:
-		scan_index += AMS_SEQ_SUPPLY10;
-		break;
-	case AMS_ALARM_BIT_VCCAMS:
-		scan_index += AMS_SEQ_VCCAMS;
-		break;
-	case AMS_ALARM_BIT_TEMP_REMOTE:
-		scan_index += AMS_SEQ_TEMP_REMOTE;
-		break;
-	default:
-		break;
-	}
+	if (event < 0 || event >= ARRAY_SIZE(alarm_map))
+		return NULL;
+
+	if (alarm_map[event].base_offset == AMS_ALARM_INVALID)
+		return NULL;
+
+	scan_index += alarm_map[event].scan_index;
 
 	for (i = 0; i < dev->num_channels; i++)
 		if (dev->channels[i].scan_index == scan_index)
@@ -877,43 +859,18 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
 
 static int ams_get_alarm_mask(int scan_index)
 {
-	int bit = 0;
+	int bit = 0, event;
 
 	if (scan_index >= AMS_PS_SEQ_MAX) {
 		bit = AMS_PL_ALARM_START;
 		scan_index -= AMS_PS_SEQ_MAX;
 	}
 
-	switch (scan_index) {
-	case AMS_SEQ_TEMP:
-		return BIT(AMS_ALARM_BIT_TEMP + bit);
-	case AMS_SEQ_SUPPLY1:
-		return BIT(AMS_ALARM_BIT_SUPPLY1 + bit);
-	case AMS_SEQ_SUPPLY2:
-		return BIT(AMS_ALARM_BIT_SUPPLY2 + bit);
-	case AMS_SEQ_SUPPLY3:
-		return BIT(AMS_ALARM_BIT_SUPPLY3 + bit);
-	case AMS_SEQ_SUPPLY4:
-		return BIT(AMS_ALARM_BIT_SUPPLY4 + bit);
-	case AMS_SEQ_SUPPLY5:
-		return BIT(AMS_ALARM_BIT_SUPPLY5 + bit);
-	case AMS_SEQ_SUPPLY6:
-		return BIT(AMS_ALARM_BIT_SUPPLY6 + bit);
-	case AMS_SEQ_SUPPLY7:
-		return BIT(AMS_ALARM_BIT_SUPPLY7 + bit);
-	case AMS_SEQ_SUPPLY8:
-		return BIT(AMS_ALARM_BIT_SUPPLY8 + bit);
-	case AMS_SEQ_SUPPLY9:
-		return BIT(AMS_ALARM_BIT_SUPPLY9 + bit);
-	case AMS_SEQ_SUPPLY10:
-		return BIT(AMS_ALARM_BIT_SUPPLY10 + bit);
-	case AMS_SEQ_VCCAMS:
-		return BIT(AMS_ALARM_BIT_VCCAMS + bit);
-	case AMS_SEQ_TEMP_REMOTE:
-		return BIT(AMS_ALARM_BIT_TEMP_REMOTE + bit);
-	default:
+	event = ams_scan_index_to_event(scan_index);
+	if (event < 0)
 		return 0;
-	}
+
+	return BIT(event + bit);
 }
 
 static int ams_read_event_config(struct iio_dev *indio_dev,
-- 
2.47.3



^ permalink raw reply related

* Re: [PATCH 0/3] arm-smmu-v3: Add PMCG child support and update PMU MMIO mapping
From: Robin Murphy @ 2026-04-14  9:32 UTC (permalink / raw)
  To: Peng Fan
  Cc: Will Deacon, Joerg Roedel, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Mark Rutland, linux-arm-kernel, iommu, devicetree,
	linux-kernel, linux-perf-users, Peng Fan
In-Reply-To: <ad3w/P1vA2uKsV/o@shlinux89>

On 2026-04-14 8:47 am, Peng Fan wrote:
> Hi Robin,
> 
> On Fri, Apr 10, 2026 at 01:07:29PM +0100, Robin Murphy wrote:
>> On 08/04/2026 2:47 pm, Peng Fan wrote:
>>> On Wed, Apr 08, 2026 at 12:15:31PM +0100, Robin Murphy wrote:
>>>> On 2026-04-08 8:51 am, Peng Fan (OSS) wrote:
>>>>> This patch series adds proper support for describing and probing the
>>>>> Arm SMMU v3 PMCG (Performance Monitor Control Group) as a child node of
>>>>> the SMMU in Devicetree, and updates the relevant drivers accordingly.
>>>>>
>>>>> The SMMU v3 architecture allows an optional PMCG block, typically
>>>>> associated with TCUs, to be implemented within the SMMU register
>>>>> address space. For example, mmu700 PMCG is at the offset 0x2000 of the
>>>>> TCU page 0.
>>>>
>>>> But what's wrong with the existing binding? Especially given that it even has
>>>> an upstream user already:
>>>>
>>>> https://git.kernel.org/torvalds/c/aef9703dcbf8
>>>>
>>>>> Patch 1 updates the SMMU v3 Devicetree binding to allow PMCG child nodes,
>>>>> referencing the existing arm,smmu-v3-pmcg binding.
>>>>>
>>>>> Patch 2 updates the arm-smmu-v3 driver to populate platform devices for
>>>>> child nodes described in DT once the SMMU probe succeeds.
>>>>>
>>>>> Patch 3 updates the SMMUv3 PMU driver to correctly handle MMIO mapping when
>>>>> PMCG is described as a child node. The PMCG registers occupy a sub-region
>>>>> of the parent SMMU MMIO window, which is already requested by the SMMU
>>>>
>>>> That has not been the case since 52f3fab0067d ("iommu/arm-smmu-v3: Don't
>>>> reserve implementation defined register space") nearly 6 years ago, where the
>>>> whole purpose was to support Arm's PMCG implementation properly. What kernel
>>>> is this based on?
>>>
>>> Seems I am wrong. I thought PMCG is in page 0, so there were resource
>>> conflicts. I just retest without this patchset, all goes well.
>>>
>>> But from dt perspective, should the TCU PMCG node be child node of
>>> SMMU node?
>>
>> No. PMCGs can be used entirely independently of the SMMU itself, and while
>> most of the events do relate to SMMU translation and thus aren't necessarily
>> meaningful if it's not in use, there are still some which can be useful for
>> basic traffic counting, monitoring GPT/translation activity from _other_
>> security states (if observation is delegated to Non-Secure) and possibly
>> other things, even if the "main" Non-Secure SMMU interface isn't advertised
>> at all. It would be unreasonable to require the SMMU node to be present and
>> enabled *and* have a driver to populate PMCGs, to monitor events which are
>> outside the scope of that driver.
> 
> Thanks for explaining this in detail.
> 
> Just have one more question, we are using mmu-700, but MMU-700 implementation
> defined TCU and TBU events are not supported.
> 
> Should we introduce a compatible string saying "arm,mmu700-tcu-pmcg" or
> "arm,mmu700-tbu-pmcg"? TBH, I have not checked MMU600(AE) or else.

MMU-700 and all other Arm implementations are still fully compatible 
with "arm,mmu-600-pmcg" in terms of what that means. That lets the 
driver correctly construct the "identifier" attribute, which then allows 
userspace to know what exact PMU implementation it is.

We don't maintain ever-growing lists of aliases for imp-def events in 
the kernel driver, same as we don't for CPU PMUs either. Generally, 
anyone who has reason to go near those is likely to already have the TRM 
to hand and thus have the encodings anyway, but I suppose you could add 
jevents with the proper meaningful descriptions if you really wanted to.

Thanks,
Robin.


^ permalink raw reply

* Re: [PATCH bpf-next v2 1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
From: Puranjay Mohan @ 2026-04-14  9:38 UTC (permalink / raw)
  To: Xu Kuohai
  Cc: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, Catalin Marinas, Will Deacon,
	Luke Nelson, Xi Wang, Björn Töpel, Pu Lehui,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	linux-arm-kernel, linux-riscv, linux-kernel
In-Reply-To: <dd645fcf-76dc-4c68-8b6f-1a168cafd44f@huaweicloud.com>

On Tue, Apr 14, 2026 at 2:56 AM Xu Kuohai <xukuohai@huaweicloud.com> wrote:
>
> On 4/14/2026 3:11 AM, Puranjay Mohan wrote:
> > bpf_flush_icache() calls flush_icache_range() to clean the data cache
> > and invalidate the instruction cache for the JITed code region. However,
> > since commit 1dad391daef1 ("bpf, arm64: use bpf_prog_pack for memory
> > management"), this flush is redundant.
> >
> > bpf_jit_binary_pack_finalize() copies the JITed instructions to the ROX
> > region via bpf_arch_text_copy() -> aarch64_insn_copy() -> __text_poke(),
> > and __text_poke() already calls flush_icache_range() on the written
> > range. The subsequent bpf_flush_icache() repeats the same cache
> > maintenance on an overlapping range, including an unnecessary second
> > synchronous IPI to all CPUs via kick_all_cpus_sync().
> >
>
> So icache is flushed twice: once per instruction and again after all
> instructions are copied. I think it's better to remove the per-instruction
> flush and retain the single final flush to avoid repeating flush overhead
> for each instruction.

No, bpf_jit_binary_pack_finalize() is called at the end after the
whole program is jited, and it calls: bpf_arch_text_copy(ro_header,
rw_header, rw_header->size); which does aarch64_insn_copy(dst, src,
len), this calls __text_poke() which copies the whole program and then
does flush_icache_range((uintptr_t)addr, (uintptr_t)addr + len); once.
This is correct, after this we don't need to call flush_icache_range()
on the same range again.

If we had been calling flush_icache_range() for each instruction, the
system would hang due to the storm of IPIs.


^ permalink raw reply

* [PATCH v6 0/3] pinctrl: aspeed: Add AST2700 SoC0 support
From: Billy Tsai @ 2026-04-14  9:38 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Linus Walleij, Billy Tsai,
	Bartosz Golaszewski, Ryan Chen
  Cc: Andrew Jeffery, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, linux-gpio, linux-clk

AST2700 is composed of two interconnected SoC instances, each providing
its own pin control hardware. This series introduces bindings describing
the AST2700 pinctrl architecture and adds pinctrl driver support for the
SoC0 instance.

The bindings document the AST2700 dual-SoC design and follow common
pinctrl conventions, while the SoC0 driver implementation builds upon
the existing ASPEED pinctrl infrastructure.

---
Changes in v6:
- Restrict AST2700 SoC0 pinctrl pin configuration properties
  (`drive-strength` and `bias-*`) to `pins`-based state nodes in the
  binding schema.
- Move `memory-region` and `memory-region-names` in the AST2x00 SCU
  binding to top-level descriptions, and keep the conditional schema
  only to disallow them for non-AST2700 SCU0 compatibles.
- Add bias pull-up, pull-down, and disable support for AST2700 SoC0
  GPIO18A/GPIO18B pins in the pinctrl driver.
- Fix the USB2 Port B XH/XHP mux selector definitions to use the
  correct `PORTB_U2_XH_DESC` setting.
- Link to v5: https://lore.kernel.org/r/20260331-upstream_pinctrl-v5-0-8994f59ff367@aspeedtech.com

Changes in v5:
- Complete the AST2700 SCU0 binding and disallow child nodes that are
  not relevant for the hardware (p2a-control and smp-memram).
- Add examples for both the AST2700 SCU0 binding and the pinctrl binding,
  ensuring they are valid against the schema.
- Rework the pinctrl binding example to be self-contained and independent
  of the SCU binding.
- Reorder the binding patches so the pinctrl binding is introduced before
  the SCU binding update, allowing the SCU example to be added cleanly.
- Adjust the binding accordingly to restrict drive-strength to the
  supported values.
- Update the drive-strength table to match hardware-defined values.
- Link to v4: https://lore.kernel.org/r/20260306-upstream_pinctrl-v4-0-ad4e8ab8b489@aspeedtech.com

Changes in v4:
- Rename series title to "pinctrl: aspeed: Add AST2700 SoC0 support"
  to make it specific to SoC0.
- Remove unnecessary SCU example from bindings.
- Fix Makefile newline to avoid patch warning.
- Make pinctrl data structures const and align with existing Aspeed drivers.
- Sort the arrays and enums alphabetically.
- Minor cleanups for consistency, no functional changes.
- Link to v3: https://lore.kernel.org/r/20260120-upstream_pinctrl-v3-0-868fbf8413b5@aspeedtech.com

Changes in v3:
dt-bindings: pinctrl: aspeed: AST2700 pinctrl improvements
- Improved binding descriptions for SoC0 and SoC1 to better explain the
  AST2700 dual-SoC architecture with independent pin control blocks
- Switched from additionalProperties to patternProperties using the
  '-state$' suffix to restrict child node naming
- Removed per-binding examples based on review feedback
- Added additionalProperties: false at the top level for stricter schema
  validation
- Dropped the aspeed,ast2700-soc1-pinctrl binding, as the SoC1 pinctrl
  registers follow a regular layout and can be described using an
  existing generic pinctrl binding
- Updated the function and group enum lists to match the definitions
  used by the AST2700 pinctrl driver

dt-bindings: mfd: aspeed: Add AST2700 SCU example with pinctrl
- Added a complete AST2700 SCU0 example demonstrating pinctrl integration
- Example covers both pin function/group configuration and pin
  drive-strength settings
- Updated child node naming to use the '-state' suffix, following common
  pinctrl conventions

pinctrl: aspeed: AST2700 SoC0 driver improvements
- Refactored pin and signal declarations to use common ASPEED pinmux
  macros (SIG_EXPR_LIST_DECL_SEMG, SIG_EXPR_LIST_DECL_SESG, PIN_DECL_*)
- Added SCU010 register definition for hardware strap control
- Reworked code structure to better align with existing ASPEED pinctrl
  drivers

- Link to v2: https://lore.kernel.org/r/20250904103401.88287-1-billy_tsai@aspeedtech.com

Changes in v2:
- Update pinctrl aspeed binding files.
- Update the commit message for pinctrl binding patch.
- Link to v1: https://lore.kernel.org/r/20250829073030.2749482-1-billy_tsai@aspeedtech.com

---
Billy Tsai (3):
      dt-bindings: pinctrl: Add aspeed,ast2700-soc0-pinctrl
      dt-bindings: mfd: aspeed,ast2x00-scu: Describe AST2700 SCU0
      pinctrl: aspeed: Add AST2700 SoC0 support

 .../bindings/mfd/aspeed,ast2x00-scu.yaml           | 112 +++
 .../pinctrl/aspeed,ast2700-soc0-pinctrl.yaml       | 170 +++++
 drivers/pinctrl/aspeed/Kconfig                     |   9 +
 drivers/pinctrl/aspeed/Makefile                    |   1 +
 drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c    | 749 +++++++++++++++++++++
 5 files changed, 1041 insertions(+)
---
base-commit: af4e9ef3d78420feb8fe58cd9a1ab80c501b3c08
change-id: 20251215-upstream_pinctrl-8f195df0a975

Best regards,
-- 
Billy Tsai <billy_tsai@aspeedtech.com>



^ permalink raw reply

* [PATCH v6 1/3] dt-bindings: pinctrl: Add aspeed,ast2700-soc0-pinctrl
From: Billy Tsai @ 2026-04-14  9:38 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Linus Walleij, Billy Tsai,
	Bartosz Golaszewski, Ryan Chen
  Cc: Andrew Jeffery, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, linux-gpio, linux-clk
In-Reply-To: <20260414-upstream_pinctrl-v6-0-709f2127da33@aspeedtech.com>

Add a device tree binding for the pin controller found in the
ASPEED AST2700 SoC0.

The controller manages various peripheral functions such as eMMC, USB,
VGA DDC, JTAG, and PCIe root complex signals.

Describe the AST2700 SoC0 pin controller using standard pin multiplexing
and configuration properties.

Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
 .../pinctrl/aspeed,ast2700-soc0-pinctrl.yaml       | 170 +++++++++++++++++++++
 1 file changed, 170 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc0-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc0-pinctrl.yaml
new file mode 100644
index 000000000000..ca008cf9dc7c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc0-pinctrl.yaml
@@ -0,0 +1,170 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/aspeed,ast2700-soc0-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ASPEED AST2700 SoC0 Pin Controller
+
+maintainers:
+  - Billy Tsai <billy_tsai@aspeedtech.com>
+
+description:
+  The AST2700 features a dual-SoC architecture with two interconnected SoCs,
+  each having its own System Control Unit (SCU) for independent pin control.
+  This pin controller manages the pin multiplexing for SoC0.
+
+  The SoC0 pin controller manages pin functions including eMMC, VGA DDC,
+  dual USB3/USB2 ports (A and B), JTAG, and PCIe root complex interfaces.
+
+properties:
+  compatible:
+    const: aspeed,ast2700-soc0-pinctrl
+  reg:
+    maxItems: 1
+
+patternProperties:
+  '-state$':
+    type: object
+    allOf:
+      - $ref: pinmux-node.yaml#
+      - $ref: pincfg-node.yaml#
+      - if:
+          required:
+            - pins
+        else:
+          properties:
+            drive-strength: false
+            bias-disable: false
+            bias-pull-up: false
+            bias-pull-down: false
+    additionalProperties: false
+
+    properties:
+      function:
+        enum:
+          - EMMC
+          - JTAGDDR
+          - JTAGM0
+          - JTAGPCIEA
+          - JTAGPCIEB
+          - JTAGPSP
+          - JTAGSSP
+          - JTAGTSP
+          - JTAGUSB3A
+          - JTAGUSB3B
+          - PCIERC0PERST
+          - PCIERC1PERST
+          - TSPRSTN
+          - UFSCLKI
+          - USB2AD0
+          - USB2AD1
+          - USB2AH
+          - USB2AHP
+          - USB2AHPD0
+          - USB2AXH
+          - USB2AXH2B
+          - USB2AXHD1
+          - USB2AXHP
+          - USB2AXHP2B
+          - USB2AXHPD1
+          - USB2BD0
+          - USB2BD1
+          - USB2BH
+          - USB2BHP
+          - USB2BHPD0
+          - USB2BXH
+          - USB2BXH2A
+          - USB2BXHD1
+          - USB2BXHP
+          - USB2BXHP2A
+          - USB2BXHPD1
+          - USB3AXH
+          - USB3AXH2B
+          - USB3AXHD
+          - USB3AXHP
+          - USB3AXHP2B
+          - USB3AXHPD
+          - USB3BXH
+          - USB3BXH2A
+          - USB3BXHD
+          - USB3BXHP
+          - USB3BXHP2A
+          - USB3BXHPD
+          - VB
+          - VGADDC
+
+      groups:
+        enum:
+          - EMMCCDN
+          - EMMCG1
+          - EMMCG4
+          - EMMCG8
+          - EMMCWPN
+          - JTAG0
+          - PCIERC0PERST
+          - PCIERC1PERST
+          - TSPRSTN
+          - UFSCLKI
+          - USB2A
+          - USB2AAP
+          - USB2ABP
+          - USB2ADAP
+          - USB2AH
+          - USB2AHAP
+          - USB2B
+          - USB2BAP
+          - USB2BBP
+          - USB2BDBP
+          - USB2BH
+          - USB2BHBP
+          - USB3A
+          - USB3AAP
+          - USB3ABP
+          - USB3B
+          - USB3BAP
+          - USB3BBP
+          - VB0
+          - VB1
+          - VGADDC
+      pins:
+        enum:
+          - AB13
+          - AB14
+          - AC13
+          - AC14
+          - AD13
+          - AD14
+          - AE13
+          - AE14
+          - AE15
+          - AF13
+          - AF14
+          - AF15
+
+      drive-strength:
+        enum: [3, 6, 8, 11, 16, 18, 20, 23, 30, 32, 33, 35, 37, 38, 39, 41]
+
+      bias-disable: true
+      bias-pull-up: true
+      bias-pull-down: true
+
+required:
+  - compatible
+  - reg
+
+allOf:
+  - $ref: pinctrl.yaml#
+
+additionalProperties: false
+
+examples:
+  - |
+    pinctrl@400 {
+        compatible = "aspeed,ast2700-soc0-pinctrl";
+        reg = <0x400 0x318>;
+        emmc-state {
+            function = "EMMC";
+            groups = "EMMCG1";
+        };
+    };

-- 
2.34.1



^ permalink raw reply related

* [PATCH v6 2/3] dt-bindings: mfd: aspeed,ast2x00-scu: Describe AST2700 SCU0
From: Billy Tsai @ 2026-04-14  9:39 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Linus Walleij, Billy Tsai,
	Bartosz Golaszewski, Ryan Chen
  Cc: Andrew Jeffery, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, linux-gpio, linux-clk
In-Reply-To: <20260414-upstream_pinctrl-v6-0-709f2127da33@aspeedtech.com>

AST2700 consists of two interconnected SoC instances, each with its own
System Control Unit (SCU). The SCU0 provides pin control, interrupt
controllers, clocks, resets, and address-space mappings for the
Secondary and Tertiary Service Processors (SSP and TSP).

Describe the SSP/TSP address mappings using the standard
memory-region and memory-region-names properties.

Disallow legacy child nodes that are not present on AST2700, including
p2a-control and smp-memram. The latter is unnecessary as software can
access the scratch registers via the SCU syscon.

Also allow the AST2700 SoC0 pin controller to be described as a child
node of the SCU0, and add an example illustrating the SCU0 layout,
including reserved-memory, interrupt controllers, and pinctrl.

Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
 .../bindings/mfd/aspeed,ast2x00-scu.yaml           | 112 +++++++++++++++++++++
 1 file changed, 112 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
index a87f31fce019..d65897576a40 100644
--- a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
+++ b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
@@ -46,6 +46,17 @@ properties:
   '#reset-cells':
     const: 1
 
+  memory-region:
+    items:
+      - description: Region mapped through the first SSP address window.
+      - description: Region mapped through the second SSP address window.
+      - description: Region mapped through the TSP address window.
+  memory-region-names:
+    items:
+      - const: ssp-0
+      - const: ssp-1
+      - const: tsp
+
 patternProperties:
   '^p2a-control@[0-9a-f]+$':
     description: >
@@ -87,6 +98,7 @@ patternProperties:
             - aspeed,ast2400-pinctrl
             - aspeed,ast2500-pinctrl
             - aspeed,ast2600-pinctrl
+            - aspeed,ast2700-soc0-pinctrl
 
     required:
       - compatible
@@ -156,6 +168,29 @@ required:
   - '#clock-cells'
   - '#reset-cells'
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            anyOf:
+              - const: aspeed,ast2700-scu0
+              - const: aspeed,ast2700-scu1
+    then:
+      patternProperties:
+        '^p2a-control@[0-9a-f]+$': false
+        '^smp-memram@[0-9a-f]+$': false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: aspeed,ast2700-scu0
+    else:
+      properties:
+        memory-region: false
+        memory-region-names: false
+
 additionalProperties: false
 
 examples:
@@ -180,4 +215,81 @@ examples:
             reg = <0x7c 0x4>, <0x150 0x8>;
         };
     };
+
+  - |
+    / {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        reserved-memory {
+            #address-cells = <2>;
+            #size-cells = <2>;
+            ranges;
+
+            ssp_region_0: memory@400000000 {
+                reg = <0x4 0x00000000 0x0 0x01000000>;
+                no-map;
+            };
+
+            ssp_region_1: memory@401000000 {
+                reg = <0x4 0x01000000 0x0 0x01000000>;
+                no-map;
+            };
+
+            tsp_region: memory@402000000 {
+                reg = <0x4 0x02000000 0x0 0x01000000>;
+                no-map;
+            };
+        };
+
+        bus {
+            #address-cells = <2>;
+            #size-cells = <2>;
+
+            syscon@12c02000 {
+                compatible = "aspeed,ast2700-scu0", "syscon", "simple-mfd";
+                reg = <0 0x12c02000 0 0x1000>;
+                ranges = <0x0 0x0 0x12c02000 0x1000>;
+                #address-cells = <1>;
+                #size-cells = <1>;
+                #clock-cells = <1>;
+                #reset-cells = <1>;
+
+                memory-region = <&ssp_region_0>, <&ssp_region_1>,
+                                <&tsp_region>;
+                memory-region-names = "ssp-0", "ssp-1", "tsp";
+
+                silicon-id@0 {
+                    compatible = "aspeed,ast2700-silicon-id", "aspeed,silicon-id";
+                    reg = <0x0 0x4>;
+                };
+
+                interrupt-controller@1b0 {
+                    compatible = "aspeed,ast2700-scu-ic0";
+                    reg = <0x1b0 0x4>;
+                    #interrupt-cells = <1>;
+                    interrupts-extended = <&intc0 97>;
+                    interrupt-controller;
+                };
+
+                interrupt-controller@1e0 {
+                    compatible = "aspeed,ast2700-scu-ic1";
+                    reg = <0x1e0 0x4>;
+                    #interrupt-cells = <1>;
+                    interrupts-extended = <&intc0 98>;
+                    interrupt-controller;
+                };
+
+                pinctrl@400 {
+                    compatible = "aspeed,ast2700-soc0-pinctrl";
+                    reg = <0x400 0x318>;
+                    emmc-state {
+                        function = "EMMC";
+                        groups = "EMMCG1";
+                    };
+                };
+            };
+        };
+    };
+
 ...

-- 
2.34.1



^ permalink raw reply related

* [PATCH v6 3/3] pinctrl: aspeed: Add AST2700 SoC0 support
From: Billy Tsai @ 2026-04-14  9:39 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Andrew Jeffery, Linus Walleij, Billy Tsai,
	Bartosz Golaszewski, Ryan Chen
  Cc: Andrew Jeffery, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel, openbmc, linux-gpio, linux-clk
In-Reply-To: <20260414-upstream_pinctrl-v6-0-709f2127da33@aspeedtech.com>

Add pinctrl support for the SoC0 instance of the ASPEED AST2700.

AST2700 consists of two interconnected SoC instances, each with its own
pinctrl register block.

The SoC0 pinctrl hardware closely follows the design found in previous
ASPEED BMC generations, allowing the driver to build upon the common
ASPEED pinctrl infrastructure.

Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
 drivers/pinctrl/aspeed/Kconfig                  |   9 +
 drivers/pinctrl/aspeed/Makefile                 |   1 +
 drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c | 749 ++++++++++++++++++++++++
 3 files changed, 759 insertions(+)

diff --git a/drivers/pinctrl/aspeed/Kconfig b/drivers/pinctrl/aspeed/Kconfig
index 1a4e5b9ed471..f9672cca891e 100644
--- a/drivers/pinctrl/aspeed/Kconfig
+++ b/drivers/pinctrl/aspeed/Kconfig
@@ -31,3 +31,12 @@ config PINCTRL_ASPEED_G6
 	help
 	  Say Y here to enable pin controller support for Aspeed's 6th
 	  generation SoCs. GPIO is provided by a separate GPIO driver.
+
+config PINCTRL_ASPEED_G7_SOC0
+	bool "Aspeed G7 SoC pin control"
+	depends on (ARCH_ASPEED || COMPILE_TEST) && OF
+	select PINCTRL_ASPEED
+	help
+	  Say Y here to enable pin controller support for the SoC0 instance
+	  of Aspeed's 7th generation SoCs. GPIO is provided by a separate
+	  GPIO driver.
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
index db2a7600ae2b..0de524ca2c72 100644
--- a/drivers/pinctrl/aspeed/Makefile
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_PINCTRL_ASPEED)	+= pinctrl-aspeed.o pinmux-aspeed.o
 obj-$(CONFIG_PINCTRL_ASPEED_G4)	+= pinctrl-aspeed-g4.o
 obj-$(CONFIG_PINCTRL_ASPEED_G5)	+= pinctrl-aspeed-g5.o
 obj-$(CONFIG_PINCTRL_ASPEED_G6)	+= pinctrl-aspeed-g6.o
+obj-$(CONFIG_PINCTRL_ASPEED_G7_SOC0) += pinctrl-aspeed-g7-soc0.o
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c
new file mode 100644
index 000000000000..35a28b677318
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c
@@ -0,0 +1,749 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bitops.h>
+#include <linux/bits.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "pinctrl-aspeed.h"
+#include "pinmux-aspeed.h"
+#include "../pinctrl-utils.h"
+
+#define SCU200 0x200 /* System Reset Control #1  */
+
+#define SCU010 0x010 /* Hardware Strap Register */
+#define SCU400 0x400 /* Multi-function Pin Control #1  */
+#define SCU404 0x404 /* Multi-function Pin Control #2  */
+#define SCU408 0x408 /* Multi-function Pin Control #3  */
+#define SCU40C 0x40C /* Multi-function Pin Control #3  */
+#define SCU410 0x410 /* USB Multi-function Control Register  */
+#define SCU414 0x414 /* VGA Function Control Register  */
+
+#define SCU480 0x480 /* GPIO18A0 IO Control Register */
+#define SCU484 0x484 /* GPIO18A1 IO Control Register */
+#define SCU488 0x488 /* GPIO18A2 IO Control Register */
+#define SCU48C 0x48c /* GPIO18A3 IO Control Register */
+#define SCU490 0x490 /* GPIO18A4 IO Control Register */
+#define SCU494 0x494 /* GPIO18A5 IO Control Register */
+#define SCU498 0x498 /* GPIO18A6 IO Control Register */
+#define SCU49C 0x49c /* GPIO18A7 IO Control Register */
+#define SCU4A0 0x4A0 /* GPIO18B0 IO Control Register */
+#define SCU4A4 0x4A4 /* GPIO18B1 IO Control Register */
+#define SCU4A8 0x4A8 /* GPIO18B2 IO Control Register */
+#define SCU4AC 0x4AC /* GPIO18B3 IO Control Register */
+
+enum {
+	AC14,
+	AE15,
+	AD14,
+	AE14,
+	AF14,
+	AB13,
+	AB14,
+	AF15,
+	AF13,
+	AC13,
+	AD13,
+	AE13,
+	JTAG_PORT,
+	PCIERC0_PERST,
+	PCIERC1_PERST,
+	PORTA_MODE,
+	PORTA_U2,
+	PORTB_MODE,
+	PORTB_U2,
+	PORTA_U2_PHY,
+	PORTB_U2_PHY,
+	PORTA_U3,
+	PORTB_U3,
+	PORTA_U3_PHY,
+	PORTB_U3_PHY,
+};
+
+SIG_EXPR_LIST_DECL_SEMG(AC14, EMMCCLK, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 0));
+SIG_EXPR_LIST_DECL_SESG(AC14, VB1CS, VB1, SIG_DESC_SET(SCU404, 0));
+PIN_DECL_2(AC14, GPIO18A0, EMMCCLK, VB1CS);
+
+SIG_EXPR_LIST_DECL_SEMG(AE15, EMMCCMD, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 1));
+SIG_EXPR_LIST_DECL_SESG(AE15, VB1CK, VB1, SIG_DESC_SET(SCU404, 1));
+PIN_DECL_2(AE15, GPIO18A1, EMMCCMD, VB1CK);
+
+SIG_EXPR_LIST_DECL_SEMG(AD14, EMMCDAT0, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 2));
+SIG_EXPR_LIST_DECL_SESG(AD14, VB1MOSI, VB1, SIG_DESC_SET(SCU404, 2));
+PIN_DECL_2(AD14, GPIO18A2, EMMCDAT0, VB1MOSI);
+
+SIG_EXPR_LIST_DECL_SEMG(AE14, EMMCDAT1, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 3));
+SIG_EXPR_LIST_DECL_SESG(AE14, VB1MISO, VB1, SIG_DESC_SET(SCU404, 3));
+PIN_DECL_2(AE14, GPIO18A3, EMMCDAT1, VB1MISO);
+
+SIG_EXPR_LIST_DECL_SEMG(AF14, EMMCDAT2, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 4));
+PIN_DECL_1(AF14, GPIO18A4, EMMCDAT2);
+
+SIG_EXPR_LIST_DECL_SEMG(AB13, EMMCDAT3, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 5));
+PIN_DECL_1(AB13, GPIO18A5, EMMCDAT3);
+
+SIG_EXPR_LIST_DECL_SEMG(AB14, EMMCCDN, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 6));
+SIG_EXPR_LIST_DECL_SESG(AB14, VB0CS, VB0, SIG_DESC_SET(SCU010, 17));
+PIN_DECL_2(AB14, GPIO18A6, EMMCCDN, VB0CS);
+
+SIG_EXPR_LIST_DECL_SEMG(AF15, EMMCWPN, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 7));
+SIG_EXPR_LIST_DECL_SESG(AF15, VB0CK, VB0, SIG_DESC_SET(SCU010, 17));
+PIN_DECL_2(AF15, GPIO18A7, EMMCWPN, VB0CK);
+
+SIG_EXPR_LIST_DECL_SESG(AF13, TSPRSTN, TSPRSTN, SIG_DESC_SET(SCU010, 9));
+SIG_EXPR_LIST_DECL_SEMG(AF13, EMMCDAT4, EMMCG8, EMMC, SIG_DESC_SET(SCU400, 8));
+SIG_EXPR_LIST_DECL_SESG(AF13, VB0MOSI, VB0, SIG_DESC_SET(SCU010, 17));
+PIN_DECL_3(AF13, GPIO18B0, TSPRSTN, EMMCDAT4, VB0MOSI);
+
+SIG_EXPR_LIST_DECL_SESG(AC13, UFSCLKI, UFSCLKI, SIG_DESC_SET(SCU010, 19));
+SIG_EXPR_LIST_DECL_SEMG(AC13, EMMCDAT5, EMMCG8, EMMC, SIG_DESC_SET(SCU400, 9));
+SIG_EXPR_LIST_DECL_SESG(AC13, VB0MISO, VB0, SIG_DESC_SET(SCU010, 17));
+PIN_DECL_3(AC13, GPIO18B1, UFSCLKI, EMMCDAT5, VB0MISO);
+
+SIG_EXPR_LIST_DECL_SEMG(AD13, EMMCDAT6, EMMCG8, EMMC, SIG_DESC_SET(SCU400, 10));
+SIG_EXPR_LIST_DECL_SESG(AD13, DDCCLK, VGADDC, SIG_DESC_SET(SCU404, 10));
+PIN_DECL_2(AD13, GPIO18B2, EMMCDAT6, DDCCLK);
+
+SIG_EXPR_LIST_DECL_SEMG(AE13, EMMCDAT7, EMMCG8, EMMC, SIG_DESC_SET(SCU400, 11));
+SIG_EXPR_LIST_DECL_SESG(AE13, DDCDAT, VGADDC, SIG_DESC_SET(SCU404, 11));
+PIN_DECL_2(AE13, GPIO18B3, EMMCDAT7, DDCDAT);
+
+GROUP_DECL(EMMCG1, AC14, AE15, AD14);
+GROUP_DECL(EMMCG4, AC14, AE15, AD14, AE14, AF14, AB13);
+GROUP_DECL(EMMCG8, AC14, AE15, AD14, AE14, AF14, AB13, AF13, AC13, AD13, AE13);
+GROUP_DECL(EMMCWPN, AF15);
+GROUP_DECL(EMMCCDN, AB14);
+FUNC_DECL_(EMMC, "EMMCG1", "EMMCG4", "EMMCG8", "EMMCWPN", "EMMCCDN");
+
+GROUP_DECL(VB1, AC14, AE15, AD14, AE14);
+GROUP_DECL(VB0, AF15, AB14, AF13, AC13);
+FUNC_DECL_2(VB, VB1, VB0);
+
+FUNC_GROUP_DECL(TSPRSTN, AF13);
+
+FUNC_GROUP_DECL(UFSCLKI, AC13);
+
+FUNC_GROUP_DECL(VGADDC, AD13, AE13);
+
+/* JTAG Port Selection */
+#define JTAG_PORT_PSP_DESC   { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x0, 0 }
+#define JTAG_PORT_SSP_DESC   { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x41, 0 }
+#define JTAG_PORT_TSP_DESC   { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x42, 0 }
+#define JTAG_PORT_DDR_DESC   { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x43, 0 }
+#define JTAG_PORT_USB3A_DESC { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x44, 0 }
+#define JTAG_PORT_USB3B_DESC { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x45, 0 }
+#define JTAG_PORT_PCIEA_DESC { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x46, 0 }
+#define JTAG_PORT_PCIEB_DESC { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x47, 0 }
+#define JTAG_PORT_JTAGM0_DESC { ASPEED_IP_SCU, SCU408, GENMASK(12, 5), 0x8, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGPSP, JTAG0, JTAGPSP, JTAG_PORT_PSP_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGSSP, JTAG0, JTAGSSP, JTAG_PORT_SSP_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGTSP, JTAG0, JTAGTSP, JTAG_PORT_TSP_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGDDR, JTAG0, JTAGDDR, JTAG_PORT_DDR_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGUSB3A, JTAG0, JTAGUSB3A, JTAG_PORT_USB3A_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGUSB3B, JTAG0, JTAGUSB3B, JTAG_PORT_USB3B_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGPCIEA, JTAG0, JTAGPCIEA, JTAG_PORT_PCIEA_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGPCIEB, JTAG0, JTAGPCIEB, JTAG_PORT_PCIEB_DESC);
+SIG_EXPR_LIST_DECL_SEMG(JTAG_PORT, JTAGM0, JTAG0, JTAGM0, JTAG_PORT_JTAGM0_DESC);
+PIN_DECL_(JTAG_PORT, SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGPSP), SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGSSP),
+	  SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGTSP), SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGDDR),
+	  SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGUSB3A), SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGUSB3B),
+	  SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGPCIEA), SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGPCIEB),
+	  SIG_EXPR_LIST_PTR(JTAG_PORT, JTAGM0));
+
+GROUP_DECL(JTAG0, JTAG_PORT);
+
+FUNC_DECL_1(JTAGPSP, JTAG0);
+FUNC_DECL_1(JTAGSSP, JTAG0);
+FUNC_DECL_1(JTAGTSP, JTAG0);
+FUNC_DECL_1(JTAGDDR, JTAG0);
+FUNC_DECL_1(JTAGUSB3A, JTAG0);
+FUNC_DECL_1(JTAGUSB3B, JTAG0);
+FUNC_DECL_1(JTAGPCIEA, JTAG0);
+FUNC_DECL_1(JTAGPCIEB, JTAG0);
+FUNC_DECL_1(JTAGM0, JTAG0);
+
+/* PCIe Reset Control */
+SIG_EXPR_LIST_DECL_SESG(PCIERC0_PERST, PCIERC0PERST, PCIERC0PERST, SIG_DESC_SET(SCU200, 21));
+PIN_DECL_(PCIERC0_PERST, SIG_EXPR_LIST_PTR(PCIERC0_PERST, PCIERC0PERST));
+FUNC_GROUP_DECL(PCIERC0PERST, PCIERC0_PERST);
+
+SIG_EXPR_LIST_DECL_SESG(PCIERC1_PERST, PCIERC1PERST, PCIERC1PERST, SIG_DESC_SET(SCU200, 19));
+PIN_DECL_(PCIERC1_PERST, SIG_EXPR_LIST_PTR(PCIERC1_PERST, PCIERC1PERST));
+FUNC_GROUP_DECL(PCIERC1PERST, PCIERC1_PERST);
+
+#define PORTA_MODE_HPD0_DESC { ASPEED_IP_SCU, SCU410, GENMASK(25, 24), 0, 0 }
+#define PORTA_MODE_D0_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(25, 24), 1, 0 }
+#define PORTA_MODE_H_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(25, 24), 2, 0 }
+#define PORTA_MODE_HP_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(25, 24), 3, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(PORTA_MODE, USB2AHPD0, USB2AH, USB2AHPD0, PORTA_MODE_HPD0_DESC);
+SIG_EXPR_LIST_DECL_SEMG(PORTA_MODE, USB2AH, USB2AHAP, USB2AH, PORTA_MODE_H_DESC);
+SIG_EXPR_LIST_DECL_SEMG(PORTA_MODE, USB2AHP, USB2AHAP, USB2AHP, PORTA_MODE_HP_DESC);
+SIG_EXPR_LIST_DECL_SEMG(PORTA_MODE, USB2AD0, USB2AHAP, USB2AD0, PORTA_MODE_D0_DESC);
+PIN_DECL_(PORTA_MODE, SIG_EXPR_LIST_PTR(PORTA_MODE, USB2AHPD0),
+	  SIG_EXPR_LIST_PTR(PORTA_MODE, USB2AH), SIG_EXPR_LIST_PTR(PORTA_MODE, USB2AHP),
+	  SIG_EXPR_LIST_PTR(PORTA_MODE, USB2AD0));
+
+#define PORTA_U2_XHD_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(3, 2), 0, 0 }
+#define PORTA_U2_D1_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(3, 2), 1, 0 }
+#define PORTA_U2_XH_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(3, 2), 2, 0 }
+#define PORTA_U2_XH2E_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(3, 2), 3, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AXHD1, USB2A, USB2AXHD1, PORTA_U2_XHD_DESC,
+			SIG_DESC_SET(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AXHPD1, USB2A, USB2AXHPD1, PORTA_U2_XHD_DESC,
+			SIG_DESC_CLEAR(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AXH, USB2AAP, USB2AXH, PORTA_U2_XH_DESC,
+			SIG_DESC_SET(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AXHP, USB2AAP, USB2AXHP, PORTA_U2_XH_DESC,
+			SIG_DESC_CLEAR(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AXH2B, USB2ABP, USB2AXH2B, PORTA_U2_XH2E_DESC,
+			SIG_DESC_SET(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AXHP2B, USB2ABP, USB2AXHP2B, PORTA_U2_XH2E_DESC,
+			SIG_DESC_CLEAR(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U2, USB2AD1, USB2ADAP, USB2AD1, PORTA_U2_D1_DESC);
+PIN_DECL_(PORTA_U2, SIG_EXPR_LIST_PTR(PORTA_U2, USB2AXHD1), SIG_EXPR_LIST_PTR(PORTA_U2, USB2AXHPD1),
+	  SIG_EXPR_LIST_PTR(PORTA_U2, USB2AXH), SIG_EXPR_LIST_PTR(PORTA_U2, USB2AXHP),
+	  SIG_EXPR_LIST_PTR(PORTA_U2, USB2AXH2B), SIG_EXPR_LIST_PTR(PORTA_U2, USB2AXHP2B),
+	  SIG_EXPR_LIST_PTR(PORTA_U2, USB2AD1));
+
+#define PORTB_MODE_HPD0_DESC { ASPEED_IP_SCU, SCU410, GENMASK(29, 28), 0, 0 }
+#define PORTB_MODE_D0_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(29, 28), 1, 0 }
+#define PORTB_MODE_H_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(29, 28), 2, 0 }
+#define PORTB_MODE_HP_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(29, 28), 3, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(PORTB_MODE, USB2BHPD0, USB2BH, USB2BHPD0, PORTB_MODE_HPD0_DESC);
+SIG_EXPR_LIST_DECL_SEMG(PORTB_MODE, USB2BH, USB2BHBP, USB2BH, PORTB_MODE_H_DESC);
+SIG_EXPR_LIST_DECL_SEMG(PORTB_MODE, USB2BHP, USB2BHBP, USB2BHP, PORTB_MODE_HP_DESC);
+SIG_EXPR_LIST_DECL_SEMG(PORTB_MODE, USB2BD0, USB2BHBP, USB2BD0, PORTB_MODE_D0_DESC);
+PIN_DECL_(PORTB_MODE, SIG_EXPR_LIST_PTR(PORTB_MODE, USB2BHPD0),
+	  SIG_EXPR_LIST_PTR(PORTB_MODE, USB2BH), SIG_EXPR_LIST_PTR(PORTB_MODE, USB2BHP),
+	  SIG_EXPR_LIST_PTR(PORTB_MODE, USB2BD0));
+
+#define PORTB_U2_XHD_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(7, 6), 0, 0 }
+#define PORTB_U2_D1_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(7, 6), 1, 0 }
+#define PORTB_U2_XH_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(7, 6), 2, 0 }
+#define PORTB_U2_XH2E_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(7, 6), 3, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BXHD1, USB2B, USB2BXHD1, PORTB_U2_XHD_DESC,
+			SIG_DESC_SET(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BXHPD1, USB2B, USB2BXHPD1, PORTB_U2_XHD_DESC,
+			SIG_DESC_CLEAR(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BXH, USB2BBP, USB2BXH, PORTB_U2_XH_DESC,
+			SIG_DESC_SET(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BXHP, USB2BBP, USB2BXHP, PORTB_U2_XH_DESC,
+			SIG_DESC_CLEAR(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BXH2A, USB2BAP, USB2BXH2A, PORTB_U2_XH2E_DESC,
+			SIG_DESC_SET(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BXHP2A, USB2BAP, USB2BXHP2A, PORTB_U2_XH2E_DESC,
+			SIG_DESC_CLEAR(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U2, USB2BD1, USB2BDBP, USB2BD1, PORTB_U2_D1_DESC);
+PIN_DECL_(PORTB_U2, SIG_EXPR_LIST_PTR(PORTB_U2, USB2BXHD1), SIG_EXPR_LIST_PTR(PORTB_U2, USB2BXHPD1),
+	  SIG_EXPR_LIST_PTR(PORTB_U2, USB2BXH), SIG_EXPR_LIST_PTR(PORTB_U2, USB2BXHP),
+	  SIG_EXPR_LIST_PTR(PORTB_U2, USB2BXH2A), SIG_EXPR_LIST_PTR(PORTB_U2, USB2BXHP2A),
+	  SIG_EXPR_LIST_PTR(PORTB_U2, USB2BD1));
+/*
+ * USB2 virtual PHY pins.
+ *
+ * PORTA_U2_PHY and PORTB_U2_PHY are logical endpoints, not package pins.
+ * They alias existing USB2 expressions so pin groups can model direct and
+ * cross-coupled routing for host and mode paths.
+ *
+ * - USB2AAP/USB2ADAP/USB2AHAP: use PORTA_U2_PHY
+ * - USB2ABP                  : use PORTB_U2_PHY
+ * - USB2BBP/USB2BDBP/USB2BHBP: use PORTB_U2_PHY
+ * - USB2BAP                  : use PORTA_U2_PHY
+ *
+ * They do not have any registers to configure this behaviour; the goal is
+ * simply for the driver to prevent conflicting selections. For example,
+ * selecting group USB2ABP and USB2BBP at the same time should not be
+ * allowed.
+ */
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2AXH, USB2AAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2AXHP, USB2AAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2BXH2A, USB2BAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2BXHP2A, USB2BAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2AD1, USB2ADAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2AH, USB2AHAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2AHP, USB2AHAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U2_PHY, USB2AD0, USB2AHAP);
+PIN_DECL_(PORTA_U2_PHY, SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2AXH),
+	  SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2AXHP), SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2BXH2A),
+	  SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2BXHP2A), SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2AD1),
+	  SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2AH), SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2AHP),
+	  SIG_EXPR_LIST_PTR(PORTA_U2_PHY, USB2AD0));
+
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2AXH2B, USB2ABP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2AXHP2B, USB2ABP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2BXH, USB2BBP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2BXHP, USB2BBP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2BD1, USB2BDBP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2BH, USB2BHBP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2BHP, USB2BHBP);
+SIG_EXPR_LIST_ALIAS(PORTB_U2_PHY, USB2BD0, USB2BHBP);
+PIN_DECL_(PORTB_U2_PHY, SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2AXH2B),
+	  SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2AXHP2B), SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2BXH),
+	  SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2BXHP), SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2BD1),
+	  SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2BH), SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2BHP),
+	  SIG_EXPR_LIST_PTR(PORTB_U2_PHY, USB2BD0));
+
+GROUP_DECL(USB2A, PORTA_U2);
+GROUP_DECL(USB2AAP, PORTA_U2, PORTA_U2_PHY);
+GROUP_DECL(USB2ABP, PORTA_U2, PORTB_U2_PHY);
+GROUP_DECL(USB2ADAP, PORTA_U2, PORTA_U2_PHY);
+GROUP_DECL(USB2AH, PORTA_MODE);
+GROUP_DECL(USB2AHAP, PORTA_MODE, PORTA_U2_PHY);
+
+FUNC_DECL_1(USB2AXHD1, USB2A);
+FUNC_DECL_1(USB2AXHPD1, USB2A);
+FUNC_DECL_1(USB2AXH, USB2AAP);
+FUNC_DECL_1(USB2AXHP, USB2AAP);
+FUNC_DECL_1(USB2AXH2B, USB2ABP);
+FUNC_DECL_1(USB2AXHP2B, USB2ABP);
+FUNC_DECL_1(USB2AD1, USB2ADAP);
+FUNC_DECL_1(USB2AHPD0, USB2AH);
+FUNC_DECL_1(USB2AH, USB2AHAP);
+FUNC_DECL_1(USB2AHP, USB2AHAP);
+FUNC_DECL_1(USB2AD0, USB2AHAP);
+
+GROUP_DECL(USB2B, PORTB_U2);
+GROUP_DECL(USB2BBP, PORTB_U2, PORTB_U2_PHY);
+GROUP_DECL(USB2BAP, PORTB_U2, PORTA_U2_PHY);
+GROUP_DECL(USB2BDBP, PORTB_U2, PORTB_U2_PHY);
+GROUP_DECL(USB2BH, PORTB_MODE);
+GROUP_DECL(USB2BHBP, PORTB_MODE, PORTB_U2_PHY);
+
+FUNC_DECL_1(USB2BXHD1, USB2B);
+FUNC_DECL_1(USB2BXHPD1, USB2B);
+FUNC_DECL_1(USB2BXH, USB2BBP);
+FUNC_DECL_1(USB2BXHP, USB2BBP);
+FUNC_DECL_1(USB2BXH2A, USB2BAP);
+FUNC_DECL_1(USB2BXHP2A, USB2BAP);
+FUNC_DECL_1(USB2BD1, USB2BDBP);
+FUNC_DECL_1(USB2BHPD0, USB2BH);
+FUNC_DECL_1(USB2BH, USB2BHBP);
+FUNC_DECL_1(USB2BHP, USB2BHBP);
+FUNC_DECL_1(USB2BD0, USB2BHBP);
+
+#define PORTA_U3_XHD_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(1, 0), 0, 0 }
+#define PORTA_U3_XH_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(1, 0), 2, 0 }
+#define PORTA_U3_XH2E_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(1, 0), 3, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U3, USB3AXHD, USB3A, USB3AXHD, PORTA_U3_XHD_DESC,
+			SIG_DESC_SET(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U3, USB3AXHPD, USB3A, USB3AXHPD, PORTA_U3_XHD_DESC,
+			SIG_DESC_CLEAR(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U3, USB3AXH, USB3AAP, USB3AXH, PORTA_U3_XH_DESC,
+			SIG_DESC_SET(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U3, USB3AXHP, USB3AAP, USB3AXHP, PORTA_U3_XH_DESC,
+			SIG_DESC_CLEAR(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U3, USB3AXH2B, USB3ABP, USB3AXH2B, PORTA_U3_XH2E_DESC,
+			SIG_DESC_SET(SCU410, 9));
+SIG_EXPR_LIST_DECL_SEMG(PORTA_U3, USB3AXHP2B, USB3ABP, USB3AXHP2B, PORTA_U3_XH2E_DESC,
+			SIG_DESC_CLEAR(SCU410, 9));
+PIN_DECL_(PORTA_U3, SIG_EXPR_LIST_PTR(PORTA_U3, USB3AXHD), SIG_EXPR_LIST_PTR(PORTA_U3, USB3AXHPD),
+	  SIG_EXPR_LIST_PTR(PORTA_U3, USB3AXH), SIG_EXPR_LIST_PTR(PORTA_U3, USB3AXHP),
+	  SIG_EXPR_LIST_PTR(PORTA_U3, USB3AXH2B), SIG_EXPR_LIST_PTR(PORTA_U3, USB3AXHP2B));
+
+#define PORTB_U3_XHD_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(5, 4), 0, 0 }
+#define PORTB_U3_XH_DESC    { ASPEED_IP_SCU, SCU410, GENMASK(5, 4), 2, 0 }
+#define PORTB_U3_XH2E_DESC   { ASPEED_IP_SCU, SCU410, GENMASK(5, 4), 3, 0 }
+
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U3, USB3BXHD, USB3B, USB3BXHD, PORTB_U3_XHD_DESC,
+			SIG_DESC_SET(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U3, USB3BXHPD, USB3B, USB3BXHPD, PORTB_U3_XHD_DESC,
+			SIG_DESC_CLEAR(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U3, USB3BXH, USB3BBP, USB3BXH, PORTB_U3_XH_DESC,
+			SIG_DESC_SET(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U3, USB3BXHP, USB3BBP, USB3BXHP, PORTB_U3_XH_DESC,
+			SIG_DESC_CLEAR(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U3, USB3BXH2A, USB3BAP, USB3BXH2A, PORTB_U3_XH2E_DESC,
+			SIG_DESC_SET(SCU410, 10));
+SIG_EXPR_LIST_DECL_SEMG(PORTB_U3, USB3BXHP2A, USB3BAP, USB3BXHP2A, PORTB_U3_XH2E_DESC,
+			SIG_DESC_CLEAR(SCU410, 10));
+PIN_DECL_(PORTB_U3, SIG_EXPR_LIST_PTR(PORTB_U3, USB3BXHD), SIG_EXPR_LIST_PTR(PORTB_U3, USB3BXHPD),
+	  SIG_EXPR_LIST_PTR(PORTB_U3, USB3BXH), SIG_EXPR_LIST_PTR(PORTB_U3, USB3BXHP),
+	  SIG_EXPR_LIST_PTR(PORTB_U3, USB3BXH2A), SIG_EXPR_LIST_PTR(PORTB_U3, USB3BXHP2A));
+
+/*
+ * USB3 virtual PHY pins.
+ *
+ * PORTA_U3_PHY and PORTB_U3_PHY are logical endpoints, not package pins.
+ * They alias existing USB3 expressions so pin groups can model both direct and
+ * cross-coupled routing to PHY A/B.
+ *
+ * - USB3AAP: PORTA_U3 + PORTA_U3_PHY   (A -> PHY A)
+ * - USB3ABP: PORTA_U3 + PORTB_U3_PHY   (A -> PHY B)
+ * - USB3BBP: PORTB_U3 + PORTB_U3_PHY   (B -> PHY B)
+ * - USB3BAP: PORTB_U3 + PORTA_U3_PHY   (B -> PHY A)
+ *
+ * They do not have any registers to configure this behavior; the goal is
+ * simply for the driver to prevent conflicting selections. For example,
+ * selecting group USB3ABP and USB3BBP at the same time should not be
+ * allowed.
+ */
+SIG_EXPR_LIST_ALIAS(PORTA_U3_PHY, USB3AXH, USB3AAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U3_PHY, USB3AXHP, USB3AAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U3_PHY, USB3BXH2A, USB3BAP);
+SIG_EXPR_LIST_ALIAS(PORTA_U3_PHY, USB3BXHP2A, USB3BAP);
+PIN_DECL_(PORTA_U3_PHY, SIG_EXPR_LIST_PTR(PORTA_U3_PHY, USB3AXH),
+	  SIG_EXPR_LIST_PTR(PORTA_U3_PHY, USB3AXHP), SIG_EXPR_LIST_PTR(PORTA_U3_PHY, USB3BXH2A),
+	  SIG_EXPR_LIST_PTR(PORTA_U3_PHY, USB3BXHP2A));
+
+SIG_EXPR_LIST_ALIAS(PORTB_U3_PHY, USB3AXH2B, USB3ABP);
+SIG_EXPR_LIST_ALIAS(PORTB_U3_PHY, USB3AXHP2B, USB3ABP);
+SIG_EXPR_LIST_ALIAS(PORTB_U3_PHY, USB3BXH, USB3BBP);
+SIG_EXPR_LIST_ALIAS(PORTB_U3_PHY, USB3BXHP, USB3BBP);
+PIN_DECL_(PORTB_U3_PHY, SIG_EXPR_LIST_PTR(PORTB_U3_PHY, USB3AXH2B),
+	  SIG_EXPR_LIST_PTR(PORTB_U3_PHY, USB3AXHP2B), SIG_EXPR_LIST_PTR(PORTB_U3_PHY, USB3BXH),
+	  SIG_EXPR_LIST_PTR(PORTB_U3_PHY, USB3BXHP));
+
+/* USB3A xHCI to vHUB */
+GROUP_DECL(USB3A, PORTA_U3);
+/* USB3A xHCI to USB3A PHY */
+GROUP_DECL(USB3AAP, PORTA_U3, PORTA_U3_PHY);
+/* USB3A xHCI to USB3B PHY */
+GROUP_DECL(USB3ABP, PORTA_U3, PORTB_U3_PHY);
+
+FUNC_DECL_1(USB3AXHD, USB3A);
+FUNC_DECL_1(USB3AXHPD, USB3A);
+FUNC_DECL_1(USB3AXH, USB3AAP);
+FUNC_DECL_1(USB3AXHP, USB3AAP);
+FUNC_DECL_1(USB3AXH2B, USB3ABP);
+FUNC_DECL_1(USB3AXHP2B, USB3ABP);
+
+/* USB3B xHCI to vHUB */
+GROUP_DECL(USB3B, PORTB_U3);
+/* USB3B xHCI to USB3A PHY */
+GROUP_DECL(USB3BAP, PORTB_U3, PORTA_U3_PHY);
+/* USB3B xHCI to USB3B PHY */
+GROUP_DECL(USB3BBP, PORTB_U3, PORTB_U3_PHY);
+
+FUNC_DECL_1(USB3BXHD, USB3B);
+FUNC_DECL_1(USB3BXHPD, USB3B);
+FUNC_DECL_1(USB3BXH, USB3BBP);
+FUNC_DECL_1(USB3BXHP, USB3BBP);
+FUNC_DECL_1(USB3BXH2A, USB3BAP);
+FUNC_DECL_1(USB3BXHP2A, USB3BAP);
+
+static const struct pinctrl_pin_desc aspeed_g7_soc0_pins[] = {
+	ASPEED_PINCTRL_PIN(AC14),
+	ASPEED_PINCTRL_PIN(AE15),
+	ASPEED_PINCTRL_PIN(AD14),
+	ASPEED_PINCTRL_PIN(AE14),
+	ASPEED_PINCTRL_PIN(AF14),
+	ASPEED_PINCTRL_PIN(AB13),
+	ASPEED_PINCTRL_PIN(AB14),
+	ASPEED_PINCTRL_PIN(AF15),
+	ASPEED_PINCTRL_PIN(AF13),
+	ASPEED_PINCTRL_PIN(AC13),
+	ASPEED_PINCTRL_PIN(AD13),
+	ASPEED_PINCTRL_PIN(AE13),
+	ASPEED_PINCTRL_PIN(JTAG_PORT),
+	ASPEED_PINCTRL_PIN(PCIERC0_PERST),
+	ASPEED_PINCTRL_PIN(PCIERC1_PERST),
+	ASPEED_PINCTRL_PIN(PORTA_MODE),
+	ASPEED_PINCTRL_PIN(PORTA_U2),
+	ASPEED_PINCTRL_PIN(PORTA_U3),
+	ASPEED_PINCTRL_PIN(PORTA_U2_PHY),
+	ASPEED_PINCTRL_PIN(PORTA_U3_PHY),
+	ASPEED_PINCTRL_PIN(PORTB_MODE),
+	ASPEED_PINCTRL_PIN(PORTB_U2),
+	ASPEED_PINCTRL_PIN(PORTB_U3),
+	ASPEED_PINCTRL_PIN(PORTB_U2_PHY),
+	ASPEED_PINCTRL_PIN(PORTB_U3_PHY),
+};
+
+static const struct aspeed_pin_group aspeed_g7_soc0_groups[] = {
+	ASPEED_PINCTRL_GROUP(EMMCCDN),
+	ASPEED_PINCTRL_GROUP(EMMCG1),
+	ASPEED_PINCTRL_GROUP(EMMCG4),
+	ASPEED_PINCTRL_GROUP(EMMCG8),
+	ASPEED_PINCTRL_GROUP(EMMCWPN),
+	ASPEED_PINCTRL_GROUP(TSPRSTN),
+	ASPEED_PINCTRL_GROUP(UFSCLKI),
+	ASPEED_PINCTRL_GROUP(VB0),
+	ASPEED_PINCTRL_GROUP(VB1),
+	ASPEED_PINCTRL_GROUP(VGADDC),
+	/* JTAG groups */
+	ASPEED_PINCTRL_GROUP(JTAG0),
+	/* PCIE RC groups */
+	ASPEED_PINCTRL_GROUP(PCIERC0PERST),
+	ASPEED_PINCTRL_GROUP(PCIERC1PERST),
+	/* USB3A groups */
+	ASPEED_PINCTRL_GROUP(USB3A),
+	ASPEED_PINCTRL_GROUP(USB3AAP),
+	ASPEED_PINCTRL_GROUP(USB3ABP),
+	/* USB3B groups */
+	ASPEED_PINCTRL_GROUP(USB3B),
+	ASPEED_PINCTRL_GROUP(USB3BAP),
+	ASPEED_PINCTRL_GROUP(USB3BBP),
+	/* USB2A groups */
+	ASPEED_PINCTRL_GROUP(USB2A),
+	ASPEED_PINCTRL_GROUP(USB2AAP),
+	ASPEED_PINCTRL_GROUP(USB2ABP),
+	ASPEED_PINCTRL_GROUP(USB2ADAP),
+	ASPEED_PINCTRL_GROUP(USB2AH),
+	ASPEED_PINCTRL_GROUP(USB2AHAP),
+	/* USB2B groups */
+	ASPEED_PINCTRL_GROUP(USB2B),
+	ASPEED_PINCTRL_GROUP(USB2BAP),
+	ASPEED_PINCTRL_GROUP(USB2BBP),
+	ASPEED_PINCTRL_GROUP(USB2BDBP),
+	ASPEED_PINCTRL_GROUP(USB2BH),
+	ASPEED_PINCTRL_GROUP(USB2BHBP),
+};
+
+static const struct aspeed_pin_function aspeed_g7_soc0_functions[] = {
+	ASPEED_PINCTRL_FUNC(EMMC),
+	ASPEED_PINCTRL_FUNC(TSPRSTN),
+	ASPEED_PINCTRL_FUNC(UFSCLKI),
+	ASPEED_PINCTRL_FUNC(VB),
+	ASPEED_PINCTRL_FUNC(VGADDC),
+	/* JTAG functions */
+	ASPEED_PINCTRL_FUNC(JTAGDDR),
+	ASPEED_PINCTRL_FUNC(JTAGM0),
+	ASPEED_PINCTRL_FUNC(JTAGPCIEA),
+	ASPEED_PINCTRL_FUNC(JTAGPCIEB),
+	ASPEED_PINCTRL_FUNC(JTAGPSP),
+	ASPEED_PINCTRL_FUNC(JTAGSSP),
+	ASPEED_PINCTRL_FUNC(JTAGTSP),
+	ASPEED_PINCTRL_FUNC(JTAGUSB3A),
+	ASPEED_PINCTRL_FUNC(JTAGUSB3B),
+	/* PCIE RC functions */
+	ASPEED_PINCTRL_FUNC(PCIERC0PERST),
+	ASPEED_PINCTRL_FUNC(PCIERC1PERST),
+	/* USB3A functions */
+	ASPEED_PINCTRL_FUNC(USB3AXH),
+	ASPEED_PINCTRL_FUNC(USB3AXH2B),
+	ASPEED_PINCTRL_FUNC(USB3AXHD),
+	ASPEED_PINCTRL_FUNC(USB3AXHP),
+	ASPEED_PINCTRL_FUNC(USB3AXHP2B),
+	ASPEED_PINCTRL_FUNC(USB3AXHPD),
+	/* USB3B functions */
+	ASPEED_PINCTRL_FUNC(USB3BXH),
+	ASPEED_PINCTRL_FUNC(USB3BXH2A),
+	ASPEED_PINCTRL_FUNC(USB3BXHD),
+	ASPEED_PINCTRL_FUNC(USB3BXHP),
+	ASPEED_PINCTRL_FUNC(USB3BXHP2A),
+	ASPEED_PINCTRL_FUNC(USB3BXHPD),
+	/* USB2A functions */
+	ASPEED_PINCTRL_FUNC(USB2AD0),
+	ASPEED_PINCTRL_FUNC(USB2AD1),
+	ASPEED_PINCTRL_FUNC(USB2AH),
+	ASPEED_PINCTRL_FUNC(USB2AHP),
+	ASPEED_PINCTRL_FUNC(USB2AHPD0),
+	ASPEED_PINCTRL_FUNC(USB2AXH),
+	ASPEED_PINCTRL_FUNC(USB2AXH2B),
+	ASPEED_PINCTRL_FUNC(USB2AXHD1),
+	ASPEED_PINCTRL_FUNC(USB2AXHP),
+	ASPEED_PINCTRL_FUNC(USB2AXHP2B),
+	ASPEED_PINCTRL_FUNC(USB2AXHPD1),
+	/* USB2B functions */
+	ASPEED_PINCTRL_FUNC(USB2BD0),
+	ASPEED_PINCTRL_FUNC(USB2BD1),
+	ASPEED_PINCTRL_FUNC(USB2BH),
+	ASPEED_PINCTRL_FUNC(USB2BHP),
+	ASPEED_PINCTRL_FUNC(USB2BHPD0),
+	ASPEED_PINCTRL_FUNC(USB2BXH),
+	ASPEED_PINCTRL_FUNC(USB2BXH2A),
+	ASPEED_PINCTRL_FUNC(USB2BXHD1),
+	ASPEED_PINCTRL_FUNC(USB2BXHP),
+	ASPEED_PINCTRL_FUNC(USB2BXHP2A),
+	ASPEED_PINCTRL_FUNC(USB2BXHPD1),
+};
+
+static const struct pinmux_ops aspeed_g7_soc0_pinmux_ops = {
+	.get_functions_count = aspeed_pinmux_get_fn_count,
+	.get_function_name = aspeed_pinmux_get_fn_name,
+	.get_function_groups = aspeed_pinmux_get_fn_groups,
+	.set_mux = aspeed_pinmux_set_mux,
+	.gpio_request_enable = aspeed_gpio_request_enable,
+	.strict = true,
+};
+
+static const struct pinctrl_ops aspeed_g7_soc0_pinctrl_ops = {
+	.get_groups_count = aspeed_pinctrl_get_groups_count,
+	.get_group_name = aspeed_pinctrl_get_group_name,
+	.get_group_pins = aspeed_pinctrl_get_group_pins,
+	.pin_dbg_show = aspeed_pinctrl_pin_dbg_show,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+	.dt_free_map = pinctrl_utils_free_map,
+};
+
+static const struct pinconf_ops aspeed_g7_soc0_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = aspeed_pin_config_get,
+	.pin_config_set = aspeed_pin_config_set,
+	.pin_config_group_get = aspeed_pin_config_group_get,
+	.pin_config_group_set = aspeed_pin_config_group_set,
+};
+
+/* pinctrl_desc */
+static const struct pinctrl_desc aspeed_g7_soc0_pinctrl_desc = {
+	.name = "aspeed-g7-soc0-pinctrl",
+	.pins = aspeed_g7_soc0_pins,
+	.npins = ARRAY_SIZE(aspeed_g7_soc0_pins),
+	.pctlops = &aspeed_g7_soc0_pinctrl_ops,
+	.pmxops = &aspeed_g7_soc0_pinmux_ops,
+	.confops = &aspeed_g7_soc0_pinconf_ops,
+};
+
+static const struct aspeed_pin_config aspeed_g7_soc0_configs[] = {
+	/* GPIO18A */
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AC14, AC14 }, SCU480, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AC14, AC14 }, SCU480, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AC14, AC14 }, SCU480, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AC14, AC14 }, SCU480, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AE15, AE15 }, SCU484, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AE15, AE15 }, SCU484, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AE15, AE15 }, SCU484, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AE15, AE15 }, SCU484, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AD14, AD14 }, SCU488, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AD14, AD14 }, SCU488, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AD14, AD14 }, SCU488, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AD14, AD14 }, SCU488, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AE14, AE14 }, SCU48C, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AE14, AE14 }, SCU48C, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AE14, AE14 }, SCU48C, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AE14, AE14 }, SCU48C, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AF14, AF14 }, SCU490, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AF14, AF14 }, SCU490, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AF14, AF14 }, SCU490, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AF14, AF14 }, SCU490, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AB13, AB13 }, SCU494, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AB13, AB13 }, SCU494, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AB13, AB13 }, SCU494, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AB13, AB13 }, SCU494, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AB14, AB14 }, SCU498, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AB14, AB14 }, SCU498, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AB14, AB14 }, SCU498, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AB14, AB14 }, SCU498, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AF15, AF15 }, SCU49C, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AF15, AF15 }, SCU49C, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AF15, AF15 }, SCU49C, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AF15, AF15 }, SCU49C, BIT(5) },
+	/* GPIO18B */
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AF13, AF13 }, SCU4A0, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AF13, AF13 }, SCU4A0, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AF13, AF13 }, SCU4A0, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AF13, AF13 }, SCU4A0, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AC13, AC13 }, SCU4A4, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AC13, AC13 }, SCU4A4, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AC13, AC13 }, SCU4A4, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AC13, AC13 }, SCU4A4, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AD13, AD13 }, SCU4A8, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AD13, AD13 }, SCU4A8, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AD13, AD13 }, SCU4A8, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AD13, AD13 }, SCU4A8, BIT(5) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, { AE13, AE13 }, SCU4AC, GENMASK(3, 0) },
+	{ PIN_CONFIG_BIAS_PULL_DOWN, { AE13, AE13 }, SCU4AC, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_PULL_UP, { AE13, AE13 }, SCU4AC, GENMASK(5, 4) },
+	{ PIN_CONFIG_BIAS_DISABLE, { AE13, AE13 }, SCU4AC, BIT(5) },
+};
+
+static const struct aspeed_pin_config_map aspeed_g7_soc0_pin_config_map[] = {
+	{ PIN_CONFIG_BIAS_PULL_DOWN, -1, 2, GENMASK(1, 0) },
+	{ PIN_CONFIG_BIAS_PULL_UP, -1, 3, GENMASK(1, 0) },
+	{ PIN_CONFIG_BIAS_DISABLE, -1, 0, BIT_MASK(0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 3, 0, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 6, 1, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 8, 2, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 11, 3, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 16, 4, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 18, 5, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 20, 6, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 23, 7, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 30, 8, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 32, 9, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 33, 10, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 35, 11, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 37, 12, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 38, 13, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 39, 14, GENMASK(3, 0) },
+	{ PIN_CONFIG_DRIVE_STRENGTH, 41, 15, GENMASK(3, 0) },
+
+};
+
+static int aspeed_g7_soc0_sig_expr_set(struct aspeed_pinmux_data *ctx,
+				       const struct aspeed_sig_expr *expr, bool enable)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < expr->ndescs; i++) {
+		const struct aspeed_sig_desc *desc = &expr->descs[i];
+		u32 pattern = enable ? desc->enable : desc->disable;
+		u32 val = (pattern << __ffs(desc->mask));
+
+		if (!ctx->maps[desc->ip])
+			return -ENODEV;
+
+		WARN_ON_ONCE(desc->ip != ASPEED_IP_SCU);
+
+		ret = regmap_update_bits(ctx->maps[desc->ip], desc->reg,
+					 desc->mask, val);
+		if (ret)
+			return ret;
+	}
+
+	ret = aspeed_sig_expr_eval(ctx, expr, enable);
+	if (ret < 0)
+		return ret;
+
+	return ret ? 0 : -EPERM;
+}
+
+static const struct aspeed_pinmux_ops aspeed_g7_soc0_ops = {
+	.set = aspeed_g7_soc0_sig_expr_set,
+};
+
+static struct aspeed_pinctrl_data aspeed_g7_soc0_pinctrl_data = {
+	.pins = aspeed_g7_soc0_pins,
+	.npins = ARRAY_SIZE(aspeed_g7_soc0_pins),
+	.pinmux = {
+		.ops = &aspeed_g7_soc0_ops,
+		.groups = aspeed_g7_soc0_groups,
+		.ngroups = ARRAY_SIZE(aspeed_g7_soc0_groups),
+		.functions = aspeed_g7_soc0_functions,
+		.nfunctions = ARRAY_SIZE(aspeed_g7_soc0_functions),
+	},
+	.configs = aspeed_g7_soc0_configs,
+	.nconfigs = ARRAY_SIZE(aspeed_g7_soc0_configs),
+	.confmaps = aspeed_g7_soc0_pin_config_map,
+	.nconfmaps = ARRAY_SIZE(aspeed_g7_soc0_pin_config_map),
+};
+
+static int aspeed_g7_soc0_pinctrl_probe(struct platform_device *pdev)
+{
+	return aspeed_pinctrl_probe(pdev, &aspeed_g7_soc0_pinctrl_desc,
+				    &aspeed_g7_soc0_pinctrl_data);
+}
+
+static const struct of_device_id aspeed_g7_soc0_pinctrl_match[] = {
+	{ .compatible = "aspeed,ast2700-soc0-pinctrl" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, aspeed_g7_soc0_pinctrl_match);
+
+static struct platform_driver aspeed_g7_soc0_pinctrl_driver = {
+	.probe = aspeed_g7_soc0_pinctrl_probe,
+	.driver = {
+		.name = "aspeed-g7-soc0-pinctrl",
+		.of_match_table = aspeed_g7_soc0_pinctrl_match,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init aspeed_g7_soc0_pinctrl_init(void)
+{
+	return platform_driver_register(&aspeed_g7_soc0_pinctrl_driver);
+}
+arch_initcall(aspeed_g7_soc0_pinctrl_init);

-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH RFC] ACPI: processor: idle: Do not propagate acpi_processor_ffh_lpi_probe() -ENODEV
From: lihuisong (C) @ 2026-04-14  9:43 UTC (permalink / raw)
  To: Breno Leitao, Rafael J. Wysocki, Len Brown, lpieralisi,
	catalin.marinas, will
  Cc: Rafael J. Wysocki, linux-acpi, linux-kernel, pjaroszynski,
	guohanjun, sudeep.holla, linux-arm-kernel, rmikey, kernel-team,
	lihuisong
In-Reply-To: <20260413-ffh-v1-1-301704f69e2f@debian.org>


On 4/14/2026 12:54 AM, Breno Leitao wrote:
> Commit cac173bea57d ("ACPI: processor: idle: Rework the handling of
> acpi_processor_ffh_lpi_probe()") moved the acpi_processor_ffh_lpi_probe()
> call from acpi_processor_setup_cpuidle_dev(), where its return value was
> ignored, to acpi_processor_get_power_info(), where it is treated as a
> hard failure. This causes cpuidle setup to fail entirely for all CPUs on
> platforms where the FFH LPI probe returns an error.
>
> On NVIDIA Grace (aarch64) systems with PSCIv1.1, the probe fails for all
> 72 CPUs with -ENODEV because psci_acpi_cpu_init_idle() finds
> power.count - 1 <= 0 (power.count=1). This results in no cpuidle states
> registered for any CPU, forcing them to busy-poll when idle instead of
> entering low-power states.
>
>
Sorry for bring you cpuidle issues on your platform.
IIUC, your platfom just has one LPI states on failure, it should be WFI, 
right?
This failure will only cause the cpuidle directory for each CPU not to 
be created, but will not affect the CPU entering the WFI state which 
done by cpuidle core.

But it is a real issue. Thanks for your report.
I think the best way to fix your issue is that remove this verification 
in psci_acpi_cpu_init_idle().
Because it is legal for platform to report one LPI state.
This function just needs to verify the LPI states which are FFH.

/Huisong
>
>


^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: reset: imx8mq: Add _N suffix to IMX8MQ_RESET_MIPI_CSI*_RESET
From: Robby Cai @ 2026-04-14  9:55 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam, devicetree,
	kernel, imx, linux-arm-kernel, linux-kernel, aisheng.dong
In-Reply-To: <d6cdea5f1a4f2eb3f7b73e6136c77020f444d8f0.camel@pengutronix.de>

On Tue, Mar 31, 2026 at 02:45:07PM +0200, Philipp Zabel wrote:
> On Di, 2026-03-31 at 18:13 +0800, Robby Cai wrote:
> > The assert logic of the MIPI CSI reset signals is active-low on i.MX8MQ,
> > but the existing names do not indicate this explicitly. To improve
> > consistency and clarity, append the _N suffix to all
> > IMX8MQ_RESET_MIPI_CSI*_RESET definitions. The deprecated
> > IMX8MQ_RESET_MIPI_CSI*_RESET versions remain temporarily for DT ABI
> > compatibility and will be removed at an appropriate time in the future.
> 
> The register description in the latest reference manual I can download,
> IMX8MDQLQRM Rev. 3.1 (06/2021), still call these bits
> MIPI_CSI1_CORE_RESET and so on (without _N). There is no mention of
> polarity in the bitfield description. Is a documentation update
> planned?

Yes. A documentation update is already planned to clarify the reset polarity
(active-low) and naming. The current RM description is incomplete and will be
corrected in a future revision.

> 
> Right now I'd say this improves clarity, but reduces consistency with
> existing documentation.
> 
> Are these bits self-clearing, or can the reset be asserted by writing
> 0? As it stands, the CSI driver using these resets, imx8mq-mipi-csi2.c,
> only calls reset_control_assert() in imx8mq_mipi_csi_sw_reset():
> 
>           /*                                                          
>            * these are most likely self-clearing reset bits. to make it
>            * more clear, the reset-imx7 driver should implement the   
>            * .reset() operation.                                      
>            */                     
>           ret = reset_control_assert(state->rst);
> 
> This will probably have to be turned into a deassert together with the
> reset driver change.

No, these reset bits are not self-clearing.

According to the design team, the MIPI CSI reset logic on i.MX8MQ is identical
to MIPI DSI: the reset is active-low and must be explicitly deasserted.
Writing ��0�� asserts reset and it will remain asserted until cleared by software.

The current assumption in the CSI driver that these bits are self-clearing is
therefore incorrect. This was exposed by the landing patch [1].

To fix this properly, the reset-imx7 driver needs to reflect the correct polarity,
and the CSI driver should use deassert instead of only calling
reset_control_assert(). The RM will also be updated to clarify this behavior.

[1] https://git.linuxtv.org/media.git/commit/?id=6d79bb8fd2aa25afccbd6aeec2821722fa0b5db5


Regards,
Robby



^ permalink raw reply

* Re: [PATCH 1/3] iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event handling
From: Andy Shevchenko @ 2026-04-14  9:58 UTC (permalink / raw)
  To: Guilherme Ivo Bozi
  Cc: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek,
	David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260414093018.7153-2-guilherme.bozi@usp.br>

On Tue, Apr 14, 2026 at 06:29:28AM -0300, Guilherme Ivo Bozi wrote:
> ams_event_to_channel() may return a pointer past the end of
> dev->channels when no matching scan_index is found. This can lead
> to invalid memory access in ams_handle_event().
> 
> Add a bounds check in ams_event_to_channel() and return NULL when
> no channel is found. Also guard the caller to safely handle this
> case.

> Fixes: <d5c70627a79455154f5f636096abe6fe57510605>

Incorrect format of the Fixes tag. Please, consult with Submitting Patches
documentation on that matter.

-- 
With Best Regards,
Andy Shevchenko




^ permalink raw reply

* Re: [PATCH 2/3] iio: adc: xilinx-ams: use guard(mutex) for automatic locking
From: Andy Shevchenko @ 2026-04-14  9:59 UTC (permalink / raw)
  To: Guilherme Ivo Bozi
  Cc: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek,
	David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260414093018.7153-3-guilherme.bozi@usp.br>

On Tue, Apr 14, 2026 at 06:29:29AM -0300, Guilherme Ivo Bozi wrote:
> Replace open-coded mutex_lock()/mutex_unlock() pairs with
> guard(mutex) to simplify locking and ensure proper unlock on
> all control flow paths.
> 
> This removes explicit unlock handling, reduces boilerplate,
> and avoids potential mistakes in error paths while keeping
> the behavior unchanged.

OK.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>

-- 
With Best Regards,
Andy Shevchenko




^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox