Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] dt-bindings: arm-smmu: qcom: Add compatible for Qualcomm Shikra SoC
From: Komal Bajaj @ 2026-04-30 12:24 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, Komal Bajaj

Qualcomm Shikra SoC includes an apps SMMU that implements arm,mmu-500,
which is used to translate device-visible virtual addresses to physical
addresses. Add compatible for it.

Signed-off-by: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
---
 Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 06fb5c8e7547..1f544103b574 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -55,6 +55,7 @@ properties:
               - qcom,sdx55-smmu-500
               - qcom,sdx65-smmu-500
               - qcom,sdx75-smmu-500
+              - qcom,shikra-smmu-500
               - qcom,sm6115-smmu-500
               - qcom,sm6125-smmu-500
               - qcom,sm6350-smmu-500

---
base-commit: 39704f00f747aba3144289870b5fd8ac230a9aaf
change-id: 20260430-shikra-smmu-binding-7befe45ecf2a

Best regards,
-- 
Komal Bajaj <komal.bajaj@oss.qualcomm.com>



^ permalink raw reply related

* Re: [PATCH net v2] net: airoha: Move entries to queue head in case of DMA mapping failure in airoha_dev_xmit()
From: Lorenzo Bianconi @ 2026-04-30 12:23 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Jacob Keller
  Cc: Simon Horman, linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <20260429-airoha-xmit-unmap-error-path-v2-1-32e43b7c6d25@kernel.org>

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

> In order to respect the original descriptor order and avoid any
> potential IOMMU fault or memory corruption, move pending queue entries
> to the head of hw queue tx_list if the DMA mapping of current inflight
> packet fails in airoha_dev_xmit routine.
> 
> Fixes: 3f47e67dff1f7 ("net: airoha: Add the capability to consume out-of-order DMA tx descriptors")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> Changes in v2:
> - Remove leftover airoha_queue_entry initialization inside the loop from
>   the previous version.
> - Link to v1: https://lore.kernel.org/r/20260428-airoha-xmit-unmap-error-path-v1-1-aec44c6765c1@kernel.org
> ---
>  drivers/net/ethernet/airoha/airoha_eth.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 5effb4a4ae84..fb4f51d67dd7 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -2123,14 +2123,12 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>  	return NETDEV_TX_OK;
>  
>  error_unmap:
> -	while (!list_empty(&tx_list)) {
> -		e = list_first_entry(&tx_list, struct airoha_queue_entry,
> -				     list);
> +	list_for_each_entry(e, &tx_list, list) {
>  		dma_unmap_single(dev->dev.parent, e->dma_addr, e->dma_len,
>  				 DMA_TO_DEVICE);
>  		e->dma_addr = 0;
> -		list_move_tail(&e->list, &q->tx_list);
>  	}
> +	list_splice(&tx_list, &q->tx_list);
>  
>  	spin_unlock_bh(&q->lock);
>  error:

commenting on Sashiko's reported issues:
https://sashiko.dev/#/patchset/20260429-airoha-xmit-unmap-error-path-v2-1-32e43b7c6d25%40kernel.org

- Should the driver be updated to use skb_frag_dma_map() for mapping the SKB
  fragments, and correspondingly use dma_unmap_page() for those fragments in
  this error handling path?
  As we already pointed out here [0], we decided to skip this request and keep
  using dma_map_single() even for skb fragments.

Regards,
Lorenzo

[0] https://lore.kernel.org/netdev/20260427173935.6a1e36ee@kernel.org/

> 
> ---
> base-commit: 0c7a5ba011d336df4fcd1f667fcc16ea5549be12
> change-id: 20260428-airoha-xmit-unmap-error-path-8125594efb23
> 
> Best regards,
> -- 
> Lorenzo Bianconi <lorenzo@kernel.org>
> 

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

^ permalink raw reply

* Re: [PATCH 16/43] KVM: arm64: gic-v5: Initialise and teardown VMTEs & doorbells
From: Marc Zyngier @ 2026-04-30 12:23 UTC (permalink / raw)
  To: Sascha Bischoff
  Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
	kvm@vger.kernel.org, nd, oliver.upton@linux.dev, Joey Gouly,
	Suzuki Poulose, yuzenghui@huawei.com, peter.maydell@linaro.org,
	lpieralisi@kernel.org, Timothy Hayes
In-Reply-To: <20260427160547.3129448-17-sascha.bischoff@arm.com>

On Mon, 27 Apr 2026 17:11:30 +0100,
Sascha Bischoff <Sascha.Bischoff@arm.com> wrote:
> 
> Each GICv5 VM requires a valid VM Table Entry (VMTE). The VM Table
> itself is allocated during probe time, but a VM needs to provision a
> VMTE before it is able to properly run (PPIs will work, but nothing
> else will - and PPIs only are not useful!).
> 
> The correct time for setting up the VMTE is during VM
> initialisation. For GICv5, this is vgic_v5_init(). Each VM needs a VM
> ID - this is actually the index into the VM Table so it is how a
> specific VMTE is selected too. As part of vgic_v5_init get a VM ID via
> vgic_v5_allocate_vm_id(), which internally uses an IDA to select an
> unused VM ID (and hence VMTE) within the range of allowed VM IDs.
> 
> Once the VM ID has been allocated, the doorbell domain for the VM is
> allocated, and each of the doorbells itself is allocated and assigned
> to a vcpu.
> 
> Assuming everything up until this point has succeeded, initialise the
> VMTE. Internally this allocates the additional data structures
> required by the hardware - the VM Descriptor, VPE Table, etc. This
> VMTE is then made valid via the IRS's MMIO interface. Finally, all
> VPEs are allocated within the VPET.
> 
> On teardown, this process is reversed again. The VMTE is made invalid,
> the VPEs are freed, the doorbells are released and the domain torn
> down, and finally the VM ID is released. The latter allows the VM ID
> and VMTE to be reused for a future VM.
> 
> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> ---
>  arch/arm64/kvm/vgic/vgic-v5.c | 146 +++++++++++++++++++++++++++++-----
>  1 file changed, 128 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
> index 2fc6fa4df034f..9347bc6895223 100644
> --- a/arch/arm64/kvm/vgic/vgic-v5.c
> +++ b/arch/arm64/kvm/vgic/vgic-v5.c
> @@ -518,6 +518,18 @@ static int vgic_v5_irs_vpe_cr0_update(int vm_id, int vpe_id, u32 cr0)
>  	return 0;
>  }
>  
> +static irqreturn_t db_handler(int irq, void *data)
> +{
> +	struct kvm_vcpu *vcpu = data;
> +
> +	WRITE_ONCE(vcpu->arch.vgic_cpu.vgic_v5.gicv5_vpe.db_fired, true);
> +
> +	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
> +	kvm_vcpu_kick(vcpu);
> +
> +	return IRQ_HANDLED;
> +}
> +

I think it'd make more sense if the doorbell
handling/requesting/freeing was one patch, or at least a set of
consecutive patches in the series.

As it is now, it is very hard to keep track of things. You have part
of it in the previous patch, the requesting and handling here, and
probably the freeing in some other patch I haven't seen.

>  static int vgic_v5_send_command(struct kvm_vcpu *vcpu,
>  				enum gicv5_vcpu_info_cmd_type type)
>  {
> @@ -726,26 +738,46 @@ void vgic_v5_reset(struct kvm_vcpu *vcpu)
>  	}
>  }
>  
> -int vgic_v5_init(struct kvm *kvm)
> +int vgic_v5_map_resources(struct kvm *kvm)
>  {
> -	struct kvm_vcpu *vcpu;
> -	unsigned long idx;
> -	int ret;
> +	if (!vgic_initialized(kvm))
> +		return -EBUSY;
>  
> -	if (vgic_initialized(kvm))
> -		return 0;
> +	return 0;
> +}

Pointless code movement?

>
> -	ret = vgic_v5_create_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> -	if (ret)
> -		return ret;
> +/*
> + * Claim and populate a VMTE (optionally making a new L2 VMT valid), create VPE
> + * doorbells, allocate VPET and populate for each VPE. Finally, we also init the
> + * vIRS, which means allocating and making the virtual SPI IST valid.
> + *
> + * Note: We do need to put the cart before the horse here. The VPE doorbells are
> + * our conduit for communication with the IRS, which means we need to have those
> + * before making the VMTE valid.
> + *
> + * On failure, we clean up in the teardown path (vgic_v5_teardown()).
> + */
> +int vgic_v5_init(struct kvm *kvm)
> +{
> +	int nr_vcpus, ret = 0;
> +	struct kvm_vcpu *vcpu, *vcpu0;
> +	unsigned long i;
> +	struct irq_data *d;
> +	unsigned int db_virq;
> +
> +	nr_vcpus = atomic_read(&kvm->online_vcpus);
> +	if (nr_vcpus == 0)
> +		return -ENODEV;
>  
> -	kvm_for_each_vcpu(idx, vcpu, kvm) {
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
>  		if (vcpu_has_nv(vcpu)) {
>  			kvm_err("Nested GICv5 VMs are currently unsupported\n");
>  			return -EINVAL;
>  		}
>  	}
>  
> +	kvm->arch.vgic.gicv5_vm.nr_vpes = nr_vcpus;

Why do we need to track the number of vcpus separately from what KVM
already does? GICv4 does it because a lot of the state is managed by
the irqchip driver, but that's not the case here. I hope we can come
up with a slightly simpler model with GICv5.

> +
>  	/* We only allow userspace to drive the SW_PPI, if it is implemented. */
>  	bitmap_zero(kvm->arch.vgic.gicv5_vm.userspace_ppis,
>  		    VGIC_V5_NR_PRIVATE_IRQS);
> @@ -754,20 +786,98 @@ int vgic_v5_init(struct kvm *kvm)
>  		   kvm->arch.vgic.gicv5_vm.userspace_ppis,
>  		   ppi_caps.impl_ppi_mask, VGIC_V5_NR_PRIVATE_IRQS);
>  
> -	return 0;
> +	ret = vgic_v5_allocate_vm_id(kvm);
> +	if (ret) {
> +		kvm_err("Maximum number of GICv5 VMs reached!\n");
> +		return ret;
> +	}

I'd rather we don't scream on the console when running out of
VMIDs. If we're at capacity, so be it. That's not an error worth
spamming the console over.

> +
> +	ret = vgic_v5_create_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> +	if (ret)
> +		return ret;

Who is freeing the VMID?

> +
> +	/*
> +	 * Allocate VPE doorbells first - these are our conduit for
> +	 * communicating with the host irqchip driver.
> +	 */
> +	db_virq = irq_domain_alloc_irqs(kvm->arch.vgic.gicv5_vm.domain,
> +					nr_vcpus, NUMA_NO_NODE,
> +					&kvm->arch.vgic.gicv5_vm);
> +	if (db_virq < 0) {
> +		/* Simplify teardown by doing this early! */
> +		vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> +		return db_virq;
> +	}
> +
> +	kvm->arch.vgic.gicv5_vm.vpe_db_base = db_virq;
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		d = irq_domain_get_irq_data(kvm->arch.vgic.gicv5_vm.domain,
> +					    db_virq + i);
> +		irq_set_status_flags(db_virq + i, IRQ_NOAUTOEN);
> +
> +		ret = request_irq(db_virq + i, db_handler, 0, "vcpu", vcpu);
> +		if (ret)
> +			return ret;
> +
> +		/* Stash it with the VCPU for easy retrieval */
> +		vcpu->arch.vgic_cpu.vgic_v5.gicv5_vpe.db = db_virq + i;
> +	}
> +
> +	/* Populate VMTE (with VPET and VM descriptor) */
> +	ret = vgic_v5_vmte_init(kvm);
> +	if (ret)
> +		return ret;
> +
> +	/* We pick the first vcpu to make the VMTE valid - any would do */
> +	vcpu0 = kvm_get_vcpu(kvm, 0);
> +	ret = vgic_v5_send_command(vcpu0, VMTE_MAKE_VALID);
> +	if (ret)
> +		return ret;
> +
> +	/* Loop over all VPEs, allocate/populate their data structures */
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		ret = vgic_v5_vmte_alloc_vpe(vcpu);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return ret;

I'm very worried about the error handling of that function. Who is
responsible for cleaning up the mess when this fails?

>  }
>  
>  void vgic_v5_teardown(struct kvm *kvm)
>  {
> -	vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> -}
> +	struct kvm_vcpu *vcpu, *vcpu0;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	unsigned long i;
> +	int rc;
>  
> -int vgic_v5_map_resources(struct kvm *kvm)
> -{
> -	if (!vgic_initialized(kvm))
> -		return -EBUSY;
> +	/*
> +	 * If the VM's ID isn't valid, then we failed init very early. Nothing
> +	 * to do here.
> +	 */
> +	if (!kvm->arch.vgic.gicv5_vm.vm_id_valid)
> +		return;
>  
> -	return 0;
> +	if (kvm->arch.vgic.gicv5_vm.vmte_allocated) {
> +		/* Make the VM invalid  */
> +		vcpu0 = kvm_get_vcpu(kvm, 0);
> +		rc = vgic_v5_send_command(vcpu0, VMTE_MAKE_INVALID);
> +		if (rc)
> +			kvm_err("could not make VMTE invalid\n");
> +
> +		kvm_for_each_vcpu(i, vcpu, kvm) {
> +			if (vgic_v5_vmte_free_vpe(vcpu))
> +				kvm_err("Failed to free VPE\n");
> +		}
> +
> +		if (vgic_v5_vmte_release(kvm))
> +			kvm_err("Failed to release VM 0x%x\n", dist->gicv5_vm.vm_id);
> +	}
> +
> +	vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> +
> +	vgic_v5_release_vm_id(kvm);
>  }
>  
>  int vgic_v5_finalize_ppi_state(struct kvm *kvm)

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply

* Re: [PATCH 1/8] KVM: arm64: Make EL2 exception entry and exit context-synchronization events
From: Fuad Tabba @ 2026-04-30 12:18 UTC (permalink / raw)
  To: Will Deacon
  Cc: maz, oliver.upton, james.morse, suzuki.poulose, yuzenghui,
	qperret, vdonnefort, catalin.marinas, linux-arm-kernel, kvmarm,
	linux-kernel, stable
In-Reply-To: <afMb7uuPlUbLeu7k@willie-the-truck>

Hi Will,


