aboutsummaryrefslogtreecommitdiffstats
path: root/package/boot/uboot-mediatek/patches/101-26-net-mediatek-add-support-for-MediaTek-MT7988-SoC.patch
blob: 29e8649052150208fce6002c4c0d4467bb6e6fb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
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