.../devicetree/bindings/net/nfc/st,st-nci.yaml | 49 +++++++++---- arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 34 ++++++++- drivers/nfc/st-nci/core.c | 22 ++++++ drivers/nfc/st-nci/i2c.c | 82 ++++++++++++++++++++-- drivers/nfc/st-nci/ndlc.c | 27 +++++-- drivers/nfc/st-nci/ndlc.h | 5 +- drivers/nfc/st-nci/se.c | 3 + drivers/nfc/st-nci/spi.c | 2 +- drivers/nfc/st-nci/st-nci.h | 2 + 9 files changed, 197 insertions(+), 29 deletions(-)
This adds NFC on the Fairphone 5 (qcm6490). The board uses an ST21NFCD
on I2C. That part speaks raw NCI; the current st-nci driver always
wraps NDLC, so using st,st21nfcb-i2c leaves the adapter unusable.
The series adds a st,st21nfcd compatible for the raw-NCI path and the
Fairphone 5 DT node. Boards that already use st21nfcb / st21nfcc keep
the NDLC path.
Patches are against linux-nfc/for-next (Linux 7.3-rc1). Hardware test
was on a Fairphone 5 running postmarketOS:
- 7.1.2 sc7280, earlier raw-NCI modules: nfctool Powered: Yes;
initiator poll / neard: NTAG 215, NDEF URI read OK
- 7.2.0-nfc-test+ (sc7280-mainline), this v4 st-nci as modules:
10x initiator poll finds Type 2 in 0.13-0.14 s, no
"unsupported ntf opcode 0xf02". Repeat poll with a Type 2 tag
in the field stays Powered: Yes. Empty-field poll SIGINT
(nfctool -p, no tag) also stays Powered: Yes.
The ndlc: hexdumps are pr_debug. SIGINT during CORE_RESET (nfctool -0
then Ctrl-C during -1) wedges stock nci core; that is not this series.
ese-present and uicc-present follow the public schematic (NFC_SWP1/SWP2:
SWP_SE to SIM1, SWP_UICC to SIM2). SE/HCE is not tested.
CLK_REQ (GPIO 39) is omitted, as on Fairphone 6 NFC. VBAT and VDD_TX sit
on VPH_PWR and are not modelled. VCC_UICC_IN (L4C) is not modelled;
UICC SWP is untested.
Signed-off-by: Kristian Brox <isyourbrainfoss@proton.me>
---
Link to v3:
https://lore.kernel.org/oe-linux-nfc/20260820-fp5-st21nfcd-v3-v3-0-5ee0a7f44d04@proton.me/
Changes in v4:
- Driver: consume ST proprietary RF NTF 0xf02 (Luca)
- Driver: set raw_nci before nci_register_device (Sashiko / David)
- Driver: enable vdd-io and SYS_CLK before driving reset
- Driver: keep named i2c/acpi id initializers; do not add trailing
commas on existing of_match entries (David)
- Driver: reset pulse uses gpiod_is_active_low so new DT can be
GPIO_ACTIVE_LOW without breaking old nfcb DTS (Krzysztof)
- Binding: ST21NFCD is not I2C-only (data brief lists SPI); do not
put st,st21nfcd in the I2C-only spi-max-frequency:false enum
- Binding: SPI $ref only in the non-I2C else (not a global allOf item)
- Binding: clocks/vdd-io-supply on the existing I2C example; drop the
extra example (Krzysztof)
- DTS: reset-gpios GPIO_ACTIVE_LOW (Krzysztof). Physical GPIO 38 HIGH
is the run level. Konrad R-b not carried (polarity changed).
Changes in v3:
- Binding: new compatible is a different ST part (not a driver-sharing note)
- Binding: drop NDLC/raw-NCI description on compatible
- Binding example uses interrupts-extended
- DTS: one nfc_default pinctrl group, pins sorted, no output-high
- Fresh series (not a reply to v1/v2)
Changes in v2:
- Compatible is st,st21nfcd (no -i2c suffix)
- Sent without PGP/MIME
- DTS: interrupts-extended and pinctrl for IRQ/reset
- DTS: ese-present / uicc-present (schematic)
- DTS: SYS_CLK from LN_BB_CLK2, VPS_IO from L18B
- Binding: optional clocks and vdd-io-supply
- Driver: optional clk / vdd-io enable
---
Kristian Brox (3):
dt-bindings: net: nfc: add st,st21nfcd
nfc: st-nci: add raw NCI path for ST21NFCD
arm64: dts: qcom: qcm6490-fairphone-fp5: add ST21NFCD NFC
.../devicetree/bindings/net/nfc/st,st-nci.yaml | 49 +++++++++----
arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 34 ++++++++-
drivers/nfc/st-nci/core.c | 22 ++++++
drivers/nfc/st-nci/i2c.c | 82 ++++++++++++++++++++--
drivers/nfc/st-nci/ndlc.c | 27 +++++--
drivers/nfc/st-nci/ndlc.h | 5 +-
drivers/nfc/st-nci/se.c | 3 +
drivers/nfc/st-nci/spi.c | 2 +-
drivers/nfc/st-nci/st-nci.h | 2 +
9 files changed, 197 insertions(+), 29 deletions(-)
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260902-fp5-st21nfcd-v4-1685be1d7c52
Best regards,
--
Kristian Brox <isyourbrainfoss@proton.me>
Hi Kristian! On Wed Sep 2, 2026 at 11:22 PM CEST, Kristian Brox wrote: > This adds NFC on the Fairphone 5 (qcm6490). The board uses an ST21NFCD > on I2C. That part speaks raw NCI; the current st-nci driver always > wraps NDLC, so using st,st21nfcb-i2c leaves the adapter unusable. > > The series adds a st,st21nfcd compatible for the raw-NCI path and the > Fairphone 5 DT node. Boards that already use st21nfcb / st21nfcc keep > the NDLC path. > > Patches are against linux-nfc/for-next (Linux 7.3-rc1). Hardware test > was on a Fairphone 5 running postmarketOS: > > - 7.1.2 sc7280, earlier raw-NCI modules: nfctool Powered: Yes; > initiator poll / neard: NTAG 215, NDEF URI read OK > - 7.2.0-nfc-test+ (sc7280-mainline), this v4 st-nci as modules: > 10x initiator poll finds Type 2 in 0.13-0.14 s, no > "unsupported ntf opcode 0xf02". Repeat poll with a Type 2 tag > in the field stays Powered: Yes. Empty-field poll SIGINT > (nfctool -p, no tag) also stays Powered: Yes. > > The ndlc: hexdumps are pr_debug. SIGINT during CORE_RESET (nfctool -0 > then Ctrl-C during -1) wedges stock nci core; that is not this series. > > ese-present and uicc-present follow the public schematic (NFC_SWP1/SWP2: > SWP_SE to SIM1, SWP_UICC to SIM2). SE/HCE is not tested. > > CLK_REQ (GPIO 39) is omitted, as on Fairphone 6 NFC. VBAT and VDD_TX sit > on VPH_PWR and are not modelled. VCC_UICC_IN (L4C) is not modelled; > UICC SWP is untested. Thanks for sending this revision! Unfortunately I can still fairly easily reproduce to break scanning: [ 211.682211] nci: __nci_request: wait_for_completion_interruptible_timeout failed 0 [ 211.682246] nci: nci_start_poll: failed to set local general bytes [ 224.483009] nci: __nci_request: wait_for_completion_interruptible_timeout failed 0 [ 224.483033] nci: nci_start_poll: failed to set local general bytes I enabled polling with neard, scanned the tag a bunch of time. Then disable polling, and afterwards the errors above appeared and starting polling again does not work anymore - until I reboot. In fact, I can reproduce this just be enabling polling, disabling polling and enabling polling again. No need to scan a tag inbetween. Can you please share how you've been testing these patches? Regards Luca > > Signed-off-by: Kristian Brox <isyourbrainfoss@proton.me> > --- > Link to v3: > https://lore.kernel.org/oe-linux-nfc/20260820-fp5-st21nfcd-v3-v3-0-5ee0a7f44d04@proton.me/ > > Changes in v4: > - Driver: consume ST proprietary RF NTF 0xf02 (Luca) > - Driver: set raw_nci before nci_register_device (Sashiko / David) > - Driver: enable vdd-io and SYS_CLK before driving reset > - Driver: keep named i2c/acpi id initializers; do not add trailing > commas on existing of_match entries (David) > - Driver: reset pulse uses gpiod_is_active_low so new DT can be > GPIO_ACTIVE_LOW without breaking old nfcb DTS (Krzysztof) > - Binding: ST21NFCD is not I2C-only (data brief lists SPI); do not > put st,st21nfcd in the I2C-only spi-max-frequency:false enum > - Binding: SPI $ref only in the non-I2C else (not a global allOf item) > - Binding: clocks/vdd-io-supply on the existing I2C example; drop the > extra example (Krzysztof) > - DTS: reset-gpios GPIO_ACTIVE_LOW (Krzysztof). Physical GPIO 38 HIGH > is the run level. Konrad R-b not carried (polarity changed). > > Changes in v3: > - Binding: new compatible is a different ST part (not a driver-sharing note) > - Binding: drop NDLC/raw-NCI description on compatible > - Binding example uses interrupts-extended > - DTS: one nfc_default pinctrl group, pins sorted, no output-high > - Fresh series (not a reply to v1/v2) > > Changes in v2: > - Compatible is st,st21nfcd (no -i2c suffix) > - Sent without PGP/MIME > - DTS: interrupts-extended and pinctrl for IRQ/reset > - DTS: ese-present / uicc-present (schematic) > - DTS: SYS_CLK from LN_BB_CLK2, VPS_IO from L18B > - Binding: optional clocks and vdd-io-supply > - Driver: optional clk / vdd-io enable > > --- > Kristian Brox (3): > dt-bindings: net: nfc: add st,st21nfcd > nfc: st-nci: add raw NCI path for ST21NFCD > arm64: dts: qcom: qcm6490-fairphone-fp5: add ST21NFCD NFC > > .../devicetree/bindings/net/nfc/st,st-nci.yaml | 49 +++++++++---- > arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 34 ++++++++- > drivers/nfc/st-nci/core.c | 22 ++++++ > drivers/nfc/st-nci/i2c.c | 82 ++++++++++++++++++++-- > drivers/nfc/st-nci/ndlc.c | 27 +++++-- > drivers/nfc/st-nci/ndlc.h | 5 +- > drivers/nfc/st-nci/se.c | 3 + > drivers/nfc/st-nci/spi.c | 2 +- > drivers/nfc/st-nci/st-nci.h | 2 + > 9 files changed, 197 insertions(+), 29 deletions(-) > --- > base-commit: cee9395acd8043be0644b25c34bfa86623f2b935 > change-id: 20260902-fp5-st21nfcd-v4-1685be1d7c52 > > Best regards, > -- > Kristian Brox <isyourbrainfoss@proton.me>
Hi Luca, On Fri, Sep 18, 2026 at 10:08:20 +0200, Luca Weiss wrote: > Can you please share how you've been testing these patches? The cover letter was nfctool, not neard turning polling off and on. On the 7.2.0-nfc-test+ phone from that letter: nfctool -d nfc0 -1 -p with a Type 2 tag in the field, repeated, then the same poll with no tag and Ctrl-C. Powered stayed Yes. I did not cycle neard before sending v4. I tried that today on the same phone, neard 0.20, with no tag. StartPollLoop Initiator, stop, start again: no error. Dual prints this on every start, including the first: nci: nci_start_poll: failed to set listen parameters That is CORE_SET_CONFIG id 0x54 returning status 0x09. RF_DISCOVER still returns 0, and stop/start again does the same. Powering the adapter off and on does not turn it into a timeout. I did not get "failed to set local general bytes" or wait_for_completion_interruptible_timeout failed 0. With a Type 2 on the phone afterwards, nfctool -d nfc0 -1 -p found tag0. neard StartPollLoop Initiator showed Type 2, UID 53:d9:49:68:b5:00:01, no NDEF. So I have not reproduced the failure that needs a reboot. If you still have the dmesg from just before the first "failed 0", that would show which command was outstanding. Regards Kristian
© 2016 - 2026 Red Hat, Inc.