* [PATCH 01/15] KVM: arm64: vgic: Don't reset cpuif/redist addresses at finalize time
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Although we are OK with rewriting idregs at finalize time, resetting
the guest's cpuif (GICv3) or redistributor (GICv3) addresses once
we start running the guest is a pretty bad idea.
Move back this initialisation to vgic creation time.
Fixes: a258a383b9177 ("KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE")
Link: https://patch.msgid.link/20260323174713.3183111-1-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 47169604100f2..fd872079f2a24 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -147,6 +147,15 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST;
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+ switch (type) {
+ case KVM_DEV_TYPE_ARM_VGIC_V2:
+ kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+ break;
+ case KVM_DEV_TYPE_ARM_VGIC_V3:
+ INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
+ break;
+ }
+
/*
* We've now created the GIC. Update the system register state
* to accurately reflect what we've created.
@@ -684,10 +693,8 @@ void kvm_vgic_finalize_idregs(struct kvm *kvm)
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
- kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
break;
case KVM_DEV_TYPE_ARM_VGIC_V3:
- INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
break;
--
2.47.3
^ permalink raw reply related
* [PATCH 15/15] KVM: arm64: Don't advertises GICv3 in ID_PFR1_EL1 if AArch32 isn't supported
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Although the AArch32 ID regs are architecturally UNKNOWN when AArch32
isn't supported at any EL, KVM makes a point in making them RAZ.
Therefore, advertising GICv3 in ID_PFR1_EL1 must be gated on AArch32
being supported at least at EL0.
Fixes: a258a383b9177 ("KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE")
Reported-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index ecb0aea180327..5c684ecf79e66 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -700,7 +700,8 @@ void kvm_vgic_finalize_idregs(struct kvm *kvm)
break;
case KVM_DEV_TYPE_ARM_VGIC_V3:
aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
- pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
+ if (kvm_supports_32bit_el0())
+ pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
break;
case KVM_DEV_TYPE_ARM_VGIC_V5:
aa64pfr2 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR2_EL1, GCIE, IMP);
--
2.47.3
^ permalink raw reply related
* [PATCH 07/15] KVM: arm64: vgic-v5: Transfer edge pending state to ICH_PPI_PENDRx_EL2
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
While it is perfectly correct to leave the pending state of a level
interrupt as is when queuing it (it is, after all, only driven by
the line), edge pending state must be transfered, as nothing will
lower it.
Fixes: 4d591252bacb2 ("KVM: arm64: gic-v5: Implement PPI interrupt injection")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 119d7d01d0e77..422741c86c6a8 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -445,8 +445,11 @@ void vgic_v5_flush_ppi_state(struct kvm_vcpu *vcpu)
irq = vgic_get_vcpu_irq(vcpu, intid);
- scoped_guard(raw_spinlock_irqsave, &irq->irq_lock)
+ scoped_guard(raw_spinlock_irqsave, &irq->irq_lock) {
__assign_bit(i, pendr, irq_is_pending(irq));
+ if (irq->config == VGIC_CONFIG_EDGE)
+ irq->pending_latch = false;
+ }
vgic_put_irq(vcpu->kvm, irq);
}
--
2.47.3
^ permalink raw reply related
* [PATCH 06/15] KVM: arm64: vgic-v5: Hold config_lock while finalizing GICv5 PPIs
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Finalizing the PPI state is done without holding any lock, which
means that two vcpus can race against each other and have one zeroing
the state while another one is setting it, or even maybe using it.
Fixing this is done by:
- holding the config lock while performing the initialisation
- checking if SW_PPI has already been advertised, meaning that
we have already completed the initialisation once
Fixes: 8f1fbe2fd2792 ("KVM: arm64: gic-v5: Finalize GICv5 PPIs and generate mask")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 2b6cd5c3f9c2f..119d7d01d0e77 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -172,6 +172,16 @@ int vgic_v5_finalize_ppi_state(struct kvm *kvm)
if (!vgic_is_v5(kvm))
return 0;
+ guard(mutex)(&kvm->arch.config_lock);
+
+ /*
+ * If SW_PPI has been advertised, then we know we already
+ * initialised the whole thing, and we can return early. Yes,
+ * this is pretty hackish as far as state tracking goes...
+ */
+ if (test_bit(GICV5_ARCH_PPI_SW_PPI, kvm->arch.vgic.gicv5_vm.vgic_ppi_mask))
+ return 0;
+
/* The PPI state for all VCPUs should be the same. Pick the first. */
vcpu0 = kvm_get_vcpu(kvm, 0);
--
2.47.3
^ permalink raw reply related
* [PATCH 09/15] KVM: arm64: vgic-v5: align priority comparison with other GICs
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The way the effective priority mask is computed, and then compared
to the priority of an interrupt to decide whether to wake-up or not,
is slightly odd, and breaks at the limits.
This could result in spurious wake-ups that are undesirable.
Adopt the GICv[23] logic instead, which checks that the priority value
is strictly lower than the mask.
Fixes: 933e5288fa971 ("KVM: arm64: gic-v5: Check for pending PPIs")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 0f269321ece4b..75372bbfb6a6a 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -238,7 +238,7 @@ static u32 vgic_v5_get_effective_priority_mask(struct kvm_vcpu *vcpu)
*/
priority_mask = FIELD_GET(FEAT_GCIE_ICH_VMCR_EL2_VPMR, cpu_if->vgic_vmcr);
- return min(highest_ap, priority_mask + 1);
+ return min(highest_ap, priority_mask);
}
/*
@@ -367,7 +367,7 @@ bool vgic_v5_has_pending_ppi(struct kvm_vcpu *vcpu)
scoped_guard(raw_spinlock_irqsave, &irq->irq_lock)
has_pending = (irq->enabled && irq_is_pending(irq) &&
- irq->priority <= priority_mask);
+ irq->priority < priority_mask);
vgic_put_irq(vcpu->kvm, irq);
--
2.47.3
^ permalink raw reply related
* [PATCH 08/15] KVM: arm64: vgic-v5: Cast vgic_apr to u32 to avoid undefined behaviours
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Passing a u64 to __builtin_ctz() is odd, and requires some digging to
figure out why this construct is indeed safe as long as the HW is
correct.
But it is much easier to make it clear to the compiler by casting
the u64 into an intermediate u32, and be done with the UD.
Fixes: 933e5288fa971 ("KVM: arm64: gic-v5: Check for pending PPIs")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 422741c86c6a8..0f269321ece4b 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -212,7 +212,7 @@ int vgic_v5_finalize_ppi_state(struct kvm *kvm)
static u32 vgic_v5_get_effective_priority_mask(struct kvm_vcpu *vcpu)
{
struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
- u32 highest_ap, priority_mask;
+ u32 highest_ap, priority_mask, apr;
/*
* If the guest's CPU has not opted to receive interrupts, then the
@@ -227,7 +227,8 @@ static u32 vgic_v5_get_effective_priority_mask(struct kvm_vcpu *vcpu)
* priority. Explicitly use the 32-bit version here as we have 32
* priorities. 32 then means that there are no active priorities.
*/
- highest_ap = cpu_if->vgic_apr ? __builtin_ctz(cpu_if->vgic_apr) : 32;
+ apr = cpu_if->vgic_apr;
+ highest_ap = apr ? __builtin_ctz(apr) : 32;
/*
* An interrupt is of sufficient priority if it is equal to or
--
2.47.3
^ permalink raw reply related
* [PATCH 13/15] KVM: arm64: Move GICv5 timer PPI validation into timer_irqs_are_valid()
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Userspace can set the timer PPI numbers way before a GIC has been
created, leading to odd behaviours on GICv5 as we'd accept non
architectural PPI numbers.
Move the v5 check into timer_irqs_are_valid(), which aligns the
behaviour with the pre-v5 GICs, and is also guaranteed to run
only once a GIC has been configured.
Fixes: 9491c63b6cd7b ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arch_timer.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 6608c47d1f628..cbea4d9ee9552 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -1543,6 +1543,10 @@ static bool timer_irqs_are_valid(struct kvm_vcpu *vcpu)
if (kvm_vgic_set_owner(vcpu, irq, ctx))
break;
+ /* With GICv5, the default PPI is what you get -- nothing else */
+ if (vgic_is_v5(vcpu->kvm) && irq != get_vgic_ppi(vcpu->kvm, default_ppi[i]))
+ break;
+
/*
* We know by construction that we only have PPIs, so all values
* are less than 32 for non-GICv5 VGICs. On GICv5, they are
@@ -1678,13 +1682,6 @@ int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
return -ENXIO;
}
- /*
- * The PPIs for the Arch Timers are architecturally defined for
- * GICv5. Reject anything that changes them from the specified value.
- */
- if (vgic_is_v5(vcpu->kvm) && vcpu->kvm->arch.timer_data.ppi[idx] != irq)
- return -EINVAL;
-
/*
* We cannot validate the IRQ unicity before we run, so take it at
* face value. The verdict will be given on first vcpu run, for each
--
2.47.3
^ permalink raw reply related
* [PATCH 11/15] KVM: arm64: Kill arch_timer_context::direct field
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The newly introduced arch_timer_context::direct field is a bit pointless,
as it is always set on timers that are... err... direct, while
we already have a way to get to that by doing a get_map() operation.
Additionally, this field is:
- only set when get_map() is called
- never cleared
and the single point where it is actually checked doesn't call get_map()
at all.
At this stage, it is probably better to just kill it, and rely on
get_map() to give us the correct information.
Fixes: 9491c63b6cd7b ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arch_timer.c | 15 +++++++++------
include/kvm/arm_arch_timer.h | 3 ---
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 67b989671b410..37279f8748695 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -183,10 +183,6 @@ void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
map->emul_ptimer = vcpu_ptimer(vcpu);
}
- map->direct_vtimer->direct = true;
- if (map->direct_ptimer)
- map->direct_ptimer->direct = true;
-
trace_kvm_get_timer_map(vcpu->vcpu_id, map);
}
@@ -462,8 +458,15 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
return;
/* Skip injecting on GICv5 for directly injected (DVI'd) timers */
- if (vgic_is_v5(vcpu->kvm) && timer_ctx->direct)
- return;
+ if (vgic_is_v5(vcpu->kvm)) {
+ struct timer_map map;
+
+ get_timer_map(vcpu, &map);
+
+ if (map.direct_ptimer == timer_ctx ||
+ map.direct_vtimer == timer_ctx)
+ return;
+ }
kvm_vgic_inject_irq(vcpu->kvm, vcpu,
timer_irq(timer_ctx),
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index a7754e0a2ef41..bf8cc9589bd09 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -76,9 +76,6 @@ struct arch_timer_context {
/* Duplicated state from arch_timer.c for convenience */
u32 host_timer_irq;
-
- /* Is this a direct timer? */
- bool direct;
};
struct timer_map {
--
2.47.3
^ permalink raw reply related
* [PATCH 10/15] KVM: arm64: vgic-v5: Correctly set dist->ready once initialised
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
kvm_vgic_map_resources() targetting a v5 model results in vgic->dist_ready
never being set. This doesn't result in anything really bad, only
some more heavy locking as we go and re-init something for no good reason.
Rejig the code to correctly set the ready flag in all non-failing
cases.
Fixes: f4d37c7c35769 ("KVM: arm64: gic-v5: Create and initialise vgic_v5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index fd872079f2a24..ecb0aea180327 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -657,16 +657,20 @@ int kvm_vgic_map_resources(struct kvm *kvm)
needs_dist = false;
}
- if (ret || !needs_dist)
+ if (ret)
goto out;
- dist_base = dist->vgic_dist_base;
- mutex_unlock(&kvm->arch.config_lock);
+ if (needs_dist) {
+ dist_base = dist->vgic_dist_base;
+ mutex_unlock(&kvm->arch.config_lock);
- ret = vgic_register_dist_iodev(kvm, dist_base, type);
- if (ret) {
- kvm_err("Unable to register VGIC dist MMIO regions\n");
- goto out_slots;
+ ret = vgic_register_dist_iodev(kvm, dist_base, type);
+ if (ret) {
+ kvm_err("Unable to register VGIC dist MMIO regions\n");
+ goto out_slots;
+ }
+ } else {
+ mutex_unlock(&kvm->arch.config_lock);
}
smp_store_release(&dist->ready, true);
--
2.47.3
^ permalink raw reply related
* [PATCH 12/15] KVM: arm64: Remove evaluation of timer state in kvm_cpu_has_pending_timer()
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The vgic-v5 code added some evaluations of the timers in a helper funtion
(kvm_cpu_has_pending_timer()) that is called to determine whether
the vcpu can wake-up.
But looking at the timer there is wrong:
- we want to see timers that are signalling an interrupt to the
vcpu, and not just that have a pending interrupt
- we already have kvm_arch_vcpu_runnable() that evaluates the
state of interrupts
- kvm_cpu_has_pending_timer() really is about WFIT, as the timeout
does not generate an interrupt, and is therefore distinct from
the point above
As a consequence, revert these changes.
Fixes: 9491c63b6cd7b ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arch_timer.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 37279f8748695..6608c47d1f628 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -402,11 +402,7 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
- struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
- struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
-
- return kvm_timer_should_fire(vtimer) || kvm_timer_should_fire(ptimer) ||
- (vcpu_has_wfit_active(vcpu) && wfit_delay_ns(vcpu) == 0);
+ return vcpu_has_wfit_active(vcpu) && wfit_delay_ns(vcpu) == 0;
}
/*
--
2.47.3
^ permalink raw reply related
* [PATCH 14/15] KVM: arm64: Correctly plumb ID_AA64PFR2_EL1 into pkvm idreg handling
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
While we now compute ID_AA64PFR2_EL1 to a glorious 0, we never use
that data and instead return the 0 that corresponds to an allocated
idreg. Not a big deal, but we might as well be consistent.
Fixes: 5aefaf11f9af5 ("KVM: arm64: gic: Hide GICv5 for protected guests")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/hyp/nvhe/sys_regs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
index b40fd01ebf329..be6f420388a14 100644
--- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
+++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
@@ -439,7 +439,7 @@ static const struct sys_reg_desc pvm_sys_reg_descs[] = {
/* CRm=4 */
AARCH64(SYS_ID_AA64PFR0_EL1),
AARCH64(SYS_ID_AA64PFR1_EL1),
- ID_UNALLOCATED(4,2),
+ AARCH64(SYS_ID_AA64PFR2_EL1),
ID_UNALLOCATED(4,3),
AARCH64(SYS_ID_AA64ZFR0_EL1),
ID_UNALLOCATED(4,5),
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v2 07/17] firmware: arm_scmi: Use new Telemetry traces
From: Cristian Marussi @ 2026-03-26 15:35 UTC (permalink / raw)
To: Elif Topuz
Cc: Cristian Marussi, linux-kernel, linux-arm-kernel, arm-scmi,
linux-fsdevel, sudeep.holla, james.quinlan, f.fainelli,
vincent.guittot, etienne.carriere, peng.fan, michal.simek,
dan.carpenter, d-gole, jonathan.cameron, lukasz.luba,
philip.radford, souvik.chakravarty
In-Reply-To: <3c6bddfd-a674-486c-add4-35ef93ec88c4@arm.com>
On Fri, Jan 23, 2026 at 11:43:37AM +0000, Elif Topuz wrote:
>
> Hi Cristian,
Hi Elif,
>
> On 14/01/2026 11:46, Cristian Marussi wrote:
> > Track failed SHMTI accesses and received notifications.
> >
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---
> > drivers/firmware/arm_scmi/telemetry.c | 57 ++++++++++++++++++++++-----
> > 1 file changed, 48 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/firmware/arm_scmi/telemetry.c b/drivers/firmware/arm_scmi/telemetry.c
> > index 16bcdcdc1dc3..443e032a3553 100644
> > --- a/drivers/firmware/arm_scmi/telemetry.c
> > +++ b/drivers/firmware/arm_scmi/telemetry.c
> > @@ -25,6 +25,8 @@
> > #include "protocols.h"
> > #include "notify.h"
> >
> > +#include <trace/events/scmi.h>
> > +
> > /* Updated only after ALL the mandatory features for that version are merged */
> > #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000
> >
> > @@ -1366,8 +1368,10 @@ static void scmi_telemetry_tdcf_blkts_parse(struct telemetry_info *ti,
> >
> > /* Check for spec compliance */
> > if (USE_LINE_TS(payld) || USE_BLK_TS(payld) ||
> > - DATA_INVALID(payld) || (PAYLD_ID(payld) != 0))
> > + DATA_INVALID(payld) || (PAYLD_ID(payld) != 0)) {
> > + trace_scmi_tlm_access(0, "BLK_TS_INVALID", 0, 0);
> > return;
> > + }
> >
> > /* A BLK_TS descriptor MUST be returned: it is found or it is crated */
> > bts = scmi_telemetry_blkts_lookup(ti->ph->dev, &ti->xa_bts, payld);
> > @@ -1376,6 +1380,9 @@ static void scmi_telemetry_tdcf_blkts_parse(struct telemetry_info *ti,
> >
> > /* Update the descriptor with the lastest TS*/
> > scmi_telemetry_blkts_update(shmti->last_magic, bts);
> > +
> > + trace_scmi_tlm_collect(bts->last_ts, (u64)payld,
> > + bts->last_magic, "SHMTI_BLK_TS");
> > }
> >
> > static void scmi_telemetry_tdcf_data_parse(struct telemetry_info *ti,
> > @@ -1393,8 +1400,10 @@ static void scmi_telemetry_tdcf_data_parse(struct telemetry_info *ti,
> > /* Is thi DE ID know ? */
> > tde = scmi_telemetry_tde_lookup(ti, de_id);
> > if (!tde) {
> > - if (mode != SCAN_DISCOVERY)
> > + if (mode != SCAN_DISCOVERY) {
> > + trace_scmi_tlm_access(de_id, "DE_INVALID", 0, 0);
> > return;
> > + }
> >
> > /* In SCAN_DISCOVERY mode we allocate new DEs for unknown IDs */
> > tde = scmi_telemetry_tde_get(ti, de_id);
> > @@ -1462,6 +1471,8 @@ static void scmi_telemetry_tdcf_data_parse(struct telemetry_info *ti,
> > tde->last_ts = tstamp;
> > else
> > tde->last_ts = 0;
> > +
> > + trace_scmi_tlm_collect(0, tde->de.info->id, tde->last_val, "SHMTI_DE_UPDT");
>
> tde->last_ts instead of 0?
>
Yes, but I have reworked a lot the code so the traces also are moved
around a lot with different tags...also I move the trace definitions
before the protocol series in V3 and scattered the trace calls all
across the protocol patches, which I split a lot.
I tried anyway to follow your advice...well..anyway I doubt V3 will be
the last one :P, so you're welcome to complain...
> > }
> >
> > static int scmi_telemetry_tdcf_line_parse(struct telemetry_info *ti,
> > @@ -1507,8 +1518,10 @@ static int scmi_telemetry_shmti_scan(struct telemetry_info *ti,
> > fsleep((SCMI_TLM_TDCF_MAX_RETRIES - retries) * 1000);
> >
> > startm = TDCF_START_SEQ_GET(tdcf);
> > - if (IS_BAD_START_SEQ(startm))
> > + if (IS_BAD_START_SEQ(startm)) {
> > + trace_scmi_tlm_access(0, "MSEQ_BADSTART", startm, 0);
> > continue;
> > + }
> >
> > /* On a BAD_SEQ this will be updated on the next attempt */
> > shmti->last_magic = startm;
> > @@ -1520,18 +1533,25 @@ static int scmi_telemetry_shmti_scan(struct telemetry_info *ti,
> >
> > used_qwords = scmi_telemetry_tdcf_line_parse(ti, next,
> > shmti, mode);
> > - if (qwords < used_qwords)
> > + if (qwords < used_qwords) {
> > + trace_scmi_tlm_access(PAYLD_ID(next),
> > + "BAD_QWORDS", startm, 0);
> > return -EINVAL;
> > + }
> >
> > next += used_qwords * 8;
> > qwords -= used_qwords;
> > }
> >
> > endm = TDCF_END_SEQ_GET(eplg);
> > + if (startm != endm)
> > + trace_scmi_tlm_access(0, "MSEQ_MISMATCH", startm, endm);
> > } while (startm != endm && --retries);
> >
> > - if (startm != endm)
> > + if (startm != endm) {
> > + trace_scmi_tlm_access(0, "TDCF_SCAN_FAIL", startm, endm);
> > return -EPROTO;
> > + }
> >
> > return 0;
> > }
> > @@ -1923,6 +1943,8 @@ static void scmi_telemetry_scan_update(struct telemetry_info *ti, u64 ts)
> > tde->last_ts = tstamp;
> > else
> > tde->last_ts = 0;
> > +
> > + trace_scmi_tlm_collect(ts, tde->de.info->id, tde->last_val, "FC_UPDATE");
>
> tde->last_ts instead of ts?
Yes...but a lot of rework as said above...
>
> > }
> > }
> >
> > @@ -2001,8 +2023,11 @@ static int scmi_telemetry_tdcf_de_parse(struct telemetry_de *tde,
> > fsleep((SCMI_TLM_TDCF_MAX_RETRIES - retries) * 1000);
> >
> > startm = TDCF_START_SEQ_GET(tdcf);
> > - if (IS_BAD_START_SEQ(startm))
> > + if (IS_BAD_START_SEQ(startm)) {
> > + trace_scmi_tlm_access(tde->de.info->id, "MSEQ_BADSTART",
> > + startm, 0);
> > continue;
> > + }
> >
> > /* Has anything changed at all at the SHMTI level ? */
> > scoped_guard(mutex, &tde->mtx) {
> > @@ -2018,11 +2043,16 @@ static int scmi_telemetry_tdcf_de_parse(struct telemetry_de *tde,
> > if (DATA_INVALID(payld))
> > return -EINVAL;
> >
> > - if (IS_BLK_TS(payld))
> > + if (IS_BLK_TS(payld)) {
> > + trace_scmi_tlm_access(tde->de.info->id,
> > + "BAD_DE_META", 0, 0);
> > return -EINVAL;
> > + }
> >
> > - if (PAYLD_ID(payld) != tde->de.info->id)
> > + if (PAYLD_ID(payld) != tde->de.info->id) {
> > + trace_scmi_tlm_access(tde->de.info->id, "DE_INVALID", 0, 0);
> > return -EINVAL;
> > + }
> >
> > /* Data is always valid since NOT handling BLK TS lines here */
> > *val = LINE_DATA_GET(&payld->l);
> > @@ -2046,10 +2076,16 @@ static int scmi_telemetry_tdcf_de_parse(struct telemetry_de *tde,
> > }
> >
> > endm = TDCF_END_SEQ_GET(tde->eplg);
> > + if (startm != endm)
> > + trace_scmi_tlm_access(tde->de.info->id, "MSEQ_MISMATCH",
> > + startm, endm);
> > } while (startm != endm && --retries);
> >
> > - if (startm != endm)
> > + if (startm != endm) {
> > + trace_scmi_tlm_access(tde->de.info->id, "TDCF_DE_FAIL",
> > + startm, endm);
> > return -EPROTO;
> > + }
> >
> > guard(mutex)(&tde->mtx);
> > tde->last_magic = startm;
> > @@ -2230,6 +2266,9 @@ scmi_telemetry_msg_payld_process(struct telemetry_info *ti,
> > tde->last_ts = LINE_TSTAMP_GET(&payld->tsl);
> > else
> > tde->last_ts = 0;
> > +
> > + trace_scmi_tlm_collect(timestamp, tde->de.info->id, tde->last_val,
> > + "MESSAGE");
>
> tde->last_ts instead of timestamp? If I understand correctly, tde->last_ts
> corresponds to the time coming from the platform. We have kernel time anyway
> coming from ftrace format.
Yes good point...timestamp is the time of arrival of the
notification...I can also drop that parameter at this point...
Thanks a lot for reviewing !
Cristian
^ permalink raw reply
* Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD TX packets
From: Sean Anderson @ 2026-03-26 15:38 UTC (permalink / raw)
To: Gupta, Suraj, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
Simek, Michal, Pandey, Radhey Shyam, horms@kernel.org
Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Katakam, Harini
In-Reply-To: <SA1PR12MB6798E4EB242D58AEB86661B9C949A@SA1PR12MB6798.namprd12.prod.outlook.com>
On 3/25/26 01:30, Gupta, Suraj wrote:
> [Public]
>
>> -----Original Message-----
>> From: Sean Anderson <sean.anderson@linux.dev>
>> Sent: Tuesday, March 24, 2026 9:39 PM
>> To: Gupta, Suraj <Suraj.Gupta2@amd.com>; andrew+netdev@lunn.ch;
>> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
>> pabeni@redhat.com; Simek, Michal <michal.simek@amd.com>; Pandey,
>> Radhey Shyam <radhey.shyam.pandey@amd.com>; horms@kernel.org
>> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
>> kernel@vger.kernel.org; Katakam, Harini <harini.katakam@amd.com>
>> Subject: Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD
>> TX packets
>>
>> Caution: This message originated from an External Source. Use proper caution
>> when opening attachments, clicking links, or responding.
>>
>>
>> On 3/24/26 10:53, Suraj Gupta wrote:
>> > When a TX packet spans multiple buffer descriptors (scatter-gather),
>> > the per-BD byte count is accumulated into a local variable that resets
>> > on each NAPI poll. If the BDs for a single packet complete across
>> > different polls, the earlier bytes are lost and never credited to BQL.
>> > This causes BQL to think bytes are permanently in-flight, eventually
>> > stalling the TX queue.
>> >
>> > Fix this by replacing the local accumulator with a persistent counter
>> > (tx_compl_bytes) that survives across polls and is reset only after
>> > updating BQL and stats.
>>
>> Do we need this? Can't we just do something like
>>
>
> Nope, the 'size' variable passed to axienet_free_tx_chain() is local
> to axienet_tx_poll() and goes out of scope between different polls.
> This means it can't track completion bytes across multiple NAPI polls.
Yes, but that's fine since we only update completed bytes when we retire at least one packet:
packets = axienet_free_tx_chain(lp, &size, budget);
if (packets) {
netdev_completed_queue(ndev, packets, size);
u64_stats_update_begin(&lp->tx_stat_sync);
u64_stats_add(&lp->tx_packets, packets);
u64_stats_add(&lp->tx_bytes, size);
u64_stats_update_end(&lp->tx_stat_sync);
/* Matches barrier in axienet_start_xmit */
smp_mb();
if (((tail - ci) & (lp->rx_bd_num - 1)) >= MAX_SKB_FRAGS + 1)
netif_wake_queue(ndev);
}
and this matches the value we use when enqueuing a packet
tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * (last_p - lp->tx_bd_v);
smp_store_release(&lp->tx_bd_tail, new_tail_ptr);
netdev_sent_queue(ndev, skb->len);
> Regards,
> Suraj
>
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> index 415e9bc252527..1ea8a6592bce1 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> @@ -768,6 +768,7 @@ static int axienet_free_tx_chain(struct axienet_local
>> *lp, u32 *sizep, int budge
>> if (cur_p->skb) {
>> struct axienet_cb *cb = (void *)cur_p->skb->cb;
>>
>> + *sizep += skb->len;
>> dma_unmap_sgtable(lp->dev, &cb->sgt, DMA_TO_DEVICE, 0);
>> sg_free_table_chained(&cb->sgt, XAE_INLINE_SG_CNT);
>> napi_consume_skb(cur_p->skb, budget); @@ -783,8 +784,6 @@
>> static int axienet_free_tx_chain(struct axienet_local *lp, u32 *sizep, int budge
>> wmb();
>> cur_p->cntrl = 0;
>> cur_p->status = 0;
>> -
>> - *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> }
>>
>> smp_store_release(&lp->tx_bd_ci, (ci + i) & (lp->tx_bd_num - 1));
>>
>> > Fixes: c900e49d58eb ("net: xilinx: axienet: Implement BQL")
>> > Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
>> > ---
>> > drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 +++
>> > .../net/ethernet/xilinx/xilinx_axienet_main.c | 20 +++++++++----------
>> > 2 files changed, 13 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > index 602389843342..a4444c939451 100644
>> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > @@ -509,6 +509,8 @@ struct skbuf_dma_descriptor {
>> > * complete. Only updated at runtime by TX NAPI poll.
>> > * @tx_bd_tail: Stores the index of the next Tx buffer descriptor in the ring
>> > * to be populated.
>> > + * @tx_compl_bytes: Accumulates TX completion length until a full packet is
>> > + * reported to the stack.
>> > * @tx_packets: TX packet count for statistics
>> > * @tx_bytes: TX byte count for statistics
>> > * @tx_stat_sync: Synchronization object for TX stats @@ -592,6
>> > +594,7 @@ struct axienet_local {
>> > u32 tx_bd_num;
>> > u32 tx_bd_ci;
>> > u32 tx_bd_tail;
>> > + u32 tx_compl_bytes;
>> > u64_stats_t tx_packets;
>> > u64_stats_t tx_bytes;
>> > struct u64_stats_sync tx_stat_sync; diff --git
>> > a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > index b06e4c37ff61..95bf61986cb7 100644
>> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > @@ -692,6 +692,8 @@ static void axienet_dma_stop(struct axienet_local
>> *lp)
>> > axienet_lock_mii(lp);
>> > __axienet_device_reset(lp);
>> > axienet_unlock_mii(lp);
>> > +
>> > + lp->tx_compl_bytes = 0;
>> > }
>> >
>> > /**
>> > @@ -770,8 +772,6 @@ static int axienet_device_reset(struct net_device
>> *ndev)
>> > * @first_bd: Index of first descriptor to clean up
>> > * @nr_bds: Max number of descriptors to clean up
>> > * @force: Whether to clean descriptors even if not complete
>> > - * @sizep: Pointer to a u32 filled with the total sum of all bytes
>> > - * in all cleaned-up descriptors. Ignored if NULL.
>> > * @budget: NAPI budget (use 0 when not called from NAPI poll)
>> > *
>> > * Would either be called after a successful transmit operation, or
>> > after @@ -780,7 +780,7 @@ static int axienet_device_reset(struct net_device
>> *ndev)
>> > * Return: The number of packets handled.
>> > */
>> > static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd,
>> > - int nr_bds, bool force, u32 *sizep, int budget)
>> > + int nr_bds, bool force, int budget)
>> > {
>> > struct axidma_bd *cur_p;
>> > unsigned int status;
>> > @@ -819,8 +819,8 @@ static int axienet_free_tx_chain(struct axienet_local
>> *lp, u32 first_bd,
>> > cur_p->cntrl = 0;
>> > cur_p->status = 0;
>> >
>> > - if (sizep)
>> > - *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> > + if (!force)
>> > + lp->tx_compl_bytes += status &
>> > + XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> > }
>> >
>> > if (!force) {
>> > @@ -999,18 +999,18 @@ static int axienet_tx_poll(struct napi_struct
>> > *napi, int budget) {
>> > struct axienet_local *lp = container_of(napi, struct axienet_local, napi_tx);
>> > struct net_device *ndev = lp->ndev;
>> > - u32 size = 0;
>> > int packets;
>> >
>> > packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, lp->tx_bd_num, false,
>> > - &size, budget);
>> > + budget);
>> >
>> > if (packets) {
>> > - netdev_completed_queue(ndev, packets, size);
>> > + netdev_completed_queue(ndev, packets,
>> > + lp->tx_compl_bytes);
>> > u64_stats_update_begin(&lp->tx_stat_sync);
>> > u64_stats_add(&lp->tx_packets, packets);
>> > - u64_stats_add(&lp->tx_bytes, size);
>> > + u64_stats_add(&lp->tx_bytes, lp->tx_compl_bytes);
>> > u64_stats_update_end(&lp->tx_stat_sync);
>> > + lp->tx_compl_bytes = 0;
>> >
>> > /* Matches barrier in axienet_start_xmit */
>> > smp_mb();
>> > @@ -1115,7 +1115,7 @@ axienet_start_xmit(struct sk_buff *skb, struct
>> net_device *ndev)
>> > netdev_err(ndev, "TX DMA mapping error\n");
>> > ndev->stats.tx_dropped++;
>> > axienet_free_tx_chain(lp, orig_tail_ptr, ii + 1,
>> > - true, NULL, 0);
>> > + true, 0);
>> > dev_kfree_skb_any(skb);
>> > return NETDEV_TX_OK;
>> > }
^ permalink raw reply
* Re: [PATCH v10 00/12] barrier: Add smp_cond_load_{relaxed,acquire}_timeout()
From: Catalin Marinas @ 2026-03-26 15:39 UTC (permalink / raw)
To: David Laight
Cc: Ankur Arora, Andrew Morton, linux-kernel, linux-arch,
linux-arm-kernel, linux-pm, bpf, arnd, will, peterz, mark.rutland,
harisokn, cl, ast, rafael, daniel.lezcano, memxor, zhenglifeng1,
xueshuai, rdunlap, joao.m.martins, boris.ostrovsky, konrad.wilk
In-Reply-To: <20260325202357.3e203314@pumpkin>
On Wed, Mar 25, 2026 at 08:23:57PM +0000, David Laight wrote:
> On Wed, 25 Mar 2026 16:32:49 +0000
> Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> > On Wed, Mar 25, 2026 at 03:42:10PM +0000, David Laight wrote:
> ...
> > > Looking at the code I think the "sevl; wfe" pair should be higher up.
> >
> > Yes, I replied to your other message. We could move it higher indeed,
> > before the condition check, but I can't get my head around the ordering.
> > Can need_resched() check be speculated before the WFE? I need to think
> > some more.
>
> I don't think speculation can matter.
> Both SEVL and WFE must be serialised against any other instructions
> that can change the event flag (as well as each other) otherwise
> everything is broken.
Welcome to the Arm memory model. We don't have any guarantee that an LDR
will only access memory after SEVL+WFE. They are not serialising.
> Apart from that it doesn't matter, what matters is the instruction
> boundary the interrupt happens at.
True. If an interrupt is taken before the LDR (that would be a
need_resched() check for example), then a prior WFE would not matter.
This won't work if we replace the IPI with a SEV though (suggested
somewhere in this thread).
> Actually both SEVL and WFE may be synchronising instructions and very slow.
Most likely not.
> So you may not want to put them in the fast path where the condition
> is true on entry (or even true after a retry).
> So the code might have to look like:
> for (;;) {
> VAL = mem;
If we only waited on the location passed to LDXR, things would have been
much simpler. But the osq_lock() also wants to wait on the TIF flags via
need_resched() (and vcpu_is_preempted()).
> if (cond(VAL)) return;
So the cond(VAL) here is actually a series of other memory loads
unrelated to 'mem'
> SEVL; WFE;
> if (cond(VAL)) return;
I think this will work in principle even if 'cond' accesses other memory
locations, though I wouldn't bother with an additional 'cond' call, I'd
expect SEVL+WFE to be mostly NOPs. However, 'cond' must not set a local
event, otherwise the power saving on waiting is gone.
> v1 = LDX(mem);
> if (v1 == VAL)
> WFE;
> }
I think it's cleaner to use Ankur's timeout API here for the very rare
case where an IPI hits at the wrong time. We then keep
smp_cond_load_relaxed() intact as it's really not meant to wait on
multiple memory locations to change. Any changes of
smp_cond_load_relaxed() with moving the WFE around are just hacks, not
the intended use of this API.
--
Catalin
^ permalink raw reply
* [PATCH v1 0/3] Add support for Variscite DART-MX93 and Sonata board
From: Stefano Radaelli @ 2026-03-26 15:47 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Dario Binacchi, Alexander Stein,
Maud Spierings, Josua Mayer, Markus Niebel, Francesco Dolcini,
Primoz Fiser
This patch series adds support for the Variscite DART-MX93 system on
module and the Sonata carrier board.
The series includes:
- SOM device tree with on-module peripherals
- Sonata carrier board device tree with board-specific features
The implementation follows the standard SOM + carrier board pattern
where the SOM dtsi contains only peripherals mounted on the module,
while carrier-specific interfaces are enabled in the board dts.
Stefano Radaelli (3):
dt-bindings: arm: fsl: add Variscite DART-MX93 Boards
arm64: dts: freescale: Add support for Variscite DART-MX93
arm64: dts: imx93-var-dart: Add support for Variscite Sonata board
.../devicetree/bindings/arm/fsl.yaml | 6 +
arch/arm64/boot/dts/freescale/Makefile | 1 +
.../dts/freescale/imx93-var-dart-sonata.dts | 654 ++++++++++++++++++
.../boot/dts/freescale/imx93-var-dart.dtsi | 462 +++++++++++++
4 files changed, 1123 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/imx93-var-dart-sonata.dts
create mode 100644 arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
base-commit: 6c4b48012d57f205c94f25da0c68a4027ea6daf6
--
2.47.3
^ permalink raw reply
* [PATCH v1 1/3] dt-bindings: arm: fsl: add Variscite DART-MX93 Boards
From: Stefano Radaelli @ 2026-03-26 15:47 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Dario Binacchi, Alexander Stein,
Maud Spierings, Josua Mayer, Markus Niebel, Francesco Dolcini,
Primoz Fiser
In-Reply-To: <cover.1774539301.git.stefano.r@variscite.com>
From: Stefano Radaelli <stefano.r@variscite.com>
Add DT compatible strings for Variscite DART-MX93 SoM and Variscite
development carrier Board.
Signed-off-by: Stefano Radaelli <stefano.r@variscite.com>
---
Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index da2be7114f64..77497a261fd5 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1587,6 +1587,12 @@ properties:
- const: variscite,var-dart-mx91 # Variscite DART-MX91 SOM
- const: fsl,imx91
+ - description: Variscite DART-MX93 based boards
+ items:
+ - const: variscite,var-dart-mx93-sonata # Variscite DART-MX93 on Sonata Development Board
+ - const: variscite,var-dart-mx93 # Variscite DART-MX93 SOM
+ - const: fsl,imx93
+
- description: Variscite VAR-SOM-MX93 based boards
items:
- const: variscite,var-som-mx93-symphony
--
2.47.3
^ permalink raw reply related
* [PATCH v1 2/3] arm64: dts: freescale: Add support for Variscite DART-MX93
From: Stefano Radaelli @ 2026-03-26 15:47 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Dario Binacchi, Alexander Stein,
Maud Spierings, Josua Mayer, Markus Niebel, Francesco Dolcini,
Primoz Fiser
In-Reply-To: <cover.1774539301.git.stefano.r@variscite.com>
From: Stefano Radaelli <stefano.r@variscite.com>
Add device tree support for the Variscite DART-MX93 system on module.
This SOM is designed to be used with various carrier boards.
The module includes:
- NXP i.MX93 MPU processor
- Up to 2GB of LPDDR4 memory
- Up to 128GB of eMMC storage memory
- Integrated 10/100/1000 Mbps Ethernet Transceiver
- Codec audio WM8904
- WIFI6 dual-band 802.11ax/ac/a/b/g/n with optional 802.15.4 and Bluetooth
Only SOM-specific peripherals are enabled by default. Carrier board
specific interfaces are left disabled to be enabled in the respective
carrier board device trees.
Link: https://variscite.com/system-on-module-som/i-mx-9/i-mx-93/dart-mx93/
Signed-off-by: Stefano Radaelli <stefano.r@variscite.com>
---
.../boot/dts/freescale/imx93-var-dart.dtsi | 462 ++++++++++++++++++
1 file changed, 462 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
diff --git a/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
new file mode 100644
index 000000000000..bfed6625f5ab
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Common dtsi for Variscite DART-MX93
+ *
+ * Link: https://variscite.com/system-on-module-som/i-mx-9/i-mx-93/dart-mx93/
+ *
+ * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/usb/pd.h>
+#include "imx93.dtsi"
+
+/ {
+ model = "Variscite DART-MX93 Module";
+ compatible = "variscite,var-dart-mx93", "fsl,imx93";
+
+ sound-wm8904 {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&codec_dai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&codec_dai>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,name = "wm8904-audio";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "IN1L", "Microphone Jack",
+ "IN1R", "Microphone Jack";
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Headphone", "Headphone Jack",
+ "Line", "Line In Jack";
+
+ codec_dai: simple-audio-card,codec {
+ sound-dai = <&wm8904>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai1>;
+ };
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ post-power-on-delay-ms = <100>;
+ power-off-delay-us = <10000>;
+ reset-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>, /* WIFI_RESET */
+ <&gpio3 7 GPIO_ACTIVE_LOW>; /* WIFI_PWR_EN */
+ };
+};
+
+&cm33 {
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&mu1 0 1>,
+ <&mu1 1 1>,
+ <&mu1 3 1>;
+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>,
+ <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>;
+ status = "okay";
+};
+
+&eqos {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_eqos>;
+ pinctrl-1 = <&pinctrl_eqos_sleep>;
+ /*
+ * The required RGMII TX and RX 2ns delays are implemented directly
+ * in hardware via passive delay elements on the SOM PCB.
+ * No delay configuration is needed in software via PHY driver.
+ */
+ phy-mode = "rgmii";
+ phy-handle = <ðphy0>;
+ snps,clk-csr = <5>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ clock-frequency = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <100000>;
+ };
+ };
+};
+
+&lpi2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "sleep", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c3>;
+ pinctrl-1 = <&pinctrl_lpi2c3_gpio>;
+ pinctrl-2 = <&pinctrl_lpi2c3_gpio>;
+ scl-gpios = <&gpio2 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ wm8904: audio-codec@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ clocks = <&clk IMX93_CLK_SAI1_GATE>;
+ clock-names = "mclk";
+ AVDD-supply = <&buck5>;
+ CPVDD-supply = <&buck5>;
+ DBVDD-supply = <&buck4>;
+ DCVDD-supply = <&buck5>;
+ MICVDD-supply = <&buck5>;
+ wlf,drc-cfg-names = "default", "peaklimiter", "tradition",
+ "soft", "music";
+ /*
+ * Config registers per name, respectively:
+ * KNEE_IP = 0, KNEE_OP = 0, HI_COMP = 1, LO_COMP = 1
+ * KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1
+ * KNEE_IP = -42, KNEE_OP = -3, HI_COMP = 0, LO_COMP = 1
+ * KNEE_IP = -45, KNEE_OP = -9, HI_COMP = 1/8, LO_COMP = 1
+ * KNEE_IP = -30, KNEE_OP = -10.5, HI_COMP = 1/4, LO_COMP = 1
+ */
+ wlf,drc-cfg-regs = /bits/ 16 <0x01af 0x3248 0x0000 0x0000>,
+ /bits/ 16 <0x04af 0x324b 0x0010 0x0408>,
+ /bits/ 16 <0x04af 0x324b 0x0028 0x0704>,
+ /bits/ 16 <0x04af 0x324b 0x0018 0x078c>,
+ /bits/ 16 <0x04af 0x324b 0x0010 0x050e>;
+ /* GPIO1 = DMIC_CLK, don't touch others */
+ wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>;
+ /* DMIC is connected to IN1L */
+ wlf,in1l-as-dmicdat1;
+ };
+
+ pmic@25 {
+ compatible = "nxp,pca9451a";
+ reg = <0x25>;
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-name = "BUCK1";
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <2237500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ };
+
+ buck2: BUCK2 {
+ regulator-name = "BUCK2";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <2187500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ };
+
+ buck4: BUCK4 {
+ regulator-name = "BUCK4";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5: BUCK5 {
+ regulator-name = "BUCK5";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6: BUCK6 {
+ regulator-name = "BUCK6";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1: LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "LDO4";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo5: LDO5 {
+ regulator-name = "LDO5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+/* BT module */
+&lpuart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>, <&pinctrl_bt>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "nxp,88w8987-bt";
+ };
+};
+
+&mu1 {
+ status = "okay";
+};
+
+&mu2 {
+ status = "okay";
+};
+
+&sai1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_sai1>;
+ pinctrl-1 = <&pinctrl_sai1_sleep>;
+ assigned-clocks = <&clk IMX93_CLK_SAI1>;
+ assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>;
+ assigned-clock-rates = <12288000>;
+ #sound-dai-cells = <0>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
+/* eMMC */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+/* WiFi */
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_wlan>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>, <&pinctrl_usdhc3_wlan>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>, <&pinctrl_usdhc3_wlan>;
+ pinctrl-3 = <&pinctrl_usdhc3_sleep>, <&pinctrl_usdhc3_wlan>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ keep-power-in-suspend;
+ bus-width = <4>;
+ non-removable;
+ wakeup-source;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX93_PAD_ENET2_MDIO__GPIO4_IO15 0x51e
+ >;
+ };
+
+ pinctrl_eqos: eqosgrp {
+ fsl,pins = <
+ MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e
+ MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e
+ MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e
+ MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e
+ MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e
+ MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e
+ MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x58e
+ MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e
+ MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e
+ MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e
+ MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e
+ MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e
+ MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e
+ MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e
+ MX93_PAD_UART2_TXD__GPIO1_IO07 0x51e
+ >;
+ };
+
+ pinctrl_eqos_sleep: eqos-sleepgrp {
+ fsl,pins = <
+ MX93_PAD_ENET1_MDC__GPIO4_IO00 0x31e
+ MX93_PAD_ENET1_MDIO__GPIO4_IO01 0x31e
+ MX93_PAD_ENET1_RD0__GPIO4_IO10 0x31e
+ MX93_PAD_ENET1_RD1__GPIO4_IO11 0x31e
+ MX93_PAD_ENET1_RD2__GPIO4_IO12 0x31e
+ MX93_PAD_ENET1_RD3__GPIO4_IO13 0x31e
+ MX93_PAD_ENET1_RXC__GPIO4_IO09 0x31e
+ MX93_PAD_ENET1_RX_CTL__GPIO4_IO08 0x31e
+ MX93_PAD_ENET1_TD0__GPIO4_IO05 0x31e
+ MX93_PAD_ENET1_TD1__GPIO4_IO04 0x31e
+ MX93_PAD_ENET1_TD2__GPIO4_IO03 0x31e
+ MX93_PAD_ENET1_TD3__GPIO4_IO02 0x31e
+ MX93_PAD_ENET1_TXC__GPIO4_IO07 0x31e
+ MX93_PAD_ENET1_TX_CTL__GPIO4_IO06 0x31e
+ >;
+ };
+
+ pinctrl_lpi2c3: lpi2c3grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e
+ MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e
+ >;
+ };
+
+ pinctrl_lpi2c3_gpio: lpi2c3gpiogrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO28__GPIO2_IO28 0x40000b9e
+ MX93_PAD_GPIO_IO29__GPIO2_IO29 0x40000b9e
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX93_PAD_SAI1_TXC__SAI1_TX_BCLK 0x31e
+ MX93_PAD_SAI1_TXFS__SAI1_TX_SYNC 0x31e
+ MX93_PAD_SAI1_TXD0__SAI1_TX_DATA00 0x31e
+ MX93_PAD_SAI1_RXD0__SAI1_RX_DATA00 0x31e
+ MX93_PAD_I2C2_SDA__SAI1_RX_BCLK 0x31e
+ MX93_PAD_I2C2_SCL__SAI1_RX_SYNC 0x31e
+ MX93_PAD_UART2_RXD__SAI1_MCLK 0x31e
+ >;
+ };
+
+ pinctrl_sai1_sleep: sai1-sleepgrp {
+ fsl,pins = <
+ MX93_PAD_SAI1_TXC__GPIO1_IO12 0x31e
+ MX93_PAD_SAI1_TXFS__GPIO1_IO11 0x31e
+ MX93_PAD_SAI1_TXD0__GPIO1_IO13 0x31e
+ MX93_PAD_SAI1_RXD0__GPIO1_IO14 0x31e
+ MX93_PAD_UART2_RXD__GPIO1_IO06 0x31e
+ MX93_PAD_I2C2_SDA__GPIO1_IO03 0x31e
+ MX93_PAD_I2C2_SCL__GPIO1_IO02 0x31e
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e
+ MX93_PAD_DAP_TDI__LPUART5_RX 0x31e
+ MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e
+ MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582
+ MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382
+ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382
+ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382
+ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382
+ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382
+ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382
+ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382
+ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382
+ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382
+ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e
+ MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e
+ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e
+ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e
+ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e
+ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e
+ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e
+ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e
+ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e
+ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e
+ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe
+ MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe
+ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe
+ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe
+ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe
+ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe
+ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe
+ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe
+ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe
+ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe
+ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX93_PAD_SD3_CLK__USDHC3_CLK 0x1582
+ MX93_PAD_SD3_CMD__USDHC3_CMD 0x40001382
+ MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x40001382
+ MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x40001382
+ MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x40001382
+ MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x40001382
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD3_CLK__USDHC3_CLK 0x158e
+ MX93_PAD_SD3_CMD__USDHC3_CMD 0x4000138e
+ MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x4000138e
+ MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x4000138e
+ MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x4000138e
+ MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x4000138e
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD3_CLK__USDHC3_CLK 0x15fe
+ MX93_PAD_SD3_CMD__USDHC3_CMD 0x400013fe
+ MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x400013fe
+ MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x400013fe
+ MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x400013fe
+ MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x400013fe
+ >;
+ };
+
+ pinctrl_usdhc3_sleep: usdhc3-sleepgrp {
+ fsl,pins = <
+ MX93_PAD_SD3_CLK__GPIO3_IO20 0x400
+ MX93_PAD_SD3_CMD__GPIO3_IO21 0x400
+ MX93_PAD_SD3_DATA0__GPIO3_IO22 0x400
+ MX93_PAD_SD3_DATA1__GPIO3_IO23 0x400
+ MX93_PAD_SD3_DATA2__GPIO3_IO24 0x400
+ MX93_PAD_SD3_DATA3__GPIO3_IO25 0x400
+ >;
+ };
+
+ pinctrl_usdhc3_wlan: usdhc3wlangrp {
+ fsl,pins = <
+ MX93_PAD_ENET2_MDC__GPIO4_IO14 0x51e
+ MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x51e
+ >;
+ };
+};
--
2.47.3
^ permalink raw reply related
* [PATCH v1 3/3] arm64: dts: imx93-var-dart: Add support for Variscite Sonata board
From: Stefano Radaelli @ 2026-03-26 15:47 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Dario Binacchi, Alexander Stein,
Maud Spierings, Josua Mayer, Markus Niebel, Francesco Dolcini,
Primoz Fiser
In-Reply-To: <cover.1774539301.git.stefano.r@variscite.com>
From: Stefano Radaelli <stefano.r@variscite.com>
Add device tree support for the Variscite Sonata carrier board with the
DART-MX93 system on module.
The Sonata board includes
- uSD Card support
- USB ports and OTG
- Additional Gigabit Ethernet interface
- Uart, SPI and I2C interfaces
- GPIO Expanders
- RTC module
- TPM module
- CAN peripherals
Link: https://variscite.com/carrier-boards/sonata-board/
Signed-off-by: Stefano Radaelli <stefano.r@variscite.com>
---
arch/arm64/boot/dts/freescale/Makefile | 1 +
.../dts/freescale/imx93-var-dart-sonata.dts | 654 ++++++++++++++++++
2 files changed, 655 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/imx93-var-dart-sonata.dts
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 2da6dc4f8a14..266eddd745c9 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -487,6 +487,7 @@ imx93-tqma9352-mba91xxca-rgb-cdtech-dc44-dtbs := imx93-tqma9352-mba91xxca.dtb im
dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba91xxca-lvds-tm070jvhg33.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba91xxca-rgb-cdtech-dc44.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx93-var-dart-sonata.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93w-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx943-evk.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx93-var-dart-sonata.dts b/arch/arm64/boot/dts/freescale/imx93-var-dart-sonata.dts
new file mode 100644
index 000000000000..5513d3b148a2
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-var-dart-sonata.dts
@@ -0,0 +1,654 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Variscite Sonata carrier board for DART-MX93
+ *
+ * Link: https://variscite.com/carrier-boards/sonata-board/
+ *
+ * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "imx93-var-dart.dtsi"
+
+/ {
+ model = "Variscite DART-MX93 on Sonata-Board";
+ compatible = "variscite,var-dart-mx93-sonata",
+ "variscite,var-dart-mx93",
+ "fsl,imx93";
+
+ aliases {
+ ethernet0 = &eqos;
+ ethernet1 = &fec;
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ i2c0 = &lpi2c1;
+ i2c1 = &lpi2c2;
+ i2c2 = &lpi2c3;
+ i2c3 = &lpi2c4;
+ i2c4 = &lpi2c5;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ serial0 = &lpuart1;
+ serial1 = &lpuart2;
+ serial2 = &lpuart3;
+ serial3 = &lpuart4;
+ serial4 = &lpuart5;
+ serial5 = &lpuart6;
+ serial6 = &lpuart7;
+ };
+
+ chosen {
+ stdout-path = &lpuart1;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home";
+ linux,code = <KEY_HOME>;
+ gpios = <&pca6408_1 4 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ button-up {
+ label = "Up";
+ linux,code = <KEY_UP>;
+ gpios = <&pca6408_1 5 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ button-down {
+ label = "Down";
+ linux,code = <KEY_DOWN>;
+ gpios = <&pca6408_1 6 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ button-back {
+ label = "Back";
+ linux,code = <KEY_BACK>;
+ gpios = <&pca6408_1 7 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_leds_gpio>;
+
+ led-emmc {
+ gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ label = "eMMC";
+ linux,default-trigger = "mmc0";
+ };
+ };
+
+ clk40m: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <40000000>;
+ clock-output-names = "can_osc";
+ };
+
+ reg_vref_1v8: regulator-adc-vref {
+ compatible = "regulator-fixed";
+ regulator-name = "vref_1v8";
+ regulator-max-microvolt = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ };
+
+ reg_usdhc2_vmmc: regulator-vmmc-usdhc2 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_SD2_3V3";
+ off-on-delay-us = <20000>;
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ pinctrl-names = "default";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ gpio = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ethosu_mem: ethosu-region@88000000 {
+ compatible = "shared-dma-pool";
+ reusable;
+ reg = <0x0 0x88000000 0x0 0x8000000>;
+ };
+
+ vdev0vring0: vdev0vring0@87ee0000 {
+ reg = <0 0x87ee0000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@87ee8000 {
+ reg = <0 0x87ee8000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: vdev1vring0@87ef0000 {
+ reg = <0 0x87ef0000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: vdev1vring1@87ef8000 {
+ reg = <0 0x87ef8000 0 0x8000>;
+ no-map;
+ };
+
+ rsc_table: rsc-table@2021e000 {
+ reg = <0 0x2021e000 0 0x1000>;
+ no-map;
+ };
+
+ vdevbuffer: vdevbuffer@87f00000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x87f00000 0 0x100000>;
+ no-map;
+ };
+
+ ele_reserved: ele-reserved@87de0000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x87de0000 0 0x100000>;
+ no-map;
+ };
+ };
+};
+
+&adc1 {
+ vref-supply = <®_vref_1v8>;
+ status = "okay";
+};
+
+/* Use external instead of internal RTC */
+&bbnsm_rtc {
+ status = "disabled";
+};
+
+&eqos {
+ mdio {
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ reset-assert-us = <15000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&pca6408_2 0 GPIO_ACTIVE_LOW>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ linux,default-trigger = "netdev";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ linux,default-trigger = "netdev";
+ };
+ };
+ };
+ };
+};
+
+ðphy0 {
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ linux,default-trigger = "netdev";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ linux,default-trigger = "netdev";
+ };
+ };
+};
+
+&fec {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_fec>;
+ pinctrl-1 = <&pinctrl_fec_sleep>;
+ /*
+ * The required RGMII TX and RX 2ns delays are implemented directly
+ * in hardware via passive delay elements on the SOM PCB.
+ * No delay configuration is needed in software via PHY driver.
+ */
+ phy-mode = "rgmii";
+ phy-handle = <ðphy1>;
+ status = "okay";
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "okay";
+};
+
+&lpi2c1 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&pinctrl_lpi2c1>;
+ pinctrl-1 = <&pinctrl_lpi2c1_gpio>;
+ pinctrl-2 = <&pinctrl_lpi2c1_gpio>;
+ pinctrl-names = "default", "sleep", "gpio";
+ scl-gpios = <&gpio1 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ pca9534: gpio@22 {
+ compatible = "nxp,pca9534";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ /* Capacitive touch controller */
+ ft5x06_ts: touchscreen@38 {
+ compatible = "edt,edt-ft5206";
+ reg = <0x38>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-0 = <&pinctrl_captouch>;
+ pinctrl-names = "default";
+ reset-gpios = <&pca6408_2 4 GPIO_ACTIVE_LOW>;
+ touchscreen-inverted-x;
+ touchscreen-inverted-y;
+ touchscreen-size-x = <800>;
+ touchscreen-size-y = <480>;
+ wakeup-source;
+ };
+
+ /* USB Type-C Controller */
+ typec@3d {
+ compatible = "nxp,ptn5150";
+ reg = <0x3d>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <29 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&pinctrl_extcon>;
+ pinctrl-names = "default";
+
+ port {
+ typec1_dr_sw: endpoint {
+ remote-endpoint = <&usb1_drd_sw>;
+ };
+ };
+ };
+
+ rtc@68 {
+ compatible = "dallas,ds1337";
+ reg = <0x68>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rtc>;
+ wakeup-source;
+ };
+};
+
+&lpi2c5 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "sleep", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c5>;
+ pinctrl-1 = <&pinctrl_lpi2c5_gpio>;
+ pinctrl-2 = <&pinctrl_lpi2c5_gpio>;
+ scl-gpios = <&gpio2 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+&lpi2c7 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "sleep", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c7>;
+ pinctrl-1 = <&pinctrl_lpi2c7_gpio>;
+ pinctrl-2 = <&pinctrl_lpi2c7_gpio>;
+ scl-gpios = <&gpio2 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ pca6408_1: gpio@20 {
+ compatible = "nxp,pcal6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pca6408_2: gpio@21 {
+ compatible = "nxp,pcal6408";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ st33ktpm2xi2c: tpm@2e {
+ compatible = "st,st33ktpm2xi2c", "tcg,tpm-tis-i2c";
+ reg = <0x2e>;
+ };
+};
+
+&lpspi8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi8>;
+ cs-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ /* CAN controller */
+ can0: can@0 {
+ compatible = "microchip,mcp251xfd";
+ reg = <0>;
+ clocks = <&clk40m>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can>;
+ spi-max-frequency = <1000000>;
+ };
+};
+
+/* Console (J10) */
+&lpuart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+/* Header (J12.4, J12.6) */
+&lpuart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart6>;
+ status = "okay";
+};
+
+/* Header (J12.11, J12.13) */
+&lpuart7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart7>;
+ status = "okay";
+};
+
+&tpm3 {
+ pinctrl-0 = <&pinctrl_tpm3>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&typec1_dr_sw>;
+ };
+ };
+};
+
+&usbotg2 {
+ disable-over-current;
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* SD */
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <®_usdhc2_vmmc>;
+ bus-width = <4>;
+ no-sdio;
+ no-mmc;
+ status = "okay";
+};
+
+&wdog3 {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_can: cangrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO03__GPIO2_IO03 0x31e
+ >;
+ };
+
+ pinctrl_captouch: captouchgrp {
+ fsl,pins = <
+ MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e
+ >;
+ };
+
+ pinctrl_extcon: extcongrp {
+ fsl,pins = <
+ MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x31e
+ >;
+ };
+
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e
+ MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e
+ MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e
+ MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x37e
+ MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x58e
+ MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e
+ MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e
+ MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e
+ MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e
+ MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e
+ MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x58e
+ MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e
+ >;
+ };
+
+ pinctrl_fec_sleep: fecsleepgrp {
+ fsl,pins = <
+ MX93_PAD_ENET2_RD0__GPIO4_IO24 0x51e
+ MX93_PAD_ENET2_RD1__GPIO4_IO25 0x51e
+ MX93_PAD_ENET2_RD2__GPIO4_IO26 0x51e
+ MX93_PAD_ENET2_RD3__GPIO4_IO27 0x51e
+ MX93_PAD_ENET2_RXC__GPIO4_IO23 0x51e
+ MX93_PAD_ENET2_RX_CTL__GPIO4_IO22 0x51e
+ MX93_PAD_ENET2_TD0__GPIO4_IO19 0x51e
+ MX93_PAD_ENET2_TD1__GPIO4_IO18 0x51e
+ MX93_PAD_ENET2_TD2__GPIO4_IO17 0x51e
+ MX93_PAD_ENET2_TD3__GPIO4_IO16 0x51e
+ MX93_PAD_ENET2_TXC__GPIO4_IO21 0x51e
+ MX93_PAD_ENET2_TX_CTL__GPIO4_IO20 0x51e
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX93_PAD_PDM_CLK__CAN1_TX 0x139e
+ MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x139e
+ >;
+ };
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* GPIO Expanders shared IRQ */
+ MX93_PAD_PDM_BIT_STREAM1__GPIO1_IO10 0x31e
+ >;
+ };
+
+ pinctrl_leds_gpio: ledgrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO11__GPIO2_IO11 0x31e
+ >;
+ };
+
+ pinctrl_lpi2c1: lpi2c1grp {
+ fsl,pins = <
+ MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e
+ MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e
+ >;
+ };
+
+ pinctrl_lpi2c1_gpio: lpi2c1-gpiogrp {
+ fsl,pins = <
+ MX93_PAD_I2C1_SCL__GPIO1_IO00 0x31e
+ MX93_PAD_I2C1_SDA__GPIO1_IO01 0x31e
+ >;
+ };
+
+ pinctrl_lpi2c5: lpi2c5grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO22__LPI2C5_SDA 0x40000b9e
+ MX93_PAD_GPIO_IO23__LPI2C5_SCL 0x40000b9e
+ >;
+ };
+
+ pinctrl_lpi2c5_gpio: lpi2c5-gpiogrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO22__GPIO2_IO22 0x31e
+ MX93_PAD_GPIO_IO23__GPIO2_IO23 0x31e
+ >;
+ };
+
+ pinctrl_lpi2c7: lpi2c7grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO07__LPI2C7_SCL 0x40000b9e
+ MX93_PAD_GPIO_IO06__LPI2C7_SDA 0x40000b9e
+ >;
+ };
+
+ pinctrl_lpi2c7_gpio: lpi2c7-gpiogrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO07__GPIO2_IO07 0x31e
+ MX93_PAD_GPIO_IO06__GPIO2_IO06 0x31e
+ >;
+ };
+
+ pinctrl_lpspi8: lpspi8grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO00__GPIO2_IO00 0x31e
+ MX93_PAD_GPIO_IO01__GPIO2_IO01 0x31e
+ MX93_PAD_GPIO_IO12__GPIO2_IO12 0x31e
+ MX93_PAD_GPIO_IO13__LPSPI8_SIN 0x31e
+ MX93_PAD_GPIO_IO14__LPSPI8_SOUT 0x31e
+ MX93_PAD_GPIO_IO15__LPSPI8_SCK 0x31e
+ >;
+ };
+
+ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
+ fsl,pins = <
+ MX93_PAD_CCM_CLKO3__GPIO4_IO28 0x31e
+ >;
+ };
+
+ pinctrl_rtc: rtcgrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO02__GPIO2_IO02 0x31e
+ >;
+ };
+
+ pinctrl_tpm3: tpm3grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO24__TPM3_CH3 0x51e
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX93_PAD_UART1_RXD__LPUART1_RX 0x31e
+ MX93_PAD_UART1_TXD__LPUART1_TX 0x31e
+ >;
+ };
+
+ pinctrl_uart6: uart6grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO05__LPUART6_RX 0x31e
+ MX93_PAD_GPIO_IO04__LPUART6_TX 0x31e
+ >;
+ };
+
+ pinctrl_uart7: uart7grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO09__LPUART7_RX 0x31e
+ MX93_PAD_GPIO_IO08__LPUART7_TX 0x31e
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582
+ MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382
+ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382
+ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382
+ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382
+ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382
+ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e
+ MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e
+ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e
+ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e
+ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e
+ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e
+ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe
+ MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe
+ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe
+ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe
+ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe
+ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe
+ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e
+ >;
+ };
+};
--
2.47.3
^ permalink raw reply related
* Re: Clear CLKREQ# override breaks functionality
From: Franz Schnyder @ 2026-03-26 15:52 UTC (permalink / raw)
To: Hongxing Zhu
Cc: Franz Schnyder, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev,
linux-kernel@vger.kernel.org, Francesco Dolcini,
Manivannan Sadhasivam, Frank Li
In-Reply-To: <AS8PR04MB8833063C53B769C0ACB086958C56A@AS8PR04MB8833.eurprd04.prod.outlook.com>
On Thu, Mar 26, 2026 at 08:17:29AM +0000, Hongxing Zhu wrote:
> > -----Original Message-----
> > From: Franz Schnyder <fra.schnyder@gmail.com>
> > Sent: 2026年3月26日 16:00
> > To: Hongxing Zhu <hongxing.zhu@nxp.com>
> > Cc: Franz Schnyder <franz.schnyder@toradex.com>;
> > linux-pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > imx@lists.linux.dev; linux-kernel@vger.kernel.org; Francesco Dolcini
> > <francesco@dolcini.it>; Manivannan Sadhasivam <mani@kernel.org>; Frank
> > Li <frank.li@nxp.com>
> > Subject: Clear CLKREQ# override breaks functionality
> >
> > Hi Richard,
> >
> > While integrating the `supports-clkreq` DT property on our iMX95-based
> > SoM, we had failures in our CI on one of the two M.2 PCIe slots on our
> > development board.
> > The failing slot uses a card that does not advertise L1 PM substates.
> > This issue comes from commit a152a90f5390 ("PCI: imx6: Clear CLKREQ#
> > override if 'supports-clkreq' DT property is available"), which clears the
> > CLKREQ# override based only on the DT property.
> >
> > It seems that clearing the CLKREQ# override should happen only when the
> > driver knows that the downstream device advertises L1 PM Substates.
> > Otherwise CLKREQ# should remain asserted to keep compatibility with cards
> > that do not support L1 PM Substates.
> >
> > Thoughts?
> Hi Franz:
> No, CLKREQ# is not dependent on L1 PM Substates capabilities.
>
> According to the PCI Express Card Electromechanical Specification r6.0,
> Section 2 (Auxiliary Signals):
>
> "CLKREQ# (optional) signal is an open drain, active low signal that is driven
> low by the card to request that the PCI Express reference clock be available
> (active clock state) to allow the PCI Express interface to send/receive data."
>
> When the 'supports-clkreq' property is present, it indicates that the endpoint
> device supports CLKREQ# signaling and will actively drive the signal low when
> it needs the reference clock.
>
> Therefore, the RC (Root Complex) controller can safely clear any CLKREQ#
> active-low override settings, allowing the endpoint to control the clock
> request through proper CLKREQ# signaling.
>
> If the endpoint devices on your platform can't drive the CLKREQ# signal to
> low, remove 'supports-clkreq' property from your board's device tree file.
>
> Best Regards
> Richard Zhu
> >
> > Kind Regards
> >
> > Franz
Hi Richard,
Thanks for the explanation. I managed to find a PCIe specification, and
I can now see that my assumption was wrong. The L1 PM Substates mechanism
requires CLKREQ#, but not vice versa. To be safe with cards which lack
support, we'll just remove the 'supports-clkreq' property for now.
Kind regards
Franz
^ permalink raw reply
* Re: [PATCH net-next v4 1/2] net: stmmac: provide flag to disable EEE
From: Laurent Pinchart @ 2026-03-26 15:53 UTC (permalink / raw)
To: netdev, imx
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Fabio Estevam,
Francesco Dolcini, Frank Li, Jakub Kicinski, Joy Zou,
Kieran Bingham, Marco Felsch, Paolo Abeni,
Pengutronix Kernel Team, Russell King (Oracle), Stefan Klug,
linux-arm-kernel
In-Reply-To: <20260325210003.2752013-2-laurent.pinchart@ideasonboard.com>
On Wed, Mar 25, 2026 at 11:00:02PM +0200, Laurent Pinchart wrote:
> From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
>
> Some platforms have problems when EEE is enabled, and thus need a way
> to disable stmmac EEE support. Add a flag before the other LPI related
> flags which tells stmmac to avoid populating the phylink LPI
> capabilities, which causes phylink to call phy_disable_eee() for any
> PHY that is attached to the affected phylink instance.
>
> iMX8MP is an example - the lpi_intr_o signal is wired to an OR gate
> along with the main dwmac interrupts. Since lpi_intr_o is synchronous
> to the receive clock domain, and takes four clock cycles to clear, this
> leads to interrupt storms as the interrupt remains asserted for some
> time after the LPI control and status register is read.
>
> This problem becomes worse when the receive clock from the PHY stops
> when the receive path enters LPI state - which means that lpi_intr_o
> can not deassert until the clock restarts. Since the LPI state of the
> receive path depends on the link partner, this is out of our control.
> We could disable RX clock stop at the PHY, but that doesn't get around
> the slow-to-deassert lpi_intr_o mentioned in the above paragraph.
>
> Previously, iMX8MP worked around this by disabling gigabit EEE, but
> this is insufficient - the problem is also visible at 100M speeds,
> where the receive clock is slower.
>
> There is extensive discussion and investigation in the thread linked
> below, the result of which is summarised in this commit message.
>
> Reported-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Closes: https://lore.kernel.org/r/20251026122905.29028-1-laurent.pinchart@ideasonboard.com
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
> Tested-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
And I just realized I haven't sent an R-b tag, despite having reviewed
the patch.
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 7 ++++++-
> include/linux/stmmac.h | 13 +++++++------
> 2 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 9b6b49331639..ce51b9c22129 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1438,7 +1438,12 @@ static int stmmac_phylink_setup(struct stmmac_priv *priv)
> config->supported_interfaces,
> pcs->supported_interfaces);
>
> - if (priv->dma_cap.eee) {
> + /* Some platforms, e.g. iMX8MP, wire lpi_intr_o to the same interrupt
> + * used for stmmac's main interrupts, which leads to interrupt storms.
> + * STMMAC_FLAG_EEE_DISABLE allows EEE to be disabled on such platforms.
> + */
> + if (priv->dma_cap.eee &&
> + !(priv->plat->flags & STMMAC_FLAG_EEE_DISABLE)) {
> /* The GMAC 3.74a databook states that EEE is only supported
> * in MII, GMII, and RGMII interfaces.
> */
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 5b2bece81448..e62d21afd56d 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -207,12 +207,13 @@ enum dwmac_core_type {
> #define STMMAC_FLAG_MULTI_MSI_EN BIT(7)
> #define STMMAC_FLAG_EXT_SNAPSHOT_EN BIT(8)
> #define STMMAC_FLAG_INT_SNAPSHOT_EN BIT(9)
> -#define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI BIT(10)
> -#define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING BIT(11)
> -#define STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP BIT(12)
> -#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY BIT(13)
> -#define STMMAC_FLAG_KEEP_PREAMBLE_BEFORE_SFD BIT(14)
> -#define STMMAC_FLAG_SERDES_SUPPORTS_2500M BIT(15)
> +#define STMMAC_FLAG_EEE_DISABLE BIT(10)
> +#define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI BIT(11)
> +#define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING BIT(12)
> +#define STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP BIT(13)
> +#define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY BIT(14)
> +#define STMMAC_FLAG_KEEP_PREAMBLE_BEFORE_SFD BIT(15)
> +#define STMMAC_FLAG_SERDES_SUPPORTS_2500M BIT(16)
>
> struct mac_device_info;
>
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: (subset) [PATCH v10 0/5] Add MIPI CSI-2 support for i.MX8ULP
From: Frank Li @ 2026-03-26 15:57 UTC (permalink / raw)
To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Philipp Zabel,
Guoniu Zhou
Cc: linux-media, devicetree, imx, linux-arm-kernel, linux-kernel,
Conor Dooley
In-Reply-To: <177453839102.4969.6512848643800500076.b4-ty@nxp.com>
On Thu, Mar 26, 2026 at 11:20:54AM -0400, Frank Li wrote:
>
> On Fri, 05 Dec 2025 17:07:42 +0800, Guoniu Zhou wrote:
> > The serial adds MIPI CSI-2 support for i.MX8ULP.
> >
> >
>
> Applied, thanks!
>
> [5/5] arm64: dts: imx8ulp: Add CSI and ISI Nodes
> commit: 73f3ca0f85285b2fc4ea05affb9a44bf899cd595
>
> Add extra empty line between reg and child node.
Guoniu Zhou:
I have to drop this one because miss <dt-bindings/reset/imx8ulp-pcc-reset.h>
Do you miss some dependence?
Frank
>
> Best regards,
> --
> Frank Li <Frank.Li@nxp.com>
^ permalink raw reply
* Re: [PATCH] arm64: dts: qcom: sm8750-mtp: Set sufficient voltage for panel nt37801
From: Bjorn Andersson @ 2026-03-26 15:58 UTC (permalink / raw)
To: Ayushi Makhija
Cc: konrad.dybcio, robh+dt, krzysztof.kozlowski+dt, conor+dt,
dmitry.baryshkov, linux-arm-msm, devicetree, linux-kernel,
linux-arm-kernel, quic_rajeevny, quic_vproddut
In-Reply-To: <ccb11c2a-4cf1-4486-be71-d4bcc983cee6@quicinc.com>
On Thu, Mar 26, 2026 at 03:06:52PM +0530, Ayushi Makhija wrote:
> On 3/24/2026 7:34 AM, Bjorn Andersson wrote:
> > On Mon, Mar 23, 2026 at 03:52:29PM +0530, Ayushi Makhija wrote:
> >> The NT37801 Sepc V1.0 chapter "5.7.1 Power On Sequence" states
> >> VDDI=1.65V~1.95V, so set sufficient voltage for panel nt37801.
> >>
> >
> > Please add Fixes: tag.
> >
>
> Hi Bjorn,
>
> Sure, will add in new patchset.
>
> >> Signed-off-by: Ayushi Makhija <quic_amakhija@quicinc.com>
> >
> > Please start using your oss.qualcomm.com address.
> >
> >> ---
> >> arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 2 +-
> >> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
> >> index 3837f6785320..6ba4e69bf377 100644
> >> --- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
> >> +++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts
> >> @@ -462,7 +462,7 @@ vreg_l11b_1p0: ldo11 {
> >>
> >> vreg_l12b_1p8: ldo12 {
> >> regulator-name = "vreg_l12b_1p8";
> >> - regulator-min-microvolt = <1200000>;
> >> + regulator-min-microvolt = <1650000>;
> >
> > Are you sure it's not supposed to be 1.8V, given the name of the rail?
> >
> > Regards,
> > Bjorn
>
> There was already discussion regarding the minimum voltage for this regulator on sm8550 target
> on other upstream patch.
>
> Link: https://lore.kernel.org/all/aQQdQoCLeKhYtY7W@yuanjiey.ap.qualcomm.com/
>
> This values is according to the NT37801 panel sec
> "The NT37801 Sepc V1.0 chapter "5.7.1 Power On Sequence" states
> VDDI=1.65V~1.95V."
>
Yes, so the panel requires 1.65V, so regulator-min-microvolt needs to be
at least that. But regulator-min-microvolt should account for all the
consumers of the rail, are there any others?
Which leads me to my question, the people designing the board named the
rail VREG_L12B_1P8 in the schematics, why didn't they name it
VREG_L12B_1P65?
Please check all the consumers and make the regulator-min-microvolt work
for all of them - if that's 1.65V, then your change is good.
Regards,
Bjorn
> Thanks,
> Ayushi
>
> >> regulator-max-microvolt = <1800000>;
> >> regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
> >> regulator-allow-set-load;
> >> --
> >> 2.34.1
> >>
>
^ permalink raw reply
* Re: [PATCH v2] irqchip/gic-v3: Print a warning for out-of-range interrupt numbers
From: Marc Zyngier @ 2026-03-26 16:00 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Thomas Gleixner, linux-arm-kernel, linux-renesas-soc,
linux-kernel
In-Reply-To: <ce695ea46decc816974179314a86f2b9b5cad6a9.1772799134.git.geert+renesas@glider.be>
On Fri, 06 Mar 2026 12:13:32 +0000,
Geert Uytterhoeven <geert+renesas@glider.be> wrote:
>
> gic_irq_domain_translate() does not check if an interrupt number lies
> within the valid range of the specified interrupt type. Add these
> checks, and print a warning if the interrupt number is out of range.
>
> This can help flagging incorrectly described Extended SPI and PPI
> interrupts in DT.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> This would have prevented the issue fixed by "[PATCH] arm64: dts:
> renesas: r8a78000: Fix out-of-range SPI interrupt numbers"[1].
>
> v2:
> - Fix off-by-one error in PPI range check.
>
> [1] https://lore.kernel.org/1f9dd274720ea1b66617a5dd84f76c3efc829dc8.1772641415.git.geert+renesas@glider.be/
> ---
> drivers/irqchip/irq-gic-v3.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 20f13b686ab22faf..9e97505d4b767043 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -1603,15 +1603,27 @@ static int gic_irq_domain_translate(struct irq_domain *d,
>
> switch (fwspec->param[0]) {
> case 0: /* SPI */
> + if (fwspec->param[1] > 987)
> + pr_warn_once("SPI %u out of range (use ESPI?)\n",
> + fwspec->param[1]);
> *hwirq = fwspec->param[1] + 32;
> break;
> case 1: /* PPI */
> + if (fwspec->param[1] > 15)
> + pr_warn_once("PPI %u out of range (use EPPI?)\n",
> + fwspec->param[1]);
> *hwirq = fwspec->param[1] + 16;
> break;
> case 2: /* ESPI */
> + if (fwspec->param[1] > 1023)
> + pr_warn_once("ESPI %u out of range\n",
> + fwspec->param[1]);
> *hwirq = fwspec->param[1] + ESPI_BASE_INTID;
> break;
> case 3: /* EPPI */
> + if (fwspec->param[1] > 63)
> + pr_warn_once("EPPI %u out of range\n",
> + fwspec->param[1]);
> *hwirq = fwspec->param[1] + EPPI_BASE_INTID;
> break;
> case GIC_IRQ_TYPE_LPI: /* LPI */
Acked-by: Marc Zyngier <maz@kernel.org>
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v11 2/3] of: Factor arguments passed to of_map_id() into a struct
From: Bjorn Helgaas @ 2026-03-26 16:19 UTC (permalink / raw)
To: Vijayanand Jitta, Richard Zhu, Lucas Stach
Cc: Nipun Gupta, Nikhil Agarwal, Joerg Roedel, Will Deacon,
Robin Murphy, Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner,
Saravana Kannan, Krzysztof Wilczyński, Manivannan Sadhasivam,
Bjorn Helgaas, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, Dmitry Baryshkov, Konrad Dybcio,
Bjorn Andersson, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
Prakash Gupta, Vikash Garodia, linux-kernel, iommu,
linux-arm-kernel, devicetree, linux-pci, imx, xen-devel,
linux-arm-msm, Charan Teja Kalla
In-Reply-To: <20260325-parse_iommu_cells-v11-2-1fefa5c0e82c@oss.qualcomm.com>
[cc->to: Richard, Lucas for pci-imx6.c question]
On Wed, Mar 25, 2026 at 04:38:23PM +0530, Vijayanand Jitta wrote:
> From: Charan Teja Kalla <charan.kalla@oss.qualcomm.com>
>
> Change of_map_id() to take a pointer to struct of_phandle_args
> instead of passing target device node and translated IDs separately.
> Update all callers accordingly.
>
> Add an explicit filter_np parameter to of_map_id() and of_map_msi_id()
> to separate the filter input from the output. Previously, the target
> parameter served dual purpose: as an input filter (if non-NULL, only
> match entries targeting that node) and as an output (receiving the
> matched node with a reference held). Now filter_np is the explicit
> input filter and arg->np is the pure output.
>
> Previously, of_map_id() would call of_node_put() on the matched node
> when a filter was provided, making reference ownership inconsistent.
> Remove this internal of_node_put() call so that of_map_id() now always
> transfers ownership of the matched node reference to the caller via
> arg->np. Callers are now consistently responsible for releasing this
> reference with of_node_put(arg->np) when done.
> ...
Not actually part of *this* patch, and AFAICS this patch is correct
as-is, but is it necessary to have different logic around
of_node_put() for imx_pcie_add_lut_by_rid() and
apple_pcie_enable_device()?
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1137,6 +1137,8 @@ static void imx_pcie_remove_lut(struct imx_pcie *imx_pcie, u16 rid)
>
> static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
> {
> + struct of_phandle_args iommu_spec = {};
> + struct of_phandle_args msi_spec = {};
> struct device *dev = imx_pcie->pci->dev;
> struct device_node *target;
> u32 sid_i, sid_m;
> @@ -1144,7 +1146,12 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
> u32 sid = 0;
>
> target = NULL;
> - err_i = of_map_iommu_id(dev->of_node, rid, &target, &sid_i);
> + err_i = of_map_iommu_id(dev->of_node, rid, &iommu_spec);
> + if (!err_i) {
> + target = iommu_spec.np;
> + sid_i = iommu_spec.args[0];
> + }
> +
> if (target) {
> of_node_put(target);
Here it's conditional on "target" even though of_node_put() checks
internally for non-NULL, so it would be safe without the conditional
here.
> } else {
> @@ -1156,8 +1163,11 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
> err_i = -EINVAL;
> }
>
> - target = NULL;
> - err_m = of_map_msi_id(dev->of_node, rid, &target, &sid_m);
> + err_m = of_map_msi_id(dev->of_node, rid, NULL, &msi_spec);
> + if (!err_m) {
> + target = msi_spec.np;
> + sid_m = msi_spec.args[0];
> + }
>
> /*
> * err_m target
And here (outside the diff context) we also call of_node_put()
conditionally:
...
else if (target)
of_node_put(target);
> diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
> index a0937b7b3c4d..c2cffc0659f4 100644
> --- a/drivers/pci/controller/pcie-apple.c
> +++ b/drivers/pci/controller/pcie-apple.c
> @@ -755,6 +755,7 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
> {
> u32 sid, rid = pci_dev_id(pdev);
> struct apple_pcie_port *port;
> + struct of_phandle_args iommu_spec = {};
> int idx, err;
>
> port = apple_pcie_get_port(pdev);
> @@ -764,10 +765,12 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
> dev_dbg(&pdev->dev, "added to bus %s, index %d\n",
> pci_name(pdev->bus->self), port->idx);
>
> - err = of_map_iommu_id(port->pcie->dev->of_node, rid, NULL, &sid);
> + err = of_map_iommu_id(port->pcie->dev->of_node, rid, &iommu_spec);
> if (err)
> return err;
>
> + of_node_put(iommu_spec.np);
Here we call of_node_put() unconditionally.
I think it would be much nicer if imx_pcie_add_lut_by_rid() used the
same style as apple_pcie_enable_device() and did the of_node_put()
unconditionally. That would untangle the function a bit and make it
easier to analyze.
> + sid = iommu_spec.args[0];
> mutex_lock(&port->pcie->lock);
>
> idx = bitmap_find_free_region(port->sid_map, port->sid_map_sz, 0);
^ permalink raw reply
* Re: [PATCH v2 2/4] mm: replace exec_folio_order() with generic preferred_exec_order()
From: Jan Kara @ 2026-03-26 16:21 UTC (permalink / raw)
To: Usama Arif
Cc: Jan Kara, david, ryan.roberts, Andrew Morton, willy, linux-mm, r,
ajd, apopple, baohua, baolin.wang, brauner, catalin.marinas,
dev.jain, kees, kevin.brodsky, lance.yang, Liam.Howlett,
linux-arm-kernel, linux-fsdevel, linux-kernel, lorenzo.stoakes,
mhocko, npache, pasha.tatashin, rmclure, rppt, surenb, vbabka,
Al Viro, wilts.infradead.org, ziy, hannes, kas, shakeel.butt,
kernel-team
In-Reply-To: <0ce07bc5-6365-4c54-90e2-4e56ad2b7465@linux.dev>
On Thu 26-03-26 08:40:21, Usama Arif wrote:
> On 20/03/2026 17:42, Jan Kara wrote:
> >> + /* Step down under memory pressure */
> >> + gfp = mapping_gfp_mask(vma->vm_file->f_mapping);
> >> + zone = first_zones_zonelist(node_zonelist(numa_node_id(), gfp),
> >> + gfp_zone(gfp), NULL)->zone;
> >> + if (zone) {
> >> + while (order > 0 &&
> >> + !zone_watermark_ok(zone, order,
> >> + high_wmark_pages(zone), 0, 0))
> >> + order--;
> >> + }
> >
> > It looks wrong for this logic to be here. Trimming order based on memory
> > pressure makes sense (and we've already got reports that on memory limited
> > devices large order folios in the page cache have too big memory overhead
> > so we'll likely need to handle that for page cache allocations in general)
> > but IMHO it belongs to page_cache_ra_order() or some other common place
> > like that.
> >
> > Honza
>
> So I have been thinking about this. readahead_gfp_mask() already sets
> __GFP_NORETRY, so we wont try aggressive reclaim/compaction to satisfy
> the allocation. page_cache_ra_order() falls through to the fallback path
> faulting in order 0 page when allocation is not satsified.
>
> So the allocator already naturally steps down under memory pressure,
> the explicit zone_watermark_ok() loop might be redundant?
Probably yes. I still think we'll have to somehow better tweak the used
order based on expected size of the page cache (2M folios seem unreasonably
large for a machine that has e.g. 1G of memory in total, even if it has
enough free memory at this point in time - we'll benefit from smaller
folios and thus finer grained folio activity tracking for such cases). But
that's not for this patch set.
> What are your thoughts on just setting
> ra->order = min(HPAGE_PMD_ORDER, ilog2(SZ_2M >> PAGE_SHIFT))?
> We can do the higher orlder allocation with gfp &= ~__GFP_RECLAIM
> for the VM_EXEC case.
Yes, it's simple and it makes sense to me so if others are fine with it...
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox