Skip to content

Commit

Permalink
net: ethernet: mtk_eth_soc: add paths and SerDes modes for MT7988
Browse files Browse the repository at this point in the history
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-KR,
2500Base-X, 1000Base-X and Cisco SGMII interface modes.

Implement support for configuring for the new paths to SerDes interfaces
and 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 <daniel@makrotopia.org>
  • Loading branch information
dangowrt committed Aug 17, 2023
1 parent 3a1ef9f commit c81d14e
Show file tree
Hide file tree
Showing 6 changed files with 1,315 additions and 40 deletions.
16 changes: 16 additions & 0 deletions drivers/net/ethernet/mediatek/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ config NET_MEDIATEK_SOC
This driver supports the gigabit ethernet MACs in the
MediaTek SoC family.

config NET_MEDIATEK_SOC_USXGMII
bool "Support USXGMII SerDes on MT7988"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
def_bool NET_MEDIATEK_SOC != n
help
Include support for 10G SerDes which can be found on MT7988.
If this kernel should run on SoCs with 10 GBit/s Ethernet you
will need to select this option to use GMAC2 and GMAC3 with
external PHYs, SFP(+) cages in 10000Base-R, 5000Base-R or
USXGMII interface mode.

Note that as the 2500Base-X/1000Base-X/Cisco SGMII SerDes PCS
unit (MediaTek LynxI) in MT7988 is connected via the new 10GE
SerDes, you will also need to select this option in case you
want to use any of those SerDes modes.

config NET_MEDIATEK_STAR_EMAC
tristate "MediaTek STAR Ethernet MAC support"
select PHYLIB
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mediatek/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_USXGMII) += mtk_usxgmii.o
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o
ifdef CONFIG_DEBUG_FS
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
Expand Down
134 changes: 129 additions & 5 deletions drivers/net/ethernet/mediatek/mtk_eth_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down Expand Up @@ -127,6 +137,31 @@ static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
return 0;
}

static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
int mac_id = 0;

regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);

switch (path) {
case MTK_ETH_PATH_GMAC2_2P5GPHY:
val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
mac_id = MTK_GMAC2_ID;
break;
default:
updated = false;
break;
};

if (updated)
regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
SYSCFG0_SGMII_MASK, val);

return 0;
}

static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
Expand Down Expand Up @@ -165,7 +200,55 @@ static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
return 0;
}

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 = 0;
bool updated = true;
int mac_id = 0;

/* Disable SYSCFG1 SGMII */
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);

switch (path) {
case MTK_ETH_PATH_GMAC1_USXGMII:
val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2;
mac_id = MTK_GMAC1_ID;
break;
case MTK_ETH_PATH_GMAC2_USXGMII:
val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
mac_id = MTK_GMAC2_ID;
break;
case MTK_ETH_PATH_GMAC3_USXGMII:
val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2;
mac_id = MTK_GMAC3_ID;
break;
default:
updated = false;
};

if (updated) {
regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
SYSCFG0_SGMII_MASK, val);

/* Enable XGDM Path */
mtk_m32(eth, MTK_GDMA_XGDM_SEL, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac_id));

if (mtk_is_netsys_v3_or_greater(eth) &&
mac_id == MTK_GMAC2_ID) {
regmap_update_bits(eth->infra,
TOP_MISC_NETSYS_PCS_MUX,
NETSYS_PCS_MUX_MASK,
MUX_G2_USXGMII_SEL);
}
}

dev_dbg(eth->dev, "path %s in %s updated = %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 = 0;
bool updated = true;
Expand All @@ -182,6 +265,9 @@ static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
case MTK_ETH_PATH_GMAC2_SGMII:
val |= SYSCFG0_SGMII_GMAC2_V2;
break;
case MTK_ETH_PATH_GMAC3_SGMII:
val |= SYSCFG0_SGMII_GMAC3_V2;
break;
default:
updated = false;
}
Expand Down Expand Up @@ -209,14 +295,26 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] = {
.name = "mux_u3_gmac2_to_qphy",
.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
.set_path = set_mux_u3_gmac2_to_qphy,
}, {
.name = "mux_gmac2_to_2p5gphy",
.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
.set_path = set_mux_gmac2_to_2p5gphy,
}, {
.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
.set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
}, {
.name = "mux_gmac12_to_gephy_sgmii",
.cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
.set_path = set_mux_gmac12_to_gephy_sgmii,
.set_path = set_mux_gmac123_to_gephy_sgmii,
}, {
.name = "mux_gmac123_to_gephy_sgmii",
.cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII,
.set_path = set_mux_gmac123_to_gephy_sgmii,
}, {
.name = "mux_gmac123_to_usxgmii",
.cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII,
.set_path = set_mux_gmac123_to_usxgmii,
},
};

Expand Down Expand Up @@ -249,12 +347,39 @@ static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
return err;
}

int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
u64 path;

path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII :
(mac_id == 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;

path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
MTK_ETH_PATH_GMAC2_SGMII;
path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII :
(mac_id == 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 = 0;

if (mac_id == MTK_GMAC2_ID)
path = MTK_ETH_PATH_GMAC2_2P5GPHY;

if (!path)
return -EINVAL;

/* Setup proper MUXes along the path */
return mtk_eth_mux_setup(eth, path);
Expand Down Expand Up @@ -284,4 +409,3 @@ int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
/* Setup proper MUXes along the path */
return mtk_eth_mux_setup(eth, path);
}

0 comments on commit c81d14e

Please sign in to comment.