net: mediatek: add support for MediaTek MT7988 SoC
This patch adds support for MediaTek MT7988. MT7988 features MediaTek NETSYS v3, including three GMACs, and two of them supports 10Gbps USXGMII. MT7988 embeds a MT7531 switch (not MCM) which supports accessing internal registers through MMIO instead of MDIO. Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
This commit is contained in:
@@ -54,6 +54,16 @@
|
|||||||
(DP_PDMA << MC_DP_S) | \
|
(DP_PDMA << MC_DP_S) | \
|
||||||
(DP_PDMA << UN_DP_S))
|
(DP_PDMA << UN_DP_S))
|
||||||
|
|
||||||
|
#define GDMA_BRIDGE_TO_CPU \
|
||||||
|
(0xC0000000 | \
|
||||||
|
GDM_ICS_EN | \
|
||||||
|
GDM_TCS_EN | \
|
||||||
|
GDM_UCS_EN | \
|
||||||
|
(DP_PDMA << MYMAC_DP_S) | \
|
||||||
|
(DP_PDMA << BC_DP_S) | \
|
||||||
|
(DP_PDMA << MC_DP_S) | \
|
||||||
|
(DP_PDMA << UN_DP_S))
|
||||||
|
|
||||||
#define GDMA_FWD_DISCARD \
|
#define GDMA_FWD_DISCARD \
|
||||||
(0x20000000 | \
|
(0x20000000 | \
|
||||||
GDM_ICS_EN | \
|
GDM_ICS_EN | \
|
||||||
@@ -68,7 +78,8 @@
|
|||||||
enum mtk_switch {
|
enum mtk_switch {
|
||||||
SW_NONE,
|
SW_NONE,
|
||||||
SW_MT7530,
|
SW_MT7530,
|
||||||
SW_MT7531
|
SW_MT7531,
|
||||||
|
SW_MT7988,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* struct mtk_soc_data - This is the structure holding all differences
|
/* struct mtk_soc_data - This is the structure holding all differences
|
||||||
@@ -102,6 +113,7 @@ struct mtk_eth_priv {
|
|||||||
void __iomem *fe_base;
|
void __iomem *fe_base;
|
||||||
void __iomem *gmac_base;
|
void __iomem *gmac_base;
|
||||||
void __iomem *sgmii_base;
|
void __iomem *sgmii_base;
|
||||||
|
void __iomem *gsw_base;
|
||||||
|
|
||||||
struct regmap *ethsys_regmap;
|
struct regmap *ethsys_regmap;
|
||||||
|
|
||||||
@@ -171,6 +183,11 @@ static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg,
|
|||||||
writel(val, priv->fe_base + gdma_base + reg);
|
writel(val, priv->fe_base + gdma_base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mtk_fe_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set)
|
||||||
|
{
|
||||||
|
clrsetbits_le32(priv->fe_base + reg, clr, set);
|
||||||
|
}
|
||||||
|
|
||||||
static u32 mtk_gmac_read(struct mtk_eth_priv *priv, u32 reg)
|
static u32 mtk_gmac_read(struct mtk_eth_priv *priv, u32 reg)
|
||||||
{
|
{
|
||||||
return readl(priv->gmac_base + reg);
|
return readl(priv->gmac_base + reg);
|
||||||
@@ -208,6 +225,16 @@ static void mtk_infra_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
|
|||||||
regmap_write(priv->infra_regmap, reg, val);
|
regmap_write(priv->infra_regmap, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 mtk_gsw_read(struct mtk_eth_priv *priv, u32 reg)
|
||||||
|
{
|
||||||
|
return readl(priv->gsw_base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtk_gsw_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
|
||||||
|
{
|
||||||
|
writel(val, priv->gsw_base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Direct MDIO clause 22/45 access via SoC */
|
/* Direct MDIO clause 22/45 access via SoC */
|
||||||
static int mtk_mii_rw(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data,
|
static int mtk_mii_rw(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data,
|
||||||
u32 cmd, u32 st)
|
u32 cmd, u32 st)
|
||||||
@@ -342,6 +369,11 @@ static int mt753x_reg_read(struct mtk_eth_priv *priv, u32 reg, u32 *data)
|
|||||||
{
|
{
|
||||||
int ret, low_word, high_word;
|
int ret, low_word, high_word;
|
||||||
|
|
||||||
|
if (priv->sw == SW_MT7988) {
|
||||||
|
*data = mtk_gsw_read(priv, reg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write page address */
|
/* Write page address */
|
||||||
ret = mtk_mii_write(priv, priv->mt753x_smi_addr, 0x1f, reg >> 6);
|
ret = mtk_mii_write(priv, priv->mt753x_smi_addr, 0x1f, reg >> 6);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -367,6 +399,11 @@ static int mt753x_reg_write(struct mtk_eth_priv *priv, u32 reg, u32 data)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (priv->sw == SW_MT7988) {
|
||||||
|
mtk_gsw_write(priv, reg, data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write page address */
|
/* Write page address */
|
||||||
ret = mtk_mii_write(priv, priv->mt753x_smi_addr, 0x1f, reg >> 6);
|
ret = mtk_mii_write(priv, priv->mt753x_smi_addr, 0x1f, reg >> 6);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -537,6 +574,7 @@ static int mtk_mdio_register(struct udevice *dev)
|
|||||||
priv->mmd_write = mtk_mmd_ind_write;
|
priv->mmd_write = mtk_mmd_ind_write;
|
||||||
break;
|
break;
|
||||||
case SW_MT7531:
|
case SW_MT7531:
|
||||||
|
case SW_MT7988:
|
||||||
priv->mii_read = mt7531_mii_ind_read;
|
priv->mii_read = mt7531_mii_ind_read;
|
||||||
priv->mii_write = mt7531_mii_ind_write;
|
priv->mii_write = mt7531_mii_ind_write;
|
||||||
priv->mmd_read = mt7531_mmd_ind_read;
|
priv->mmd_read = mt7531_mmd_ind_read;
|
||||||
@@ -957,6 +995,103 @@ static int mt7531_setup(struct mtk_eth_priv *priv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mt7988_phy_setting(struct mtk_eth_priv *priv)
|
||||||
|
{
|
||||||
|
u16 val;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||||
|
/* Enable HW auto downshift */
|
||||||
|
priv->mii_write(priv, i, 0x1f, 0x1);
|
||||||
|
val = priv->mii_read(priv, i, PHY_EXT_REG_14);
|
||||||
|
val |= PHY_EN_DOWN_SHFIT;
|
||||||
|
priv->mii_write(priv, i, PHY_EXT_REG_14, val);
|
||||||
|
|
||||||
|
/* PHY link down power saving enable */
|
||||||
|
val = priv->mii_read(priv, i, PHY_EXT_REG_17);
|
||||||
|
val |= PHY_LINKDOWN_POWER_SAVING_EN;
|
||||||
|
priv->mii_write(priv, i, PHY_EXT_REG_17, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mt7988_mac_control(struct mtk_eth_priv *priv, bool enable)
|
||||||
|
{
|
||||||
|
u32 pmcr = FORCE_MODE_LNK;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
pmcr = priv->mt753x_pmcr;
|
||||||
|
|
||||||
|
mt753x_reg_write(priv, PMCR_REG(6), pmcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mt7988_setup(struct mtk_eth_priv *priv)
|
||||||
|
{
|
||||||
|
u16 phy_addr, phy_val;
|
||||||
|
u32 pmcr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
priv->gsw_base = regmap_get_range(priv->ethsys_regmap, 0) + GSW_BASE;
|
||||||
|
|
||||||
|
priv->mt753x_phy_base = (priv->mt753x_smi_addr + 1) &
|
||||||
|
MT753X_SMI_ADDR_MASK;
|
||||||
|
|
||||||
|
/* Turn off PHYs */
|
||||||
|
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||||
|
phy_addr = MT753X_PHY_ADDR(priv->mt753x_phy_base, i);
|
||||||
|
phy_val = priv->mii_read(priv, phy_addr, MII_BMCR);
|
||||||
|
phy_val |= BMCR_PDOWN;
|
||||||
|
priv->mii_write(priv, phy_addr, MII_BMCR, phy_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (priv->phy_interface) {
|
||||||
|
case PHY_INTERFACE_MODE_USXGMII:
|
||||||
|
/* Use CPU bridge instead of actual USXGMII path */
|
||||||
|
|
||||||
|
/* Set GDM1 no drop */
|
||||||
|
mtk_fe_rmw(priv, PSE_NO_DROP_CFG_REG, 0, PSE_NO_DROP_GDM1);
|
||||||
|
|
||||||
|
/* Enable GDM1 to GSW CPU bridge */
|
||||||
|
mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, BIT(0));
|
||||||
|
|
||||||
|
/* XGMAC force link up */
|
||||||
|
mtk_gmac_rmw(priv, GMAC_XGMAC_STS_REG, 0, P1_XGMAC_FORCE_LINK);
|
||||||
|
|
||||||
|
/* Setup GSW CPU bridge IPG */
|
||||||
|
mtk_gmac_rmw(priv, GMAC_GSW_CFG_REG, GSWTX_IPG_M | GSWRX_IPG_M,
|
||||||
|
(0xB << GSWTX_IPG_S) | (0xB << GSWRX_IPG_S));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Error: MT7988 GSW does not support %s interface\n",
|
||||||
|
phy_string_for_interface(priv->phy_interface));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmcr = MT7988_FORCE_MODE |
|
||||||
|
(IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
|
||||||
|
MAC_MODE | MAC_TX_EN | MAC_RX_EN |
|
||||||
|
BKOFF_EN | BACKPR_EN |
|
||||||
|
FORCE_RX_FC | FORCE_TX_FC |
|
||||||
|
(SPEED_1000M << FORCE_SPD_S) | FORCE_DPX |
|
||||||
|
FORCE_LINK;
|
||||||
|
|
||||||
|
priv->mt753x_pmcr = pmcr;
|
||||||
|
|
||||||
|
/* Keep MAC link down before starting eth */
|
||||||
|
mt753x_reg_write(priv, PMCR_REG(6), FORCE_MODE_LNK);
|
||||||
|
|
||||||
|
/* Turn on PHYs */
|
||||||
|
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||||
|
phy_addr = MT753X_PHY_ADDR(priv->mt753x_phy_base, i);
|
||||||
|
phy_val = priv->mii_read(priv, phy_addr, MII_BMCR);
|
||||||
|
phy_val &= ~BMCR_PDOWN;
|
||||||
|
priv->mii_write(priv, phy_addr, MII_BMCR, phy_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
mt7988_phy_setting(priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mt753x_switch_init(struct mtk_eth_priv *priv)
|
static int mt753x_switch_init(struct mtk_eth_priv *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1497,6 +1632,11 @@ static int mtk_eth_start(struct udevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3)) {
|
if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3)) {
|
||||||
|
if (priv->sw == SW_MT7988 && priv->gmac_id == 0) {
|
||||||
|
mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG,
|
||||||
|
GDMA_BRIDGE_TO_CPU);
|
||||||
|
}
|
||||||
|
|
||||||
mtk_gdma_write(priv, priv->gmac_id, GDMA_EG_CTRL_REG,
|
mtk_gdma_write(priv, priv->gmac_id, GDMA_EG_CTRL_REG,
|
||||||
GDMA_CPU_BRIDGE_EN);
|
GDMA_CPU_BRIDGE_EN);
|
||||||
}
|
}
|
||||||
@@ -1845,6 +1985,12 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
|
|||||||
priv->switch_mac_control = mt7531_mac_control;
|
priv->switch_mac_control = mt7531_mac_control;
|
||||||
priv->mt753x_smi_addr = MT753X_DFL_SMI_ADDR;
|
priv->mt753x_smi_addr = MT753X_DFL_SMI_ADDR;
|
||||||
priv->mt753x_reset_wait_time = 200;
|
priv->mt753x_reset_wait_time = 200;
|
||||||
|
} else if (!strcmp(str, "mt7988")) {
|
||||||
|
priv->sw = SW_MT7988;
|
||||||
|
priv->switch_init = mt7988_setup;
|
||||||
|
priv->switch_mac_control = mt7988_mac_control;
|
||||||
|
priv->mt753x_smi_addr = MT753X_DFL_SMI_ADDR;
|
||||||
|
priv->mt753x_reset_wait_time = 50;
|
||||||
} else {
|
} else {
|
||||||
printf("error: unsupported switch\n");
|
printf("error: unsupported switch\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -1879,6 +2025,15 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct mtk_soc_data mt7988_data = {
|
||||||
|
.caps = MT7988_CAPS,
|
||||||
|
.ana_rgc3 = 0x128,
|
||||||
|
.gdma_count = 3,
|
||||||
|
.pdma_base = PDMA_V3_BASE,
|
||||||
|
.txd_size = sizeof(struct mtk_tx_dma_v2),
|
||||||
|
.rxd_size = sizeof(struct mtk_rx_dma_v2),
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mtk_soc_data mt7986_data = {
|
static const struct mtk_soc_data mt7986_data = {
|
||||||
.caps = MT7986_CAPS,
|
.caps = MT7986_CAPS,
|
||||||
.ana_rgc3 = 0x128,
|
.ana_rgc3 = 0x128,
|
||||||
@@ -1930,6 +2085,7 @@ static const struct mtk_soc_data mt7621_data = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id mtk_eth_ids[] = {
|
static const struct udevice_id mtk_eth_ids[] = {
|
||||||
|
{ .compatible = "mediatek,mt7988-eth", .data = (ulong)&mt7988_data },
|
||||||
{ .compatible = "mediatek,mt7986-eth", .data = (ulong)&mt7986_data },
|
{ .compatible = "mediatek,mt7986-eth", .data = (ulong)&mt7986_data },
|
||||||
{ .compatible = "mediatek,mt7981-eth", .data = (ulong)&mt7981_data },
|
{ .compatible = "mediatek,mt7981-eth", .data = (ulong)&mt7981_data },
|
||||||
{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
|
{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
|
||||||
|
@@ -51,6 +51,8 @@ enum mkt_eth_capabilities {
|
|||||||
|
|
||||||
#define MT7986_CAPS (MTK_NETSYS_V2)
|
#define MT7986_CAPS (MTK_NETSYS_V2)
|
||||||
|
|
||||||
|
#define MT7988_CAPS (MTK_NETSYS_V3 | MTK_INFRA)
|
||||||
|
|
||||||
/* Frame Engine Register Bases */
|
/* Frame Engine Register Bases */
|
||||||
#define PDMA_V1_BASE 0x0800
|
#define PDMA_V1_BASE 0x0800
|
||||||
#define PDMA_V2_BASE 0x6000
|
#define PDMA_V2_BASE 0x6000
|
||||||
@@ -59,6 +61,7 @@ enum mkt_eth_capabilities {
|
|||||||
#define GDMA2_BASE 0x1500
|
#define GDMA2_BASE 0x1500
|
||||||
#define GDMA3_BASE 0x0540
|
#define GDMA3_BASE 0x0540
|
||||||
#define GMAC_BASE 0x10000
|
#define GMAC_BASE 0x10000
|
||||||
|
#define GSW_BASE 0x20000
|
||||||
|
|
||||||
/* Ethernet subsystem registers */
|
/* Ethernet subsystem registers */
|
||||||
|
|
||||||
@@ -117,6 +120,9 @@ enum mkt_eth_capabilities {
|
|||||||
#define RG_XFI_PLL_ANA_SWWA 0x02283248
|
#define RG_XFI_PLL_ANA_SWWA 0x02283248
|
||||||
|
|
||||||
/* Frame Engine Registers */
|
/* Frame Engine Registers */
|
||||||
|
#define PSE_NO_DROP_CFG_REG 0x108
|
||||||
|
#define PSE_NO_DROP_GDM1 BIT(1)
|
||||||
|
|
||||||
#define FE_GLO_MISC_REG 0x124
|
#define FE_GLO_MISC_REG 0x124
|
||||||
#define PDMA_VER_V2 BIT(4)
|
#define PDMA_VER_V2 BIT(4)
|
||||||
|
|
||||||
@@ -187,6 +193,17 @@ enum mkt_eth_capabilities {
|
|||||||
#define MDIO_RW_DATA_S 0
|
#define MDIO_RW_DATA_S 0
|
||||||
#define MDIO_RW_DATA_M 0xffff
|
#define MDIO_RW_DATA_M 0xffff
|
||||||
|
|
||||||
|
#define GMAC_XGMAC_STS_REG 0x000c
|
||||||
|
#define P1_XGMAC_FORCE_LINK BIT(15)
|
||||||
|
|
||||||
|
#define GMAC_MAC_MISC_REG 0x0010
|
||||||
|
|
||||||
|
#define GMAC_GSW_CFG_REG 0x0080
|
||||||
|
#define GSWTX_IPG_M 0xF0000
|
||||||
|
#define GSWTX_IPG_S 16
|
||||||
|
#define GSWRX_IPG_M 0xF
|
||||||
|
#define GSWRX_IPG_S 0
|
||||||
|
|
||||||
/* MDIO_CMD: MDIO commands */
|
/* MDIO_CMD: MDIO commands */
|
||||||
#define MDIO_CMD_ADDR 0
|
#define MDIO_CMD_ADDR 0
|
||||||
#define MDIO_CMD_WRITE 1
|
#define MDIO_CMD_WRITE 1
|
||||||
@@ -285,6 +302,9 @@ enum mkt_eth_capabilities {
|
|||||||
FORCE_MODE_TX_FC | FORCE_MODE_RX_FC | \
|
FORCE_MODE_TX_FC | FORCE_MODE_RX_FC | \
|
||||||
FORCE_MODE_DPX | FORCE_MODE_SPD | \
|
FORCE_MODE_DPX | FORCE_MODE_SPD | \
|
||||||
FORCE_MODE_LNK
|
FORCE_MODE_LNK
|
||||||
|
#define MT7988_FORCE_MODE FORCE_MODE_TX_FC | FORCE_MODE_RX_FC | \
|
||||||
|
FORCE_MODE_DPX | FORCE_MODE_SPD | \
|
||||||
|
FORCE_MODE_LNK
|
||||||
|
|
||||||
/* MT7531 SGMII Registers */
|
/* MT7531 SGMII Registers */
|
||||||
#define MT7531_SGMII_REG_BASE 0x5000
|
#define MT7531_SGMII_REG_BASE 0x5000
|
||||||
|
Reference in New Issue
Block a user