mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	Import pending patches adding support for MT7988 and provide builds for the reference board for all possible boot media. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
		
			
				
	
	
		
			328 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 59dba9d87c9caf04a5d797af46699055a53870f4 Mon Sep 17 00:00:00 2001
 | |
| From: Weijie Gao <weijie.gao@mediatek.com>
 | |
| Date: Wed, 19 Jul 2023 17:17:41 +0800
 | |
| Subject: [PATCH 26/29] 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>
 | |
| ---
 | |
|  drivers/net/mtk_eth.c | 158 +++++++++++++++++++++++++++++++++++++++++-
 | |
|  drivers/net/mtk_eth.h |  20 ++++++
 | |
|  2 files changed, 177 insertions(+), 1 deletion(-)
 | |
| 
 | |
| --- a/drivers/net/mtk_eth.c
 | |
| +++ b/drivers/net/mtk_eth.c
 | |
| @@ -54,6 +54,16 @@
 | |
|  	(DP_PDMA << MC_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 \
 | |
|  	(0x20000000 | \
 | |
|  	GDM_ICS_EN | \
 | |
| @@ -68,7 +78,8 @@
 | |
|  enum mtk_switch {
 | |
|  	SW_NONE,
 | |
|  	SW_MT7530,
 | |
| -	SW_MT7531
 | |
| +	SW_MT7531,
 | |
| +	SW_MT7988,
 | |
|  };
 | |
|  
 | |
|  /* 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 *gmac_base;
 | |
|  	void __iomem *sgmii_base;
 | |
| +	void __iomem *gsw_base;
 | |
|  
 | |
|  	struct regmap *ethsys_regmap;
 | |
|  
 | |
| @@ -171,6 +183,11 @@ static void mtk_gdma_write(struct mtk_et
 | |
|  	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)
 | |
|  {
 | |
|  	return readl(priv->gmac_base + reg);
 | |
| @@ -208,6 +225,16 @@ static void mtk_infra_rmw(struct mtk_eth
 | |
|  	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 */
 | |
|  static int mtk_mii_rw(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data,
 | |
|  		      u32 cmd, u32 st)
 | |
| @@ -342,6 +369,11 @@ static int mt753x_reg_read(struct mtk_et
 | |
|  {
 | |
|  	int ret, low_word, high_word;
 | |
|  
 | |
| +	if (priv->sw == SW_MT7988) {
 | |
| +		*data = mtk_gsw_read(priv, reg);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
|  	/* Write page address */
 | |
|  	ret = mtk_mii_write(priv, priv->mt753x_smi_addr, 0x1f, reg >> 6);
 | |
|  	if (ret)
 | |
| @@ -367,6 +399,11 @@ static int mt753x_reg_write(struct mtk_e
 | |
|  {
 | |
|  	int ret;
 | |
|  
 | |
| +	if (priv->sw == SW_MT7988) {
 | |
| +		mtk_gsw_write(priv, reg, data);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
|  	/* Write page address */
 | |
|  	ret = mtk_mii_write(priv, priv->mt753x_smi_addr, 0x1f, reg >> 6);
 | |
|  	if (ret)
 | |
| @@ -537,6 +574,7 @@ static int mtk_mdio_register(struct udev
 | |
|  		priv->mmd_write = mtk_mmd_ind_write;
 | |
|  		break;
 | |
|  	case SW_MT7531:
 | |
| +	case SW_MT7988:
 | |
|  		priv->mii_read = mt7531_mii_ind_read;
 | |
|  		priv->mii_write = mt7531_mii_ind_write;
 | |
|  		priv->mmd_read = mt7531_mmd_ind_read;
 | |
| @@ -957,6 +995,103 @@ static int mt7531_setup(struct mtk_eth_p
 | |
|  	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)
 | |
|  {
 | |
|  	int ret;
 | |
| @@ -1497,6 +1632,11 @@ static int mtk_eth_start(struct udevice
 | |
|  	}
 | |
|  
 | |
|  	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,
 | |
|  			       GDMA_CPU_BRIDGE_EN);
 | |
|  	}
 | |
| @@ -1845,6 +1985,12 @@ static int mtk_eth_of_to_plat(struct ude
 | |
|  			priv->switch_mac_control = mt7531_mac_control;
 | |
|  			priv->mt753x_smi_addr = MT753X_DFL_SMI_ADDR;
 | |
|  			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 {
 | |
|  			printf("error: unsupported switch\n");
 | |
|  			return -EINVAL;
 | |
| @@ -1879,6 +2025,15 @@ static int mtk_eth_of_to_plat(struct ude
 | |
|  	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 = {
 | |
|  	.caps = MT7986_CAPS,
 | |
|  	.ana_rgc3 = 0x128,
 | |
| @@ -1930,6 +2085,7 @@ static const struct mtk_soc_data mt7621_
 | |
|  };
 | |
|  
 | |
|  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,mt7981-eth", .data = (ulong)&mt7981_data },
 | |
|  	{ .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
 | |
| --- a/drivers/net/mtk_eth.h
 | |
| +++ b/drivers/net/mtk_eth.h
 | |
| @@ -51,6 +51,8 @@ enum mkt_eth_capabilities {
 | |
|  
 | |
|  #define MT7986_CAPS  (MTK_NETSYS_V2)
 | |
|  
 | |
| +#define MT7988_CAPS  (MTK_NETSYS_V3 | MTK_INFRA)
 | |
| +
 | |
|  /* Frame Engine Register Bases */
 | |
|  #define PDMA_V1_BASE			0x0800
 | |
|  #define PDMA_V2_BASE			0x6000
 | |
| @@ -59,6 +61,7 @@ enum mkt_eth_capabilities {
 | |
|  #define GDMA2_BASE			0x1500
 | |
|  #define GDMA3_BASE			0x0540
 | |
|  #define GMAC_BASE			0x10000
 | |
| +#define GSW_BASE			0x20000
 | |
|  
 | |
|  /* Ethernet subsystem registers */
 | |
|  
 | |
| @@ -117,6 +120,9 @@ enum mkt_eth_capabilities {
 | |
|  #define RG_XFI_PLL_ANA_SWWA		0x02283248
 | |
|  
 | |
|  /* Frame Engine Registers */
 | |
| +#define PSE_NO_DROP_CFG_REG		0x108
 | |
| +#define PSE_NO_DROP_GDM1		BIT(1)
 | |
| +
 | |
|  #define FE_GLO_MISC_REG			0x124
 | |
|  #define PDMA_VER_V2			BIT(4)
 | |
|  
 | |
| @@ -187,6 +193,17 @@ enum mkt_eth_capabilities {
 | |
|  #define MDIO_RW_DATA_S			0
 | |
|  #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 */
 | |
|  #define MDIO_CMD_ADDR			0
 | |
|  #define MDIO_CMD_WRITE			1
 | |
| @@ -285,6 +302,9 @@ enum mkt_eth_capabilities {
 | |
|  					FORCE_MODE_TX_FC | FORCE_MODE_RX_FC | \
 | |
|  					FORCE_MODE_DPX   | FORCE_MODE_SPD | \
 | |
|  					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 */
 | |
|  #define MT7531_SGMII_REG_BASE		0x5000
 |