Skip to content

Commit 51cf06d

Browse files
dangowrtkuba-moo
authored andcommitted
net: ethernet: mtk_eth_soc: add support for MT7988 internal 2.5G PHY
The MediaTek MT7988 SoC comes with an single built-in Ethernet PHY for 2500Base-T/1000Base-T/100Base-TX/10Base-T link partners in addition to the built-in 1GE switch. The built-in PHY only supports full duplex. Add muxes allowing to select GMAC2->2.5G PHY path and add basic support for XGMAC as the built-in 2.5G PHY is internally connected via XGMII. The XGMAC features will also be used by 5GBase-R, 10GBase-R and USXGMII SerDes modes which are going to be added once support for standalone PCS drivers is in place. In order to make use of the built-in 2.5G PHY the appropriate PHY driver as well as (proprietary) PHY firmware has to be present as well. Signed-off-by: Daniel Golle <[email protected]> Link: https://patch.msgid.link/9072cefbff6db969720672ec98ed5cef65e8218c.1745715380.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 7a4f15c commit 51cf06d

File tree

3 files changed

+203
-16
lines changed

3 files changed

+203
-16
lines changed

drivers/net/ethernet/mediatek/mtk_eth_path.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static const char *mtk_eth_path_name(u64 path)
3131
return "gmac2_rgmii";
3232
case MTK_ETH_PATH_GMAC2_SGMII:
3333
return "gmac2_sgmii";
34+
case MTK_ETH_PATH_GMAC2_2P5GPHY:
35+
return "gmac2_2p5gphy";
3436
case MTK_ETH_PATH_GMAC2_GEPHY:
3537
return "gmac2_gephy";
3638
case MTK_ETH_PATH_GDM1_ESW:
@@ -127,6 +129,29 @@ static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
127129
return 0;
128130
}
129131

132+
static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
133+
{
134+
int ret;
135+
136+
if (path == MTK_ETH_PATH_GMAC2_2P5GPHY) {
137+
ret = regmap_clear_bits(eth->ethsys, ETHSYS_SYSCFG0,
138+
SYSCFG0_SGMII_GMAC2_V2);
139+
if (ret)
140+
return ret;
141+
142+
/* Setup mux to 2p5g PHY */
143+
ret = regmap_clear_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX,
144+
MUX_G2_USXGMII_SEL);
145+
if (ret)
146+
return ret;
147+
148+
dev_dbg(eth->dev, "path %s in %s updated\n",
149+
mtk_eth_path_name(path), __func__);
150+
}
151+
152+
return 0;
153+
}
154+
130155
static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
131156
{
132157
unsigned int val = 0;
@@ -209,6 +234,10 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] = {
209234
.name = "mux_u3_gmac2_to_qphy",
210235
.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
211236
.set_path = set_mux_u3_gmac2_to_qphy,
237+
}, {
238+
.name = "mux_gmac2_to_2p5gphy",
239+
.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
240+
.set_path = set_mux_gmac2_to_2p5gphy,
212241
}, {
213242
.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
214243
.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
@@ -260,6 +289,20 @@ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
260289
return mtk_eth_mux_setup(eth, path);
261290
}
262291

292+
int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
293+
{
294+
u64 path = 0;
295+
296+
if (mac_id == MTK_GMAC2_ID)
297+
path = MTK_ETH_PATH_GMAC2_2P5GPHY;
298+
299+
if (!path)
300+
return -EINVAL;
301+
302+
/* Setup proper MUXes along the path */
303+
return mtk_eth_mux_setup(eth, path);
304+
}
305+
263306
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
264307
{
265308
u64 path = 0;

drivers/net/ethernet/mediatek/mtk_eth_soc.c

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth,
503503
static void mtk_setup_bridge_switch(struct mtk_eth *eth)
504504
{
505505
/* Force Port1 XGMAC Link Up */
506-
mtk_m32(eth, 0, MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID),
506+
mtk_m32(eth, 0, MTK_XGMAC_FORCE_MODE(MTK_GMAC1_ID),
507507
MTK_XGMAC_STS(MTK_GMAC1_ID));
508508

509509
/* Adjust GSW bridge IPG to 11 */
@@ -532,6 +532,26 @@ static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
532532
return NULL;
533533
}
534534

535+
static int mtk_mac_prepare(struct phylink_config *config, unsigned int mode,
536+
phy_interface_t iface)
537+
{
538+
struct mtk_mac *mac = container_of(config, struct mtk_mac,
539+
phylink_config);
540+
struct mtk_eth *eth = mac->hw;
541+
542+
if (mtk_interface_mode_is_xgmii(eth, iface) &&
543+
mac->id != MTK_GMAC1_ID) {
544+
mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE,
545+
XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id));
546+
547+
mtk_m32(mac->hw, MTK_XGMAC_FORCE_MODE(mac->id) |
548+
MTK_XGMAC_FORCE_LINK(mac->id),
549+
MTK_XGMAC_FORCE_MODE(mac->id), MTK_XGMAC_STS(mac->id));
550+
}
551+
552+
return 0;
553+
}
554+
535555
static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
536556
const struct phylink_link_state *state)
537557
{
@@ -573,6 +593,12 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
573593
}
574594
break;
575595
case PHY_INTERFACE_MODE_INTERNAL:
596+
if (mac->id == MTK_GMAC2_ID &&
597+
MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) {
598+
err = mtk_gmac_2p5gphy_path_setup(eth, mac->id);
599+
if (err)
600+
goto init_err;
601+
}
576602
break;
577603
default:
578604
goto err_phy;
@@ -644,12 +670,12 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
644670
}
645671

