From nobody Sun Dec 22 11:38:36 2024 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F96AC7EE23 for ; Thu, 1 Jun 2023 14:15:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234226AbjFAOPr (ORCPT ); Thu, 1 Jun 2023 10:15:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234209AbjFAOPa (ORCPT ); Thu, 1 Jun 2023 10:15:30 -0400 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 18CC1E66; Thu, 1 Jun 2023 07:15:16 -0700 (PDT) X-GND-Sasl: maxime.chevallier@bootlin.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1685628915; 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=OL7zcYJTWV/nEVLufRJVs96x/jiRqDhLoDIaAwogNMU=; b=U2OiZEab/X89NwF/hNerB+H1MUaok3GnK+ZDaq72hBHDwfQF9XgYWnQX4Schty8/zM1Qgw U0BBQwBJIiRZy4UN40bLrIyEWUtNxuSA1k4CtkWHSXyOkQqPycRdtXSEwIJj/j7a2G1lPr wdsN+YYNhTTeRJghz4jvQ98gSDJ0XEQmm/lHNgQB8LyIy0MVnTMQeiJCOFpkhn7R1YlgqI rfMEqA0bMfIwv+XPh8K9u0/3gY7wNWzOCcwcQlCkQTZy4V2LcuPvkUxI/wVD5nKWP5P8MP JvvrMQygpUnONvqJ3VKhDdrMpiTwZQzU2mTVZBxxcR4MbmjJo4eGszUDqBT4gQ== X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com X-GND-Sasl: maxime.chevallier@bootlin.com Received: by mail.gandi.net (Postfix) with ESMTPSA id E61D620008; Thu, 1 Jun 2023 14:15:12 +0000 (UTC) From: Maxime Chevallier To: Mark Brown , davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alexis.lothore@bootlin.com, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Ioana Ciornei , linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, Maxime Coquelin , Jose Abreu , Alexandre Torgue , Giuseppe Cavallaro , Simon Horman Subject: [PATCH net-next v4 4/4] net: stmmac: dwmac-sogfpga: use the lynx pcs driver Date: Thu, 1 Jun 2023 16:14:54 +0200 Message-Id: <20230601141454.67858-5-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230601141454.67858-1-maxime.chevallier@bootlin.com> References: <20230601141454.67858-1-maxime.chevallier@bootlin.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" dwmac_socfpga re-implements support for the TSE PCS, which is identical to the already existing TSE PCS, which in turn is the same as the Lynx PCS. Drop the existing TSE re-implemenation and use the Lynx PCS instead, relying on the regmap-mdio driver to translate MDIO accesses into mmio accesses. Add a lynx_pcs reference in the stmmac's internal structure, and use .mac_select_pcs() to return the relevant PCS to be used. Signed-off-by: Maxime Chevallier Reviewed-by: Simon Horman --- V3->V4 : - Use pcs_lynx_create/destroy() - Add a missing cleanup step for this PCS - rename the new PCS field from phylink_pcs to lynx_pcs, as we need to know which kind of PCS it is to call the proper cleanup helper - Add missing Kconfig dependencies V2->V3 : No changes V1->V2 : No changes drivers/net/ethernet/stmicro/stmmac/Kconfig | 3 + drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- .../ethernet/stmicro/stmmac/altr_tse_pcs.c | 257 ------------------ .../ethernet/stmicro/stmmac/altr_tse_pcs.h | 29 -- drivers/net/ethernet/stmicro/stmmac/common.h | 2 + .../ethernet/stmicro/stmmac/dwmac-socfpga.c | 91 +++++-- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 12 +- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 + 8 files changed, 83 insertions(+), 316 deletions(-) delete mode 100644 drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c delete mode 100644 drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethe= rnet/stmicro/stmmac/Kconfig index 5f5a997f21f3..5583f0b055ec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -158,6 +158,9 @@ config DWMAC_SOCFPGA default ARCH_INTEL_SOCFPGA depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST) select MFD_SYSCON + select MDIO_REGMAP + select REGMAP_MMIO + select PCS_LYNX help Support for ethernet controller on Altera SOCFPGA =20 diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/eth= ernet/stmicro/stmmac/Makefile index 8738fdbb4b2d..7dd3d388068b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_DWMAC_IMX8) +=3D dwmac-imx.o obj-$(CONFIG_DWMAC_TEGRA) +=3D dwmac-tegra.o obj-$(CONFIG_DWMAC_VISCONTI) +=3D dwmac-visconti.o stmmac-platform-objs:=3D stmmac_platform.o -dwmac-altr-socfpga-objs :=3D altr_tse_pcs.o dwmac-socfpga.o +dwmac-altr-socfpga-objs :=3D dwmac-socfpga.o =20 obj-$(CONFIG_STMMAC_PCI) +=3D stmmac-pci.o obj-$(CONFIG_DWMAC_INTEL) +=3D dwmac-intel.o diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/n= et/ethernet/stmicro/stmmac/altr_tse_pcs.c deleted file mode 100644 index 00f6d347eaf7..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright Altera Corporation (C) 2016. All rights reserved. - * - * Author: Tien Hock Loh - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stmmac.h" -#include "stmmac_platform.h" -#include "altr_tse_pcs.h" - -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0 -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII BIT(1) -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII BIT(2) -#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 -#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK GENMASK(1, 0) - -#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12) -#define TSE_PCS_CONTROL_REG 0x00 -#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9) -#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140 -#define TSE_PCS_IF_MODE_REG 0x28 -#define TSE_PCS_LINK_TIMER_0_REG 0x24 -#define TSE_PCS_LINK_TIMER_1_REG 0x26 -#define TSE_PCS_SIZE 0x40 -#define TSE_PCS_STATUS_AN_COMPLETED_MASK BIT(5) -#define TSE_PCS_STATUS_LINK_MASK 0x0004 -#define TSE_PCS_STATUS_REG 0x02 -#define TSE_PCS_SGMII_SPEED_1000 BIT(3) -#define TSE_PCS_SGMII_SPEED_100 BIT(2) -#define TSE_PCS_SGMII_SPEED_10 0x0 -#define TSE_PCS_SW_RST_MASK 0x8000 -#define TSE_PCS_PARTNER_ABILITY_REG 0x0A -#define TSE_PCS_PARTNER_DUPLEX_FULL 0x1000 -#define TSE_PCS_PARTNER_DUPLEX_HALF 0x0000 -#define TSE_PCS_PARTNER_DUPLEX_MASK 0x1000 -#define TSE_PCS_PARTNER_SPEED_MASK GENMASK(11, 10) -#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) -#define TSE_PCS_PARTNER_SPEED_100 BIT(10) -#define TSE_PCS_PARTNER_SPEED_10 0x0000 -#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) -#define TSE_PCS_PARTNER_SPEED_100 BIT(10) -#define TSE_PCS_PARTNER_SPEED_10 0x0000 -#define TSE_PCS_SGMII_SPEED_MASK GENMASK(3, 2) -#define TSE_PCS_SGMII_LINK_TIMER_0 0x0D40 -#define TSE_PCS_SGMII_LINK_TIMER_1 0x0003 -#define TSE_PCS_SW_RESET_TIMEOUT 100 -#define TSE_PCS_USE_SGMII_AN_MASK BIT(1) -#define TSE_PCS_USE_SGMII_ENA BIT(0) -#define TSE_PCS_IF_USE_SGMII 0x03 - -#define AUTONEGO_LINK_TIMER 20 - -static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs) -{ - int counter =3D 0; - u16 val; - - val =3D readw(base + TSE_PCS_CONTROL_REG); - val |=3D TSE_PCS_SW_RST_MASK; - writew(val, base + TSE_PCS_CONTROL_REG); - - while (counter < TSE_PCS_SW_RESET_TIMEOUT) { - val =3D readw(base + TSE_PCS_CONTROL_REG); - val &=3D TSE_PCS_SW_RST_MASK; - if (val =3D=3D 0) - break; - counter++; - udelay(1); - } - if (counter >=3D TSE_PCS_SW_RESET_TIMEOUT) { - dev_err(pcs->dev, "PCS could not get out of sw reset\n"); - return -ETIMEDOUT; - } - - return 0; -} - -int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs) -{ - int ret =3D 0; - - writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG); - - writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG); - - writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG); - writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); - - ret =3D tse_pcs_reset(base, pcs); - if (ret =3D=3D 0) - writew(SGMII_ADAPTER_ENABLE, - pcs->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - - return ret; -} - -static void pcs_link_timer_callback(struct tse_pcs *pcs) -{ - u16 val =3D 0; - void __iomem *tse_pcs_base =3D pcs->tse_pcs_base; - void __iomem *sgmii_adapter_base =3D pcs->sgmii_adapter_base; - - val =3D readw(tse_pcs_base + TSE_PCS_STATUS_REG); - val &=3D TSE_PCS_STATUS_LINK_MASK; - - if (val !=3D 0) { - dev_dbg(pcs->dev, "Adapter: Link is established\n"); - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - } else { - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} - -static void auto_nego_timer_callback(struct tse_pcs *pcs) -{ - u16 val =3D 0; - u16 speed =3D 0; - u16 duplex =3D 0; - void __iomem *tse_pcs_base =3D pcs->tse_pcs_base; - void __iomem *sgmii_adapter_base =3D pcs->sgmii_adapter_base; - - val =3D readw(tse_pcs_base + TSE_PCS_STATUS_REG); - val &=3D TSE_PCS_STATUS_AN_COMPLETED_MASK; - - if (val !=3D 0) { - dev_dbg(pcs->dev, "Adapter: Auto Negotiation is completed\n"); - val =3D readw(tse_pcs_base + TSE_PCS_PARTNER_ABILITY_REG); - speed =3D val & TSE_PCS_PARTNER_SPEED_MASK; - duplex =3D val & TSE_PCS_PARTNER_DUPLEX_MASK; - - if (speed =3D=3D TSE_PCS_PARTNER_SPEED_10 && - duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 10/Full\n"); - else if (speed =3D=3D TSE_PCS_PARTNER_SPEED_100 && - duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 100/Full\n"); - else if (speed =3D=3D TSE_PCS_PARTNER_SPEED_1000 && - duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 1000/Full\n"); - else if (speed =3D=3D TSE_PCS_PARTNER_SPEED_10 && - duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else if (speed =3D=3D TSE_PCS_PARTNER_SPEED_100 && - duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else if (speed =3D=3D TSE_PCS_PARTNER_SPEED_1000 && - duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else - dev_err(pcs->dev, - "Adapter: Invalid Partner Speed and Duplex\n"); - - if (duplex =3D=3D TSE_PCS_PARTNER_DUPLEX_FULL && - (speed =3D=3D TSE_PCS_PARTNER_SPEED_10 || - speed =3D=3D TSE_PCS_PARTNER_SPEED_100 || - speed =3D=3D TSE_PCS_PARTNER_SPEED_1000)) - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - } else { - val =3D readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |=3D TSE_PCS_CONTROL_RESTART_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - tse_pcs_reset(tse_pcs_base, pcs); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} - -static void aneg_link_timer_callback(struct timer_list *t) -{ - struct tse_pcs *pcs =3D from_timer(pcs, t, aneg_link_timer); - - if (pcs->autoneg =3D=3D AUTONEG_ENABLE) - auto_nego_timer_callback(pcs); - else if (pcs->autoneg =3D=3D AUTONEG_DISABLE) - pcs_link_timer_callback(pcs); -} - -void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, - unsigned int speed) -{ - void __iomem *tse_pcs_base =3D pcs->tse_pcs_base; - u32 val; - - pcs->autoneg =3D phy_dev->autoneg; - - if (phy_dev->autoneg =3D=3D AUTONEG_ENABLE) { - val =3D readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |=3D TSE_PCS_CONTROL_AN_EN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - val =3D readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val |=3D TSE_PCS_USE_SGMII_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - val =3D readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |=3D TSE_PCS_CONTROL_RESTART_AN_MASK; - - tse_pcs_reset(tse_pcs_base, pcs); - - timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback, - 0); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } else if (phy_dev->autoneg =3D=3D AUTONEG_DISABLE) { - val =3D readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val &=3D ~TSE_PCS_CONTROL_AN_EN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - val =3D readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val &=3D ~TSE_PCS_USE_SGMII_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - val =3D readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val &=3D ~TSE_PCS_SGMII_SPEED_MASK; - - switch (speed) { - case 1000: - val |=3D TSE_PCS_SGMII_SPEED_1000; - break; - case 100: - val |=3D TSE_PCS_SGMII_SPEED_100; - break; - case 10: - val |=3D TSE_PCS_SGMII_SPEED_10; - break; - default: - return; - } - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - tse_pcs_reset(tse_pcs_base, pcs); - - timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback, - 0); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/n= et/ethernet/stmicro/stmmac/altr_tse_pcs.h deleted file mode 100644 index 694ac25ef426..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright Altera Corporation (C) 2016. All rights reserved. - * - * Author: Tien Hock Loh - */ - -#ifndef __TSE_PCS_H__ -#define __TSE_PCS_H__ - -#include -#include - -#define SGMII_ADAPTER_CTRL_REG 0x00 -#define SGMII_ADAPTER_ENABLE 0x0000 -#define SGMII_ADAPTER_DISABLE 0x0001 - -struct tse_pcs { - struct device *dev; - void __iomem *tse_pcs_base; - void __iomem *sgmii_adapter_base; - struct timer_list aneg_link_timer; - int autoneg; -}; - -int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs); -void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, - unsigned int speed); - -#endif /* __TSE_PCS_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/eth= ernet/stmicro/stmmac/common.h index 4ad692c4116c..52c5ec553276 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #if IS_ENABLED(CONFIG_VLAN_8021Q) #define STMMAC_VLAN_TAG_USED @@ -519,6 +520,7 @@ struct mac_device_info { const struct stmmac_tc_ops *tc; const struct stmmac_mmc_ops *mmc; struct dw_xpcs *xpcs; + struct phylink_pcs *lynx_pcs; /* Lynx external PCS */ struct mii_regs mii; /* MII register Addresses */ struct mac_link link; void __iomem *pcsr; /* vpointer to device CSRs */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/= net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 6ee050300b31..e399fccbafe5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -10,14 +10,13 @@ #include #include #include +#include #include #include =20 #include "stmmac.h" #include "stmmac_platform.h" =20 -#include "altr_tse_pcs.h" - #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 @@ -37,6 +36,10 @@ #define EMAC_SPLITTER_CTRL_SPEED_100 0x3 #define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 =20 +#define SGMII_ADAPTER_CTRL_REG 0x00 +#define SGMII_ADAPTER_ENABLE 0x0000 +#define SGMII_ADAPTER_DISABLE 0x0001 + struct socfpga_dwmac; struct socfpga_dwmac_ops { int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); @@ -50,16 +53,18 @@ struct socfpga_dwmac { struct reset_control *stmmac_rst; struct reset_control *stmmac_ocp_rst; void __iomem *splitter_base; + void __iomem *tse_pcs_base; + void __iomem *sgmii_adapter_base; bool f2h_ptp_ref_clk; - struct tse_pcs pcs; const struct socfpga_dwmac_ops *ops; + struct mdio_device *pcs_mdiodev; }; =20 static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) { struct socfpga_dwmac *dwmac =3D (struct socfpga_dwmac *)priv; void __iomem *splitter_base =3D dwmac->splitter_base; - void __iomem *sgmii_adapter_base =3D dwmac->pcs.sgmii_adapter_base; + void __iomem *sgmii_adapter_base =3D dwmac->sgmii_adapter_base; struct device *dev =3D dwmac->dev; struct net_device *ndev =3D dev_get_drvdata(dev); struct phy_device *phy_dev =3D ndev->phydev; @@ -89,11 +94,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsi= gned int speed) writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); } =20 - if (phy_dev && sgmii_adapter_base) { + if (phy_dev && sgmii_adapter_base) writew(SGMII_ADAPTER_ENABLE, sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); - } } =20 static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct de= vice *dev) @@ -183,11 +186,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dw= mac *dwmac, struct device * goto err_node_put; } =20 - dwmac->pcs.sgmii_adapter_base =3D + dwmac->sgmii_adapter_base =3D devm_ioremap_resource(dev, &res_sgmii_adapter); =20 - if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) { - ret =3D PTR_ERR(dwmac->pcs.sgmii_adapter_base); + if (IS_ERR(dwmac->sgmii_adapter_base)) { + ret =3D PTR_ERR(dwmac->sgmii_adapter_base); goto err_node_put; } } @@ -205,11 +208,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dw= mac *dwmac, struct device * goto err_node_put; } =20 - dwmac->pcs.tse_pcs_base =3D + dwmac->tse_pcs_base =3D devm_ioremap_resource(dev, &res_tse_pcs); =20 - if (IS_ERR(dwmac->pcs.tse_pcs_base)) { - ret =3D PTR_ERR(dwmac->pcs.tse_pcs_base); + if (IS_ERR(dwmac->tse_pcs_base)) { + ret =3D PTR_ERR(dwmac->tse_pcs_base); goto err_node_put; } } @@ -235,6 +238,13 @@ static int socfpga_get_plat_phymode(struct socfpga_dwm= ac *dwmac) return priv->plat->interface; } =20 +static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable) +{ + u16 val =3D enable ? SGMII_ADAPTER_ENABLE : SGMII_ADAPTER_DISABLE; + + writew(val, dwmac->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); +} + static int socfpga_set_phy_mode_common(int phymode, u32 *val) { switch (phymode) { @@ -310,12 +320,8 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dw= mac *dwmac) */ reset_control_deassert(dwmac->stmmac_ocp_rst); reset_control_deassert(dwmac->stmmac_rst); - if (phymode =3D=3D PHY_INTERFACE_MODE_SGMII) { - if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) !=3D 0) { - dev_err(dwmac->dev, "Unable to initialize TSE PCS"); - return -EINVAL; - } - } + if (phymode =3D=3D PHY_INTERFACE_MODE_SGMII) + socfpga_sgmii_config(dwmac, true); =20 return 0; } @@ -367,12 +373,8 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_d= wmac *dwmac) */ reset_control_deassert(dwmac->stmmac_ocp_rst); reset_control_deassert(dwmac->stmmac_rst); - if (phymode =3D=3D PHY_INTERFACE_MODE_SGMII) { - if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) !=3D 0) { - dev_err(dwmac->dev, "Unable to initialize TSE PCS"); - return -EINVAL; - } - } + if (phymode =3D=3D PHY_INTERFACE_MODE_SGMII) + socfpga_sgmii_config(dwmac, true); return 0; } =20 @@ -386,6 +388,7 @@ static int socfpga_dwmac_probe(struct platform_device *= pdev) struct net_device *ndev; struct stmmac_priv *stpriv; const struct socfpga_dwmac_ops *ops; + struct regmap_config pcs_regmap_cfg; =20 ops =3D device_get_match_data(&pdev->dev); if (!ops) { @@ -443,6 +446,44 @@ static int socfpga_dwmac_probe(struct platform_device = *pdev) if (ret) goto err_dvr_remove; =20 + memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg)); + pcs_regmap_cfg.reg_bits =3D 16; + pcs_regmap_cfg.val_bits =3D 16; + pcs_regmap_cfg.reg_shift =3D REGMAP_UPSHIFT(1); + + /* Create a regmap for the PCS so that it can be used by the PCS driver, + * if we have such a PCS + */ + if (dwmac->tse_pcs_base) { + struct mdio_regmap_config mrc; + struct regmap *pcs_regmap; + struct mii_bus *pcs_bus; + + pcs_regmap =3D devm_regmap_init_mmio(&pdev->dev, dwmac->tse_pcs_base, + &pcs_regmap_cfg); + if (IS_ERR(pcs_regmap)) { + ret =3D PTR_ERR(pcs_regmap); + goto err_dvr_remove; + } + + mrc.regmap =3D pcs_regmap; + mrc.parent =3D &pdev->dev; + mrc.valid_addr =3D 0x0; + + snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name); + pcs_bus =3D devm_mdio_regmap_register(&pdev->dev, &mrc); + if (IS_ERR(pcs_bus)) { + ret =3D PTR_ERR(pcs_bus); + goto err_dvr_remove; + } + + stpriv->hw->lynx_pcs =3D lynx_pcs_create_mdiodev(pcs_bus, 0); + if (IS_ERR(stpriv->hw->lynx_pcs)) { + ret =3D PTR_ERR(stpriv->hw->lynx_pcs); + goto err_dvr_remove; + } + } + return 0; =20 err_dvr_remove: diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_main.c index 0fca81507a77..cff76e215f7d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -937,10 +937,13 @@ static struct phylink_pcs *stmmac_mac_select_pcs(stru= ct phylink_config *config, { struct stmmac_priv *priv =3D netdev_priv(to_net_dev(config->dev)); =20 - if (!priv->hw->xpcs) - return NULL; + if (priv->hw->xpcs) + return &priv->hw->xpcs->pcs; + + if (priv->hw->lynx_pcs) + return priv->hw->lynx_pcs; =20 - return &priv->hw->xpcs->pcs; + return NULL; } =20 static void stmmac_mac_config(struct phylink_config *config, unsigned int = mode, @@ -3813,7 +3816,8 @@ static int __stmmac_open(struct net_device *dev, if (priv->hw->pcs !=3D STMMAC_PCS_TBI && priv->hw->pcs !=3D STMMAC_PCS_RTBI && (!priv->hw->xpcs || - xpcs_get_an_mode(priv->hw->xpcs, mode) !=3D DW_AN_C73)) { + xpcs_get_an_mode(priv->hw->xpcs, mode) !=3D DW_AN_C73) && + !priv->hw->lynx_pcs) { ret =3D stmmac_init_phy(dev); if (ret) { netdev_err(priv->dev, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_mdio.c index 3db1cb0fd160..c784a6731f08 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -665,6 +665,9 @@ int stmmac_mdio_unregister(struct net_device *ndev) if (priv->hw->xpcs) xpcs_destroy(priv->hw->xpcs); =20 + if (priv->hw->lynx_pcs) + lynx_pcs_destroy(priv->hw->lynx_pcs); + mdiobus_unregister(priv->mii); priv->mii->priv =3D NULL; mdiobus_free(priv->mii); --=20 2.40.1