From nobody Fri Sep 20 09:31:24 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 7B489C4332F for ; Tue, 12 Dec 2023 03:51:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345902AbjLLDvf (ORCPT ); Mon, 11 Dec 2023 22:51:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43306 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234973AbjLLDvb (ORCPT ); Mon, 11 Dec 2023 22:51:31 -0500 Received: from pidgin.makrotopia.org (pidgin.makrotopia.org [185.142.180.65]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF894CE; Mon, 11 Dec 2023 19:51:30 -0800 (PST) Received: from local by pidgin.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.96.2) (envelope-from ) id 1rCtng-0002vh-2P; Tue, 12 Dec 2023 03:51:17 +0000 Date: Tue, 12 Dec 2023 03:51:14 +0000 From: Daniel Golle To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chunfeng Yun , Vinod Koul , Kishon Vijay Abraham I , Felix Fietkau , John Crispin , Sean Wang , Mark Lee , Lorenzo Bianconi , Matthias Brugger , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King , Alexander Couzens , Daniel Golle , Qingfang Deng , SkyLake Huang , Philipp Zabel , netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org Subject: [RFC PATCH net-next v3 8/8] net: ethernet: mtk_eth_soc: add paths and SerDes modes for MT7988 Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" MT7988 comes with a built-in 2.5G PHY as well as SerDes lanes to connect external PHYs or transceivers in USXGMII, 10GBase-R, 5GBase-R, 2500Base-X, 1000Base-X and Cisco SGMII interface modes. Implement support for configuring for the new paths to SerDes interfaces and the internal 2.5G PHY. Add USXGMII PCS driver for 10GBase-R, 5GBase-R and USXGMII mode, and setup the new PHYA on MT7988 to access the also still existing old LynxI PCS for 1000Base-X, 2500Base-X and Cisco SGMII PCS interface modes. Signed-off-by: Daniel Golle --- drivers/net/ethernet/mediatek/mtk_eth_path.c | 122 +++++++- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 291 +++++++++++++++++-- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 107 ++++++- 3 files changed, 469 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_path.c b/drivers/net/eth= ernet/mediatek/mtk_eth_path.c index 7c27a19c4d8f4..3f4f4cfe6a233 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_path.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c @@ -31,10 +31,20 @@ static const char *mtk_eth_path_name(u64 path) return "gmac2_rgmii"; case MTK_ETH_PATH_GMAC2_SGMII: return "gmac2_sgmii"; + case MTK_ETH_PATH_GMAC2_2P5GPHY: + return "gmac2_2p5gphy"; case MTK_ETH_PATH_GMAC2_GEPHY: return "gmac2_gephy"; + case MTK_ETH_PATH_GMAC3_SGMII: + return "gmac3_sgmii"; case MTK_ETH_PATH_GDM1_ESW: return "gdm1_esw"; + case MTK_ETH_PATH_GMAC1_USXGMII: + return "gmac1_usxgmii"; + case MTK_ETH_PATH_GMAC2_USXGMII: + return "gmac2_usxgmii"; + case MTK_ETH_PATH_GMAC3_USXGMII: + return "gmac3_usxgmii"; default: return "unknown path"; } @@ -127,6 +137,27 @@ static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *et= h, u64 path) return 0; } =20 +static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path) +{ + int ret; + + if (path =3D=3D MTK_ETH_PATH_GMAC2_2P5GPHY) { + ret =3D regmap_clear_bits(eth->ethsys, ETHSYS_SYSCFG0, SYSCFG0_SGMII_GMA= C2_V2); + if (ret) + return ret; + + /* Setup mux to 2p5g PHY */ + ret =3D regmap_clear_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX, MUX_G2_US= XGMII_SEL); + if (ret) + return ret; + + dev_dbg(eth->dev, "path %s in %s updated\n", + mtk_eth_path_name(path), __func__); + } + + return 0; +} + static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 pat= h) { unsigned int val =3D 0; @@ -165,7 +196,48 @@ static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct m= tk_eth *eth, u64 path) return 0; } =20 -static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) +static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path) +{ + unsigned int val =3D 0; + bool updated =3D true; + int mac_id =3D 0; + + /* Disable SYSCFG1 SGMII */ + regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); + + switch (path) { + case MTK_ETH_PATH_GMAC1_USXGMII: + val &=3D ~(u32)SYSCFG0_SGMII_GMAC1_V2; + mac_id =3D MTK_GMAC1_ID; + break; + case MTK_ETH_PATH_GMAC2_USXGMII: + val &=3D ~(u32)SYSCFG0_SGMII_GMAC2_V2; + mac_id =3D MTK_GMAC2_ID; + break; + case MTK_ETH_PATH_GMAC3_USXGMII: + val &=3D ~(u32)SYSCFG0_SGMII_GMAC3_V2; + mac_id =3D MTK_GMAC3_ID; + break; + default: + updated =3D false; + }; + + if (updated) { + regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, + SYSCFG0_SGMII_MASK, val); + + if (mac_id =3D=3D MTK_GMAC2_ID) + regmap_set_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX, + MUX_G2_USXGMII_SEL); + } + + dev_dbg(eth->dev, "path %s in %s updated =3D %d\n", + mtk_eth_path_name(path), __func__, updated); + + return 0; +} + +static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path) { unsigned int val =3D 0; bool updated =3D true; @@ -182,6 +254,9 @@ static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth= *eth, u64 path) case MTK_ETH_PATH_GMAC2_SGMII: val |=3D SYSCFG0_SGMII_GMAC2_V2; break; + case MTK_ETH_PATH_GMAC3_SGMII: + val |=3D SYSCFG0_SGMII_GMAC3_V2; + break; default: updated =3D false; } @@ -209,6 +284,10 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] =3D { .name =3D "mux_u3_gmac2_to_qphy", .cap_bit =3D MTK_ETH_MUX_U3_GMAC2_TO_QPHY, .set_path =3D set_mux_u3_gmac2_to_qphy, + }, { + .name =3D "mux_gmac2_to_2p5gphy", + .cap_bit =3D MTK_ETH_MUX_GMAC2_TO_2P5GPHY, + .set_path =3D set_mux_gmac2_to_2p5gphy, }, { .name =3D "mux_gmac1_gmac2_to_sgmii_rgmii", .cap_bit =3D MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII, @@ -216,7 +295,15 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] =3D { }, { .name =3D "mux_gmac12_to_gephy_sgmii", .cap_bit =3D MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII, - .set_path =3D set_mux_gmac12_to_gephy_sgmii, + .set_path =3D set_mux_gmac123_to_gephy_sgmii, + }, { + .name =3D "mux_gmac123_to_gephy_sgmii", + .cap_bit =3D MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII, + .set_path =3D set_mux_gmac123_to_gephy_sgmii, + }, { + .name =3D "mux_gmac123_to_usxgmii", + .cap_bit =3D MTK_ETH_MUX_GMAC123_TO_USXGMII, + .set_path =3D set_mux_gmac123_to_usxgmii, }, }; =20 @@ -249,12 +336,39 @@ static int mtk_eth_mux_setup(struct mtk_eth *eth, u64= path) return err; } =20 +int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id) +{ + u64 path; + + path =3D (mac_id =3D=3D MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII : + (mac_id =3D=3D MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_USXGMII : + MTK_ETH_PATH_GMAC3_USXGMII; + + /* Setup proper MUXes along the path */ + return mtk_eth_mux_setup(eth, path); +} + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) { u64 path; =20 - path =3D (mac_id =3D=3D 0) ? MTK_ETH_PATH_GMAC1_SGMII : - MTK_ETH_PATH_GMAC2_SGMII; + path =3D (mac_id =3D=3D MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII : + (mac_id =3D=3D MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII : + MTK_ETH_PATH_GMAC3_SGMII; + + /* Setup proper MUXes along the path */ + return mtk_eth_mux_setup(eth, path); +} + +int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id) +{ + u64 path =3D 0; + + if (mac_id =3D=3D MTK_GMAC2_ID) + path =3D MTK_ETH_PATH_GMAC2_2P5GPHY; + + if (!path) + return -EINVAL; =20 /* Setup proper MUXes along the path */ return mtk_eth_mux_setup(eth, path); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethe= rnet/mediatek/mtk_eth_soc.c index a6e91573f8dae..da0ec44268c8e 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -260,12 +262,8 @@ static const char * const mtk_clks_source_name[] =3D { "ethwarp_wocpu2", "ethwarp_wocpu1", "ethwarp_wocpu0", - "top_usxgmii0_sel", - "top_usxgmii1_sel", "top_sgm0_sel", "top_sgm1_sel", - "top_xfi_phy0_xtal_sel", - "top_xfi_phy1_xtal_sel", "top_eth_gmii_sel", "top_eth_refck_50m_sel", "top_eth_sys_200m_sel", @@ -508,6 +506,30 @@ static void mtk_setup_bridge_switch(struct mtk_eth *et= h) MTK_GSW_CFG); } =20 +static bool mtk_check_gmac23_idle(struct mtk_mac *mac) +{ + u32 mac_fsm, gdm_fsm; + + mac_fsm =3D mtk_r32(mac->hw, MTK_MAC_FSM(mac->id)); + + switch (mac->id) { + case MTK_GMAC2_ID: + gdm_fsm =3D mtk_r32(mac->hw, MTK_FE_GDM2_FSM); + break; + case MTK_GMAC3_ID: + gdm_fsm =3D mtk_r32(mac->hw, MTK_FE_GDM3_FSM); + break; + default: + return true; + }; + + if ((mac_fsm & 0xFFFF0000) =3D=3D 0x01010000 && + (gdm_fsm & 0xFFFF0000) =3D=3D 0x00000000) + return true; + + return false; +} + static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *confi= g, phy_interface_t interface) { @@ -516,6 +538,21 @@ static struct phylink_pcs *mtk_mac_select_pcs(struct p= hylink_config *config, struct mtk_eth *eth =3D mac->hw; unsigned int sid; =20 + if (mtk_is_netsys_v3_or_greater(eth)) { + switch (interface) { + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_SGMII: + return mac->sgmii_pcs; + case PHY_INTERFACE_MODE_5GBASER: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_USXGMII: + return mac->usxgmii_pcs; + default: + return NULL; + } + } + if (interface =3D=3D PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) { sid =3D (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? @@ -567,7 +604,22 @@ static void mtk_mac_config(struct phylink_config *conf= ig, unsigned int mode, goto init_err; } break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_5GBASER: + if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) { + err =3D mtk_gmac_usxgmii_path_setup(eth, mac->id); + if (err) + goto init_err; + } + break; case PHY_INTERFACE_MODE_INTERNAL: + if (mac->id =3D=3D MTK_GMAC2_ID && + MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) { + err =3D mtk_gmac_2p5gphy_path_setup(eth, mac->id); + if (err) + goto init_err; + } break; default: goto err_phy; @@ -614,8 +666,6 @@ static void mtk_mac_config(struct phylink_config *confi= g, unsigned int mode, val &=3D ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id); val |=3D SYSCFG0_GE_MODE(ge_mode, mac->id); regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); - - mac->interface =3D state->interface; } =20 /* SGMII */ @@ -632,21 +682,40 @@ static void mtk_mac_config(struct phylink_config *con= fig, unsigned int mode, =20 /* Save the syscfg0 value for mac_finish */ mac->syscfg0 =3D val; - } else if (phylink_autoneg_inband(mode)) { + } else if (state->interface !=3D PHY_INTERFACE_MODE_USXGMII && + state->interface !=3D PHY_INTERFACE_MODE_10GBASER && + state->interface !=3D PHY_INTERFACE_MODE_5GBASER && + phylink_autoneg_inband(mode)) { dev_err(eth->dev, - "In-band mode not supported in non SGMII mode!\n"); + "In-band mode not supported in non-SerDes modes!\n"); return; } =20 /* Setup gmac */ - if (mtk_is_netsys_v3_or_greater(eth) && - mac->interface =3D=3D PHY_INTERFACE_MODE_INTERNAL) { - mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id)); - mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id)); + if (mtk_is_netsys_v3_or_greater(eth)) { + if (mtk_interface_mode_is_xgmii(state->interface)) { + mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id)); + mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id)); =20 - mtk_setup_bridge_switch(eth); + if (mac->id =3D=3D MTK_GMAC1_ID) + mtk_setup_bridge_switch(eth); + } else { + mtk_w32(eth, 0, MTK_GDMA_EG_CTRL(mac->id)); + + /* FIXME: In current hardware design, we have to reset FE + * when swtiching XGDM to GDM. Therefore, here trigger an SER + * to let GDM go back to the initial state. + */ + if ((mtk_interface_mode_is_xgmii(mac->interface) || + mac->interface =3D=3D PHY_INTERFACE_MODE_NA) && + !mtk_check_gmac23_idle(mac) && + !test_bit(MTK_RESETTING, ð->state)) + schedule_work(ð->pending_work); + } } =20 + mac->interface =3D state->interface; + return; =20 err_phy: @@ -659,6 +728,18 @@ static void mtk_mac_config(struct phylink_config *conf= ig, unsigned int mode, mac->id, phy_modes(state->interface), err); } =20 +static int mtk_mac_prepare(struct phylink_config *config, unsigned int mod= e, + phy_interface_t interface) +{ + struct mtk_mac *mac =3D container_of(config, struct mtk_mac, + phylink_config); + + if (mac->pextp && mac->interface !=3D interface) + phy_reset(mac->pextp); + + return 0; +} + static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, phy_interface_t interface) { @@ -667,6 +748,10 @@ static int mtk_mac_finish(struct phylink_config *confi= g, unsigned int mode, struct mtk_eth *eth =3D mac->hw; u32 mcr_cur, mcr_new; =20 + /* Setup PMA/PMD */ + if (mac->pextp) + phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface); + /* Enable SGMII */ if (interface =3D=3D PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) @@ -692,10 +777,13 @@ static void mtk_mac_link_down(struct phylink_config *= config, unsigned int mode, { struct mtk_mac *mac =3D container_of(config, struct mtk_mac, phylink_config); - u32 mcr =3D mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); =20 - mcr &=3D ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + if (!mtk_interface_mode_is_xgmii(interface)) { + mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN, 0, MTK_MAC_MCR(mac->id)); + mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id= )); + } else if (mac->id !=3D MTK_GMAC1_ID) { + mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MC= R(mac->id)); + } } =20 static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, @@ -767,13 +855,11 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, = unsigned int idx, mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } =20 -static void mtk_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) +static void mtk_gdm_mac_link_up(struct mtk_mac *mac, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, bool tx_pause, bool rx_pause) { - struct mtk_mac *mac =3D container_of(config, struct mtk_mac, - phylink_config); u32 mcr; =20 mcr =3D mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); @@ -807,9 +893,63 @@ static void mtk_mac_link_up(struct phylink_config *con= fig, mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } =20 +static void mtk_xgdm_mac_link_up(struct mtk_mac *mac, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, bool tx_pause, bool rx_pause) +{ + u32 mcr, force_link =3D 0; + + if (mac->id =3D=3D MTK_GMAC1_ID) + return; + + /* Eliminate the interference(before link-up) caused by PHY noise */ + mtk_m32(mac->hw, XMAC_LOGIC_RST, 0, MTK_XMAC_LOGIC_RST(mac->id)); + mdelay(20); + mtk_m32(mac->hw, XMAC_GLB_CNTCLR, XMAC_GLB_CNTCLR, MTK_XMAC_CNT_CTRL(mac-= >id)); + + if (mac->interface =3D=3D PHY_INTERFACE_MODE_INTERNAL || mac->id =3D=3D M= TK_GMAC3_ID) + force_link =3D MTK_XGMAC_FORCE_LINK(mac->id); + + mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), force_link, MTK_XGMAC_STS= (mac->id)); + + mcr =3D mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id)); + mcr &=3D ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC | XMAC_MCR_TRX_DIS= ABLE); + /* Configure pause modes - + * phylink will avoid these for half duplex + */ + if (tx_pause) + mcr |=3D XMAC_MCR_FORCE_TX_FC; + if (rx_pause) + mcr |=3D XMAC_MCR_FORCE_RX_FC; + + mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id)); +} + +static void mtk_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 mtk_mac *mac =3D container_of(config, struct mtk_mac, + phylink_config); + + if (mtk_interface_mode_is_xgmii(interface)) + mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex, + tx_pause, rx_pause); + else + mtk_gdm_mac_link_up(mac, phy, mode, interface, speed, duplex, + tx_pause, rx_pause); + + /* Repeat pextp setup to tune link */ + if (mac->pextp) + phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface); +} + static const struct phylink_mac_ops mtk_phylink_ops =3D { .mac_select_pcs =3D mtk_mac_select_pcs, .mac_config =3D mtk_mac_config, + .mac_prepare =3D mtk_mac_prepare, .mac_finish =3D mtk_mac_finish, .mac_link_down =3D mtk_mac_link_down, .mac_link_up =3D mtk_mac_link_up, @@ -3359,6 +3499,9 @@ static int mtk_open(struct net_device *dev) struct mtk_eth *eth =3D mac->hw; int i, err; =20 + if (mac->pextp) + phy_power_on(mac->pextp); + err =3D phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, @@ -3488,6 +3631,9 @@ static int mtk_stop(struct net_device *dev) for (i =3D 0; i < ARRAY_SIZE(eth->ppe); i++) mtk_ppe_stop(eth->ppe[i]); =20 + if (mac->pextp) + phy_power_off(mac->pextp); + return 0; } =20 @@ -4485,6 +4631,7 @@ static const struct net_device_ops mtk_netdev_ops =3D= { static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { const __be32 *_id =3D of_get_property(np, "reg", NULL); + struct device_node *pcs_np; phy_interface_t phy_mode; struct phylink *phylink; struct mtk_mac *mac; @@ -4521,16 +4668,41 @@ static int mtk_add_mac(struct mtk_eth *eth, struct = device_node *np) mac->id =3D id; mac->hw =3D eth; mac->of_node =3D np; + pcs_np =3D of_parse_phandle(mac->of_node, "pcs-handle", 0); + if (pcs_np) { + mac->sgmii_pcs =3D mtk_pcs_lynxi_get(eth->dev, pcs_np); + if (IS_ERR(mac->sgmii_pcs)) { + if (PTR_ERR(mac->sgmii_pcs) =3D=3D -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(eth->dev, "cannot select SGMII PCS, error %ld\n", + PTR_ERR(mac->sgmii_pcs)); + return PTR_ERR(mac->sgmii_pcs); + } + } =20 - err =3D of_get_ethdev_address(mac->of_node, eth->netdev[id]); - if (err =3D=3D -EPROBE_DEFER) - return err; + pcs_np =3D of_parse_phandle(mac->of_node, "pcs-handle", 1); + if (pcs_np) { + mac->usxgmii_pcs =3D mtk_usxgmii_pcs_get(eth->dev, pcs_np); + if (IS_ERR(mac->usxgmii_pcs)) { + if (PTR_ERR(mac->usxgmii_pcs) =3D=3D -EPROBE_DEFER) + return -EPROBE_DEFER; =20 - if (err) { - /* If the mac address is invalid, use random mac address */ - eth_hw_addr_random(eth->netdev[id]); - dev_err(eth->dev, "generated random MAC address %pM\n", - eth->netdev[id]->dev_addr); + dev_err(eth->dev, "cannot select USXGMII PCS, error %ld\n", + PTR_ERR(mac->usxgmii_pcs)); + return PTR_ERR(mac->usxgmii_pcs); + } + } + + if (mtk_is_netsys_v3_or_greater(eth) && (mac->sgmii_pcs || mac->usxgmii_p= cs)) { + mac->pextp =3D devm_of_phy_get(eth->dev, mac->of_node, NULL); + if (IS_ERR(mac->pextp)) { + if (PTR_ERR(mac->pextp) !=3D -EPROBE_DEFER) + dev_err(eth->dev, "cannot get PHY, error %ld\n", + PTR_ERR(mac->pextp)); + + return PTR_ERR(mac->pextp); + } } =20 memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); @@ -4613,8 +4785,21 @@ static int mtk_add_mac(struct mtk_eth *eth, struct d= evice_node *np) phy_interface_zero(mac->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_INTERNAL, mac->phylink_config.supported_interfaces); + } else if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) { + mac->phylink_config.mac_capabilities |=3D MAC_5000FD | MAC_10000FD; + __set_bit(PHY_INTERFACE_MODE_5GBASER, + mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_10GBASER, + mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_USXGMII, + mac->phylink_config.supported_interfaces); } =20 + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) && + id =3D=3D MTK_GMAC2_ID) + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + mac->phylink_config.supported_interfaces); + phylink =3D phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); @@ -4665,6 +4850,26 @@ static int mtk_add_mac(struct mtk_eth *eth, struct d= evice_node *np) return err; } =20 +static int mtk_mac_assign_address(struct mtk_eth *eth, int i, bool test_de= fer_only) +{ + int err =3D of_get_ethdev_address(eth->mac[i]->of_node, eth->netdev[i]); + + if (err =3D=3D -EPROBE_DEFER) + return err; + + if (test_defer_only) + return 0; + + if (err) { + /* If the mac address is invalid, use random mac address */ + eth_hw_addr_random(eth->netdev[i]); + dev_err(eth->dev, "generated random MAC address %pM\n", + eth->netdev[i]); + } + + return 0; +} + void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) { struct net_device *dev, *tmp; @@ -4808,7 +5013,8 @@ static int mtk_probe(struct platform_device *pdev) regmap_write(cci, 0, 3); } =20 - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII) && + !mtk_is_netsys_v3_or_greater(eth)) { err =3D mtk_sgmii_init(eth); =20 if (err) @@ -4919,6 +5125,24 @@ static int mtk_probe(struct platform_device *pdev) } } =20 + for (i =3D 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) + continue; + + err =3D mtk_mac_assign_address(eth, i, true); + if (err) + goto err_deinit_hw; + } + + for (i =3D 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) + continue; + + err =3D mtk_mac_assign_address(eth, i, false); + if (err) + goto err_deinit_hw; + } + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { err =3D devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq, 0, @@ -5019,6 +5243,11 @@ static void mtk_remove(struct platform_device *pdev) mtk_stop(eth->netdev[i]); mac =3D netdev_priv(eth->netdev[i]); phylink_disconnect_phy(mac->phylink); + if (mac->sgmii_pcs) + mtk_pcs_lynxi_put(mac->sgmii_pcs); + + if (mac->usxgmii_pcs) + mtk_usxgmii_pcs_put(mac->usxgmii_pcs); } =20 mtk_wed_exit(); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethe= rnet/mediatek/mtk_eth_soc.h index 9ae3b8a71d0e6..8424ac6cb725b 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -503,6 +504,21 @@ #define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED) #define INTF_MODE_RGMII_10_100 0 =20 +/* XFI Mac control registers */ +#define MTK_XMAC_BASE(x) (0x12000 + (((x) - 1) * 0x1000)) +#define MTK_XMAC_MCR(x) (MTK_XMAC_BASE(x)) +#define XMAC_MCR_TRX_DISABLE 0xf +#define XMAC_MCR_FORCE_TX_FC BIT(5) +#define XMAC_MCR_FORCE_RX_FC BIT(4) + +/* XFI Mac logic reset registers */ +#define MTK_XMAC_LOGIC_RST(x) (MTK_XMAC_BASE(x) + 0x10) +#define XMAC_LOGIC_RST BIT(0) + +/* XFI Mac count global control */ +#define MTK_XMAC_CNT_CTRL(x) (MTK_XMAC_BASE(x) + 0x100) +#define XMAC_GLB_CNTCLR BIT(0) + /* GPIO port control registers for GMAC 2*/ #define GPIO_OD33_CTRL8 0x4c0 #define GPIO_BIAS_CTRL 0xed0 @@ -528,6 +544,7 @@ #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) #define SYSCFG0_SGMII_GMAC2_V2 BIT(8) +#define SYSCFG0_SGMII_GMAC3_V2 BIT(7) =20 =20 /* ethernet subsystem clock register */ @@ -566,6 +583,11 @@ #define GEPHY_MAC_SEL BIT(1) =20 /* Top misc registers */ +#define TOP_MISC_NETSYS_PCS_MUX 0x84 +#define NETSYS_PCS_MUX_MASK GENMASK(1, 0) +#define MUX_G2_USXGMII_SEL BIT(1) +#define MUX_HSGMII1_G1_SEL BIT(0) + #define USB_PHY_SWITCH_REG 0x218 #define QPHY_SEL_MASK GENMASK(1, 0) #define SGMII_QPHY_SEL 0x2 @@ -590,6 +612,8 @@ #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) =20 +/* Debug Purpose Register */ +#define MTK_PSE_FQFC_CFG 0x100 #define MTK_FE_CDM1_FSM 0x220 #define MTK_FE_CDM2_FSM 0x224 #define MTK_FE_CDM3_FSM 0x238 @@ -598,6 +622,11 @@ #define MTK_FE_CDM6_FSM 0x328 #define MTK_FE_GDM1_FSM 0x228 #define MTK_FE_GDM2_FSM 0x22C +#define MTK_FE_GDM3_FSM 0x23C +#define MTK_FE_PSE_FREE 0x240 +#define MTK_FE_DROP_FQ 0x244 +#define MTK_FE_DROP_FC 0x248 +#define MTK_FE_DROP_PPE 0x24C =20 #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) =20 @@ -722,12 +751,8 @@ enum mtk_clks_map { MTK_CLK_ETHWARP_WOCPU2, MTK_CLK_ETHWARP_WOCPU1, MTK_CLK_ETHWARP_WOCPU0, - MTK_CLK_TOP_USXGMII_SBUS_0_SEL, - MTK_CLK_TOP_USXGMII_SBUS_1_SEL, MTK_CLK_TOP_SGM_0_SEL, MTK_CLK_TOP_SGM_1_SEL, - MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL, - MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL, MTK_CLK_TOP_ETH_GMII_SEL, MTK_CLK_TOP_ETH_REFCK_50M_SEL, MTK_CLK_TOP_ETH_SYS_200M_SEL, @@ -798,19 +823,9 @@ enum mtk_clks_map { BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \ BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \ BIT_ULL(MTK_CLK_CRYPTO) | \ - BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ - BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ - BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ - BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \ BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \ BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \ - BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \ - BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \ - BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \ - BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \ - BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \ - BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \ BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \ BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \ BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \ @@ -944,6 +959,8 @@ enum mkt_eth_capabilities { MTK_RGMII_BIT =3D 0, MTK_TRGMII_BIT, MTK_SGMII_BIT, + MTK_USXGMII_BIT, + MTK_2P5GPHY_BIT, MTK_ESW_BIT, MTK_GEPHY_BIT, MTK_MUX_BIT, @@ -964,8 +981,11 @@ enum mkt_eth_capabilities { MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT, MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT, + MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT, MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT, MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT, + MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT, + MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT, =20 /* PATH BITS */ MTK_ETH_PATH_GMAC1_RGMII_BIT, @@ -973,14 +993,21 @@ enum mkt_eth_capabilities { MTK_ETH_PATH_GMAC1_SGMII_BIT, MTK_ETH_PATH_GMAC2_RGMII_BIT, MTK_ETH_PATH_GMAC2_SGMII_BIT, + MTK_ETH_PATH_GMAC2_2P5GPHY_BIT, MTK_ETH_PATH_GMAC2_GEPHY_BIT, + MTK_ETH_PATH_GMAC3_SGMII_BIT, MTK_ETH_PATH_GDM1_ESW_BIT, + MTK_ETH_PATH_GMAC1_USXGMII_BIT, + MTK_ETH_PATH_GMAC2_USXGMII_BIT, + MTK_ETH_PATH_GMAC3_USXGMII_BIT, }; =20 /* Supported hardware group on SoCs */ #define MTK_RGMII BIT_ULL(MTK_RGMII_BIT) #define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) #define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) +#define MTK_USXGMII BIT_ULL(MTK_USXGMII_BIT) +#define MTK_2P5GPHY BIT_ULL(MTK_2P5GPHY_BIT) #define MTK_ESW BIT_ULL(MTK_ESW_BIT) #define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) #define MTK_MUX BIT_ULL(MTK_MUX_BIT) @@ -1003,10 +1030,16 @@ enum mkt_eth_capabilities { BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \ BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) +#define MTK_ETH_MUX_GMAC2_TO_2P5GPHY \ + BIT_ULL(MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT) #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \ BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) +#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII \ + BIT_ULL(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT) +#define MTK_ETH_MUX_GMAC123_TO_USXGMII \ + BIT_ULL(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT) =20 /* Supported path present on SoCs */ #define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) @@ -1014,8 +1047,13 @@ enum mkt_eth_capabilities { #define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT) #define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) #define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) +#define MTK_ETH_PATH_GMAC2_2P5GPHY BIT_ULL(MTK_ETH_PATH_GMAC2_2P5GPHY_BIT) #define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) +#define MTK_ETH_PATH_GMAC3_SGMII BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT) #define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) +#define MTK_ETH_PATH_GMAC1_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC1_USXGMII_BIT) +#define MTK_ETH_PATH_GMAC2_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC2_USXGMII_BIT) +#define MTK_ETH_PATH_GMAC3_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC3_USXGMII_BIT) =20 #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) @@ -1023,7 +1061,12 @@ enum mkt_eth_capabilities { #define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII) #define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII) #define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY) +#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY) +#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII) #define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW) +#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII) +#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII) +#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII) =20 /* MUXes present on SoCs */ /* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */ @@ -1042,10 +1085,20 @@ enum mkt_eth_capabilities { (MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \ MTK_SHARED_SGMII) =20 +/* 2: GMAC2 -> XGMII */ +#define MTK_MUX_GMAC2_TO_2P5GPHY \ + (MTK_ETH_MUX_GMAC2_TO_2P5GPHY | MTK_MUX | MTK_INFRA) + /* 0: GMACx -> GEPHY, 1: GMACx -> SGMII where x is 1 or 2 */ #define MTK_MUX_GMAC12_TO_GEPHY_SGMII \ (MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX) =20 +#define MTK_MUX_GMAC123_TO_GEPHY_SGMII \ + (MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX) + +#define MTK_MUX_GMAC123_TO_USXGMII \ + (MTK_ETH_MUX_GMAC123_TO_USXGMII | MTK_MUX | MTK_INFRA) + #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) =3D=3D (_x)) =20 #define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ @@ -1077,8 +1130,12 @@ enum mkt_eth_capabilities { MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_RSTCTRL_PPE1 | MTK_SRAM) =20 -#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \ - MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) +#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ + MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ + MTK_GMAC3_SGMII | MTK_GMAC3_USXGMII | \ + MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ + MTK_MUX_GMAC123_TO_USXGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \ + MTK_QDMA | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) =20 struct mtk_tx_dma_desc_info { dma_addr_t addr; @@ -1315,6 +1372,9 @@ struct mtk_mac { struct device_node *of_node; struct phylink *phylink; struct phylink_config phylink_config; + struct phylink_pcs *sgmii_pcs; + struct phylink_pcs *usxgmii_pcs; + struct phy *pextp; struct mtk_eth *hw; struct mtk_hw_stats *hw_stats; __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; @@ -1421,6 +1481,19 @@ static inline u32 mtk_get_ib2_multicast_mask(struct = mtk_eth *eth) return MTK_FOE_IB2_MULTICAST; } =20 +static inline bool mtk_interface_mode_is_xgmii(phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_INTERNAL: + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_5GBASER: + return true; + default: + return false; + } +} + /* read the hardware status register */ void mtk_stats_update_mac(struct mtk_mac *mac); =20 @@ -1429,8 +1502,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigned reg); u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); =20 int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); +int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id); int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id); +int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id); =20 int mtk_eth_offload_init(struct mtk_eth *eth); int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, --=20 2.43.0