[][kernel][common][eth][Add NETSYSv3 new feature support]
[Description]
Add NETSYSv3 new feature support.
If without this patch, driver can't work on the NETSYSv3 hardware.
Patchset9: Add RSS supporting, and rename mtk_mac_link_state()
to mtk_mac_pcs_get_state().
Patchset12: Add Signed-off.
Patchset15: Improve NETSYS stability.
[Release-log]
N/A
Change-Id: I095e0d39819448c9d2c18d2bb6e6d8065fc23d33
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6574066
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a05cd19..46deff5 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -260,13 +260,35 @@
mtk_w32(eth, val, TRGMII_TCK_CTRL);
}
+static void mtk_setup_bridge_switch(struct mtk_eth *eth)
+{
+ int val;
+
+ /* Force Port1 XGMAC Link Up */
+ val = mtk_r32(eth, MTK_XGMAC_STS(MTK_GMAC1_ID));
+ mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK,
+ MTK_XGMAC_STS(MTK_GMAC1_ID));
+
+ /* Adjust GSW bridge IPG to 11*/
+ val = mtk_r32(eth, MTK_GSW_CFG);
+ val &= ~(GSWTX_IPG_MASK | GSWRX_IPG_MASK);
+ val |= (GSW_IPG_11 << GSWTX_IPG_SHIFT) |
+ (GSW_IPG_11 << GSWRX_IPG_SHIFT);
+ mtk_w32(eth, val, MTK_GSW_CFG);
+
+ /* Disable GDM1 RX CRC stripping */
+ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(0));
+ val &= ~MTK_GDMA_STRP_CRC;
+ mtk_w32(eth, val, MTK_GDMA_FWD_CFG(0));
+}
+
static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
struct mtk_eth *eth = mac->hw;
- u32 mcr_cur, mcr_new, sid, i;
+ u32 sid, i;
int val, ge_mode, err=0;
/* MT76x8 has no hardware settings between for the MAC */
@@ -310,6 +332,14 @@
goto init_err;
}
break;
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GKR:
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
+ err = mtk_gmac_usxgmii_path_setup(eth, mac->id);
+ if (err)
+ goto init_err;
+ }
+ break;
default:
goto err_phy;
}
@@ -389,10 +419,10 @@
/* Setup SGMIISYS with the determined property */
if (state->interface != PHY_INTERFACE_MODE_SGMII)
- err = mtk_sgmii_setup_mode_force(eth->sgmii, sid,
+ err = mtk_sgmii_setup_mode_force(eth->xgmii, sid,
state);
else
- err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
+ err = mtk_sgmii_setup_mode_an(eth->xgmii, sid);
if (err) {
spin_unlock(ð->syscfg0_lock);
@@ -402,6 +432,22 @@
regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
SYSCFG0_SGMII_MASK, val);
spin_unlock(ð->syscfg0_lock);
+ } else if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
+ state->interface == PHY_INTERFACE_MODE_10GKR) {
+ sid = mac->id;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
+ sid != MTK_GMAC1_ID) {
+ if (phylink_autoneg_inband(mode))
+ err = mtk_usxgmii_setup_mode_force(eth->xgmii, sid,
+ SPEED_10000);
+ else
+ err = mtk_usxgmii_setup_mode_an(eth->xgmii, sid,
+ SPEED_10000);
+
+ if (err)
+ goto init_err;
+ }
} else if (phylink_autoneg_inband(mode)) {
dev_err(eth->dev,
"In-band mode not supported in non SGMII mode!\n");
@@ -409,35 +455,25 @@
}
/* Setup gmac */
- mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
- mcr_new = mcr_cur;
- mcr_new &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
- MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
- MAC_MCR_FORCE_RX_FC);
- mcr_new |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+ if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
+ state->interface == PHY_INTERFACE_MODE_10GKR) {
+ 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));
- switch (state->speed) {
- case SPEED_2500:
- case SPEED_1000:
- mcr_new |= MAC_MCR_SPEED_1000;
- break;
- case SPEED_100:
- mcr_new |= MAC_MCR_SPEED_100;
- break;
- }
- if (state->duplex == DUPLEX_FULL) {
- mcr_new |= MAC_MCR_FORCE_DPX;
- if (state->pause & MLO_PAUSE_TX)
- mcr_new |= MAC_MCR_FORCE_TX_FC;
- if (state->pause & MLO_PAUSE_RX)
- mcr_new |= MAC_MCR_FORCE_RX_FC;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ switch (mac->id) {
+ case MTK_GMAC1_ID:
+ mtk_setup_bridge_switch(eth);
+ break;
+ case MTK_GMAC3_ID:
+ val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
+ mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK,
+ MTK_XGMAC_STS(mac->id));
+ break;
+ }
+ }
}
- /* Only update control register when needed! */
- if (mcr_new != mcr_cur)
- mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
-
return;
err_phy:
@@ -450,36 +486,90 @@
mac->id, phy_modes(state->interface), err);
}
-static int mtk_mac_link_state(struct phylink_config *config,
- struct phylink_link_state *state)
+static int mtk_mac_pcs_get_state(struct phylink_config *config,
+ struct phylink_link_state *state)
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
- u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id));
- state->link = (pmsr & MAC_MSR_LINK);
- state->duplex = (pmsr & MAC_MSR_DPX) >> 1;
+ if (mac->type == MTK_XGDM_TYPE) {
+ u32 sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- switch (pmsr & (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)) {
- case 0:
- state->speed = SPEED_10;
- break;
- case MAC_MSR_SPEED_100:
- state->speed = SPEED_100;
- break;
- case MAC_MSR_SPEED_1000:
- state->speed = SPEED_1000;
- break;
- default:
- state->speed = SPEED_UNKNOWN;
- break;
- }
+ if (mac->id == MTK_GMAC2_ID)
+ sts = sts >> 16;
- state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX);
- if (pmsr & MAC_MSR_RX_FC)
- state->pause |= MLO_PAUSE_RX;
- if (pmsr & MAC_MSR_TX_FC)
- state->pause |= MLO_PAUSE_TX;
+ state->duplex = 1;
+
+ switch (FIELD_GET(MTK_USXGMII_PCS_MODE, sts)) {
+ case 0:
+ state->speed = SPEED_10000;
+ break;
+ case 1:
+ state->speed = SPEED_5000;
+ break;
+ case 2:
+ state->speed = SPEED_2500;
+ break;
+ case 3:
+ state->speed = SPEED_1000;
+ break;
+ }
+
+ state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, sts);
+ } else if (mac->type == MTK_GDM_TYPE) {
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_xgmii *ss = eth->xgmii;
+ u32 id = mtk_mac2xgmii_id(eth, mac->id);
+ u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id));
+ u32 val;
+
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, &val);
+
+ state->link = FIELD_GET(SGMII_LINK_STATYS, val);
+
+ if (FIELD_GET(SGMII_AN_ENABLE, val)) {
+ regmap_read(ss->regmap_sgmii[id], SGMII_PCS_SPEED_ABILITY, &val);
+
+ val = val >> 16;
+
+ state->duplex = FIELD_GET(SGMII_PCS_SPEED_DUPLEX, val);
+
+ switch (FIELD_GET(SGMII_PCS_SPEED_MASK, val)) {
+ case 0:
+ state->speed = SPEED_10;
+ break;
+ case 1:
+ state->speed = SPEED_100;
+ break;
+ case 2:
+ state->speed = SPEED_1000;
+ break;
+ }
+ } else {
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
+
+ state->duplex = !FIELD_GET(SGMII_DUPLEX_FULL, val);
+
+ switch (FIELD_GET(SGMII_SPEED_MASK, val)) {
+ case 0:
+ state->speed = SPEED_10;
+ break;
+ case 1:
+ state->speed = SPEED_100;
+ break;
+ case 2:
+ regmap_read(ss->regmap_sgmii[id], ss->ana_rgc3, &val);
+ state->speed = (FIELD_GET(RG_PHY_SPEED_3_125G, val)) ? SPEED_2500 : SPEED_1000;
+ break;
+ }
+ }
+
+ state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX);
+ if (pmsr & MAC_MSR_RX_FC)
+ state->pause |= MLO_PAUSE_RX;
+ if (pmsr & MAC_MSR_TX_FC)
+ state->pause |= MLO_PAUSE_TX;
+ }
return 1;
}
@@ -489,7 +579,8 @@
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
- mtk_sgmii_restart_an(mac->hw, mac->id);
+ if (mac->type != MTK_XGDM_TYPE)
+ mtk_sgmii_restart_an(mac->hw, mac->id);
}
static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
@@ -497,10 +588,19 @@
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
- u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ u32 mcr;
+
+ if (mac->type == MTK_GDM_TYPE) {
+ mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN);
+ mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ } else if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
+ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN);
- mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ mcr &= 0xfffffff0;
+ mcr |= XMAC_MCR_TRX_DISABLE;
+ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
+ }
}
static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode,
@@ -509,10 +609,60 @@
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
- u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ u32 mcr, mcr_cur;
+
+ if (mac->type == MTK_GDM_TYPE) {
+ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ mcr = mcr_cur;
+ mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
+ MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
+ MAC_MCR_FORCE_RX_FC);
+ mcr |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
+ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+
+ /* Configure speed */
+ switch (speed) {
+ case SPEED_2500:
+ case SPEED_1000:
+ mcr |= MAC_MCR_SPEED_1000;
+ break;
+ case SPEED_100:
+ mcr |= MAC_MCR_SPEED_100;
+ break;
+ }
+
+ /* Configure duplex */
+ if (duplex == DUPLEX_FULL)
+ mcr |= MAC_MCR_FORCE_DPX;
+
+ /* Configure pause modes -
+ * phylink will avoid these for half duplex
+ */
+ if (tx_pause)
+ mcr |= MAC_MCR_FORCE_TX_FC;
+ if (rx_pause)
+ mcr |= MAC_MCR_FORCE_RX_FC;
+
+ mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN;
+
+ /* Only update control register when needed! */
+ if (mcr != mcr_cur)
+ mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ } else if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
+ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
+
+ mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC);
+ /* Configure pause modes -
+ * phylink will avoid these for half duplex
+ */
+ if (tx_pause)
+ mcr |= XMAC_MCR_FORCE_TX_FC;
+ if (rx_pause)
+ mcr |= XMAC_MCR_FORCE_RX_FC;
- mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN;
- mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ mcr &= ~(XMAC_MCR_TRX_DISABLE);
+ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
+ }
}
static void mtk_validate(struct phylink_config *config,
@@ -532,7 +682,11 @@
!mac->id && state->interface == PHY_INTERFACE_MODE_TRGMII) &&
!(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII) &&
(state->interface == PHY_INTERFACE_MODE_SGMII ||
- phy_interface_mode_is_8023z(state->interface)))) {
+ phy_interface_mode_is_8023z(state->interface))) &&
+ !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII) &&
+ (state->interface == PHY_INTERFACE_MODE_USXGMII)) &&
+ !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII) &&
+ (state->interface == PHY_INTERFACE_MODE_10GKR))) {
linkmode_zero(supported);
return;
}
@@ -541,12 +695,28 @@
phylink_set(mask, Autoneg);
switch (state->interface) {
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GKR:
+ phylink_set(mask, 10000baseKR_Full);
+ phylink_set(mask, 10000baseT_Full);
+ phylink_set(mask, 10000baseCR_Full);
+ phylink_set(mask, 10000baseSR_Full);
+ phylink_set(mask, 10000baseLR_Full);
+ phylink_set(mask, 10000baseLRM_Full);
+ phylink_set(mask, 10000baseER_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ phylink_set(mask, 1000baseT_Half);
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+ break;
case PHY_INTERFACE_MODE_TRGMII:
phylink_set(mask, 1000baseT_Full);
break;
case PHY_INTERFACE_MODE_1000BASEX:
- case PHY_INTERFACE_MODE_2500BASEX:
phylink_set(mask, 1000baseX_Full);
+ /* fall through; */
+ case PHY_INTERFACE_MODE_2500BASEX:
phylink_set(mask, 2500baseX_Full);
phylink_set(mask, 2500baseT_Full);
/* fall through; */
@@ -574,6 +744,18 @@
}
if (state->interface == PHY_INTERFACE_MODE_NA) {
+
+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) {
+ phylink_set(mask, 10000baseKR_Full);
+ phylink_set(mask, 10000baseSR_Full);
+ phylink_set(mask, 10000baseLR_Full);
+ phylink_set(mask, 10000baseLRM_Full);
+ phylink_set(mask, 10000baseER_Full);
+ phylink_set(mask, 1000baseKX_Full);
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+ phylink_set(mask, 2500baseX_Full);
+ }
if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) {
phylink_set(mask, 1000baseT_Full);
phylink_set(mask, 1000baseX_Full);
@@ -604,7 +786,7 @@
static const struct phylink_mac_ops mtk_phylink_ops = {
.validate = mtk_validate,
- .mac_link_state = mtk_mac_link_state,
+ .mac_link_state = mtk_mac_pcs_get_state,
.mac_an_restart = mtk_mac_an_restart,
.mac_config = mtk_mac_config,
.mac_link_down = mtk_mac_link_down,
@@ -737,6 +919,7 @@
void mtk_stats_update_mac(struct mtk_mac *mac)
{
+ struct mtk_eth *eth = mac->hw;
struct mtk_hw_stats *hw_stats = mac->hw_stats;
unsigned int base = MTK_GDM1_TX_GBCNT;
u64 stats;
@@ -757,14 +940,26 @@
hw_stats->rx_checksum_errors += mtk_r32(mac->hw, base + 0x20);
hw_stats->rx_flow_control_packets +=
mtk_r32(mac->hw, base + 0x24);
- hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x28);
- hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x2c);
- hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x30);
- stats = mtk_r32(mac->hw, base + 0x34);
- if (stats)
- hw_stats->tx_bytes += (stats << 32);
- hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
- u64_stats_update_end(&hw_stats->syncp);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x50);
+ hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x54);
+ hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x40);
+ stats = mtk_r32(mac->hw, base + 0x44);
+ if (stats)
+ hw_stats->tx_bytes += (stats << 32);
+ hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x48);
+ u64_stats_update_end(&hw_stats->syncp);
+ } else {
+ hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x28);
+ hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x2c);
+ hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x30);
+ stats = mtk_r32(mac->hw, base + 0x34);
+ if (stats)
+ hw_stats->tx_bytes += (stats << 32);
+ hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
+ u64_stats_update_end(&hw_stats->syncp);
+ }
}
static void mtk_stats_update(struct mtk_eth *eth)
@@ -846,7 +1041,8 @@
rxd->rxd3 = READ_ONCE(dma_rxd->rxd3);
rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
}
@@ -869,7 +1065,10 @@
ð->phy_scratch_ring,
GFP_KERNEL);
} else {
- eth->scratch_ring = eth->base + MTK_ETH_SRAM_OFFSET;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ eth->scratch_ring = eth->sram_base;
+ else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ eth->scratch_ring = eth->base + MTK_ETH_SRAM_OFFSET;
}
if (unlikely(!eth->scratch_ring))
@@ -899,7 +1098,8 @@
txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
txd->txd4 = 0;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
txd->txd5 = 0;
txd->txd6 = 0;
txd->txd7 = 0;
@@ -1050,19 +1250,24 @@
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
struct mtk_tx_dma_v2 *desc = txd;
+ u64 addr64 = 0;
u32 data = 0;
if(!info->qid && mac->id)
info->qid = MTK_QDMA_GMAC2_QID;
+ addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+ TX_DMA_SDP1(info->addr) : 0;
+
WRITE_ONCE(desc->txd1, info->addr);
data = TX_DMA_PLEN0(info->size);
if (info->last)
data |= TX_DMA_LS0;
- WRITE_ONCE(desc->txd3, data);
+ WRITE_ONCE(desc->txd3, data | addr64);
- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+ data = ((mac->id == MTK_GMAC3_ID) ?
+ PSE_GDM3_PORT : (mac->id + 1)) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
if (HNAT_SKB_CB2(skb)->magic == 0x78681415) {
@@ -1100,7 +1305,8 @@
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
mtk_tx_set_dma_desc_v2(skb, dev, txd, info);
else
mtk_tx_set_dma_desc_v1(skb, dev, txd, info);
@@ -1144,8 +1350,9 @@
mtk_tx_set_dma_desc(skb, dev, itxd, &txd_info);
itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
- itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
- MTK_TX_FLAGS_FPORT1;
+ itx_buf->flags |= (mac->id == MTK_GMAC1_ID) ? MTK_TX_FLAGS_FPORT0 :
+ (mac->id == MTK_GMAC2_ID) ? MTK_TX_FLAGS_FPORT1 :
+ MTK_TX_FLAGS_FPORT2;
setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
k++);
@@ -1191,8 +1398,10 @@
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
- tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
- MTK_TX_FLAGS_FPORT1;
+ tx_buf->flags |=
+ (mac->id == MTK_GMAC1_ID) ? MTK_TX_FLAGS_FPORT0 :
+ (mac->id == MTK_GMAC2_ID) ? MTK_TX_FLAGS_FPORT1 :
+ MTK_TX_FLAGS_FPORT2;
setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
txd_info.size, k++);
@@ -1404,6 +1613,7 @@
struct mtk_rx_ring *ring = rx_napi->rx_ring;
int idx;
struct sk_buff *skb;
+ u64 addr64 = 0;
u8 *data, *new_data;
struct mtk_rx_dma_v2 *rxd, trxd;
int done = 0;
@@ -1434,9 +1644,18 @@
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
mac = 0;
} else {
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
- mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
- else
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ switch (RX_DMA_GET_SPORT_V2(trxd.rxd5)) {
+ case PSE_GDM1_PORT:
+ case PSE_GDM2_PORT:
+ mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
+ break;
+ case PSE_GDM3_PORT:
+ mac = MTK_GMAC3_ID;
+ break;
+ }
+ } else
mac = (trxd.rxd4 & RX_DMA_SPECIAL_TAG) ?
0 : RX_DMA_GET_SPORT(trxd.rxd4) - 1;
}
@@ -1467,7 +1686,11 @@
goto release_desc;
}
- dma_unmap_single(eth->dev, trxd.rxd1,
+ addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+ ((u64)(trxd.rxd2 & 0xf)) << 32 : 0;
+
+ dma_unmap_single(eth->dev,
+ (u64)(trxd.rxd1 | addr64),
ring->buf_size, DMA_FROM_DEVICE);
/* receive data */
@@ -1483,9 +1706,9 @@
skb->dev = netdev;
skb_put(skb, pktlen);
- if ((!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
+ if ((MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) &&
(trxd.rxd4 & eth->rx_dma_l4_valid)) ||
- (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
+ (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) &&
(trxd.rxd3 & eth->rx_dma_l4_valid)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
@@ -1493,7 +1716,8 @@
skb->protocol = eth_type_trans(skb, netdev);
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
if (trxd.rxd3 & RX_DMA_VTAG_V2)
__vlan_hwaccel_put_tag(skb,
htons(RX_DMA_VPID_V2(trxd.rxd4)),
@@ -1516,7 +1740,8 @@
}
#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
*(u32 *)(skb->head) = trxd.rxd5;
else
*(u32 *)(skb->head) = trxd.rxd4;
@@ -1549,10 +1774,13 @@
rxd->rxd1 = (unsigned int)dma_addr;
release_desc:
+ addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+ RX_DMA_SDP1(dma_addr) : 0;
+
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
rxd->rxd2 = RX_DMA_LSO;
else
- rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size);
+ rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size) | addr64;
ring->calc_idx = idx;
@@ -1597,7 +1825,9 @@
tx_buf = mtk_desc_to_tx_buf(ring, desc, soc->txrx.txd_size);
if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
- mac = 1;
+ mac = MTK_GMAC2_ID;
+ else if (tx_buf->flags & MTK_TX_FLAGS_FPORT2)
+ mac = MTK_GMAC3_ID;
skb = tx_buf->skb;
if (!skb)
@@ -1797,7 +2027,8 @@
txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
txd->txd4 = 0;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
txd->txd5 = 0;
txd->txd6 = 0;
txd->txd7 = 0;
@@ -1890,6 +2121,7 @@
struct mtk_rx_ring *ring;
int rx_data_len, rx_dma_size;
int i;
+ u64 addr64 = 0;
if (rx_flag == MTK_RX_FLAGS_QDMA) {
if (ring_no)
@@ -1949,15 +2181,19 @@
rxd = ring->dma + i * eth->soc->txrx.rxd_size;
rxd->rxd1 = (unsigned int)dma_addr;
+ addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+ RX_DMA_SDP1(dma_addr) : 0;
+
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
rxd->rxd2 = RX_DMA_LSO;
else
- rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size);
+ rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size) | addr64;
rxd->rxd3 = 0;
rxd->rxd4 = 0;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
rxd->rxd5 = 0;
rxd->rxd6 = 0;
rxd->rxd7 = 0;
@@ -1994,6 +2230,7 @@
static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_sram)
{
int i;
+ u64 addr64 = 0;
if (ring->data && ring->dma) {
for (i = 0; i < ring->dma_size; i++) {
@@ -2006,8 +2243,12 @@
if (!rxd->rxd1)
continue;
+ addr64 = (MTK_HAS_CAPS(eth->soc->caps,
+ MTK_8GB_ADDRESSING)) ?
+ ((u64)(rxd->rxd2 & 0xf)) << 32 : 0;
+
dma_unmap_single(eth->dev,
- rxd->rxd1,
+ (u64)(rxd->rxd1 | addr64),
ring->buf_size,
DMA_FROM_DEVICE);
skb_free_frag(ring->data[i]);
@@ -2077,7 +2318,8 @@
/* the minimal remaining room of SDL0 in RXD for lro aggregation */
lro_ctrl_dw3 |= MTK_LRO_MIN_RXD_SDL;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
val = mtk_r32(eth, MTK_PDMA_RX_CFG);
mtk_w32(eth, val | (MTK_PDMA_LRO_SDL << MTK_RX_CFG_SDL_OFFSET),
MTK_PDMA_RX_CFG);
@@ -2133,7 +2375,8 @@
{
u32 reg_val;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
idx += 1;
reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
@@ -2151,7 +2394,8 @@
{
u32 reg_val;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
idx += 1;
reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
@@ -2285,7 +2529,7 @@
{
u32 val;
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
/* Set RSS rings to PSE modes */
val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(1));
val |= MTK_RING_PSE_MODE;
@@ -2338,6 +2582,9 @@
/* Set GRP INT */
mtk_w32(eth, 0x21021030, MTK_FE_INT_GRP);
+ /* Enable RSS delay interrupt */
+ mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_RSS_DELAY_INT);
+
return 0;
}
@@ -2458,7 +2705,7 @@
return err;
if (eth->hwlro) {
- i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ? 4 : 1;
+ i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) ? 1 : 4;
for (; i < MTK_MAX_RX_RING_NUM; i++) {
err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_HWLRO);
if (err)
@@ -2514,7 +2761,7 @@
if (eth->hwlro) {
mtk_hwlro_rx_uninit(eth);
- i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ? 4 : 1;
+ i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) ? 1 : 4;
for (; i < MTK_MAX_RX_RING_NUM; i++)
mtk_rx_clean(eth, ð->rx_ring[i], 0);
}
@@ -2644,7 +2891,8 @@
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
val = mtk_r32(eth, MTK_QDMA_GLO_CFG);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
val &= ~MTK_RESV_BUF_MASK;
mtk_w32(eth,
val | MTK_TX_DMA_EN | MTK_RX_DMA_EN |
@@ -2673,7 +2921,7 @@
MTK_PDMA_GLO_CFG);
}
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && eth->hwlro) {
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) && eth->hwlro) {
val = mtk_r32(eth, MTK_PDMA_GLO_CFG);
mtk_w32(eth, val | MTK_RX_DMA_LRO_EN, MTK_PDMA_GLO_CFG);
}
@@ -2787,9 +3035,9 @@
phylink_start(mac->phylink);
netif_start_queue(dev);
phy_node = of_parse_phandle(mac->of_node, "phy-handle", 0);
- if (!phy_node && eth->sgmii->regmap[mac->id]) {
- regmap_write(eth->sgmii->regmap[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
- }
+ if (!phy_node && eth->xgmii->regmap_sgmii[mac->id])
+ regmap_write(eth->xgmii->regmap_sgmii[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
return 0;
}
@@ -2831,10 +3079,10 @@
val = _mtk_mdio_read(eth, 0, 0);
val |= BMCR_PDOWN;
_mtk_mdio_write(eth, 0, 0, val);
- } else if (eth->sgmii->regmap[mac->id]) {
- regmap_read(eth->sgmii->regmap[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ } else if (eth->xgmii->regmap_sgmii[mac->id]) {
+ regmap_read(eth->xgmii->regmap_sgmii[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val |= SGMII_PHYA_PWD;
- regmap_write(eth->sgmii->regmap[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(eth->xgmii->regmap_sgmii[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
}
//GMAC RX disable
@@ -2986,7 +3234,8 @@
else
mtk_eth_cold_reset(eth);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
/* Set FE to PDMAv2 if necessary */
mtk_w32(eth, mtk_r32(eth, MTK_FE_GLO_MISC) | MTK_PDMA_V2, MTK_FE_GLO_MISC);
}
@@ -3032,7 +3281,22 @@
MTK_FE_INT_TSO_ILLEGAL | MTK_FE_INT_TSO_ALIGN |
MTK_FE_INT_RFIFO_OV | MTK_FE_INT_RFIFO_UF, MTK_FE_INT_ENABLE);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ /* PSE should not drop port1, port8 and port9 packets */
+ mtk_w32(eth, 0x00000302, PSE_NO_DROP_CFG);
+
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ /* GDM and CDM Threshold */
+ mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES);
+ mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
+
+ /* PSE GDM3 MIB counter has incorrect hw default values,
+ * so the driver ought to read clear the values beforehand
+ * in case ethtool retrieve wrong mib values.
+ */
+ for (i = 0; i < MTK_STAT_OFFSET; i += 0x4)
+ mtk_r32(eth,
+ MTK_GDM1_TX_GBCNT + MTK_STAT_OFFSET * 2 + i);
+ } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
/* PSE Free Queue Flow Control */
mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2);
@@ -3232,9 +3496,9 @@
for (i = 0; i < MTK_MAC_COUNT; i++) {
mac = netdev_priv(eth->netdev[i]);
phy_node = of_parse_phandle(mac->of_node, "phy-handle", 0);
- if (!phy_node && eth->sgmii->regmap[i]) {
+ if (!phy_node && eth->xgmii->regmap_sgmii[i]) {
mtk_gmac_sgmii_path_setup(eth, i);
- regmap_write(eth->sgmii->regmap[i], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+ regmap_write(eth->xgmii->regmap_sgmii[i], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
}
}
@@ -3577,6 +3841,10 @@
mac->phylink_config.dev = ð->netdev[id]->dev;
mac->phylink_config.type = PHYLINK_NETDEV;
+ mac->type = (phy_mode == PHY_INTERFACE_MODE_10GKR ||
+ phy_mode == PHY_INTERFACE_MODE_USXGMII) ?
+ MTK_XGDM_TYPE : MTK_GDM_TYPE;
+
phylink = phylink_create(&mac->phylink_config,
of_fwnode_handle(mac->of_node),
phy_mode, &mtk_phylink_ops);
@@ -3663,6 +3931,12 @@
if (IS_ERR(eth->base))
return PTR_ERR(eth->base);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ eth->sram_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(eth->sram_base))
+ return PTR_ERR(eth->sram_base);
+ }
+
if(eth->soc->has_sram) {
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -3683,12 +3957,25 @@
eth->rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA;
eth->ip_align = NET_IP_ALIGN;
} else {
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
eth->rx_dma_l4_valid = RX_DMA_L4_VALID_V2;
else
eth->rx_dma_l4_valid = RX_DMA_L4_VALID;
}
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) {
+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
+ if (!err) {
+ err = dma_set_coherent_mask(&pdev->dev,
+ DMA_BIT_MASK(36));
+ if (err) {
+ dev_err(&pdev->dev, "Wrong DMA config\n");
+ return -EINVAL;
+ }
+ }
+ }
+
spin_lock_init(ð->page_lock);
spin_lock_init(ð->tx_irq_lock);
spin_lock_init(ð->rx_irq_lock);
@@ -3713,14 +4000,33 @@
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
- eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii),
+ eth->xgmii = devm_kzalloc(eth->dev, sizeof(*eth->xgmii),
GFP_KERNEL);
- if (!eth->sgmii)
+ if (!eth->xgmii)
return -ENOMEM;
- err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node,
+ eth->xgmii->eth = eth;
+ err = mtk_sgmii_init(eth->xgmii, pdev->dev.of_node,
eth->soc->ana_rgc3);
+ if (err)
+ return err;
+ }
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
+ err = mtk_usxgmii_init(eth->xgmii, pdev->dev.of_node);
+ if (err)
+ return err;
+
+ err = mtk_xfi_pextp_init(eth->xgmii, pdev->dev.of_node);
+ if (err)
+ return err;
+
+ err = mtk_xfi_pll_init(eth->xgmii, pdev->dev.of_node);
+ if (err)
+ return err;
+
+ err = mtk_toprgu_init(eth, pdev->dev.of_node);
if (err)
return err;
}
@@ -4024,6 +4330,21 @@
},
};
+static const struct mtk_soc_data mt7988_data = {
+ .ana_rgc3 = 0x128,
+ .caps = MT7988_CAPS,
+ .hw_features = MTK_HW_FEATURES,
+ .required_clks = MT7988_CLKS_BITMAP,
+ .required_pctl = false,
+ .has_sram = true,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+ },
+};
+
static const struct mtk_soc_data rt5350_data = {
.caps = MT7628_CAPS,
.hw_features = MTK_HW_FEATURES_MT7628,
@@ -4046,6 +4367,7 @@
{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data},
{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data},
{ .compatible = "mediatek,mt7981-eth", .data = &mt7981_data},
+ { .compatible = "mediatek,mt7988-eth", .data = &mt7988_data},
{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data},
{},
};