From patchwork Mon Oct 23 15:50:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain Gantois X-Patchwork-Id: 13433087 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 064C8C001E0 for ; Mon, 23 Oct 2023 15:50:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=mPGUXnQBc9JdpeJFxFw16CkD5p2U3SwTYl5/yo+3UOE=; b=rVD5skuTrc3e4E vFjWXj/Du8e1HFUp+W2YVmhuT+UZcc+/CW2/SRyvwP0XwNLLLUpLmreoWfBMXerTaoxyepsNBchcc lAXsGJSTuoBa6Wmw364Dn59EjlBTbFLfWddA/MlHIrlBIoB7D977MKJzAnM2C+dKfJEUWdIGE4BH0 mWCQ+rgVrMHcI2u7xnFhGQsTQH1qwLfB27we1cRVafYLQ0LelzMbpC4Hm3Za6pHnBf7CRM5u6Ei8m XnawuWyJ0bixKtvSf6KhDtJrDTG2yIKvgiodf1vt8ajb3blPBdLvDHZLlSss4M65fnKYVsxtX7HGY /t/3S2Q5QQVaWQqsZB/w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1quxC5-007k9V-2a; Mon, 23 Oct 2023 15:50:17 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1quxC2-007k7P-0K for linux-arm-kernel@lists.infradead.org; Mon, 23 Oct 2023 15:50:16 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id E2FB91BF208; Mon, 23 Oct 2023 15:50:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1698076208; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yuCpGuToREVg41/lmByogXykAGaEM+x67Szl0gpgQI4=; b=dv9LlfqineMcniEywwvOfYShADtiCDoO0eYL7fzbATZnKBu6/rlUCyAqxZgleo5oEcl1ES r18R4RouunwSRtYbFHhFN1R+lQDGfZ0IiTh5EquLEEFMmkPldMWSjCMxL/YEDBR9sHlJ6M F3lLF8udVJPbXd9tfc5YE5RTYO0KLBmlyDQCgDA+r3/OYouvO8ttr8RntvnCqpnMxuH7SU Pxter4DPidWvxDkzbrtMPZyw322PT4kS18O1CRAMF3Syir1XKbYKUCAlLpAKeFk8JPeUzp z1/RELsDbPl0ESyjqMSXD4Mxqcf43k1j2yOMY2RABxceE8Lg9/MBQfJy5l+kyQ== From: Romain Gantois To: davem@davemloft.net, Rob Herring , Krzysztof Kozlowski Cc: Romain Gantois , Jakub Kicinski , Eric Dumazet , Paolo Abeni , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Florian Fainelli , Heiner Kallweit , Russell King , linux-arm-kernel@lists.infradead.org, Vladimir Oltean , Luka Perkov , Robert Marko , Andy Gross , Bjorn Andersson , Konrad Dybcio , Maxime Chevallier Subject: [PATCH net-next 1/5] net: dt-bindings: Introduce the Qualcomm IPQESS Ethernet switch Date: Mon, 23 Oct 2023 17:50:08 +0200 Message-ID: <20231023155013.512999-2-romain.gantois@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231023155013.512999-1-romain.gantois@bootlin.com> References: <20231023155013.512999-1-romain.gantois@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: romain.gantois@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231023_085014_422839_47C25A36 X-CRM114-Status: GOOD ( 13.90 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add the DT binding for the IPQESS Ethernet switch subsystem, that integrates a modified QCA8K switch and an EDMA MAC controller. It inherits from a basic ethernet switch binding and adds three regmaps, a phandle and reset line for the PSGMII, a phandle to the MDIO bus, a clock, and 32 interrupts. Signed-off-by: Romain Gantois --- .../bindings/net/qcom,ipq4019-ess.yaml | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/qcom,ipq4019-ess.yaml diff --git a/Documentation/devicetree/bindings/net/qcom,ipq4019-ess.yaml b/Documentation/devicetree/bindings/net/qcom,ipq4019-ess.yaml new file mode 100644 index 000000000000..9bb6b010ea6a --- /dev/null +++ b/Documentation/devicetree/bindings/net/qcom,ipq4019-ess.yaml @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/qcom,ipq4019-ess.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm IPQ4019 Ethernet switch subsystem driver + +maintainers: + - Romain Gantois + +$ref: ethernet-switch.yaml# + +properties: + compatible: + const: qca,ipq4019-qca8337n + + reg: + maxItems: 3 + description: Base ESS registers, PSGMII registers and EDMA registers + + reg-names: + maxItems: 3 + + resets: + maxItems: 2 + description: Handles to the PSGMII and ESS reset lines + + reset-names: + maxItems: 2 + + clocks: + maxItems: 1 + description: Handle to the GCC ESS clock + + clock-names: + maxItems: 1 + + psgmii-ethphy: + maxItems: 1 + description: Handle to the MDIO bus node corresponding to the PSGMII + + mdio: + maxItems: 1 + description: Handle to the IPQ4019 MDIO Controller + + interrupts: + maxItems: 32 + description: One interrupt per tx and rx queue, the first 16 are rx queues + and the last 16 are the tx queues + +required: + - compatible + - reg + - reg-names + - resets + - reset-names + - clocks + - clock-names + - mdio + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + #include + switch: switch@c000000 { + compatible = "qca,ipq4019-qca8337n"; + reg = <0xc000000 0x80000>, <0x98000 0x800>, <0xc080000 0x80000>; + reg-names = "base", "psgmii_phy", "edma"; + resets = <&gcc ESS_PSGMII_ARES>, <&gcc ESS_RESET>; + reset-names = "psgmii_rst", "ess"; + clocks = <&gcc GCC_ESS_CLK>; + clock-names = "ess"; + mdio = <&mdio>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + swport1: port@1 { /* MAC1 */ + reg = <1>; + label = "lan1"; + phy-handle = <ðphy0>; + phy-mode = "psgmii"; + }; + + swport2: port@2 { /* MAC2 */ + reg = <2>; + label = "lan2"; + phy-handle = <ðphy1>; + phy-mode = "psgmii"; + }; + + swport3: port@3 { /* MAC3 */ + reg = <3>; + label = "lan3"; + phy-handle = <ðphy2>; + phy-mode = "psgmii"; + }; + + swport4: port@4 { /* MAC4 */ + reg = <4>; + label = "lan4"; + phy-handle = <ðphy3>; + phy-mode = "psgmii"; + }; + + swport5: port@5 { /* MAC5 */ + reg = <5>; + label = "wan"; + phy-handle = <ðphy4>; + phy-mode = "psgmii"; + }; + }; + }; + +... From patchwork Mon Oct 23 15:50:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain Gantois X-Patchwork-Id: 13433091 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7AF08C001E0 for ; Mon, 23 Oct 2023 15:51:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Hwe2IpfGSlL18kVMoe6VuVHjUVg2MJ7XIOJSBN98grg=; b=TANh+gfj/kLY/J 7GQv49onai+O4l2xOqkhP4+RD0D2AUx4yYU5DxbtcgZD7zERTd1AfCoJ0GGJw728Ior1lYnn9vjz8 ArvajlFvegtQd7L7hpSOw+J5143TcN9SYN/bo/O8cg90HGdM97iHNpNNveuqZN1nwSX2YmfeMmTC+ pLFHopZK2CrG4XyORr+iTWosx0SlFE+DhTSOK6rcpVgFAOHT639gF9fBc4rl4RoFrPJwRSdwVlX8F bNxh+AJMqGAUF1OUKOJXK+Zu3c9TTVymhBeuasiFMriNRnrMa403nm+UkUkEu9mTuKEh4KtMSgJkP 1taOsM2ZUs1AXcOSrUnw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1quxCL-007kG4-0i; Mon, 23 Oct 2023 15:50:33 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1quxC2-007k7R-0L for linux-arm-kernel@lists.infradead.org; Mon, 23 Oct 2023 15:50:19 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id EFBB81BF20D; Mon, 23 Oct 2023 15:50:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1698076210; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+NdzWvUbGq3zmLMsfefyovgECZPQbabjvtx+noQHsm8=; b=TiX0tkKlt9XAKxqYOxLClCzZ6R7kH7Ki41ma6yx8K7S7AuOFzzhoOpv3Rb+gxhbBGyS6GJ uWsPkGe/b2srWV7wN6yI1Q5cCaCI/l6zyqMb7J0aYYgRsqWOWUmVU6xr5b3IQf0KAciEPi P3sqYAwGWLwEEHMRCErkPwhfID1BKE3jmeL/ySUm2QYQA+0X1REE4xMIHnL9NGxudL5zoS JrQec8gYdHGvCdxYwEW0gO7dkSIiDDThpFY2C+1a3QJFz5XifDVkRxkB17zfeeF6Z2oUUh E4DqgOWDSKeAybD1PNL2sH8uvVQdwEN5X/xaQcmbO95ByiEdFotmK5fmK4gW5g== From: Romain Gantois To: davem@davemloft.net, Rob Herring , Krzysztof Kozlowski Cc: Romain Gantois , Jakub Kicinski , Eric Dumazet , Paolo Abeni , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Florian Fainelli , Heiner Kallweit , Russell King , linux-arm-kernel@lists.infradead.org, Vladimir Oltean , Luka Perkov , Robert Marko , Andy Gross , Bjorn Andersson , Konrad Dybcio , Maxime Chevallier Subject: [PATCH net-next 2/5] net: dsa: qca: Make the QCA8K hardware library available globally Date: Mon, 23 Oct 2023 17:50:09 +0200 Message-ID: <20231023155013.512999-3-romain.gantois@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231023155013.512999-1-romain.gantois@bootlin.com> References: <20231023155013.512999-1-romain.gantois@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: romain.gantois@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231023_085014_429954_31C9D675 X-CRM114-Status: GOOD ( 19.29 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The Qualcomm QCA8K Ethernet switch is already supported in the kernel, as a DSA switch. However, the Qualcomm IPQ4019 SoC contains an internal modified QCA8K switch that does not fit into the DSA model, since it uses an out-of-band tagging protocol. Move the qca8k.h header file out of the QCA8K DSA driver so that the upcoming IPQ4019 QCA8K switchdev driver can include it. Refactor qca8k-common into a separate module so that the IPQESS driver can be built as a module. Signed-off-by: Romain Gantois --- drivers/net/dsa/qca/Kconfig | 10 ++ drivers/net/dsa/qca/Makefile | 5 +- drivers/net/dsa/qca/qca8k-8xxx.c | 2 +- drivers/net/dsa/qca/qca8k-common.c | 97 +++++++++++++++---- drivers/net/dsa/qca/qca8k-leds.c | 2 +- .../net/dsa/qca => include/linux/dsa}/qca8k.h | 74 +++++++++++++- 6 files changed, 167 insertions(+), 23 deletions(-) rename {drivers/net/dsa/qca => include/linux/dsa}/qca8k.h (87%) diff --git a/drivers/net/dsa/qca/Kconfig b/drivers/net/dsa/qca/Kconfig index de9da469908b..37b8d938a7fc 100644 --- a/drivers/net/dsa/qca/Kconfig +++ b/drivers/net/dsa/qca/Kconfig @@ -11,6 +11,7 @@ config NET_DSA_AR9331 config NET_DSA_QCA8K tristate "Qualcomm Atheros QCA8K Ethernet switch family support" select NET_DSA_TAG_QCA + select NET_DSA_QCA8K_LIB select REGMAP help This enables support for the Qualcomm Atheros QCA8K Ethernet @@ -24,3 +25,12 @@ config NET_DSA_QCA8K_LEDS_SUPPORT help This enabled support for LEDs present on the Qualcomm Atheros QCA8K Ethernet switch chips. + +config NET_DSA_QCA8K_LIB + tristate "Qualcomm Atheros QCA8K hardware support library" + select REGMAP + help + This enables the hardware support library for the Qualcomm + Atheros QCA8K Ethernet switch. It is used by the switchdev-based + IPQ4019 integrated switch driver and by the DSA QCA8K switch + driver. diff --git a/drivers/net/dsa/qca/Makefile b/drivers/net/dsa/qca/Makefile index ce66b1984e5f..05990339c04e 100644 --- a/drivers/net/dsa/qca/Makefile +++ b/drivers/net/dsa/qca/Makefile @@ -1,7 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o -qca8k-y += qca8k-common.o qca8k-8xxx.o +qca8k-y += qca8k-8xxx.o ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT qca8k-y += qca8k-leds.o endif + +obj-$(CONFIG_NET_DSA_QCA8K_LIB) += qca8k-lib.o +qca8k-lib-y := qca8k-common.o diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index 4ce68e655a63..a11f4a6efef2 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -20,8 +20,8 @@ #include #include #include +#include -#include "qca8k.h" #include "qca8k_leds.h" static void diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index 9ff0a3c1cb91..aaa9c6785f13 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -8,10 +8,9 @@ #include #include +#include #include -#include "qca8k.h" - #define MIB_DESC(_s, _o, _n) \ { \ .size = (_s), \ @@ -62,21 +61,37 @@ const struct qca8k_mib_desc ar8327_mib[] = { MIB_DESC(1, 0xa8, "RXUnicast"), MIB_DESC(1, 0xac, "TXUnicast"), }; +EXPORT_SYMBOL(ar8327_mib); int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) { return regmap_read(priv->regmap, reg, val); } +EXPORT_SYMBOL(qca8k_read); int qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) { return regmap_write(priv->regmap, reg, val); } +EXPORT_SYMBOL(qca8k_write); int qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) { return regmap_update_bits(priv->regmap, reg, mask, write_val); } +EXPORT_SYMBOL(qca8k_rmw); + +int qca8k_set_bits(struct qca8k_priv *priv, u32 reg, u32 bits) +{ + return regmap_set_bits(priv->regmap, reg, bits); +} +EXPORT_SYMBOL(qca8k_set_bits); + +int qca8k_clear_bits(struct qca8k_priv *priv, u32 reg, u32 bits) +{ + return regmap_clear_bits(priv->regmap, reg, bits); +} +EXPORT_SYMBOL(qca8k_clear_bits); static const struct regmap_range qca8k_readable_ranges[] = { regmap_reg_range(0x0000, 0x00e4), /* Global control */ @@ -100,6 +115,7 @@ const struct regmap_access_table qca8k_readable_table = { .yes_ranges = qca8k_readable_ranges, .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), }; +EXPORT_SYMBOL(qca8k_readable_table); static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) { @@ -161,8 +177,8 @@ static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, QCA8K_ATU_TABLE_SIZE); } -static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, - int port) +int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, + int port) { u32 reg; int ret; @@ -196,9 +212,10 @@ static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, return 0; } +EXPORT_SYMBOL(qca8k_fdb_access); -static int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, - int port) +int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, + int port) { int ret; @@ -209,6 +226,7 @@ static int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, return qca8k_fdb_read(priv, fdb); } +EXPORT_SYMBOL(qca8k_fdb_next); static int qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac, u16 port_mask, u16 vid, u8 aging) @@ -223,8 +241,8 @@ static int qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac, return ret; } -static int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, - u16 port_mask, u16 vid) +int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, + u16 port_mask, u16 vid) { int ret; @@ -235,6 +253,7 @@ static int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, return ret; } +EXPORT_SYMBOL(qca8k_fdb_del); void qca8k_fdb_flush(struct qca8k_priv *priv) { @@ -242,9 +261,10 @@ void qca8k_fdb_flush(struct qca8k_priv *priv) qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1); mutex_unlock(&priv->reg_mutex); } +EXPORT_SYMBOL(qca8k_fdb_flush); -static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, - const u8 *mac, u16 vid, u8 aging) +int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, + const u8 *mac, u16 vid, u8 aging) { struct qca8k_fdb fdb = { 0 }; int ret; @@ -265,10 +285,11 @@ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1); if (ret) goto exit; - } else { - fdb.aging = aging; } + /* Set aging */ + fdb.aging = aging; + /* Add port to fdb portmask */ fdb.port_mask |= port_mask; @@ -279,9 +300,10 @@ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, mutex_unlock(&priv->reg_mutex); return ret; } +EXPORT_SYMBOL(qca8k_fdb_search_and_insert); -static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask, - const u8 *mac, u16 vid) +int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask, + const u8 *mac, u16 vid) { struct qca8k_fdb fdb = { 0 }; int ret; @@ -321,6 +343,7 @@ static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask, mutex_unlock(&priv->reg_mutex); return ret; } +EXPORT_SYMBOL(qca8k_fdb_search_and_del); static int qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) @@ -355,8 +378,8 @@ static int qca8k_vlan_access(struct qca8k_priv *priv, return 0; } -static int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, - bool untagged) +int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, + bool untagged) { u32 reg; int ret; @@ -392,8 +415,9 @@ static int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, return ret; } +EXPORT_SYMBOL(qca8k_vlan_add); -static int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid) +int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid) { u32 reg, mask; int ret, i; @@ -435,6 +459,7 @@ static int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid) return ret; } +EXPORT_SYMBOL(qca8k_vlan_del); int qca8k_mib_init(struct qca8k_priv *priv) { @@ -462,6 +487,7 @@ int qca8k_mib_init(struct qca8k_priv *priv) mutex_unlock(&priv->reg_mutex); return ret; } +EXPORT_SYMBOL(qca8k_mib_init); void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) { @@ -476,6 +502,7 @@ void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) else regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask); } +EXPORT_SYMBOL(qca8k_port_set_status); void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) @@ -489,6 +516,7 @@ void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, for (i = 0; i < priv->info->mib_count; i++) ethtool_sprintf(&data, "%s", ar8327_mib[i].name); } +EXPORT_SYMBOL(qca8k_get_strings); void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) @@ -522,6 +550,7 @@ void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, data[i] |= (u64)hi << 32; } } +EXPORT_SYMBOL(qca8k_get_ethtool_stats); int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset) { @@ -532,6 +561,7 @@ int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset) return priv->info->mib_count; } +EXPORT_SYMBOL(qca8k_get_sset_count); int qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *eee) @@ -556,6 +586,7 @@ int qca8k_set_mac_eee(struct dsa_switch *ds, int port, mutex_unlock(&priv->reg_mutex); return ret; } +EXPORT_SYMBOL(qca8k_set_mac_eee); int qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) @@ -563,6 +594,7 @@ int qca8k_get_mac_eee(struct dsa_switch *ds, int port, /* Nothing to do on the port's MAC */ return 0; } +EXPORT_SYMBOL(qca8k_get_mac_eee); static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, bool learning) @@ -613,6 +645,7 @@ void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) qca8k_port_configure_learning(ds, port, learning); } +EXPORT_SYMBOL(qca8k_port_stp_state_set); int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, struct switchdev_brport_flags flags, @@ -623,6 +656,7 @@ int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, return 0; } +EXPORT_SYMBOL(qca8k_port_pre_bridge_flags); int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, struct switchdev_brport_flags flags, @@ -639,6 +673,7 @@ int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, return 0; } +EXPORT_SYMBOL(qca8k_port_bridge_flags); int qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, @@ -675,6 +710,7 @@ int qca8k_port_bridge_join(struct dsa_switch *ds, int port, return ret; } +EXPORT_SYMBOL(qca8k_port_bridge_join); void qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge) @@ -703,6 +739,7 @@ void qca8k_port_bridge_leave(struct dsa_switch *ds, int port, qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); } +EXPORT_SYMBOL(qca8k_port_bridge_leave); void qca8k_port_fast_age(struct dsa_switch *ds, int port) { @@ -712,6 +749,7 @@ void qca8k_port_fast_age(struct dsa_switch *ds, int port) qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port); mutex_unlock(&priv->reg_mutex); } +EXPORT_SYMBOL(qca8k_port_fast_age); int qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) { @@ -732,6 +770,7 @@ int qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) QCA8K_ATU_AGE_TIME_MASK, QCA8K_ATU_AGE_TIME(val)); } +EXPORT_SYMBOL(qca8k_set_ageing_time); int qca8k_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) @@ -746,6 +785,7 @@ int qca8k_port_enable(struct dsa_switch *ds, int port, return 0; } +EXPORT_SYMBOL(qca8k_port_enable); void qca8k_port_disable(struct dsa_switch *ds, int port) { @@ -754,6 +794,7 @@ void qca8k_port_disable(struct dsa_switch *ds, int port) qca8k_port_set_status(priv, port, 0); priv->port_enabled_map &= ~BIT(port); } +EXPORT_SYMBOL(qca8k_port_disable); int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) { @@ -792,11 +833,13 @@ int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) return ret; } +EXPORT_SYMBOL(qca8k_port_change_mtu); int qca8k_port_max_mtu(struct dsa_switch *ds, int port) { return QCA8K_MAX_MTU; } +EXPORT_SYMBOL(qca8k_port_max_mtu); int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr, u16 port_mask, u16 vid) @@ -808,6 +851,7 @@ int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr, return qca8k_fdb_add(priv, addr, port_mask, vid, QCA8K_ATU_STATUS_STATIC); } +EXPORT_SYMBOL(qca8k_port_fdb_insert); int qca8k_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, @@ -818,6 +862,7 @@ int qca8k_port_fdb_add(struct dsa_switch *ds, int port, return qca8k_port_fdb_insert(priv, addr, port_mask, vid); } +EXPORT_SYMBOL(qca8k_port_fdb_add); int qca8k_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, @@ -831,6 +876,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port, return qca8k_fdb_del(priv, addr, port_mask, vid); } +EXPORT_SYMBOL(qca8k_port_fdb_del); int qca8k_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data) @@ -854,6 +900,7 @@ int qca8k_port_fdb_dump(struct dsa_switch *ds, int port, return 0; } +EXPORT_SYMBOL(qca8k_port_fdb_dump); int qca8k_port_mdb_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb, @@ -869,6 +916,7 @@ int qca8k_port_mdb_add(struct dsa_switch *ds, int port, return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid, QCA8K_ATU_STATUS_STATIC); } +EXPORT_SYMBOL(qca8k_port_mdb_add); int qca8k_port_mdb_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb, @@ -883,10 +931,11 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port, return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid); } +EXPORT_SYMBOL(qca8k_port_mdb_del); int qca8k_port_mirror_add(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress, struct netlink_ext_ack *extack) + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, struct netlink_ext_ack *extack) { struct qca8k_priv *priv = ds->priv; int monitor_port, ret; @@ -938,6 +987,7 @@ int qca8k_port_mirror_add(struct dsa_switch *ds, int port, return 0; } +EXPORT_SYMBOL(qca8k_port_mirror_add); void qca8k_port_mirror_del(struct dsa_switch *ds, int port, struct dsa_mall_mirror_tc_entry *mirror) @@ -974,6 +1024,7 @@ void qca8k_port_mirror_del(struct dsa_switch *ds, int port, err: dev_err(priv->dev, "Failed to del mirror port from %d", port); } +EXPORT_SYMBOL(qca8k_port_mirror_del); int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, @@ -994,6 +1045,7 @@ int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, return ret; } +EXPORT_SYMBOL(qca8k_port_vlan_filtering); int qca8k_port_vlan_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, @@ -1024,6 +1076,7 @@ int qca8k_port_vlan_add(struct dsa_switch *ds, int port, return ret; } +EXPORT_SYMBOL(qca8k_port_vlan_add); int qca8k_port_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) @@ -1037,6 +1090,7 @@ int qca8k_port_vlan_del(struct dsa_switch *ds, int port, return ret; } +EXPORT_SYMBOL(qca8k_port_vlan_del); static bool qca8k_lag_can_offload(struct dsa_switch *ds, struct dsa_lag lag, @@ -1207,12 +1261,14 @@ int qca8k_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag, return qca8k_lag_refresh_portmap(ds, port, lag, false); } +EXPORT_SYMBOL(qca8k_port_lag_join); int qca8k_port_lag_leave(struct dsa_switch *ds, int port, struct dsa_lag lag) { return qca8k_lag_refresh_portmap(ds, port, lag, true); } +EXPORT_SYMBOL(qca8k_port_lag_leave); int qca8k_read_switch_id(struct qca8k_priv *priv) { @@ -1242,3 +1298,6 @@ int qca8k_read_switch_id(struct qca8k_priv *priv) return 0; } +EXPORT_SYMBOL(qca8k_read_switch_id); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c index e8c16e76e34b..6500b5dd73de 100644 --- a/drivers/net/dsa/qca/qca8k-leds.c +++ b/drivers/net/dsa/qca/qca8k-leds.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include -#include "qca8k.h" #include "qca8k_leds.h" static u32 qca8k_phy_to_port(int phy) diff --git a/drivers/net/dsa/qca/qca8k.h b/include/linux/dsa/qca8k.h similarity index 87% rename from drivers/net/dsa/qca/qca8k.h rename to include/linux/dsa/qca8k.h index 8f88b7db384d..42829aa1728a 100644 --- a/drivers/net/dsa/qca/qca8k.h +++ b/include/linux/dsa/qca8k.h @@ -13,6 +13,7 @@ #include #include #include +#include #define QCA8K_ETHERNET_MDIO_PRIORITY 7 #define QCA8K_ETHERNET_PHY_PRIORITY 6 @@ -265,6 +266,7 @@ #define QCA8K_PORT_LOOKUP_STATE_LEARNING QCA8K_PORT_LOOKUP_STATE(0x3) #define QCA8K_PORT_LOOKUP_STATE_FORWARD QCA8K_PORT_LOOKUP_STATE(0x4) #define QCA8K_PORT_LOOKUP_LEARN BIT(20) +#define QCA8K_PORT_LOOKUP_LOOPBACK_EN BIT(21) #define QCA8K_PORT_LOOKUP_ING_MIRROR_EN BIT(25) #define QCA8K_REG_GOL_TRUNK_CTRL0 0x700 @@ -341,6 +343,55 @@ #define MII_ATH_MMD_ADDR 0x0d #define MII_ATH_MMD_DATA 0x0e +/* IPQ4019 PSGMII PHY registers */ +#define QCA8K_IPQ4019_REG_RGMII_CTRL 0x004 +#define QCA8K_IPQ4019_RGMII_CTRL_RGMII_RXC GENMASK(1, 0) +#define QCA8K_IPQ4019_RGMII_CTRL_RGMII_TXC GENMASK(9, 8) +/* Some kind of CLK selection + * 0: gcc_ess_dly2ns + * 1: gcc_ess_clk + */ +#define QCA8K_IPQ4019_RGMII_CTRL_CLK BIT(10) +#define QCA8K_IPQ4019_RGMII_CTRL_DELAY_RMII0 GENMASK(17, 16) +#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII0_REF_CLK BIT(18) +#define QCA8K_IPQ4019_RGMII_CTRL_DELAY_RMII1 GENMASK(20, 19) +#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII1_REF_CLK BIT(21) +#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII0_MASTER_EN BIT(24) +#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII1_MASTER_EN BIT(25) + +#define PSGMIIPHY_MODE_CONTROL 0x1b4 +#define PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M BIT(0) +#define PSGMIIPHY_TX_CONTROL 0x288 +#define PSGMIIPHY_TX_CONTROL_MAGIC_VALUE 0x8380 +#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1 0x9c +#define PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART BIT(14) +#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2 0xa0 +#define PSGMIIPHY_REG_PLL_VCO_CALIB_READY BIT(0) + +#define MII_QCA8075_SSTATUS 0x11 +#define MII_QCA8075_SSTATUS_WAIT 8 +#define MII_QCA8075_SSTATUS_TIMEOUT 800 +#define QCA8075_PHY_SPEC_STATUS_LINK BIT(10) +#define QCA8075_MMD7_CRC_AND_PKTS_COUNT 0x8029 +#define QCA8075_MMD7_PKT_GEN_PKT_NUMB 0x8021 +#define QCA8075_MMD7_PKT_GEN_PKT_SIZE 0x8062 +#define QCA8075_MMD7_PKT_GEN_CTRL 0x8020 +#define QCA8075_MMD7_CNT_SELFCLR BIT(1) +#define QCA8075_MMD7_CNT_FRAME_CHK_EN BIT(0) +#define QCA8075_MMD7_PKT_GEN_START BIT(13) +#define QCA8075_MMD7_PKT_GEN_INPROGR BIT(15) +#define QCA8075_MMD7_IG_FRAME_RECV_CNT_HI 0x802a +#define QCA8075_MMD7_IG_FRAME_RECV_CNT_LO 0x802b +#define QCA8075_MMD7_IG_FRAME_ERR_CNT 0x802c +#define QCA8075_MMD7_EG_FRAME_RECV_CNT_HI 0x802d +#define QCA8075_MMD7_EG_FRAME_RECV_CNT_LO 0x802e +#define QCA8075_MMD7_EG_FRAME_ERR_CNT 0x802f +#define QCA8075_MMD7_MDIO_BRDCST_WRITE 0x8028 +#define QCA8075_MMD7_MDIO_BRDCST_WRITE_EN BIT(15) +#define QCA8075_MDIO_BRDCST_PHY_ADDR 0x1f +#define QCA8075_PKT_GEN_PKTS_COUNT 4096 +#define QCA8075_PKT_GEN_PKTS_SIZE 1504 + enum { QCA8K_PORT_SPEED_10M = 0, QCA8K_PORT_SPEED_100M = 1, @@ -466,6 +517,11 @@ struct qca8k_priv { struct qca8k_pcs pcs_port_6; const struct qca8k_match_data *info; struct qca8k_led ports_led[QCA8K_LED_COUNT]; + + /* IPQ4019 specific */ + struct regmap *psgmii; + struct phy_device *psgmii_ethphy; + atomic_t psgmii_calibrated; }; struct qca8k_mib_desc { @@ -506,6 +562,8 @@ int qca8k_read_switch_id(struct qca8k_priv *priv); int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val); int qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val); int qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val); +int qca8k_set_bits(struct qca8k_priv *priv, u32 reg, u32 bits); +int qca8k_clear_bits(struct qca8k_priv *priv, u32 reg, u32 bits); /* Common ops function */ void qca8k_fdb_flush(struct qca8k_priv *priv); @@ -559,6 +617,16 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port, struct dsa_db db); int qca8k_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data); +int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, + u16 port_mask, u16 vid); +int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, + int port); +int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, + int port); +int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, + const u8 *mac, u16 vid, u8 aging); +int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask, + const u8 *mac, u16 vid); /* Common MDB function */ int qca8k_port_mdb_add(struct dsa_switch *ds, int port, @@ -576,8 +644,12 @@ void qca8k_port_mirror_del(struct dsa_switch *ds, int port, struct dsa_mall_mirror_tc_entry *mirror); /* Common port VLAN function */ -int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, +int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering, struct netlink_ext_ack *extack); +int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, + bool untagged); +int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid); int qca8k_port_vlan_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct netlink_ext_ack *extack); From patchwork Mon Oct 23 15:50:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain Gantois X-Patchwork-Id: 13433090 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A4E5CC004C0 for ; Mon, 23 Oct 2023 15:50:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=qM1YWSGVc8rC5mxbj/TWnz0HVr4+xl0mgvgACzDGv24=; b=oX/PPI44e8Ddft XFfuJCEjZsiaysJ5zfpnKmGU1jAmKXFy/Yeqry3PJ0c8uSGlIKxiirvIG8DXoMYvpgSLvpFXqaDSp dHcAdQWunr1X1DF0BWvQPNhsDrLeukvC05BlrQPMmEQRsR1gjrhjtQja63QhaK9wGqoUpTviwSQCA PR+oVvOKYtOzqfIi01+EGSGkxP6DsiLnUgE4olq9cC64HqgcrUEKfIkSKtb+N740XuWq4V3IT+c++ iEXJPADcWvBD20Mt342zUvK7fdFmYwz+rO6yvEN/r8vqiXrgEWwJL8uQlIjm+wowd97Xq9bessBvq bOl5Z8hxgYun/Eorwonw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1quxCK-007kFN-1s; Mon, 23 Oct 2023 15:50:32 +0000 Received: from relay8-d.mail.gandi.net ([2001:4b98:dc4:8::228]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1quxC2-007k7V-0N for linux-arm-kernel@lists.infradead.org; Mon, 23 Oct 2023 15:50:18 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id 58B0D1BF216; Mon, 23 Oct 2023 15:50:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1698076212; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vaYaHeCezQayxJ2/GqMRLkniVlk5Cnh902YETWh3nkE=; b=BmmDlWNXqjzRHh739q0oVMXuOGkb/XaxEOov8wLd13J7SODvhmnfHcENliU+hMjLm+xVl6 NXCnR1xi9EduY2RboJZiH9K+RBySK5JXfRn9jU3XPPkXyIoc4NNEcQEZeWRAaDeaCpK7eP q1eXp9FxaAp/YMltdAmFoVmtLyv2sB7fpdyz2S3Q5W+DuY/bQCmJ1daSkhbU5zQCn0TZ0A d0Fc8+0eb9hRpu93ODScMMjIrCjrNG1oiSUdebx8CDp5DnHKSPtTuYz0vqtPR3K9jILtgl euzsy87sUdqApfLHESdmlWYL/DkxqQiYZ0uCeuiqtWyjwnTewzH2IsVq7Gf79g== From: Romain Gantois To: davem@davemloft.net, Rob Herring , Krzysztof Kozlowski Cc: Romain Gantois , Jakub Kicinski , Eric Dumazet , Paolo Abeni , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Florian Fainelli , Heiner Kallweit , Russell King , linux-arm-kernel@lists.infradead.org, Vladimir Oltean , Luka Perkov , Robert Marko , Andy Gross , Bjorn Andersson , Konrad Dybcio , Maxime Chevallier Subject: [PATCH net-next 4/5] net: ipqess: add a PSGMII calibration procedure to the IPQESS driver Date: Mon, 23 Oct 2023 17:50:11 +0200 Message-ID: <20231023155013.512999-5-romain.gantois@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231023155013.512999-1-romain.gantois@bootlin.com> References: <20231023155013.512999-1-romain.gantois@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: romain.gantois@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231023_085014_466297_9F704309 X-CRM114-Status: GOOD ( 24.14 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The IPQ4019 Ethernet Switch Subsystem uses a PSGMII link to communicate with a QCA8075 5-port PHY. This 1G link requires calibration before it can be used reliably. This commit introduces a calibration procedure followed by thourough testing of the link between each switch port and its corresponding PHY port. Signed-off-by: Romain Gantois --- drivers/net/ethernet/qualcomm/ipqess/Makefile | 2 +- .../ethernet/qualcomm/ipqess/ipqess_calib.c | 495 ++++++++++++++++++ .../ethernet/qualcomm/ipqess/ipqess_port.c | 3 +- .../ethernet/qualcomm/ipqess/ipqess_port.h | 4 + 4 files changed, 502 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/qualcomm/ipqess/ipqess_calib.c diff --git a/drivers/net/ethernet/qualcomm/ipqess/Makefile b/drivers/net/ethernet/qualcomm/ipqess/Makefile index 51d7163ef0fc..110f6003f04b 100644 --- a/drivers/net/ethernet/qualcomm/ipqess/Makefile +++ b/drivers/net/ethernet/qualcomm/ipqess/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_QCOM_IPQ4019_ESS) += ipqess.o -ipqess-objs := ipqess_port.o ipqess_switch.o ipqess_notifiers.o ipqess_edma.o +ipqess-objs := ipqess_port.o ipqess_switch.o ipqess_notifiers.o ipqess_edma.o ipqess_calib.o diff --git a/drivers/net/ethernet/qualcomm/ipqess/ipqess_calib.c b/drivers/net/ethernet/qualcomm/ipqess/ipqess_calib.c new file mode 100644 index 000000000000..ca9b5593a200 --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess_calib.c @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Calibration procedure for the IPQ4019 PSGMII link + * + * Copyright (C) 2009 Felix Fietkau + * Copyright (C) 2011-2012, 2020-2021 Gabor Juhos + * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016 John Crispin + * Copyright (c) 2022 Robert Marko + * Copyright (c) 2023 Romain Gantois + */ + +#include +#include +#include +#include +#include + +#include "ipqess_port.h" + +/* Nonstandard MII registers for the psgmii + * device on the IPQ4019 MDIO bus. + */ + +#define PSGMII_RSTCTRL 0x0 /* Reset control register */ +#define PSGMII_RSTCTRL_RST BIT(6) +#define PSGMII_RSTCTRL_RX20 BIT(2) /* Fix/release RX 20 bit */ + +#define PSGMII_CDRCTRL 0x1a /* Clock and data recovery control register */ +#define PSGMII_CDRCTRL_RELEASE BIT(12) + +#define PSGMII_VCO_CALIB_CTRL 0x28 /* VCO PLL calibration */ +#define PSGMII_VCO_CALIB_READY BIT(0) + +/* Delays and timeouts */ + +#define PSGMII_WAIT_AFTER_CALIB 50 +#define PSGMII_WAIT_AFTER_RELEASE 200 +#define PSGMII_VCO_CALIB_INTERVAL 1000000 +#define PSGMII_VCO_CALIB_TIMEOUT 10000 +#define PSGMII_CALIB_RETRIES 50 +#define PSGMII_CALIB_RETRIES_BURST 5 +#define PSGMII_CALIB_RETRY_DELAY 100 + +/* Calibration data */ + +struct psgmii_port_data { + struct list_head list; + struct phy_device *phy; + int id; + + /* calibration test results */ + u32 test_ok; + u32 tx_loss; + u32 rx_loss; + u32 tx_errors; + u32 rx_errors; +}; + +static LIST_HEAD(calib); + +static int psgmii_vco_calibrate(struct qca8k_priv *priv) +{ + int val, ret; + + if (!priv->psgmii_ethphy) { + dev_err(priv->dev, + "PSGMII eth PHY missing, calibration failed!\n"); + return -ENODEV; + } + + /* Fix PSGMII RX 20bit */ + ret = phy_clear_bits(priv->psgmii_ethphy, PSGMII_RSTCTRL, + PSGMII_RSTCTRL_RX20); + /* Reset PHY PSGMII */ + ret = phy_clear_bits(priv->psgmii_ethphy, PSGMII_RSTCTRL, + PSGMII_RSTCTRL_RST); + /* Release PHY PSGMII reset */ + ret = phy_set_bits(priv->psgmii_ethphy, PSGMII_RSTCTRL, + PSGMII_RSTCTRL_RST); + + /* Poll for VCO PLL calibration finish - Malibu(QCA8075) */ + ret = phy_read_mmd_poll_timeout(priv->psgmii_ethphy, + MDIO_MMD_PMAPMD, + PSGMII_VCO_CALIB_CTRL, + val, + val & PSGMII_VCO_CALIB_READY, + PSGMII_VCO_CALIB_INTERVAL, + PSGMII_VCO_CALIB_TIMEOUT, + false); + if (ret) { + dev_err(priv->dev, + "QCA807x PSGMII VCO calibration PLL not ready\n"); + return ret; + } + mdelay(PSGMII_WAIT_AFTER_CALIB); + + /* Freeze PSGMII RX CDR */ + ret = phy_clear_bits(priv->psgmii_ethphy, PSGMII_CDRCTRL, + PSGMII_CDRCTRL_RELEASE); + + /* Start PSGMIIPHY VCO PLL calibration */ + ret = regmap_set_bits(priv->psgmii, + PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1, + PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART); + + /* Poll for PSGMIIPHY PLL calibration finish - Dakota(IPQ40xx) */ + ret = regmap_read_poll_timeout(priv->psgmii, + PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2, + val, + val & PSGMIIPHY_REG_PLL_VCO_CALIB_READY, + PSGMII_VCO_CALIB_INTERVAL, + PSGMII_VCO_CALIB_TIMEOUT); + if (ret) { + dev_err(priv->dev, + "IPQ PSGMIIPHY VCO calibration PLL not ready\n"); + return ret; + } + mdelay(PSGMII_WAIT_AFTER_CALIB); + + /* Release PSGMII RX CDR */ + ret = phy_set_bits(priv->psgmii_ethphy, PSGMII_CDRCTRL, + PSGMII_CDRCTRL_RELEASE); + /* Release PSGMII RX 20bit */ + ret = phy_set_bits(priv->psgmii_ethphy, PSGMII_RSTCTRL, + PSGMII_RSTCTRL_RX20); + mdelay(PSGMII_WAIT_AFTER_RELEASE); + + return ret; +} + +static int +qca8k_wait_for_phy_link_state(struct phy_device *phy, int need_link) +{ + u16 status; + int ret; + + ret = phy_read_poll_timeout(phy, MII_QCA8075_SSTATUS, status, + !!(status & QCA8075_PHY_SPEC_STATUS_LINK) == need_link, + MII_QCA8075_SSTATUS_WAIT, MII_QCA8075_SSTATUS_TIMEOUT, 1); + if (ret == -ETIMEDOUT) + return -EINVAL; + + return 0; +} + +static void +psgmii_phy_loopback_enable(struct qca8k_priv *priv, struct phy_device *phy, + int sw_port) +{ + phy_write(phy, MII_BMCR, BMCR_ANENABLE | BMCR_RESET); + phy_modify(phy, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); + qca8k_wait_for_phy_link_state(phy, 0); + qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), 0); + phy_write(phy, MII_BMCR, + BMCR_SPEED1000 + | BMCR_FULLDPLX + | BMCR_LOOPBACK); + qca8k_wait_for_phy_link_state(phy, 1); + qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), + QCA8K_PORT_STATUS_SPEED_1000 + | QCA8K_PORT_STATUS_TXMAC + | QCA8K_PORT_STATUS_RXMAC + | QCA8K_PORT_STATUS_DUPLEX); + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(sw_port), + QCA8K_PORT_LOOKUP_STATE_FORWARD, + QCA8K_PORT_LOOKUP_STATE_FORWARD); +} + +static void +psgmii_phy_loopback_disable(struct qca8k_priv *priv, struct phy_device *phy, + int sw_port) +{ + qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), 0); + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(sw_port), + QCA8K_PORT_LOOKUP_STATE_DISABLED, + QCA8K_PORT_LOOKUP_STATE_DISABLED); + phy_write(phy, MII_BMCR, + BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_RESET); + /* turn off the power of the phys - so that unused + * ports do not raise links + */ + phy_modify(phy, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); +} + +static void +qca8k_wait_for_phy_pkt_gen_fin(struct qca8k_priv *priv, struct phy_device *phy) +{ + int val; + + /* Wait for all traffic to end: + * 4096(pkt num)*1524(size)*8ns(125MHz)=49938us + */ + phy_read_mmd_poll_timeout(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, + val, !(val & QCA8075_MMD7_PKT_GEN_INPROGR), + 50000, 1000000, true); +} + +static int +psgmii_start_parallel_pkt_gen(struct qca8k_priv *priv) +{ + struct phy_device *phy; + + phy = phy_device_create(priv->bus, QCA8075_MDIO_BRDCST_PHY_ADDR, + 0, 0, NULL); + if (!phy) { + dev_err(priv->dev, + "unable to create mdio broadcast PHY(0x%x)\n", + QCA8075_MDIO_BRDCST_PHY_ADDR); + return -ENODEV; + } + + /* start packet generation */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, + QCA8075_MMD7_PKT_GEN_START | QCA8075_MMD7_PKT_GEN_INPROGR); + + phy_device_free(phy); + return 0; +} + +static void +qca8k_get_phy_pkt_gen_test_result(struct psgmii_port_data *port_data) +{ + struct phy_device *phy = port_data->phy; + u32 tx_all_ok, rx_all_ok; + u32 tx_ok, tx_errors; + u32 rx_ok, rx_errors; + u32 tx_ok_high16; + u32 rx_ok_high16; + + /* check counters */ + tx_ok = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_RECV_CNT_LO); + tx_ok_high16 = phy_read_mmd(phy, MDIO_MMD_AN, + QCA8075_MMD7_EG_FRAME_RECV_CNT_HI); + tx_errors = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_ERR_CNT); + rx_ok = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_RECV_CNT_LO); + rx_ok_high16 = phy_read_mmd(phy, MDIO_MMD_AN, + QCA8075_MMD7_IG_FRAME_RECV_CNT_HI); + rx_errors = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_ERR_CNT); + tx_all_ok = tx_ok + (tx_ok_high16 << 16); + rx_all_ok = rx_ok + (rx_ok_high16 << 16); + + port_data->tx_loss = QCA8075_PKT_GEN_PKTS_COUNT - tx_all_ok; + port_data->rx_loss = QCA8075_PKT_GEN_PKTS_COUNT - rx_all_ok; + port_data->tx_errors = tx_errors; + port_data->rx_errors = rx_errors; + port_data->test_ok = !(port_data->tx_loss | port_data->rx_loss | tx_errors | rx_errors); +} + +static void psgmii_port_cleanup_test(struct qca8k_priv *priv, + struct psgmii_port_data *port_data) +{ + struct phy_device *phy = port_data->phy; + int port_id = port_data->id; + + /* set packet count to 0 */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_NUMB, 0); + + /* disable CRC checker and packet counter */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, 0); + + /* disable traffic gen */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, 0); + + /* disable broadcasts on MDIO bus */ + phy_clear_bits_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_MDIO_BRDCST_WRITE, + QCA8075_MMD7_MDIO_BRDCST_WRITE_EN); + + /* disable loopback on switch port and PHY */ + qca8k_clear_bits(priv, QCA8K_PORT_LOOKUP_CTRL(port_id), + QCA8K_PORT_LOOKUP_LOOPBACK_EN); + psgmii_phy_loopback_disable(priv, phy, port_id); +} + +static void psgmii_port_prep_test(struct qca8k_priv *priv, + struct psgmii_port_data *port_data) +{ + struct phy_device *phy = port_data->phy; + int port_id = port_data->id; + + /* put PHY and switch port in loopback */ + psgmii_phy_loopback_enable(priv, phy, port_id); + qca8k_set_bits(priv, QCA8K_PORT_LOOKUP_CTRL(port_id), + QCA8K_PORT_LOOKUP_LOOPBACK_EN); + + /* enable broadcasts on MDIO bus */ + phy_set_bits_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_MDIO_BRDCST_WRITE, + QCA8075_MMD7_MDIO_BRDCST_WRITE_EN); + + /* enable PHY CRC checker and packet counters */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, + QCA8075_MMD7_CNT_FRAME_CHK_EN | QCA8075_MMD7_CNT_SELFCLR); + qca8k_wait_for_phy_link_state(phy, 1); + + /* set number of packets to send during the test */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_NUMB, + QCA8075_PKT_GEN_PKTS_COUNT); + /* set packet size */ + phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_SIZE, + QCA8075_PKT_GEN_PKTS_SIZE); +} + +static int psgmii_link_parallel_test(struct qca8k_priv *priv) +{ + struct psgmii_port_data *port_data; + bool test_failed = false; + + list_for_each_entry(port_data, &calib, list) { + /* prep switch port for test */ + psgmii_port_prep_test(priv, port_data); + } + + psgmii_start_parallel_pkt_gen(priv); + + list_for_each_entry(port_data, &calib, list) { + /* wait for test results */ + qca8k_wait_for_phy_pkt_gen_fin(priv, port_data->phy); + qca8k_get_phy_pkt_gen_test_result(port_data); + + if (!port_data->test_ok) { + dev_dbg(priv->dev, + "PSGMII calibration: failed parallel test on port %d errors: %d %d %d %d\n", + port_data->id, port_data->tx_loss, port_data->rx_loss, + port_data->tx_errors, port_data->rx_errors); + + test_failed = true; + } + + psgmii_port_cleanup_test(priv, port_data); + } + + return test_failed; +} + +static int psgmii_link_serial_test(struct qca8k_priv *priv) +{ + struct psgmii_port_data *port_data; + bool test_failed = false; + + list_for_each_entry(port_data, &calib, list) { + /* prep switch port for test */ + psgmii_port_prep_test(priv, port_data); + + /* start packet generation */ + phy_write_mmd(port_data->phy, + MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, + QCA8075_MMD7_PKT_GEN_START | + QCA8075_MMD7_PKT_GEN_INPROGR); + + /* wait for test results */ + qca8k_wait_for_phy_pkt_gen_fin(priv, port_data->phy); + qca8k_get_phy_pkt_gen_test_result(port_data); + + if (!port_data->test_ok) { + dev_dbg(priv->dev, + "PSGMII calibration: failed serial test on port %d errors: %d %d %d %d\n", + port_data->id, port_data->tx_loss, port_data->rx_loss, + port_data->tx_errors, port_data->rx_errors); + + test_failed = true; + } + + psgmii_port_cleanup_test(priv, port_data); + } + + return test_failed; +} + +static void psgmii_free_calib_data(void) +{ + struct psgmii_port_data *port_data, *temp; + + list_for_each_entry_safe(port_data, temp, &calib, list) { + list_del(&port_data->list); + kfree(port_data); + } +} + +static int psgmii_alloc_calib_data(struct qca8k_priv *priv) +{ + struct device_node *phy_dn, *ports, *port_dn; + struct psgmii_port_data *port_data; + struct phy_device *phy; + int err, port_id; + + /* get port data from device tree */ + ports = of_get_child_by_name(priv->dev->of_node, "ports"); + if (!ports) { + dev_err(priv->dev, "no ports child node found\n"); + return -EINVAL; + } + for_each_available_child_of_node(ports, port_dn) { + /* alloc port data */ + port_data = kzalloc(sizeof(port_data), GFP_KERNEL); + if (!port_data) { + err = -ENOMEM; + goto out_free; + } + + list_add(&port_data->list, &calib); + + /* get port ID */ + err = of_property_read_u32(port_dn, "reg", &port_id); + if (err) { + dev_err(priv->dev, "error: missing 'reg' property in device node\n"); + goto out_free; + } + + if (port_id >= QCA8K_NUM_PORTS) { + dev_err(priv->dev, "error: port ID out of range\n"); + err = -EINVAL; + goto out_free; + } + + /* get PHY device */ + phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); + if (!phy_dn) { + dev_err(priv->dev, "error: missing 'phy-handle' property in device node\n"); + err = -EINVAL; + goto out_free; + } + phy = of_phy_find_device(phy_dn); + of_node_put(phy_dn); + if (!phy) { + dev_err(priv->dev, + "error: unable to fetch PHY device for port %d\n", + port_id); + err = -EINVAL; + goto out_free; + } + + port_data->phy = phy; + port_data->id = port_id; + } + + return 0; + +out_free: + psgmii_free_calib_data(); + return err; +} + +int psgmii_calibrate_and_test(struct qca8k_priv *priv) +{ + struct psgmii_port_data *port_data; + bool test_failed = false; + int ret, attempt; + + ret = psgmii_alloc_calib_data(priv); + if (ret) + return ret; + + for (attempt = 0; attempt <= PSGMII_CALIB_RETRIES; attempt++) { + /* first we run the VCO calibration */ + ret = psgmii_vco_calibrate(priv); + if (ret) + goto out_free; + + /* then, we test the link */ + test_failed = psgmii_link_serial_test(priv); + if (!test_failed) + test_failed = psgmii_link_parallel_test(priv); + + qca8k_fdb_flush(priv); + + if (!test_failed) { + dev_dbg(priv->dev, + "PSGMII link stabilized after %d attempts\n", + attempt + 1); + ret = 0; + goto out_free; + } + + /* On tested hardware, the link often stabilizes in 4 or 5 retries. + * If it still isn't stable, we wait a bit, then try another set + * of calibration attempts. + */ + dev_warn(priv->dev, "PSGMII link is unstable! Retrying... %d/QCA8K_PSGMII_CALIB_RETRIES\n", + attempt + 1); + if (attempt % PSGMII_CALIB_RETRIES_BURST == 0) + schedule_timeout_interruptible(msecs_to_jiffies(PSGMII_CALIB_RETRY_DELAY)); + else + schedule(); + } + + dev_err(priv->dev, "PSGMII work is unstable! Repeated recalibration attempts did not help!\n"); + ret = -EFAULT; + +out_free: + list_for_each_entry(port_data, &calib, list) { + put_device(&port_data->phy->mdio.dev); + } + psgmii_free_calib_data(); + return ret; +} diff --git a/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.c b/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.c index 95407a008971..757d937dd711 100644 --- a/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.c +++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.c @@ -1315,7 +1315,8 @@ ipqess_psgmii_configure(struct qca8k_priv *priv) int ret; if (!atomic_fetch_inc(&priv->psgmii_calibrated)) { - dev_warn(priv->dev, "Unable to calibrate PSGMII, link will be unstable!\n"); + dev_dbg(priv->dev, "starting PSGMII calibration...\n"); + psgmii_calibrate_and_test(priv); ret = regmap_clear_bits(priv->psgmii, PSGMIIPHY_MODE_CONTROL, PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M); diff --git a/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.h b/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.h index a0639933e8bb..6e6a5d15f588 100644 --- a/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.h +++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess_port.h @@ -92,4 +92,8 @@ int ipqess_port_obj_del(struct net_device *netdev, const void *ctx, bool ipqess_port_offloads_bridge_port(struct ipqess_port *port, const struct net_device *netdev); + +/* Defined in ipqess_calib.c */ +int psgmii_calibrate_and_test(struct qca8k_priv *priv); + #endif From patchwork Mon Oct 23 15:50:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain Gantois X-Patchwork-Id: 13433089 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A6592C25B41 for ; Mon, 23 Oct 2023 15:50:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=1Via4iXp+WdDivpko0xccmk6xz5//0q1ig/qUFoZKQ4=; b=0ozgLjmb2516JU IL2OeRrFT91l2O4DJN7aZ5PMqk2h0T0NTX6cUlFguLNu7fWyWiiWz4nd7aEVJdEhuo3wb3EIKtsUK vHx8piLeCry5otRkYKAMevQVnpQ7vv4+Js1aZr5wlCTNiuhjeqyjaVYhtLQFQbp5La0RQxN/wAB3Y sCxIzCL1CrXFXApNhd22irSlVqM4ViFEsbRuPCs7URUM5hVs7Op2ucr06vd13aIt1RARhp2bAn821 ZdxpxULMldWzlq4ZdQ7bt5cDXqbx6QGCAsvkz53S2m5wPUQncCXf1LTUu1yObgediCI1dtR1WrlSP 3OT+jHbPb9a37vmeNKbw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1quxCJ-007kEZ-1S; Mon, 23 Oct 2023 15:50:31 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1quxC2-007k7a-2W for linux-arm-kernel@lists.infradead.org; Mon, 23 Oct 2023 15:50:18 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id 6C5431BF21A; Mon, 23 Oct 2023 15:50:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1698076213; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0UKmAk7rbamYxizK/2w/z1HSWepeDGqOjvVyArYGKZ4=; b=ortd9qJ0zTIUFVZTjx403Enr48YnyRMXO2nMn6U21mFm4c7T8aLF06qVYBQqpJbMtLW6Cm 7Pb+90Teb/lJJ2U97IEqOQ8d9uqsPFtF0I2JZBg50G+sO1MKHdJD3IsuWhxreDA2BDTHLp 8wmxYKAJpSdYaohs/06+oOgMzrv962+zrxMY/rIzrOBXOv1FdPhzBFrJQb3Vc5jlSemTcr qB24vXCPODfoGdG9JxQd4fjblbq/OPQnQ8kgdTYULvnOK/SGYZ3Cty1pSykJiPCTbBdfrp azZzyY9B3mp9OiKV6ioIErONYySu+5SG5xqQZLVze7gEpbwazTnP6g28o7C/Tw== From: Romain Gantois To: davem@davemloft.net, Rob Herring , Krzysztof Kozlowski Cc: Romain Gantois , Jakub Kicinski , Eric Dumazet , Paolo Abeni , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Florian Fainelli , Heiner Kallweit , Russell King , linux-arm-kernel@lists.infradead.org, Vladimir Oltean , Luka Perkov , Robert Marko , Andy Gross , Bjorn Andersson , Konrad Dybcio , Maxime Chevallier Subject: [PATCH net-next 5/5] dts: qcom: ipq4019: Add description for the IPQ4019 ESS EDMA and switch Date: Mon, 23 Oct 2023 17:50:12 +0200 Message-ID: <20231023155013.512999-6-romain.gantois@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231023155013.512999-1-romain.gantois@bootlin.com> References: <20231023155013.512999-1-romain.gantois@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: romain.gantois@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231023_085015_090630_3C8E7E74 X-CRM114-Status: GOOD ( 10.77 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The Qualcomm IPQ4019 includes a modified version of the QCA8K Ethernet switch. The switch's CPU port is connected to the SoC through the internal EDMA Ethernet controller. Add support for these two devices, which are coupled tightly enough to justify treating them as a single device. Signed-off-by: Romain Gantois --- .../boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi | 13 +++ arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi | 94 +++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi index da67d55fa557..6a185b8b31c6 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi @@ -242,6 +242,19 @@ &mdio { pinctrl-names = "default"; }; +&switch { + status = "okay"; +}; + +&swport4 { + status = "okay"; + label = "lan"; +}; + +&swport5 { + status = "okay"; +}; + &wifi0 { status = "okay"; nvmem-cell-names = "pre-calibration"; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi index 9844e0b7cff9..0d8597513929 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi @@ -596,6 +596,100 @@ wifi1: wifi@a800000 { status = "disabled"; }; + switch: switch@c000000 { + compatible = "qca,ipq4019-qca8337n"; + reg = <0xc000000 0x80000>, <0x98000 0x800>, <0xc080000 0x8000>; + reg-names = "base", "psgmii_phy", "edma"; + resets = <&gcc ESS_PSGMII_ARES>, <&gcc ESS_RESET>; + reset-names = "psgmii_rst", "ess"; + clocks = <&gcc GCC_ESS_CLK>; + clock-names = "ess"; + mdio = <&mdio>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + swport1: port@1 { /* MAC1 */ + reg = <1>; + label = "lan1"; + phy-handle = <ðphy0>; + phy-mode = "psgmii"; + + status = "disabled"; + }; + + swport2: port@2 { /* MAC2 */ + reg = <2>; + label = "lan2"; + phy-handle = <ðphy1>; + phy-mode = "psgmii"; + + status = "disabled"; + }; + + swport3: port@3 { /* MAC3 */ + reg = <3>; + label = "lan3"; + phy-handle = <ðphy2>; + phy-mode = "psgmii"; + + status = "disabled"; + }; + + swport4: port@4 { /* MAC4 */ + reg = <4>; + label = "lan4"; + phy-handle = <ðphy3>; + phy-mode = "psgmii"; + + status = "disabled"; + }; + + swport5: port@5 { /* MAC5 */ + reg = <5>; + label = "wan"; + phy-handle = <ðphy4>; + phy-mode = "psgmii"; + + status = "disabled"; + }; + }; + }; + mdio: mdio@90000 { #address-cells = <1>; #size-cells = <0>;