646672
/* Setup gmac */
647-
if (mtk_is_netsys_v3_or_greater(eth) &&
648-
mac->interface == PHY_INTERFACE_MODE_INTERNAL) {
673+
if (mtk_interface_mode_is_xgmii(eth, state->interface)) {
649674
mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id));
650675
mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id));
651676

652-
mtk_setup_bridge_switch(eth);
677+
if (mac->id == MTK_GMAC1_ID)
678+
mtk_setup_bridge_switch(eth);
653679
}
654680

655681
return;
@@ -696,10 +722,19 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
696722
{
697723
struct mtk_mac *mac = container_of(config, struct mtk_mac,
698724
phylink_config);
699-
u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
700725

701-
mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK);
702-
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
726+
if (!mtk_interface_mode_is_xgmii(mac->hw, interface)) {
727+
/* GMAC modes */
728+
mtk_m32(mac->hw,
729+
MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0,
730+
MTK_MAC_MCR(mac->id));
731+
} else if (mac->id != MTK_GMAC1_ID) {
732+
/* XGMAC except for built-in switch */
733+
mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE,
734+
MTK_XMAC_MCR(mac->id));
735+
mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0,
736+
MTK_XGMAC_STS(mac->id));
737+
}
703738
}
704739

705740
static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
@@ -771,13 +806,12 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
771806
mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
772807
}
773808

774-
static void mtk_mac_link_up(struct phylink_config *config,
775-
struct phy_device *phy,
776-
unsigned int mode, phy_interface_t interface,
777-
int speed, int duplex, bool tx_pause, bool rx_pause)
809+
static void mtk_gdm_mac_link_up(struct mtk_mac *mac,
810+
struct phy_device *phy,
811+
unsigned int mode, phy_interface_t interface,
812+
int speed, int duplex, bool tx_pause,
813+
bool rx_pause)
778814
{
779-
struct mtk_mac *mac = container_of(config, struct mtk_mac,
780-
phylink_config);
781815
u32 mcr;
782816

783817
mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
@@ -811,6 +845,56 @@ static void mtk_mac_link_up(struct phylink_config *config,
811845
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
812846
}
813847

848+
static void mtk_xgdm_mac_link_up(struct mtk_mac *mac,
849+
struct phy_device *phy,
850+
unsigned int mode, phy_interface_t interface,
851+
int speed, int duplex, bool tx_pause,
852+
bool rx_pause)
853+
{
854+
u32 mcr;
855+
856+
if (mac->id == MTK_GMAC1_ID)
857+
return;
858+
859+
/* Eliminate the interference(before link-up) caused by PHY noise */
860+
mtk_m32(mac->hw, XMAC_LOGIC_RST, 0, MTK_XMAC_LOGIC_RST(mac->id));
861+
mdelay(20);
862+
mtk_m32(mac->hw, XMAC_GLB_CNTCLR, XMAC_GLB_CNTCLR,
863+
MTK_XMAC_CNT_CTRL(mac->id));
864+
865+
mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id),
866+
MTK_XGMAC_FORCE_LINK(mac->id), MTK_XGMAC_STS(mac->id));
867+
868+
mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
869+
mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC |
870+
XMAC_MCR_TRX_DISABLE);
871+
/* Configure pause modes -
872+
* phylink will avoid these for half duplex
873+
*/
874+
if (tx_pause)
875+
mcr |= XMAC_MCR_FORCE_TX_FC;
876+
if (rx_pause)
877+
mcr |= XMAC_MCR_FORCE_RX_FC;
878+
879+
mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
880+
}
881+
882+
static void mtk_mac_link_up(struct phylink_config *config,
883+
struct phy_device *phy,
884+
unsigned int mode, phy_interface_t interface,
885+
int speed, int duplex, bool tx_pause, bool rx_pause)
886+
{
887+
struct mtk_mac *mac = container_of(config, struct mtk_mac,
888+
phylink_config);
889+
890+
if (mtk_interface_mode_is_xgmii(mac->hw, interface))
891+
mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex,
892+
tx_pause, rx_pause);
893+
else
894+
mtk_gdm_mac_link_up(mac, phy, mode, interface, speed, duplex,
895+
tx_pause, rx_pause);
896+
}
897+
814898
static void mtk_mac_disable_tx_lpi(struct phylink_config *config)
815899
{
816900
struct mtk_mac *mac = container_of(config, struct mtk_mac,
@@ -828,6 +912,9 @@ static int mtk_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
828912
struct mtk_eth *eth = mac->hw;
829913
u32 val;
830914

915+
if (mtk_interface_mode_is_xgmii(eth, mac->interface))
916+
return -EOPNOTSUPP;
917+
831918
/* Tx idle timer in ms */
832919
timer = DIV_ROUND_UP(timer, 1000);
833920

@@ -858,6 +945,7 @@ static int mtk_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
858945
}
859946

860947
static const struct phylink_mac_ops mtk_phylink_ops = {
948+
.mac_prepare = mtk_mac_prepare,
861949
.mac_select_pcs = mtk_mac_select_pcs,
862950
.mac_config = mtk_mac_config,
863951
.mac_finish = mtk_mac_finish,
@@ -4763,6 +4851,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
47634851

47644852
mac->phylink = phylink;
47654853

4854+
if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) &&
4855+
id == MTK_GMAC2_ID)
4856+
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
4857+
mac->phylink_config.supported_interfaces);
4858+
47664859
SET_NETDEV_DEV(eth->netdev[id], eth->dev);
47674860
eth->netdev[id]->watchdog_timeo = 5 * HZ;
47684861
eth->netdev[id]->netdev_ops = &mtk_netdev_ops;

0 commit comments

Comments
 (0)