blob: 1e6b30769d14a5672c7a0fb8431108f03314df00 [file] [log] [blame]
developerc3ac93d2018-12-20 16:12:53 +08001// SPDX-License-Identifier: GPL-2.0
2/*
developer29d9d9f2025-01-10 16:41:13 +08003 * Copyright (C) 2025 MediaTek Inc.
developerc3ac93d2018-12-20 16:12:53 +08004 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 * Author: Mark Lee <mark-mc.lee@mediatek.com>
7 */
8
Simon Glass63334482019-11-14 12:57:39 -07009#include <cpu_func.h>
developerc3ac93d2018-12-20 16:12:53 +080010#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
developerc3ac93d2018-12-20 16:12:53 +080012#include <malloc.h>
13#include <miiphy.h>
Simon Glass274e0b02020-05-10 11:39:56 -060014#include <net.h>
developerc3ac93d2018-12-20 16:12:53 +080015#include <regmap.h>
16#include <reset.h>
17#include <syscon.h>
18#include <wait_bit.h>
Simon Glass274e0b02020-05-10 11:39:56 -060019#include <asm/cache.h>
developerc3ac93d2018-12-20 16:12:53 +080020#include <asm/gpio.h>
21#include <asm/io.h>
Simon Glass9bc15642020-02-03 07:36:16 -070022#include <dm/device_compat.h>
Simon Glassdbd79542020-05-10 11:40:11 -060023#include <linux/delay.h>
developerc3ac93d2018-12-20 16:12:53 +080024#include <linux/err.h>
25#include <linux/ioport.h>
26#include <linux/mdio.h>
27#include <linux/mii.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060028#include <linux/printk.h>
developerc3ac93d2018-12-20 16:12:53 +080029
30#include "mtk_eth.h"
31
developer813a7d32024-12-17 16:40:03 +080032#define NUM_TX_DESC 32
33#define NUM_RX_DESC 32
developerc3ac93d2018-12-20 16:12:53 +080034#define TX_TOTAL_BUF_SIZE (NUM_TX_DESC * PKTSIZE_ALIGN)
35#define RX_TOTAL_BUF_SIZE (NUM_RX_DESC * PKTSIZE_ALIGN)
36#define TOTAL_PKT_BUF_SIZE (TX_TOTAL_BUF_SIZE + RX_TOTAL_BUF_SIZE)
37
developerc3ac93d2018-12-20 16:12:53 +080038#define GDMA_FWD_TO_CPU \
39 (0x20000000 | \
40 GDM_ICS_EN | \
41 GDM_TCS_EN | \
42 GDM_UCS_EN | \
43 STRP_CRC | \
44 (DP_PDMA << MYMAC_DP_S) | \
45 (DP_PDMA << BC_DP_S) | \
46 (DP_PDMA << MC_DP_S) | \
47 (DP_PDMA << UN_DP_S))
48
developer76e14722023-07-19 17:17:41 +080049#define GDMA_BRIDGE_TO_CPU \
50 (0xC0000000 | \
51 GDM_ICS_EN | \
52 GDM_TCS_EN | \
53 GDM_UCS_EN | \
54 (DP_PDMA << MYMAC_DP_S) | \
55 (DP_PDMA << BC_DP_S) | \
56 (DP_PDMA << MC_DP_S) | \
57 (DP_PDMA << UN_DP_S))
58
developerc3ac93d2018-12-20 16:12:53 +080059#define GDMA_FWD_DISCARD \
60 (0x20000000 | \
61 GDM_ICS_EN | \
62 GDM_TCS_EN | \
63 GDM_UCS_EN | \
64 STRP_CRC | \
65 (DP_DISCARD << MYMAC_DP_S) | \
66 (DP_DISCARD << BC_DP_S) | \
67 (DP_DISCARD << MC_DP_S) | \
68 (DP_DISCARD << UN_DP_S))
69
developerc3ac93d2018-12-20 16:12:53 +080070struct mtk_eth_priv {
71 char pkt_pool[TOTAL_PKT_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
72
developer65089f72022-09-09 19:59:24 +080073 void *tx_ring_noc;
74 void *rx_ring_noc;
developerc3ac93d2018-12-20 16:12:53 +080075
76 int rx_dma_owner_idx0;
77 int tx_cpu_owner_idx0;
78
79 void __iomem *fe_base;
80 void __iomem *gmac_base;
developer9a12c242020-01-21 19:31:57 +080081 void __iomem *sgmii_base;
developerc3ac93d2018-12-20 16:12:53 +080082
developera182b7e2022-05-20 11:23:37 +080083 struct regmap *ethsys_regmap;
84
developera5d712a2023-07-19 17:17:22 +080085 struct regmap *infra_regmap;
86
developer03ce27b2023-07-19 17:17:31 +080087 struct regmap *usxgmii_regmap;
88 struct regmap *xfi_pextp_regmap;
89 struct regmap *xfi_pll_regmap;
90 struct regmap *toprgu_regmap;
91
developerc3ac93d2018-12-20 16:12:53 +080092 struct mii_dev *mdio_bus;
developerc3ac93d2018-12-20 16:12:53 +080093
developer1d3b1f62022-09-09 19:59:21 +080094 const struct mtk_soc_data *soc;
developerc3ac93d2018-12-20 16:12:53 +080095 int gmac_id;
96 int force_mode;
97 int speed;
98 int duplex;
developer4843ad32024-01-22 10:08:11 +080099 int mdc;
developer053929c2022-09-09 19:59:28 +0800100 bool pn_swap;
developerc3ac93d2018-12-20 16:12:53 +0800101
102 struct phy_device *phydev;
103 int phy_interface;
104 int phy_addr;
105
developer29d9d9f2025-01-10 16:41:13 +0800106 struct mtk_eth_switch_priv *swpriv;
107 const char *swname;
developerc3ac93d2018-12-20 16:12:53 +0800108
109 struct gpio_desc rst_gpio;
110 int mcm;
111
112 struct reset_ctl rst_fe;
113 struct reset_ctl rst_mcm;
114};
115
116static void mtk_pdma_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
117{
developera7cdebf2022-09-09 19:59:26 +0800118 writel(val, priv->fe_base + priv->soc->pdma_base + reg);
developerc3ac93d2018-12-20 16:12:53 +0800119}
120
121static void mtk_pdma_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
122 u32 set)
123{
developera7cdebf2022-09-09 19:59:26 +0800124 clrsetbits_le32(priv->fe_base + priv->soc->pdma_base + reg, clr, set);
developerc3ac93d2018-12-20 16:12:53 +0800125}
126
127static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg,
128 u32 val)
129{
130 u32 gdma_base;
131
developer78fed682023-07-19 17:17:37 +0800132 if (no == 2)
133 gdma_base = GDMA3_BASE;
134 else if (no == 1)
developerc3ac93d2018-12-20 16:12:53 +0800135 gdma_base = GDMA2_BASE;
136 else
137 gdma_base = GDMA1_BASE;
138
139 writel(val, priv->fe_base + gdma_base + reg);
140}
141
developer29d9d9f2025-01-10 16:41:13 +0800142void mtk_fe_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set)
developer76e14722023-07-19 17:17:41 +0800143{
144 clrsetbits_le32(priv->fe_base + reg, clr, set);
145}
146
developerc3ac93d2018-12-20 16:12:53 +0800147static u32 mtk_gmac_read(struct mtk_eth_priv *priv, u32 reg)
148{
149 return readl(priv->gmac_base + reg);
150}
151
152static void mtk_gmac_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
153{
154 writel(val, priv->gmac_base + reg);
155}
156
developer29d9d9f2025-01-10 16:41:13 +0800157void mtk_gmac_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set)
developerc3ac93d2018-12-20 16:12:53 +0800158{
159 clrsetbits_le32(priv->gmac_base + reg, clr, set);
160}
161
developer29d9d9f2025-01-10 16:41:13 +0800162void mtk_ethsys_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set)
developerc3ac93d2018-12-20 16:12:53 +0800163{
developera182b7e2022-05-20 11:23:37 +0800164 uint val;
165
166 regmap_read(priv->ethsys_regmap, reg, &val);
167 val &= ~clr;
168 val |= set;
169 regmap_write(priv->ethsys_regmap, reg, val);
developerc3ac93d2018-12-20 16:12:53 +0800170}
171
developera5d712a2023-07-19 17:17:22 +0800172static void mtk_infra_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
173 u32 set)
174{
175 uint val;
176
177 regmap_read(priv->infra_regmap, reg, &val);
178 val &= ~clr;
179 val |= set;
180 regmap_write(priv->infra_regmap, reg, val);
181}
182
developerc3ac93d2018-12-20 16:12:53 +0800183/* Direct MDIO clause 22/45 access via SoC */
184static int mtk_mii_rw(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data,
185 u32 cmd, u32 st)
186{
187 int ret;
188 u32 val;
189
190 val = (st << MDIO_ST_S) |
191 ((cmd << MDIO_CMD_S) & MDIO_CMD_M) |
192 (((u32)phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) |
193 (((u32)reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M);
194
developer4781c6e2023-07-19 17:17:03 +0800195 if (cmd == MDIO_CMD_WRITE || cmd == MDIO_CMD_ADDR)
developerc3ac93d2018-12-20 16:12:53 +0800196 val |= data & MDIO_RW_DATA_M;
197
198 mtk_gmac_write(priv, GMAC_PIAC_REG, val | PHY_ACS_ST);
199
200 ret = wait_for_bit_le32(priv->gmac_base + GMAC_PIAC_REG,
201 PHY_ACS_ST, 0, 5000, 0);
202 if (ret) {
203 pr_warn("MDIO access timeout\n");
204 return ret;
205 }
206
developer4781c6e2023-07-19 17:17:03 +0800207 if (cmd == MDIO_CMD_READ || cmd == MDIO_CMD_READ_C45) {
developerc3ac93d2018-12-20 16:12:53 +0800208 val = mtk_gmac_read(priv, GMAC_PIAC_REG);
209 return val & MDIO_RW_DATA_M;
210 }
211
212 return 0;
213}
214
215/* Direct MDIO clause 22 read via SoC */
developer29d9d9f2025-01-10 16:41:13 +0800216int mtk_mii_read(struct mtk_eth_priv *priv, u8 phy, u8 reg)
developerc3ac93d2018-12-20 16:12:53 +0800217{
218 return mtk_mii_rw(priv, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22);
219}
220
221/* Direct MDIO clause 22 write via SoC */
developer29d9d9f2025-01-10 16:41:13 +0800222int mtk_mii_write(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data)
developerc3ac93d2018-12-20 16:12:53 +0800223{
224 return mtk_mii_rw(priv, phy, reg, data, MDIO_CMD_WRITE, MDIO_ST_C22);
225}
226
227/* Direct MDIO clause 45 read via SoC */
developer29d9d9f2025-01-10 16:41:13 +0800228int mtk_mmd_read(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg)
developerc3ac93d2018-12-20 16:12:53 +0800229{
230 int ret;
231
232 ret = mtk_mii_rw(priv, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
233 if (ret)
234 return ret;
235
236 return mtk_mii_rw(priv, addr, devad, 0, MDIO_CMD_READ_C45,
237 MDIO_ST_C45);
238}
239
240/* Direct MDIO clause 45 write via SoC */
developer29d9d9f2025-01-10 16:41:13 +0800241int mtk_mmd_write(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg,
242 u16 val)
developerc3ac93d2018-12-20 16:12:53 +0800243{
244 int ret;
245
246 ret = mtk_mii_rw(priv, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
247 if (ret)
248 return ret;
249
250 return mtk_mii_rw(priv, addr, devad, val, MDIO_CMD_WRITE,
251 MDIO_ST_C45);
252}
253
254/* Indirect MDIO clause 45 read via MII registers */
developer29d9d9f2025-01-10 16:41:13 +0800255int mtk_mmd_ind_read(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg)
developerc3ac93d2018-12-20 16:12:53 +0800256{
257 int ret;
258
developer29d9d9f2025-01-10 16:41:13 +0800259 ret = mtk_mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
260 (MMD_ADDR << MMD_CMD_S) |
261 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
developerc3ac93d2018-12-20 16:12:53 +0800262 if (ret)
263 return ret;
264
developer29d9d9f2025-01-10 16:41:13 +0800265 ret = mtk_mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, reg);
developerc3ac93d2018-12-20 16:12:53 +0800266 if (ret)
267 return ret;
268
developer29d9d9f2025-01-10 16:41:13 +0800269 ret = mtk_mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
270 (MMD_DATA << MMD_CMD_S) |
271 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
developerc3ac93d2018-12-20 16:12:53 +0800272 if (ret)
273 return ret;
274
developer29d9d9f2025-01-10 16:41:13 +0800275 return mtk_mii_read(priv, addr, MII_MMD_ADDR_DATA_REG);
developerc3ac93d2018-12-20 16:12:53 +0800276}
277
278/* Indirect MDIO clause 45 write via MII registers */
developer29d9d9f2025-01-10 16:41:13 +0800279int mtk_mmd_ind_write(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg,
280 u16 val)
developerd5d73952020-02-18 16:49:37 +0800281{
282 int ret;
283
developer29d9d9f2025-01-10 16:41:13 +0800284 ret = mtk_mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
285 (MMD_ADDR << MMD_CMD_S) |
286 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
developerd5d73952020-02-18 16:49:37 +0800287 if (ret)
288 return ret;
289
developer29d9d9f2025-01-10 16:41:13 +0800290 ret = mtk_mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, reg);
developerd5d73952020-02-18 16:49:37 +0800291 if (ret)
292 return ret;
293
developer29d9d9f2025-01-10 16:41:13 +0800294 ret = mtk_mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
295 (MMD_DATA << MMD_CMD_S) |
296 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
developerd5d73952020-02-18 16:49:37 +0800297 if (ret)
298 return ret;
299
developer29d9d9f2025-01-10 16:41:13 +0800300 return mtk_mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, val);
developerd5d73952020-02-18 16:49:37 +0800301}
302
developerc3ac93d2018-12-20 16:12:53 +0800303static int mtk_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
304{
305 struct mtk_eth_priv *priv = bus->priv;
306
307 if (devad < 0)
developer29d9d9f2025-01-10 16:41:13 +0800308 return mtk_mii_read(priv, addr, reg);
309
310 return mtk_mmd_read(priv, addr, devad, reg);
developerc3ac93d2018-12-20 16:12:53 +0800311}
312
313static int mtk_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
314 u16 val)
315{
316 struct mtk_eth_priv *priv = bus->priv;
317
318 if (devad < 0)
developer29d9d9f2025-01-10 16:41:13 +0800319 return mtk_mii_write(priv, addr, reg, val);
320
321 return mtk_mmd_write(priv, addr, devad, reg, val);
developerc3ac93d2018-12-20 16:12:53 +0800322}
323
324static int mtk_mdio_register(struct udevice *dev)
325{
326 struct mtk_eth_priv *priv = dev_get_priv(dev);
327 struct mii_dev *mdio_bus = mdio_alloc();
328 int ret;
329
330 if (!mdio_bus)
331 return -ENOMEM;
332
developerc3ac93d2018-12-20 16:12:53 +0800333 mdio_bus->read = mtk_mdio_read;
334 mdio_bus->write = mtk_mdio_write;
335 snprintf(mdio_bus->name, sizeof(mdio_bus->name), dev->name);
336
337 mdio_bus->priv = (void *)priv;
338
339 ret = mdio_register(mdio_bus);
340
341 if (ret)
342 return ret;
343
344 priv->mdio_bus = mdio_bus;
345
346 return 0;
347}
348
developer29d9d9f2025-01-10 16:41:13 +0800349static int mtk_switch_init(struct mtk_eth_priv *priv)
developer76e14722023-07-19 17:17:41 +0800350{
developer29d9d9f2025-01-10 16:41:13 +0800351 struct mtk_eth_switch *swdrvs = ll_entry_start(struct mtk_eth_switch,
352 mtk_eth_switch);
353 const u32 n_swdrvs = ll_entry_count(struct mtk_eth_switch,
354 mtk_eth_switch);
355 struct mtk_eth_switch *tmp, *swdrv = NULL;
356 u32 reset_wait_time = 500;
357 size_t priv_size;
358 int ret;
developer76e14722023-07-19 17:17:41 +0800359
developer29d9d9f2025-01-10 16:41:13 +0800360 if (strcmp(priv->swname, "auto")) {
361 for (tmp = swdrvs; tmp < swdrvs + n_swdrvs; tmp++) {
362 if (!strcmp(tmp->name, priv->swname)) {
363 swdrv = tmp;
364 break;
365 }
366 }
developer76e14722023-07-19 17:17:41 +0800367 }
368
developer29d9d9f2025-01-10 16:41:13 +0800369 if (swdrv)
370 reset_wait_time = swdrv->reset_wait_time;
developerd5d73952020-02-18 16:49:37 +0800371
372 /* Global reset switch */
373 if (priv->mcm) {
374 reset_assert(&priv->rst_mcm);
375 udelay(1000);
376 reset_deassert(&priv->rst_mcm);
developer29d9d9f2025-01-10 16:41:13 +0800377 mdelay(reset_wait_time);
developerd5d73952020-02-18 16:49:37 +0800378 } else if (dm_gpio_is_valid(&priv->rst_gpio)) {
379 dm_gpio_set_value(&priv->rst_gpio, 0);
380 udelay(1000);
381 dm_gpio_set_value(&priv->rst_gpio, 1);
developer29d9d9f2025-01-10 16:41:13 +0800382 mdelay(reset_wait_time);
developerd5d73952020-02-18 16:49:37 +0800383 }
384
developer29d9d9f2025-01-10 16:41:13 +0800385 if (!swdrv) {
386 for (tmp = swdrvs; tmp < swdrvs + n_swdrvs; tmp++) {
387 if (!tmp->detect)
388 continue;
developerd5d73952020-02-18 16:49:37 +0800389
developer29d9d9f2025-01-10 16:41:13 +0800390 ret = tmp->detect(priv);
391 if (!ret) {
392 swdrv = tmp;
393 break;
394 }
395 }
396
397 if (!swdrv) {
398 printf("Error: unable to detect switch\n");
399 return -ENODEV;
400 }
401 } else {
402 if (swdrv->detect) {
403 ret = swdrv->detect(priv);
404 if (ret) {
405 printf("Error: switch probing failed\n");
406 return -ENODEV;
407 }
408 }
409 }
developerc3ac93d2018-12-20 16:12:53 +0800410
developer29d9d9f2025-01-10 16:41:13 +0800411 printf("%s\n", swdrv->desc);
412
413 priv_size = swdrv->priv_size;
414 if (priv_size < sizeof(struct mtk_eth_switch_priv))
415 priv_size = sizeof(struct mtk_eth_switch_priv);
416
417 priv->swpriv = calloc(1, priv_size);
418 if (!priv->swpriv) {
419 printf("Error: no memory for switch data\n");
420 return -ENOMEM;
developerc3ac93d2018-12-20 16:12:53 +0800421 }
422
developer29d9d9f2025-01-10 16:41:13 +0800423 priv->swpriv->eth = priv;
424 priv->swpriv->soc = priv->soc;
425 priv->swpriv->phy_interface = priv->phy_interface;
426 priv->swpriv->sw = swdrv;
427 priv->swpriv->ethsys_base = regmap_get_range(priv->ethsys_regmap, 0);
428
429 ret = swdrv->setup(priv->swpriv);
430 if (ret) {
431 free(priv->swpriv);
432 priv->swpriv = NULL;
433 return ret;
434 }
435
developerc3ac93d2018-12-20 16:12:53 +0800436 return 0;
437}
438
developer03ce27b2023-07-19 17:17:31 +0800439static void mtk_xphy_link_adjust(struct mtk_eth_priv *priv)
440{
441 u16 lcl_adv = 0, rmt_adv = 0;
442 u8 flowctrl;
443 u32 mcr;
444
445 mcr = mtk_gmac_read(priv, XGMAC_PORT_MCR(priv->gmac_id));
446 mcr &= ~(XGMAC_FORCE_TX_FC | XGMAC_FORCE_RX_FC);
447
448 if (priv->phydev->duplex) {
449 if (priv->phydev->pause)
450 rmt_adv = LPA_PAUSE_CAP;
451 if (priv->phydev->asym_pause)
452 rmt_adv |= LPA_PAUSE_ASYM;
453
454 if (priv->phydev->advertising & ADVERTISED_Pause)
455 lcl_adv |= ADVERTISE_PAUSE_CAP;
456 if (priv->phydev->advertising & ADVERTISED_Asym_Pause)
457 lcl_adv |= ADVERTISE_PAUSE_ASYM;
458
459 flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
460
461 if (flowctrl & FLOW_CTRL_TX)
462 mcr |= XGMAC_FORCE_TX_FC;
463 if (flowctrl & FLOW_CTRL_RX)
464 mcr |= XGMAC_FORCE_RX_FC;
465
466 debug("rx pause %s, tx pause %s\n",
467 flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
468 flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
469 }
470
471 mcr &= ~(XGMAC_TRX_DISABLE);
472 mtk_gmac_write(priv, XGMAC_PORT_MCR(priv->gmac_id), mcr);
473}
474
developerc3ac93d2018-12-20 16:12:53 +0800475static void mtk_phy_link_adjust(struct mtk_eth_priv *priv)
476{
477 u16 lcl_adv = 0, rmt_adv = 0;
478 u8 flowctrl;
479 u32 mcr;
480
developerd5d73952020-02-18 16:49:37 +0800481 mcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
developerc3ac93d2018-12-20 16:12:53 +0800482 (MAC_RX_PKT_LEN_1536 << MAC_RX_PKT_LEN_S) |
483 MAC_MODE | FORCE_MODE |
484 MAC_TX_EN | MAC_RX_EN |
developer4aafc992023-07-19 17:17:13 +0800485 DEL_RXFIFO_CLR |
developerc3ac93d2018-12-20 16:12:53 +0800486 BKOFF_EN | BACKPR_EN;
487
488 switch (priv->phydev->speed) {
489 case SPEED_10:
490 mcr |= (SPEED_10M << FORCE_SPD_S);
491 break;
492 case SPEED_100:
493 mcr |= (SPEED_100M << FORCE_SPD_S);
494 break;
495 case SPEED_1000:
developer4aafc992023-07-19 17:17:13 +0800496 case SPEED_2500:
developerc3ac93d2018-12-20 16:12:53 +0800497 mcr |= (SPEED_1000M << FORCE_SPD_S);
498 break;
499 };
500
501 if (priv->phydev->link)
502 mcr |= FORCE_LINK;
503
504 if (priv->phydev->duplex) {
505 mcr |= FORCE_DPX;
506
507 if (priv->phydev->pause)
508 rmt_adv = LPA_PAUSE_CAP;
509 if (priv->phydev->asym_pause)
510 rmt_adv |= LPA_PAUSE_ASYM;
511
512 if (priv->phydev->advertising & ADVERTISED_Pause)
513 lcl_adv |= ADVERTISE_PAUSE_CAP;
514 if (priv->phydev->advertising & ADVERTISED_Asym_Pause)
515 lcl_adv |= ADVERTISE_PAUSE_ASYM;
516
517 flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
518
519 if (flowctrl & FLOW_CTRL_TX)
520 mcr |= FORCE_TX_FC;
521 if (flowctrl & FLOW_CTRL_RX)
522 mcr |= FORCE_RX_FC;
523
524 debug("rx pause %s, tx pause %s\n",
525 flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
526 flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
527 }
528
529 mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr);
530}
531
532static int mtk_phy_start(struct mtk_eth_priv *priv)
533{
534 struct phy_device *phydev = priv->phydev;
535 int ret;
536
537 ret = phy_startup(phydev);
538
539 if (ret) {
540 debug("Could not initialize PHY %s\n", phydev->dev->name);
541 return ret;
542 }
543
544 if (!phydev->link) {
545 debug("%s: link down.\n", phydev->dev->name);
546 return 0;
547 }
548
developer03ce27b2023-07-19 17:17:31 +0800549 if (!priv->force_mode) {
developeref7b6502024-01-22 10:08:16 +0800550 if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
developer7fe0b3c2024-12-17 16:39:50 +0800551 priv->phy_interface == PHY_INTERFACE_MODE_10GBASER ||
developeref7b6502024-01-22 10:08:16 +0800552 priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
developer03ce27b2023-07-19 17:17:31 +0800553 mtk_xphy_link_adjust(priv);
554 else
555 mtk_phy_link_adjust(priv);
556 }
developerc3ac93d2018-12-20 16:12:53 +0800557
558 debug("Speed: %d, %s duplex%s\n", phydev->speed,
559 (phydev->duplex) ? "full" : "half",
560 (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
561
562 return 0;
563}
564
565static int mtk_phy_probe(struct udevice *dev)
566{
567 struct mtk_eth_priv *priv = dev_get_priv(dev);
568 struct phy_device *phydev;
569
570 phydev = phy_connect(priv->mdio_bus, priv->phy_addr, dev,
571 priv->phy_interface);
572 if (!phydev)
573 return -ENODEV;
574
575 phydev->supported &= PHY_GBIT_FEATURES;
576 phydev->advertising = phydev->supported;
577
578 priv->phydev = phydev;
579 phy_config(phydev);
580
581 return 0;
582}
583
developer4aafc992023-07-19 17:17:13 +0800584static void mtk_sgmii_an_init(struct mtk_eth_priv *priv)
585{
586 /* Set SGMII GEN1 speed(1G) */
developer0535efd2024-12-17 16:39:23 +0800587 clrbits_le32(priv->sgmii_base + priv->soc->ana_rgc3, SGMSYS_SPEED_MASK);
developer4aafc992023-07-19 17:17:13 +0800588
589 /* Enable SGMII AN */
590 setbits_le32(priv->sgmii_base + SGMSYS_PCS_CONTROL_1,
591 SGMII_AN_ENABLE);
592
593 /* SGMII AN mode setting */
594 writel(SGMII_AN_MODE, priv->sgmii_base + SGMSYS_SGMII_MODE);
595
596 /* SGMII PN SWAP setting */
597 if (priv->pn_swap) {
598 setbits_le32(priv->sgmii_base + SGMSYS_QPHY_WRAP_CTRL,
599 SGMII_PN_SWAP_TX_RX);
600 }
601
602 /* Release PHYA power down state */
603 clrsetbits_le32(priv->sgmii_base + SGMSYS_QPHY_PWR_STATE_CTRL,
604 SGMII_PHYA_PWD, 0);
605}
606
607static void mtk_sgmii_force_init(struct mtk_eth_priv *priv)
developer9a12c242020-01-21 19:31:57 +0800608{
609 /* Set SGMII GEN2 speed(2.5G) */
developer0535efd2024-12-17 16:39:23 +0800610 clrsetbits_le32(priv->sgmii_base + priv->soc->ana_rgc3,
611 SGMSYS_SPEED_MASK,
612 FIELD_PREP(SGMSYS_SPEED_MASK, SGMSYS_SPEED_2500));
developer9a12c242020-01-21 19:31:57 +0800613
614 /* Disable SGMII AN */
615 clrsetbits_le32(priv->sgmii_base + SGMSYS_PCS_CONTROL_1,
616 SGMII_AN_ENABLE, 0);
617
618 /* SGMII force mode setting */
619 writel(SGMII_FORCE_MODE, priv->sgmii_base + SGMSYS_SGMII_MODE);
620
developer053929c2022-09-09 19:59:28 +0800621 /* SGMII PN SWAP setting */
622 if (priv->pn_swap) {
623 setbits_le32(priv->sgmii_base + SGMSYS_QPHY_WRAP_CTRL,
624 SGMII_PN_SWAP_TX_RX);
625 }
626
developer9a12c242020-01-21 19:31:57 +0800627 /* Release PHYA power down state */
628 clrsetbits_le32(priv->sgmii_base + SGMSYS_QPHY_PWR_STATE_CTRL,
629 SGMII_PHYA_PWD, 0);
630}
631
developer03ce27b2023-07-19 17:17:31 +0800632static void mtk_xfi_pll_enable(struct mtk_eth_priv *priv)
633{
634 u32 val = 0;
635
636 /* Add software workaround for USXGMII PLL TCL issue */
637 regmap_write(priv->xfi_pll_regmap, XFI_PLL_ANA_GLB8,
638 RG_XFI_PLL_ANA_SWWA);
639
640 regmap_read(priv->xfi_pll_regmap, XFI_PLL_DIG_GLB8, &val);
641 val |= RG_XFI_PLL_EN;
642 regmap_write(priv->xfi_pll_regmap, XFI_PLL_DIG_GLB8, val);
643}
644
645static void mtk_usxgmii_reset(struct mtk_eth_priv *priv)
646{
647 switch (priv->gmac_id) {
648 case 1:
649 regmap_write(priv->toprgu_regmap, 0xFC, 0x0000A004);
650 regmap_write(priv->toprgu_regmap, 0x18, 0x88F0A004);
651 regmap_write(priv->toprgu_regmap, 0xFC, 0x00000000);
652 regmap_write(priv->toprgu_regmap, 0x18, 0x88F00000);
653 regmap_write(priv->toprgu_regmap, 0x18, 0x00F00000);
654 break;
655 case 2:
656 regmap_write(priv->toprgu_regmap, 0xFC, 0x00005002);
657 regmap_write(priv->toprgu_regmap, 0x18, 0x88F05002);
658 regmap_write(priv->toprgu_regmap, 0xFC, 0x00000000);
659 regmap_write(priv->toprgu_regmap, 0x18, 0x88F00000);
660 regmap_write(priv->toprgu_regmap, 0x18, 0x00F00000);
661 break;
662 }
663
664 mdelay(10);
665}
666
667static void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth_priv *priv)
668{
669 regmap_write(priv->usxgmii_regmap, 0x810, 0x000FFE6D);
670 regmap_write(priv->usxgmii_regmap, 0x818, 0x07B1EC7B);
671 regmap_write(priv->usxgmii_regmap, 0x80C, 0x30000000);
672 ndelay(1020);
673 regmap_write(priv->usxgmii_regmap, 0x80C, 0x10000000);
674 ndelay(1020);
675 regmap_write(priv->usxgmii_regmap, 0x80C, 0x00000000);
676
677 regmap_write(priv->xfi_pextp_regmap, 0x9024, 0x00C9071C);
678 regmap_write(priv->xfi_pextp_regmap, 0x2020, 0xAA8585AA);
679 regmap_write(priv->xfi_pextp_regmap, 0x2030, 0x0C020707);
680 regmap_write(priv->xfi_pextp_regmap, 0x2034, 0x0E050F0F);
681 regmap_write(priv->xfi_pextp_regmap, 0x2040, 0x00140032);
682 regmap_write(priv->xfi_pextp_regmap, 0x50F0, 0x00C014AA);
683 regmap_write(priv->xfi_pextp_regmap, 0x50E0, 0x3777C12B);
684 regmap_write(priv->xfi_pextp_regmap, 0x506C, 0x005F9CFF);
685 regmap_write(priv->xfi_pextp_regmap, 0x5070, 0x9D9DFAFA);
686 regmap_write(priv->xfi_pextp_regmap, 0x5074, 0x27273F3F);
687 regmap_write(priv->xfi_pextp_regmap, 0x5078, 0xA7883C68);
688 regmap_write(priv->xfi_pextp_regmap, 0x507C, 0x11661166);
689 regmap_write(priv->xfi_pextp_regmap, 0x5080, 0x0E000AAF);
690 regmap_write(priv->xfi_pextp_regmap, 0x5084, 0x08080D0D);
691 regmap_write(priv->xfi_pextp_regmap, 0x5088, 0x02030909);
692 regmap_write(priv->xfi_pextp_regmap, 0x50E4, 0x0C0C0000);
693 regmap_write(priv->xfi_pextp_regmap, 0x50E8, 0x04040000);
694 regmap_write(priv->xfi_pextp_regmap, 0x50EC, 0x0F0F0C06);
695 regmap_write(priv->xfi_pextp_regmap, 0x50A8, 0x506E8C8C);
696 regmap_write(priv->xfi_pextp_regmap, 0x6004, 0x18190000);
697 regmap_write(priv->xfi_pextp_regmap, 0x00F8, 0x01423342);
698 regmap_write(priv->xfi_pextp_regmap, 0x00F4, 0x80201F20);
699 regmap_write(priv->xfi_pextp_regmap, 0x0030, 0x00050C00);
700 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x02002800);
701 ndelay(1020);
702 regmap_write(priv->xfi_pextp_regmap, 0x30B0, 0x00000020);
703 regmap_write(priv->xfi_pextp_regmap, 0x3028, 0x00008A01);
704 regmap_write(priv->xfi_pextp_regmap, 0x302C, 0x0000A884);
705 regmap_write(priv->xfi_pextp_regmap, 0x3024, 0x00083002);
706 regmap_write(priv->xfi_pextp_regmap, 0x3010, 0x00022220);
707 regmap_write(priv->xfi_pextp_regmap, 0x5064, 0x0F020A01);
708 regmap_write(priv->xfi_pextp_regmap, 0x50B4, 0x06100600);
709 regmap_write(priv->xfi_pextp_regmap, 0x3048, 0x40704000);
710 regmap_write(priv->xfi_pextp_regmap, 0x3050, 0xA8000000);
711 regmap_write(priv->xfi_pextp_regmap, 0x3054, 0x000000AA);
712 regmap_write(priv->xfi_pextp_regmap, 0x306C, 0x00000F00);
713 regmap_write(priv->xfi_pextp_regmap, 0xA060, 0x00040000);
714 regmap_write(priv->xfi_pextp_regmap, 0x90D0, 0x00000001);
715 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0200E800);
716 udelay(150);
717 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0200C111);
718 ndelay(1020);
719 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0200C101);
720 udelay(15);
721 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0202C111);
722 ndelay(1020);
723 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0202C101);
724 udelay(100);
725 regmap_write(priv->xfi_pextp_regmap, 0x30B0, 0x00000030);
726 regmap_write(priv->xfi_pextp_regmap, 0x00F4, 0x80201F00);
727 regmap_write(priv->xfi_pextp_regmap, 0x3040, 0x30000000);
728 udelay(400);
729}
730
developer7fe0b3c2024-12-17 16:39:50 +0800731static void mtk_usxgmii_setup_phya_force_10000(struct mtk_eth_priv *priv)
732{
733 regmap_write(priv->usxgmii_regmap, 0x810, 0x000FFE6C);
734 regmap_write(priv->usxgmii_regmap, 0x818, 0x07B1EC7B);
735 regmap_write(priv->usxgmii_regmap, 0x80C, 0xB0000000);
736 ndelay(1020);
737 regmap_write(priv->usxgmii_regmap, 0x80C, 0x90000000);
738 ndelay(1020);
739
740 regmap_write(priv->xfi_pextp_regmap, 0x9024, 0x00C9071C);
741 regmap_write(priv->xfi_pextp_regmap, 0x2020, 0xAA8585AA);
742 regmap_write(priv->xfi_pextp_regmap, 0x2030, 0x0C020707);
743 regmap_write(priv->xfi_pextp_regmap, 0x2034, 0x0E050F0F);
744 regmap_write(priv->xfi_pextp_regmap, 0x2040, 0x00140032);
745 regmap_write(priv->xfi_pextp_regmap, 0x50F0, 0x00C014AA);
746 regmap_write(priv->xfi_pextp_regmap, 0x50E0, 0x3777C12B);
747 regmap_write(priv->xfi_pextp_regmap, 0x506C, 0x005F9CFF);
748 regmap_write(priv->xfi_pextp_regmap, 0x5070, 0x9D9DFAFA);
749 regmap_write(priv->xfi_pextp_regmap, 0x5074, 0x27273F3F);
750 regmap_write(priv->xfi_pextp_regmap, 0x5078, 0xA7883C68);
751 regmap_write(priv->xfi_pextp_regmap, 0x507C, 0x11661166);
752 regmap_write(priv->xfi_pextp_regmap, 0x5080, 0x0E000AAF);
753 regmap_write(priv->xfi_pextp_regmap, 0x5084, 0x08080D0D);
754 regmap_write(priv->xfi_pextp_regmap, 0x5088, 0x02030909);
755 regmap_write(priv->xfi_pextp_regmap, 0x50E4, 0x0C0C0000);
756 regmap_write(priv->xfi_pextp_regmap, 0x50E8, 0x04040000);
757 regmap_write(priv->xfi_pextp_regmap, 0x50EC, 0x0F0F0C06);
758 regmap_write(priv->xfi_pextp_regmap, 0x50A8, 0x506E8C8C);
759 regmap_write(priv->xfi_pextp_regmap, 0x6004, 0x18190000);
760 regmap_write(priv->xfi_pextp_regmap, 0x00F8, 0x01423342);
761 regmap_write(priv->xfi_pextp_regmap, 0x00F4, 0x80201F20);
762 regmap_write(priv->xfi_pextp_regmap, 0x0030, 0x00050C00);
763 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x02002800);
764 ndelay(1020);
765 regmap_write(priv->xfi_pextp_regmap, 0x30B0, 0x00000020);
766 regmap_write(priv->xfi_pextp_regmap, 0x3028, 0x00008A01);
767 regmap_write(priv->xfi_pextp_regmap, 0x302C, 0x0000A884);
768 regmap_write(priv->xfi_pextp_regmap, 0x3024, 0x00083002);
769 regmap_write(priv->xfi_pextp_regmap, 0x3010, 0x00022220);
770 regmap_write(priv->xfi_pextp_regmap, 0x5064, 0x0F020A01);
771 regmap_write(priv->xfi_pextp_regmap, 0x50B4, 0x06100600);
772 regmap_write(priv->xfi_pextp_regmap, 0x3048, 0x47684100);
773 regmap_write(priv->xfi_pextp_regmap, 0x3050, 0x00000000);
774 regmap_write(priv->xfi_pextp_regmap, 0x3054, 0x00000000);
775 regmap_write(priv->xfi_pextp_regmap, 0x306C, 0x00000F00);
776 if (priv->gmac_id == 2)
777 regmap_write(priv->xfi_pextp_regmap, 0xA008, 0x0007B400);
778 regmap_write(priv->xfi_pextp_regmap, 0xA060, 0x00040000);
779 regmap_write(priv->xfi_pextp_regmap, 0x90D0, 0x00000001);
780 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0200E800);
781 udelay(150);
782 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0200C111);
783 ndelay(1020);
784 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0200C101);
785 udelay(15);
786 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0202C111);
787 ndelay(1020);
788 regmap_write(priv->xfi_pextp_regmap, 0x0070, 0x0202C101);
789 udelay(100);
790 regmap_write(priv->xfi_pextp_regmap, 0x30B0, 0x00000030);
791 regmap_write(priv->xfi_pextp_regmap, 0x00F4, 0x80201F00);
792 regmap_write(priv->xfi_pextp_regmap, 0x3040, 0x30000000);
793 udelay(400);
794}
795
developer03ce27b2023-07-19 17:17:31 +0800796static void mtk_usxgmii_an_init(struct mtk_eth_priv *priv)
797{
798 mtk_xfi_pll_enable(priv);
799 mtk_usxgmii_reset(priv);
800 mtk_usxgmii_setup_phya_an_10000(priv);
801}
802
developer7fe0b3c2024-12-17 16:39:50 +0800803static void mtk_10gbaser_init(struct mtk_eth_priv *priv)
804{
805 mtk_xfi_pll_enable(priv);
806 mtk_usxgmii_reset(priv);
807 mtk_usxgmii_setup_phya_force_10000(priv);
808}
809
developera2a01412024-12-17 16:39:55 +0800810static int mtk_mac_init(struct mtk_eth_priv *priv)
developerc3ac93d2018-12-20 16:12:53 +0800811{
developer2da7d4a2024-12-17 16:39:41 +0800812 int i, sgmii_sel_mask = 0, ge_mode = 0;
developerc3ac93d2018-12-20 16:12:53 +0800813 u32 mcr;
814
developere8f42692024-12-17 16:39:46 +0800815 if (MTK_HAS_CAPS(priv->soc->caps, MTK_ETH_PATH_MT7629_GMAC2)) {
816 mtk_infra_rmw(priv, MT7629_INFRA_MISC2_REG,
817 INFRA_MISC2_BONDING_OPTION, priv->gmac_id);
818 }
819
developerc3ac93d2018-12-20 16:12:53 +0800820 switch (priv->phy_interface) {
821 case PHY_INTERFACE_MODE_RGMII_RXID:
822 case PHY_INTERFACE_MODE_RGMII:
developer9a12c242020-01-21 19:31:57 +0800823 ge_mode = GE_MODE_RGMII;
824 break;
developerc3ac93d2018-12-20 16:12:53 +0800825 case PHY_INTERFACE_MODE_SGMII:
developer4aafc992023-07-19 17:17:13 +0800826 case PHY_INTERFACE_MODE_2500BASEX:
developera2a01412024-12-17 16:39:55 +0800827 if (!IS_ENABLED(CONFIG_MTK_ETH_SGMII)) {
828 printf("Error: SGMII is not supported on this platform\n");
829 return -ENOTSUPP;
830 }
831
developera5d712a2023-07-19 17:17:22 +0800832 if (MTK_HAS_CAPS(priv->soc->caps, MTK_GMAC2_U3_QPHY)) {
833 mtk_infra_rmw(priv, USB_PHY_SWITCH_REG, QPHY_SEL_MASK,
834 SGMII_QPHY_SEL);
835 }
836
developer2da7d4a2024-12-17 16:39:41 +0800837 if (MTK_HAS_CAPS(priv->soc->caps, MTK_ETH_PATH_MT7622_SGMII))
838 sgmii_sel_mask = SYSCFG1_SGMII_SEL_M;
839
840 mtk_ethsys_rmw(priv, ETHSYS_SYSCFG1_REG, sgmii_sel_mask,
developer0b584952024-12-17 16:39:27 +0800841 SYSCFG1_SGMII_SEL(priv->gmac_id));
developer2da7d4a2024-12-17 16:39:41 +0800842
developer4aafc992023-07-19 17:17:13 +0800843 if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
844 mtk_sgmii_an_init(priv);
845 else
846 mtk_sgmii_force_init(priv);
developera2a01412024-12-17 16:39:55 +0800847
848 ge_mode = GE_MODE_RGMII;
developerc3ac93d2018-12-20 16:12:53 +0800849 break;
850 case PHY_INTERFACE_MODE_MII:
851 case PHY_INTERFACE_MODE_GMII:
852 ge_mode = GE_MODE_MII;
853 break;
854 case PHY_INTERFACE_MODE_RMII:
855 ge_mode = GE_MODE_RMII;
856 break;
857 default:
858 break;
859 }
860
861 /* set the gmac to the right mode */
developer0b584952024-12-17 16:39:27 +0800862 mtk_ethsys_rmw(priv, ETHSYS_SYSCFG1_REG,
863 SYSCFG1_GE_MODE_M << SYSCFG1_GE_MODE_S(priv->gmac_id),
864 ge_mode << SYSCFG1_GE_MODE_S(priv->gmac_id));
developerc3ac93d2018-12-20 16:12:53 +0800865
866 if (priv->force_mode) {
developerd5d73952020-02-18 16:49:37 +0800867 mcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
developerc3ac93d2018-12-20 16:12:53 +0800868 (MAC_RX_PKT_LEN_1536 << MAC_RX_PKT_LEN_S) |
869 MAC_MODE | FORCE_MODE |
870 MAC_TX_EN | MAC_RX_EN |
871 BKOFF_EN | BACKPR_EN |
872 FORCE_LINK;
873
874 switch (priv->speed) {
875 case SPEED_10:
876 mcr |= SPEED_10M << FORCE_SPD_S;
877 break;
878 case SPEED_100:
879 mcr |= SPEED_100M << FORCE_SPD_S;
880 break;
881 case SPEED_1000:
developer4aafc992023-07-19 17:17:13 +0800882 case SPEED_2500:
developerc3ac93d2018-12-20 16:12:53 +0800883 mcr |= SPEED_1000M << FORCE_SPD_S;
884 break;
885 }
886
887 if (priv->duplex)
888 mcr |= FORCE_DPX;
889
890 mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr);
891 }
892
developer1d3b1f62022-09-09 19:59:21 +0800893 if (MTK_HAS_CAPS(priv->soc->caps, MTK_GMAC1_TRGMII) &&
894 !MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) {
developerc3ac93d2018-12-20 16:12:53 +0800895 /* Lower Tx Driving for TRGMII path */
896 for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
897 mtk_gmac_write(priv, GMAC_TRGMII_TD_ODT(i),
898 (8 << TD_DM_DRVP_S) |
899 (8 << TD_DM_DRVN_S));
900
901 mtk_gmac_rmw(priv, GMAC_TRGMII_RCK_CTRL, 0,
902 RX_RST | RXC_DQSISEL);
903 mtk_gmac_rmw(priv, GMAC_TRGMII_RCK_CTRL, RX_RST, 0);
904 }
developera2a01412024-12-17 16:39:55 +0800905
906 return 0;
developer03ce27b2023-07-19 17:17:31 +0800907}
908
developera2a01412024-12-17 16:39:55 +0800909static int mtk_xmac_init(struct mtk_eth_priv *priv)
developer03ce27b2023-07-19 17:17:31 +0800910{
developeref7b6502024-01-22 10:08:16 +0800911 u32 force_link = 0;
developer03ce27b2023-07-19 17:17:31 +0800912
developera2a01412024-12-17 16:39:55 +0800913 if (!IS_ENABLED(CONFIG_MTK_ETH_XGMII)) {
914 printf("Error: 10Gb interface is not supported on this platform\n");
915 return -ENOTSUPP;
916 }
917
developer03ce27b2023-07-19 17:17:31 +0800918 switch (priv->phy_interface) {
919 case PHY_INTERFACE_MODE_USXGMII:
920 mtk_usxgmii_an_init(priv);
921 break;
developer7fe0b3c2024-12-17 16:39:50 +0800922 case PHY_INTERFACE_MODE_10GBASER:
923 mtk_10gbaser_init(priv);
924 break;
developer03ce27b2023-07-19 17:17:31 +0800925 default:
926 break;
927 }
928
929 /* Set GMAC to the correct mode */
developer0b584952024-12-17 16:39:27 +0800930 mtk_ethsys_rmw(priv, ETHSYS_SYSCFG1_REG,
931 SYSCFG1_GE_MODE_M << SYSCFG1_GE_MODE_S(priv->gmac_id),
developer03ce27b2023-07-19 17:17:31 +0800932 0);
933
developer7fe0b3c2024-12-17 16:39:50 +0800934 if ((priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
935 priv->phy_interface == PHY_INTERFACE_MODE_10GBASER) &&
developeref7b6502024-01-22 10:08:16 +0800936 priv->gmac_id == 1) {
developer03ce27b2023-07-19 17:17:31 +0800937 mtk_infra_rmw(priv, TOPMISC_NETSYS_PCS_MUX,
938 NETSYS_PCS_MUX_MASK, MUX_G2_USXGMII_SEL);
developer03ce27b2023-07-19 17:17:31 +0800939 }
940
developeref7b6502024-01-22 10:08:16 +0800941 if (priv->phy_interface == PHY_INTERFACE_MODE_XGMII ||
942 priv->gmac_id == 2)
943 force_link = XGMAC_FORCE_LINK(priv->gmac_id);
944
945 mtk_gmac_rmw(priv, XGMAC_STS(priv->gmac_id),
946 XGMAC_FORCE_LINK(priv->gmac_id), force_link);
947
developer03ce27b2023-07-19 17:17:31 +0800948 /* Force GMAC link down */
949 mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), FORCE_MODE);
developera2a01412024-12-17 16:39:55 +0800950
951 return 0;
developerc3ac93d2018-12-20 16:12:53 +0800952}
953
954static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
955{
956 char *pkt_base = priv->pkt_pool;
developera7cdebf2022-09-09 19:59:26 +0800957 struct mtk_tx_dma_v2 *txd;
958 struct mtk_rx_dma_v2 *rxd;
developerc3ac93d2018-12-20 16:12:53 +0800959 int i;
960
961 mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0);
962 udelay(500);
963
developer65089f72022-09-09 19:59:24 +0800964 memset(priv->tx_ring_noc, 0, NUM_TX_DESC * priv->soc->txd_size);
965 memset(priv->rx_ring_noc, 0, NUM_RX_DESC * priv->soc->rxd_size);
966 memset(priv->pkt_pool, 0xff, TOTAL_PKT_BUF_SIZE);
developerc3ac93d2018-12-20 16:12:53 +0800967
Frank Wunderlich44350182020-01-31 10:23:29 +0100968 flush_dcache_range((ulong)pkt_base,
969 (ulong)(pkt_base + TOTAL_PKT_BUF_SIZE));
developerc3ac93d2018-12-20 16:12:53 +0800970
971 priv->rx_dma_owner_idx0 = 0;
972 priv->tx_cpu_owner_idx0 = 0;
973
974 for (i = 0; i < NUM_TX_DESC; i++) {
developer65089f72022-09-09 19:59:24 +0800975 txd = priv->tx_ring_noc + i * priv->soc->txd_size;
developerc3ac93d2018-12-20 16:12:53 +0800976
developer65089f72022-09-09 19:59:24 +0800977 txd->txd1 = virt_to_phys(pkt_base);
978 txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0;
developera7cdebf2022-09-09 19:59:26 +0800979
developer78fed682023-07-19 17:17:37 +0800980 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
981 txd->txd5 = PDMA_V2_TXD5_FPORT_SET(priv->gmac_id == 2 ?
982 15 : priv->gmac_id + 1);
983 else if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2))
developera7cdebf2022-09-09 19:59:26 +0800984 txd->txd5 = PDMA_V2_TXD5_FPORT_SET(priv->gmac_id + 1);
985 else
986 txd->txd4 = PDMA_V1_TXD4_FPORT_SET(priv->gmac_id + 1);
developer65089f72022-09-09 19:59:24 +0800987
developerc3ac93d2018-12-20 16:12:53 +0800988 pkt_base += PKTSIZE_ALIGN;
989 }
990
991 for (i = 0; i < NUM_RX_DESC; i++) {
developer65089f72022-09-09 19:59:24 +0800992 rxd = priv->rx_ring_noc + i * priv->soc->rxd_size;
993
994 rxd->rxd1 = virt_to_phys(pkt_base);
developera7cdebf2022-09-09 19:59:26 +0800995
developer78fed682023-07-19 17:17:37 +0800996 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2) ||
997 MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
developera7cdebf2022-09-09 19:59:26 +0800998 rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
999 else
1000 rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
developer65089f72022-09-09 19:59:24 +08001001
developerc3ac93d2018-12-20 16:12:53 +08001002 pkt_base += PKTSIZE_ALIGN;
1003 }
1004
1005 mtk_pdma_write(priv, TX_BASE_PTR_REG(0),
1006 virt_to_phys(priv->tx_ring_noc));
1007 mtk_pdma_write(priv, TX_MAX_CNT_REG(0), NUM_TX_DESC);
1008 mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
1009
1010 mtk_pdma_write(priv, RX_BASE_PTR_REG(0),
1011 virt_to_phys(priv->rx_ring_noc));
1012 mtk_pdma_write(priv, RX_MAX_CNT_REG(0), NUM_RX_DESC);
1013 mtk_pdma_write(priv, RX_CRX_IDX_REG(0), NUM_RX_DESC - 1);
1014
1015 mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0);
1016}
1017
developer4843ad32024-01-22 10:08:11 +08001018static void mtk_eth_mdc_init(struct mtk_eth_priv *priv)
1019{
1020 u32 divider;
1021
1022 if (priv->mdc == 0)
1023 return;
1024
1025 divider = min_t(u32, DIV_ROUND_UP(MDC_MAX_FREQ, priv->mdc), MDC_MAX_DIVIDER);
1026
1027 /* Configure MDC turbo mode */
1028 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
1029 mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, MISC_MDC_TURBO);
1030 else
1031 mtk_gmac_rmw(priv, GMAC_PPSC_REG, 0, MISC_MDC_TURBO);
1032
1033 /* Configure MDC divider */
1034 mtk_gmac_rmw(priv, GMAC_PPSC_REG, PHY_MDC_CFG,
1035 FIELD_PREP(PHY_MDC_CFG, divider));
1036}
1037
developerc3ac93d2018-12-20 16:12:53 +08001038static int mtk_eth_start(struct udevice *dev)
1039{
1040 struct mtk_eth_priv *priv = dev_get_priv(dev);
developer78fed682023-07-19 17:17:37 +08001041 int i, ret;
developerc3ac93d2018-12-20 16:12:53 +08001042
1043 /* Reset FE */
1044 reset_assert(&priv->rst_fe);
1045 udelay(1000);
1046 reset_deassert(&priv->rst_fe);
1047 mdelay(10);
1048
developer78fed682023-07-19 17:17:37 +08001049 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2) ||
1050 MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
developera7cdebf2022-09-09 19:59:26 +08001051 setbits_le32(priv->fe_base + FE_GLO_MISC_REG, PDMA_VER_V2);
1052
developerc3ac93d2018-12-20 16:12:53 +08001053 /* Packets forward to PDMA */
1054 mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG, GDMA_FWD_TO_CPU);
1055
developer78fed682023-07-19 17:17:37 +08001056 for (i = 0; i < priv->soc->gdma_count; i++) {
1057 if (i == priv->gmac_id)
1058 continue;
1059
1060 mtk_gdma_write(priv, i, GDMA_IG_CTRL_REG, GDMA_FWD_DISCARD);
1061 }
1062
1063 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3)) {
developer29d9d9f2025-01-10 16:41:13 +08001064 if (priv->swpriv && !strcmp(priv->swpriv->sw->name, "mt7988") &&
1065 priv->gmac_id == 0) {
developer76e14722023-07-19 17:17:41 +08001066 mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG,
1067 GDMA_BRIDGE_TO_CPU);
developer76e14722023-07-19 17:17:41 +08001068
developer46508642024-12-17 16:39:59 +08001069 mtk_gdma_write(priv, priv->gmac_id, GDMA_EG_CTRL_REG,
1070 GDMA_CPU_BRIDGE_EN);
1071 } else if ((priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
1072 priv->phy_interface == PHY_INTERFACE_MODE_10GBASER ||
1073 priv->phy_interface == PHY_INTERFACE_MODE_XGMII) &&
1074 priv->gmac_id != 0) {
1075 mtk_gdma_write(priv, priv->gmac_id, GDMA_EG_CTRL_REG,
1076 GDMA_CPU_BRIDGE_EN);
1077 }
developer78fed682023-07-19 17:17:37 +08001078 }
developerc3ac93d2018-12-20 16:12:53 +08001079
1080 udelay(500);
1081
1082 mtk_eth_fifo_init(priv);
1083
developer29d9d9f2025-01-10 16:41:13 +08001084 if (priv->swpriv) {
1085 /* Enable communication with switch */
1086 if (priv->swpriv->sw->mac_control)
1087 priv->swpriv->sw->mac_control(priv->swpriv, true);
1088 } else {
1089 /* Start PHY */
developerc3ac93d2018-12-20 16:12:53 +08001090 ret = mtk_phy_start(priv);
1091 if (ret)
1092 return ret;
1093 }
1094
1095 mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0,
1096 TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
1097 udelay(500);
1098
1099 return 0;
1100}
1101
1102static void mtk_eth_stop(struct udevice *dev)
1103{
1104 struct mtk_eth_priv *priv = dev_get_priv(dev);
1105
developer29d9d9f2025-01-10 16:41:13 +08001106 if (priv->swpriv) {
1107 if (priv->swpriv->sw->mac_control)
1108 priv->swpriv->sw->mac_control(priv->swpriv, false);
1109 }
developer08849652023-07-19 17:16:54 +08001110
developerc3ac93d2018-12-20 16:12:53 +08001111 mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG,
1112 TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN, 0);
1113 udelay(500);
1114
developera7cdebf2022-09-09 19:59:26 +08001115 wait_for_bit_le32(priv->fe_base + priv->soc->pdma_base + PDMA_GLO_CFG_REG,
developerc3ac93d2018-12-20 16:12:53 +08001116 RX_DMA_BUSY | TX_DMA_BUSY, 0, 5000, 0);
1117}
1118
1119static int mtk_eth_write_hwaddr(struct udevice *dev)
1120{
Simon Glassfa20e932020-12-03 16:55:20 -07001121 struct eth_pdata *pdata = dev_get_plat(dev);
developerc3ac93d2018-12-20 16:12:53 +08001122 struct mtk_eth_priv *priv = dev_get_priv(dev);
1123 unsigned char *mac = pdata->enetaddr;
1124 u32 macaddr_lsb, macaddr_msb;
1125
1126 macaddr_msb = ((u32)mac[0] << 8) | (u32)mac[1];
1127 macaddr_lsb = ((u32)mac[2] << 24) | ((u32)mac[3] << 16) |
1128 ((u32)mac[4] << 8) | (u32)mac[5];
1129
1130 mtk_gdma_write(priv, priv->gmac_id, GDMA_MAC_MSB_REG, macaddr_msb);
1131 mtk_gdma_write(priv, priv->gmac_id, GDMA_MAC_LSB_REG, macaddr_lsb);
1132
1133 return 0;
1134}
1135
1136static int mtk_eth_send(struct udevice *dev, void *packet, int length)
1137{
1138 struct mtk_eth_priv *priv = dev_get_priv(dev);
1139 u32 idx = priv->tx_cpu_owner_idx0;
developera7cdebf2022-09-09 19:59:26 +08001140 struct mtk_tx_dma_v2 *txd;
developerc3ac93d2018-12-20 16:12:53 +08001141 void *pkt_base;
1142
developer65089f72022-09-09 19:59:24 +08001143 txd = priv->tx_ring_noc + idx * priv->soc->txd_size;
1144
1145 if (!(txd->txd2 & PDMA_TXD2_DDONE)) {
developerc3ac93d2018-12-20 16:12:53 +08001146 debug("mtk-eth: TX DMA descriptor ring is full\n");
1147 return -EPERM;
1148 }
1149
developer65089f72022-09-09 19:59:24 +08001150 pkt_base = (void *)phys_to_virt(txd->txd1);
developerc3ac93d2018-12-20 16:12:53 +08001151 memcpy(pkt_base, packet, length);
Frank Wunderlich44350182020-01-31 10:23:29 +01001152 flush_dcache_range((ulong)pkt_base, (ulong)pkt_base +
developerc3ac93d2018-12-20 16:12:53 +08001153 roundup(length, ARCH_DMA_MINALIGN));
1154
developer78fed682023-07-19 17:17:37 +08001155 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2) ||
1156 MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
developera7cdebf2022-09-09 19:59:26 +08001157 txd->txd2 = PDMA_TXD2_LS0 | PDMA_V2_TXD2_SDL0_SET(length);
1158 else
1159 txd->txd2 = PDMA_TXD2_LS0 | PDMA_V1_TXD2_SDL0_SET(length);
developerc3ac93d2018-12-20 16:12:53 +08001160
1161 priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC;
1162 mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
1163
1164 return 0;
1165}
1166
1167static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
1168{
1169 struct mtk_eth_priv *priv = dev_get_priv(dev);
1170 u32 idx = priv->rx_dma_owner_idx0;
developera7cdebf2022-09-09 19:59:26 +08001171 struct mtk_rx_dma_v2 *rxd;
developerc3ac93d2018-12-20 16:12:53 +08001172 uchar *pkt_base;
1173 u32 length;
1174
developer65089f72022-09-09 19:59:24 +08001175 rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
1176
1177 if (!(rxd->rxd2 & PDMA_RXD2_DDONE)) {
developerc3ac93d2018-12-20 16:12:53 +08001178 debug("mtk-eth: RX DMA descriptor ring is empty\n");
1179 return -EAGAIN;
1180 }
1181
developer78fed682023-07-19 17:17:37 +08001182 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2) ||
1183 MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
developera7cdebf2022-09-09 19:59:26 +08001184 length = PDMA_V2_RXD2_PLEN0_GET(rxd->rxd2);
1185 else
1186 length = PDMA_V1_RXD2_PLEN0_GET(rxd->rxd2);
developer65089f72022-09-09 19:59:24 +08001187
1188 pkt_base = (void *)phys_to_virt(rxd->rxd1);
Frank Wunderlich44350182020-01-31 10:23:29 +01001189 invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base +
developerc3ac93d2018-12-20 16:12:53 +08001190 roundup(length, ARCH_DMA_MINALIGN));
1191
1192 if (packetp)
1193 *packetp = pkt_base;
1194
1195 return length;
1196}
1197
1198static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
1199{
1200 struct mtk_eth_priv *priv = dev_get_priv(dev);
1201 u32 idx = priv->rx_dma_owner_idx0;
developera7cdebf2022-09-09 19:59:26 +08001202 struct mtk_rx_dma_v2 *rxd;
developerc3ac93d2018-12-20 16:12:53 +08001203
developer65089f72022-09-09 19:59:24 +08001204 rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size;
1205
developer813a7d32024-12-17 16:40:03 +08001206 invalidate_dcache_range((ulong)rxd->rxd1,
1207 (ulong)rxd->rxd1 + PKTSIZE_ALIGN);
1208
developer78fed682023-07-19 17:17:37 +08001209 if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2) ||
1210 MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
developera7cdebf2022-09-09 19:59:26 +08001211 rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
1212 else
1213 rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN);
developerc3ac93d2018-12-20 16:12:53 +08001214
1215 mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx);
1216 priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
1217
1218 return 0;
1219}
1220
1221static int mtk_eth_probe(struct udevice *dev)
1222{
Simon Glassfa20e932020-12-03 16:55:20 -07001223 struct eth_pdata *pdata = dev_get_plat(dev);
developerc3ac93d2018-12-20 16:12:53 +08001224 struct mtk_eth_priv *priv = dev_get_priv(dev);
Frank Wunderlich44350182020-01-31 10:23:29 +01001225 ulong iobase = pdata->iobase;
developerc3ac93d2018-12-20 16:12:53 +08001226 int ret;
1227
1228 /* Frame Engine Register Base */
1229 priv->fe_base = (void *)iobase;
1230
1231 /* GMAC Register Base */
1232 priv->gmac_base = (void *)(iobase + GMAC_BASE);
1233
1234 /* MDIO register */
1235 ret = mtk_mdio_register(dev);
1236 if (ret)
1237 return ret;
1238
1239 /* Prepare for tx/rx rings */
developer65089f72022-09-09 19:59:24 +08001240 priv->tx_ring_noc = (void *)
1241 noncached_alloc(priv->soc->txd_size * NUM_TX_DESC,
developerc3ac93d2018-12-20 16:12:53 +08001242 ARCH_DMA_MINALIGN);
developer65089f72022-09-09 19:59:24 +08001243 priv->rx_ring_noc = (void *)
1244 noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
developerc3ac93d2018-12-20 16:12:53 +08001245 ARCH_DMA_MINALIGN);
1246
developer4843ad32024-01-22 10:08:11 +08001247 /* Set MDC divider */
1248 mtk_eth_mdc_init(priv);
1249
developerc3ac93d2018-12-20 16:12:53 +08001250 /* Set MAC mode */
developeref7b6502024-01-22 10:08:16 +08001251 if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
developer7fe0b3c2024-12-17 16:39:50 +08001252 priv->phy_interface == PHY_INTERFACE_MODE_10GBASER ||
developeref7b6502024-01-22 10:08:16 +08001253 priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
developera2a01412024-12-17 16:39:55 +08001254 ret = mtk_xmac_init(priv);
developer03ce27b2023-07-19 17:17:31 +08001255 else
developera2a01412024-12-17 16:39:55 +08001256 ret = mtk_mac_init(priv);
1257
1258 if (ret)
1259 return ret;
developerc3ac93d2018-12-20 16:12:53 +08001260
1261 /* Probe phy if switch is not specified */
developer29d9d9f2025-01-10 16:41:13 +08001262 if (!priv->swname)
developerc3ac93d2018-12-20 16:12:53 +08001263 return mtk_phy_probe(dev);
1264
1265 /* Initialize switch */
developer29d9d9f2025-01-10 16:41:13 +08001266 return mtk_switch_init(priv);
developerc3ac93d2018-12-20 16:12:53 +08001267}
1268
1269static int mtk_eth_remove(struct udevice *dev)
1270{
1271 struct mtk_eth_priv *priv = dev_get_priv(dev);
1272
1273 /* MDIO unregister */
1274 mdio_unregister(priv->mdio_bus);
1275 mdio_free(priv->mdio_bus);
1276
1277 /* Stop possibly started DMA */
1278 mtk_eth_stop(dev);
1279
developer29d9d9f2025-01-10 16:41:13 +08001280 if (priv->swpriv) {
1281 if (priv->swpriv->sw->cleanup)
1282 priv->swpriv->sw->cleanup(priv->swpriv);
1283 free(priv->swpriv);
1284 }
1285
developerc3ac93d2018-12-20 16:12:53 +08001286 return 0;
1287}
1288
Simon Glassaad29ae2020-12-03 16:55:21 -07001289static int mtk_eth_of_to_plat(struct udevice *dev)
developerc3ac93d2018-12-20 16:12:53 +08001290{
Simon Glassfa20e932020-12-03 16:55:20 -07001291 struct eth_pdata *pdata = dev_get_plat(dev);
developerc3ac93d2018-12-20 16:12:53 +08001292 struct mtk_eth_priv *priv = dev_get_priv(dev);
1293 struct ofnode_phandle_args args;
1294 struct regmap *regmap;
developerc3ac93d2018-12-20 16:12:53 +08001295 ofnode subnode;
1296 int ret;
1297
developer1d3b1f62022-09-09 19:59:21 +08001298 priv->soc = (const struct mtk_soc_data *)dev_get_driver_data(dev);
1299 if (!priv->soc) {
1300 dev_err(dev, "missing soc compatible data\n");
1301 return -EINVAL;
1302 }
developerc3ac93d2018-12-20 16:12:53 +08001303
developerafa74c22022-05-20 11:23:31 +08001304 pdata->iobase = (phys_addr_t)dev_remap_addr(dev);
developerc3ac93d2018-12-20 16:12:53 +08001305
1306 /* get corresponding ethsys phandle */
1307 ret = dev_read_phandle_with_args(dev, "mediatek,ethsys", NULL, 0, 0,
1308 &args);
1309 if (ret)
1310 return ret;
1311
developera182b7e2022-05-20 11:23:37 +08001312 priv->ethsys_regmap = syscon_node_to_regmap(args.node);
1313 if (IS_ERR(priv->ethsys_regmap))
1314 return PTR_ERR(priv->ethsys_regmap);
developerc3ac93d2018-12-20 16:12:53 +08001315
developera5d712a2023-07-19 17:17:22 +08001316 if (MTK_HAS_CAPS(priv->soc->caps, MTK_INFRA)) {
1317 /* get corresponding infracfg phandle */
1318 ret = dev_read_phandle_with_args(dev, "mediatek,infracfg",
1319 NULL, 0, 0, &args);
1320
1321 if (ret)
1322 return ret;
1323
1324 priv->infra_regmap = syscon_node_to_regmap(args.node);
1325 if (IS_ERR(priv->infra_regmap))
1326 return PTR_ERR(priv->infra_regmap);
1327 }
1328
developerc3ac93d2018-12-20 16:12:53 +08001329 /* Reset controllers */
1330 ret = reset_get_by_name(dev, "fe", &priv->rst_fe);
1331 if (ret) {
1332 printf("error: Unable to get reset ctrl for frame engine\n");
1333 return ret;
1334 }
1335
1336 priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0);
1337
developer4843ad32024-01-22 10:08:11 +08001338 priv->mdc = 0;
1339 subnode = ofnode_find_subnode(dev_ofnode(dev), "mdio");
1340 if (ofnode_valid(subnode)) {
1341 priv->mdc = ofnode_read_u32_default(subnode, "clock-frequency", 2500000);
1342 if (priv->mdc > MDC_MAX_FREQ ||
1343 priv->mdc < MDC_MAX_FREQ / MDC_MAX_DIVIDER) {
1344 printf("error: MDIO clock frequency out of range\n");
1345 return -EINVAL;
1346 }
1347 }
1348
developerc3ac93d2018-12-20 16:12:53 +08001349 /* Interface mode is required */
Marek Behúnbc194772022-04-07 00:33:01 +02001350 pdata->phy_interface = dev_read_phy_mode(dev);
1351 priv->phy_interface = pdata->phy_interface;
Marek Behún48631e42022-04-07 00:33:03 +02001352 if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
developerc3ac93d2018-12-20 16:12:53 +08001353 printf("error: phy-mode is not set\n");
1354 return -EINVAL;
1355 }
1356
1357 /* Force mode or autoneg */
1358 subnode = ofnode_find_subnode(dev_ofnode(dev), "fixed-link");
1359 if (ofnode_valid(subnode)) {
1360 priv->force_mode = 1;
1361 priv->speed = ofnode_read_u32_default(subnode, "speed", 0);
1362 priv->duplex = ofnode_read_bool(subnode, "full-duplex");
1363
1364 if (priv->speed != SPEED_10 && priv->speed != SPEED_100 &&
developer4aafc992023-07-19 17:17:13 +08001365 priv->speed != SPEED_1000 && priv->speed != SPEED_2500 &&
1366 priv->speed != SPEED_10000) {
developerc3ac93d2018-12-20 16:12:53 +08001367 printf("error: no valid speed set in fixed-link\n");
1368 return -EINVAL;
1369 }
1370 }
1371
developera2a01412024-12-17 16:39:55 +08001372 if ((priv->phy_interface == PHY_INTERFACE_MODE_SGMII ||
1373 priv->phy_interface == PHY_INTERFACE_MODE_2500BASEX) &&
1374 IS_ENABLED(CONFIG_MTK_ETH_SGMII)) {
developer9a12c242020-01-21 19:31:57 +08001375 /* get corresponding sgmii phandle */
1376 ret = dev_read_phandle_with_args(dev, "mediatek,sgmiisys",
1377 NULL, 0, 0, &args);
1378 if (ret)
1379 return ret;
1380
1381 regmap = syscon_node_to_regmap(args.node);
1382
1383 if (IS_ERR(regmap))
1384 return PTR_ERR(regmap);
1385
1386 priv->sgmii_base = regmap_get_range(regmap, 0);
1387
1388 if (!priv->sgmii_base) {
1389 dev_err(dev, "Unable to find sgmii\n");
1390 return -ENODEV;
1391 }
developer053929c2022-09-09 19:59:28 +08001392
Christian Marangi50ba7a52024-06-24 23:03:30 +02001393 /* Upstream linux use mediatek,pnswap instead of pn_swap */
1394 priv->pn_swap = ofnode_read_bool(args.node, "pn_swap") ||
1395 ofnode_read_bool(args.node, "mediatek,pnswap");
developera2a01412024-12-17 16:39:55 +08001396 } else if ((priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
1397 priv->phy_interface == PHY_INTERFACE_MODE_10GBASER) &&
1398 IS_ENABLED(CONFIG_MTK_ETH_XGMII)) {
developer03ce27b2023-07-19 17:17:31 +08001399 /* get corresponding usxgmii phandle */
1400 ret = dev_read_phandle_with_args(dev, "mediatek,usxgmiisys",
1401 NULL, 0, 0, &args);
1402 if (ret)
1403 return ret;
1404
1405 priv->usxgmii_regmap = syscon_node_to_regmap(args.node);
1406 if (IS_ERR(priv->usxgmii_regmap))
1407 return PTR_ERR(priv->usxgmii_regmap);
1408
1409 /* get corresponding xfi_pextp phandle */
1410 ret = dev_read_phandle_with_args(dev, "mediatek,xfi_pextp",
1411 NULL, 0, 0, &args);
1412 if (ret)
1413 return ret;
1414
1415 priv->xfi_pextp_regmap = syscon_node_to_regmap(args.node);
1416 if (IS_ERR(priv->xfi_pextp_regmap))
1417 return PTR_ERR(priv->xfi_pextp_regmap);
1418
1419 /* get corresponding xfi_pll phandle */
1420 ret = dev_read_phandle_with_args(dev, "mediatek,xfi_pll",
1421 NULL, 0, 0, &args);
1422 if (ret)
1423 return ret;
1424
1425 priv->xfi_pll_regmap = syscon_node_to_regmap(args.node);
1426 if (IS_ERR(priv->xfi_pll_regmap))
1427 return PTR_ERR(priv->xfi_pll_regmap);
1428
1429 /* get corresponding toprgu phandle */
1430 ret = dev_read_phandle_with_args(dev, "mediatek,toprgu",
1431 NULL, 0, 0, &args);
1432 if (ret)
1433 return ret;
1434
1435 priv->toprgu_regmap = syscon_node_to_regmap(args.node);
1436 if (IS_ERR(priv->toprgu_regmap))
1437 return PTR_ERR(priv->toprgu_regmap);
developer9a12c242020-01-21 19:31:57 +08001438 }
1439
developer29d9d9f2025-01-10 16:41:13 +08001440 priv->swname = dev_read_string(dev, "mediatek,switch");
1441 if (priv->swname) {
developerc3ac93d2018-12-20 16:12:53 +08001442 priv->mcm = dev_read_bool(dev, "mediatek,mcm");
1443 if (priv->mcm) {
1444 ret = reset_get_by_name(dev, "mcm", &priv->rst_mcm);
1445 if (ret) {
1446 printf("error: no reset ctrl for mcm\n");
1447 return ret;
1448 }
1449 } else {
1450 gpio_request_by_name(dev, "reset-gpios", 0,
1451 &priv->rst_gpio, GPIOD_IS_OUT);
1452 }
1453 } else {
developera19b69d2019-04-28 15:08:57 +08001454 ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0,
1455 0, &args);
1456 if (ret) {
developerc3ac93d2018-12-20 16:12:53 +08001457 printf("error: phy-handle is not specified\n");
1458 return ret;
1459 }
1460
developera19b69d2019-04-28 15:08:57 +08001461 priv->phy_addr = ofnode_read_s32_default(args.node, "reg", -1);
developerc3ac93d2018-12-20 16:12:53 +08001462 if (priv->phy_addr < 0) {
1463 printf("error: phy address is not specified\n");
1464 return ret;
1465 }
1466 }
1467
1468 return 0;
1469}
1470
developer76e14722023-07-19 17:17:41 +08001471static const struct mtk_soc_data mt7988_data = {
1472 .caps = MT7988_CAPS,
1473 .ana_rgc3 = 0x128,
1474 .gdma_count = 3,
1475 .pdma_base = PDMA_V3_BASE,
1476 .txd_size = sizeof(struct mtk_tx_dma_v2),
1477 .rxd_size = sizeof(struct mtk_rx_dma_v2),
1478};
1479
developer053929c2022-09-09 19:59:28 +08001480static const struct mtk_soc_data mt7986_data = {
1481 .caps = MT7986_CAPS,
1482 .ana_rgc3 = 0x128,
developer78fed682023-07-19 17:17:37 +08001483 .gdma_count = 2,
developer053929c2022-09-09 19:59:28 +08001484 .pdma_base = PDMA_V2_BASE,
1485 .txd_size = sizeof(struct mtk_tx_dma_v2),
1486 .rxd_size = sizeof(struct mtk_rx_dma_v2),
1487};
1488
1489static const struct mtk_soc_data mt7981_data = {
developera5d712a2023-07-19 17:17:22 +08001490 .caps = MT7981_CAPS,
developer053929c2022-09-09 19:59:28 +08001491 .ana_rgc3 = 0x128,
developer78fed682023-07-19 17:17:37 +08001492 .gdma_count = 2,
developer053929c2022-09-09 19:59:28 +08001493 .pdma_base = PDMA_V2_BASE,
1494 .txd_size = sizeof(struct mtk_tx_dma_v2),
1495 .rxd_size = sizeof(struct mtk_rx_dma_v2),
1496};
1497
developer1d3b1f62022-09-09 19:59:21 +08001498static const struct mtk_soc_data mt7629_data = {
developere8f42692024-12-17 16:39:46 +08001499 .caps = MT7629_CAPS,
developer1d3b1f62022-09-09 19:59:21 +08001500 .ana_rgc3 = 0x128,
developer78fed682023-07-19 17:17:37 +08001501 .gdma_count = 2,
developera7cdebf2022-09-09 19:59:26 +08001502 .pdma_base = PDMA_V1_BASE,
developer65089f72022-09-09 19:59:24 +08001503 .txd_size = sizeof(struct mtk_tx_dma),
1504 .rxd_size = sizeof(struct mtk_rx_dma),
developer1d3b1f62022-09-09 19:59:21 +08001505};
1506
1507static const struct mtk_soc_data mt7623_data = {
1508 .caps = MT7623_CAPS,
developer78fed682023-07-19 17:17:37 +08001509 .gdma_count = 2,
developera7cdebf2022-09-09 19:59:26 +08001510 .pdma_base = PDMA_V1_BASE,
developer65089f72022-09-09 19:59:24 +08001511 .txd_size = sizeof(struct mtk_tx_dma),
1512 .rxd_size = sizeof(struct mtk_rx_dma),
developer1d3b1f62022-09-09 19:59:21 +08001513};
1514
1515static const struct mtk_soc_data mt7622_data = {
developer2da7d4a2024-12-17 16:39:41 +08001516 .caps = MT7622_CAPS,
developer1d3b1f62022-09-09 19:59:21 +08001517 .ana_rgc3 = 0x2028,
developer78fed682023-07-19 17:17:37 +08001518 .gdma_count = 2,
developera7cdebf2022-09-09 19:59:26 +08001519 .pdma_base = PDMA_V1_BASE,
developer65089f72022-09-09 19:59:24 +08001520 .txd_size = sizeof(struct mtk_tx_dma),
1521 .rxd_size = sizeof(struct mtk_rx_dma),
developer1d3b1f62022-09-09 19:59:21 +08001522};
1523
1524static const struct mtk_soc_data mt7621_data = {
1525 .caps = MT7621_CAPS,
developer78fed682023-07-19 17:17:37 +08001526 .gdma_count = 2,
developera7cdebf2022-09-09 19:59:26 +08001527 .pdma_base = PDMA_V1_BASE,
developer65089f72022-09-09 19:59:24 +08001528 .txd_size = sizeof(struct mtk_tx_dma),
1529 .rxd_size = sizeof(struct mtk_rx_dma),
developer1d3b1f62022-09-09 19:59:21 +08001530};
1531
developerc3ac93d2018-12-20 16:12:53 +08001532static const struct udevice_id mtk_eth_ids[] = {
developer76e14722023-07-19 17:17:41 +08001533 { .compatible = "mediatek,mt7988-eth", .data = (ulong)&mt7988_data },
developer053929c2022-09-09 19:59:28 +08001534 { .compatible = "mediatek,mt7986-eth", .data = (ulong)&mt7986_data },
1535 { .compatible = "mediatek,mt7981-eth", .data = (ulong)&mt7981_data },
developer1d3b1f62022-09-09 19:59:21 +08001536 { .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data },
1537 { .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data },
1538 { .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data },
1539 { .compatible = "mediatek,mt7621-eth", .data = (ulong)&mt7621_data },
developerc3ac93d2018-12-20 16:12:53 +08001540 {}
1541};
1542
1543static const struct eth_ops mtk_eth_ops = {
1544 .start = mtk_eth_start,
1545 .stop = mtk_eth_stop,
1546 .send = mtk_eth_send,
1547 .recv = mtk_eth_recv,
1548 .free_pkt = mtk_eth_free_pkt,
1549 .write_hwaddr = mtk_eth_write_hwaddr,
1550};
1551
1552U_BOOT_DRIVER(mtk_eth) = {
1553 .name = "mtk-eth",
1554 .id = UCLASS_ETH,
1555 .of_match = mtk_eth_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001556 .of_to_plat = mtk_eth_of_to_plat,
developer29d9d9f2025-01-10 16:41:13 +08001557 .plat_auto = sizeof(struct eth_pdata),
developerc3ac93d2018-12-20 16:12:53 +08001558 .probe = mtk_eth_probe,
1559 .remove = mtk_eth_remove,
1560 .ops = &mtk_eth_ops,
developer29d9d9f2025-01-10 16:41:13 +08001561 .priv_auto = sizeof(struct mtk_eth_priv),
developerc3ac93d2018-12-20 16:12:53 +08001562 .flags = DM_FLAG_ALLOC_PRIV_DMA,
1563};