[][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/Kconfig b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig
index 42e6b38..7bfc78b 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig
@@ -20,6 +20,16 @@
---help---
This options enable MTK Ethernet NETSYS V2 support
+config MEDIATEK_NETSYS_V3
+ tristate "MediaTek Ethernet NETSYS V3 support"
+ depends on ARCH_MEDIATEK && NET_MEDIATEK_SOC
+ ---help---
+ This options enable MTK Ethernet NETSYS V3 support for
+ XGMAC and USXGMII.
+
+ If you have a network system belong to this class, say Y.
+ If unsure, say N.
+
config NET_MEDIATEK_HNAT
tristate "MediaTek HW NAT support"
depends on NET_MEDIATEK_SOC && NF_CONNTRACK && IP_NF_NAT
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
index 13c5b4e..634640d 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
@@ -4,5 +4,5 @@
#
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 0d5ca16..c6f76bf 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -24,6 +24,7 @@
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/of_mdio.h>
+#include <linux/of_address.h>
#include "mtk_eth_soc.h"
#include "mtk_eth_dbg.h"
@@ -43,20 +44,55 @@
typedef int (*mtk_lro_dbg_func) (int par);
struct mtk_eth_debug {
- struct dentry *root;
+ struct dentry *root;
+ void __iomem *base;
+ int direct_access;
};
struct mtk_eth *g_eth;
struct mtk_eth_debug eth_debug;
+int mt798x_iomap(void)
+{
+ struct device_node *np = NULL;
+
+ np = of_find_node_by_name(NULL, "switch0");
+ if (np) {
+ eth_debug.base = of_iomap(np, 0);
+ if (!eth_debug.base) {
+ pr_err("of_iomap failed\n");
+ of_node_put(np);
+ return -ENOMEM;
+ }
+
+ of_node_put(np);
+ eth_debug.direct_access = 1;
+ }
+
+ return 0;
+}
+
+int mt798x_iounmap(void)
+{
+ eth_debug.direct_access = 0;
+ if (eth_debug.base)
+ iounmap(eth_debug.base);
+
+ return 0;
+}
+
void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val)
{
mutex_lock(ð->mii_bus->mdio_lock);
- _mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
- _mtk_mdio_write(eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
- _mtk_mdio_write(eth, 0x1f, 0x10, val >> 16);
+ if (eth_debug.direct_access)
+ __raw_writel(val, eth_debug.base + reg);
+ else {
+ _mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+ _mtk_mdio_write(eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
+ _mtk_mdio_write(eth, 0x1f, 0x10, val >> 16);
+ }
mutex_unlock(ð->mii_bus->mdio_lock);
}
@@ -64,9 +100,15 @@
u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
{
u16 high, low;
+ u32 ret;
mutex_lock(ð->mii_bus->mdio_lock);
+ if (eth_debug.direct_access) {
+ ret = __raw_readl(eth_debug.base + reg);
+ mutex_unlock(ð->mii_bus->mdio_lock);
+ return ret;
+ }
_mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
low = _mtk_mdio_read(eth, 0x1f, (reg >> 2) & 0xf);
high = _mtk_mdio_read(eth, 0x1f, 0x10);
@@ -118,6 +160,7 @@
}
static const struct file_operations mtketh_debug_fops = {
+ .owner = THIS_MODULE,
.open = mtketh_debug_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -209,6 +252,7 @@
}
static const struct file_operations mtketh_debug_mt7530sw_fops = {
+ .owner = THIS_MODULE,
.open = mtketh_debug_mt7530sw_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -417,7 +461,7 @@
*read_data = mt7530_mdio_r32(eth, phy_register);
else
- *read_data = _mtk_mdio_read(eth, phy_addr, phy_register);
+ *read_data = mdiobus_read(eth->mii_bus, phy_addr, phy_register);
}
void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register,
@@ -427,17 +471,17 @@
mt7530_mdio_w32(eth, phy_register, write_data);
else
- _mtk_mdio_write(eth, phy_addr, phy_register, write_data);
+ mdiobus_write(eth->mii_bus, phy_addr, phy_register, write_data);
}
static void mii_mgr_read_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 *data)
{
- *data = _mtk_mdio_read(eth, port, mdiobus_c45_addr(devad, reg));
+ *data = mdiobus_read(eth->mii_bus, port, mdiobus_c45_addr(devad, reg));
}
static void mii_mgr_write_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 data)
{
- _mtk_mdio_write(eth, port, mdiobus_c45_addr(devad, reg), data);
+ mdiobus_write(eth->mii_bus, port, mdiobus_c45_addr(devad, reg), data);
}
int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -519,75 +563,112 @@
return -EFAULT;
}
+static void gdm_reg_dump_v3(struct mtk_eth *eth, u32 gdm_id, u32 mib_base)
+{
+ pr_info("| GDMA%d_RX_GBCNT : %010u (Rx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base));
+ pr_info("| GDMA%d_RX_GPCNT : %010u (Rx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x08));
+ pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x10));
+ pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x14));
+ pr_info("| GDMA%d_RX_SERCNT : %010u (too short) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x18));
+ pr_info("| GDMA%d_RX_LERCNT : %010u (too long) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x1C));
+ pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x20));
+ pr_info("| GDMA%d_RX_FCCNT : %010u (flow control) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x24));
+ pr_info("| GDMA%d_RX_VDPCNT : %010u (VID drop) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x28));
+ pr_info("| GDMA%d_RX_PFCCNT : %010u (priority flow control)\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x2C));
+ pr_info("| GDMA%d_TX_GBCNT : %010u (Tx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x40));
+ pr_info("| GDMA%d_TX_GPCNT : %010u (Tx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x48));
+ pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x50));
+ pr_info("| GDMA%d_TX_COLCNT : %010u (collision count)|\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x54));
+ pr_info("| GDMA%d_TX_OERCNT : %010u (overflow error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x58));
+ pr_info("| GDMA%d_TX_FCCNT : %010u (flow control) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x60));
+ pr_info("| GDMA%d_TX_PFCCNT : %010u (priority flow control)\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x64));
+ pr_info("| |\n");
+}
+
+static void gdm_reg_dump_v2(struct mtk_eth *eth, u32 gdm_id, u32 mib_base)
+{
+ pr_info("| GDMA%d_RX_GBCNT : %010u (Rx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base));
+ pr_info("| GDMA%d_RX_GPCNT : %010u (Rx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x08));
+ pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x10));
+ pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x14));
+ pr_info("| GDMA%d_RX_SERCNT : %010u (too short) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x18));
+ pr_info("| GDMA%d_RX_LERCNT : %010u (too long) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x1C));
+ pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x20));
+ pr_info("| GDMA%d_RX_FCCNT : %010u (flow control) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x24));
+ pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x28));
+ pr_info("| GDMA%d_TX_COLCNT : %010u (collision count) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x2C));
+ pr_info("| GDMA%d_TX_GBCNT : %010u (Tx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x30));
+ pr_info("| GDMA%d_TX_GPCNT : %010u (Tx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x38));
+ pr_info("| |\n");
+}
+
+static void gdm_cnt_read(struct mtk_eth *eth)
+{
+ u32 i, mib_base;
+
+ pr_info("\n <<CPU>>\n");
+ pr_info(" |\n");
+ pr_info("+-----------------------------------------------+\n");
+ pr_info("| <<PSE>> |\n");
+ pr_info("+-----------------------------------------------+\n");
+ pr_info(" |\n");
+ pr_info("+-----------------------------------------------+\n");
+ pr_info("| <<GDMA>> |\n");
+
+ for (i = 0; i < MTK_MAC_COUNT; i++) {
+ mib_base = MTK_GDM1_TX_GBCNT + MTK_STAT_OFFSET * i;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ gdm_reg_dump_v3(eth, i + 1, mib_base);
+ else
+ gdm_reg_dump_v2(eth, i + 1, mib_base);
+ }
+
+ pr_info("+-----------------------------------------------+\n");
+}
+
int esw_cnt_read(struct seq_file *seq, void *v)
{
unsigned int pkt_cnt = 0;
int i = 0;
struct mtk_eth *eth = g_eth;
- unsigned int mib_base = MTK_GDM1_TX_GBCNT;
- seq_puts(seq, "\n <<CPU>>\n");
- seq_puts(seq, " |\n");
- seq_puts(seq, "+-----------------------------------------------+\n");
- seq_puts(seq, "| <<PSE>> |\n");
- seq_puts(seq, "+-----------------------------------------------+\n");
- seq_puts(seq, " |\n");
- seq_puts(seq, "+-----------------------------------------------+\n");
- seq_puts(seq, "| <<GDMA>> |\n");
- seq_printf(seq, "| GDMA1_RX_GBCNT : %010u (Rx Good Bytes) |\n",
- mtk_r32(eth, mib_base));
- seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n",
- mtk_r32(eth, mib_base+0x08));
- seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error) |\n",
- mtk_r32(eth, mib_base+0x10));
- seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n",
- mtk_r32(eth, mib_base+0x14));
- seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n",
- mtk_r32(eth, mib_base+0x18));
- seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n",
- mtk_r32(eth, mib_base+0x1C));
- seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error) |\n",
- mtk_r32(eth, mib_base+0x20));
- seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n",
- mtk_r32(eth, mib_base+0x24));
- seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count) |\n",
- mtk_r32(eth, mib_base+0x28));
- seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count) |\n",
- mtk_r32(eth, mib_base+0x2C));
- seq_printf(seq, "| GDMA1_TX_GBCNT : %010u (Tx Good Bytes) |\n",
- mtk_r32(eth, mib_base+0x30));
- seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n",
- mtk_r32(eth, mib_base+0x38));
- seq_puts(seq, "| |\n");
- seq_printf(seq, "| GDMA2_RX_GBCNT : %010u (Rx Good Bytes) |\n",
- mtk_r32(eth, mib_base+0x40));
- seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n",
- mtk_r32(eth, mib_base+0x48));
- seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error) |\n",
- mtk_r32(eth, mib_base+0x50));
- seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n",
- mtk_r32(eth, mib_base+0x54));
- seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n",
- mtk_r32(eth, mib_base+0x58));
- seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n",
- mtk_r32(eth, mib_base+0x5C));
- seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error) |\n",
- mtk_r32(eth, mib_base+0x60));
- seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n",
- mtk_r32(eth, mib_base+0x64));
- seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n",
- mtk_r32(eth, mib_base+0x68));
- seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n",
- mtk_r32(eth, mib_base+0x6C));
- seq_printf(seq, "| GDMA2_TX_GBCNT : %010u (Tx Good Bytes) |\n",
- mtk_r32(eth, mib_base+0x70));
- seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n",
- mtk_r32(eth, mib_base+0x78));
- seq_puts(seq, "+-----------------------------------------------+\n");
+ gdm_cnt_read(eth);
if (!mt7530_exist(eth))
return 0;
+ mt798x_iomap();
+
#define DUMP_EACH_PORT(base) \
do { \
for (i = 0; i < 7; i++) { \
@@ -643,6 +724,8 @@
seq_puts(seq, "\n");
+ mt798x_iounmap();
+
return 0;
}
@@ -680,7 +763,8 @@
tx_ring->txd1, tx_ring->txd2,
tx_ring->txd3, tx_ring->txd4);
- 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)) {
seq_printf(seq, " %08x %08x %08x %08x",
tx_ring->txd5, tx_ring->txd6,
tx_ring->txd7, tx_ring->txd8);
@@ -720,7 +804,8 @@
hwtx_ring->txd1, hwtx_ring->txd2,
hwtx_ring->txd3, hwtx_ring->txd4);
- 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)) {
seq_printf(seq, " %08x %08x %08x %08x",
hwtx_ring->txd5, hwtx_ring->txd6,
hwtx_ring->txd7, hwtx_ring->txd8);
@@ -761,7 +846,8 @@
rx_ring->rxd1, rx_ring->rxd2,
rx_ring->rxd3, rx_ring->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)) {
seq_printf(seq, " %08x %08x %08x %08x",
rx_ring->rxd5, rx_ring->rxd6,
rx_ring->rxd7, rx_ring->rxd8);
@@ -806,7 +892,8 @@
seq_printf(seq, "| FE_INT_STA : %08x |\n",
mtk_r32(eth, MTK_FE_INT_STATUS));
- 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))
seq_printf(seq, "| FE_INT_STA2 : %08x |\n",
mtk_r32(eth, MTK_FE_INT_STATUS2));
@@ -817,13 +904,20 @@
seq_printf(seq, "| PSE_IQ_STA2 : %08x |\n",
mtk_r32(eth, MTK_PSE_IQ_STA(1)));
- 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)) {
seq_printf(seq, "| PSE_IQ_STA3 : %08x |\n",
mtk_r32(eth, MTK_PSE_IQ_STA(2)));
seq_printf(seq, "| PSE_IQ_STA4 : %08x |\n",
mtk_r32(eth, MTK_PSE_IQ_STA(3)));
seq_printf(seq, "| PSE_IQ_STA5 : %08x |\n",
mtk_r32(eth, MTK_PSE_IQ_STA(4)));
+ seq_printf(seq, "| PSE_IQ_STA6 : %08x |\n",
+ mtk_r32(eth, MTK_PSE_IQ_STA(5)));
+ seq_printf(seq, "| PSE_IQ_STA7 : %08x |\n",
+ mtk_r32(eth, MTK_PSE_IQ_STA(6)));
+ seq_printf(seq, "| PSE_IQ_STA8 : %08x |\n",
+ mtk_r32(eth, MTK_PSE_IQ_STA(7)));
}
seq_printf(seq, "| PSE_OQ_STA1 : %08x |\n",
@@ -831,13 +925,20 @@
seq_printf(seq, "| PSE_OQ_STA2 : %08x |\n",
mtk_r32(eth, MTK_PSE_OQ_STA(1)));
- 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)) {
seq_printf(seq, "| PSE_OQ_STA3 : %08x |\n",
mtk_r32(eth, MTK_PSE_OQ_STA(2)));
seq_printf(seq, "| PSE_OQ_STA4 : %08x |\n",
mtk_r32(eth, MTK_PSE_OQ_STA(3)));
seq_printf(seq, "| PSE_OQ_STA5 : %08x |\n",
mtk_r32(eth, MTK_PSE_OQ_STA(4)));
+ seq_printf(seq, "| PSE_OQ_STA6 : %08x |\n",
+ mtk_r32(eth, MTK_PSE_OQ_STA(5)));
+ seq_printf(seq, "| PSE_OQ_STA7 : %08x |\n",
+ mtk_r32(eth, MTK_PSE_OQ_STA(6)));
+ seq_printf(seq, "| PSE_OQ_STA8 : %08x |\n",
+ mtk_r32(eth, MTK_PSE_OQ_STA(7)));
}
seq_printf(seq, "| PDMA_CRX_IDX : %08x |\n",
@@ -850,6 +951,10 @@
mtk_r32(eth, MTK_QTX_DTX_PTR));
seq_printf(seq, "| QDMA_FQ_CNT : %08x |\n",
mtk_r32(eth, MTK_QDMA_FQ_CNT));
+ seq_printf(seq, "| QDMA_FWD_CNT : %08x |\n",
+ mtk_r32(eth, MTK_QDMA_FWD_CNT));
+ seq_printf(seq, "| QDMA_FSM : %08x |\n",
+ mtk_r32(eth, MTK_QDMA_FSM));
seq_printf(seq, "| FE_PSE_FREE : %08x |\n",
mtk_r32(eth, MTK_FE_PSE_FREE));
seq_printf(seq, "| FE_DROP_FQ : %08x |\n",
@@ -862,16 +967,29 @@
mtk_r32(eth, MTK_GDMA_FWD_CFG(0)));
seq_printf(seq, "| GDM2_IG_CTRL : %08x |\n",
mtk_r32(eth, MTK_GDMA_FWD_CFG(1)));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ seq_printf(seq, "| GDM3_IG_CTRL : %08x |\n",
+ mtk_r32(eth, MTK_GDMA_FWD_CFG(2)));
+ }
seq_printf(seq, "| MAC_P1_MCR : %08x |\n",
mtk_r32(eth, MTK_MAC_MCR(0)));
seq_printf(seq, "| MAC_P2_MCR : %08x |\n",
mtk_r32(eth, MTK_MAC_MCR(1)));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ seq_printf(seq, "| MAC_P3_MCR : %08x |\n",
+ mtk_r32(eth, MTK_MAC_MCR(2)));
+ }
seq_printf(seq, "| MAC_P1_FSM : %08x |\n",
mtk_r32(eth, MTK_MAC_FSM(0)));
seq_printf(seq, "| MAC_P2_FSM : %08x |\n",
mtk_r32(eth, MTK_MAC_FSM(1)));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ seq_printf(seq, "| MAC_P3_FSM : %08x |\n",
+ mtk_r32(eth, MTK_MAC_FSM(2)));
+ }
- 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)) {
seq_printf(seq, "| FE_CDM1_FSM : %08x |\n",
mtk_r32(eth, MTK_FE_CDM1_FSM));
seq_printf(seq, "| FE_CDM2_FSM : %08x |\n",
@@ -880,6 +998,10 @@
mtk_r32(eth, MTK_FE_CDM3_FSM));
seq_printf(seq, "| FE_CDM4_FSM : %08x |\n",
mtk_r32(eth, MTK_FE_CDM4_FSM));
+ seq_printf(seq, "| FE_CDM5_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM5_FSM));
+ seq_printf(seq, "| FE_CDM6_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM6_FSM));
seq_printf(seq, "| FE_GDM1_FSM : %08x |\n",
mtk_r32(eth, MTK_FE_GDM1_FSM));
seq_printf(seq, "| FE_GDM2_FSM : %08x |\n",
@@ -895,7 +1017,8 @@
}
mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS);
- 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_w32(eth, 0xffffffff, MTK_FE_INT_STATUS2);
return 0;
@@ -919,7 +1042,8 @@
struct mtk_eth *eth = g_eth;
u32 idx, agg_cnt, agg_size;
- 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 = ring_no - 4;
agg_cnt = RX_DMA_GET_AGG_CNT_V2(rxd->rxd6);
} else {
@@ -940,7 +1064,8 @@
struct mtk_eth *eth = g_eth;
u32 idx, flush_reason;
- 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 = ring_no - 4;
flush_reason = RX_DMA_GET_FLUSH_RSN_V2(rxd->rxd6);
} else {
@@ -1187,7 +1312,8 @@
{
struct mtk_eth *eth = g_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))
hw_lro_stats_read_v2(seq, v);
else
hw_lro_stats_read_v1(seq, v);
@@ -1458,7 +1584,8 @@
seq_puts(seq, "[4] = hwlro_ring_enable_ctrl\n");
seq_puts(seq, "[5] = hwlro_stats_enable_ctrl\n\n");
- if (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V2) ||
+ MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V3)) {
for (i = 1; i <= 8; i++)
hw_lro_auto_tlb_dump_v2(seq, i);
} else {
@@ -1494,7 +1621,7 @@
((reg_op1 >> MTK_LRO_RING_AGE_TIME_L_OFFSET) & 0x3ff);
seq_printf(seq,
"Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n",
- (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V2))? i+3 : i,
+ (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V1)) ? i : i+3,
agg_cnt, agg_time, age_time, reg_op4);
}
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index 52bd729..1932ac6 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -24,6 +24,8 @@
#define MTK_FE_CDM2_FSM 0x224
#define MTK_FE_CDM3_FSM 0x238
#define MTK_FE_CDM4_FSM 0x298
+#define MTK_FE_CDM5_FSM 0x318
+#define MTK_FE_CDM6_FSM 0x328
#define MTK_FE_GDM1_FSM 0x228
#define MTK_FE_GDM2_FSM 0x22C
#define MTK_FE_PSE_FREE 0x240
@@ -35,7 +37,7 @@
#define MTK_SGMII_EFUSE 0x11D008C8
#define MTK_WED_RTQM_GLO_CFG 0x15010B00
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_PSE_IQ_STA(x) (0x180 + (x) * 0x4)
#define MTK_PSE_OQ_STA(x) (0x1A0 + (x) * 0x4)
#else
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
index dcb3c8a..2b78ee1 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -14,11 +14,11 @@
struct mtk_eth_muxc {
const char *name;
- int cap_bit;
- int (*set_path)(struct mtk_eth *eth, int path);
+ u64 cap_bit;
+ int (*set_path)(struct mtk_eth *eth, u64 path);
};
-static const char *mtk_eth_path_name(int path)
+static const char *mtk_eth_path_name(u64 path)
{
switch (path) {
case MTK_ETH_PATH_GMAC1_RGMII:
@@ -33,14 +33,22 @@
return "gmac2_sgmii";
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";
}
}
-static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
+static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
{
bool updated = true;
u32 val, mask, set;
@@ -71,7 +79,7 @@
return 0;
}
-static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
+static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
@@ -94,7 +102,7 @@
return 0;
}
-static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
+static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0,mask=0,reg=0;
bool updated = true;
@@ -125,7 +133,7 @@
return 0;
}
-static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
+static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
@@ -167,10 +175,73 @@
return 0;
}
-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int 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, id = 0;
+
+ dev_dbg(eth->dev, "path %s in %s updated = %d\n",
+ mtk_eth_path_name(path), __func__, updated);
+
+ /* 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);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
+ mac_id == MTK_GMAC2_ID) {
+ id = mtk_mac2xgmii_id(eth, mac_id);
+ if (MTK_HAS_FLAGS(eth->xgmii->flags[id],
+ MTK_USXGMII_INT_2500)) {
+ val = mtk_r32(eth, MTK_XGMAC_STS(mac_id));
+ mtk_w32(eth,
+ val | (MTK_XGMAC_FORCE_LINK << 16),
+ MTK_XGMAC_STS(mac_id));
+ } else {
+ regmap_update_bits(eth->infra,
+ TOP_MISC_NETSYS_PCS_MUX,
+ NETSYS_PCS_MUX_MASK,
+ MUX_G2_USXGMII_SEL);
+ }
+ }
+ }
+
+ /* Enable XGDM Path */
+ val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac_id));
+ val |= MTK_GDMA_XGDM_SEL;
+ mtk_w32(eth, val, MTK_GDMA_EG_CTRL(mac_id));
+
+ 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;
spin_lock(ð->syscfg0_lock);
@@ -186,6 +257,9 @@
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;
};
@@ -222,11 +296,19 @@
}, {
.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,
},
};
-static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
+static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
{
int i, err = 0;
@@ -255,12 +337,34 @@
return err;
}
+int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
+{
+ int err;
+ 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;
+
+ dev_err(eth->dev, "%s path %s in\n", __func__,
+ mtk_eth_path_name(path));
+
+ /* Setup proper MUXes along the path */
+ err = mtk_eth_mux_setup(eth, path);
+ if (err)
+ return err;
+
+ return 0;
+}
+
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
- int err, path;
+ int err;
+ 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 */
err = mtk_eth_mux_setup(eth, path);
@@ -272,7 +376,8 @@
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
{
- int err, path = 0;
+ int err;
+ u64 path = 0;
if (mac_id == 1)
path = MTK_ETH_PATH_GMAC2_GEPHY;
@@ -290,7 +395,8 @@
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
- int err, path;
+ int err;
+ u64 path;
path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
MTK_ETH_PATH_GMAC2_RGMII;
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
index ebb3940..4655356 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
@@ -33,7 +33,8 @@
int mtk_eth_cold_reset(struct mtk_eth *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))
regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0);
if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
@@ -41,7 +42,8 @@
else
ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | RSTCTRL_PPE0);
- 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))
regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0x3ffffff);
return 0;
@@ -344,12 +346,12 @@
/* Power down sgmii */
for (i = 0; i < MTK_MAX_DEVS; i++) {
- if (!eth->sgmii->regmap[i])
+ if (!eth->xgmii->regmap_sgmii[i])
continue;
- regmap_read(eth->sgmii->regmap[i], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(eth->xgmii->regmap_sgmii[i], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val |= SGMII_PHYA_PWD;
- regmap_write(eth->sgmii->regmap[i], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(eth->xgmii->regmap_sgmii[i], SGMSYS_QPHY_PWR_STATE_CTRL, val);
}
/* Force link down GMAC */
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},
{},
};
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index edaeceb..4de60dc 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -20,7 +20,13 @@
#define MTK_MAX_RX_LENGTH 1536
#define MTK_DMA_SIZE 2048
#define MTK_NAPI_WEIGHT 256
+
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_MAC_COUNT 3
+#else
#define MTK_MAC_COUNT 2
+#endif
+
#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
#define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
#define MTK_DMA_DUMMY_DESC 0xffffffff
@@ -100,23 +106,36 @@
/* CDMP Exgress Control Register */
#define MTK_CDMP_EG_CTRL 0x404
-/* GDM Exgress Control Register */
-#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000))
+/* GDM Ingress Control Register */
+#define MTK_GDMA_FWD_CFG(x) ((x == MTK_GMAC3_ID) ? \
+ 0x540 : 0x500 + (x * 0x1000))
#define MTK_GDMA_SPECIAL_TAG BIT(24)
#define MTK_GDMA_ICS_EN BIT(22)
#define MTK_GDMA_TCS_EN BIT(21)
#define MTK_GDMA_UCS_EN BIT(20)
+#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
#define MTK_GDMA_DROP_ALL 0x7777
+/* GDM Egress Control Register */
+#define MTK_GDMA_EG_CTRL(x) ((x == MTK_GMAC3_ID) ? \
+ 0x544 : 0x504 + (x * 0x1000))
+#define MTK_GDMA_XGDM_SEL BIT(31)
+
/* Unicast Filter MAC Address Register - Low */
-#define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000))
+#define MTK_GDMA_MAC_ADRL(x) ((x == MTK_GMAC3_ID) ? \
+ 0x548 : 0x508 + (x * 0x1000))
/* Unicast Filter MAC Address Register - High */
-#define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000))
+#define MTK_GDMA_MAC_ADRH(x) ((x == MTK_GMAC3_ID) ? \
+ 0x54C : 0x50C + (x * 0x1000))
/* Internal SRAM offset */
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_ETH_SRAM_OFFSET 0x300000
+#else
#define MTK_ETH_SRAM_OFFSET 0x40000
+#endif
/* FE global misc reg*/
#define MTK_FE_GLO_MISC 0x124
@@ -143,7 +162,12 @@
#define MTK_PDMA_V2 BIT(4)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define PDMA_BASE 0x6800
+#define QDMA_BASE 0x4400
+#define WDMA_BASE(x) (0x4800 + ((x) * 0x400))
+#define PPE_BASE(x) ((x == 2) ? 0x2C00 : 0x2200 + ((x) * 0x400))
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
#define PDMA_BASE 0x6000
#define QDMA_BASE 0x4400
#define WDMA_BASE(x) (0x4800 + ((x) * 0x400))
@@ -172,7 +196,7 @@
/* PDMA HW LRO Control Registers */
#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_MAX_RX_RING_NUM (8)
#define MTK_HW_LRO_RING_NUM (4)
#define IS_HW_LRO_RING(ring_no) (((ring_no) > 3) && ((ring_no) < 8))
@@ -216,7 +240,7 @@
#define MTK_LRO_MIN_RXD_SDL (MTK_HW_LRO_SDL_REMAIN_ROOM << 16)
/* PDMA RSS Control Registers */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_PDMA_RSS_GLO_CFG (PDMA_BASE + 0x800)
#define MTK_RX_NAPI_NUM (2)
#define MTK_MAX_IRQ_NUM (4)
@@ -258,6 +282,7 @@
/* PDMA Delay Interrupt Register */
#define MTK_PDMA_DELAY_INT (PDMA_BASE + 0x20c)
+#define MTK_PDMA_RSS_DELAY_INT (PDMA_BASE + 0x2c0)
#define MTK_PDMA_DELAY_RX_EN BIT(15)
#define MTK_PDMA_DELAY_RX_PINT 4
#define MTK_PDMA_DELAY_RX_PINT_SHIFT 8
@@ -275,7 +300,7 @@
/* PDMA Interrupt grouping registers */
#define MTK_PDMA_INT_GRP1 (PDMA_BASE + 0x250)
#define MTK_PDMA_INT_GRP2 (PDMA_BASE + 0x254)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_PDMA_INT_GRP3 (PDMA_BASE + 0x258)
#else
#define MTK_PDMA_INT_GRP3 (PDMA_BASE + 0x22c)
@@ -284,7 +309,7 @@
#define MTK_MAX_DELAY_INT 0x8f0f8f0f
/* PDMA HW LRO IP Setting Registers */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_LRO_RX_RING0_DIP_DW0 (PDMA_BASE + 0x414)
#else
#define MTK_LRO_RX_RING0_DIP_DW0 (PDMA_BASE + 0x304)
@@ -403,9 +428,10 @@
/* QDMA Interrupt Status Register */
#define MTK_QDMA_INT_STATUS (QDMA_BASE + 0x218)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-#define MTK_RX_DONE_INT(ring_no) \
- ((ring_no)? BIT(16 + (ring_no)) : BIT(14))
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_RX_DONE_INT(ring_no) \
+ (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS) ? (BIT(24 + (ring_no))) : \
+ ((ring_no) ? BIT(16 + (ring_no)) : BIT(14)))
#else
#define MTK_RX_DONE_INT(ring_no) \
((ring_no)? BIT(24 + (ring_no)) : BIT(30))
@@ -469,12 +495,17 @@
#define MTK_CDM_TXFIFO_RDY BIT(7)
/* GMA1 Received Good Byte Count Register */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_GDM1_TX_GBCNT 0x1C00
#else
#define MTK_GDM1_TX_GBCNT 0x2400
#endif
+
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_STAT_OFFSET 0x80
+#else
#define MTK_STAT_OFFSET 0x40
+#endif
/* QDMA TX NUM */
#define MTK_QDMA_TX_NUM 16
@@ -492,6 +523,7 @@
/* QDMA V2 descriptor txd5 */
#define TX_DMA_CHKSUM_V2 (0x7 << 28)
#define TX_DMA_TSO_V2 BIT(31)
+#define TX_DMA_SPTAG_V3 BIT(27)
/* QDMA V2 descriptor txd4 */
#define TX_DMA_FPORT_SHIFT_V2 8
@@ -521,6 +553,7 @@
#define TX_DMA_PLEN0(_x) (((_x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
#define TX_DMA_PLEN1(_x) ((_x) & eth->soc->txrx.dma_max_len)
#define TX_DMA_SWC BIT(14)
+#define TX_DMA_SDP1(_x) ((((u64)(_x)) >> 32) & 0xf)
/* PDMA on MT7628 */
#define TX_DMA_DONE BIT(31)
@@ -535,6 +568,7 @@
#define RX_DMA_GET_AGG_CNT(_x) (((_x) >> 2) & 0xff)
#define RX_DMA_GET_REV(_x) (((_x) >> 10) & 0x1f)
#define RX_DMA_VTAG BIT(15)
+#define RX_DMA_SDP1(_x) ((((u64)(_x)) >> 32) & 0xf)
/* QDMA descriptor rxd3 */
#define RX_DMA_VID(_x) ((_x) & VLAN_VID_MASK)
@@ -578,6 +612,23 @@
#define MTK_MAC_MISC 0x1000c
#define MTK_MUX_TO_ESW BIT(0)
+/* XMAC status registers */
+#define MTK_XGMAC_STS(x) ((x == MTK_GMAC3_ID) ? 0x1001C : 0x1000C)
+#define MTK_XGMAC_FORCE_LINK BIT(15)
+#define MTK_USXGMII_PCS_LINK BIT(8)
+#define MTK_XGMAC_RX_FC BIT(5)
+#define MTK_XGMAC_TX_FC BIT(4)
+#define MTK_USXGMII_PCS_MODE GENMASK(3, 1)
+#define MTK_XGMAC_LINK_STS BIT(0)
+
+/* GSW bridge registers */
+#define MTK_GSW_CFG (0x10080)
+#define GSWTX_IPG_MASK GENMASK(19, 16)
+#define GSWTX_IPG_SHIFT 16
+#define GSWRX_IPG_MASK GENMASK(3, 0)
+#define GSWRX_IPG_SHIFT 0
+#define GSW_IPG_11 11
+
/* Mac control registers */
#define MTK_MAC_MCR(x) (0x10100 + (x * 0x100))
#define MAC_MCR_MAX_RX_1536 BIT(24)
@@ -595,6 +646,12 @@
#define MAC_MCR_FORCE_LINK BIT(0)
#define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE)
+/* XFI Mac control registers */
+#define MTK_XMAC_MCR(x) (0x12000 + ((x - 1) * 0x1000))
+#define XMAC_MCR_TRX_DISABLE 0xf
+#define XMAC_MCR_FORCE_TX_FC BIT(5)
+#define XMAC_MCR_FORCE_RX_FC BIT(4)
+
/* Mac status registers */
#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
#define MAC_MSR_EEE1G BIT(7)
@@ -659,11 +716,12 @@
#define ETHSYS_SYSCFG0 0x14
#define SYSCFG0_GE_MASK 0x3
#define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2)))
-#define SYSCFG0_SGMII_MASK GENMASK(9, 8)
+#define SYSCFG0_SGMII_MASK GENMASK(9, 7)
#define SYSCFG0_SGMII_GMAC1 ((2 << 8) & SYSCFG0_SGMII_MASK)
#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)
/* ethernet subsystem clock register */
@@ -701,6 +759,15 @@
#define SGMII_PCS_FAULT BIT(23)
#define SGMII_AN_EXPANSION_CLR BIT(30)
+/* Register to set SGMII speed */
+#define SGMII_PCS_SPEED_ABILITY 0x08
+#define SGMII_PCS_SPEED_MASK GENMASK(11, 10)
+#define SGMII_PCS_SPEED_10 0
+#define SGMII_PCS_SPEED_100 1
+#define SGMII_PCS_SPEED_1000 2
+#define SGMII_PCS_SPEED_DUPLEX BIT(12)
+#define SGMII_PCS_SPEED_LINK BIT(15)
+
/* Register to programmable link timer, the unit in 2 * 8ns */
#define SGMSYS_PCS_LINK_TIMER 0x18
#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0))
@@ -709,6 +776,7 @@
#define SGMSYS_SGMII_MODE 0x20
#define SGMII_IF_MODE_BIT0 BIT(0)
#define SGMII_SPEED_DUPLEX_AN BIT(1)
+#define SGMII_SPEED_MASK GENMASK(3, 2)
#define SGMII_SPEED_10 0x0
#define SGMII_SPEED_100 BIT(2)
#define SGMII_SPEED_1000 BIT(3)
@@ -739,12 +807,49 @@
#define SGMII_PN_SWAP_MASK GENMASK(1, 0)
#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1))
+/* USXGMII subsystem config registers */
+/* Register to control speed */
+#define RG_PHY_TOP_SPEED_CTRL1 0x80C
+#define RG_USXGMII_RATE_UPDATE_MODE BIT(31)
+#define RG_MAC_CK_GATED BIT(29)
+#define RG_IF_FORCE_EN BIT(28)
+#define RG_RATE_ADAPT_MODE GENMASK(10, 8)
+#define RG_RATE_ADAPT_MODE_X1 0
+#define RG_RATE_ADAPT_MODE_X2 1
+#define RG_RATE_ADAPT_MODE_X4 2
+#define RG_RATE_ADAPT_MODE_X10 3
+#define RG_RATE_ADAPT_MODE_X100 4
+#define RG_RATE_ADAPT_MODE_X5 5
+#define RG_RATE_ADAPT_MODE_X50 6
+#define RG_XFI_RX_MODE GENMASK(6, 4)
+#define RG_XFI_RX_MODE_10G 0
+#define RG_XFI_RX_MODE_5G 1
+#define RG_XFI_TX_MODE GENMASK(2, 0)
+#define RG_XFI_TX_MODE_10G 0
+#define RG_XFI_TX_MODE_5G 1
+
+/* Register to control PCS AN */
+#define RG_PCS_AN_CTRL0 0x810
+#define RG_AN_ENABLE BIT(0)
+
+/* Register to control USXGMII XFI PLL digital */
+#define XFI_PLL_DIG_GLB8 0x08
+#define RG_XFI_PLL_EN BIT(31)
+
+/* Register to control USXGMII XFI PLL analog */
+#define XFI_PLL_ANA_GLB8 0x108
+#define RG_XFI_PLL_ANA_SWWA 0x02283248
+
/* Infrasys subsystem config registers */
#define INFRA_MISC2 0x70c
#define CO_QPHY_SEL BIT(0)
#define GEPHY_MAC_SEL BIT(1)
/* 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
@@ -846,6 +951,7 @@
*/
MTK_TX_FLAGS_FPORT0 = 0x04,
MTK_TX_FLAGS_FPORT1 = 0x08,
+ MTK_TX_FLAGS_FPORT2 = 0x10,
};
/* This enum allows us to identify how the clock is defined on the array of the
@@ -925,11 +1031,59 @@
BIT(MTK_CLK_SGMII2_RX_250M) | \
BIT(MTK_CLK_SGMII2_CDR_REF) | \
BIT(MTK_CLK_SGMII2_CDR_FB))
+
+#define MT7988_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
+ BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \
+ BIT(MTK_CLK_SGMII_TX_250M) | \
+ BIT(MTK_CLK_SGMII_RX_250M) | \
+ BIT(MTK_CLK_SGMII_CDR_REF) | \
+ BIT(MTK_CLK_SGMII_CDR_FB) | \
+ BIT(MTK_CLK_SGMII2_TX_250M) | \
+ BIT(MTK_CLK_SGMII2_RX_250M) | \
+ BIT(MTK_CLK_SGMII2_CDR_REF) | \
+ BIT(MTK_CLK_SGMII2_CDR_FB))
+
enum mtk_dev_state {
MTK_HW_INIT,
MTK_RESETTING
};
+/* PSE Port Definition */
+enum mtk_pse_port {
+ PSE_ADMA_PORT = 0,
+ PSE_GDM1_PORT,
+ PSE_GDM2_PORT,
+ PSE_PPE0_PORT,
+ PSE_PPE1_PORT,
+ PSE_QDMA_TX_PORT,
+ PSE_QDMA_RX_PORT,
+ PSE_DROP_PORT,
+ PSE_WDMA0_PORT,
+ PSE_WDMA1_PORT,
+ PSE_TDMA_PORT,
+ PSE_NONE_PORT,
+ PSE_PPE2_PORT,
+ PSE_WDMA2_PORT,
+ PSE_EIP197_PORT,
+ PSE_GDM3_PORT,
+ PSE_PORT_MAX
+};
+
+/* GMAC Identifier */
+enum mtk_gmac_id {
+ MTK_GMAC1_ID = 0,
+ MTK_GMAC2_ID,
+ MTK_GMAC3_ID,
+ MTK_GMAC_ID_MAX
+};
+
+/* GDM Type */
+enum mtk_gdm_type {
+ MTK_GDM_TYPE = 0,
+ MTK_XGDM_TYPE,
+ MTK_GDM_TYPE_MAX
+};
+
/* struct mtk_tx_buf - This struct holds the pointers to the memory pointed at
* by the TX descriptor s
* @skb: The SKB pointer of the packet being sent
@@ -1020,6 +1174,7 @@
MTK_RGMII_BIT = 0,
MTK_TRGMII_BIT,
MTK_SGMII_BIT,
+ MTK_USXGMII_BIT,
MTK_ESW_BIT,
MTK_GEPHY_BIT,
MTK_MUX_BIT,
@@ -1030,10 +1185,13 @@
MTK_SHARED_INT_BIT,
MTK_TRGMII_MT7621_CLK_BIT,
MTK_QDMA_BIT,
+ MTK_NETSYS_V1_BIT,
MTK_NETSYS_V2_BIT,
+ MTK_NETSYS_V3_BIT,
MTK_SOC_MT7628_BIT,
MTK_RSTCTRL_PPE1_BIT,
MTK_U3_COPHY_V2_BIT,
+ MTK_8GB_ADDRESSING_BIT,
/* MUX BITS*/
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
@@ -1041,6 +1199,8 @@
MTK_ETH_MUX_U3_GMAC2_TO_QPHY_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,
/* PATH BITS */
MTK_ETH_PATH_GMAC1_RGMII_BIT,
@@ -1049,13 +1209,18 @@
MTK_ETH_PATH_GMAC2_RGMII_BIT,
MTK_ETH_PATH_GMAC2_SGMII_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,
};
/* Supported hardware group on SoCs */
#define MTK_RGMII BIT(MTK_RGMII_BIT)
#define MTK_TRGMII BIT(MTK_TRGMII_BIT)
#define MTK_SGMII BIT(MTK_SGMII_BIT)
+#define MTK_USXGMII BIT(MTK_USXGMII_BIT)
#define MTK_ESW BIT(MTK_ESW_BIT)
#define MTK_GEPHY BIT(MTK_GEPHY_BIT)
#define MTK_MUX BIT(MTK_MUX_BIT)
@@ -1066,10 +1231,13 @@
#define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT)
#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT)
#define MTK_QDMA BIT(MTK_QDMA_BIT)
+#define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT)
#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT)
+#define MTK_NETSYS_V3 BIT(MTK_NETSYS_V3_BIT)
#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT)
#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT)
#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT)
+#define MTK_8GB_ADDRESSING BIT(MTK_8GB_ADDRESSING_BIT)
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
@@ -1081,6 +1249,10 @@
BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
#define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \
BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
+#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII \
+ BIT(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT)
+#define MTK_ETH_MUX_GMAC123_TO_USXGMII \
+ BIT(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT)
/* Supported path present on SoCs */
#define MTK_ETH_PATH_GMAC1_RGMII BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT)
@@ -1089,7 +1261,11 @@
#define MTK_ETH_PATH_GMAC2_RGMII BIT(MTK_ETH_PATH_GMAC2_RGMII_BIT)
#define MTK_ETH_PATH_GMAC2_SGMII BIT(MTK_ETH_PATH_GMAC2_SGMII_BIT)
#define MTK_ETH_PATH_GMAC2_GEPHY BIT(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
+#define MTK_ETH_PATH_GMAC3_SGMII BIT(MTK_ETH_PATH_GMAC3_SGMII_BIT)
#define MTK_ETH_PATH_GDM1_ESW BIT(MTK_ETH_PATH_GDM1_ESW_BIT)
+#define MTK_ETH_PATH_GMAC1_USXGMII BIT(MTK_ETH_PATH_GMAC1_USXGMII_BIT)
+#define MTK_ETH_PATH_GMAC2_USXGMII BIT(MTK_ETH_PATH_GMAC2_USXGMII_BIT)
+#define MTK_ETH_PATH_GMAC3_USXGMII BIT(MTK_ETH_PATH_GMAC3_USXGMII_BIT)
#define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
@@ -1097,7 +1273,11 @@
#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_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)
/* MUXes present on SoCs */
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
@@ -1120,26 +1300,32 @@
#define MTK_MUX_GMAC12_TO_GEPHY_SGMII \
(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX)
+#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)) == (_x))
#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
MTK_GMAC2_RGMII | MTK_SHARED_INT | \
- MTK_TRGMII_MT7621_CLK | MTK_QDMA)
+ MTK_TRGMII_MT7621_CLK | MTK_QDMA | MTK_NETSYS_V1)
#define MT7622_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | MTK_GMAC2_RGMII | \
MTK_GMAC2_SGMII | MTK_GDM1_ESW | \
- MTK_MUX_GDM1_TO_GMAC1_ESW | \
+ MTK_MUX_GDM1_TO_GMAC1_ESW | MTK_NETSYS_V1 | \
MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA)
#define MT7623_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII | \
- MTK_QDMA)
+ MTK_QDMA | MTK_NETSYS_V1)
-#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628)
+#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628 | MTK_NETSYS_V1)
#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
- MTK_MUX_U3_GMAC2_TO_QPHY | \
+ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
@@ -1151,6 +1337,12 @@
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
MTK_NETSYS_V2)
+#define MT7988_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC3_SGMII | \
+ MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA | \
+ MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | \
+ MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
+ MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | MTK_RSS)
+
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
u32 size;
@@ -1180,7 +1372,7 @@
*/
struct mtk_soc_data {
u32 ana_rgc3;
- u32 caps;
+ u64 caps;
u32 required_clks;
bool required_pctl;
netdev_features_t hw_features;
@@ -1193,26 +1385,37 @@
} txrx;
};
-/* currently no SoC has more than 2 macs */
-#define MTK_MAX_DEVS 2
+/* currently no SoC has more than 3 macs */
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_MAX_DEVS 3
+#else
+#define MTK_MAX_DEVS 2
+#endif
#define MTK_SGMII_PHYSPEED_AN BIT(31)
#define MTK_SGMII_PHYSPEED_MASK GENMASK(2, 0)
#define MTK_SGMII_PHYSPEED_1000 BIT(0)
#define MTK_SGMII_PHYSPEED_2500 BIT(1)
+#define MTK_SGMII_PHYSPEED_5000 BIT(2)
+#define MTK_SGMII_PHYSPEED_10000 BIT(3)
#define MTK_SGMII_PN_SWAP BIT(16)
+#define MTK_USXGMII_INT_2500 BIT(17)
#define MTK_HAS_FLAGS(flags, _x) (((flags) & (_x)) == (_x))
-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
- * characteristics
+/* struct mtk_xgmii - This is the structure holding sgmii/usxgmii regmap and
+ * its characteristics
* @regmap: The register map pointing at the range used to setup
- * SGMII modes
+ * SGMII/USXGMII modes
* @flags: The enum refers to which mode the sgmii wants to run on
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
*/
-struct mtk_sgmii {
- struct regmap *regmap[MTK_MAX_DEVS];
+struct mtk_xgmii {
+ struct mtk_eth *eth;
+ struct regmap *regmap_sgmii[MTK_MAX_DEVS];
+ struct regmap *regmap_usxgmii[MTK_MAX_DEVS];
+ struct regmap *regmap_pextp[MTK_MAX_DEVS];
+ struct regmap *regmap_pll;
u32 flags[MTK_MAX_DEVS];
u32 ana_rgc3;
};
@@ -1279,6 +1482,7 @@
struct mtk_eth {
struct device *dev;
void __iomem *base;
+ void __iomem *sram_base;
spinlock_t page_lock;
spinlock_t tx_irq_lock;
spinlock_t rx_irq_lock;
@@ -1290,7 +1494,8 @@
unsigned long sysclk;
struct regmap *ethsys;
struct regmap *infra;
- struct mtk_sgmii *sgmii;
+ struct regmap *toprgu;
+ struct mtk_xgmii *xgmii;
struct regmap *pctl;
bool hwlro;
refcount_t dma_refcnt;
@@ -1331,6 +1536,7 @@
unsigned int id;
phy_interface_t interface;
unsigned int mode;
+ unsigned int type;
int speed;
struct device_node *of_node;
struct phylink *phylink;
@@ -1353,17 +1559,31 @@
u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg);
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
+int mtk_sgmii_init(struct mtk_xgmii *ss, struct device_node *np,
u32 ana_rgc3);
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, unsigned int id);
-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, unsigned int id,
+int mtk_sgmii_setup_mode_an(struct mtk_xgmii *ss, unsigned int mac_id);
+int mtk_sgmii_setup_mode_force(struct mtk_xgmii *ss, unsigned int mac_id,
const struct phylink_link_state *state);
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
+void mtk_sgmii_setup_phya_gen2(struct mtk_xgmii *ss, int mac_id);
int mtk_gmac_sgmii_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);
void mtk_gdm_config(struct mtk_eth *eth, u32 config);
void ethsys_reset(struct mtk_eth *eth, u32 reset_bits);
+int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id);
+int mtk_usxgmii_init(struct mtk_xgmii *ss, struct device_node *r);
+int mtk_xfi_pextp_init(struct mtk_xgmii *ss, struct device_node *r);
+int mtk_xfi_pll_init(struct mtk_xgmii *ss, struct device_node *r);
+int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
+int mtk_xfi_pll_enable(struct mtk_xgmii *ss);
+int mtk_usxgmii_setup_mode_an(struct mtk_xgmii *ss, int mac_id,
+ int max_speed);
+int mtk_usxgmii_setup_mode_force(struct mtk_xgmii *ss, int mac_id,
+ int max_speed);
+void mtk_usxgmii_setup_phya_an_10000(struct mtk_xgmii *ss, int mac_id);
+void mtk_usxgmii_reset(struct mtk_xgmii *ss, int mac_id);
#endif /* MTK_ETH_H */
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 2661645..d200b16 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -13,7 +13,7 @@
#include "mtk_eth_soc.h"
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+int mtk_sgmii_init(struct mtk_xgmii *ss, struct device_node *r, u32 ana_rgc3)
{
struct device_node *np;
int i;
@@ -25,9 +25,9 @@
if (!np)
break;
- ss->regmap[i] = syscon_node_to_regmap(np);
- if (IS_ERR(ss->regmap[i]))
- return PTR_ERR(ss->regmap[i]);
+ ss->regmap_sgmii[i] = syscon_node_to_regmap(np);
+ if (IS_ERR(ss->regmap_sgmii[i]))
+ return PTR_ERR(ss->regmap_sgmii[i]);
ss->flags[i] &= ~(MTK_SGMII_PN_SWAP);
if (of_property_read_bool(np, "pn_swap"))
@@ -37,78 +37,213 @@
return 0;
}
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, unsigned int id)
+void mtk_sgmii_setup_phya_gen1(struct mtk_xgmii *ss, int mac_id)
{
+ u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+ if (id < 0 || id >= MTK_MAX_DEVS ||
+ !ss->regmap_sgmii[id] || !ss->regmap_pextp[id])
+ return;
+
+ regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00D9071C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020207);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E05050F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00200032);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014BA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+ regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+ regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000EAF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080E0D);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030B09);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0606);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x00FA32FA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F21);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00011110);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x40704000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3064, GENMASK(31, 0), 0x0000C000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0xA8000000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x000000AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x20200F00);
+ regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00050000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000007);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+ udelay(150);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+ udelay(15);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C101);
+ udelay(100);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+ udelay(400);
+}
+
+void mtk_sgmii_setup_phya_gen2(struct mtk_xgmii *ss, int mac_id)
+{
+ u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+ if (id < 0 || id >= MTK_MAX_DEVS ||
+ !ss->regmap_sgmii[id] || !ss->regmap_pextp[id])
+ return;
+
+ regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00D9071C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020707);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E050F0F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00140032);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+ regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+ regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000AAF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080D0D);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030909);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0C06);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x009C329C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F21);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00011110);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x40704000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0xA8000000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x000000AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x22000F00);
+ regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00050000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000005);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+ udelay(150);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+ udelay(15);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C101);
+ udelay(100);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+ udelay(400);
+}
+
+int mtk_sgmii_setup_mode_an(struct mtk_xgmii *ss, unsigned int mac_id)
+{
+ struct mtk_eth *eth = ss->eth;
unsigned int val;
+ u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
- if (!ss->regmap[id])
+ if (!ss->regmap_sgmii[id])
return -EINVAL;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ mtk_xfi_pll_enable(ss);
+
/* Assert PHYA power down state */
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
/* Reset SGMII PCS state */
- regmap_write(ss->regmap[id], SGMII_RESERVED_0, SGMII_SW_RESET);
+ regmap_write(ss->regmap_sgmii[id], SGMII_RESERVED_0, SGMII_SW_RESET);
- regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ regmap_read(ss->regmap_sgmii[id], ss->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_3_125G;
- regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ regmap_write(ss->regmap_sgmii[id], ss->ana_rgc3, val);
/* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
val |= SGMII_REMOTE_FAULT_DIS;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, val);
/* SGMII AN mode setting */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
val &= ~SGMII_IF_MODE_MASK;
val |= SGMII_SPEED_DUPLEX_AN;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, val);
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ /* Enable SGMII AN */
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_ENABLE;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, val);
if(MTK_HAS_FLAGS(ss->flags[id],MTK_SGMII_PN_SWAP))
- regmap_update_bits(ss->regmap[id], SGMSYS_QPHY_WRAP_CTRL,
+ regmap_update_bits(ss->regmap_sgmii[id], SGMSYS_QPHY_WRAP_CTRL,
SGMII_PN_SWAP_MASK, SGMII_PN_SWAP_TX_RX);
/* Release PHYA power down state */
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ mtk_sgmii_setup_phya_gen1(ss, mac_id);
return 0;
}
-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, unsigned int id,
+int mtk_sgmii_setup_mode_force(struct mtk_xgmii *ss, unsigned int mac_id,
const struct phylink_link_state *state)
{
+ struct mtk_eth *eth = ss->eth;
unsigned int val;
+ u32 id = mtk_mac2xgmii_id(eth, mac_id);
- if (!ss->regmap[id])
+ if (!ss->regmap_sgmii[id])
return -EINVAL;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ mtk_xfi_pll_enable(ss);
+
/* Assert PHYA power down state */
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
/* Reset SGMII PCS state */
- regmap_write(ss->regmap[id], SGMII_RESERVED_0, SGMII_SW_RESET);
+ regmap_write(ss->regmap_sgmii[id], SGMII_RESERVED_0, SGMII_SW_RESET);
- regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ regmap_read(ss->regmap_sgmii[id], ss->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_MASK;
if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
val |= RG_PHY_SPEED_3_125G;
- regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ regmap_write(ss->regmap_sgmii[id], ss->ana_rgc3, val);
/* Disable SGMII AN */
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, &val);
val &= ~SGMII_AN_ENABLE;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, val);
/* SGMII force mode setting */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
val &= ~SGMII_IF_MODE_MASK;
val &= ~SGMII_REMOTE_FAULT_DIS;
@@ -121,6 +256,7 @@
break;
case SPEED_2500:
case SPEED_1000:
+ default:
val |= SGMII_SPEED_1000;
break;
};
@@ -131,31 +267,34 @@
if (state->duplex != DUPLEX_FULL)
val |= SGMII_DUPLEX_FULL;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, val);
if(MTK_HAS_FLAGS(ss->flags[id],MTK_SGMII_PN_SWAP))
- regmap_update_bits(ss->regmap[id], SGMSYS_QPHY_WRAP_CTRL,
+ regmap_update_bits(ss->regmap_sgmii[id], SGMSYS_QPHY_WRAP_CTRL,
SGMII_PN_SWAP_MASK, SGMII_PN_SWAP_TX_RX);
/* Release PHYA power down state */
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+ regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ mtk_sgmii_setup_phya_gen2(ss, mac_id);
return 0;
}
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
{
- struct mtk_sgmii *ss = eth->sgmii;
- unsigned int val, sid;
+ struct mtk_xgmii *ss = eth->xgmii;
+ unsigned int val, sid = mtk_mac2xgmii_id(eth, mac_id);
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
- 0 : mac_id;
+ 0 : sid;
- if (!ss->regmap[sid])
+ if (!ss->regmap_sgmii[sid])
return;
- regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(ss->regmap_sgmii[sid], SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(ss->regmap_sgmii[sid], SGMSYS_PCS_CONTROL_1, val);
}
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
new file mode 100644
index 0000000..aaefa80
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
@@ -0,0 +1,350 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Henry Yen <henry.yen@mediatek.com>
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include "mtk_eth_soc.h"
+
+int mtk_usxgmii_init(struct mtk_xgmii *ss, struct device_node *r)
+{
+ struct device_node *np;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
+ if (!np)
+ break;
+
+ ss->regmap_usxgmii[i] = syscon_node_to_regmap(np);
+ if (IS_ERR(ss->regmap_usxgmii[i]))
+ return PTR_ERR(ss->regmap_usxgmii[i]);
+
+ ss->flags[i] &= ~(MTK_USXGMII_INT_2500);
+ if (of_property_read_bool(np, "internal_2500"))
+ ss->flags[i] |= MTK_USXGMII_INT_2500;
+ }
+
+ return 0;
+}
+
+int mtk_xfi_pextp_init(struct mtk_xgmii *ss, struct device_node *r)
+{
+ struct device_node *np;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(r, "mediatek,xfi_pextp", i);
+ if (!np)
+ break;
+
+ ss->regmap_pextp[i] = syscon_node_to_regmap(np);
+ if (IS_ERR(ss->regmap_pextp[i]))
+ return PTR_ERR(ss->regmap_pextp[i]);
+ }
+
+ return 0;
+}
+
+int mtk_xfi_pll_init(struct mtk_xgmii *ss, struct device_node *r)
+{
+ struct device_node *np;
+
+ np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
+ if (!np)
+ return -1;
+
+ ss->regmap_pll = syscon_node_to_regmap(np);
+ if (IS_ERR(ss->regmap_pll))
+ return PTR_ERR(ss->regmap_pll);
+
+ return 0;
+}
+
+int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r)
+{
+ struct device_node *np;
+
+ np = of_parse_phandle(r, "mediatek,toprgu", 0);
+ if (!np)
+ return -1;
+
+ eth->toprgu = syscon_node_to_regmap(np);
+ if (IS_ERR(eth->toprgu))
+ return PTR_ERR(eth->toprgu);
+
+ return 0;
+}
+
+int mtk_xfi_pll_enable(struct mtk_xgmii *ss)
+{
+ u32 val = 0;
+
+ if (!ss->regmap_pll)
+ return -EINVAL;
+
+ /* Add software workaround for USXGMII PLL TCL issue */
+ regmap_write(ss->regmap_pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA);
+
+ regmap_read(ss->regmap_pll, XFI_PLL_DIG_GLB8, &val);
+ val |= RG_XFI_PLL_EN;
+ regmap_write(ss->regmap_pll, XFI_PLL_DIG_GLB8, val);
+
+ return 0;
+}
+
+int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id)
+{
+ u32 xgmii_id = mac_id;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ switch (mac_id) {
+ case MTK_GMAC1_ID:
+ case MTK_GMAC2_ID:
+ xgmii_id = 1;
+ break;
+ case MTK_GMAC3_ID:
+ xgmii_id = 0;
+ break;
+ default:
+ pr_info("[%s] Warning: get illegal mac_id=%d !=!!!\n",
+ __func__, mac_id);
+ }
+ }
+
+ return xgmii_id;
+}
+
+void mtk_usxgmii_setup_phya_an_10000(struct mtk_xgmii *ss, int mac_id)
+{
+ u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+ if (id < 0 || id >= MTK_MAX_DEVS ||
+ !ss->regmap_usxgmii[id] || !ss->regmap_pextp[id])
+ return;
+
+ regmap_update_bits(ss->regmap_usxgmii[id], 0x810, GENMASK(31, 0), 0x000FFE6D);
+ regmap_update_bits(ss->regmap_usxgmii[id], 0x818, GENMASK(31, 0), 0x07B1EC7B);
+ regmap_update_bits(ss->regmap_usxgmii[id], 0x80C, GENMASK(31, 0), 0x30000000);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_usxgmii[id], 0x80C, GENMASK(31, 0), 0x10000000);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_usxgmii[id], 0x80C, GENMASK(31, 0), 0x00000000);
+
+ regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00C9071C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020707);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E050F0F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00140032);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+ regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+ regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000AAF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080D0D);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030909);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0C06);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x01423342);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F20);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00022220);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5064, GENMASK(31, 0), 0x0F020A01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50B4, GENMASK(31, 0), 0x06100600);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x40704000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0xA8000000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x000000AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x00000F00);
+ regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00040000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000001);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+ udelay(150);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+ udelay(15);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C101);
+ udelay(100);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F00);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+ udelay(400);
+}
+
+void mtk_usxgmii_setup_phya_force(struct mtk_xgmii *ss, int mac_id, int max_speed)
+{
+ unsigned int val;
+ u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+ if (id < 0 || id >= MTK_MAX_DEVS ||
+ !ss->regmap_usxgmii[id] || !ss->regmap_pextp[id])
+ return;
+
+ /* Decide USXGMII speed */
+ switch (max_speed) {
+ case SPEED_5000:
+ val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_5G) |
+ FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_5G);
+ break;
+ case SPEED_10000:
+ default:
+ val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_10G) |
+ FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_10G);
+ break;
+ };
+ regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+ /* Disable USXGMII AN mode */
+ regmap_read(ss->regmap_usxgmii[id], RG_PCS_AN_CTRL0, &val);
+ val &= ~RG_AN_ENABLE;
+ regmap_write(ss->regmap_usxgmii[id], RG_PCS_AN_CTRL0, val);
+
+ /* Gated USXGMII */
+ regmap_read(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
+ val |= RG_MAC_CK_GATED;
+ regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+ ndelay(1020);
+
+ /* USXGMII force mode setting */
+ regmap_read(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
+ val |= RG_USXGMII_RATE_UPDATE_MODE;
+ val |= RG_IF_FORCE_EN;
+ val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
+ regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+ /* Un-gated USXGMII */
+ regmap_read(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
+ val &= ~RG_MAC_CK_GATED;
+ regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+ ndelay(1020);
+
+ regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00C9071C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020707);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E050F0F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00140032);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014AA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+ regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+ regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000AAF);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080D0D);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030909);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0C06);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+ regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x01423342);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F20);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00022220);
+ regmap_update_bits(ss->regmap_pextp[id], 0x5064, GENMASK(31, 0), 0x0F020A01);
+ regmap_update_bits(ss->regmap_pextp[id], 0x50B4, GENMASK(31, 0), 0x06100600);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x49664100);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0x00000000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x00000000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x00000F00);
+ regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00040000);
+ regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000001);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+ udelay(150);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+ udelay(15);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C111);
+ ndelay(1020);
+ regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C101);
+ udelay(100);
+ regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+ regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F00);
+ regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+ udelay(400);
+}
+
+void mtk_usxgmii_reset(struct mtk_xgmii *ss, int mac_id)
+{
+ struct mtk_eth *eth = ss->eth;
+ u32 id = mtk_mac2xgmii_id(eth, mac_id);
+
+ if (id < 0 || id >= MTK_MAX_DEVS || !eth->toprgu)
+ return;
+
+ switch (mac_id) {
+ case MTK_GMAC2_ID:
+ regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x0000A004);
+ regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F0A004);
+ regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x00000000);
+ regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F00000);
+ regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x00F00000);
+ break;
+ case MTK_GMAC3_ID:
+ regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x00005002);
+ regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F05002);
+ regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x00000000);
+ regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F00000);
+ regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x00F00000);
+ break;
+ }
+
+ udelay(100);
+}
+
+int mtk_usxgmii_setup_mode_an(struct mtk_xgmii *ss, int mac_id, int max_speed)
+{
+ if (mac_id < 0 || mac_id >= MTK_MAX_DEVS)
+ return -EINVAL;
+
+ if ((max_speed != SPEED_10000) && (max_speed != SPEED_5000))
+ return -EINVAL;
+
+ mtk_xfi_pll_enable(ss);
+ mtk_usxgmii_reset(ss, mac_id);
+ mtk_usxgmii_setup_phya_an_10000(ss, mac_id);
+
+ return 0;
+}
+
+int mtk_usxgmii_setup_mode_force(struct mtk_xgmii *ss, int mac_id, int max_speed)
+{
+ if (mac_id < 0 || mac_id >= MTK_MAX_DEVS)
+ return -EINVAL;
+
+ if ((max_speed != SPEED_10000) && (max_speed != SPEED_5000))
+ return -EINVAL;
+
+ mtk_xfi_pll_enable(ss);
+ mtk_usxgmii_reset(ss, mac_id);
+ mtk_usxgmii_setup_phya_force(ss, mac_id, max_speed);
+
+ return 0;
+}