From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 631614ADD9A for ; Tue, 5 May 2026 18:27:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.46 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778005669; cv=none; b=jtguigYTvro+37EfgHjIKjHpS/23xXytVdsxigum2JFWiHMxhTIL//3MBkboA8BM11CYJXKbRA5nQZ7v+Tp8DqzzGnwlXL+jE342jJ8e8HhcC4aLOcKLJF/ShHs8lidKfJwE38Fs7aS9ksB7BUhkn5YDd4kU0CnfXRwVjBmGsSc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778005669; c=relaxed/simple; bh=8TOcBAcHy4ERcrNCANl+/YGMOI+dYHXMFUUcTMQqtHg=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KOFXOGvCI5Mf4CDwY0UMXL9tQNlyaAiWzQHy4sWz4swLxiT73XQJIsG+22tv4Pah6yB12qabpELLmylUoIgEDrSFjXPxv18nSLnDN7c0wCwjulGotB3P+aXm6curfvjUN8oC0tYN024NB2bCIzijWX2/m4JYthj6ROt9kBq7dTQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YCaMBBQR; arc=none smtp.client-ip=209.85.128.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YCaMBBQR" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-488ba840146so49002365e9.1 for ; Tue, 05 May 2026 11:27:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778005666; x=1778610466; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=pbS3OG+YVDKJuembzs3rrFe7024t5JnNqmdQJp33Wns=; b=YCaMBBQRRAC1hLMgUq1Z3pFDbrDK+W7p0G1YCX1G3egY8k7uIg7AQPJZsGMCGE175r E2fj0E1FuS52IXgSIk6sP7RzMqr8IfOKI2UUFjfejW9nsFaWv3bQ3cEjSFoxmbcV1djQ EeHOp57oWDPqtia7gCsCACmhHyI/Z8eCjudktwpjwpsO1V53qn3tcExYZWkUT8JFMVkd dFK+T1LXvfX3Aj+45axaPGvT/9hYGts+bFi0KT6i0arVduYcnBBwMIM6VV6478vBtepx XVYhlVfCcQd3z+TS8f4sCcb9otdSO9SpXcyRUA+kW/sy/B4howaSXHyUQzpE5HcoEKKF Perg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778005666; x=1778610466; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=pbS3OG+YVDKJuembzs3rrFe7024t5JnNqmdQJp33Wns=; b=RtOFBZGVPNVTuY3SENs8sqOLMdU+MC52xfwcXwE0RLeJg+09ZgVaDUQE8926avvxJY 5Sh0M+WSGgyWh7sv/1hlCnKlWEF7hDlmBq0H1o++Rm5XRW3+wrEB+Fnpwr3FPW9Dclzk A0mCkeXLb6yCkAeQD46aKKeAbPL8Ujr6pAb6khSlK0QE6gyB8xyXSkTx4GW57beCNuUs +p2OOJEyC86mDhpb6GYAmVRgn5dlp2yBz+EtMH43+qkC0TSUcYKnaWo/i6YoFcdKLcS2 WhlYhz2QdAwt79YqMGUL3YgbaAXrD/T8NUJnM0DDhaqIeFaIn5HdAhu8JoFMdF/C4KpG YD5Q== X-Forwarded-Encrypted: i=1; AFNElJ/6BmYNzrgRQg60xfMWG619MzjpQweBmUhue5q097u18FkvhMPfdLQuXA9QWT7c5ucFT9gd@lists.linux.dev X-Gm-Message-State: AOJu0YxBszvGTcShrNlUD7YpRVTGn646eMx0X32S8IRY2HnjsQTNX5r/ pUikVyyrj92Ql3q3OD8r1qsXjpAJyy7YL6S5N2k5wDMXF58W1ftWwvg+ X-Gm-Gg: AeBDieuo0DuephwgKFypSR8rhgUGLzKqA05miAnlriy1M8Zy+c7cfMvJxEN3f1bsf8A 5oQitmFA91JaAoS/YqJta+7VRBO734CfMLdLs9qiQRhjn6Zu2PitqwGNjG9CrORUWcE1xV9qYbu 8jp3RVwg1suJj+WkLQ+IBsOtgaFeyejA+l6Rc0HM4wsf9ZP0JCWbfnoTEJpdn5nF6c6R0tzgKQm 42FKXB/T1yH0vE2yvTYvtfqYL2LUdZGPGXKvMO6iIBCXIN8vAZodRZKLX8T5BzyIythRWcZXt/H /bqq97EVIT9sYUc8N8yeU/5i1Nax33MR3NU/jNIfCIw+z8XexLYc1GsNdm69pVsUGBeumwFkX3Z 5PBfXajT4GF5RL0VeCoKVe8AToNGjRFyDG0IbS04qj2Viwen2Tn4yFzvbEMvfwh2QQ7IEgbW4ON HLL5DTtV21cy84DEFpSlZyeCWDnCCXDGhS6Eo1uG5vfVHa44ozuMc9BHAW78UBtUxobrA550VKZ YtOTvo= X-Received: by 2002:a05:600c:34ca:b0:489:1f08:91b with SMTP id 5b1f17b1804b1-48e521e6085mr3516555e9.16.1778005665680; Tue, 05 May 2026 11:27:45 -0700 (PDT) Received: from Ansuel-XPS24 (host-82-59-227-65.retail.telecomitalia.it. [82.59.227.65]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-48a820c865esm408208245e9.5.2026.05.05.11.27.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 May 2026 11:27:45 -0700 (PDT) From: Christian Marangi To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lorenzo Bianconi , Heiner Kallweit , Russell King , Philipp Zabel , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Christian Marangi , Daniel Golle , netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, llvm@lists.linux.dev Subject: [net-next RFC PATCH v5 10/10] net: airoha: add phylink support for GDM2/3/4 Date: Tue, 5 May 2026 20:27:11 +0200 Message-ID: <20260505182713.27644-11-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260505182713.27644-1-ansuelsmth@gmail.com> References: <20260505182713.27644-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: llvm@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add phylink support for GDM2/3/4 port that require configuration of the PCS to make the external PHY or attached SFP cage work. These needs to be defined in the GDM port node using the pcs-handle property. Signed-off-by: Christian Marangi --- drivers/net/ethernet/airoha/Kconfig | 1 + drivers/net/ethernet/airoha/airoha_eth.c | 144 +++++++++++++++++++++- drivers/net/ethernet/airoha/airoha_eth.h | 3 + drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ 4 files changed, 159 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/airoha/Kconfig b/drivers/net/ethernet/airoha/Kconfig index ad3ce501e7a5..38dcc76e5998 100644 --- a/drivers/net/ethernet/airoha/Kconfig +++ b/drivers/net/ethernet/airoha/Kconfig @@ -20,6 +20,7 @@ config NET_AIROHA depends on NET_DSA || !NET_DSA select NET_AIROHA_NPU select PAGE_POOL + select PHYLINK help This driver supports the gigabit ethernet MACs in the Airoha SoC family. diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index 2bd79da70934..ad0328a25422 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,11 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank, airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } +static bool airhoa_is_phy_external(struct airoha_gdm_port *port) +{ + return port->id != 1; +} + static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) { struct airoha_eth *eth = port->qdma->eth; @@ -1644,6 +1650,17 @@ static int airoha_dev_open(struct net_device *dev) struct airoha_qdma *qdma = port->qdma; u32 pse_port = FE_PSE_PORT_PPE1; + if (airhoa_is_phy_external(port)) { + err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); + if (err) { + netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, + err); + return err; + } + + phylink_start(port->phylink); + } + netif_tx_start_all_queues(dev); err = airoha_set_vip_for_gdm_port(port, true); if (err) @@ -1707,6 +1724,11 @@ static int airoha_dev_stop(struct net_device *dev) } } + if (airhoa_is_phy_external(port)) { + phylink_stop(port->phylink); + phylink_disconnect_phy(port->phylink); + } + return 0; } @@ -2883,6 +2905,115 @@ bool airoha_is_valid_gdm_port(struct airoha_eth *eth, return false; } +static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, bool tx_pause, bool rx_pause) +{ + struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, + phylink_config); + struct airoha_qdma *qdma = port->qdma; + struct airoha_eth *eth = qdma->eth; + u32 frag_size_tx, frag_size_rx; + + if (port->id != 4) + return; + + switch (speed) { + case SPEED_10000: + case SPEED_5000: + frag_size_tx = 8; + frag_size_rx = 8; + break; + case SPEED_2500: + frag_size_tx = 2; + frag_size_rx = 1; + break; + default: + frag_size_tx = 1; + frag_size_rx = 0; + } + + /* Configure TX/RX frag based on speed */ + airoha_fe_rmw(eth, REG_GDMA4_TMBI_FRAG, + GDMA4_SGMII0_TX_FRAG_SIZE_MASK, + FIELD_PREP(GDMA4_SGMII0_TX_FRAG_SIZE_MASK, + frag_size_tx)); + + airoha_fe_rmw(eth, REG_GDMA4_RMBI_FRAG, + GDMA4_SGMII0_RX_FRAG_SIZE_MASK, + FIELD_PREP(GDMA4_SGMII0_RX_FRAG_SIZE_MASK, + frag_size_rx)); +} + +static const struct phylink_mac_ops airoha_phylink_ops = { + .mac_link_up = airoha_mac_link_up, +}; + +static int airoha_setup_phylink(struct net_device *dev) +{ + struct airoha_gdm_port *port = netdev_priv(dev); + struct device_node *np = dev->dev.of_node; + struct phylink_pcs **available_pcs; + phy_interface_t phy_mode; + struct phylink *phylink; + unsigned int num_pcs; + int err; + + err = of_get_phy_mode(np, &phy_mode); + if (err) { + dev_err(&dev->dev, "incorrect phy-mode\n"); + return err; + } + + port->phylink_config.dev = &dev->dev; + port->phylink_config.type = PHYLINK_NETDEV; + port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | + MAC_5000FD | MAC_10000FD; + + err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, &num_pcs); + if (err) + return err; + + available_pcs = kcalloc(num_pcs, sizeof(*available_pcs), GFP_KERNEL); + if (!available_pcs) + return -ENOMEM; + + err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), available_pcs, + &num_pcs); + if (err) + goto out; + + port->phylink_config.available_pcs = available_pcs; + port->phylink_config.num_available_pcs = num_pcs; + + __set_bit(PHY_INTERFACE_MODE_SGMII, + port->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, + port->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, + port->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_USXGMII, + port->phylink_config.supported_interfaces); + + phy_interface_copy(port->phylink_config.pcs_interfaces, + port->phylink_config.supported_interfaces); + + phylink = phylink_create(&port->phylink_config, + of_fwnode_handle(np), + phy_mode, &airoha_phylink_ops); + if (IS_ERR(phylink)) { + err = PTR_ERR(phylink); + goto out; + } + + port->phylink = phylink; +out: + kfree(available_pcs); + + return err; +} + static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) { @@ -2954,6 +3085,12 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth, port->id = id; eth->ports[p] = port; + if (airhoa_is_phy_external(port)) { + err = airoha_setup_phylink(dev); + if (err) + return err; + } + return airoha_metadata_dst_alloc(port); } @@ -3081,8 +3218,11 @@ static int airoha_probe(struct platform_device *pdev) if (!port) continue; - if (port->dev->reg_state == NETREG_REGISTERED) + if (port->dev->reg_state == NETREG_REGISTERED) { + if (airhoa_is_phy_external(port)) + phylink_destroy(port->phylink); unregister_netdev(port->dev); + } airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); @@ -3107,6 +3247,8 @@ static void airoha_remove(struct platform_device *pdev) if (!port) continue; + if (airhoa_is_phy_external(port)) + phylink_destroy(port->phylink); unregister_netdev(port->dev); airoha_metadata_dst_free(port); } diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index af29fc74165b..e5c70f1fa4f1 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -538,6 +538,9 @@ struct airoha_gdm_port { struct net_device *dev; int id; + struct phylink *phylink; + struct phylink_config phylink_config; + struct airoha_hw_stats stats; DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h index 436f3c8779c1..27f2583e143a 100644 --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -358,6 +358,18 @@ #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) +#define REG_GDMA4_TMBI_FRAG 0x2028 +#define GDMA4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) +#define GDMA4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) +#define GDMA4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) +#define GDMA4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) + +#define REG_GDMA4_RMBI_FRAG 0x202c +#define GDMA4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) +#define GDMA4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) +#define GDMA4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) +#define GDMA4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) + #define REG_MC_VLAN_EN 0x2100 #define MC_VLAN_EN_MASK BIT(0) -- 2.53.0