From nobody Sat Sep 26 09:20:09 2026 Received: from mail-43101.protonmail.ch (mail-43101.protonmail.ch [185.70.43.101]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1D534252B7; Wed, 2 Sep 2026 21:22:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.101 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788384161; cv=none; b=YMO+8NYr/BPFGxIOJl9rGquWFZKKcQdcdC40D44KVOIwSfxJUI/UfmzN7wKR8MftZS6Fx7ajr+39khO26d58LHPp0rOWXm6Ehgm2d8aE7Iv83Im2bG6HwYo7u8wR44xbmEkNnIIUa+p9XZ6mGt+VNpIY2Hr0SO+9s15yWtq+alU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788384161; c=relaxed/simple; bh=3gj0kSLsPkp7d/bNS6rXLOSD9pvnNEbtOz7WcVsgHI8=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=U+qqguvsxbNZG9nu+zDiDTVDNEAzyTZB8ewox0bozjUYupR59F09l2EPX3p1w7/8hrl65hTr5GS1bb1kbvP/VPK7ChmetX4F1KK0twmK8IkATIXyaqJiVD2m6uiZuqaJBFGWTS6AWYz7j5rGxhvUW3vnNoRIfIQaVcG4Cg33IMk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me; spf=pass smtp.mailfrom=proton.me; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b=J6LERhRX; arc=none smtp.client-ip=185.70.43.101 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=proton.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b="J6LERhRX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=bttjsimnxnbpbgimf4fwcpgurq.protonmail; t=1788384142; x=1788643342; bh=dS3+A9eI+tmeoJ5w1r4TVLIeNSpcjB+BfvEJnyPVnDw=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=J6LERhRXAhtAdBq025g77m/FcORrkbEZrIkkiRettxL+koUt2nbznZ/1nxENk3Duh 9DAvo/1YMs0DOccL+hWx4wJWUnT7ljGWX0zrYM13r5MO/mHaZAOxiQFJ+PNMW21j2E wXJVj3VwnmLqXIGS9HwgmR8cWCJFHcU9pdmOVMz36kM1hpVUlm4mRWfL8dpWCaQo6q Os0QPk2EvatNXGtY8gIUO7LgUmf/oQ+yyAK+tZT3FBBumIaUA51gxnpouhE7vkThe3 MfwYAPgWjo+dogqeCCAee1kbkZEFmYNOUid/bGgucGGLXqlsDrzJ/yNDUzqi2Zpvl7 IP6Wpx4Fs8iPQ== Date: Wed, 02 Sep 2026 21:22:18 +0000 To: David Heidelberg , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Bjorn Andersson , Konrad Dybcio From: Kristian Brox Cc: Krzysztof Kozlowski , Konrad Dybcio , Luca Weiss , Dmitry Baryshkov , oe-linux-nfc@lists.linux.dev, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Kristian Brox Subject: [PATCH v4 1/3] dt-bindings: net: nfc: add st,st21nfcd Message-ID: <20260902-fp5-st21nfcd-v4-v4-1-ded2f1c501be@proton.me> In-Reply-To: <20260902-fp5-st21nfcd-v4-v4-0-ded2f1c501be@proton.me> References: <20260902-fp5-st21nfcd-v4-v4-0-ded2f1c501be@proton.me> Feedback-ID: 203906395:user:proton X-Pm-Message-ID: 60a34411ed117ddd54a64cbbc892ca3c69075bec Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a compatible for the ST ST21NFCD NFC controller. Document optional SYS_CLK (clocks) and VPS_IO (vdd-io-supply). ST21NFCD is not I2C-only; the ST data brief lists I2C and SPI. Split the spi-max-frequency if/else: forbid it for st,st21nfcb-i2c and st,st21nfcc-i2c, require it for st,st21nfcb-spi, and leave it optional for st,st21nfcd. Add clocks and vdd-io-supply to the existing st,st21nfcb-i2c example instead of a second I2C example. Signed-off-by: Kristian Brox Reviewed-by: Krzysztof Kozlowski --- .../devicetree/bindings/net/nfc/st,st-nci.yaml | 49 +++++++++++++++---= ---- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/net/nfc/st,st-nci.yaml b/Doc= umentation/devicetree/bindings/net/nfc/st,st-nci.yaml index 1dcbddbc5a74..8abafb3d8994 100644 --- a/Documentation/devicetree/bindings/net/nfc/st,st-nci.yaml +++ b/Documentation/devicetree/bindings/net/nfc/st,st-nci.yaml @@ -15,6 +15,7 @@ properties: - st,st21nfcb-i2c - st,st21nfcb-spi - st,st21nfcc-i2c + - st,st21nfcd =20 reset-gpios: description: Output GPIO pin used for resetting the controller @@ -36,26 +37,43 @@ properties: Specifies that the uicc swp signal can be physically connected to the controller =20 + clocks: + maxItems: 1 + description: + External reference clock connected to SYS_CLK. + + vdd-io-supply: + description: + Digital I/O supply (VPS_IO). + required: - compatible - interrupts - reg - reset-gpios =20 -if: - properties: - compatible: - contains: - enum: - - st,st21nfcb-i2c - - st,st21nfcc-i2c -then: - properties: - spi-max-frequency: false -else: - $ref: /schemas/spi/spi-peripheral-props.yaml# - required: - - spi-max-frequency +allOf: + - if: + properties: + compatible: + contains: + enum: + - st,st21nfcb-i2c + - st,st21nfcc-i2c + then: + properties: + spi-max-frequency: false + else: + $ref: /schemas/spi/spi-peripheral-props.yaml# + + - if: + properties: + compatible: + contains: + const: st,st21nfcb-spi + then: + required: + - spi-max-frequency =20 unevaluatedProperties: false =20 @@ -76,6 +94,9 @@ examples: interrupts =3D <2 IRQ_TYPE_LEVEL_HIGH>; reset-gpios =3D <&gpio5 29 GPIO_ACTIVE_HIGH>; =20 + clocks =3D <&clk>; + vdd-io-supply =3D <&vdd_io>; + ese-present; uicc-present; }; --=20 2.55.0 From nobody Sat Sep 26 09:20:09 2026 Received: from mail-43101.protonmail.ch (mail-43101.protonmail.ch [185.70.43.101]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF0C74AE114; Wed, 2 Sep 2026 21:22:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.101 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788384165; cv=none; b=oLe9r74PiPehSz8ydUqFpa54r5rIW3Qoy9Th1LUMhixBdrEfp/odTBWuTdtfx8oLyj+ioi078/S+uNHf0/ygeVYaqy7MbmOK8ZgMFXXU48BaKTGILMhOx/7Dh8AIPJUxAi+HLq5/7YbLaegPa343kvxMQvQwhaOSLY5dpXKYs1A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788384165; c=relaxed/simple; bh=mwupkeZkdl3euysvPkd79p+pLqU5ZEaCA50ubsrKRlc=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=I5G6KFZAH6Ul6iQKTYti7XFhfTzFF1lKZ1/6pZPWJZF78demn32neMsdvc5TciL43jj9zfkyvb3Z1idMgSB9CA/OAalhjomO4oMmXdd8I+QcDh8BNYYl/PyGRMXwv5mQekPRBmczQJkmVapgXgnluaVCOlPLDITlVWu81or25e8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me; spf=pass smtp.mailfrom=proton.me; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b=aTedbZFx; arc=none smtp.client-ip=185.70.43.101 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=proton.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b="aTedbZFx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=vdezpkdcs5cahhga3wrt3ksiie.protonmail; t=1788384145; x=1788643345; bh=dTuz6/9KXziUH8uCWYyIJsDjJtRw0Lr8UlTTR79Pf0E=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=aTedbZFxlHsO2w+IavPuB6GsHRN8sXnpf0qZIrRknw/hASmZ5kgO+qeMq/MFInZSc IgIQ72NBgSQDR+mCon1yUpTYrRk/V6bgI/buRSLIQsz8gSw/kbav6lQ92Yyu/DLxmD 3G4ewbJHPFw6oKgi5LM3ODEySwtBIsJHset8QvLd2E5UaKbt7GiA9Eh8wCAhJAA0zF 7lAqD5dtx+bAxUlaHPNZQCqcSB6bMoO9px8Lp7EuCZSrgI6Io1Ec1bxvh01qIVvyoG RAWjA4IioDWV7JqgWOPX1T9+cldtctAMdkpoxmqa+nkfIxy3LMie/Dydo1LXrUaIzv aCV0ArR6tm4BQ== Date: Wed, 02 Sep 2026 21:22:22 +0000 To: David Heidelberg , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Bjorn Andersson , Konrad Dybcio From: Kristian Brox Cc: Krzysztof Kozlowski , Konrad Dybcio , Luca Weiss , Dmitry Baryshkov , oe-linux-nfc@lists.linux.dev, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Kristian Brox Subject: [PATCH v4 2/3] nfc: st-nci: add raw NCI path for ST21NFCD Message-ID: <20260902-fp5-st21nfcd-v4-v4-2-ded2f1c501be@proton.me> In-Reply-To: <20260902-fp5-st21nfcd-v4-v4-0-ded2f1c501be@proton.me> References: <20260902-fp5-st21nfcd-v4-v4-0-ded2f1c501be@proton.me> Feedback-ID: 203906395:user:proton X-Pm-Message-ID: 29b8da9f2a8d352c21944c75c3fd37adcae0aea2 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" ST21NFCD does not use NDLC. When the compatible is st,st21nfcd, talk raw NCI: - do not add or strip an NDLC PCB - do not run the T1/T2 ACK timers - I2C reads are a 3-byte NCI header plus payload - skip proprietary SET_NFC_MODE and HCI SE discovery - consume proprietary RF NTF 0xf02 (GID 0xf, OID 0x02) Set the raw_nci flag before nci_register_device so ndlc_send does not push an NDLC PCB into a 0-headroom skb. Enable optional vdd-io (VPS_IO) and SYS_CLK before driving reset. Reset is active-low. Existing boards describe it as GPIO_ACTIVE_HIGH and the driver treats gpiod_set_value(reset, 1) as chip-running. Keep that path so old DTS is unchanged. If the GPIO is active-low, pulse logical 1 then 0 (assert, then deassert). Existing st21nfcb / st21nfcc boards keep the NDLC path and do not need those properties. Tested on Fairphone 5: adapter powers up and reads an NTAG 215. Signed-off-by: Kristian Brox --- 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 ++ 7 files changed, 129 insertions(+), 14 deletions(-) diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c index a367136d4330..d7802434abda 100644 --- a/drivers/nfc/st-nci/core.c +++ b/drivers/nfc/st-nci/core.c @@ -18,8 +18,13 @@ =20 static int st_nci_init(struct nci_dev *ndev) { + struct st_nci_info *info =3D nci_get_drvdata(ndev); struct nci_mode_set_cmd cmd; =20 + /* ST21NFCD has no NDLC proprietary SET_NFC_MODE */ + if (info->ndlc->raw_nci) + return 0; + cmd.cmd_type =3D ST_NCI_SET_NFC_MODE; cmd.mode =3D 1; =20 @@ -84,12 +89,29 @@ static int st_nci_prop_rsp_packet(struct nci_dev *ndev, return 0; } =20 +/* + * ST21NFCD emits proprietary NCI NTFs (GID 0xf, OID 0x02) on CORE_RESET + * and during each RF poll loop. The payload is an RF trace; tags are + * still reported with the standard RF_INTF_ACTIVATED_NTF. Consume the + * packet so nci_ntf_packet does not log "unsupported ntf opcode 0xf02". + */ +static int st_nci_prop_rf_ntf_packet(struct nci_dev *ndev, + struct sk_buff *skb) +{ + return 0; +} + static const struct nci_driver_ops st_nci_prop_ops[] =3D { { .opcode =3D nci_opcode_pack(NCI_GID_PROPRIETARY, ST_NCI_CORE_PROP), .rsp =3D st_nci_prop_rsp_packet, }, + { + .opcode =3D nci_opcode_pack(NCI_GID_PROPRIETARY, + ST_NCI_PROP_RF_NTF), + .ntf =3D st_nci_prop_rf_ntf_packet, + }, }; =20 static const struct nci_ops st_nci_ops =3D { diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c index 152c20b6bb01..2ec029f31c67 100644 --- a/drivers/nfc/st-nci/i2c.c +++ b/drivers/nfc/st-nci/i2c.c @@ -10,10 +10,13 @@ #include #include #include +#include #include #include #include #include +#include +#include =20 #include "st-nci.h" =20 @@ -22,10 +25,17 @@ /* ndlc header */ #define ST_NCI_FRAME_HEADROOM 1 #define ST_NCI_FRAME_TAILROOM 0 +#define ST_NCI_RAW_FRAME_HEADROOM 0 =20 #define ST_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */ +#define ST_NCI_NCI_HDR_SIZE 3 /* raw NCI: MT/PBF/GID + OID + len */ #define ST_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */ =20 +enum st_nci_i2c_proto { + ST_NCI_I2C_PROTO_NDLC =3D 0, + ST_NCI_I2C_PROTO_RAW_NCI, +}; + #define ST_NCI_DRIVER_NAME "st_nci" #define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c" =20 @@ -34,6 +44,7 @@ struct st_nci_i2c_phy { struct llt_ndlc *ndlc; =20 bool irq_active; + bool raw_nci; =20 struct gpio_desc *gpiod_reset; =20 @@ -44,9 +55,20 @@ static int st_nci_i2c_enable(void *phy_id) { struct st_nci_i2c_phy *phy =3D phy_id; =20 - gpiod_set_value(phy->gpiod_reset, 0); - usleep_range(10000, 15000); - gpiod_set_value(phy->gpiod_reset, 1); + /* + * Existing DTS uses GPIO_ACTIVE_HIGH and treats logical 1 as + * chip-running. GPIO_ACTIVE_LOW: logical 1 asserts reset + * (physical LOW). + */ + if (gpiod_is_active_low(phy->gpiod_reset)) { + gpiod_set_value(phy->gpiod_reset, 1); + usleep_range(10000, 15000); + gpiod_set_value(phy->gpiod_reset, 0); + } else { + gpiod_set_value(phy->gpiod_reset, 0); + usleep_range(10000, 15000); + gpiod_set_value(phy->gpiod_reset, 1); + } usleep_range(80000, 85000); =20 if (phy->ndlc->powered =3D=3D 0 && phy->irq_active =3D=3D 0) { @@ -111,6 +133,42 @@ static int st_nci_i2c_read(struct st_nci_i2c_phy *phy, u8 buf[ST_NCI_I2C_MAX_SIZE]; struct i2c_client *client =3D phy->i2c_dev; =20 + if (phy->raw_nci) { + r =3D i2c_master_recv(client, buf, ST_NCI_NCI_HDR_SIZE); + if (r < 0) { + usleep_range(1000, 4000); + r =3D i2c_master_recv(client, buf, ST_NCI_NCI_HDR_SIZE); + } + if (r !=3D ST_NCI_NCI_HDR_SIZE) + return -EREMOTEIO; + + len =3D buf[2]; + if (len > ST_NCI_I2C_MAX_SIZE) { + nfc_err(&client->dev, "invalid frame len\n"); + return -EBADMSG; + } + + *skb =3D alloc_skb(ST_NCI_NCI_HDR_SIZE + len, GFP_KERNEL); + if (!*skb) + return -ENOMEM; + + skb_put(*skb, ST_NCI_NCI_HDR_SIZE); + memcpy((*skb)->data, buf, ST_NCI_NCI_HDR_SIZE); + + if (!len) + return 0; + + r =3D i2c_master_recv(client, buf, len); + if (r !=3D len) { + kfree_skb(*skb); + return -EREMOTEIO; + } + + skb_put(*skb, len); + memcpy((*skb)->data + ST_NCI_NCI_HDR_SIZE, buf, len); + return 0; + } + r =3D i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE); if (r < 0) { /* Retry, chip was in standby */ usleep_range(1000, 4000); @@ -211,6 +269,8 @@ static int st_nci_i2c_probe(struct i2c_client *client) return -ENOMEM; =20 phy->i2c_dev =3D client; + phy->raw_nci =3D (uintptr_t)device_get_match_data(dev) =3D=3D + ST_NCI_I2C_PROTO_RAW_NCI; =20 i2c_set_clientdata(client, phy); =20 @@ -218,6 +278,14 @@ static int st_nci_i2c_probe(struct i2c_client *client) if (r) dev_dbg(dev, "Unable to add GPIO mapping table\n"); =20 + r =3D devm_regulator_get_enable_optional(dev, "vdd-io"); + if (r && r !=3D -ENODEV) + return dev_err_probe(dev, r, "failed to enable vdd-io\n"); + + r =3D PTR_ERR_OR_ZERO(devm_clk_get_optional_enabled(dev, NULL)); + if (r) + return dev_err_probe(dev, r, "failed to enable clock\n"); + /* Get RESET GPIO */ phy->gpiod_reset =3D devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(phy->gpiod_reset)) { @@ -231,8 +299,10 @@ static int st_nci_i2c_probe(struct i2c_client *client) device_property_read_bool(dev, "uicc-present"); =20 r =3D ndlc_probe(phy, &i2c_phy_ops, &client->dev, - ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM, - &phy->ndlc, &phy->se_status); + phy->raw_nci ? ST_NCI_RAW_FRAME_HEADROOM : + ST_NCI_FRAME_HEADROOM, + ST_NCI_FRAME_TAILROOM, + &phy->ndlc, &phy->se_status, phy->raw_nci); if (r < 0) { nfc_err(&client->dev, "Unable to register ndlc layer\n"); return r; @@ -273,6 +343,8 @@ static const struct of_device_id of_st_nci_i2c_match[] = =3D { { .compatible =3D "st,st21nfcb-i2c" }, { .compatible =3D "st,st21nfcb_i2c" }, { .compatible =3D "st,st21nfcc-i2c" }, + { .compatible =3D "st,st21nfcd", + .data =3D (void *)ST_NCI_I2C_PROTO_RAW_NCI }, { } }; MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match); diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c index be4808859cfa..13026c4facb3 100644 --- a/drivers/nfc/st-nci/ndlc.c +++ b/drivers/nfc/st-nci/ndlc.c @@ -62,8 +62,9 @@ void ndlc_close(struct llt_ndlc *ndlc) /* toggle reset pin */ ndlc->ops->enable(ndlc->phy_id); =20 - nci_prop_cmd(ndlc->ndev, ST_NCI_CORE_PROP, - sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd); + if (!ndlc->raw_nci) + nci_prop_cmd(ndlc->ndev, ST_NCI_CORE_PROP, + sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd); =20 ndlc->powered =3D 0; ndlc->ops->disable(ndlc->phy_id); @@ -72,11 +73,13 @@ EXPORT_SYMBOL(ndlc_close); =20 int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb) { - /* add ndlc header */ - u8 pcb =3D PCB_TYPE_DATAFRAME | PCB_DATAFRAME_RETRANSMIT_NO | - PCB_FRAME_CRC_INFO_NOTPRESENT; + if (!ndlc->raw_nci) { + /* add ndlc header */ + u8 pcb =3D PCB_TYPE_DATAFRAME | PCB_DATAFRAME_RETRANSMIT_NO | + PCB_FRAME_CRC_INFO_NOTPRESENT; =20 - *(u8 *)skb_push(skb, 1) =3D pcb; + *(u8 *)skb_push(skb, 1) =3D pcb; + } skb_queue_tail(&ndlc->send_q, skb); =20 schedule_work(&ndlc->sm_work); @@ -103,6 +106,10 @@ static void llt_ndlc_send_queue(struct llt_ndlc *ndlc) ndlc->hard_fault =3D r; break; } + if (ndlc->raw_nci) { + kfree_skb(skb); + continue; + } time_sent =3D jiffies; *(unsigned long *)skb->cb =3D time_sent; =20 @@ -154,6 +161,10 @@ static void llt_ndlc_rcv_queue(struct llt_ndlc *ndlc) pr_debug("rcvQlen=3D%d\n", ndlc->rcv_q.qlen); =20 while ((skb =3D skb_dequeue(&ndlc->rcv_q)) !=3D NULL) { + if (ndlc->raw_nci) { + nci_recv_frame(ndlc->ndev, skb); + continue; + } pcb =3D skb->data[0]; skb_pull(skb, 1); if ((pcb & PCB_TYPE_MASK) =3D=3D PCB_TYPE_SUPERVISOR) { @@ -251,7 +262,8 @@ static void ndlc_t2_timeout(struct timer_list *t) =20 int ndlc_probe(void *phy_id, const struct nfc_phy_ops *phy_ops, struct device *dev, int phy_headroom, int phy_tailroom, - struct llt_ndlc **ndlc_id, struct st_nci_se_status *se_status) + struct llt_ndlc **ndlc_id, struct st_nci_se_status *se_status, + bool raw_nci) { struct llt_ndlc *ndlc; =20 @@ -263,6 +275,7 @@ int ndlc_probe(void *phy_id, const struct nfc_phy_ops *= phy_ops, ndlc->phy_id =3D phy_id; ndlc->dev =3D dev; ndlc->powered =3D 0; + ndlc->raw_nci =3D raw_nci; =20 *ndlc_id =3D ndlc; =20 diff --git a/drivers/nfc/st-nci/ndlc.h b/drivers/nfc/st-nci/ndlc.h index c24ce9b0df52..0b12e12e47d2 100644 --- a/drivers/nfc/st-nci/ndlc.h +++ b/drivers/nfc/st-nci/ndlc.h @@ -39,6 +39,8 @@ struct llt_ndlc { */ int hard_fault; int powered; + /* ST21NFCD: raw NCI on the wire, no NDLC PCB / ACK timers */ + bool raw_nci; }; =20 int ndlc_open(struct llt_ndlc *ndlc); @@ -47,6 +49,7 @@ int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb); void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb); int ndlc_probe(void *phy_id, const struct nfc_phy_ops *phy_ops, struct device *dev, int phy_headroom, int phy_tailroom, - struct llt_ndlc **ndlc_id, struct st_nci_se_status *se_status); + struct llt_ndlc **ndlc_id, struct st_nci_se_status *se_status, + bool raw_nci); void ndlc_remove(struct llt_ndlc *ndlc); #endif /* __LOCAL_NDLC_H__ */ diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c index 607ec768eb7b..44cc102bcde2 100644 --- a/drivers/nfc/st-nci/se.c +++ b/drivers/nfc/st-nci/se.c @@ -621,6 +621,9 @@ int st_nci_discover_se(struct nci_dev *ndev) int se_count =3D 0; struct st_nci_info *info =3D nci_get_drvdata(ndev); =20 + if (info->ndlc->raw_nci) + return 0; + r =3D st_nci_hci_network_init(ndev); if (r !=3D 0) return r; diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c index 7948c7e0c88c..1ce80a85bfe6 100644 --- a/drivers/nfc/st-nci/spi.c +++ b/drivers/nfc/st-nci/spi.c @@ -246,7 +246,7 @@ static int st_nci_spi_probe(struct spi_device *dev) =20 r =3D ndlc_probe(phy, &spi_phy_ops, &dev->dev, ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM, - &phy->ndlc, &phy->se_status); + &phy->ndlc, &phy->se_status, false); if (r < 0) { nfc_err(&dev->dev, "Unable to register ndlc layer\n"); return r; diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h index 5286071e52cf..aa8782c95d2f 100644 --- a/drivers/nfc/st-nci/st-nci.h +++ b/drivers/nfc/st-nci/st-nci.h @@ -15,6 +15,8 @@ =20 #define ST_NCI_CORE_PROP 0x01 #define ST_NCI_SET_NFC_MODE 0x02 +/* ST21NFCD proprietary RF activity / poll-trace notification (GID 0xf) */ +#define ST_NCI_PROP_RF_NTF 0x02 =20 /* * ref ISO7816-3 chap 8.1. the initial character TS is followed by a --=20 2.55.0 From nobody Sat Sep 26 09:20:09 2026 Received: from mail-10630.protonmail.ch (mail-10630.protonmail.ch [79.135.106.30]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7EDE40DB47 for ; Wed, 2 Sep 2026 21:22:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.30 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788384168; cv=none; b=dJtrn7v2867TfFjOl41PSZOcIFoVEvwXoC+Myysl0B2QUwOy3faKvRvCOhV9Y1cRmhH82zpRsk8rwnnJmZo7EGuFsijEvHNUK1CAajht3yaouwrvHSishsjvgDzyrLmaaxbfR396qtp6rjnT/88suysu6/XhmcJUvbs0fgnLxD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788384168; c=relaxed/simple; bh=N38+peKMXiO4pZtIjokGtVOkCxm0tkIOhgMfwECw6wM=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=t0QtcZqVlwz4Te0G8UnLp9SQcbCxxVbY1y3p+K/utc8FHGtxRKrLFV2hs0wQNRHctrNLhgI2pwIt2VI+SJdDNZozeRCec+cODcMY6TKoKr2nEmh9odP+WbRqdNRG5ImwCgwalTZdKyNST02iQYUN2OIHQeXU5f/cKGCnKDzkWPA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me; spf=pass smtp.mailfrom=proton.me; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b=Dwh5vIWo; arc=none smtp.client-ip=79.135.106.30 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=proton.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b="Dwh5vIWo" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1788384149; x=1788643349; bh=N38+peKMXiO4pZtIjokGtVOkCxm0tkIOhgMfwECw6wM=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=Dwh5vIWo0NqSQEetDSwtJXlBkB9z+q03yjX0K1vpN2k406kEZcaBSMB0tKIZGgAws TLlae7qV+ExvPPBcyh3YscJTay4jjYaihNLwOpxJ7i14PCUE/XMWbeM8tntjIJNgYy nCDdHO12ee8LSpvphFN4bxMcapopXN7rRnJCKNEiao7RMrjvSSelQPL+/ivLohowfi sfUFU+daogueFlKPLJ4Mi5PIqFczvwOZRt99KG9lQI4HbIpMgYaS6BBzA+IpKNgaTu 5VXKJ4+EzheaAqClmw+xti86bUyVyGKbvvpMZEUFVQm2r1ag9ZidBM8SpTqQBoQXOZ cavLCiY7qxExg== Date: Wed, 02 Sep 2026 21:22:25 +0000 To: David Heidelberg , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Bjorn Andersson , Konrad Dybcio From: Kristian Brox Cc: Krzysztof Kozlowski , Konrad Dybcio , Luca Weiss , Dmitry Baryshkov , oe-linux-nfc@lists.linux.dev, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Kristian Brox Subject: [PATCH v4 3/3] arm64: dts: qcom: qcm6490-fairphone-fp5: add ST21NFCD NFC Message-ID: <20260902-fp5-st21nfcd-v4-v4-3-ded2f1c501be@proton.me> In-Reply-To: <20260902-fp5-st21nfcd-v4-v4-0-ded2f1c501be@proton.me> References: <20260902-fp5-st21nfcd-v4-v4-0-ded2f1c501be@proton.me> Feedback-ID: 203906395:user:proton X-Pm-Message-ID: 3c1b6f39bba4351a7e3072044bfe914a77b17bcc Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable the ST21NFCD on i2c9 (0x08), IRQ TLMM 41, reset TLMM 38 active-low. Compatible is st,st21nfcd (raw NCI). SYS_CLK is LN_BB_CLK2. VPS_IO is L18B (vreg_l18b). ese-present and uicc-present follow the public schematic (NFC_SWP1/SWP2: SWP_SE to SIM1, SWP_UICC to SIM2). Reader path is tested; SE/HCE is not. Signed-off-by: Kristian Brox Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 34 ++++++++++++++++++= +++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm6= 4/boot/dts/qcom/qcm6490-fairphone-fp5.dts index f41ad446a39e..b028d1bb25d4 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts @@ -933,7 +933,23 @@ redriver_ss_in: endpoint { &i2c9 { status =3D "okay"; =20 - /* ST21NFC NFC @ 28 */ + nfc@8 { + compatible =3D "st,st21nfcd"; + reg =3D <0x08>; + + interrupts-extended =3D <&tlmm 41 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios =3D <&tlmm 38 GPIO_ACTIVE_LOW>; + + pinctrl-0 =3D <&nfc_default>; + pinctrl-names =3D "default"; + + clocks =3D <&rpmhcc RPMH_LN_BB_CLK2>; + vdd-io-supply =3D <&vreg_l18b>; + + ese-present; + uicc-present; + }; + /* VL53L3 ToF @ 29 */ }; =20 @@ -1462,6 +1478,22 @@ hall_sensor_default: hall-sensor-default-state { drive-strength =3D <2>; bias-pull-up; }; + + nfc_default: nfc-default-state { + reset-pins { + pins =3D "gpio38"; + function =3D "gpio"; + drive-strength =3D <2>; + bias-disable; + }; + + int-pins { + pins =3D "gpio41"; + function =3D "gpio"; + drive-strength =3D <2>; + bias-disable; + }; + }; }; =20 &uart5 { --=20 2.55.0