On Thu, 30 Apr 2026 at 10:08, Will Deacon <will@kernel.org> wrote:
>
> On Tue, Apr 28, 2026 at 11:30:01AM +0100, Fuad Tabba wrote:
> > SCTLR_EL2.EIS and SCTLR_EL2.EOS control whether exception entry and
> > exit at EL2 are Context Synchronisation Events (CSEs). Per ARM DDI
> > 0487 M.b, EIS is governed by D1.4.2 rule RBBSRF (p. D1-7205) and EOS
> > by D1.4.4.1 rule RBWCFK (p. D1-7209). D24.2.175 (p. D24-9754):
> >
> >   - !FEAT_ExS: the bit is RES1, so the entry/exit is unconditionally
> >     a CSE.
> >   - FEAT_ExS: the reset value is architecturally UNKNOWN; software
> >     must set the bit to make the entry/exit a CSE.
> >
> > INIT_SCTLR_EL2_MMU_ON in arch/arm64/include/asm/sysreg.h sets neither
> > bit. KVM/arm64 hot paths rely on ERET from EL2 being a CSE, and on
> > synchronous EL1->EL2 entry being a CSE, to elide explicit ISBs after
> > MSRs to context-switching system registers (HCR_EL2, HFGxTR_EL2,
> > HCRX_EL2, ZCR_EL2, CPACR_EL1, CPTR_EL2, SCTLR_EL1, ptrauth keys,
> > etc.); examples include the activate-traps path,
> > ptrauth_switch_to_guest, and the FPSIMD trap re-enable in
> > kvm_hyp_handle_fpsimd. On FEAT_ExS hardware those reliances are not
> > architecturally backed unless EOS=1 (and, for entry, EIS=1), and
> > whether they hold today depends on firmware initialisation outside
> > the kernel's control.
> >
> > Make the guarantee explicit: include SCTLR_ELx_EIS | SCTLR_ELx_EOS in
> > INIT_SCTLR_EL2_MMU_ON so that EL2 exception entry and exit are
> > unconditionally CSEs regardless of whether FEAT_ExS is implemented.
> > This matches the pairing in arch/arm64/kvm/config.c which treats EIS
> > and EOS together as RES1 under !FEAT_ExS.
> >
> > INIT_SCTLR_EL2_MMU_OFF is left unchanged: that path is used during
> > very early EL2 init and the EL2 MMU-off transition, neither of which
> > relies on these bits in the same way.
> >
> > Fixes: fe2c8d19189e ("KVM: arm64: Turn SCTLR_ELx_FLAGS into INIT_SCTLR_EL2_MMU_ON")
>
> I don't think this Fixes: tag is accurate:
>
> 1. That commit doesn't do anything with EIS/EOS afaict.
> 2. Back in 5.12 (when that thing landed), SCTLR_EL2_RES1 did actually
>    include EIS and EOS
>
> so I think the issue here might be that the auto-generated sysreg file
> quietly changes the RES1 definitions as bits get allocated, but the
> macros using the RES1 definition don't get updated. That's a pretty
> horrible pit that it feels like we might keep falling into :/
>
> Looking at 0a35bd285f43 ("arm64: Convert SCTLR_EL2 to sysreg
> infrastructure"), I think we ended up dropping a whole bunch of fields
> from the RES1 mask (which became 0!). Have you checked all of those?

You're right, fe2c8d19189e didn't touch EIS/EOS: the SCTLR_EL2_RES1
mask it pulled into INIT_SCTLR_EL2_MMU_ON already contained
BIT(11)/BIT(22). Looking at it, I _think_ it's this one:

  0a35bd285f43 ("arm64: Convert SCTLR_EL2 to sysreg infrastructure")

After that commit SCTLR_EL2_RES1 is auto-generated. Because the
sysreg tooling can only model unconditional RES1, and EIS/EOS are
RES1 only when !FEAT_ExS, the generated mask is UL(0). I'll fix the
Fixes: tag in v2.

On the wider question of the other bits dropped from the old mask,
I went through them against DDI 0487 M.b §D24.2.175. The summary
(SCTLR_EL2 with E2H=0):

  bit  field    E2H=0 status                  kernel cares?
  -------------------------------------------------------------
   4   SA0      RES1 unconditionally          no
   5   CP15BEN  RES1 unconditionally          no
  11   EOS      RES1 iff !FEAT_ExS, else RW   yes (this fix)
  16   nTWI     RES1 unconditionally          no
  18   nTWE     RES1 unconditionally          no
  22   EIS      RES1 iff !FEAT_ExS, else RW   yes (this fix)
  23   SPAN     RES1 unconditionally          no
  28   nTLSMD   RES1 unconditionally          no
  29   LSMAOE   RES1 unconditionally          no

The seven non-EIS/EOS bits all fall under the "Otherwise: Reserved,
RES1" clause for the E2H=0 layout, with no feature guard. Writing 0
to them is a no-op, so dropping them from the mask should be harmless
I think. EIS and EOS are the only positions where the bit
becomes RW (with UNKNOWN reset) on FEAT_ExS hardware and the
kernel actively relies on the value being 1, which is what this
patch addresses.

I agree the auto-generator silently zeroing previously hand-rolled
RES1 masks is a real problem. Happy to look at either teaching the
sysreg infrastructure to express conditional RES1 (so config.c's
AS_RES1/FEAT_X facts can flow back into the header masks), or at
least adding a build-time check that flags any auto-generated
<REG>_RES1 that shrinks. After this series, though. Let me know if
you'd like me to take a stab.

What plan to changechange in v2:

1. Fixes: 0a35bd285f43 ("arm64: Convert SCTLR_EL2 to sysreg infrastructure").
2. Add one paragraph in the commit message explaining that the bug
landed when SCTLR_EL2_RES1 was auto-generated to UL(0), with a
one-line justification that the other seven dropped bits are
unconditionally RES1 at E2H=0 and so harmless.
3. Code diff unchanged (still just adding SCTLR_ELx_EIS |
SCTLR_ELx_EOS to INIT_SCTLR_EL2_MMU_ON).

What do you think?

Cheers,
/fuad

> Will


^ permalink raw reply

* [PATCH v3 0/2] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-30 12:17 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer,
	Krzysztof Kozlowski

Add bindings and description for SolidRUn i.MX8DXL based SoM and
HummingBoard Telematics.

Modify SJA1110 Ethernet Switch bindings to allow SPI Mode 0.

This patch-set is based on v7.0-rc2, because rc1 was experiencing
deadlocks with imx8qxp clock driver.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
Changes in v3:
- rebased on v7.1-rc1.
- dropped dsa swtch port labels, should be handled by udev rules if
  required.
- Fixed spelling error in alias comment.
- Dropped superfluous status okay properties from switch sub-nodes.
- Link to v2: https://lore.kernel.org/r/20260409-imx8dxl-sr-som-v2-0-83ff20629ba0@solid-run.com

Changes in v2:
- Dropped accidental change to unrelated imx8mp-sr-som.dtsi file.
- Fixed phy-mode on fixed link between cpu and ethernet switch.
  (Reported-by: Andrew Lunn <andrew@lunn.ch>)
- Removed spi-cpol property from ethernet-switch on spi bus, fixing
  sja1110a driver probe.
- Changed SJA1110 bindings to allow removing spi-cpol property.
- Aligned comments on all ethernet switch port nodes to be consistent.
- Dropped regulator-always-on from dsrc radio power-supplies.
- Link to v1: https://lore.kernel.org/r/20260408-imx8dxl-sr-som-v1-0-ce5a39acd713@solid-run.com

---
Josua Mayer (2):
      dt-bindings: arm: fsl: Add SolidRun i.MX8DXL SoM and HummingBoard
      arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard

 Documentation/devicetree/bindings/arm/fsl.yaml     |   7 +
 arch/arm64/boot/dts/freescale/Makefile             |   2 +
 .../freescale/imx8dxl-hummingboard-telematics.dts  | 523 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi  | 458 ++++++++++++++++++
 4 files changed, 990 insertions(+)
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260408-imx8dxl-sr-som-f141ec343173

Best regards,
-- 
Josua Mayer <josua@solid-run.com>



^ permalink raw reply

* [PATCH v3 2/2] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-30 12:17 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer
In-Reply-To: <20260430-imx8dxl-sr-som-v3-0-ce2b86cf75bc@solid-run.com>

Add support for the SolidRun i.MX8DXL System-on-Module (revision 2.1)
and its corresponding evaluation carrier board, the HummingBoard
Telematics (revision 2.0).

The SoM features:
- eMMC
- GNSS with 1PPS
- V2X DSRC Radio
- Secure Element for V2X Applications
- Inertial Sensor
- Pressure Sensor
- Compass

The HummingBoard Telematics carrier board features:
- Cellular Modem
- WiFi & Bluetooth
- RTC with backup battery
- CAN
- 100Base-TX Ethernet
- 100Base-T1 Ethernet
- Multi-interface I/O connector
- Multi-interface add-on board connector

The multi-interface I/O connector supplies power and provides basic I/O
(Console UART, 100Base-TX, 100Base-T1, CAN, and power-supply logic level
GPIOs). The SolidRun Evaluation Kit includes a suitable cable and
adapter board that breaks these out into RJ45, USB Type-A, microUSB
Console, and Terminal Block connectors.

The multi-interface add-on board connector provides additional
interfaces (4x 100Base-T1, 2x SGMII, USB 2.0 shared with the cellular
modem, CAN, MDIO, SPI, UART, PCIe, I2C, and GPIO). These add-on
interfaces are disabled by default in the base device tree and are
intended to be enabled and extended via device tree overlays.

Note that a few components physically present on the SoM were omitted
from this description due to a lack of upstream bindings and drivers:
- Pressure Sensor
- V2X DSRC Radio
- Secure Element

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/Makefile             |   2 +
 .../freescale/imx8dxl-hummingboard-telematics.dts  | 523 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi  | 458 ++++++++++++++++++
 3 files changed, 983 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 711e36cc2c990..7db459f666610 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -111,6 +111,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx8dxl-evk.dtb
 
 imx8dxl-evk-pcie-ep-dtbs += imx8dxl-evk.dtb imx-pcie0-ep.dtbo
 dtb-$(CONFIG_ARCH_MXC) += imx8dxl-evk-pcie-ep.dtb
+DTC_FLAGS_imx8dxl-hummingboard-telematics := -@
+dtb-$(CONFIG_ARCH_MXC) += imx8dxl-hummingboard-telematics.dtb
 
 dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdp-mba8xx.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdps-mb-smarc-2.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-hummingboard-telematics.dts b/arch/arm64/boot/dts/freescale/imx8dxl-hummingboard-telematics.dts
new file mode 100644
index 0000000000000..7e822cbd7a528
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-hummingboard-telematics.dts
@@ -0,0 +1,523 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022-2026 Josua Mayer <josua@solid-run.com>
+ */
+
+/dts-v1/;
+
+#include "imx8dxl-sr-som.dtsi"
+
+/ {
+	compatible = "solidrun,imx8dxl-hummingboard-telematics",
+		     "solidrun,imx8dxl-sr-som", "fsl,imx8dxl";
+	model = "SolidRun i.MX8DXL HummingBoard Telematics";
+
+	aliases {
+		/* override ethernet aliases from imx8dxl.dtsi */
+		ethernet0 = &eqos;
+		/delete-property/ ethernet1;
+		gpio8 = &tca6408_u2;
+		mmc2 = &usdhc3;
+		rtc0 = &carrier_rtc;
+		rtc1 = &rtc;
+		serial1 = &lpuart1;
+	};
+
+	v_1_1: regulator-1-1 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v1";
+		pinctrl-0 = <&regulator_1v1_pins>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-max-microvolt = <1100000>;
+		regulator-min-microvolt = <1100000>;
+		vin-supply = <&v_5_0>;
+		gpio = <&lsio_gpio4 5 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_5_0: regulator-5-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "5v0";
+		regulator-max-microvolt = <5000000>;
+		regulator-min-microvolt = <5000000>;
+	};
+
+	/* can transceiver builtin regulator (STBN1 pin) */
+	reg_flexcan1_stby: regulator-flexcan1-standby {
+		compatible = "regulator-fixed";
+		regulator-name = "flexcan1-standby";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		gpio = <&tca6408_u2 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	/* can transceiver builtin regulator (STBN2 pin) */
+	reg_flexcan2_stby: regulator-flexcan2-standby {
+		compatible = "regulator-fixed";
+		regulator-name = "flexcan2-standby";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		gpio = <&tca6408_u2 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	modem_vbat: regulator-modem-vbat {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		pinctrl-0 = <&regulator_modem_vbat_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <3600000>;
+		regulator-min-microvolt = <3600000>;
+		vin-supply = <&v_5_0>;
+		gpio = <&lsio_gpio0 14 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vbus1: regulator-vbus-1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus1";
+		pinctrl-0 = <&regulator_usb1_vbus_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <5000000>;
+		regulator-min-microvolt = <5000000>;
+		gpio = <&lsio_gpio0 16 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	usdhc3_pwrseq: usdhc3-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&lsio_gpio0 15 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&dma_apbh {
+	status = "disabled";
+};
+
+&eqos {
+	/* delays are added by connected ethernet-switch cpu port */
+	phy-mode = "rgmii";
+	pinctrl-0 = <&eqos_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fixed-link {
+		full-duplex;
+		speed = <1000>;
+	};
+};
+
+&flexcan1 {
+	pinctrl-0 = <&flexcan1_pins>;
+	pinctrl-names = "default";
+	xceiver-supply = <&reg_flexcan1_stby>;
+	status = "okay";
+
+	can-transceiver {
+		max-bitrate = <5000000>;
+	};
+};
+
+&flexcan2 {
+	pinctrl-0 = <&flexcan2_pins>;
+	pinctrl-names = "default";
+	xceiver-supply = <&reg_flexcan2_stby>;
+	status = "okay";
+
+	can-transceiver {
+		max-bitrate = <5000000>;
+	};
+};
+
+&i2c2 {
+	/* routed to J14: SDA(51), SCL(53) */
+
+	/* regulator@18 */
+
+	tca6408_u2: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-line-names = "DIG_IN1", "DIG_IN2", "CAN_STNB1", "CAN_STNB2",
+				  "DIG_OUT1", "DIG_OUT2", "", "";
+		interrupts-extended = <&lsio_gpio0 20 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-0 = <&tca6408_u2_int_pins>;
+		pinctrl-names = "default";
+	};
+
+	carrier_rtc: rtc@32 {
+		compatible = "epson,rx8111";
+		reg = <0x32>;
+	};
+};
+
+&iomuxc {
+	bluetooth_pins: pinctrl-bluetooth-grp {
+		fsl,pins = <
+			/* BT_REG_ON: io without pull (module integrates pd) */
+			IMX8DXL_SPI3_SCK_LSIO_GPIO0_IO13			0x0000061
+		>;
+	};
+
+	eqos_pins: pinctrl-eqos-grp {
+		fsl,pins = <
+			/* MDIO to Switch */
+			/* enet0 mdio pads supplied with 3.3v */
+			/* IMX8DXL_COMP_CTL_GPIO_1V8_3V3_GPIOCT */
+			IMX8DXL_ENET0_MDC_CONN_EQOS_MDC				0x06000020
+			IMX8DXL_ENET0_MDIO_CONN_EQOS_MDIO			0x06000020
+			/* RGMII to Switch */
+			IMX8DXL_ENET1_RGMII_TX_CTL_CONN_EQOS_RGMII_TX_CTL	0x06000020
+			IMX8DXL_ENET1_RGMII_TXC_CONN_EQOS_RGMII_TXC		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD0_CONN_EQOS_RGMII_TXD0		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD1_CONN_EQOS_RGMII_TXD1		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD2_CONN_EQOS_RGMII_TXD2		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD3_CONN_EQOS_RGMII_TXD3		0x06000020
+			IMX8DXL_ENET1_RGMII_RXC_CONN_EQOS_RGMII_RXC		0x06000020
+			IMX8DXL_ENET1_RGMII_RX_CTL_CONN_EQOS_RGMII_RX_CTL	0x06000020
+			IMX8DXL_ENET1_RGMII_RXD0_CONN_EQOS_RGMII_RXD0		0x06000020
+			IMX8DXL_ENET1_RGMII_RXD1_CONN_EQOS_RGMII_RXD1		0x06000020
+			IMX8DXL_ENET1_RGMII_RXD2_CONN_EQOS_RGMII_RXD2		0x06000020
+			IMX8DXL_ENET1_RGMII_RXD3_CONN_EQOS_RGMII_RXD3		0x06000020
+		>;
+	};
+
+	flexcan1_pins: pinctrl-flexcan1-grp {
+		fsl,pins = <
+			IMX8DXL_FLEXCAN0_TX_ADMA_FLEXCAN0_TX			0x00000021
+			IMX8DXL_FLEXCAN0_RX_ADMA_FLEXCAN0_RX			0x00000021
+		>;
+	};
+
+	flexcan2_pins: pinctrl-flexcan2-grp {
+		fsl,pins = <
+			IMX8DXL_FLEXCAN1_TX_ADMA_FLEXCAN1_TX			0x00000021
+			IMX8DXL_FLEXCAN1_RX_ADMA_FLEXCAN1_RX			0x00000021
+		>;
+	};
+
+	lpspi0_pins: pinctrl-lpspi0-grp {
+		fsl,pins = <
+			IMX8DXL_SPI0_SCK_ADMA_SPI0_SCK				0x600004c
+			IMX8DXL_SPI0_SDO_ADMA_SPI0_SDO				0x600004c
+			IMX8DXL_SPI0_SDI_ADMA_SPI0_SDI				0x600004c
+			IMX8DXL_SPI0_CS0_LSIO_GPIO1_IO08			0x0000021
+			IMX8DXL_SPI0_CS1_LSIO_GPIO1_IO07			0x0000021
+		>;
+	};
+
+	lpuart1_pins: pinctrl-lpuart1-grp {
+		fsl,pins = <
+			IMX8DXL_UART1_RX_ADMA_UART1_RX				0x06000020
+			IMX8DXL_UART1_TX_ADMA_UART1_TX				0x06000020
+			IMX8DXL_UART1_CTS_B_ADMA_UART1_CTS_B			0x06000020
+			IMX8DXL_UART1_RTS_B_ADMA_UART1_RTS_B			0x06000020
+		>;
+	};
+
+	modem_pins: pinctrl-lte-grp {
+		fsl,pins = <
+			/* modem RESET_N: io open drain drive 2mA */
+			IMX8DXL_ADC_IN3_LSIO_GPIO1_IO11	0x2000061
+
+			/* modem PWRKEY: io open drain with pull-up, drive 2mA */
+			IMX8DXL_ADC_IN2_LSIO_GPIO1_IO12	0x2000021
+		>;
+	};
+
+	regulator_1v1_pins: pinctrl-regulator-1-1-grp {
+		fsl,pins = <
+			/* SW_PE: io without pull-up */
+			IMX8DXL_USB_SS3_TC2_LSIO_GPIO4_IO05			0x0000061
+		>;
+	};
+
+	regulator_modem_vbat_pins: pinctrl-regulator-modem-vbat-grp {
+		fsl,pins = <
+			/*
+			 * RF_PWR: io without pull-up,
+			 * has either external pull-up (R1117) or pull-down (R1118).
+			 * With pull-up Modem will boot at system power-up,
+			 * with pull-down modem will enter power-down mode once
+			 * vbat is enabled -> toggle pwrkey to boot modem.
+			 * Hence pull-up (R1117) is preferred.
+			 */
+			IMX8DXL_SPI3_SDO_LSIO_GPIO0_IO14			0x0000061
+		>;
+	};
+
+	regulator_usb1_vbus_pins: pinctrl-regulator-usb1-vbus-grp {
+		fsl,pins = <
+			/* regulator enable: open-drain with pull-up & low drive strength */
+			IMX8DXL_SPI3_CS0_LSIO_GPIO0_IO16			0x2000021
+		>;
+	};
+
+	switch_pins: pinctrl-switch-grp {
+		fsl,pins = <
+			/* SW_RSTn: io without pull-up */
+			IMX8DXL_USB_SS3_TC0_LSIO_GPIO4_IO03			0x0000021
+
+			/* SW_CORE_RSTn: io without pull-up */
+			IMX8DXL_USB_SS3_TC1_LSIO_GPIO4_IO04			0x0000021
+
+			/* INT_N: io without pull-up */
+			IMX8DXL_USB_SS3_TC3_LSIO_GPIO4_IO06			0x0000021
+		>;
+	};
+
+	tca6408_u2_int_pins: pinctrl-tca6408-u2-int-grp {
+		fsl,pins = <
+			/* gpio-expander interrupt: io with pull-up */
+			IMX8DXL_MCLK_OUT0_LSIO_GPIO0_IO20			0x0000021
+		>;
+	};
+
+	usdhc3_pins: pinctrl-usdhc3-grp {
+		fsl,pins = <
+			IMX8DXL_ENET0_RGMII_TXC_CONN_USDHC2_CLK			0x06000040
+			IMX8DXL_ENET0_RGMII_TX_CTL_CONN_USDHC2_CMD		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD0_CONN_USDHC2_DATA0		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD1_CONN_USDHC2_DATA1		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD2_CONN_USDHC2_DATA2		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD3_CONN_USDHC2_DATA3		0x00000021
+		>;
+	};
+
+	wifi_pins: pinctrl-wifi-grp {
+		fsl,pins = <
+			/* WL_REG_ON: io without pull (module integrates pd) */
+			IMX8DXL_SPI3_SDI_LSIO_GPIO0_IO15			0x0000061
+		>;
+	};
+};
+
+&lpspi0 {
+	cs-gpios = <&lsio_gpio1 8 GPIO_ACTIVE_LOW>, <&lsio_gpio1 7 GPIO_ACTIVE_LOW>;
+	pinctrl-0 = <&lpspi0_pins>, <&switch_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	ethernet-switch@0 {
+		compatible = "nxp,sja1110a";
+		reg = <0>;
+		reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
+		spi-max-frequency = <4000000>;
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* 100Base-TX on connector J26 */
+			port@1 {
+				reg = <0x1>;
+				phy-handle = <&switch_port1_base_tx_phy>;
+				phy-mode = "internal";
+			};
+
+			/* CPU */
+			port@2 {
+				reg = <0x2>;
+				ethernet = <&eqos>;
+				phy-mode = "rgmii-id";
+				rx-internal-delay-ps = <2000>;
+				tx-internal-delay-ps = <2000>;
+
+				fixed-link {
+					full-duplex;
+					speed = <1000>;
+				};
+			};
+
+			/* sgmii on addon board connector J21 */
+			port@3 {
+				reg = <0x3>;
+				status = "disabled";
+			};
+
+			/* sgmii on addon board connector J21 */
+			port@4 {
+				reg = <0x4>;
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@5 {
+				reg = <0x5>;
+				phy-handle = <&switch_port5_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@6 {
+				reg = <0x6>;
+				phy-handle = <&switch_port6_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@7 {
+				reg = <0x7>;
+				phy-handle = <&switch_port7_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@8 {
+				reg = <0x8>;
+				phy-handle = <&switch_port8_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@9 {
+				reg = <0x9>;
+				phy-handle = <&switch_port9_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100Base-T1 on connector J26 */
+			port@a {
+				reg = <0xa>;
+				phy-handle = <&switch_port10_base_t1_phy>;
+				phy-mode = "internal";
+			};
+		};
+
+		mdios {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			mdio@0 {
+				compatible = "nxp,sja1110-base-t1-mdio";
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port5_base_t1_phy: ethernet-phy@1 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x1>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port6_base_t1_phy: ethernet-phy@2 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x2>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port7_base_t1_phy: ethernet-phy@3 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x3>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port8_base_t1_phy: ethernet-phy@4 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x4>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port9_base_t1_phy: ethernet-phy@5 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x5>;
+					status = "disabled";
+				};
+
+				/* 100Base-T1 on connector J26 */
+				switch_port10_base_t1_phy: ethernet-phy@6 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x6>;
+				};
+			};
+
+			mdio@1 {
+				compatible = "nxp,sja1110-base-tx-mdio";
+				reg = <1>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* 100Base-TX on connector J26 */
+				switch_port1_base_tx_phy: ethernet-phy@1 {
+					reg = <0x1>;
+				};
+			};
+		};
+	};
+};
+
+/* bluetooth */
+&lpuart1 {
+	pinctrl-0 = <&lpuart1_pins>, <&bluetooth_pins>;
+	pinctrl-names = "default";
+	uart-has-rtscts;
+	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm4345c5";
+		/* Murata 1MW module supports max. 3M baud */
+		max-speed = <3000000>;
+		shutdown-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&usbotg1 {
+	vbus-supply = <&vbus1>;
+};
+
+/* cellular modem */
+&usbotg2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	adp-disable;
+	disable-over-current;
+	dr_mode = "host";
+	hnp-disable;
+	pinctrl-0 = <&modem_pins>;
+	pinctrl-names = "default";
+	power-active-high;
+	srp-disable;
+	vbus-supply = <&v_5_0>;
+	status = "okay";
+
+	usb-device@1 {
+		compatible = "usb2c7c,125";
+		reg = <1>;
+		reset-duration-us = <150000>;
+		reset-gpios = <&lsio_gpio1 11 GPIO_ACTIVE_LOW>;
+		vbus-supply = <&v_3_3>;
+		vdd-supply = <&modem_vbat>;
+	};
+};
+
+&usbphy2 {
+	status = "okay";
+};
+
+/* WiFi */
+&usdhc3 {
+	bus-width = <4>;
+	mmc-pwrseq = <&usdhc3_pwrseq>;
+	non-removable;
+	no-sd;
+	pinctrl-0 = <&usdhc3_pins>, <&wifi_pins>;
+	pinctrl-names = "default";
+	vmmc-supply = <&v_3_3>;
+	vqmmc-supply = <&v_1_8>;
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi
new file mode 100644
index 0000000000000..93a0eb4d7f770
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022-2026 Josua Mayer <josua@solid-run.com>
+ */
+
+#include "imx8dxl.dtsi"
+/ {
+	compatible = "solidrun,imx8dxl-sr-som", "fsl,imx8dxl";
+	model = "SolidRun i.MX8DXL SoM";
+
+	aliases {
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		serial0 = &lpuart0;
+		serial2 = &lpuart2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	imx8dxl-cm4 {
+		compatible = "fsl,imx8qxp-cm4";
+		clocks = <&clk_dummy>;
+		mboxes = <&lsio_mu5 0 1 &lsio_mu5 1 1 &lsio_mu5 3 1>;
+		mbox-names = "tx", "rx", "rxdb";
+		memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>,
+				<&vdev1vring0>, <&vdev1vring1>, <&rsc_table>;
+		power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>;
+		fsl,entry-address = <0x34fe0000>;
+		fsl,resource-id = <IMX_SC_R_M4_0_PID0>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&lsio_gpio2 6 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&gnss_pps_pins>;
+		pinctrl-names = "default";
+	};
+
+	v_1_2: regulator-1-2 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v2";
+		pinctrl-0 = <&regulator_1_2_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <1200000>;
+		regulator-min-microvolt = <1200000>;
+		gpio = <&lsio_gpio1 13 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_1_6: regulator-1-6 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v6";
+		pinctrl-0 = <&regulator_1_6_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <1600000>;
+		regulator-min-microvolt = <1600000>;
+		vin-supply = <&v_1_8>;
+		gpio = <&lsio_gpio1 14 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_1_8: regulator-1-8 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v8";
+		regulator-max-microvolt = <1800000>;
+		regulator-min-microvolt = <1800000>;
+	};
+
+	v_1_8_se: regulator-1-8-secure-element {
+		compatible = "regulator-fixed";
+		regulator-name = "1v8-se";
+		pinctrl-0 = <&regulator_1_8_se_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <1800000>;
+		regulator-min-microvolt = <1800000>;
+		vin-supply = <&v_1_8>;
+		gpio = <&lsio_gpio3 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_3_3: regulator-3-3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3v3";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+	};
+
+	reserved-memory {
+		ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		/* global autoconfigured region for contiguous allocations */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x98000000 0 0x14000000>;
+			reusable;
+			size = <0 0x14000000>;
+			linux,cma-default;
+		};
+
+		vdev0vring0: memory0@90000000 {
+			reg = <0 0x90000000 0 0x8000>;
+			no-map;
+		};
+
+		vdev0vring1: memory@90008000 {
+			reg = <0 0x90008000 0 0x8000>;
+			no-map;
+		};
+
+		vdev1vring0: memory@90010000 {
+			reg = <0 0x90010000 0 0x8000>;
+			no-map;
+		};
+
+		vdev1vring1: memory@90018000 {
+			reg = <0 0x90018000 0 0x8000>;
+			no-map;
+		};
+
+		rsc_table: memory-rsc-table@900ff000 {
+			reg = <0 0x900ff000 0 0x1000>;
+			no-map;
+		};
+
+		vdevbuffer: memory-vdevbuffer@90400000 {
+			compatible = "shared-dma-pool";
+			reg = <0 0x90400000 0 0x100000>;
+			no-map;
+		};
+
+		/*
+		 * Memory reserved for optee usage. Please do not use.
+		 * This will be automatically added to dtb if OP-TEE is installed.
+		 * optee@96000000 {
+		 *     reg = <0 0x96000000 0 0x2000000>;
+		 *     no-map;
+		 * };
+		 */
+	};
+
+	memory@80000000 {
+		reg = <0x00000000 0x80000000 0 0x40000000>;
+		device_type = "memory";
+	};
+};
+
+&i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-1 = <&i2c2_gpio_pins>;
+	pinctrl-names = "default", "gpio";
+	scl-gpios = <&lsio_gpio3 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&lsio_gpio3 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	status = "okay";
+};
+
+&i2c3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c3_pins>;
+	pinctrl-1 = <&i2c3_gpio_pins>;
+	pinctrl-names = "default", "gpio";
+	scl-gpios = <&lsio_gpio3 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&lsio_gpio3 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	status = "okay";
+
+	magnetometer@1e {
+		compatible = "st,iis2mdc";
+		reg = <0x1e>;
+		interrupt-parent = <&lsio_gpio2>;
+		interrupts = <10 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-0 = <&magnetometer_pins>;
+		pinctrl-names = "default";
+		st,drdy-int-pin = <1>;
+	};
+
+	/* pressure-sensor@5c */
+
+	inertial-sensor@6b {
+		compatible = "st,ism330dhcx";
+		reg = <0x6b>;
+		interrupt-parent = <&lsio_gpio2>;
+		interrupts = <11 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-0 = <&imu_pins>;
+		pinctrl-names = "default";
+		st,drdy-int-pin = <1>;
+	};
+};
+
+&iomuxc {
+	pinctrl-0 = <&pinctrl_hog>;
+	pinctrl-names = "default";
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			IMX8DXL_COMP_CTL_GPIO_1V8_3V3_GPIORHB_PAD	0x000514a0
+			IMX8DXL_COMP_CTL_GPIO_1V8_3V3_GPIORHK_PAD	0x000014a0
+		>;
+	};
+
+	dsrc_pins: pinctrl-dsrc-grp {
+		fsl,pins = <
+			/* reset: io without pull */
+			IMX8DXL_ADC_IN0_LSIO_GPIO1_IO10			0x0000060
+
+			/*
+			 * boot0: io without pull
+			 * After reset, this pin selects radio boot media:
+			 * - 0: flash spi
+			 * - 1: slave sdio
+			 * Once the firmware boots however, the radio controls
+			 * this pin for flow-control to signal readiness.
+			 */
+			IMX8DXL_ADC_IN1_LSIO_GPIO1_IO09			0x0000060
+		>;
+	};
+
+	gnss_pins: pinctrl-gnss-grp {
+		fsl,pins = <
+			/* gps reset: input with pull-up */
+			IMX8DXL_SNVS_TAMPER_OUT4_LSIO_GPIO2_IO08_IN	0x0000021
+			/* gps interrupt: io without pull-up */
+			IMX8DXL_SNVS_TAMPER_IN0_LSIO_GPIO2_IO09_IN	0x0000061
+		>;
+	};
+
+	gnss_pps_pins: pinctrl-gnss-pps-grp {
+		fsl,pins = <
+			/* gps timepulse: input without pull-up */
+			IMX8DXL_SNVS_TAMPER_OUT2_LSIO_GPIO2_IO06_IN	0x0000061
+		>;
+	};
+
+	i2c2_gpio_pins: pinctrl-i2c2-gpio-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_SCK_LSIO_GPIO3_IO00		0x00000021
+			/* io with pull-up, weak drive, open-drain */
+			IMX8DXL_SPI1_SDO_LSIO_GPIO3_IO01		0x02000021
+		>;
+	};
+
+	i2c2_pins: pinctrl-i2c2-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_SCK_ADMA_I2C2_SDA			0x06000021
+			IMX8DXL_SPI1_SDO_ADMA_I2C2_SCL			0x06000021
+		>;
+	};
+
+	i2c3_gpio_pins: pinctrl-i2c3-gpio-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_CS0_LSIO_GPIO3_IO03		0x00000021
+			/* io with pull-up, weak drive, open-drain */
+			IMX8DXL_SPI1_SDI_LSIO_GPIO3_IO02		0x02000021
+		>;
+	};
+
+	i2c3_pins: pinctrl-i2c3-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_CS0_ADMA_I2C3_SDA			0x06000021
+			IMX8DXL_SPI1_SDI_ADMA_I2C3_SCL			0x06000021
+		>;
+	};
+
+	imu_pins: pinctrl-imu-grp {
+		fsl,pins = <
+			/* interrupt: io with pull-down */
+			IMX8DXL_SNVS_TAMPER_IN2_LSIO_GPIO2_IO11_IN	0x0000041
+		>;
+	};
+
+	lpspi2_pins: pinctrl-lpspi2-grp {
+		fsl,pins = <
+			IMX8DXL_USDHC1_RESET_B_ADMA_SPI2_SCK		0x600004c
+			IMX8DXL_USDHC1_VSELECT_ADMA_SPI2_SDO		0x600004c
+			IMX8DXL_USDHC1_WP_ADMA_SPI2_SDI			0x600004c
+			IMX8DXL_USDHC1_CD_B_LSIO_GPIO4_IO22		0x6000021
+		>;
+	};
+
+	lpuart0_pins: pinctrl-lpuart0-grp {
+		fsl,pins = <
+			IMX8DXL_UART0_RX_ADMA_UART0_RX			0x06000020
+			IMX8DXL_UART0_TX_ADMA_UART0_TX			0x06000020
+		>;
+	};
+
+	lpuart2_pins: pinctrl-lpuart2-grp {
+		fsl,pins = <
+			IMX8DXL_UART2_TX_ADMA_UART2_TX			0x06000020
+			IMX8DXL_UART2_RX_ADMA_UART2_RX			0x06000020
+		>;
+	};
+
+	magnetometer_pins: pinctrl-magnetometer-grp {
+		fsl,pins = <
+			/* interrupt: io with pull-down */
+			IMX8DXL_SNVS_TAMPER_IN1_LSIO_GPIO2_IO10_IN	0x0000041
+		>;
+	};
+
+	regulator_1_2_pins: pinctrl-regulator-1-2-grp {
+		fsl,pins = <
+			/* io without pull-up */
+			/* has etxernal pull-down */
+			IMX8DXL_ADC_IN5_LSIO_GPIO1_IO13			0x0000061
+		>;
+	};
+
+	regulator_1_6_pins: pinctrl-regulator-1-6-grp {
+		fsl,pins = <
+			/* io without pull-up */
+			/* has etxernal pull-down */
+			IMX8DXL_ADC_IN4_LSIO_GPIO1_IO14			0x0000061
+		>;
+	};
+
+	regulator_1_8_se_pins: pinctrl-regulator-1-8-secure-element-grp {
+		fsl,pins = <
+			/* v2x-secure-element power switch: io with pull-down */
+			IMX8DXL_QSPI0B_DATA0_LSIO_GPIO3_IO18		0x0000041
+		>;
+	};
+
+	se_pins: pinctrl-secure-element-grp {
+		fsl,pins = <
+			/* v2x-secure-element reset: io with pull-up */
+			IMX8DXL_QSPI0B_DATA1_LSIO_GPIO3_IO19		0x0000021
+
+			/*
+			 * v2x-secure-element gpio0: io with pull-up
+			 * pulled low by sxf after boot indicating ready for commands
+			 */
+			IMX8DXL_QSPI0B_DATA2_LSIO_GPIO3_IO20		0x0000021
+
+			/* v2x-secure-element gpio1: io with pull-up */
+			IMX8DXL_QSPI0B_DATA3_LSIO_GPIO3_IO21		0x0000021
+		>;
+	};
+
+	usdhc1_pins: pinctrl-usdhc1-grp {
+		fsl,pins = <
+			IMX8DXL_EMMC0_CLK_CONN_EMMC0_CLK		0x06000041
+			IMX8DXL_EMMC0_CMD_CONN_EMMC0_CMD		0x00000021
+			IMX8DXL_EMMC0_DATA0_CONN_EMMC0_DATA0		0x00000021
+			IMX8DXL_EMMC0_DATA1_CONN_EMMC0_DATA1		0x00000021
+			IMX8DXL_EMMC0_DATA2_CONN_EMMC0_DATA2		0x00000021
+			IMX8DXL_EMMC0_DATA3_CONN_EMMC0_DATA3		0x00000021
+			IMX8DXL_EMMC0_DATA4_CONN_EMMC0_DATA4		0x00000021
+			IMX8DXL_EMMC0_DATA5_CONN_EMMC0_DATA5		0x00000021
+			IMX8DXL_EMMC0_DATA6_CONN_EMMC0_DATA6		0x00000021
+			IMX8DXL_EMMC0_DATA7_CONN_EMMC0_DATA7		0x00000021
+			IMX8DXL_EMMC0_STROBE_CONN_EMMC0_STROBE		0x00000041
+			IMX8DXL_EMMC0_RESET_B_CONN_EMMC0_RESET_B	0x00000061
+		>;
+	};
+
+	usdhc2_pins: pinctrl-usdhc2-grp {
+		fsl,pins = <
+			IMX8DXL_ENET0_RGMII_RXC_CONN_USDHC1_CLK		0x06000040
+			IMX8DXL_ENET0_RGMII_RX_CTL_CONN_USDHC1_CMD	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD0_CONN_USDHC1_DATA0	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD1_CONN_USDHC1_DATA1	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD2_CONN_USDHC1_DATA2	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD3_CONN_USDHC1_DATA3	0x00000021
+		>;
+	};
+};
+
+&lpspi2 {
+	cs-gpios = <&lsio_gpio4 22 GPIO_ACTIVE_LOW>;
+	num-cs = <1>;
+	pinctrl-0 = <&lpspi2_pins>, <&se_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+/* console */
+&lpuart0 {
+	pinctrl-0 = <&lpuart0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+/* gnss */
+&lpuart2 {
+	pinctrl-0 = <&lpuart2_pins>, <&gnss_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&lsio_gpio3 {
+	gpio-line-names = "", "", "", "", "", "", "", "",
+			  "", "", "", "", "", "", "", "",
+			  "", "", "", "SXF_RST", "SXF_GPIO0", "SXF_GPIO1", "", "",
+			  "", "", "", "", "", "", "", "";
+};
+
+&lsio_mu5 {
+	status = "okay";
+};
+
+/* OTG port for boot */
+&usbotg1 {
+	adp-disable;
+	disable-over-current;
+	dr_mode = "peripheral";
+	hnp-disable;
+	power-active-high;
+	srp-disable;
+	status = "okay";
+};
+
+&usbphy1 {
+	status = "okay";
+};
+
+/* eMMC */
+&usdhc1 {
+	bus-width = <8>;
+	cap-mmc-hw-reset;
+	non-removable;
+	no-sd;
+	no-sdio;
+	pinctrl-0 = <&usdhc1_pins>;
+	pinctrl-1 = <&usdhc1_pins>;
+	pinctrl-2 = <&usdhc1_pins>;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	vmmc-supply = <&v_3_3>;
+	vqmmc-supply = <&v_1_8>;
+	status = "okay";
+};
+
+/* DSRC Radio */
+&usdhc2 {
+	bus-width = <4>;
+	keep-power-in-suspend;
+	max-frequency = <40000000>;
+	non-removable;
+	no-sd;
+	pinctrl-0 = <&usdhc2_pins>, <&dsrc_pins>;
+	pinctrl-names = "default";
+	vmmc-supply = <&v_3_3>;
+	vqmmc-supply = <&v_1_8>;
+	status = "okay";
+};

-- 
2.51.0



^ permalink raw reply related

* [PATCH v3 1/2] dt-bindings: arm: fsl: Add SolidRun i.MX8DXL SoM and HummingBoard
From: Josua Mayer @ 2026-04-30 12:17 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer,
	Krzysztof Kozlowski
In-Reply-To: <20260430-imx8dxl-sr-som-v3-0-ce2b86cf75bc@solid-run.com>

Add binding for the SolidRun i.MX8DXL based System on Module, and the
reference HummingBoard Telematics.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 0023cd1268075..17cd47e8efce8 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1394,6 +1394,13 @@ properties:
               - fsl,imx8dxl-evk           # i.MX8DXL EVK Board
           - const: fsl,imx8dxl
 
+      - description: SolidRun i.MX8DXL SoM based boards
+        items:
+          - enum:
+              - solidrun,imx8dxl-hummingboard-telematics # SolidRun i.MX8DXL SoM EVK Board
+          - const: solidrun,imx8dxl-sr-som
+          - const: fsl,imx8dxl
+
       - description: i.MX8QXP/i.MX8DX Boards with Toradex Colibri iMX8X Modules
         items:
           - enum:

-- 
2.51.0



^ permalink raw reply related

* Re: [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-30 12:14 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Yazan Shhady, Mikhail Anikin,
	Alexander Dahl, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, Conor Dooley,
	Krzysztof Kozlowski, netdev@vger.kernel.org
In-Reply-To: <20260430120341.4sqmblbt2hqoklsb@skbuf>

Am 30.04.26 um 14:03 schrieb Vladimir Oltean:
> On Thu, Apr 30, 2026 at 11:48:45AM +0000, Josua Mayer wrote:
>>> Also, can you use udev for user
>>> interface naming?
>> Possibly .... I am aware of systemd (udev) based default behaviour
>> for network interface aliases (eth0, eth1, ...).
>>
>> However I have not seen it for dsa switch ports.
> In /etc/udev/rules.d/10-network.rules:
>
> ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p0", NAME="lan0"
> ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p1", NAME="lan1"
> ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p2", NAME="lan2"
> ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p3", NAME="lan3"
> ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p4", NAME="lan4"
> ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p5", NAME="lan5"
>
>> It has been common practice for switch ports to be named lan[0-9]+,
>> and I'd prefer to keep it that way here too.
>> Predictable names are important for users in particular when interfaces
>> are of different types and at different connectors.
>>
>> Re. the T1 ports names I didn't know whether to use "lan" or "trx".
>> For those if "lan" is preferred, I can change them.
> No objection to your naming choice. Just want to point out that we
> encourage DSA users to use the same naming infrastructure as any other
> net device.
Understood.
> The device tree labels mostly come from deeply embedded
> environments where a full udev implementation is missing (like OpenWrt).
> If you don't have that excuse, you can try to leave the labels in the
> device tree out and set up predictable names through an udev rule.
Today I would claim that even OpenWRT has sufficient mechanisms
for interface naming.

The board in question can run a full OS due to sufficient RAM storage.
So I will drop the labels as suggested, for v3.

Note there is one other board using this same ethernet switch, and it specifies all the labels:
arch/arm64/boot/dts/freescale/fsl-lx2160a-bluebox3.dts

^ permalink raw reply

* [PATCH] arm64: dts: mediatek: mt8192-asurada: Move PCIe DMA bounce buffer to host
From: Chen-Yu Tsai @ 2026-04-30 12:07 UTC (permalink / raw)
  To: Matthias Brugger, AngeloGioacchino Del Regno
  Cc: Chen-Yu Tsai, linux-mediatek, devicetree, linux-arm-kernel,
	linux-kernel

The DMA bounce buffer is attached to the PCIe host controller, i.e. all
PCIe DMA transfers should use it.

Move it from the PCIe (WiFi) device node down to the PCIe host
controller node.

Fixes: 0dca9f0b3e63 ("arm64: dts: mediatek: asurada: Enable PCIe and add WiFi")
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
 arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index 217c9bd5e9a1..eebcc4068e28 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -645,6 +645,7 @@ flash@0 {
 &pcie {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie_pins>;
+	memory-region = <&wifi_restricted_dma_region>;
 
 	pcie0: pcie@0,0 {
 		device_type = "pci";
@@ -659,7 +660,6 @@ pcie0: pcie@0,0 {
 		wifi: wifi@0,0 {
 			reg = <0x10000 0 0 0 0x100000>,
 			      <0x10000 0 0x100000 0 0x100000>;
-			memory-region = <&wifi_restricted_dma_region>;
 		};
 	};
 };
-- 
2.54.0.545.g6539524ca2-goog



^ permalink raw reply related

* Re: [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Vladimir Oltean @ 2026-04-30 12:03 UTC (permalink / raw)
  To: Josua Mayer
  Cc: Andrew Lunn, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Yazan Shhady, Mikhail Anikin,
	Alexander Dahl, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, Conor Dooley,
	Krzysztof Kozlowski, netdev@vger.kernel.org
In-Reply-To: <75e338eb-afd2-4e2e-9b93-e9fc36871854@solid-run.com>

On Thu, Apr 30, 2026 at 11:48:45AM +0000, Josua Mayer wrote:
> > Also, can you use udev for user
> > interface naming?
> Possibly .... I am aware of systemd (udev) based default behaviour
> for network interface aliases (eth0, eth1, ...).
> 
> However I have not seen it for dsa switch ports.

In /etc/udev/rules.d/10-network.rules:

ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p0", NAME="lan0"
ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p1", NAME="lan1"
ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p2", NAME="lan2"
ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p3", NAME="lan3"
ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p4", NAME="lan4"
ACTION=="add", SUBSYSTEM=="net", KERNELS=="spi2.0", DRIVERS=="sja1105", ATTR{phys_port_name}=="p5", NAME="lan5"

> 
> It has been common practice for switch ports to be named lan[0-9]+,
> and I'd prefer to keep it that way here too.
> Predictable names are important for users in particular when interfaces
> are of different types and at different connectors.
> 
> Re. the T1 ports names I didn't know whether to use "lan" or "trx".
> For those if "lan" is preferred, I can change them.

No objection to your naming choice. Just want to point out that we
encourage DSA users to use the same naming infrastructure as any other
net device. The device tree labels mostly come from deeply embedded
environments where a full udev implementation is missing (like OpenWrt).
If you don't have that excuse, you can try to leave the labels in the
device tree out and set up predictable names through an udev rule.


^ permalink raw reply

* Re: [PATCH v7 phy-next 17/27] phy: introduce phy_get_max_link_rate() helper for consumers
From: Geert Uytterhoeven @ 2026-04-30 11:59 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: linux-phy, Vinod Koul, Neil Armstrong, dri-devel, freedreno,
	linux-arm-kernel, linux-arm-msm, linux-can, linux-gpio, linux-ide,
	linux-kernel, linux-media, linux-pci, linux-renesas-soc,
	linux-riscv, linux-rockchip, linux-samsung-soc, linux-scsi,
	linux-sunxi, linux-tegra, linux-usb, netdev, spacemit,
	UNGLinuxDriver, Markus Schneider-Pargmann, Andrzej Hajda,
	Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Andy Yan, Marc Kleine-Budde, Vincent Mailhol,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
	Geert Uytterhoeven, Magnus Damm
In-Reply-To: <20260430110652.558622-18-vladimir.oltean@nxp.com>

Hi Vladimir,

On Thu, 30 Apr 2026 at 13:07, Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
> Consumer drivers shouldn't dereference struct phy, not even to get to
> its attributes.
>
> We have phy_get_bus_width() as a precedent for getting the bus_width
> attribute, so let's add phy_get_max_link_rate() and use it in DRM and
> CAN drivers.
>
> In CAN drivers, the transceiver is acquired through devm_phy_optional_get()
> and NULL is given by the API as a non-error case, so the PHY API should
> also tolerate NULL coming back to it. This means we can further simplify
> the call sites that test for the NULL quality of the transceiver.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> Acked-by: Markus Schneider-Pargmann <msp@baylibre.com> # m_can

Thanks for your patch!

>  drivers/net/can/rcar/rcar_canfd.c                   | 3 +--

Acked-by: Geert Uytterhoeven <geert+renesas@glider.be> # rcar_canfd

> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -57,6 +57,7 @@ int phy_notify_disconnect(struct phy *phy, int port);
>  int phy_notify_state(struct phy *phy, union phy_notify state);
>  int phy_get_bus_width(struct phy *phy);
>  void phy_set_bus_width(struct phy *phy, int bus_width);
> +u32 phy_get_max_link_rate(struct phy *phy);

This (and all the existing getters) should take a "const struct phy *".

>  #else
>  static inline struct phy *phy_get(struct device *dev, const char *string)
>  {

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


^ permalink raw reply

* Re: [PATCH] fbdev: Consistently define pci_device_ids using named initializers
From: Helge Deller @ 2026-04-30 11:59 UTC (permalink / raw)
  To: Uwe Kleine-König (The Capable Hub)
  Cc: linux-fbdev, dri-devel, linux-kernel, linux-arm-kernel,
	linux-geode, Markus Schneider-Pargmann
In-Reply-To: <20260430111637.211336-2-u.kleine-koenig@baylibre.com>

On 4/30/26 13:16, Uwe Kleine-König (The Capable Hub) wrote:
> ... and PCI device helpers.
> 
> The various struct pci_device_id arrays were initialized mostly by list
> expressions. This isn't easily readable if you're not into PCI. Using
> named initializers is more explicit and thus easier to parse. Also use
> PCI_DEVICE* helper macros to assign .vendor, .device, .subvendor and
> .subdevice where appropriate and skip explicit assignments of 0 (which
> the compiler takes care of).
> 
> The secret plan is to make struct pci_device_id::driver_data an
> anonymous union (similar to
> https://lore.kernel.org/all/cover.1776579304.git.u.kleine-koenig@baylibre.com/)
> and that requires named initializers. But it's also a nice cleanup on
> its own.
> 
> This change doesn't introduce changes to the compiled pci_device_id
> array. Tested on x86 and arm64.
> 
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> 
>   drivers/video/fbdev/arkfb.c                  |   4 +-
>   drivers/video/fbdev/aty/aty128fb.c           | 143 +++++++------------
>   drivers/video/fbdev/aty/radeon_base.c        |   2 +-
>   drivers/video/fbdev/carminefb.c              |   5 +-
>   drivers/video/fbdev/cirrusfb.c               |   2 +-
>   drivers/video/fbdev/cyber2000fb.c            |  24 ++--
>   drivers/video/fbdev/geode/gx1fb_core.c       |  10 +-
>   drivers/video/fbdev/kyro/fbdev.c             |   5 +-
>   drivers/video/fbdev/matrox/matroxfb_base.c   |  38 ++---
>   drivers/video/fbdev/neofb.c                  |  29 ++--
>   drivers/video/fbdev/nvidia/nvidia.c          |   9 +-
>   drivers/video/fbdev/pm2fb.c                  |  11 +-
>   drivers/video/fbdev/pm3fb.c                  |   5 +-
>   drivers/video/fbdev/pvr2fb.c                 |   5 +-
>   drivers/video/fbdev/riva/fbdev.c             | 128 ++++++-----------
>   drivers/video/fbdev/s3fb.c                   |  32 ++---
>   drivers/video/fbdev/savage/savagefb_driver.c | 140 +++++++++---------
>   drivers/video/fbdev/sis/sis_main.h           |  26 ++--
>   drivers/video/fbdev/tdfxfb.c                 |  21 +--
>   drivers/video/fbdev/tridentfb.c              |  44 +++---
>   drivers/video/fbdev/vt8623fb.c               |   4 +-
>   21 files changed, 292 insertions(+), 395 deletions(-)

applied.

Thanks!
Helge


^ permalink raw reply

* Re: [PATCH v2 0/4] ARM: pxa: attach software nodes to the GPIO controllers
From: Arnd Bergmann @ 2026-04-30 11:57 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Bartosz Golaszewski, Daniel Mack, Haojian Zhuang, Robert Jarzmik,
	Russell King, Dmitry Torokhov, Linus Walleij, linux-arm-kernel,
	open list:GPIO SUBSYSTEM, linux-kernel
In-Reply-To: <CAMRc=MeKn1_pMAyx_bQfMczqRJ1s28s3R9dAVMG5he97R_q4Dw@mail.gmail.com>

On Thu, Apr 30, 2026, at 09:14, Bartosz Golaszewski wrote:
> On Mon, Apr 27, 2026 at 1:01 PM Bartosz Golaszewski <brgl@kernel.org> wrote:
>> On Mon, Apr 27, 2026 at 12:50 PM Arnd Bergmann <arnd@kernel.org> wrote:
>
> Before I address Russell's comment in v2, can you please let me know
> if pxa will be removed in v7.2?

I'll need some more time. Not sure about the schedule, but I don't
expect to remove the board files in 7.2 now, sorry.

      Arnd


^ permalink raw reply

* Re: [PATCH rc v4 1/5] iommu/arm-smmu-v3: Add arm_smmu_kdump_adopt_strtab() for kdump
From: Jason Gunthorpe @ 2026-04-30 11:55 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: will, robin.murphy, kevin.tian, joro, praan, kees, baolu.lu,
	miko.lenczewski, smostafa, linux-arm-kernel, iommu, linux-kernel,
	stable, jamien
In-Reply-To: <afJ6Lu0aZyff5TYZ@Asurada-Nvidia>

On Wed, Apr 29, 2026 at 02:37:50PM -0700, Nicolin Chen wrote:
> On Wed, Apr 29, 2026 at 12:20:49AM -0700, Nicolin Chen wrote:
> 
> > +static int arm_smmu_kdump_adopt_strtab_2lvl(struct arm_smmu_device *smmu,
> > +					    u32 cfg_reg, dma_addr_t dma)
> [...]
> > +	for (i = 0; i < num_l1_ents; i++) {
> > +		u64 l2ptr = le64_to_cpu(cfg->l2.l1tab[i].l2ptr);
> 
> Sashiko pointed out a missing READ_ON here.

??

There is no concurrency at this point?

Jason


^ permalink raw reply

* [PATCH] clk: samsung: exynos850: mark APM I3C clocks as critical
From: Alexey Klimov @ 2026-04-30 11:53 UTC (permalink / raw)
  To: Sam Protsenko, Krzysztof Kozlowski, Sylwester Nawrocki,
	Chanwoo Choi, Alim Akhtar, Michael Turquette, Stephen Boyd
  Cc: Tudor Ambarus, Brian Masney, linux-arm-kernel, linux-samsung-soc,
	linux-clk, linux-kernel

The Exynos850 APM co-processor relies on the I3C bus to communicate with
the PMIC. Currently, there is no dedicated PMIC consumer driver managing
these clocks, so the clock subsystem automatically gates them during the
initialisation. Once gated, any subsequent ACPM communication with APM
results in timeouts.

As a temporary workaround (and let's hope it doesn't become permanent),
mark both `gout_i3c_pclk` and `gout_i3c_sclk` as CLK_IS_CRITICAL ones to
prevent the clock subsystem from disabling them. This makes the ACPM
communication functional. This workaround should be reverted once a
proper ACPM PMIC driver is implemented to manage these clocks.

Cc: Sam Protsenko <semen.protsenko@linaro.org>
Cc: Tudor Ambarus <tudor.ambarus@linaro.org>
Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
---
 drivers/clk/samsung/clk-exynos850.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index eb9c80b60225efa33d85f5f3c284eb8a63a48015..b143a42293f5a154f53a86d4e97e17a3e61164f3 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -686,10 +686,11 @@ static const struct samsung_gate_clock apm_gate_clks[] __initconst = {
 	     CLK_CON_GAT_GOUT_APM_APBIF_RTC_PCLK, 21, 0, 0),
 	GATE(CLK_GOUT_TOP_RTC_PCLK, "gout_top_rtc_pclk", "dout_apm_bus",
 	     CLK_CON_GAT_GOUT_APM_APBIF_TOP_RTC_PCLK, 21, 0, 0),
+	/* TODO: Should be dealt with or enabled in PMIC ACPM driver */
 	GATE(CLK_GOUT_I3C_PCLK, "gout_i3c_pclk", "dout_apm_bus",
-	     CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_PCLK, 21, 0, 0),
+	     CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_PCLK, 21, CLK_IS_CRITICAL, 0),
 	GATE(CLK_GOUT_I3C_SCLK, "gout_i3c_sclk", "mout_apm_i3c",
-	     CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_SCLK, 21, 0, 0),
+	     CLK_CON_GAT_GOUT_APM_I3C_APM_PMIC_I_SCLK, 21, CLK_IS_CRITICAL, 0),
 	GATE(CLK_GOUT_SPEEDY_PCLK, "gout_speedy_pclk", "dout_apm_bus",
 	     CLK_CON_GAT_GOUT_APM_SPEEDY_APM_PCLK, 21, 0, 0),
 	/* TODO: Should be enabled in GPIO driver (or made CLK_IS_CRITICAL) */

---
base-commit: 0787c45ea08a13b5482e701fabc741877cf681f6
change-id: 20260430-exynos850-i3c-criticalclocks-dcabb78bf154

Best regards,
-- 
Alexey Klimov <alexey.klimov@linaro.org>



^ permalink raw reply related

* Re: [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-30 11:48 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Yazan Shhady, Mikhail Anikin,
	Alexander Dahl, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, Conor Dooley,
	Krzysztof Kozlowski, netdev@vger.kernel.org
In-Reply-To: <20260430111924.nvwohy4nexzyiyyl@skbuf>

Am 30.04.26 um 13:19 schrieb Vladimir Oltean:
> On Thu, Apr 30, 2026 at 11:17:36AM +0000, Josua Mayer wrote:
>> Am 09.04.26 um 14:46 schrieb Andrew Lunn:
>>>> +&eqos {
>>>> +	/* delays are added by connected ethernet-switch cpu port */
>>>> +	phy-mode = "rgmii";
>>>> +	pinctrl-0 = <&eqos_pins>;
>>>> +	pinctrl-names = "default";
>>>> +	status = "okay";
>>>> +
>>>> +	fixed-link {
>>>> +		full-duplex;
>>>> +		speed = <1000>;
>>>> +	};
>>>> +};
>>>> +	ethernet-switch@0 {
>>>> +		compatible = "nxp,sja1110a";
>>>> +		reg = <0>;
>>>> +		reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
>>>> +		spi-max-frequency = <4000000>;
>>>> +
>>>> +		ethernet-ports {
>>>> +			#address-cells = <1>;
>>>> +			#size-cells = <0>;
>>>> +
>>>> +			/* 100Base-TX on connector J26 */
>>>> +			port@1 {
>>>> +				reg = <0x1>;
>>>> +				label = "lan1";
>>>> +				phy-handle = <&switch_port1_base_tx_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "okay";
>> dropping unnecessary status okay for v3
>>>> +			};
>>>> +
>>>> +			/* CPU */
>>>> +			port@2 {
>>>> +				reg = <0x2>;
>>>> +				ethernet = <&eqos>;
>>>> +				label = "cpu";
> Please drop unused label = "cpu".
Okay.
> Also, can you use udev for user
> interface naming?
Possibly .... I am aware of systemd (udev) based default behaviour
for network interface aliases (eth0, eth1, ...).

However I have not seen it for dsa switch ports.

It has been common practice for switch ports to be named lan[0-9]+,
and I'd prefer to keep it that way here too.
Predictable names are important for users in particular when interfaces
are of different types and at different connectors.

Re. the T1 ports names I didn't know whether to use "lan" or "trx".
For those if "lan" is preferred, I can change them.

>
>>>> +				phy-mode = "rgmii-id";
>>>> +				rx-internal-delay-ps = <2000>;
>>>> +				tx-internal-delay-ps = <2000>;
>>>> +				status = "okay";
>> dropping unnecessary status okay for v3
>>>> +
>>>> +				fixed-link {
>>>> +					full-duplex;
>>>> +					speed = <1000>;
>>>> +				};
>>>> +			};
>>>> +
>>>> +			/* sgmii on addon board connector J21 */
>>>> +			port@3 {
>>>> +				reg = <0x3>;
>>>> +				label = "lan3";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* sgmii on addon board connector J21 */
>>>> +			port@4 {
>>>> +				reg = <0x4>;
>>>> +				label = "lan4";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* 100base-t1 on addon board connector J21 */
>>>> +			port@5 {
>>>> +				reg = <0x5>;
>>>> +				label = "trx1";
>>>> +				phy-handle = <&switch_port5_base_t1_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* 100base-t1 on addon board connector J21 */
>>>> +			port@6 {
>>>> +				reg = <0x6>;
>>>> +				label = "trx2";
>>>> +				phy-handle = <&switch_port6_base_t1_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* 100base-t1 on addon board connector J21 */
>>>> +			port@7 {
>>>> +				reg = <0x7>;
>>>> +				label = "trx3";
>>>> +				phy-handle = <&switch_port7_base_t1_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* 100base-t1 on addon board connector J21 */
>>>> +			port@8 {
>>>> +				reg = <0x8>;
>>>> +				label = "trx4";
>>>> +				phy-handle = <&switch_port8_base_t1_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* 100base-t1 on addon board connector J21 */
>>>> +			port@9 {
>>>> +				reg = <0x9>;
>>>> +				label = "trx5";
>>>> +				phy-handle = <&switch_port9_base_t1_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "disabled";
>>>> +			};
>>>> +
>>>> +			/* 100Base-T1 on connector J26 */
>>>> +			port@a {
>>>> +				reg = <0xa>;
>>>> +				label = "trx6";
>>>> +				phy-handle = <&switch_port10_base_t1_phy>;
>>>> +				phy-mode = "internal";
>>>> +				status = "okay";
>> dropping unnecessary status okay for v3
>>>> +			};
>>>> +		};
>>>> +
>>>> +		mdios {
>>>> +			#address-cells = <1>;
>>>> +			#size-cells = <0>;
>>>> +
>>>> +			mdio@0 {
>>>> +				compatible = "nxp,sja1110-base-t1-mdio";
>>>> +				reg = <0>;
>>>> +				#address-cells = <1>;
>>>> +				#size-cells = <0>;
>>>> +
>>>> +				/* 100base-t1 on addon board connector J21 */
>>>> +				switch_port5_base_t1_phy: ethernet-phy@1 {
>>>> +					compatible = "ethernet-phy-ieee802.3-c45";
>>>> +					reg = <0x1>;
>>>> +					status = "disabled";
>>>> +				};
>>>> +
>>>> +				/* 100base-t1 on addon board connector J21 */
>>>> +				switch_port6_base_t1_phy: ethernet-phy@2 {
>>>> +					compatible = "ethernet-phy-ieee802.3-c45";
>>>> +					reg = <0x2>;
>>>> +					status = "disabled";
>>>> +				};
>>>> +
>>>> +				/* 100base-t1 on addon board connector J21 */
>>>> +				switch_port7_base_t1_phy: ethernet-phy@3 {
>>>> +					compatible = "ethernet-phy-ieee802.3-c45";
>>>> +					reg = <0x3>;
>>>> +					status = "disabled";
>>>> +				};
>>>> +
>>>> +				/* 100base-t1 on addon board connector J21 */
>>>> +				switch_port8_base_t1_phy: ethernet-phy@4 {
>>>> +					compatible = "ethernet-phy-ieee802.3-c45";
>>>> +					reg = <0x4>;
>>>> +					status = "disabled";
>>>> +				};
>>>> +
>>>> +				/* 100base-t1 on addon board connector J21 */
>>>> +				switch_port9_base_t1_phy: ethernet-phy@5 {
>>>> +					compatible = "ethernet-phy-ieee802.3-c45";
>>>> +					reg = <0x5>;
>>>> +					status = "disabled";
>>>> +				};
>>>> +
>>>> +				/* 100Base-T1 on connector J26 */
>>>> +				switch_port10_base_t1_phy: ethernet-phy@6 {
>>>> +					compatible = "ethernet-phy-ieee802.3-c45";
>>>> +					reg = <0x6>;
>>>> +				};
>>>> +			};
>>>> +
>>>> +			mdio@1 {
>>>> +				compatible = "nxp,sja1110-base-tx-mdio";
>>>> +				reg = <1>;
>>>> +				#address-cells = <1>;
>>>> +				#size-cells = <0>;
>>>> +
>>>> +				/* 100Base-TX on connector J26 */
>>>> +				switch_port1_base_tx_phy: ethernet-phy@1 {
>>>> +					reg = <0x1>;
>>>> +				};
>>>> +			};
>>> For these nodes only:
>>>
>>> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
>>>
>>>     Andrew
>> Thanks!
>>
>> I don't know how to keep this partial review for v3, so I will send it without.

^ permalink raw reply

* Re: [PATCH v7 2/3] dt-bindings: hwmon: emc2305: Add fan-shutdown-percent property
From: Florin Leotescu @ 2026-04-30 12:02 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Shych, linux-hwmon, devicetree, linux-kernel,
	daniel.baluta, viorel.suman, linux-arm-kernel, imx, festevam,
	Florin Leotescu
In-Reply-To: <20260429-shiftless-docile-e57509e967c4@spud>

On Wed, Apr 29, 2026 at 07:18:04PM +0100, Conor Dooley wrote:
> On Wed, Apr 29, 2026 at 09:59:54AM +0300, florin.leotescu@oss.nxp.com wrote:
> > From: Florin Leotescu <florin.leotescu@nxp.com>
> > 
> > The EMC2305 fan controller supports multiple independent PWM fan
> > outputs. Some systems require fans to enter a defined safe state
> > during system shutdown or reboot handoff, until firmware or the next
> > boot stage reconfigures the controller.
> > 
> > Add an optional "fan-shutdown-percent" property to fan child nodes
> > allowing the PWM duty cycle applied during shutdown to be configured
> > per fan output.
> > 
> > Signed-off-by: Florin Leotescu <florin.leotescu@nxp.com>
> 
> Why didn't you pick up my tag from here:
> https://lore.kernel.org/all/20260407-slang-scoff-795164352c62@spud/
>

Apologies, I missed your Acked-by tag when preparing the series.
I will include it in the next revision.

> > ---
> >  .../devicetree/bindings/hwmon/microchip,emc2305.yaml      | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > index d3f06ebc19fa..8c2548539d7f 100644
> > --- a/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > +++ b/Documentation/devicetree/bindings/hwmon/microchip,emc2305.yaml
> > @@ -54,6 +54,12 @@ patternProperties:
> >            The fan number used to determine the associated PWM channel.
> >          maxItems: 1
> >  
> > +      fan-shutdown-percent:
> > +        description:
> > +          PWM duty cycle in percent applied to the fan during shutdown.
> > +        minimum: 0
> > +        maximum: 100
> > +
> >      required:
> >        - reg
> >  
> > @@ -80,12 +86,14 @@ examples:
> >              fan@0 {
> >                  reg = <0x0>;
> >                  pwms = <&fan_controller 26000 PWM_POLARITY_INVERTED 1>;
> > +                fan-shutdown-percent = <100>;
> >                  #cooling-cells = <2>;
> >              };
> >  
> >              fan@1 {
> >                  reg = <0x1>;
> >                  pwms = <&fan_controller 26000 0 1>;
> > +                fan-shutdown-percent = <50>;
> >                  #cooling-cells = <2>;
> >              };
> >  
> > -- 
> > 2.34.1
> > 




^ permalink raw reply

* [PATCH v1] arm64: dts: cix: Add SCMI performance domains for CPUFreq on Sky1
From: Devin Li @ 2026-04-30 11:35 UTC (permalink / raw)
  To: peter.chen, fugang.duan, robh, krzk+dt, conor+dt,
	cix-kernel-upstream
  Cc: linux-arm-kernel, devicetree, linux-kernel, guoyin.chen,
	robin.wang, hong.guo, Devin.Li

From: "devin.li" <Devin.Li@cixtech.com>

Add SCMI Protocol 13 (Performance) node under ap_to_pm_scmi with
domains.

Define SKY1_PERF_* macros in sky1-power.h for all performance domain
IDs (CPU L/B0/B1/M0/M1, GPU, DSU, NPU, VPU, CI700, NI700), and
wire each CPU node to its corresponding performance domain using
power-domains and power-domain-names properties.

Signed-off-by: Devin Li <Devin.Li@cixtech.com>
---
 arch/arm64/boot/dts/cix/sky1-power.h | 13 +++++++++++++
 arch/arm64/boot/dts/cix/sky1.dtsi    | 29 ++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/arch/arm64/boot/dts/cix/sky1-power.h b/arch/arm64/boot/dts/cix/sky1-power.h
index 53f4a3af36b3..144567579b71 100644
--- a/arch/arm64/boot/dts/cix/sky1-power.h
+++ b/arch/arm64/boot/dts/cix/sky1-power.h
@@ -30,4 +30,17 @@
 #define SKY1_PD_ISP0		20
 #define SKY1_PD_GPU		21
 
+#define SKY1_PERF_GPU_CORE	0
+#define SKY1_PERF_GPU_TOP	1
+#define SKY1_PERF_CPU_L     2
+#define SKY1_PERF_CPU_B0	3
+#define SKY1_PERF_CPU_B1	4
+#define SKY1_PERF_CPU_M0	5
+#define SKY1_PERF_CPU_M1	6
+#define SKY1_PERF_DSU	    7
+#define SKY1_PERF_NPU	    8
+#define SKY1_PERF_VPU	    9
+#define SKY1_PERF_CI700	    10
+#define SKY1_PERF_NI700	    11
+
 #endif
diff --git a/arch/arm64/boot/dts/cix/sky1.dtsi b/arch/arm64/boot/dts/cix/sky1.dtsi
index 0611098b5f05..a77c52296ebd 100644
--- a/arch/arm64/boot/dts/cix/sky1.dtsi
+++ b/arch/arm64/boot/dts/cix/sky1.dtsi
@@ -22,6 +22,8 @@ cpu0: cpu@0 {
 			enable-method = "psci";
 			reg = <0x0 0x0>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_L>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <403>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
@@ -31,6 +33,8 @@ cpu1: cpu@100 {
 			enable-method = "psci";
 			reg = <0x0 0x100>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_L>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <403>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
@@ -40,6 +44,8 @@ cpu2: cpu@200 {
 			enable-method = "psci";
 			reg = <0x0 0x200>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_L>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <403>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
@@ -49,6 +55,8 @@ cpu3: cpu@300 {
 			enable-method = "psci";
 			reg = <0x0 0x300>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_L>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <403>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
@@ -58,6 +66,8 @@ cpu4: cpu@400 {
 			enable-method = "psci";
 			reg = <0x0 0x400>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_M0>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -67,6 +77,8 @@ cpu5: cpu@500 {
 			enable-method = "psci";
 			reg = <0x0 0x500>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_M0>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -76,6 +88,8 @@ cpu6: cpu@600 {
 			enable-method = "psci";
 			reg = <0x0 0x600>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_M1>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -85,6 +99,8 @@ cpu7: cpu@700 {
 			enable-method = "psci";
 			reg = <0x0 0x700>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_M1>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -94,6 +110,8 @@ cpu8: cpu@800 {
 			enable-method = "psci";
 			reg = <0x0 0x800>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_B0>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -103,6 +121,8 @@ cpu9: cpu@900 {
 			enable-method = "psci";
 			reg = <0x0 0x900>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_B0>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -112,6 +132,8 @@ cpu10: cpu@a00 {
 			enable-method = "psci";
 			reg = <0x0 0xa00>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_B1>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -121,6 +143,8 @@ cpu11: cpu@b00 {
 			enable-method = "psci";
 			reg = <0x0 0xb00>;
 			device_type = "cpu";
+			power-domains = <&scmi_dvfs SKY1_PERF_CPU_B1>;
+			power-domain-names = "perf";
 			capacity-dmips-mhz = <1024>;
 			cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_0>;
 		};
@@ -205,6 +229,11 @@ ap_to_pm_scmi: scmi {
 			#address-cells = <1>;
 			#size-cells = <0>;
 
+			scmi_dvfs: protocol@13 {
+				reg = <0x13>;
+				#power-domain-cells = <1>;
+			};
+
 			scmi_clk: protocol@14 {
 				reg = <0x14>;
 				#clock-cells = <1>;
-- 
2.49.0



^ permalink raw reply related

* Re: [PATCH v2 1/4] gpio: Remove "default y" in Kconfig
From: Krzysztof Kozlowski @ 2026-04-30 11:24 UTC (permalink / raw)
  To: Yu-Chun Lin, linusw, brgl, robh, krzk+dt, conor+dt, afaerber,
	tychang
  Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
	linux-realtek-soc, cy.huang, stanley_chang, james.tai
In-Reply-To: <6ff75de9-6d5f-4d4a-bb19-1c06d0aa8d3a@kernel.org>

On 30/04/2026 13:23, Krzysztof Kozlowski wrote:
> On 08/04/2026 04:52, Yu-Chun Lin wrote:
>> Remove the default y to avoid bloating the build for non-Realtek platforms
>> when COMPILE_TEST is enable on other platforms.
>>
> 
> Why isn't this driver important for Realtek SoC? This should be
> explained, otherwise proper fix is default for ARCH_REALTEK.

And you were kind of asked for it at v1...

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 1/4] gpio: Remove "default y" in Kconfig
From: Krzysztof Kozlowski @ 2026-04-30 11:23 UTC (permalink / raw)
  To: Yu-Chun Lin, linusw, brgl, robh, krzk+dt, conor+dt, afaerber,
	tychang
  Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
	linux-realtek-soc, cy.huang, stanley_chang, james.tai
In-Reply-To: <20260408025243.1155482-2-eleanor.lin@realtek.com>

On 08/04/2026 04:52, Yu-Chun Lin wrote:
> Remove the default y to avoid bloating the build for non-Realtek platforms
> when COMPILE_TEST is enable on other platforms.
> 

Why isn't this driver important for Realtek SoC? This should be
explained, otherwise proper fix is default for ARCH_REALTEK.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 3/4] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
From: Michael Walle @ 2026-04-30 11:20 UTC (permalink / raw)
  To: Yu-Chun Lin [林祐君], Linus Walleij
  Cc: Bartosz Golaszewski, linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰], robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, afaerber@suse.com,
	TY_Chang[張子逸]
In-Reply-To: <b73f34ec55984a33b0172e2ac3a28e04@realtek.com>

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

Hi,

On Thu Apr 30, 2026 at 11:58 AM CEST, Yu-Chun Lin [林祐君] wrote:
>> >> 3. Hardware Debounce: We also need to support hardware debounce settings per pin,
>> >> which requires custom configuration via set_config mapped to these specific per-pin
>> >> registers.
>> >
>> > Just add a version of an optional .set_config() call to gpio-regmap.c
>> > to handle this using .reg_mask_xlate() per above and add a new
>> > GPIO_REGMAP_CONFIG_OP to the above enum, problem solved.
>> >
>> > If it seems too hard I can write patch 1 & 2 adding this infrastructure
>> > but I bet you can easily see what can be done with gpio-regmap.c
>> > here provided Michael W approves the idea.
>> >
>
> Our .set_config requires mapping specific debounce time values to
> hardware-specific enums and applying a Write-Enable bit.
>
> Would it be better to allow drivers to assign a custom '.set_config' callback
> directly within 'struct gpio_regmap_config'?

Yeah, I don't think there will be much code sharing of
code/functionality for the .set_config callback. A custom
.set_config was proposed many times in the past.

> Additionally, I didn't mention this in my previous email. we also need to
> implement GPIO interrupts. Our hardware design does not fit well with
> 'regmap_irq_chip'. Therefore, I am planning to create our own 'irqdomain' and
> 'irqchip' ops to handle our cascaded interrupts.
>
> Because of this custom IRQ implementation, I would need to use 'readl()/writel()'
> for the IRQ callbacks in the rtd1625 GPIO driver instead of the regmap APIs.
> Do you have any suggestions on how to handle this gracefully while keeping it
> aligned with the regmap infrastructure?

Why can't the MMIO regmap be used for that?

-michael

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

^ permalink raw reply

* Re: [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Vladimir Oltean @ 2026-04-30 11:19 UTC (permalink / raw)
  To: Josua Mayer
  Cc: Andrew Lunn, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Yazan Shhady, Mikhail Anikin,
	Alexander Dahl, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, Conor Dooley,
	Krzysztof Kozlowski, netdev@vger.kernel.org
In-Reply-To: <bd2e73c5-2e61-4ea1-ab3b-42a6573b31f8@solid-run.com>

On Thu, Apr 30, 2026 at 11:17:36AM +0000, Josua Mayer wrote:
> Am 09.04.26 um 14:46 schrieb Andrew Lunn:
> >> +&eqos {
> >> +	/* delays are added by connected ethernet-switch cpu port */
> >> +	phy-mode = "rgmii";
> >> +	pinctrl-0 = <&eqos_pins>;
> >> +	pinctrl-names = "default";
> >> +	status = "okay";
> >> +
> >> +	fixed-link {
> >> +		full-duplex;
> >> +		speed = <1000>;
> >> +	};
> >> +};
> >
> >> +	ethernet-switch@0 {
> >> +		compatible = "nxp,sja1110a";
> >> +		reg = <0>;
> >> +		reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
> >> +		spi-max-frequency = <4000000>;
> >> +
> >> +		ethernet-ports {
> >> +			#address-cells = <1>;
> >> +			#size-cells = <0>;
> >> +
> >> +			/* 100Base-TX on connector J26 */
> >> +			port@1 {
> >> +				reg = <0x1>;
> >> +				label = "lan1";
> >> +				phy-handle = <&switch_port1_base_tx_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "okay";
> dropping unnecessary status okay for v3
> >> +			};
> >> +
> >> +			/* CPU */
> >> +			port@2 {
> >> +				reg = <0x2>;
> >> +				ethernet = <&eqos>;
> >> +				label = "cpu";

Please drop unused label = "cpu". Also, can you use udev for user
interface naming?

> >> +				phy-mode = "rgmii-id";
> >> +				rx-internal-delay-ps = <2000>;
> >> +				tx-internal-delay-ps = <2000>;
> >> +				status = "okay";
> dropping unnecessary status okay for v3
> >> +
> >> +				fixed-link {
> >> +					full-duplex;
> >> +					speed = <1000>;
> >> +				};
> >> +			};
> >> +
> >> +			/* sgmii on addon board connector J21 */
> >> +			port@3 {
> >> +				reg = <0x3>;
> >> +				label = "lan3";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* sgmii on addon board connector J21 */
> >> +			port@4 {
> >> +				reg = <0x4>;
> >> +				label = "lan4";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* 100base-t1 on addon board connector J21 */
> >> +			port@5 {
> >> +				reg = <0x5>;
> >> +				label = "trx1";
> >> +				phy-handle = <&switch_port5_base_t1_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* 100base-t1 on addon board connector J21 */
> >> +			port@6 {
> >> +				reg = <0x6>;
> >> +				label = "trx2";
> >> +				phy-handle = <&switch_port6_base_t1_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* 100base-t1 on addon board connector J21 */
> >> +			port@7 {
> >> +				reg = <0x7>;
> >> +				label = "trx3";
> >> +				phy-handle = <&switch_port7_base_t1_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* 100base-t1 on addon board connector J21 */
> >> +			port@8 {
> >> +				reg = <0x8>;
> >> +				label = "trx4";
> >> +				phy-handle = <&switch_port8_base_t1_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* 100base-t1 on addon board connector J21 */
> >> +			port@9 {
> >> +				reg = <0x9>;
> >> +				label = "trx5";
> >> +				phy-handle = <&switch_port9_base_t1_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "disabled";
> >> +			};
> >> +
> >> +			/* 100Base-T1 on connector J26 */
> >> +			port@a {
> >> +				reg = <0xa>;
> >> +				label = "trx6";
> >> +				phy-handle = <&switch_port10_base_t1_phy>;
> >> +				phy-mode = "internal";
> >> +				status = "okay";
> dropping unnecessary status okay for v3
> >> +			};
> >> +		};
> >> +
> >> +		mdios {
> >> +			#address-cells = <1>;
> >> +			#size-cells = <0>;
> >> +
> >> +			mdio@0 {
> >> +				compatible = "nxp,sja1110-base-t1-mdio";
> >> +				reg = <0>;
> >> +				#address-cells = <1>;
> >> +				#size-cells = <0>;
> >> +
> >> +				/* 100base-t1 on addon board connector J21 */
> >> +				switch_port5_base_t1_phy: ethernet-phy@1 {
> >> +					compatible = "ethernet-phy-ieee802.3-c45";
> >> +					reg = <0x1>;
> >> +					status = "disabled";
> >> +				};
> >> +
> >> +				/* 100base-t1 on addon board connector J21 */
> >> +				switch_port6_base_t1_phy: ethernet-phy@2 {
> >> +					compatible = "ethernet-phy-ieee802.3-c45";
> >> +					reg = <0x2>;
> >> +					status = "disabled";
> >> +				};
> >> +
> >> +				/* 100base-t1 on addon board connector J21 */
> >> +				switch_port7_base_t1_phy: ethernet-phy@3 {
> >> +					compatible = "ethernet-phy-ieee802.3-c45";
> >> +					reg = <0x3>;
> >> +					status = "disabled";
> >> +				};
> >> +
> >> +				/* 100base-t1 on addon board connector J21 */
> >> +				switch_port8_base_t1_phy: ethernet-phy@4 {
> >> +					compatible = "ethernet-phy-ieee802.3-c45";
> >> +					reg = <0x4>;
> >> +					status = "disabled";
> >> +				};
> >> +
> >> +				/* 100base-t1 on addon board connector J21 */
> >> +				switch_port9_base_t1_phy: ethernet-phy@5 {
> >> +					compatible = "ethernet-phy-ieee802.3-c45";
> >> +					reg = <0x5>;
> >> +					status = "disabled";
> >> +				};
> >> +
> >> +				/* 100Base-T1 on connector J26 */
> >> +				switch_port10_base_t1_phy: ethernet-phy@6 {
> >> +					compatible = "ethernet-phy-ieee802.3-c45";
> >> +					reg = <0x6>;
> >> +				};
> >> +			};
> >> +
> >> +			mdio@1 {
> >> +				compatible = "nxp,sja1110-base-tx-mdio";
> >> +				reg = <1>;
> >> +				#address-cells = <1>;
> >> +				#size-cells = <0>;
> >> +
> >> +				/* 100Base-TX on connector J26 */
> >> +				switch_port1_base_tx_phy: ethernet-phy@1 {
> >> +					reg = <0x1>;
> >> +				};
> >> +			};
> > For these nodes only:
> >
> > Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> >
> >     Andrew
> 
> Thanks!
> 
> I don't know how to keep this partial review for v3, so I will send it without.


^ permalink raw reply

* Re: [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-30 11:17 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Yazan Shhady, Mikhail Anikin, Alexander Dahl,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	Vladimir Oltean, Conor Dooley, Krzysztof Kozlowski,
	netdev@vger.kernel.org
In-Reply-To: <8efbafe3-0a8a-4005-960c-e8fe62cee719@lunn.ch>

Am 09.04.26 um 14:46 schrieb Andrew Lunn:
>> +&eqos {
>> +	/* delays are added by connected ethernet-switch cpu port */
>> +	phy-mode = "rgmii";
>> +	pinctrl-0 = <&eqos_pins>;
>> +	pinctrl-names = "default";
>> +	status = "okay";
>> +
>> +	fixed-link {
>> +		full-duplex;
>> +		speed = <1000>;
>> +	};
>> +};
>
>> +	ethernet-switch@0 {
>> +		compatible = "nxp,sja1110a";
>> +		reg = <0>;
>> +		reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
>> +		spi-max-frequency = <4000000>;
>> +
>> +		ethernet-ports {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +
>> +			/* 100Base-TX on connector J26 */
>> +			port@1 {
>> +				reg = <0x1>;
>> +				label = "lan1";
>> +				phy-handle = <&switch_port1_base_tx_phy>;
>> +				phy-mode = "internal";
>> +				status = "okay";
dropping unnecessary status okay for v3
>> +			};
>> +
>> +			/* CPU */
>> +			port@2 {
>> +				reg = <0x2>;
>> +				ethernet = <&eqos>;
>> +				label = "cpu";
>> +				phy-mode = "rgmii-id";
>> +				rx-internal-delay-ps = <2000>;
>> +				tx-internal-delay-ps = <2000>;
>> +				status = "okay";
dropping unnecessary status okay for v3
>> +
>> +				fixed-link {
>> +					full-duplex;
>> +					speed = <1000>;
>> +				};
>> +			};
>> +
>> +			/* sgmii on addon board connector J21 */
>> +			port@3 {
>> +				reg = <0x3>;
>> +				label = "lan3";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* sgmii on addon board connector J21 */
>> +			port@4 {
>> +				reg = <0x4>;
>> +				label = "lan4";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* 100base-t1 on addon board connector J21 */
>> +			port@5 {
>> +				reg = <0x5>;
>> +				label = "trx1";
>> +				phy-handle = <&switch_port5_base_t1_phy>;
>> +				phy-mode = "internal";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* 100base-t1 on addon board connector J21 */
>> +			port@6 {
>> +				reg = <0x6>;
>> +				label = "trx2";
>> +				phy-handle = <&switch_port6_base_t1_phy>;
>> +				phy-mode = "internal";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* 100base-t1 on addon board connector J21 */
>> +			port@7 {
>> +				reg = <0x7>;
>> +				label = "trx3";
>> +				phy-handle = <&switch_port7_base_t1_phy>;
>> +				phy-mode = "internal";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* 100base-t1 on addon board connector J21 */
>> +			port@8 {
>> +				reg = <0x8>;
>> +				label = "trx4";
>> +				phy-handle = <&switch_port8_base_t1_phy>;
>> +				phy-mode = "internal";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* 100base-t1 on addon board connector J21 */
>> +			port@9 {
>> +				reg = <0x9>;
>> +				label = "trx5";
>> +				phy-handle = <&switch_port9_base_t1_phy>;
>> +				phy-mode = "internal";
>> +				status = "disabled";
>> +			};
>> +
>> +			/* 100Base-T1 on connector J26 */
>> +			port@a {
>> +				reg = <0xa>;
>> +				label = "trx6";
>> +				phy-handle = <&switch_port10_base_t1_phy>;
>> +				phy-mode = "internal";
>> +				status = "okay";
dropping unnecessary status okay for v3
>> +			};
>> +		};
>> +
>> +		mdios {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +
>> +			mdio@0 {
>> +				compatible = "nxp,sja1110-base-t1-mdio";
>> +				reg = <0>;
>> +				#address-cells = <1>;
>> +				#size-cells = <0>;
>> +
>> +				/* 100base-t1 on addon board connector J21 */
>> +				switch_port5_base_t1_phy: ethernet-phy@1 {
>> +					compatible = "ethernet-phy-ieee802.3-c45";
>> +					reg = <0x1>;
>> +					status = "disabled";
>> +				};
>> +
>> +				/* 100base-t1 on addon board connector J21 */
>> +				switch_port6_base_t1_phy: ethernet-phy@2 {
>> +					compatible = "ethernet-phy-ieee802.3-c45";
>> +					reg = <0x2>;
>> +					status = "disabled";
>> +				};
>> +
>> +				/* 100base-t1 on addon board connector J21 */
>> +				switch_port7_base_t1_phy: ethernet-phy@3 {
>> +					compatible = "ethernet-phy-ieee802.3-c45";
>> +					reg = <0x3>;
>> +					status = "disabled";
>> +				};
>> +
>> +				/* 100base-t1 on addon board connector J21 */
>> +				switch_port8_base_t1_phy: ethernet-phy@4 {
>> +					compatible = "ethernet-phy-ieee802.3-c45";
>> +					reg = <0x4>;
>> +					status = "disabled";
>> +				};
>> +
>> +				/* 100base-t1 on addon board connector J21 */
>> +				switch_port9_base_t1_phy: ethernet-phy@5 {
>> +					compatible = "ethernet-phy-ieee802.3-c45";
>> +					reg = <0x5>;
>> +					status = "disabled";
>> +				};
>> +
>> +				/* 100Base-T1 on connector J26 */
>> +				switch_port10_base_t1_phy: ethernet-phy@6 {
>> +					compatible = "ethernet-phy-ieee802.3-c45";
>> +					reg = <0x6>;
>> +				};
>> +			};
>> +
>> +			mdio@1 {
>> +				compatible = "nxp,sja1110-base-tx-mdio";
>> +				reg = <1>;
>> +				#address-cells = <1>;
>> +				#size-cells = <0>;
>> +
>> +				/* 100Base-TX on connector J26 */
>> +				switch_port1_base_tx_phy: ethernet-phy@1 {
>> +					reg = <0x1>;
>> +				};
>> +			};
> For these nodes only:
>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
>
>     Andrew

Thanks!

I don't know how to keep this partial review for v3, so I will send it without.

^ permalink raw reply

* [PATCH net-next v5 2/2] net: ti: icssg-prueth: Add ethtool ops for Frame Preemption MAC Merge
From: Meghana Malladi @ 2026-04-30 11:17 UTC (permalink / raw)
  To: vadim.fedorenko, haokexin, jacob.e.keller, horms, m-malladi, arnd,
	parvathi, afd, basharath, vladimir.oltean, rogerq, danishanwar,
	pabeni, kuba, edumazet, davem, andrew+netdev
  Cc: linux-arm-kernel, netdev, linux-kernel, srk, Vignesh Raghavendra
In-Reply-To: <20260430111723.497113-1-m-malladi@ti.com>

From: MD Danish Anwar <danishanwar@ti.com>

Add driver support for viewing and changing the MAC Merge sublayer
parameters via ethtool ops: .set_mm(), .get_mm() and .get_mm_stats().

The minimum size of non-final mPacket fragments supported by the firmware
without leading errors is 64 Bytes (including FCS). Verify time bounded to
1-128 ms per 802.3-2018 clause 30.14.1.6. Add a check to ensure
user passed tx_min_frag_size argument via ethtool, honors this.
Add pa stats registers to check statistics for preemption, which can be
dumped using ethtool ops.

Fix emac_get_stat_by_name() to return u64 instead of int and return 0 on
error instead of -EINVAL. This prevents invalid stat lookups from corrupting
output stats with signed error codes cast to u64. Error conditions are still
logged via netdev_err().

Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Signed-off-by: Meghana Malladi <m-malladi@ti.com>
---

Changes from v4(v5-v4):
- Fix the naming conventiion for icssg_qos_frag_size_min_to_add()
- Change the logic to include FCS while validating and accepting
  values from the userspace
All the above changes are addressed as part of Vladimir Oltean <vladimir.oltean@nxp.com>
comments for this patch
- Handle all verify_status values in emac_get_mm() based on what
  all states are supported by the firmware.
This change is addressed based on AI-generated review and highlighted by
Simon Horman <horms@kernel.org>

 drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 107 +++++++++++++++++-
 drivers/net/ethernet/ti/icssg/icssg_prueth.h  |   7 +-
 drivers/net/ethernet/ti/icssg/icssg_qos.h     |  38 +++++++
 drivers/net/ethernet/ti/icssg/icssg_stats.c   |   5 +-
 drivers/net/ethernet/ti/icssg/icssg_stats.h   |   5 +
 .../net/ethernet/ti/icssg/icssg_switch_map.h  |   5 +
 6 files changed, 160 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
index b715af21d23ac..6a08c40adde54 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
@@ -6,7 +6,6 @@
  */
 
 #include "icssg_prueth.h"
-#include "icssg_stats.h"
 
 static void emac_get_drvinfo(struct net_device *ndev,
 			     struct ethtool_drvinfo *info)
@@ -294,6 +293,109 @@ static int emac_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
 	return 0;
 }
 
+static int emac_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	enum icssg_ietfpe_verify_states verify_status;
+
+	if (emac->is_sr1)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&iet->fpe_lock);
+	state->tx_enabled = iet->fpe_enabled;
+	state->tx_min_frag_size = iet->tx_min_frag_size - ETH_FCS_LEN;
+	state->tx_active = iet->fpe_active;
+	state->verify_enabled = iet->mac_verify_configure;
+	state->verify_time = iet->verify_time_ms;
+	verify_status = iet->verify_status;
+	mutex_unlock(&iet->fpe_lock);
+
+	state->pmac_enabled = true;
+	/* 64Bytes is the minimum fragment size supported
+	 * by the firmware. <64B leads to min frame errors
+	 */
+	state->rx_min_frag_size = 64;
+
+	switch (verify_status) {
+	case ICSSG_IETFPE_STATE_DISABLED:
+		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+		break;
+	case ICSSG_IETFPE_STATE_INITIAL:
+		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+		break;
+	case ICSSG_IETFPE_STATE_VERIFYING:
+		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+		break;
+	case ICSSG_IETFPE_STATE_SUCCEEDED:
+		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+		break;
+	case ICSSG_IETFPE_STATE_FAILED:
+		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+		break;
+	default:
+		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
+		break;
+	}
+
+	/* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime
+	 * variable has a range between 1 and 128 ms inclusive. Limit to that.
+	 */
+	state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+
+	return 0;
+}
+
+static int emac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
+		       struct netlink_ext_ack *extack)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	int err;
+
+	if (emac->is_sr1)
+		return -EOPNOTSUPP;
+
+	if (!cfg->pmac_enabled)
+		NL_SET_ERR_MSG_MOD(extack, "preemptible MAC is always enabled");
+
+	err = icssg_qos_validate_tx_min_frag_size(cfg->tx_min_frag_size, extack);
+	if (err)
+		return err;
+
+	err = icssg_qos_validate_verify_time(cfg->verify_time, extack);
+	if (err)
+		return err;
+
+	mutex_lock(&iet->fpe_lock);
+	iet->verify_time_ms = cfg->verify_time;
+	iet->tx_min_frag_size = cfg->tx_min_frag_size + ETH_FCS_LEN;
+	iet->fpe_enabled = cfg->tx_enabled;
+	iet->mac_verify_configure = cfg->verify_enabled;
+	icssg_config_ietfpe(emac, cfg->tx_enabled);
+	mutex_unlock(&iet->fpe_lock);
+
+	return err;
+}
+
+static void emac_get_mm_stats(struct net_device *ndev,
+			      struct ethtool_mm_stats *s)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	if (emac->is_sr1)
+		return;
+
+	if (!emac->prueth->pa_stats)
+		return;
+
+	s->MACMergeFrameAssOkCount = emac_get_stat_by_name(emac, "FW_PREEMPT_ASSEMBLY_OK");
+	s->MACMergeFrameAssErrorCount = emac_get_stat_by_name(emac, "FW_PREEMPT_ASSEMBLY_ERR");
+	s->MACMergeFragCountRx = emac_get_stat_by_name(emac, "FW_PREEMPT_FRAG_CNT_RX");
+	s->MACMergeFragCountTx = emac_get_stat_by_name(emac, "FW_PREEMPT_FRAG_CNT_TX");
+	s->MACMergeFrameSmdErrorCount = emac_get_stat_by_name(emac, "FW_PREEMPT_BAD_FRAG");
+}
+
 const struct ethtool_ops icssg_ethtool_ops = {
 	.get_drvinfo = emac_get_drvinfo,
 	.get_msglevel = emac_get_msglevel,
@@ -317,5 +419,8 @@ const struct ethtool_ops icssg_ethtool_ops = {
 	.set_eee = emac_set_eee,
 	.nway_reset = emac_nway_reset,
 	.get_rmon_stats = emac_get_rmon_stats,
+	.get_mm = emac_get_mm,
+	.set_mm = emac_set_mm,
+	.get_mm_stats = emac_get_mm_stats,
 };
 EXPORT_SYMBOL_GPL(icssg_ethtool_ops);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 85f7017d2c8e7..61320c252bec2 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -45,6 +45,7 @@
 #include "icss_iep.h"
 #include "icssg_switch_map.h"
 #include "icssg_qos.h"
+#include "icssg_stats.h"
 
 #define PRUETH_MAX_MTU          (2000 - ETH_HLEN - ETH_FCS_LEN)
 #define PRUETH_MIN_PKT_SIZE     (VLAN_ETH_ZLEN)
@@ -58,8 +59,8 @@
 
 #define ICSSG_MAX_RFLOWS	8	/* per slice */
 
-#define ICSSG_NUM_PA_STATS	32
-#define ICSSG_NUM_MIIG_STATS	60
+#define ICSSG_NUM_PA_STATS	ARRAY_SIZE(icssg_all_pa_stats)
+#define ICSSG_NUM_MIIG_STATS	ARRAY_SIZE(icssg_all_miig_stats)
 /* Number of ICSSG related stats */
 #define ICSSG_NUM_STATS (ICSSG_NUM_MIIG_STATS + ICSSG_NUM_PA_STATS)
 #define ICSSG_NUM_STANDARD_STATS 31
@@ -460,7 +461,7 @@ int emac_fdb_flow_id_updated(struct prueth_emac *emac);
 
 void icssg_stats_work_handler(struct work_struct *work);
 void emac_update_hardware_stats(struct prueth_emac *emac);
-int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name);
+u64 emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name);
 
 /* Common functions */
 void prueth_cleanup_rx_chns(struct prueth_emac *emac,
diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.h b/drivers/net/ethernet/ti/icssg/icssg_qos.h
index 083f248c557de..104910516d966 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_qos.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_qos.h
@@ -65,4 +65,42 @@ void icssg_qos_link_state_update(struct net_device *ndev);
 int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 			   void *type_data);
 void icssg_config_ietfpe(struct prueth_emac *emac, bool enable);
+static inline int icssg_qos_validate_tx_min_frag_size(u32 min_frag_size,
+						      struct netlink_ext_ack *extack)
+{
+	/* Firmware takes min_frag_size including FCS length */
+	min_frag_size += ETH_FCS_LEN;
+
+	/* The minimum size of the non-final mPacket supported
+	 * by the firmware is 64B and multiples of 64B.
+	 */
+	if (min_frag_size < 64) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "tx_min_frag_size must be at least 64 bytes");
+		return -EINVAL;
+	}
+
+	if (min_frag_size % (ETH_ZLEN + ETH_FCS_LEN)) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "tx_min_frag_size must be a multiple of 64 bytes");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline int icssg_qos_validate_verify_time(u32 verify_time_ms,
+						 struct netlink_ext_ack *extack)
+{
+	/* 802.3-2018 clause 30.14.1.6: aMACMergeVerifyTime must be
+	 * between 1 and 128 ms inclusive
+	 */
+	if (verify_time_ms < 1 || verify_time_ms > 128) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "verify_time must be between 1 and 128 ms");
+		return -EINVAL;
+	}
+
+	return 0;
+}
 #endif /* __NET_TI_ICSSG_QOS_H */
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c
index 7159baa0155cf..950d58d8183eb 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c
@@ -6,7 +6,6 @@
  */
 
 #include "icssg_prueth.h"
-#include "icssg_stats.h"
 #include <linux/regmap.h>
 
 #define ICSSG_TX_PACKET_OFFSET	0xA0
@@ -74,7 +73,7 @@ void icssg_stats_work_handler(struct work_struct *work)
 }
 EXPORT_SYMBOL_GPL(icssg_stats_work_handler);
 
-int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name)
+u64 emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name)
 {
 	int i;
 
@@ -91,5 +90,5 @@ int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name)
 	}
 
 	netdev_err(emac->ndev, "Invalid stats %s\n", stat_name);
-	return -EINVAL;
+	return 0;
 }
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/net/ethernet/ti/icssg/icssg_stats.h
index 5ec0b38e0c67d..f35ae1b4f8460 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h
@@ -189,6 +189,11 @@ static const struct icssg_pa_stats icssg_all_pa_stats[] = {
 	ICSSG_PA_STATS(FW_INF_DROP_PRIOTAGGED),
 	ICSSG_PA_STATS(FW_INF_DROP_NOTAG),
 	ICSSG_PA_STATS(FW_INF_DROP_NOTMEMBER),
+	ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
+	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
+	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
+	ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
+	ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),
 	ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
 	ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
 	ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
index 7e053b8af3ece..855fd4ed0b3f6 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
@@ -256,6 +256,11 @@
 #define FW_INF_DROP_PRIOTAGGED		0x0148
 #define FW_INF_DROP_NOTAG		0x0150
 #define FW_INF_DROP_NOTMEMBER		0x0158
+#define FW_PREEMPT_BAD_FRAG		0x0160
+#define FW_PREEMPT_ASSEMBLY_ERR		0x0168
+#define FW_PREEMPT_FRAG_CNT_TX		0x0170
+#define FW_PREEMPT_ASSEMBLY_OK		0x0178
+#define FW_PREEMPT_FRAG_CNT_RX		0x0180
 #define FW_RX_EOF_SHORT_FRMERR		0x0188
 #define FW_RX_B0_DROP_EARLY_EOF		0x0190
 #define FW_TX_JUMBO_FRM_CUTOFF		0x0198
-- 
2.43.0



^ permalink raw reply related

* [PATCH net-next v5 1/2] net: ti: icssg-prueth: Add Frame Preemption MAC Merge support
From: Meghana Malladi @ 2026-04-30 11:17 UTC (permalink / raw)
  To: vadim.fedorenko, haokexin, jacob.e.keller, horms, m-malladi, arnd,
	parvathi, afd, basharath, vladimir.oltean, rogerq, danishanwar,
	pabeni, kuba, edumazet, davem, andrew+netdev
  Cc: linux-arm-kernel, netdev, linux-kernel, srk, Vignesh Raghavendra
In-Reply-To: <20260430111723.497113-1-m-malladi@ti.com>

From: MD Danish Anwar <danishanwar@ti.com>

Introduce QoS infrastructure for Frame Preemption (FPE) support in
the ICSSG Ethernet driver.

prueth_qos_iet tracks FPE enable/active state and verify state machine
status via firmware-reported enum icssg_ietfpe_verify_states.
icssg_config_ietfpe() configures IET FPE in firmware, triggers
verify state machine based on ethtool MAC Merge parameters.
Polls firmware verify status up to 3 times with verify_time_ms intervals
and driver handles timeout by logging error and returning.

For MQPRIO qdisc support all queues are express by default later
gets override by user-provided preemptible_tcs bitmask via tc qdisc mask
Preempt mask configuration: Maps traffic classes to queue express/preemptible
state and applied only when FPE is active (Tx enabled)

Verify state machine re-triggers on link up/down events based on
fpe_enabled and fpe_active flags, and for memory protection, fpe_lock
serializes all FPE state mutations, preventing races between ethtool
config, qdisc setup, and link events

Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Signed-off-by: Meghana Malladi <m-malladi@ti.com>
---

changes from v4(v5-v4):
- preemptible TCs are committed to hardware only when FPE is active
- Removed workqueue implementation with direct call to configure FPE
- Changed MAC verification logic to poll at verify_time_ms intervals
  instead of 5 seconds.
- Used mutex_lock whenever necessary to ensure proper synchronization
All the above changes are addressed as part of Vladimir Oltean <vladimir.oltean@nxp.com>
comments for this patch

 drivers/net/ethernet/ti/Makefile             |   3 +-
 drivers/net/ethernet/ti/icssg/icssg_config.h |   9 -
 drivers/net/ethernet/ti/icssg/icssg_prueth.c |   7 +
 drivers/net/ethernet/ti/icssg/icssg_prueth.h |   2 +
 drivers/net/ethernet/ti/icssg/icssg_qos.c    | 232 +++++++++++++++++++
 drivers/net/ethernet/ti/icssg/icssg_qos.h    |  68 ++++++
 6 files changed, 311 insertions(+), 10 deletions(-)
 create mode 100644 drivers/net/ethernet/ti/icssg/icssg_qos.c
 create mode 100644 drivers/net/ethernet/ti/icssg/icssg_qos.h

diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index f4276c9a77620..d19bcd25c9d07 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -46,6 +46,7 @@ icssg-y := icssg/icssg_common.o \
 	   icssg/icssg_config.o \
 	   icssg/icssg_mii_cfg.o \
 	   icssg/icssg_stats.o \
-	   icssg/icssg_ethtool.o
+	   icssg/icssg_ethtool.o \
+	   icssg/icssg_qos.o
 
 obj-$(CONFIG_TI_ICSS_IEP) += icssg/icss_iep.o
diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h
index 60d69744ffae2..1ac202f855ed4 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_config.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_config.h
@@ -323,13 +323,4 @@ struct prueth_fdb_slot {
 	u8 fid;
 	u8 fid_c2;
 } __packed;
-
-enum icssg_ietfpe_verify_states {
-	ICSSG_IETFPE_STATE_UNKNOWN = 0,
-	ICSSG_IETFPE_STATE_INITIAL,
-	ICSSG_IETFPE_STATE_VERIFYING,
-	ICSSG_IETFPE_STATE_SUCCEEDED,
-	ICSSG_IETFPE_STATE_FAILED,
-	ICSSG_IETFPE_STATE_DISABLED
-};
 #endif /* __NET_TI_ICSSG_CONFIG_H */
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 591be5c8056b4..7657dc1015f0a 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -392,6 +392,8 @@ static void emac_adjust_link(struct net_device *ndev)
 		} else {
 			icssg_set_port_state(emac, ICSSG_EMAC_PORT_DISABLE);
 		}
+
+		icssg_qos_link_state_update(ndev);
 	}
 
 	if (emac->link) {
@@ -1652,6 +1654,7 @@ static const struct net_device_ops emac_netdev_ops = {
 	.ndo_hwtstamp_get = icssg_ndo_get_ts_config,
 	.ndo_hwtstamp_set = icssg_ndo_set_ts_config,
 	.ndo_xsk_wakeup = prueth_xsk_wakeup,
+	.ndo_setup_tc = icssg_qos_ndo_setup_tc,
 };
 
 static int prueth_netdev_init(struct prueth *prueth,
@@ -1686,6 +1689,8 @@ static int prueth_netdev_init(struct prueth *prueth,
 
 	INIT_DELAYED_WORK(&emac->stats_work, icssg_stats_work_handler);
 
+	icssg_qos_init(ndev);
+
 	ret = pruss_request_mem_region(prueth->pruss,
 				       port == PRUETH_PORT_MII0 ?
 				       PRUSS_MEM_DRAM0 : PRUSS_MEM_DRAM1,
@@ -2461,6 +2466,7 @@ static int prueth_probe(struct platform_device *pdev)
 		}
 		unregister_netdev(prueth->registered_netdevs[i]);
 		disable_work_sync(&prueth->emac[i]->rx_mode_work);
+		mutex_destroy(&prueth->emac[i]->qos.iet.fpe_lock);
 	}
 
 netdev_exit:
@@ -2521,6 +2527,7 @@ static void prueth_remove(struct platform_device *pdev)
 		prueth->emac[i]->ndev->phydev = NULL;
 		unregister_netdev(prueth->registered_netdevs[i]);
 		disable_work_sync(&prueth->emac[i]->rx_mode_work);
+		mutex_destroy(&prueth->emac[i]->qos.iet.fpe_lock);
 	}
 
 	for (i = 0; i < PRUETH_NUM_MACS; i++) {
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index df93d15c5b786..85f7017d2c8e7 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -44,6 +44,7 @@
 #include "icssg_config.h"
 #include "icss_iep.h"
 #include "icssg_switch_map.h"
+#include "icssg_qos.h"
 
 #define PRUETH_MAX_MTU          (2000 - ETH_HLEN - ETH_FCS_LEN)
 #define PRUETH_MIN_PKT_SIZE     (VLAN_ETH_ZLEN)
@@ -254,6 +255,7 @@ struct prueth_emac {
 	struct bpf_prog *xdp_prog;
 	struct xdp_attachment_info xdpi;
 	int xsk_qid;
+	struct prueth_qos qos;
 };
 
 /* The buf includes headroom compatible with both skb and xdpf */
diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.c b/drivers/net/ethernet/ti/icssg/icssg_qos.c
new file mode 100644
index 0000000000000..fc4b0ebc7d683
--- /dev/null
+++ b/drivers/net/ethernet/ti/icssg/icssg_qos.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments ICSSG PRUETH QoS submodule
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "icssg_prueth.h"
+#include "icssg_switch_map.h"
+
+static void icssg_iet_set_preempt_mask(struct prueth_emac *emac)
+{
+	void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
+	struct prueth_qos_mqprio *p_mqprio = &emac->qos.mqprio;
+	struct tc_mqprio_qopt *qopt = &p_mqprio->mqprio.qopt;
+	u8 preemptible_tcs = p_mqprio->preemptible_tcs;
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	int prempt_mask = 0, i;
+	u8 tc;
+
+	/* The preemptible traffic classes should only be committed to hardware
+	 * once TX is active.
+	 */
+	if (!iet->fpe_active) {
+		netdev_dbg(emac->ndev, "FPE not active, skipping preempt mask config\n");
+		return;
+	}
+
+	/* Configure the queues based on the preemptible tc map set by the user */
+	for (tc = 0; tc < p_mqprio->mqprio.qopt.num_tc; tc++) {
+		/* check if the tc is preemptive or not */
+		if (preemptible_tcs & BIT(tc)) {
+			for (i = qopt->offset[tc]; i < qopt->offset[tc] + qopt->count[tc]; i++) {
+				/* Set all the queues in this tc as preemptive queues */
+				writeb(BIT(4), config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
+				prempt_mask &= ~BIT(i);
+			}
+		} else {
+			/* Set all the queues in this tc as express queues */
+			for (i = qopt->offset[tc]; i < qopt->offset[tc] + qopt->count[tc]; i++) {
+				writeb(0, config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
+				prempt_mask |= BIT(i);
+			}
+		}
+		netdev_set_tc_queue(emac->ndev, tc, qopt->count[tc], qopt->offset[tc]);
+	}
+	writeb(prempt_mask, config + EXPRESS_PRE_EMPTIVE_Q_MASK);
+}
+
+static int icssg_iet_verify_wait(struct prueth_emac *emac)
+{
+	void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	int try = 3;
+
+	do {
+		msleep(iet->verify_time_ms);
+		iet->verify_status = readb(config + PRE_EMPTION_VERIFY_STATUS);
+		if (iet->verify_status == ICSSG_IETFPE_STATE_SUCCEEDED)
+			return 0;
+	} while (--try > 0);
+
+	netdev_err(emac->ndev, "MAC Verify timeout\n");
+	return -ETIMEDOUT;
+}
+
+/* Direct synchronous configuration of IET FPE.
+ * Caller must hold iet->fpe_lock.
+ */
+void icssg_config_ietfpe(struct prueth_emac *emac, bool enable)
+{
+	void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	int ret;
+	u8 val;
+
+	/* return early if FPE is not active and need not be enabled */
+	if (!iet->fpe_enabled && !iet->fpe_active)
+		return;
+
+	if (!netif_running(emac->ndev)) {
+		netdev_dbg(emac->ndev, "cannot change IET/FPE state when interface is down\n");
+		return;
+	}
+
+	/* Update FPE Tx enable bit (PRE_EMPTION_ENABLE_TX) if
+	 * fpe_enabled is set to enable MM in Tx direction
+	 */
+	writeb(enable ? 1 : 0, config + PRE_EMPTION_ENABLE_TX);
+
+	/* If FPE is to be enabled, first configure MAC Verify state
+	 * machine in firmware as firmware kicks the Verify process
+	 * as soon as ICSSG_EMAC_PORT_PREMPT_TX_ENABLE command is
+	 * received.
+	 */
+	if (enable && iet->mac_verify_configure) {
+		writeb(1, config + PRE_EMPTION_ENABLE_VERIFY);
+		writew(iet->tx_min_frag_size, config + PRE_EMPTION_ADD_FRAG_SIZE_LOCAL);
+		writel(iet->verify_time_ms, config + PRE_EMPTION_VERIFY_TIME);
+	} else {
+		iet->verify_status = ICSSG_IETFPE_STATE_DISABLED;
+	}
+
+	/* Send command to enable FPE Tx side. Rx is always enabled */
+	ret = icssg_set_port_state(emac,
+				   enable ? ICSSG_EMAC_PORT_PREMPT_TX_ENABLE :
+					    ICSSG_EMAC_PORT_PREMPT_TX_DISABLE);
+	if (ret) {
+		netdev_err(emac->ndev, "TX preempt %s command failed\n",
+			   str_enable_disable(enable));
+		writeb(0, config + PRE_EMPTION_ENABLE_VERIFY);
+		iet->verify_status = ICSSG_IETFPE_STATE_DISABLED;
+		return;
+	}
+
+	if (enable && iet->mac_verify_configure) {
+		ret = icssg_iet_verify_wait(emac);
+		if (ret) {
+			netdev_err(emac->ndev, "MAC Verification failed with timeout\n");
+			return;
+		}
+	} else if (enable) {
+		/* Give firmware some time to update PRE_EMPTION_ACTIVE_TX state */
+		usleep_range(100, 200);
+	}
+
+	if (enable) {
+		val = readb(config + PRE_EMPTION_ACTIVE_TX);
+		if (val != 1) {
+			netdev_err(emac->ndev,
+				   "Firmware fails to activate IET/FPE\n");
+			return;
+		}
+		iet->fpe_active = true;
+	} else {
+		iet->fpe_active = false;
+	}
+
+	icssg_iet_set_preempt_mask(emac);
+	netdev_err(emac->ndev, "IET FPE %s successfully\n",
+		  str_enable_disable(iet->fpe_active));
+}
+EXPORT_SYMBOL_GPL(icssg_config_ietfpe);
+
+void icssg_qos_init(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+
+	iet->emac = emac;
+	mutex_init(&iet->fpe_lock);
+}
+
+static void icssg_iet_change_preemptible_tcs(struct prueth_emac *emac)
+{
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+
+	mutex_lock(&iet->fpe_lock);
+	icssg_config_ietfpe(emac, iet->fpe_enabled);
+	mutex_unlock(&iet->fpe_lock);
+}
+
+static int emac_tc_query_caps(struct net_device *ndev, void *type_data)
+{
+	struct tc_query_caps_base *base = type_data;
+
+	switch (base->type) {
+	case TC_SETUP_QDISC_MQPRIO: {
+		struct tc_mqprio_caps *caps = base->caps;
+
+		caps->validate_queue_counts = true;
+		return 0;
+	}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int emac_tc_setup_mqprio(struct net_device *ndev, void *type_data)
+{
+	struct tc_mqprio_qopt_offload *mqprio = type_data;
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct tc_mqprio_qopt *qopt = &mqprio->qopt;
+	struct prueth_qos_mqprio *p_mqprio;
+	u8 num_tc = mqprio->qopt.num_tc;
+	int tc, offset, count;
+
+	p_mqprio = &emac->qos.mqprio;
+
+	if (!num_tc) {
+		netdev_reset_tc(ndev);
+		p_mqprio->preemptible_tcs = 0;
+		p_mqprio->mqprio.qopt.num_tc = 0;
+		goto reset_tcs;
+	}
+
+	memcpy(&p_mqprio->mqprio, mqprio, sizeof(*mqprio));
+	p_mqprio->preemptible_tcs = mqprio->preemptible_tcs;
+	netdev_set_num_tc(ndev, mqprio->qopt.num_tc);
+
+	for (tc = 0; tc < num_tc; tc++) {
+		count = qopt->count[tc];
+		offset = qopt->offset[tc];
+		netdev_set_tc_queue(ndev, tc, count, offset);
+	}
+
+reset_tcs:
+	icssg_iet_change_preemptible_tcs(emac);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(icssg_qos_init);
+
+int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
+			   void *type_data)
+{
+	switch (type) {
+	case TC_QUERY_CAPS:
+		return emac_tc_query_caps(ndev, type_data);
+	case TC_SETUP_QDISC_MQPRIO:
+		return emac_tc_setup_mqprio(ndev, type_data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+EXPORT_SYMBOL_GPL(icssg_qos_ndo_setup_tc);
+
+void icssg_qos_link_state_update(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	icssg_iet_change_preemptible_tcs(emac);
+}
+EXPORT_SYMBOL_GPL(icssg_qos_link_state_update);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.h b/drivers/net/ethernet/ti/icssg/icssg_qos.h
new file mode 100644
index 0000000000000..083f248c557de
--- /dev/null
+++ b/drivers/net/ethernet/ti/icssg/icssg_qos.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#ifndef __NET_TI_ICSSG_QOS_H
+#define __NET_TI_ICSSG_QOS_H
+
+#include <linux/atomic.h>
+#include <linux/netdevice.h>
+#include <net/pkt_sched.h>
+
+/**
+ * enum icssg_ietfpe_verify_states - status of MAC Merge Verify returned by firmware
+ * @ICSSG_IETFPE_STATE_UNKNOWN:
+ *	verification status is unknown
+ * @ICSSG_IETFPE_STATE_INITIAL:
+ *	Firmware returns this if verify state diagram is idle
+ * @ICSSG_IETFPE_STATE_VERIFYING:
+ *	Firmware returns this if verification is ongoing
+ * @ICSSG_IETFPE_STATE_SUCCEEDED:
+ *	Firmware returns this if verify state diagram completes verification
+ * @ICSSG_IETFPE_STATE_FAILED:
+ *	Firmware returns this if verify state diagram fails during verification
+ * @ICSSG_IETFPE_STATE_DISABLED:
+ *	verification is disabled by the driver
+ */
+enum icssg_ietfpe_verify_states {
+	ICSSG_IETFPE_STATE_UNKNOWN = 0,
+	ICSSG_IETFPE_STATE_INITIAL,
+	ICSSG_IETFPE_STATE_VERIFYING,
+	ICSSG_IETFPE_STATE_SUCCEEDED,
+	ICSSG_IETFPE_STATE_FAILED,
+	ICSSG_IETFPE_STATE_DISABLED
+};
+
+struct prueth_qos_mqprio {
+	struct tc_mqprio_qopt_offload mqprio;
+	u8 preemptible_tcs;
+};
+
+struct prueth_qos_iet {
+	struct prueth_emac *emac;
+
+	/* Configuration state - protected by fpe_lock */
+	bool fpe_enabled;
+	bool mac_verify_configure;
+	u32 tx_min_frag_size;
+	u32 verify_time_ms;
+
+	/* Runtime state - protected by fpe_lock */
+	bool fpe_active;
+	enum icssg_ietfpe_verify_states verify_status;
+
+	/* Synchronization: single mutex protects all FPE operations */
+	struct mutex fpe_lock;
+};
+
+struct prueth_qos {
+	struct prueth_qos_iet iet;
+	struct prueth_qos_mqprio mqprio;
+};
+
+void icssg_qos_init(struct net_device *ndev);
+void icssg_qos_link_state_update(struct net_device *ndev);
+int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
+			   void *type_data);
+void icssg_config_ietfpe(struct prueth_emac *emac, bool enable);
+#endif /* __NET_TI_ICSSG_QOS_H */
-- 
2.43.0



^ permalink raw reply related


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