[PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO

Qian Zhang via B4 Relay posted 1 patch 1 month ago
arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
[PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Qian Zhang via B4 Relay 1 month ago
From: Qian Zhang <qian.zhang@oss.qualcomm.com>

The QCNFA765 M.2 PCIe WLAN module requires GPIO56 (wlan_en) to be
asserted before PCIe enumeration, and GPIO54 to control the RF kill
line.

Model GPIO56 as a regulator-fixed node (wlan_en) referenced from the
PCIe node via vddpe-3v3-supply to ensure correct power sequencing.
Model GPIO54 as a rfkill-gpio node to allow the rfkill subsystem to
manage RF state.

Signed-off-by: Qian Zhang <qian.zhang@oss.qualcomm.com>
---
The Arduino VENTUNO Q board uses a QCNFA765 M.2 PCIe WLAN module
connected to PCIe0. Two GPIOs are required for proper WLAN operation:

- GPIO56 (wlan_en): The WLAN module enable line. It must be asserted
  before PCIe enumeration begins, otherwise the module is not detected
  by the PCIe root complex. This is modeled as a regulator-fixed node
  (wlan_en) referenced from the PCIe node via vddpe-3v3-supply, which
  ensures the GPIO is asserted with a 20ms startup delay before PCIe
  enumeration starts.

- GPIO54 (rfkill): The RF kill line. It is modeled as a rfkill-gpio
  node so that the rfkill subsystem can properly manage RF state,
  including software-triggered airplane mode.

Testing:
- WLAN module (QCNFA765) successfully enumerated on PCIe after boot
- WiFi scan detects available networks
- rfkill block/unblock correctly toggles GPIO54
- GPIO56 remains high throughout rfkill block/unblock
---
Changes in v3:
- Replace regulator-fixed with rfkill-gpio for GPIO54 (rfkill)
- Reference wlan_en from PCIe node via vddpe-3v3-supply
- Fix subject prefix
- Link to v2: https://lore.kernel.org/r/20260501051918.1990713-1-qian.zhang@oss.qualcomm.com
---
 arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
index ca14f0ea4dae..e0ffe87bba90 100644
--- a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
+++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
@@ -153,6 +153,25 @@ vreg_nvme: regulator-3p3-m2 {
 		enable-active-high;
 		startup-delay-us = <20000>;
 	};
+
+	rfkill-wlan {
+		compatible = "rfkill-gpio";
+		label = "wlan";
+		radio-type = "wlan";
+		shutdown-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>;
+	};
+
+	wlan_reg_3v3: wlan-3v3-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan_en";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vdc_3v3>;
+		gpio = <&tlmm 56 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		startup-delay-us = <20000>;
+		regulator-boot-on;
+	};
 };
 
 &ethernet0 {
@@ -326,7 +345,7 @@ &pcie0 {
 	pinctrl-0 = <&pcie0_default_state>;
 	pinctrl-names = "default";
 
-	vddpe-3v3-supply = <&vdc_3v3>;
+	vddpe-3v3-supply = <&wlan_reg_3v3>;
 };
 
 &pcie1 {

---
base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
change-id: 20260511-linux-next-0846ad58ba18

Best regards,
-- 
Qian Zhang <qian.zhang@oss.qualcomm.com>
Re: [PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Konrad Dybcio 4 weeks ago
On 5/11/26 10:48 AM, Qian Zhang via B4 Relay wrote:
> From: Qian Zhang <qian.zhang@oss.qualcomm.com>
> 
> The QCNFA765 M.2 PCIe WLAN module requires GPIO56 (wlan_en) to be

But isn't that just the wlan-en pin that the power sequencing driver
takes?

ref: drivers/power/sequencing/pwrseq-qcom-wcn.c

Konrad
Re: [PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Qian Zhang 4 weeks ago

On 5/15/2026 6:51 PM, Konrad Dybcio wrote:
> On 5/11/26 10:48 AM, Qian Zhang via B4 Relay wrote:
>> From: Qian Zhang <qian.zhang@oss.qualcomm.com>
>>
>> The QCNFA765 M.2 PCIe WLAN module requires GPIO56 (wlan_en) to be
> 
> But isn't that just the wlan-en pin that the power sequencing driver
> takes?
> 
> ref: drivers/power/sequencing/pwrseq-qcom-wcn.c
> 
> Konrad
Thanks for the review.
It's not the same pin functionally, though they share the same name. 
There are two key differences:


Different power topology: The pwrseq-qcom-wcn.c driver targets WLAN
hips powered by an on-board PMU via the power sequencing framework. In 
our case (VENTUNO Q), the WLAN module has its own internal PMU, and 
wlan_en controls the power-on/off of that internal PMU — it is not part 
of the board-level power sequencing.


PCIe probe ordering: The WLAN module connects to the PCIe root complex 
through a PCIe bridge that does not currently support hotplug. If we 
were to use a similar node configuration as in pwrseq-qcom-wcn.c, there 
is no guarantee that the WLAN module would be powered on before the PCIe 
root complex probes, which would cause enumeration failure.


So while the pin name is the same, the use case and the timing 
constraints are fundamentally different.

Best regards,
Qian
Re: [PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Konrad Dybcio 4 weeks ago
On 5/15/26 2:08 PM, Qian Zhang wrote:
> 
> 
> On 5/15/2026 6:51 PM, Konrad Dybcio wrote:
>> On 5/11/26 10:48 AM, Qian Zhang via B4 Relay wrote:
>>> From: Qian Zhang <qian.zhang@oss.qualcomm.com>
>>>
>>> The QCNFA765 M.2 PCIe WLAN module requires GPIO56 (wlan_en) to be
>>
>> But isn't that just the wlan-en pin that the power sequencing driver
>> takes?
>>
>> ref: drivers/power/sequencing/pwrseq-qcom-wcn.c
>>
>> Konrad
> Thanks for the review.
> It's not the same pin functionally, though they share the same name. There are two key differences:
> 
> 
> Different power topology: The pwrseq-qcom-wcn.c driver targets WLAN
> hips powered by an on-board PMU via the power sequencing framework. In our case (VENTUNO Q), the WLAN module has its own internal PMU, and wlan_en controls the power-on/off of that internal PMU — it is not part of the board-level power sequencing.

I don't believe what you said about the pwrseq driver is true.

> PCIe probe ordering: The WLAN module connects to the PCIe root complex through a PCIe bridge that does not currently support hotplug. If we were to use a similar node configuration as in pwrseq-qcom-wcn.c, there is no guarantee that the WLAN module would be powered on before the PCIe root complex probes, which would cause enumeration failure.

What do you mean by "*currently* does not support hotplug"? Does that
depend on some more code changes?

Konrad
Re: [PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Qian Zhang 3 weeks, 3 days ago
You're right that GPIO 56 (wlan_en) is consumed by pwrseq-qcom-wcn
through the wcn6855-pmu node — apologies for the confusion in my
earlier reply.
Let me explain the hardware on this board, because it
differs slightly from the typical WCN6855 reference design and is the
source of a problem we're now stuck on.

Hardware

The WLAN module fitted on Monaco-Monza is not a bare WCN6855 — it
contains an additional, module-internal PMU (PMCA6850) that gates
power to the WCN6855 die. So the signal chain is:

SoC TLMM gpio56 (wlan_en) ──► PMCA6850 EN ──► WCN6855 rails ──► PCIe link up

wlan_en is therefore the enable pin of PMCA6850, not of the
WCN6855 itself. From the host's point of view, asserting wlan_en
brings the module out of reset; the WCN6855 only becomes visible on
PCIe after PMCA6850 has finished its own ramp-up.

Initially we reused the qcom,wcn6855-pmu compatible so that
pwrseq-qcom-wcn would drive wlan_en for us. But we hit a
resource-allocation issue this hardware behavior creates.

The problem

Because PMCA6850's enable is driven by pwrseq (which runs after the
PCI host bridge has scanned the bus), WCN6855 only appears on the bus
 ~10 s after PCIe enumeration has already finished, with no resources
reserved for it.

Topology — WCN6855 sits behind a Pericom PI7C9X2G304 switch alongside
  a TI USB controller:

pcie0 RC ── 00:00.0 ── 01:00.0 (switch UP)
                       ├── 02:01.0 (DN) ── 03:00.0  WCN6855  (BAR0 = 2
MB, appears late)
                       └── 02:02.0 (DN) ── 04:00.0  TUSB7340 (BAR0 =
64K, BAR2 = 8K, present at boot)

dmesg (kernel 6.8.0-1071-qcom):
[    5.545559] qcom-pcie 1c00000.pci: PCIe Gen.2 x1 link up
[    5.882178] pci 0000:00:00.0: bridge window [mem
0x40400000-0x404fffff]: assigned
[    5.912197] pci 0000:02:01.0: PCI bridge to [bus 03]
[    5.917368] pci 0000:04:00.0: BAR 0 [mem 0x40400000-0x4040ffff
64bit]: assigned
[    5.924919] pci 0000:04:00.0: BAR 2 [mem 0x40410000-0x40411fff
64bit]: assigned
[   16.476921] pci 0000:03:00.0: [17cb:1103] type 00 class 0x028000
PCIe Endpoint
[   16.477176] pci 0000:03:00.0: BAR 0 [mem 0x00000000-0x001fffff 64bit]
[   16.516689] pcieport 0000:02:01.0: bridge window [mem size
0x00200000]: can't assign; no space
[   16.516704] pcieport 0000:02:01.0: bridge window [mem size
0x00200000]: failed to assign
[   16.516713] pci 0000:03:00.0: BAR 0 [mem size 0x00200000 64bit]:
can't assign; no space
[   16.516720] pci 0000:03:00.0: BAR 0 [mem size 0x00200000 64bit]:
failed to assign
[   18.093137] ath11k_pci 0000:03:00.0: Adding to iommu group 24
[   18.101694] ath11k_pci 0000:03:00.0: BAR 0 [??? 0x00000000 flags
0x20000000]: can't assign; bogus alignment
[   18.101724] ath11k_pci 0000:03:00.0: failed to assign pci resource: -22
[   18.108613] ath11k_pci 0000:03:00.0: failed to claim device: -22
[   18.115481] ath11k_pci: probe of 0000:03:00.0 failed with error -22

At the initial scan the PCI core sizes the root-port window to 1 MB
based only on the TI USB endpoint that is currently visible, and
gives the 02:01.0 downstream port no MMIO window at all. When
WCN6855 appears later it requires a 2 MB BAR0 and there is nowhere
to put it.

Thanks,
Qian

On Fri, May 15, 2026 at 8:22 PM Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 5/15/26 2:08 PM, Qian Zhang wrote:
> >
> >
> > On 5/15/2026 6:51 PM, Konrad Dybcio wrote:
> >> On 5/11/26 10:48 AM, Qian Zhang via B4 Relay wrote:
> >>> From: Qian Zhang <qian.zhang@oss.qualcomm.com>
> >>>
> >>> The QCNFA765 M.2 PCIe WLAN module requires GPIO56 (wlan_en) to be
> >>
> >> But isn't that just the wlan-en pin that the power sequencing driver
> >> takes?
> >>
> >> ref: drivers/power/sequencing/pwrseq-qcom-wcn.c
> >>
> >> Konrad
> > Thanks for the review.
> > It's not the same pin functionally, though they share the same name. There are two key differences:
> >
> >
> > Different power topology: The pwrseq-qcom-wcn.c driver targets WLAN
> > hips powered by an on-board PMU via the power sequencing framework. In our case (VENTUNO Q), the WLAN module has its own internal PMU, and wlan_en controls the power-on/off of that internal PMU — it is not part of the board-level power sequencing.
>
> I don't believe what you said about the pwrseq driver is true.
>
> > PCIe probe ordering: The WLAN module connects to the PCIe root complex through a PCIe bridge that does not currently support hotplug. If we were to use a similar node configuration as in pwrseq-qcom-wcn.c, there is no guarantee that the WLAN module would be powered on before the PCIe root complex probes, which would cause enumeration failure.
>
> What do you mean by "*currently* does not support hotplug"? Does that
> depend on some more code changes?
>
> Konrad
Re: [PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Konrad Dybcio 3 weeks ago
On 5/19/26 4:58 AM, Qian Zhang wrote:
> You're right that GPIO 56 (wlan_en) is consumed by pwrseq-qcom-wcn
> through the wcn6855-pmu node — apologies for the confusion in my
> earlier reply.
> Let me explain the hardware on this board, because it
> differs slightly from the typical WCN6855 reference design and is the
> source of a problem we're now stuck on.

The wording, structure and magic characters within your reply make
me think you're using a LLM to respond to me. I will not entertain
this conversation further if that's the case.

> Hardware
> 
> The WLAN module fitted on Monaco-Monza is not a bare WCN6855 — it
> contains an additional, module-internal PMU (PMCA6850) that gates
> power to the WCN6855 die. So the signal chain is:
> 
> SoC TLMM gpio56 (wlan_en) ──► PMCA6850 EN ──► WCN6855 rails ──► PCIe link up
> 
> wlan_en is therefore the enable pin of PMCA6850, not of the
> WCN6855 itself. From the host's point of view, asserting wlan_en
> brings the module out of reset; the WCN6855 only becomes visible on
> PCIe after PMCA6850 has finished its own ramp-up.

The powerseq driver for WCN PMUs exists precisely to handle this setup.

> Initially we reused the qcom,wcn6855-pmu compatible so that
> pwrseq-qcom-wcn would drive wlan_en for us. But we hit a
> resource-allocation issue this hardware behavior creates.
> 
> The problem
> 
> Because PMCA6850's enable is driven by pwrseq (which runs after the
> PCI host bridge has scanned the bus), WCN6855 only appears on the bus
>  ~10 s after PCIe enumeration has already finished, with no resources
> reserved for it.
> 
> Topology — WCN6855 sits behind a Pericom PI7C9X2G304 switch alongside
>   a TI USB controller:
> 
> pcie0 RC ── 00:00.0 ── 01:00.0 (switch UP)
>                        ├── 02:01.0 (DN) ── 03:00.0  WCN6855  (BAR0 = 2
> MB, appears late)
>                        └── 02:02.0 (DN) ── 04:00.0  TUSB7340 (BAR0 =
> 64K, BAR2 = 8K, present at boot)
> 
> dmesg (kernel 6.8.0-1071-qcom):
> [    5.545559] qcom-pcie 1c00000.pci: PCIe Gen.2 x1 link up
> [    5.882178] pci 0000:00:00.0: bridge window [mem
> 0x40400000-0x404fffff]: assigned
> [    5.912197] pci 0000:02:01.0: PCI bridge to [bus 03]
> [    5.917368] pci 0000:04:00.0: BAR 0 [mem 0x40400000-0x4040ffff
> 64bit]: assigned
> [    5.924919] pci 0000:04:00.0: BAR 2 [mem 0x40410000-0x40411fff
> 64bit]: assigned
> [   16.476921] pci 0000:03:00.0: [17cb:1103] type 00 class 0x028000
> PCIe Endpoint
> [   16.477176] pci 0000:03:00.0: BAR 0 [mem 0x00000000-0x001fffff 64bit]
> [   16.516689] pcieport 0000:02:01.0: bridge window [mem size
> 0x00200000]: can't assign; no space
> [   16.516704] pcieport 0000:02:01.0: bridge window [mem size
> 0x00200000]: failed to assign
> [   16.516713] pci 0000:03:00.0: BAR 0 [mem size 0x00200000 64bit]:
> can't assign; no space
> [   16.516720] pci 0000:03:00.0: BAR 0 [mem size 0x00200000 64bit]:
> failed to assign
> [   18.093137] ath11k_pci 0000:03:00.0: Adding to iommu group 24
> [   18.101694] ath11k_pci 0000:03:00.0: BAR 0 [??? 0x00000000 flags
> 0x20000000]: can't assign; bogus alignment
> [   18.101724] ath11k_pci 0000:03:00.0: failed to assign pci resource: -22
> [   18.108613] ath11k_pci 0000:03:00.0: failed to claim device: -22
> [   18.115481] ath11k_pci: probe of 0000:03:00.0 failed with error -22
> 
> At the initial scan the PCI core sizes the root-port window to 1 MB
> based only on the TI USB endpoint that is currently visible, and
> gives the 02:01.0 downstream port no MMIO window at all. When
> WCN6855 appears later it requires a 2 MB BAR0 and there is nowhere
> to put it.

This is a separate issue that needs fixing. I see Mani is already
part of the thread, maybe he can take a peek

Konrad
Re: [PATCH v3] arm64: dts: qcom: arduino-monza: add WLAN enable and rfkill GPIO
Posted by Qian Zhang 2 weeks, 2 days ago
On Fri, May 22, 2026 at 6:47 PM Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 5/19/26 4:58 AM, Qian Zhang wrote:
> > You're right that GPIO 56 (wlan_en) is consumed by pwrseq-qcom-wcn
> > through the wcn6855-pmu node — apologies for the confusion in my
> > earlier reply.
> > Let me explain the hardware on this board, because it
> > differs slightly from the typical WCN6855 reference design and is the
> > source of a problem we're now stuck on.
>
> The wording, structure and magic characters within your reply make
> me think you're using a LLM to respond to me. I will not entertain
> this conversation further if that's the case.
>
> > Hardware
> >
> > The WLAN module fitted on Monaco-Monza is not a bare WCN6855 — it
> > contains an additional, module-internal PMU (PMCA6850) that gates
> > power to the WCN6855 die. So the signal chain is:
> >
> > SoC TLMM gpio56 (wlan_en) ──► PMCA6850 EN ──► WCN6855 rails ──► PCIe link up
> >
> > wlan_en is therefore the enable pin of PMCA6850, not of the
> > WCN6855 itself. From the host's point of view, asserting wlan_en
> > brings the module out of reset; the WCN6855 only becomes visible on
> > PCIe after PMCA6850 has finished its own ramp-up.
>
> The powerseq driver for WCN PMUs exists precisely to handle this setup.
>
> > Initially we reused the qcom,wcn6855-pmu compatible so that
> > pwrseq-qcom-wcn would drive wlan_en for us. But we hit a
> > resource-allocation issue this hardware behavior creates.
> >
> > The problem
> >
> > Because PMCA6850's enable is driven by pwrseq (which runs after the
> > PCI host bridge has scanned the bus), WCN6855 only appears on the bus
> >  ~10 s after PCIe enumeration has already finished, with no resources
> > reserved for it.
> >
> > Topology — WCN6855 sits behind a Pericom PI7C9X2G304 switch alongside
> >   a TI USB controller:
> >
> > pcie0 RC ── 00:00.0 ── 01:00.0 (switch UP)
> >                        ├── 02:01.0 (DN) ── 03:00.0  WCN6855  (BAR0 = 2
> > MB, appears late)
> >                        └── 02:02.0 (DN) ── 04:00.0  TUSB7340 (BAR0 =
> > 64K, BAR2 = 8K, present at boot)
> >
> > dmesg (kernel 6.8.0-1071-qcom):
> > [    5.545559] qcom-pcie 1c00000.pci: PCIe Gen.2 x1 link up
> > [    5.882178] pci 0000:00:00.0: bridge window [mem
> > 0x40400000-0x404fffff]: assigned
> > [    5.912197] pci 0000:02:01.0: PCI bridge to [bus 03]
> > [    5.917368] pci 0000:04:00.0: BAR 0 [mem 0x40400000-0x4040ffff
> > 64bit]: assigned
> > [    5.924919] pci 0000:04:00.0: BAR 2 [mem 0x40410000-0x40411fff
> > 64bit]: assigned
> > [   16.476921] pci 0000:03:00.0: [17cb:1103] type 00 class 0x028000
> > PCIe Endpoint
> > [   16.477176] pci 0000:03:00.0: BAR 0 [mem 0x00000000-0x001fffff 64bit]
> > [   16.516689] pcieport 0000:02:01.0: bridge window [mem size
> > 0x00200000]: can't assign; no space
> > [   16.516704] pcieport 0000:02:01.0: bridge window [mem size
> > 0x00200000]: failed to assign
> > [   16.516713] pci 0000:03:00.0: BAR 0 [mem size 0x00200000 64bit]:
> > can't assign; no space
> > [   16.516720] pci 0000:03:00.0: BAR 0 [mem size 0x00200000 64bit]:
> > failed to assign
> > [   18.093137] ath11k_pci 0000:03:00.0: Adding to iommu group 24
> > [   18.101694] ath11k_pci 0000:03:00.0: BAR 0 [??? 0x00000000 flags
> > 0x20000000]: can't assign; bogus alignment
> > [   18.101724] ath11k_pci 0000:03:00.0: failed to assign pci resource: -22
> > [   18.108613] ath11k_pci 0000:03:00.0: failed to claim device: -22
> > [   18.115481] ath11k_pci: probe of 0000:03:00.0 failed with error -22
> >
> > At the initial scan the PCI core sizes the root-port window to 1 MB
> > based only on the TI USB endpoint that is currently visible, and
> > gives the 02:01.0 downstream port no MMIO window at all. When
> > WCN6855 appears later it requires a 2 MB BAR0 and there is nowhere
> > to put it.
>
> This is a separate issue that needs fixing. I see Mani is already
> part of the thread, maybe he can take a peek
>
> Konrad


The PCI issue has been fixed by this patch,
https://lore.kernel.org/linux-pci/20260116192921.GA958817@bhelgaas/

I will revert to the powerseq approach.

Qian