From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 7260648C3FB; Wed, 23 Sep 2026 10:39:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159992; cv=none; b=Y8B0ey51vV1eLq8e5G9TrHyIA3Gc2a07xFPgykHhx56GK+YsBIMdgJJIuQJ3Cpe5snYeRZA3AB2C55GmIaT7YZ++t8QM3szdbbtVkGkpspK/oR2RWYWNoiV+s8pjZ5g5KfIqFaYy8xIq1VFRf09hmkJPOlSPyP8QNxL5U7eeP18= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159992; c=relaxed/simple; bh=nGlcMDxAN6UptcP2dDBMG8pXeco2X5tGzNRFpwCzNJ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UqFTc2SKltXzTHBhy82kLTQlGQix5x1AsOLSgi0Ykh6mvPCkk2L+x0emOWjSYYIZQEDoQANObPuWHqAe0xu1AzjU1ob94CRQS8q2cid5eyHg3306jH20l1uO5vVkJ0EO70H3psO71Im6DwvqMq9N7lPc5A3MRF/rxU8BdXrX+Vk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=QwtpWQp9; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=0g3xo/9T; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="QwtpWQp9"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="0g3xo/9T" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aigmjgbtLs8c723qaOIx+1R2oLC30DNEEzQmo9CtujU=; b=QwtpWQp97ILOnV8Sctwf/2VVL4kt7Rqjbu0wqMAokcCjXr1BZoXjOhiOus5Dv1caONnX7y Pq5W79zc38eBSQFo8as0XER4izK/Ljtrsb8faDN5GkmmQAbt5iDRP8M+dpOZcF1upsjZ0n s1kRDAhgj47P+ZyaYEYKOvAiiu0DeMv/8IGNpLQWeO01tqoTtgUB+Z7BvHyioeT6EwiUyY B0vX2LWKJX9Ax8q9JEOoemHEjphYhvxvLXX2SxJONqFacO9X84q1kn5PMzslWSMoxeU9LQ by1fX7MIQoKPf0GlxAuXjgKmETTnbT4Skm1JioHe3R6ydVwsVkdibs1JyBvHsw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159982; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aigmjgbtLs8c723qaOIx+1R2oLC30DNEEzQmo9CtujU=; b=0g3xo/9T9TvtTA/6UOZAx/4u7QUGspvRyUe0Lhq/7SKOsdxqSVvLSrIW1lixnd+vuOhKXm EYQT6T57E4VuHqDw== Date: Wed, 23 Sep 2026 12:39:28 +0200 Subject: [PATCH net-next v3 1/8] dt-bindings: vendor-prefixes: Add soce Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-1-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim , Krzysztof Kozlowski Document binding for System-On-Chip Engineering, S.L. Link: https://soc-e.com/ Signed-off-by: Vasilij Strassheim Acked-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Docum= entation/devicetree/bindings/vendor-prefixes.yaml index ba2002969373..1c641e1f0ca6 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1581,6 +1581,8 @@ patternProperties: description: Standard Microsystems Corporation "^snps,.*": description: Synopsys, Inc. + "^soce,.*": + description: System-On-Chip Engineering, S.L. "^sochip,.*": description: Shenzhen SoChip Technology Co., Ltd. "^socionext,.*": --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 DE15048C8AE; Wed, 23 Sep 2026 10:39:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159997; cv=none; b=H0AuabqkGztcnBDJS6oSVs7i3Ne32AGGPIrs0u4QGy/FulvDEl85+cB+QKqIewSjWCzRiKFU84IU5vcpRdTYmHyJ5OfMDHPSlH8306Qm5uF0zhoJ2gYifee/ZD+Z+RL2547uNZxvSs9prPyFJ5UTQ5uRsbaLmIwAN95F6wja644= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159997; c=relaxed/simple; bh=ReWPecma+TFKe2saPhApRyIrViwQ/YokOyxWxkliJVs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eBdywMwuJNLP3JoIsbPo8C3PR9Beo5KaK8zTHYUDmE7e2fHoK684Xuf2/KczmoF0bkwXamZIvbppVCkSE5RmL6XdheZlCcO9Hcirgw3qRXRd/+Usow3DLidUhLkvIApZQX5SHTTmQ/spWcB23UwXnUi+ZpYOTsTInkSCYB40IEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=BEF0rN1e; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=bHrBGlzy; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="BEF0rN1e"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="bHrBGlzy" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R1sJUfBEmsZ9rDD7pl7MAlsVj7stcmcCx9IW4KMl91g=; b=BEF0rN1ewo6uLm5rsGyZlPEonKfTcieU+J2SwfL42QSfdceXz0ey1vxN2iXMkaLQ7auk0t fNOoOzswmhvi5pxFwFNILjQcqkqtqQUfewDviueTegG/P4wCk9BCrmSmiUMpFJJ/ZDO0u4 XQFv5KPDcBhmV5xoMwDpslzaUt/N0PUVImJuQbHJlGLYy56vgUXchZYuIrcMW2giNMCEzz o3Vl9yAjj7U9UKsDcYW45NpWEb3GT53KUkyzig38CD7ge+Cp9wT2/VFxgLCxtrpLRp6GFp 4F+NDpTtzEzZEQydkqPYF6/K30Dx227pxG2CHVFFVcvZyhBnIpMtQx+bcl04wQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R1sJUfBEmsZ9rDD7pl7MAlsVj7stcmcCx9IW4KMl91g=; b=bHrBGlzyQJ+2eS/5gI12VBwr87G46Q35c2Yg/7lrsvmW8ikqlbZiW/RsgrjTx+LRbj3tiI rgCnygaajX1GzeAw== Date: Wed, 23 Sep 2026 12:39:29 +0200 Subject: [PATCH net-next v3 2/8] dt-bindings: net: Add SoC-e SWIP MDIO controller Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-2-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim Add a binding for the MDIO controller integrated into SoC-e SWIP Ethernet switch IP cores. The controller exposes separate register regions for transaction data and for the shared transaction control and external bus selector register. It acts as the parent bus for an MDIO mux used to access the external MDIO interfaces synthesized into the switch core. Signed-off-by: Vasilij Strassheim --- .../devicetree/bindings/net/soce,swip-mdio.yaml | 47 ++++++++++++++++++= ++++ 1 file changed, 47 insertions(+) diff --git a/Documentation/devicetree/bindings/net/soce,swip-mdio.yaml b/Do= cumentation/devicetree/bindings/net/soce,swip-mdio.yaml new file mode 100644 index 000000000000..3cf4bde0508a --- /dev/null +++ b/Documentation/devicetree/bindings/net/soce,swip-mdio.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/soce,swip-mdio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SoC-e switch IP MDIO controller + +maintainers: + - Vasilij Strassheim + +description: + MDIO controller integrated into SoC-e Ethernet switch FPGA IP cores. + The controller accesses multiple external MDIO buses through a mux. + +$ref: mdio.yaml# + +properties: + compatible: + const: soce,swip-mdio-23-02 + + reg: + items: + - description: MDIO parameter, write data, and read data registers + - description: Shared MDIO transaction control and bus selection reg= ister + + reg-names: + items: + - const: data + - const: control + +required: + - compatible + - reg + - reg-names + +unevaluatedProperties: false + +examples: + - | + mdio@204 { + compatible =3D "soce,swip-mdio-23-02"; + reg =3D <0x204 0xc>, <0x200 0x4>; + reg-names =3D "data", "control"; + #address-cells =3D <1>; + #size-cells =3D <0>; + }; --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 61DA347CA90; Wed, 23 Sep 2026 10:39:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159993; cv=none; b=mqDXP0IpQGTC1/oLDQ4y+Wy+YaLcUD6GhaEv+Jf7uWOq5dQFb7Vq6wASVM2qeohN/76SGNSsA+E6a57Q6SJ4KJVrmB4wCNfO2gf9pRk8X/tmYMyrx/BCX1QSG6HGBRZmt5JtkmJ7NYZsuxrXOb9fgRja2jVC/fCDz/7mlVdpCRU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159993; c=relaxed/simple; bh=eLfyXIHP+DBOk1PaWgQ0C2aUrJQphj77LAyGq2bH0I4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZtUM9nDIrouCji1Q3/6i7awdjXn5hORlBpPGspUNqmPCoBuwOiRdttnd8zbXv1GWyQPjn+0HVMRmde9p+nnR/BYQXHQMoR0vX+DgRCVun8SRoRHELZnvwDUNIEn07qOiCYbFPeKDSfCNDyjpYVAN3YthWUmSP+984R8lYctRQEg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=yxNYQZ4W; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=7j7ABW3k; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="yxNYQZ4W"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="7j7ABW3k" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159985; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UpUhfJx82Oe5JKxsiqQBFzO4QLK+0xqpIhBiq0nUpi8=; b=yxNYQZ4W0k2ggJCZiDD5tVXQVqUFIpcaoSNIJsrUqvmp7VQ+SJQEwJ7SUD1mDkGzuuOEsV /S/cSsRssgL5LWrQtshU2vyWIhYuYjUZPhoL3sgKHytbycqfaI5/7Onw9EiktSnez8Aync MaDEJzzw2bAnfeHxJEK1+vMonVC65Vv1UVKk53LwLj31lXj3PNgmgraB7P+Q9J/xoWKMT+ 3a0QcXJgraFZDikiZasojoURuSSr5hcFVjzc4oRkaE0H/nwVcNE8J40FKg0ikUr6TA/WPL fXlz3s2gBtLTpX+HT068/hkWHksULr/6wYg1FY1kpV1VUbC9gr9XPhE/XoBTjw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159985; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UpUhfJx82Oe5JKxsiqQBFzO4QLK+0xqpIhBiq0nUpi8=; b=7j7ABW3kcfWmLKb3qhLQTRa5P4bR45ZAFWzwIYA2oQkWJ0Xt8OdDeXMlXl3jasHq7+f6cb Y06EPrDMTrCc1yDg== Date: Wed, 23 Sep 2026 12:39:30 +0200 Subject: [PATCH net-next v3 3/8] dt-bindings: net: dsa: Add SoC-e SWIP switch Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-3-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim Add a binding for SoC-e FPGA-based Ethernet switch IP cores. The compatible identifies a register layout characterized by the core and feature identification registers at the encoded offsets. The concrete synthesis-time configuration is then autodetected from these registers. Describe the Ethernet ports and the optional integrated MDIO controller with its generic MMIO mux and child buses. Signed-off-by: Vasilij Strassheim --- .../devicetree/bindings/net/dsa/soce,swip.yaml | 162 +++++++++++++++++= ++++ 1 file changed, 162 insertions(+) diff --git a/Documentation/devicetree/bindings/net/dsa/soce,swip.yaml b/Doc= umentation/devicetree/bindings/net/dsa/soce,swip.yaml new file mode 100644 index 000000000000..d614fb2a29d3 --- /dev/null +++ b/Documentation/devicetree/bindings/net/dsa/soce,swip.yaml @@ -0,0 +1,162 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/dsa/soce,swip.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SoC-e ethernet switch IP core for FPGAs + +maintainers: + - Vasilij Strassheim + +description: + SoC-e Ethernet switch IP cores are FPGA-based switches whose features + and number of ports are selected at synthesis time. Ports can connect + to CPUs, external PHYs, FPGA logic, or other switch cores. An integrated + MDIO controller accesses the per-port external buses through a mux. + +$ref: dsa.yaml# + +properties: + compatible: + const: soce,swip-00-04-0c-10 + description: + Register layout with the core version register at offset 0x00 and + feature identification registers at offsets 0x04, 0x0c, and 0x10. + Switch instances using this register layout are autodetected from + these registers and use this compatible regardless of their + synthesis-time feature and port configuration. + + reg: + maxItems: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + + ranges: true + + mdio@204: + $ref: /schemas/net/soce,swip-mdio.yaml# + unevaluatedProperties: false + description: + Integrated MDIO controller bus on the master side of the mux. + + mdio-mux@202: + $ref: /schemas/net/mdio-mux-mmioreg.yaml# + unevaluatedProperties: false + + ethernet-ports: + type: object + patternProperties: + '^ethernet-port@[0-9a-f]+$': + type: object + $ref: dsa-port.yaml# + unevaluatedProperties: false + + properties: + reg: + maximum: 30 + description: + Switch port index. Supported switch configurations have + up to 31 ports, numbered from 0 through 30. + + phy-mode: + enum: + - mii + - gmii + - rmii + - rgmii + - rgmii-id + - rgmii-rxid + - rgmii-txid + + required: + - reg + - phy-mode + +required: + - compatible + - reg + - ethernet-ports + +unevaluatedProperties: false + +examples: + - | + ethernet-switch@80020000 { + compatible =3D "soce,swip-00-04-0c-10"; + reg =3D <0x80020000 0x10000>; + #address-cells =3D <1>; + #size-cells =3D <1>; + ranges =3D <0x0 0x80020000 0x10000>; + + mdio_parent: mdio@204 { + compatible =3D "soce,swip-mdio-23-02"; + reg =3D <0x204 0xc>, <0x200 0x4>; + reg-names =3D "data", "control"; + #address-cells =3D <1>; + #size-cells =3D <0>; + }; + + mdio-mux@202 { + compatible =3D "mdio-mux-mmioreg", "mdio-mux"; + reg =3D <0x202 0x2>; + mux-mask =3D <0x07ff>; + mdio-parent-bus =3D <&mdio_parent>; + #address-cells =3D <1>; + #size-cells =3D <0>; + + mdio@0 { + reg =3D <0>; + #address-cells =3D <1>; + #size-cells =3D <0>; + + switchphy0: ethernet-phy@1 { + compatible =3D "ethernet-phy-ieee802.3-c22"; + reg =3D <1>; + }; + }; + + mdio@1 { + reg =3D <1>; + #address-cells =3D <1>; + #size-cells =3D <0>; + + switchphy1: ethernet-phy@1 { + compatible =3D "ethernet-phy-ieee802.3-c22"; + reg =3D <1>; + }; + }; + }; + + ethernet-ports { + #address-cells =3D <1>; + #size-cells =3D <0>; + + ethernet-port@0 { + reg =3D <0>; + phy-handle =3D <&switchphy0>; + phy-mode =3D "rgmii-id"; + }; + + ethernet-port@1 { + reg =3D <1>; + phy-handle =3D <&switchphy1>; + phy-mode =3D "rgmii-id"; + }; + + ethernet-port@2 { + reg =3D <2>; + ethernet =3D <ð0>; + phy-mode =3D "gmii"; + + fixed-link { + speed =3D <1000>; + full-duplex; + }; + }; + }; + }; --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 D7EA448662F; Wed, 23 Sep 2026 10:39:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159997; cv=none; b=gTtf1VLmWuvkaCSH7/7o2miO2cN7DTndaV8lbnHgD5DEwPbJqw5dN3cUrFXSSqY1fvv3Js3PervXsRyXfwhtBie6rXjd7iIx+wc0TOmTwsxlkyNzTJQ2xf8+iwGREbIYfSceelVjqDD2NZJ+jBqtqqDIS8oQeWSDQNMbsLcETjs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790159997; c=relaxed/simple; bh=1JMuIISHrmU9d8EK+gc0TKNfWfwNjBaS+80ZHvx8U4w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gd2gyWrJrMv84EgIpNfQoQuhLZsCH0vjASXP1d+Vp9sPTYJuPdXWZqrwLy6ivmZ1R3caoHysxJ7g6jDJkInkJblClv4U8eWpiyhUIMz4gUkyqZ9hCtVZ0UOlpofPwNIof3OCvEMJEpM9MKtr7Cp54zaSWWJRBbY6ND6G9DAtY54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=OYU2sKQF; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=fZRsGygQ; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="OYU2sKQF"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="fZRsGygQ" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159985; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Xc5fLkyYctlhhIjJAyWMtKYwPSfFQ54G7ushUR2JcOo=; b=OYU2sKQFe4CMCDOhIZ+rX91IoVVRk7f460FnkTxur+bBZaLF/E0tXbL0ZSGW6LlJObLBmL sJ0ZvTunBlUBGogfEqN2oZQV9+HEJR93Kzr0VrmBJCh7i9ymTld54LuCbbyk8hp5gO4+H4 EobPSP9bBKKnm82OlglLnsxjlusOUZ8+l6gYbMOxeWGDiBFwNbUBL1q0dnu+V+M7dixvAh LAg7QUW3a/lftucDr+EdXxQ6XLCDQrBct+9KVr3GXKWp+Yfd18c9N4f97sre63NDPvi6q2 f9m9rcYTXVyXAfF8/c2EjkO9QJi12+7nzvHDgDskinUEzgXYRHNW+/1Uc16Adw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159985; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Xc5fLkyYctlhhIjJAyWMtKYwPSfFQ54G7ushUR2JcOo=; b=fZRsGygQAYEczlLkqiliB94mljV57ocZnRSTLjE57drnoqpO/jmPkGpk1pCmws4Yr2sJKZ IRJB0FOUOjYpy2Dw== Date: Wed, 23 Sep 2026 12:39:31 +0200 Subject: [PATCH net-next v3 4/8] net: dsa: Add tag handling for SoC-e switches Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-4-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim SoC-e switches exchange frames with the conduit using an 8-byte SDSA header inserted between the source MAC address and the original EtherType. The header identifies itself with EtherType 0xdcdc and carries the frame direction and a 10-bit source or destination port. Add transmit support for FROM_CPU frames and receive support for TO_CPU frames. Validate the EtherType, frame type, header length, and source port before accepting received frames. The SDSA header can also carry an 802.1Q TCI. Encode accelerated VLAN metadata into the header on transmit and restore it as skb VLAN metadata on receive. Signed-off-by: Vasilij Strassheim --- include/net/dsa.h | 2 + net/dsa/Kconfig | 6 ++ net/dsa/Makefile | 1 + net/dsa/tag_sdsa.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 167 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 5d12191b6f6f..8287fba8b107 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -62,6 +62,7 @@ struct tc_action; #define DSA_TAG_PROTO_KSZ8463_VALUE 34 #define DSA_TAG_PROTO_MT7628_VALUE 35 #define DSA_TAG_PROTO_KS8995_VALUE 36 +#define DSA_TAG_PROTO_SDSA_VALUE 37 =20 enum dsa_tag_protocol { DSA_TAG_PROTO_NONE =3D DSA_TAG_PROTO_NONE_VALUE, @@ -101,6 +102,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_KSZ8463 =3D DSA_TAG_PROTO_KSZ8463_VALUE, DSA_TAG_PROTO_MT7628 =3D DSA_TAG_PROTO_MT7628_VALUE, DSA_TAG_PROTO_KS8995 =3D DSA_TAG_PROTO_KS8995_VALUE, + DSA_TAG_PROTO_SDSA =3D DSA_TAG_PROTO_SDSA_VALUE, }; =20 struct dsa_switch; diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 4f44bf3ede23..9b299cada316 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -194,6 +194,12 @@ config NET_DSA_TAG_RZN1_A5PSW Renesas RZ/N1 embedded switch that uses an 8 byte tag located after destination MAC address. =20 +config NET_DSA_TAG_SDSA + tristate "Tag driver for SoC-e switches using EtherType SDSA headers" + help + Say Y or M if you want to enable support for tagging frames for the + SoC-e switches. + config NET_DSA_TAG_LAN9303 tristate "Tag driver for SMSC/Microchip LAN9303 family of switches" help diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 1f9cc30e9988..a4c8d0e6bc0f 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_NET_DSA_TAG_QCA) +=3D tag_qca.o obj-$(CONFIG_NET_DSA_TAG_RTL4_A) +=3D tag_rtl4_a.o obj-$(CONFIG_NET_DSA_TAG_RTL8_4) +=3D tag_rtl8_4.o obj-$(CONFIG_NET_DSA_TAG_RZN1_A5PSW) +=3D tag_rzn1_a5psw.o +obj-$(CONFIG_NET_DSA_TAG_SDSA) +=3D tag_sdsa.o obj-$(CONFIG_NET_DSA_TAG_SJA1105) +=3D tag_sja1105.o obj-$(CONFIG_NET_DSA_TAG_TRAILER) +=3D tag_trailer.o obj-$(CONFIG_NET_DSA_TAG_VSC73XX_8021Q) +=3D tag_vsc73xx_8021q.o diff --git a/net/dsa/tag_sdsa.c b/net/dsa/tag_sdsa.c new file mode 100644 index 000000000000..8cc3fa357be4 --- /dev/null +++ b/net/dsa/tag_sdsa.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2026 System on Chip engineering, S.L. + * Copyright (c) 2026 Linutronix GmbH + * Author: Vasilij Strassheim + */ + +#include +#include +#include +#include +#include + +#include "tag.h" + +#define SDSA_HLEN 8 + +#define SDSA_NAME "sdsa" +#define ETH_P_SDSA 0xDCDC + +/* SDSA tag byte layout (after the 12-byte MAC header): + * Bytes 0-1: SDSA EtherType (0xDCDC) + * Bytes 2-3: Reserved + * Byte 4: Frame type (bits 7-6), VLAN-info bit (bit 5), port[9:5] (bit= s 4-0) + * Byte 5: Port[4:0] (bits 7-3) + * Bytes 6-7: PCP (bits 7-5) / CFI (bit 4) / VID (bits 3-0 + byte 7), only + * meaningful when the VLAN-info bit is set. + */ +#define SDSA_TAG_FRAME_TYPE_MASK GENMASK(7, 6) +#define SDSA_TAG_VLAN_BIT BIT(5) +#define SDSA_TAG_PORT_HI_MASK GENMASK(4, 0) +#define SDSA_TAG_PORT_LO_MASK GENMASK(7, 3) +#define SDSA_TAG_PORT_HI_SHIFT 5 +#define SDSA_FRAME_TYPE_TO_CPU 0 +#define SDSA_FRAME_TYPE_FROM_CPU 1 + +struct sdsa_tag { + __be16 ethertype; + __be16 reserved; + u8 frame_type_port_hi; + u8 port_lo; + __be16 vlan; +}; + +static struct sk_buff *sdsa_xmit(struct sk_buff *skb, struct net_device *d= ev) +{ + struct dsa_port *dp =3D dsa_user_to_port(dev); + struct sdsa_tag *tag; + u16 vlan_tci; + + BUILD_BUG_ON(sizeof(*tag) !=3D SDSA_HLEN); + + skb_push(skb, SDSA_HLEN); + dsa_alloc_etype_header(skb, SDSA_HLEN); + + tag =3D dsa_etype_header_pos_tx(skb); + tag->ethertype =3D cpu_to_be16(ETH_P_SDSA); + tag->reserved =3D 0; + tag->frame_type_port_hi =3D + FIELD_PREP(SDSA_TAG_FRAME_TYPE_MASK, SDSA_FRAME_TYPE_FROM_CPU) | + FIELD_PREP(SDSA_TAG_PORT_HI_MASK, + dp->index >> SDSA_TAG_PORT_HI_SHIFT); + tag->port_lo =3D FIELD_PREP(SDSA_TAG_PORT_LO_MASK, dp->index); + /* SDSA carries no TPID, so only encode 802.1Q C-tags. */ + if (skb_vlan_tag_present(skb) && + skb->vlan_proto =3D=3D htons(ETH_P_8021Q)) { + vlan_tci =3D skb_vlan_tag_get(skb); + __vlan_hwaccel_clear_tag(skb); + tag->frame_type_port_hi |=3D SDSA_TAG_VLAN_BIT; + tag->vlan =3D cpu_to_be16(vlan_tci); + } else { + tag->vlan =3D 0; + } + + return skb; +} + +static struct sk_buff *sdsa_rcv(struct sk_buff *skb, struct net_device *de= v) +{ + enum skb_drop_reason reason; + struct sdsa_tag *tag; + u16 dummy_vlan_tci; + bool vlan_present; + int source_port; + u16 encap_proto; + u8 frame_type; + u16 vlan_tci; + + if (unlikely(!pskb_may_pull(skb, SDSA_HLEN))) { + reason =3D SKB_DROP_REASON_HDR_TRUNC; + goto out_drop; + } + + tag =3D dsa_etype_header_pos_rx(skb); + if (unlikely(be16_to_cpu(tag->ethertype) !=3D ETH_P_SDSA)) { + reason =3D SKB_DROP_REASON_DEV_HDR; + goto out_drop; + } + + frame_type =3D FIELD_GET(SDSA_TAG_FRAME_TYPE_MASK, + tag->frame_type_port_hi); + if (frame_type !=3D SDSA_FRAME_TYPE_TO_CPU) { + reason =3D SKB_DROP_REASON_DEV_HDR; + goto out_drop; + } + + vlan_present =3D tag->frame_type_port_hi & SDSA_TAG_VLAN_BIT; + vlan_tci =3D be16_to_cpu(tag->vlan); + encap_proto =3D get_unaligned_be16((u8 *)tag + SDSA_HLEN); + + source_port =3D FIELD_GET(SDSA_TAG_PORT_HI_MASK, + tag->frame_type_port_hi) << + SDSA_TAG_PORT_HI_SHIFT; + source_port |=3D FIELD_GET(SDSA_TAG_PORT_LO_MASK, tag->port_lo); + + skb->dev =3D dsa_conduit_find_user(dev, 0, source_port); + if (!skb->dev) { + reason =3D SKB_DROP_REASON_DEV_HDR; + goto out_drop; + } + + skb_pull_rcsum(skb, SDSA_HLEN); + dsa_strip_etype_header(skb, SDSA_HLEN); + if (vlan_present) { + if (encap_proto =3D=3D ETH_P_8021Q) { + skb_push_rcsum(skb, ETH_HLEN); + skb_reset_mac_header(skb); + if (__skb_vlan_pop(skb, &dummy_vlan_tci)) { + reason =3D SKB_DROP_REASON_NOMEM; + goto out_drop; + } + skb_pull_rcsum(skb, ETH_HLEN); + } + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); + } + + dsa_default_offload_fwd_mark(skb); + return skb; + +out_drop: + kfree_skb_reason(skb, reason); + return NULL; +} + +static const struct dsa_device_ops sdsa_netdev_ops =3D { + .name =3D SDSA_NAME, + .proto =3D DSA_TAG_PROTO_SDSA, + .xmit =3D sdsa_xmit, + .rcv =3D sdsa_rcv, + .needed_headroom =3D SDSA_HLEN, +}; + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DSA tag driver for SoC-e SDSA protocol"); +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_SDSA, SDSA_NAME); + +module_dsa_tag_driver(sdsa_netdev_ops); --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 F1A56488202; Wed, 23 Sep 2026 10:39:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160002; cv=none; b=I6FQXv7gquDeYoiDmjr8HTU5952RCqg5MPVX00qKAF5Iqp31AmhTC4r+O0um7GQU2SETgL79qskVUWiqP9xzL+ck1uZA5VPou1RJ5oySwqj89QyRYHinZl8r2lP0sZQh3M4FK+fSXvyF68kYNce6OydAeH0vjqSv4nXWS3M2Y5g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160002; c=relaxed/simple; bh=Nb3dIFnlfeNKfwiCnrBRyNz6aWD2QFhVC4bW3EFJa24=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mIRniH9Tk3lgKZd+NoRPORHPDBIysafmu84dA0b+TDKwFvGGLxl4GGv77jZWya9VnUVi/QhkND53CLbDlC/3vU+Gh3yjo0tQj0PZ7uJ2IUtkjypu0j0NVAwGqjJKdqHRDfA9nuQhEwZ79hdpYWxlYC/TC1mhz4hGedPrTRCZxxM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=PUWh5s8f; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=v3p5ZESl; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PUWh5s8f"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="v3p5ZESl" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159986; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/t3altdyPi6nOwcJldWqfunYafM8u8lfq04M8hrYN7M=; b=PUWh5s8feiAEt5ogangjDTpoCluEStI70CzV2oAc3aXPmE48UqJwjiGxZ5Vj6ZL0UCOH+r QkBVwqYuOUr7OfKNFSGHhs21fBxUa3RJg696zvucPUyGNZerqjatDVe1x6ORXQ5V+wPbME 4x1qaw6bbgguNIRzsX9cD09GRXdit0lprsAuHmCWStq+S/DOgQLQg6v/jt49jR3IpWe4Dt L8DVJIlsZTAhWIjyBM8jfUtBbizH/FjhJRWPB8RYWOP05GIBecGgoazytBYZe5N2scCqiX GL+Dxfy0LzpnuCVOrMO+EMDHirg0CSIHXW+k8mNHkINaYwldUVpzP8kCX/vToA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159986; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/t3altdyPi6nOwcJldWqfunYafM8u8lfq04M8hrYN7M=; b=v3p5ZESlLf3lqRVSgoHwpgXqLJIe/9l4upD4lSsVJ7r2PYNWb4czkjMr6umdaizJfG5Fmc 31OTXYGgjENB0jDA== Date: Wed, 23 Sep 2026 12:39:32 +0200 Subject: [PATCH net-next v3 5/8] net: mdio: Add SoC-e SWIP MDIO controller driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-5-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim Add a driver for the MDIO controller integrated into SoC-e Ethernet switch IP cores. Support Clause 22 transactions and the separate address and data cycles required for Clause 45 accesses. The transaction control register is shared with the external MDIO bus selector. The selector occupies bits 26:16 and is managed by a generic MMIO MDIO mux through the upper 16-bit halfword. Preserve those bits when starting a transaction. Check that the controller is idle before programming transaction registers and poll for completion after each transaction cycle. Return a timeout instead of waiting indefinitely, and allow a later access to retry if the hardware becomes idle again. Signed-off-by: Vasilij Strassheim --- drivers/net/mdio/Kconfig | 7 ++ drivers/net/mdio/Makefile | 1 + drivers/net/mdio/mdio-soce.c | 239 +++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 247 insertions(+) diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig index d44278f26fab..21f2b516880b 100644 --- a/drivers/net/mdio/Kconfig +++ b/drivers/net/mdio/Kconfig @@ -189,6 +189,13 @@ config MDIO_REGMAP regmap. Users willing to use this driver must explicitly select REGMAP. =20 +config MDIO_SOCE + tristate "SoC-e MDIO controller" + depends on OF_MDIO && HAS_IOMEM + help + This module provides a driver for the MDIO controller integrated + into SoC-e Ethernet switch IP cores. + config MDIO_THUNDER tristate "ThunderX SOCs MDIO buses" depends on 64BIT diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile index 048586746026..079b46dea25f 100644 --- a/drivers/net/mdio/Makefile +++ b/drivers/net/mdio/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_MDIO_OCTEON) +=3D mdio-octeon.o obj-$(CONFIG_MDIO_PIC64HPSC) +=3D mdio-pic64hpsc.o obj-$(CONFIG_MDIO_REALTEK_RTL9300) +=3D mdio-realtek-rtl9300.o obj-$(CONFIG_MDIO_REGMAP) +=3D mdio-regmap.o +obj-$(CONFIG_MDIO_SOCE) +=3D mdio-soce.o obj-$(CONFIG_MDIO_SUN4I) +=3D mdio-sun4i.o obj-$(CONFIG_MDIO_THUNDER) +=3D mdio-thunder.o obj-$(CONFIG_MDIO_XGENE) +=3D mdio-xgene.o diff --git a/drivers/net/mdio/mdio-soce.c b/drivers/net/mdio/mdio-soce.c new file mode 100644 index 000000000000..59c0b3da483e --- /dev/null +++ b/drivers/net/mdio/mdio-soce.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2026 System on Chip engineering, S.L. + * Copyright (c) 2026 Linutronix GmbH + * Author: Vasilij Strassheim + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SOCE_MDIO_TIMEOUT_US 1000 + +#define SOCE_MDIO_PARAMS_OFFSET 0x0000 +#define SOCE_MDIO_WRITE_OFFSET 0x0004 +#define SOCE_MDIO_READ_OFFSET 0x0008 +#define SOCE_MDIO_DATA_IOMAP_IDX 0 +#define SOCE_MDIO_CTRL_IOMAP_IDX 1 + +#define SOCE_MDIO_CTRL_BUS_MASK GENMASK(26, 16) +#define SOCE_MDIO_CTRL_TRANSTYPE_MASK GENMASK(4, 3) +#define SOCE_MDIO_CTRL_TRANSTYPE_WRITE 0x1 +#define SOCE_MDIO_CTRL_TRANSTYPE_READ 0x3 +#define SOCE_MDIO_CTRL_CLAUSE BIT(1) +#define SOCE_MDIO_CTRL_OPSTATUS BIT(0) +#define SOCE_MDIO_PARAMS_REGDEV_MASK GENMASK(12, 8) +#define SOCE_MDIO_PARAMS_PHYADDR_MASK GENMASK(4, 0) +#define SOCE_MDIO_READ_DATA_MASK GENMASK(15, 0) + +struct soce_mdio { + void __iomem *ctrl; + void __iomem *data; +}; + +static void __iomem *soce_mdio_iomap(struct device *dev, int index) +{ + struct resource res; + int ret; + + ret =3D of_address_to_resource(dev->of_node, index, &res); + if (ret) + return IOMEM_ERR_PTR(ret); + + return devm_ioremap(dev, res.start, resource_size(&res)); +} + +static int soce_mdio_wait_for_idle(struct soce_mdio *priv) +{ + void __iomem *ctrl =3D priv->ctrl; + u32 val; + + return readl_poll_timeout(ctrl, val, + !(val & SOCE_MDIO_CTRL_OPSTATUS), 10, + SOCE_MDIO_TIMEOUT_US); +} + +static void soce_mdio_start(struct soce_mdio *priv, u32 command) +{ + void __iomem *ctrl =3D priv->ctrl; + + /* Keep the currently selected MDIO bus while updating op bits. */ + command |=3D readl(ctrl) & SOCE_MDIO_CTRL_BUS_MASK; + writel(command, ctrl); +} + +static int soce_mdio_read(struct mii_bus *bus, int phy_addr, int regnum) +{ + struct soce_mdio *priv =3D bus->priv; + void __iomem *data =3D priv->data; + u32 command; + int ret; + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + writel(FIELD_PREP(SOCE_MDIO_PARAMS_REGDEV_MASK, regnum) | + FIELD_PREP(SOCE_MDIO_PARAMS_PHYADDR_MASK, phy_addr), + data + SOCE_MDIO_PARAMS_OFFSET); + + command =3D FIELD_PREP(SOCE_MDIO_CTRL_TRANSTYPE_MASK, + SOCE_MDIO_CTRL_TRANSTYPE_READ) | + SOCE_MDIO_CTRL_OPSTATUS; + soce_mdio_start(priv, command); + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + return readl(data + SOCE_MDIO_READ_OFFSET) & SOCE_MDIO_READ_DATA_MASK; +} + +static int soce_mdio_read_c45(struct mii_bus *bus, int phy_addr, int devad, + int regnum) +{ + struct soce_mdio *priv =3D bus->priv; + void __iomem *data =3D priv->data; + u32 command; + int ret; + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + writel(FIELD_PREP(SOCE_MDIO_PARAMS_REGDEV_MASK, devad) | + FIELD_PREP(SOCE_MDIO_PARAMS_PHYADDR_MASK, phy_addr), + data + SOCE_MDIO_PARAMS_OFFSET); + writel(regnum, data + SOCE_MDIO_WRITE_OFFSET); + + command =3D SOCE_MDIO_CTRL_CLAUSE | SOCE_MDIO_CTRL_OPSTATUS; + soce_mdio_start(priv, command); + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + command =3D FIELD_PREP(SOCE_MDIO_CTRL_TRANSTYPE_MASK, + SOCE_MDIO_CTRL_TRANSTYPE_READ) | + SOCE_MDIO_CTRL_CLAUSE | SOCE_MDIO_CTRL_OPSTATUS; + soce_mdio_start(priv, command); + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + return readl(data + SOCE_MDIO_READ_OFFSET) & SOCE_MDIO_READ_DATA_MASK; +} + +static int soce_mdio_write(struct mii_bus *bus, int phy_addr, int regnum, + u16 val) +{ + struct soce_mdio *priv =3D bus->priv; + void __iomem *data =3D priv->data; + u32 command; + int ret; + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + writel(FIELD_PREP(SOCE_MDIO_PARAMS_REGDEV_MASK, regnum) | + FIELD_PREP(SOCE_MDIO_PARAMS_PHYADDR_MASK, phy_addr), + data + SOCE_MDIO_PARAMS_OFFSET); + writel(val, data + SOCE_MDIO_WRITE_OFFSET); + + command =3D FIELD_PREP(SOCE_MDIO_CTRL_TRANSTYPE_MASK, + SOCE_MDIO_CTRL_TRANSTYPE_WRITE) | + SOCE_MDIO_CTRL_OPSTATUS; + soce_mdio_start(priv, command); + + return soce_mdio_wait_for_idle(priv); +} + +static int soce_mdio_write_c45(struct mii_bus *bus, int phy_addr, int deva= d, + int regnum, u16 val) +{ + struct soce_mdio *priv =3D bus->priv; + void __iomem *data =3D priv->data; + u32 command; + int ret; + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + writel(FIELD_PREP(SOCE_MDIO_PARAMS_REGDEV_MASK, devad) | + FIELD_PREP(SOCE_MDIO_PARAMS_PHYADDR_MASK, phy_addr), + data + SOCE_MDIO_PARAMS_OFFSET); + writel(regnum, data + SOCE_MDIO_WRITE_OFFSET); + + command =3D SOCE_MDIO_CTRL_CLAUSE | SOCE_MDIO_CTRL_OPSTATUS; + soce_mdio_start(priv, command); + + ret =3D soce_mdio_wait_for_idle(priv); + if (ret) + return ret; + + writel(val, data + SOCE_MDIO_WRITE_OFFSET); + + command =3D FIELD_PREP(SOCE_MDIO_CTRL_TRANSTYPE_MASK, + SOCE_MDIO_CTRL_TRANSTYPE_WRITE) | + SOCE_MDIO_CTRL_CLAUSE | SOCE_MDIO_CTRL_OPSTATUS; + soce_mdio_start(priv, command); + + return soce_mdio_wait_for_idle(priv); +} + +static int soce_mdio_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct soce_mdio *priv; + struct mii_bus *bus; + + bus =3D devm_mdiobus_alloc_size(dev, sizeof(*priv)); + if (!bus) + return -ENOMEM; + + priv =3D bus->priv; + priv->data =3D soce_mdio_iomap(dev, SOCE_MDIO_DATA_IOMAP_IDX); + if (IS_ERR(priv->data)) + return PTR_ERR(priv->data); + + priv->ctrl =3D soce_mdio_iomap(dev, SOCE_MDIO_CTRL_IOMAP_IDX); + if (IS_ERR(priv->ctrl)) + return PTR_ERR(priv->ctrl); + + bus->name =3D "soce mdio"; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); + bus->parent =3D dev; + bus->read =3D soce_mdio_read; + bus->write =3D soce_mdio_write; + bus->read_c45 =3D soce_mdio_read_c45; + bus->write_c45 =3D soce_mdio_write_c45; + + return devm_of_mdiobus_register(dev, bus, dev->of_node); +} + +static const struct of_device_id soce_mdio_of_match[] =3D { + { .compatible =3D "soce,swip-mdio-23-02" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, soce_mdio_of_match); + +static struct platform_driver soce_mdio_driver =3D { + .probe =3D soce_mdio_probe, + .driver =3D { + .name =3D "soce-mdio", + .of_match_table =3D soce_mdio_of_match, + }, +}; +module_platform_driver(soce_mdio_driver); + +MODULE_AUTHOR("Vasilij Strassheim "); +MODULE_DESCRIPTION("SoC-e MDIO controller driver"); +MODULE_LICENSE("GPL"); --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 56B6547DD4A; Wed, 23 Sep 2026 10:39:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160003; cv=none; b=FTT3EFLgRU802lEqi3XAhYQ93DgcCtt9XX4W6Lz1HLp1wEWuQbmcFjN5X/Vtbi2qCXTFZ7N3QBVPX1NQHP+8cMd8xpbZxzyKrXm+d2C0FAmGXVmHfc5kZVDCCx6BnGXoUdsKOopKC0H6qBxfM+d2r3fZf47PloQA20tZQqjoJbY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160003; c=relaxed/simple; bh=DWT9MbCHPQn6zdPwdCWFrIndrpMFdiYIVnm2hh8er24=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B6uHF3jMW3idpdJNs1EphyGLsQvjlYDqiQ0e+ZbMMmSSBOu1w8uc4QCs6JYtuRNiX5KiApYl/EbN6yefp3n1vPtWfAw3LG+xY+2rWEsGb5SBSKobBBdSXOGZZiRzZJ6ZugdyD9jCOUzmOXukE9PNQh+4yTgWBM9q0frcK5c3gV4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=hIx5KBKd; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ArdMpQsd; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="hIx5KBKd"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ArdMpQsd" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159986; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SGV5gJ1K+1hayQcpyLjku4E+AA+xGbM2+h3g9lK5ihY=; b=hIx5KBKdMG59v/ZU5oECKrofkucueS2RzppScDbaX3J4wFffJgpwwNQQ9SlxMRrxuMy43g mNxp/w7VvnBO3p5JAJsuO0edjnW+/MrqsIap1l22qTDtz+fgzNzKUYSICfznoiZjR6ycfp h2Epq/Ur1Go0IYCShVLgrkvzidE34Di3KyYwEnGbXNacPmkxLkIFtVX9sKsaHWowe/Zo3m Mak4TM5wj+OgMR9MjorI59dnq/m19mvsJDlswUKxqLHjKXu6EHnGwFd3XHr6s2Gp+Tpz9O OPPYtEVCBGxic0Pwa+GaCGQsBydlZW3SOT0KorixRqzP3pgjp+o9TeYSUXBZiA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159986; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SGV5gJ1K+1hayQcpyLjku4E+AA+xGbM2+h3g9lK5ihY=; b=ArdMpQsdVr4JRqhdVWRmhoc+niKMFhDwWSCtfTisGQa0lXJJfiIM9le7cjB1p7gm++/16/ d88ASMVZWhk327BQ== Date: Wed, 23 Sep 2026 12:39:33 +0200 Subject: [PATCH net-next v3 6/8] net: dsa: soce: Add basic support for SoC-e switch IP cores Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-6-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim Add a DSA driver for SoC-e FPGA-based Ethernet switch IP cores. Read the core version and synthesis-time feature registers during probe. Require DSA support and between 3 and 31 implemented ports, without exceeding the licensed port count. Derive each port's phylink capabilities from its phy-mode. Enable "DSA custom rules" tagging for all frames during setup. This directs ingress traffic from user ports to the CPU port while standalone ports remain isolated. Enable and disable port ingress and egress through the DSA port callbacks, and disable tagging again during teardown so that unbinding the driver does not leave its managed configuration active. Populate the integrated MDIO controller and mux child devices used for external PHY access. Tested with a SoC-e MRS 25.01 IP core on a Xilinx ZynqMP platform. Signed-off-by: Vasilij Strassheim --- drivers/net/dsa/Kconfig | 2 + drivers/net/dsa/Makefile | 1 + drivers/net/dsa/soce/Kconfig | 14 ++ drivers/net/dsa/soce/Makefile | 4 + drivers/net/dsa/soce/soce_dsa.h | 26 +++ drivers/net/dsa/soce/soce_dsa_core.c | 343 +++++++++++++++++++++++++++++++= ++++ 6 files changed, 390 insertions(+) diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig index fe8cd5338fda..879fbede83f0 100644 --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig @@ -94,6 +94,8 @@ source "drivers/net/dsa/ocelot/Kconfig" =20 source "drivers/net/dsa/qca/Kconfig" =20 +source "drivers/net/dsa/soce/Kconfig" + source "drivers/net/dsa/sja1105/Kconfig" =20 source "drivers/net/dsa/xrs700x/Kconfig" diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile index 7e637d56b35c..97de3d181440 100644 --- a/drivers/net/dsa/Makefile +++ b/drivers/net/dsa/Makefile @@ -26,4 +26,5 @@ obj-y +=3D ocelot/ obj-y +=3D qca/ obj-y +=3D realtek/ obj-y +=3D sja1105/ +obj-y +=3D soce/ obj-y +=3D xrs700x/ diff --git a/drivers/net/dsa/soce/Kconfig b/drivers/net/dsa/soce/Kconfig new file mode 100644 index 000000000000..c31b7c5af695 --- /dev/null +++ b/drivers/net/dsa/soce/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +config NET_DSA_SOCE + tristate "SoC-e switches" + depends on NET_DSA + depends on OF + depends on HAS_IOMEM + select MDIO_BUS_MUX_MMIOREG + select MDIO_SOCE + select NET_DSA_TAG_SDSA + help + This enables support for switches based on SoC-e IP cores. + Frames are exchanged with the CPU port using the SDSA DSA tag protocol. + The driver supports switch variants whose features and number of ports + are selected at synthesis time and detected at runtime. diff --git a/drivers/net/dsa/soce/Makefile b/drivers/net/dsa/soce/Makefile new file mode 100644 index 000000000000..2a6d95ef663f --- /dev/null +++ b/drivers/net/dsa/soce/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_NET_DSA_SOCE) +=3D soce_dsa.o +soce_dsa-objs :=3D soce_dsa_core.o diff --git a/drivers/net/dsa/soce/soce_dsa.h b/drivers/net/dsa/soce/soce_ds= a.h new file mode 100644 index 000000000000..2acd4dbaf958 --- /dev/null +++ b/drivers/net/dsa/soce/soce_dsa.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020-2026 System on Chip engineering, S.L. + * Copyright (c) 2026 Linutronix GmbH + * Author: Vasilij Strassheim + */ + +#ifndef __SOCE_DSA_H +#define __SOCE_DSA_H + +#include + +#include + +#define SOCE_MAX_NUM_PORTS 31 + +struct soce_dsa_local { + void __iomem *base_addr; +}; + +struct soce_priv { + struct soce_dsa_local local; + struct dsa_switch ds; +}; + +#endif /* __SOCE_DSA_H */ diff --git a/drivers/net/dsa/soce/soce_dsa_core.c b/drivers/net/dsa/soce/so= ce_dsa_core.c new file mode 100644 index 000000000000..d391b11b94ad --- /dev/null +++ b/drivers/net/dsa/soce/soce_dsa_core.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2026 System on Chip engineering, S.L. + * Copyright (c) 2026 Linutronix GmbH + * Author: Vasilij Strassheim + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "soce_dsa.h" + +#define SOCE_MIN_NUM_PORTS 3 + +#define SOCE_CORE_VERSION_OFFSET 0x0000 +#define SOCE_CORE_VERSION_VERSION_SHIFT 24 +#define SOCE_CORE_VERSION_SUBVERSION_SHIFT 16 +#define SOCE_MIN_CORE_VERSION 0x24 +#define SOCE_MIN_CORE_SUBVERSION 0x01 + +#define SOCE_LIC_FEATURES_OFFSET 0x0004 +#define SOCE_LIC_FEATURES_NUM_PORTS_MASK GENMASK(31, 27) + +#define SOCE_IMPL_FEATURES0_OFFSET 0x000c +#define SOCE_IMPL_FEATURES0_NUM_PORTS_MASK GENMASK(31, 27) +#define SOCE_IMPL_FEATURES0_PORT_VLAN BIT(9) +#define SOCE_IMPL_FEATURES0_DSA BIT(23) + +#define SOCE_DSA_REGS_BASE 0x1200 +#define SOCE_TAG_ALL_FRAMES_CTRL_OFFSET (SOCE_DSA_REGS_BASE + 0x001c) +#define SOCE_TAG_ALL_FRAMES_CTRL_ENABLE BIT(0) +#define SOCE_CUSTOM_RULES_TAGGING_OFFSET (SOCE_DSA_REGS_BASE + 0x0020) +#define SOCE_CUSTOM_RULES_TAGGING_ENABLE BIT(0) + +#define SOCE_PORTS_REGS_BASE 0x3000 +#define SOCE_PORTS_SELECTOR_OFFSET SOCE_PORTS_REGS_BASE +#define SOCE_PORTS_SELECTOR_PORT_MASK GENMASK(7, 0) +#define SOCE_PORTS_CTRL_OFFSET (SOCE_PORTS_REGS_BASE + 0x0004) +#define SOCE_PORTS_CTRL_INGR_EN BIT(0) +#define SOCE_PORTS_CTRL_EGR_EN BIT(1) + +static void soce_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + struct dsa_port *dp =3D dsa_to_port(ds, port); + phy_interface_t mode; + int ret; + + ret =3D of_get_phy_mode(dp->dn, &mode); + if (ret) + return; + + if (phy_interface_mode_is_rgmii(mode)) + phy_interface_set_rgmii(config->supported_interfaces); + else + __set_bit(mode, config->supported_interfaces); + + config->mac_capabilities =3D MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + + switch (mode) { + case PHY_INTERFACE_MODE_MII: + config->mac_capabilities |=3D MAC_10 | MAC_100; + break; + case PHY_INTERFACE_MODE_GMII: + config->mac_capabilities |=3D MAC_10 | MAC_100 | MAC_1000; + break; + case PHY_INTERFACE_MODE_RMII: + config->mac_capabilities |=3D MAC_10FD | MAC_100FD; + break; + default: + if (phy_interface_mode_is_rgmii(mode)) + config->mac_capabilities |=3D MAC_10FD | MAC_100FD | + MAC_1000FD; + break; + } +} + +static int soce_sw_validate_core_version(u8 version, u8 subversion) +{ + if (version < SOCE_MIN_CORE_VERSION || + (version =3D=3D SOCE_MIN_CORE_VERSION && + subversion < SOCE_MIN_CORE_SUBVERSION)) + return -ENODEV; + + return 0; +} + +static void soce_sw_read_core_version(struct soce_dsa_local *local, + u8 *version, u8 *subversion, + u16 *revision) +{ + u32 regval; + + regval =3D readl(local->base_addr + SOCE_CORE_VERSION_OFFSET); + *version =3D (u8)(regval >> SOCE_CORE_VERSION_VERSION_SHIFT); + *subversion =3D (u8)(regval >> SOCE_CORE_VERSION_SUBVERSION_SHIFT); + *revision =3D (u16)regval; +} + +static int soce_sw_detect_features(struct soce_dsa_local *local, + u32 *numports) +{ + void __iomem *base =3D local->base_addr; + u32 implemented_numports; + u32 licensed_numports; + u32 regval; + + regval =3D readl(base + SOCE_LIC_FEATURES_OFFSET); + licensed_numports =3D FIELD_GET(SOCE_LIC_FEATURES_NUM_PORTS_MASK, regval); + if (!licensed_numports || licensed_numports > SOCE_MAX_NUM_PORTS) + return -EINVAL; + + regval =3D readl(base + SOCE_IMPL_FEATURES0_OFFSET); + if (!(regval & SOCE_IMPL_FEATURES0_DSA)) + return -ENODEV; + + implemented_numports =3D + FIELD_GET(SOCE_IMPL_FEATURES0_NUM_PORTS_MASK, regval); + if (implemented_numports < SOCE_MIN_NUM_PORTS || + implemented_numports > licensed_numports) + return -EINVAL; + + *numports =3D implemented_numports; + + return 0; +} + +static void soce_sw_enable_tagging(struct soce_dsa_local *local) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + regval =3D readl(base + SOCE_TAG_ALL_FRAMES_CTRL_OFFSET); + regval |=3D SOCE_TAG_ALL_FRAMES_CTRL_ENABLE; + writel(regval, base + SOCE_TAG_ALL_FRAMES_CTRL_OFFSET); + + regval =3D readl(base + SOCE_CUSTOM_RULES_TAGGING_OFFSET); + regval |=3D SOCE_CUSTOM_RULES_TAGGING_ENABLE; + writel(regval, base + SOCE_CUSTOM_RULES_TAGGING_OFFSET); +} + +static void soce_sw_disable_tagging(struct soce_dsa_local *local) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + regval =3D readl(base + SOCE_TAG_ALL_FRAMES_CTRL_OFFSET); + regval &=3D ~SOCE_TAG_ALL_FRAMES_CTRL_ENABLE; + writel(regval, base + SOCE_TAG_ALL_FRAMES_CTRL_OFFSET); + + regval =3D readl(base + SOCE_CUSTOM_RULES_TAGGING_OFFSET); + regval &=3D ~SOCE_CUSTOM_RULES_TAGGING_ENABLE; + writel(regval, base + SOCE_CUSTOM_RULES_TAGGING_OFFSET); +} + +static void soce_port_select(struct soce_dsa_local *local, int port) +{ + writel(FIELD_PREP(SOCE_PORTS_SELECTOR_PORT_MASK, port), + local->base_addr + SOCE_PORTS_SELECTOR_OFFSET); +} + +static void soce_port_set_enabled(struct soce_dsa_local *local, int port, + bool enabled) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + soce_port_select(local, port); + + regval =3D readl(base + SOCE_PORTS_CTRL_OFFSET); + if (enabled) + regval |=3D SOCE_PORTS_CTRL_INGR_EN | SOCE_PORTS_CTRL_EGR_EN; + else + regval &=3D ~(SOCE_PORTS_CTRL_INGR_EN | SOCE_PORTS_CTRL_EGR_EN); + writel(regval, base + SOCE_PORTS_CTRL_OFFSET); +} + +static int soce_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phy) +{ + struct soce_priv *priv =3D ds->priv; + + soce_port_set_enabled(&priv->local, port, true); + + return 0; +} + +static void soce_port_disable(struct dsa_switch *ds, int port) +{ + struct soce_priv *priv =3D ds->priv; + + soce_port_set_enabled(&priv->local, port, false); +} + +static int soce_setup(struct dsa_switch *ds) +{ + struct soce_priv *priv =3D ds->priv; + + soce_sw_enable_tagging(&priv->local); + + return 0; +} + +static void soce_teardown(struct dsa_switch *ds) +{ + struct soce_priv *priv =3D ds->priv; + + soce_sw_disable_tagging(&priv->local); +} + +static enum dsa_tag_protocol soce_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mprop) +{ + return DSA_TAG_PROTO_SDSA; +} + +static const struct dsa_switch_ops soce_switch_ops =3D { + .get_tag_protocol =3D soce_get_tag_protocol, + .setup =3D soce_setup, + .teardown =3D soce_teardown, + .phylink_get_caps =3D soce_phylink_get_caps, + .port_enable =3D soce_port_enable, + .port_disable =3D soce_port_disable, +}; + +static int soce_sw_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct soce_dsa_local *local; + struct soce_priv *priv; + struct dsa_switch *ds; + u8 hw_subversion; + u16 hw_revision; + u32 hw_numports; + u8 hw_version; + int ret; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ds =3D &priv->ds; + ds->dev =3D dev; + ds->priv =3D priv; + + local =3D &priv->local; + local->base_addr =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(local->base_addr)) + return PTR_ERR(local->base_addr); + + soce_sw_read_core_version(local, &hw_version, &hw_subversion, + &hw_revision); + + ret =3D soce_sw_detect_features(local, &hw_numports); + if (ret) { + if (ret =3D=3D -ENODEV) + dev_err(dev, "switch core does not implement DSA\n"); + else + dev_err(dev, + "invalid licensed or implemented features register\n"); + return ret; + } + + ret =3D soce_sw_validate_core_version(hw_version, hw_subversion); + if (ret) { + dev_err(dev, "unsupported switch core version %.2X.%.2X.%.4X\n", + hw_version, hw_subversion, hw_revision); + return ret; + } + + ds->ops =3D &soce_switch_ops; + ds->num_ports =3D hw_numports; + ret =3D devm_of_platform_populate(dev); + if (ret) + return dev_err_probe(dev, ret, + "failed to populate child devices\n"); + + dev_set_drvdata(dev, priv); + + ret =3D dsa_register_switch(ds); + if (ret) + return dev_err_probe(dev, ret, + "failed to register DSA switch\n"); + + dev_info(dev, + "probed soce switch core version %02x.%02x.%04x with %u ports\n", + hw_version, hw_subversion, hw_revision, hw_numports); + return 0; +} + +static void soce_sw_remove(struct platform_device *pdev) +{ + struct soce_priv *priv =3D platform_get_drvdata(pdev); + + if (!priv) + return; + + dsa_unregister_switch(&priv->ds); + platform_set_drvdata(pdev, NULL); +} + +static void soce_sw_shutdown(struct platform_device *pdev) +{ + struct soce_priv *priv =3D platform_get_drvdata(pdev); + + if (!priv) + return; + + dsa_switch_shutdown(&priv->ds); + platform_set_drvdata(pdev, NULL); +} + +static const struct of_device_id soce_of_match[] =3D { + { .compatible =3D "soce,swip-00-04-0c-10" }, + { /* sentinel */ } +}; + +static struct platform_driver soce_driver =3D { + .probe =3D soce_sw_probe, + .remove =3D soce_sw_remove, + .shutdown =3D soce_sw_shutdown, + .driver =3D { + .name =3D "soce-swip", + .of_match_table =3D soce_of_match, + }, +}; + +module_platform_driver(soce_driver); +MODULE_DEVICE_TABLE(of, soce_of_match); +MODULE_AUTHOR("Vasilij Strassheim "); +MODULE_DESCRIPTION("Driver for SoC-e ethernet switch family"); +MODULE_LICENSE("GPL"); +MODULE_SOFTDEP("pre: mdio-soce mdio-mux-mmioreg"); --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 17BB3494835; Wed, 23 Sep 2026 10:39:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160002; cv=none; b=MsVQtg9+/+GzayUCoO5Ddw2Q89FoZK+0uDOEw5QLRQoeDkgXfzgYm3CAimAK+ifsLNDKwJHlsVoaVlhM/iSsxGhCqTDopZzD3A+Bx/OjjLiku0TnACePNseZFSi6NMf6SLLYSKniyYZgVD+OxFzQWmCV7v3frnKRJ8PF1UPlsBg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160002; c=relaxed/simple; bh=TxwSK6Y0b5TgpjR7a/u719a4G3NxmNq7t9yj8Gg3aZg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y/cXCoAunMLdx+A6U6fgE5cLaGMBrFgQrBopQEw5Tw/Kyvt8+Sih81ZHx2JSJ+7dk1OlLcBslCLkciz2mIfbhylqfI86zCNs4Y4OQuhN+U7+Gzi4rEAQ3aZEmm12RBpxb632HlRZ2u/LqQC4XOKhsIPaegI6YzN0VgiIoo9gF6s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=zPeKSvT4; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=mD/fNZMi; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="zPeKSvT4"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="mD/fNZMi" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159987; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RxHIQMNUG0po+e6KZ3ydpoDSMlER+beOviOrigSCjqU=; b=zPeKSvT4YbA0kFlveoNHgxX7WhWkCkA8d68zIz1POP7Dppu4IBTKHCvJI40cNw/ttxqlwc S8ybQSgKMfFiaSNVRsw8wWzqgO4EHixU1x+e8mw+O/2DpEm3AZ1JTicKLvpEcumPw+CnCm fIQ4Ys0P7qPzHrORuMOc8RdzBzXmsYzL6Y6Bv2XwhoZzBbI9YXXHhBXTLisSS1EN8MtCC5 8O/qAP9alvAwP5iYmHc57uwCFI6JOQD0wJQLFUfQDNk9d4x1b66A0BSwxU3qpSOLyAgXJr cft1nnJDDVDCufnvXk4EKTxtn8H2waSmGknf3PZ1E5TNxEHiTJnm4U/FQOs4rQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159987; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RxHIQMNUG0po+e6KZ3ydpoDSMlER+beOviOrigSCjqU=; b=mD/fNZMiRImlX+VoTci6FpT/tZXUBAF9/GYhFKYaxlTk/dKHnk9/ygCfIJMuTEe9r5pgZ0 wm1a1X5FV3Nf9GAg== Date: Wed, 23 Sep 2026 12:39:34 +0200 Subject: [PATCH net-next v3 7/8] net: dsa: soce: Add VLAN offload support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-7-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim Add VLAN filtering and membership offload for switch configurations that implement the Port VLAN synthesis option. Without this feature active, the switch removes VLAN information on CPU ingress without including the removed information in the DSA tag. To avoid silent drops and misbehaviour in this case, reject VLAN operations with a netlink extended acknowledgment. If the feature is available, configure ports in Hybrid and C-Port modes and manage their PVID, ingress filtering and acceptance mode, and custom egress untagging. Program the per-VID member and untagged port masks through the hardware selector interface. The port and VID selectors are shared by all VLAN operations, so serialize selector and data register sequences with a dedicated mutex. Track member and untagged masks in software and restore the shadow state if programming fails. Signed-off-by: Vasilij Strassheim --- drivers/net/dsa/soce/soce_dsa.h | 11 + drivers/net/dsa/soce/soce_dsa_core.c | 388 +++++++++++++++++++++++++++++++= +++- 2 files changed, 392 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/soce/soce_dsa.h b/drivers/net/dsa/soce/soce_ds= a.h index 2acd4dbaf958..41533a89d680 100644 --- a/drivers/net/dsa/soce/soce_dsa.h +++ b/drivers/net/dsa/soce/soce_dsa.h @@ -9,6 +9,7 @@ #define __SOCE_DSA_H =20 #include +#include =20 #include =20 @@ -18,8 +19,18 @@ struct soce_dsa_local { void __iomem *base_addr; }; =20 +struct soce_features { + u32 num_ports; + bool port_vlan; +}; + struct soce_priv { struct soce_dsa_local local; + struct soce_features features; + struct mutex vlan_lock; /* Serializes selector-based VLAN accesses */ + u32 *vlan_members; + u32 *vlan_untagged; + u16 port_pvid[SOCE_MAX_NUM_PORTS]; struct dsa_switch ds; }; =20 diff --git a/drivers/net/dsa/soce/soce_dsa_core.c b/drivers/net/dsa/soce/so= ce_dsa_core.c index d391b11b94ad..f93ce9da8400 100644 --- a/drivers/net/dsa/soce/soce_dsa_core.c +++ b/drivers/net/dsa/soce/soce_dsa_core.c @@ -5,7 +5,10 @@ * Author: Vasilij Strassheim */ =20 +#include +#include #include +#include #include #include #include @@ -48,6 +51,39 @@ #define SOCE_PORTS_CTRL_INGR_EN BIT(0) #define SOCE_PORTS_CTRL_EGR_EN BIT(1) =20 +#define SOCE_VLAN_REGS_BASE 0x0d00 +#define SOCE_VLAN_CTRL_OFFSET SOCE_VLAN_REGS_BASE +#define SOCE_VLAN_CTRL_ENABLE BIT(0) +#define SOCE_VLAN_RESET_OFFSET (SOCE_VLAN_REGS_BASE + 0x0004) +#define SOCE_VLAN_RESET_CMD BIT(0) +#define SOCE_VLAN_PORT_SEL_OFFSET (SOCE_VLAN_REGS_BASE + 0x0010) +#define SOCE_VLAN_PORT_SEL_PORT_MASK GENMASK(7, 0) +#define SOCE_VLAN_PORT_MODE_OFFSET (SOCE_VLAN_REGS_BASE + 0x0014) +#define SOCE_VLAN_PORT_MODE_HYBRID 0x2 +#define SOCE_VLAN_PORT_TYPE_OFFSET (SOCE_VLAN_REGS_BASE + 0x0018) +#define SOCE_VLAN_PORT_TYPE_UNAWARE 0x0 +#define SOCE_VLAN_PORT_TYPE_C_PORT 0x1 +#define SOCE_VLAN_PORT_VLAN_OFFSET (SOCE_VLAN_REGS_BASE + 0x001c) +#define SOCE_VLAN_PORT_VLAN_PVID_MASK GENMASK(11, 0) +#define SOCE_VLAN_PORT_INGR_FILTER_OFFSET (SOCE_VLAN_REGS_BASE + 0x0020) +#define SOCE_VLAN_PORT_INGR_FILTER_EN BIT(0) +#define SOCE_VLAN_PORT_INGR_ACCEPT_OFFSET (SOCE_VLAN_REGS_BASE + 0x0024) +#define SOCE_VLAN_PORT_INGR_ACCEPT_ALL 0x0 +#define SOCE_VLAN_PORT_INGR_ACCEPT_TAGGED_ONLY 0x1 +#define SOCE_VLAN_PORT_EGR_TAG_OFFSET (SOCE_VLAN_REGS_BASE + 0x0028) +#define SOCE_VLAN_PORT_EGR_TAG_MASK GENMASK(1, 0) +#define SOCE_VLAN_PORT_EGR_TAG_UNTAG_PORT 0x0 +#define SOCE_VLAN_PORT_EGR_TAG_CUSTOM_UNTAG 0x3 +#define SOCE_VLAN_VID_SEL_OFFSET (SOCE_VLAN_REGS_BASE + 0x002c) +#define SOCE_VLAN_VID_SEL_VID_MASK GENMASK(11, 0) +#define SOCE_VLAN_MEMBER_CTRL_OFFSET (SOCE_VLAN_REGS_BASE + 0x0030) +#define SOCE_VLAN_MEMBER_CTRL_WRITE BIT(0) +#define SOCE_VLAN_MEMBER_PORTS_OFFSET (SOCE_VLAN_REGS_BASE + 0x0034) +#define SOCE_VLAN_UNTAG_CTRL_OFFSET (SOCE_VLAN_REGS_BASE + 0x003c) +#define SOCE_VLAN_UNTAG_CTRL_WRITE BIT(0) +#define SOCE_VLAN_UNTAG_PORTS_OFFSET (SOCE_VLAN_REGS_BASE + 0x0040) +#define SOCE_VLAN_CMD_TIMEOUT_US 1000 + static void soce_phylink_get_caps(struct dsa_switch *ds, int port, struct phylink_config *config) { @@ -107,7 +143,7 @@ static void soce_sw_read_core_version(struct soce_dsa_l= ocal *local, } =20 static int soce_sw_detect_features(struct soce_dsa_local *local, - u32 *numports) + struct soce_features *features) { void __iomem *base =3D local->base_addr; u32 implemented_numports; @@ -123,13 +159,15 @@ static int soce_sw_detect_features(struct soce_dsa_lo= cal *local, if (!(regval & SOCE_IMPL_FEATURES0_DSA)) return -ENODEV; =20 + features->port_vlan =3D regval & SOCE_IMPL_FEATURES0_PORT_VLAN; + implemented_numports =3D FIELD_GET(SOCE_IMPL_FEATURES0_NUM_PORTS_MASK, regval); if (implemented_numports < SOCE_MIN_NUM_PORTS || implemented_numports > licensed_numports) return -EINVAL; =20 - *numports =3D implemented_numports; + features->num_ports =3D implemented_numports; =20 return 0; } @@ -162,6 +200,178 @@ static void soce_sw_disable_tagging(struct soce_dsa_l= ocal *local) writel(regval, base + SOCE_CUSTOM_RULES_TAGGING_OFFSET); } =20 +static void soce_vlan_set_enabled(struct soce_dsa_local *local, bool enabl= ed) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + regval =3D readl(base + SOCE_VLAN_CTRL_OFFSET); + if (enabled) + regval |=3D SOCE_VLAN_CTRL_ENABLE; + else + regval &=3D ~SOCE_VLAN_CTRL_ENABLE; + writel(regval, base + SOCE_VLAN_CTRL_OFFSET); +} + +static int soce_vlan_reset(struct soce_dsa_local *local) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + writel(SOCE_VLAN_RESET_CMD, base + SOCE_VLAN_RESET_OFFSET); + + return readl_poll_timeout(base + SOCE_VLAN_RESET_OFFSET, + regval, !(regval & SOCE_VLAN_RESET_CMD), 10, + SOCE_VLAN_CMD_TIMEOUT_US); +} + +static int soce_vlan_wait_for_write(struct soce_dsa_local *local, u32 offs= et, + u32 mask) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + return readl_poll_timeout(base + offset, regval, + !(regval & mask), 10, + SOCE_VLAN_CMD_TIMEOUT_US); +} + +static void soce_vlan_select_port(struct soce_dsa_local *local, int port) +{ + writel(FIELD_PREP(SOCE_VLAN_PORT_SEL_PORT_MASK, port), + local->base_addr + SOCE_VLAN_PORT_SEL_OFFSET); +} + +static void soce_vlan_select_vid(struct soce_dsa_local *local, u16 vid) +{ + writel(FIELD_PREP(SOCE_VLAN_VID_SEL_VID_MASK, vid), + local->base_addr + SOCE_VLAN_VID_SEL_OFFSET); +} + +static void soce_vlan_config_port(struct soce_priv *priv, int port, + bool vlan_filtering) +{ + struct soce_dsa_local *local =3D &priv->local; + void __iomem *base =3D local->base_addr; + u32 egress_tagging; + u32 port_type; + u32 regval; + u32 accept; + + port_type =3D vlan_filtering ? SOCE_VLAN_PORT_TYPE_C_PORT : + SOCE_VLAN_PORT_TYPE_UNAWARE; + egress_tagging =3D vlan_filtering ? SOCE_VLAN_PORT_EGR_TAG_CUSTOM_UNTAG : + SOCE_VLAN_PORT_EGR_TAG_UNTAG_PORT; + + soce_vlan_select_port(local, port); + writel(SOCE_VLAN_PORT_MODE_HYBRID, base + SOCE_VLAN_PORT_MODE_OFFSET); + writel(port_type, base + SOCE_VLAN_PORT_TYPE_OFFSET); + writel(FIELD_PREP(SOCE_VLAN_PORT_VLAN_PVID_MASK, + priv->port_pvid[port]), + base + SOCE_VLAN_PORT_VLAN_OFFSET); + writel(vlan_filtering ? SOCE_VLAN_PORT_INGR_FILTER_EN : 0, + base + SOCE_VLAN_PORT_INGR_FILTER_OFFSET); + + /* Without a PVID, untagged frames have no VLAN to be classified + * into, so only accept tagged frames while filtering. + */ + accept =3D vlan_filtering && !priv->port_pvid[port] ? + SOCE_VLAN_PORT_INGR_ACCEPT_TAGGED_ONLY : + SOCE_VLAN_PORT_INGR_ACCEPT_ALL; + writel(accept, base + SOCE_VLAN_PORT_INGR_ACCEPT_OFFSET); + + regval =3D readl(base + SOCE_VLAN_PORT_EGR_TAG_OFFSET); + regval &=3D ~SOCE_VLAN_PORT_EGR_TAG_MASK; + regval |=3D FIELD_PREP(SOCE_VLAN_PORT_EGR_TAG_MASK, egress_tagging); + writel(regval, base + SOCE_VLAN_PORT_EGR_TAG_OFFSET); +} + +static int soce_vlan_write_entry(struct soce_priv *priv, u16 vid) +{ + struct soce_dsa_local *local =3D &priv->local; + void __iomem *base =3D local->base_addr; + u32 cpu_ports; + u32 untagged; + u32 members; + int ret; + + /* The CPU port must be a tagged member of every active VLAN so + * tagged frames can reach the conduit. + */ + cpu_ports =3D dsa_cpu_ports(&priv->ds); + members =3D priv->vlan_members[vid]; + if (members) + members |=3D cpu_ports; + untagged =3D priv->vlan_untagged[vid] & ~cpu_ports; + + soce_vlan_select_vid(local, vid); + writel(members, base + SOCE_VLAN_MEMBER_PORTS_OFFSET); + writel(SOCE_VLAN_MEMBER_CTRL_WRITE, + base + SOCE_VLAN_MEMBER_CTRL_OFFSET); + ret =3D soce_vlan_wait_for_write(local, SOCE_VLAN_MEMBER_CTRL_OFFSET, + SOCE_VLAN_MEMBER_CTRL_WRITE); + if (ret) + return ret; + + writel(untagged, base + SOCE_VLAN_UNTAG_PORTS_OFFSET); + writel(SOCE_VLAN_UNTAG_CTRL_WRITE, + base + SOCE_VLAN_UNTAG_CTRL_OFFSET); + + return soce_vlan_wait_for_write(local, SOCE_VLAN_UNTAG_CTRL_OFFSET, + SOCE_VLAN_UNTAG_CTRL_WRITE); +} + +static int soce_vlan_setup(struct dsa_switch *ds) +{ + struct soce_priv *priv =3D ds->priv; + struct soce_dsa_local *local; + struct dsa_port *dp; + int ret; + + local =3D &priv->local; + + if (!priv->features.port_vlan) + return 0; + + ret =3D soce_vlan_reset(local); + if (ret) { + dev_err(ds->dev, "failed to reset VLAN configuration: %d\n", + ret); + return ret; + } + + /* Default every port to PVID 1, unfiltered, so standalone + * forwarding keeps working before any bridge VLAN is configured. + */ + scoped_guard(mutex, &priv->vlan_lock) { + dsa_switch_for_each_available_port(dp, ds) { + priv->port_pvid[dp->index] =3D 1; + soce_vlan_config_port(priv, dp->index, false); + } + soce_vlan_set_enabled(local, true); + } + + return 0; +} + +static void soce_vlan_teardown(struct soce_priv *priv) +{ + struct soce_dsa_local *local =3D &priv->local; + int ret; + + if (!priv->features.port_vlan) + return; + + scoped_guard(mutex, &priv->vlan_lock) { + ret =3D soce_vlan_reset(local); + if (ret) + dev_warn(priv->ds.dev, + "failed to reset VLAN configuration during teardown: %d\n", + ret); + soce_vlan_set_enabled(local, false); + } +} + static void soce_port_select(struct soce_dsa_local *local, int port) { writel(FIELD_PREP(SOCE_PORTS_SELECTOR_PORT_MASK, port), @@ -204,6 +414,11 @@ static void soce_port_disable(struct dsa_switch *ds, i= nt port) static int soce_setup(struct dsa_switch *ds) { struct soce_priv *priv =3D ds->priv; + int ret; + + ret =3D soce_vlan_setup(ds); + if (ret) + return ret; =20 soce_sw_enable_tagging(&priv->local); =20 @@ -213,8 +428,12 @@ static int soce_setup(struct dsa_switch *ds) static void soce_teardown(struct dsa_switch *ds) { struct soce_priv *priv =3D ds->priv; + struct soce_dsa_local *local; + + local =3D &priv->local; =20 - soce_sw_disable_tagging(&priv->local); + soce_sw_disable_tagging(local); + soce_vlan_teardown(priv); } =20 static enum dsa_tag_protocol soce_get_tag_protocol(struct dsa_switch *ds, @@ -224,6 +443,130 @@ static enum dsa_tag_protocol soce_get_tag_protocol(st= ruct dsa_switch *ds, return DSA_TAG_PROTO_SDSA; } =20 +static int soce_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) +{ + struct dsa_port *dp =3D dsa_to_port(ds, port); + struct soce_priv *priv =3D ds->priv; + u32 port_mask =3D BIT(port); + u32 *untagged_ports; + u32 old_untagged; + u32 old_members; + bool untagged; + u32 *members; + int ret; + + untagged_ports =3D priv->vlan_untagged; + members =3D priv->vlan_members; + + if (!priv->features.port_vlan) { + NL_SET_ERR_MSG_MOD(extack, + "Port VLAN support is not implemented in the switch core"); + return -EOPNOTSUPP; + } + + if (!vlan->vid) + return 0; + + untagged =3D vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + + scoped_guard(mutex, &priv->vlan_lock) { + old_members =3D members[vlan->vid]; + old_untagged =3D untagged_ports[vlan->vid]; + + members[vlan->vid] |=3D port_mask; + if (untagged) + untagged_ports[vlan->vid] |=3D port_mask; + else + untagged_ports[vlan->vid] &=3D ~port_mask; + + ret =3D soce_vlan_write_entry(priv, vlan->vid); + if (ret) { + NL_SET_ERR_MSG_MOD(extack, + "failed to update VLAN hardware tables"); + dev_err(ds->dev, + "failed to add VLAN %u on port %d: %d\n", + vlan->vid, port, ret); + members[vlan->vid] =3D old_members; + untagged_ports[vlan->vid] =3D old_untagged; + return ret; + } + + if (vlan->flags & BRIDGE_VLAN_INFO_PVID) { + priv->port_pvid[port] =3D vlan->vid; + soce_vlan_config_port(priv, port, + dsa_port_is_vlan_filtering(dp)); + } + } + + return ret; +} + +static int soce_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct dsa_port *dp =3D dsa_to_port(ds, port); + struct soce_priv *priv =3D ds->priv; + u32 port_mask =3D BIT(port); + u32 *untagged_ports; + u32 old_untagged; + u32 old_members; + u32 *members; + int ret; + + untagged_ports =3D priv->vlan_untagged; + members =3D priv->vlan_members; + + if (!priv->features.port_vlan) + return -EOPNOTSUPP; + + if (!vlan->vid) + return 0; + + scoped_guard(mutex, &priv->vlan_lock) { + old_members =3D members[vlan->vid]; + old_untagged =3D untagged_ports[vlan->vid]; + members[vlan->vid] &=3D ~port_mask; + untagged_ports[vlan->vid] &=3D ~port_mask; + ret =3D soce_vlan_write_entry(priv, vlan->vid); + if (ret) { + dev_err(ds->dev, + "failed to delete VLAN %u from port %d: %d\n", + vlan->vid, port, ret); + members[vlan->vid] =3D old_members; + untagged_ports[vlan->vid] =3D old_untagged; + return ret; + } + + if (priv->port_pvid[port] =3D=3D vlan->vid) { + priv->port_pvid[port] =3D 0; + soce_vlan_config_port(priv, port, + dsa_port_is_vlan_filtering(dp)); + } + } + + return ret; +} + +static int soce_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering, + struct netlink_ext_ack *extack) +{ + struct soce_priv *priv =3D ds->priv; + + if (!priv->features.port_vlan) { + NL_SET_ERR_MSG_MOD(extack, + "Port VLAN support is not implemented in the switch core"); + return -EOPNOTSUPP; + } + + scoped_guard(mutex, &priv->vlan_lock) + soce_vlan_config_port(priv, port, vlan_filtering); + + return 0; +} + static const struct dsa_switch_ops soce_switch_ops =3D { .get_tag_protocol =3D soce_get_tag_protocol, .setup =3D soce_setup, @@ -231,6 +574,9 @@ static const struct dsa_switch_ops soce_switch_ops =3D { .phylink_get_caps =3D soce_phylink_get_caps, .port_enable =3D soce_port_enable, .port_disable =3D soce_port_disable, + .port_vlan_filtering =3D soce_port_vlan_filtering, + .port_vlan_add =3D soce_port_vlan_add, + .port_vlan_del =3D soce_port_vlan_del, }; =20 static int soce_sw_probe(struct platform_device *pdev) @@ -241,7 +587,6 @@ static int soce_sw_probe(struct platform_device *pdev) struct dsa_switch *ds; u8 hw_subversion; u16 hw_revision; - u32 hw_numports; u8 hw_version; int ret; =20 @@ -261,7 +606,7 @@ static int soce_sw_probe(struct platform_device *pdev) soce_sw_read_core_version(local, &hw_version, &hw_subversion, &hw_revision); =20 - ret =3D soce_sw_detect_features(local, &hw_numports); + ret =3D soce_sw_detect_features(local, &priv->features); if (ret) { if (ret =3D=3D -ENODEV) dev_err(dev, "switch core does not implement DSA\n"); @@ -278,8 +623,35 @@ static int soce_sw_probe(struct platform_device *pdev) return ret; } =20 + if (priv->features.port_vlan) { + ret =3D devm_mutex_init(dev, &priv->vlan_lock); + if (ret) + return ret; + + priv->vlan_members =3D + devm_kcalloc(dev, VLAN_N_VID, + sizeof(*priv->vlan_members), GFP_KERNEL); + if (!priv->vlan_members) + return -ENOMEM; + + priv->vlan_untagged =3D + devm_kcalloc(dev, VLAN_N_VID, + sizeof(*priv->vlan_untagged), GFP_KERNEL); + if (!priv->vlan_untagged) + return -ENOMEM; + } else { + dev_warn(dev, + "VLAN-tagged frames received on the CPU port are unsupported\n"); + } + ds->ops =3D &soce_switch_ops; - ds->num_ports =3D hw_numports; + ds->num_ports =3D priv->features.num_ports; + + /* Force VLAN uppers always through the callbacks, so cores without + * Port VLAN feature can reject them instead of silently dropping + * VLAN frames. + */ + ds->needs_standalone_vlan_filtering =3D true; ret =3D devm_of_platform_populate(dev); if (ret) return dev_err_probe(dev, ret, @@ -294,7 +666,9 @@ static int soce_sw_probe(struct platform_device *pdev) =20 dev_info(dev, "probed soce switch core version %02x.%02x.%04x with %u ports\n", - hw_version, hw_subversion, hw_revision, hw_numports); + hw_version, hw_subversion, hw_revision, + priv->features.num_ports); + return 0; } =20 --=20 2.39.5 From nobody Thu Sep 24 12:55:45 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 3E70E483829; Wed, 23 Sep 2026 10:39:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160001; cv=none; b=LNNGS7trpkgxdZP1FiA4Z9o3+T1SWRzm1IctfTVJXeph6VSCI2VuwZOq7KU2lVpjT4MTtGIbG+OCS39k5txBhtTE5oexozmDlsFkmdma9ZFji35l1qQTxjZfE21J9Lq7393fhHMV9q5DeEuVUadNu+INKxliMwJqBMryn15mv48= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790160001; c=relaxed/simple; bh=+Cu7ELct7CYfKS56sCulkTJS1lam6OhwEzqTSoJ8Zg8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ewmAiLklVg4ujW1kEZnNys5dEq+C16D4PlT8utnq9q3zblmmzpTy9UlO3bmlb/FfsfC/eK5Y08Okvo6+4tLeuhwVaDVESWKTuiwmaOdP4SJh0d6bv3sCXSJrDM1+LpDVNXi5IObEX03YGNJUYWMnbF1LuRemJjf8uL4Av9R1i4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=sgOVOKml; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=kYutQOp7; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="sgOVOKml"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="kYutQOp7" From: Vasilij Strassheim DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1790159988; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pIJqn7gYsblS+oZECmBr3OHJ+dooqIeQBXuGu2zSZ3k=; b=sgOVOKmlAvrnnPqH+QYn0uJZclTkHJeO2AfKNulUlBRhNH3sYI6qVc+FD25o0zsuPjuAT0 hVVWgk8yxHaiIm7+vzH2rYkPlsHasUOL2qsmN9ARFjUgOcUyzV2RUMLFXA+0I15mGd1Fp4 w1yR179/wQm2W3dnMBX/Ra0KaP2xHJPNfrTqYN9aZCN78ANx84igH1bkmLEQO055WDYFcd oKQF63oB45jPP8XXISC6gCuIqh1EXhjPqOo9Kz3dbB+D2f7QZBjdEGw84fSeu00XzfPPdu 4EJfsW27WKPhz43seS5iT2h1nwKxcJOQZsiM3YQo4bGDO9iKJ3Zh9H50yNctcQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1790159988; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pIJqn7gYsblS+oZECmBr3OHJ+dooqIeQBXuGu2zSZ3k=; b=kYutQOp7o02Xk+OmrUMorfr18dtgpD4LAMHxVXfGxVlHEmoZqGGFvDiqYExKZ3To/t1y/E ewKBRf2XHEKqs3Cw== Date: Wed, 23 Sep 2026 12:39:35 +0200 Subject: [PATCH net-next v3 8/8] net: dsa: soce: Disable unsupported hardware STP Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260923-devel-vstrassheim-soce-dsa-ml-v3-8-ddebafcb9ba7@linutronix.de> References: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> In-Reply-To: <20260923-devel-vstrassheim-soce-dsa-ml-v3-0-ddebafcb9ba7@linutronix.de> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Andrew Lunn , Heiner Kallweit Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Martin Kaistra , Benedikt Spranger , Vasilij Strassheim The driver does not implement hardware STP offloading yet. Switch cores synthesized with the STP feature enabled may therefore retain their reset configuration and block frame forwarding. Detect the synthesized STP feature and disable it during switch setup, leaving STP state handling to the Linux bridge. Signed-off-by: Vasilij Strassheim --- drivers/net/dsa/soce/soce_dsa.h | 1 + drivers/net/dsa/soce/soce_dsa_core.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/net/dsa/soce/soce_dsa.h b/drivers/net/dsa/soce/soce_ds= a.h index 41533a89d680..bb9e65567ec6 100644 --- a/drivers/net/dsa/soce/soce_dsa.h +++ b/drivers/net/dsa/soce/soce_dsa.h @@ -22,6 +22,7 @@ struct soce_dsa_local { struct soce_features { u32 num_ports; bool port_vlan; + bool stp; }; =20 struct soce_priv { diff --git a/drivers/net/dsa/soce/soce_dsa_core.c b/drivers/net/dsa/soce/so= ce_dsa_core.c index f93ce9da8400..3b9fde7a547e 100644 --- a/drivers/net/dsa/soce/soce_dsa_core.c +++ b/drivers/net/dsa/soce/soce_dsa_core.c @@ -36,6 +36,7 @@ #define SOCE_IMPL_FEATURES0_OFFSET 0x000c #define SOCE_IMPL_FEATURES0_NUM_PORTS_MASK GENMASK(31, 27) #define SOCE_IMPL_FEATURES0_PORT_VLAN BIT(9) +#define SOCE_IMPL_FEATURES0_STP BIT(20) #define SOCE_IMPL_FEATURES0_DSA BIT(23) =20 #define SOCE_DSA_REGS_BASE 0x1200 @@ -51,6 +52,10 @@ #define SOCE_PORTS_CTRL_INGR_EN BIT(0) #define SOCE_PORTS_CTRL_EGR_EN BIT(1) =20 +#define SOCE_STP_REGS_BASE 0x0f00 +#define SOCE_STP_CTRL_OFFSET SOCE_STP_REGS_BASE +#define SOCE_STP_CTRL_ENABLE BIT(0) + #define SOCE_VLAN_REGS_BASE 0x0d00 #define SOCE_VLAN_CTRL_OFFSET SOCE_VLAN_REGS_BASE #define SOCE_VLAN_CTRL_ENABLE BIT(0) @@ -160,6 +165,7 @@ static int soce_sw_detect_features(struct soce_dsa_loca= l *local, return -ENODEV; =20 features->port_vlan =3D regval & SOCE_IMPL_FEATURES0_PORT_VLAN; + features->stp =3D regval & SOCE_IMPL_FEATURES0_STP; =20 implemented_numports =3D FIELD_GET(SOCE_IMPL_FEATURES0_NUM_PORTS_MASK, regval); @@ -200,6 +206,16 @@ static void soce_sw_disable_tagging(struct soce_dsa_lo= cal *local) writel(regval, base + SOCE_CUSTOM_RULES_TAGGING_OFFSET); } =20 +static void soce_stp_disable(struct soce_dsa_local *local) +{ + void __iomem *base =3D local->base_addr; + u32 regval; + + regval =3D readl(base + SOCE_STP_CTRL_OFFSET); + regval &=3D ~SOCE_STP_CTRL_ENABLE; + writel(regval, base + SOCE_STP_CTRL_OFFSET); +} + static void soce_vlan_set_enabled(struct soce_dsa_local *local, bool enabl= ed) { void __iomem *base =3D local->base_addr; @@ -420,6 +436,10 @@ static int soce_setup(struct dsa_switch *ds) if (ret) return ret; =20 + /* Unconfigured hardware STP blocks frame forwarding. */ + if (priv->features.stp) + soce_stp_disable(&priv->local); + soce_sw_enable_tagging(&priv->local); =20 return 0; --=20 2.39.5