1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Description: Higmac driver main process
18 */
19
20 #include <cpu_func.h>
21 #include <console.h>
22 #include "higmac.h"
23 #include "ctrl.h"
24 #include "mdio.h"
25
26 typedef enum {
27 GSF0_PORT0,
28 #if GMAC_AT_LEAST_2PORT
29 GSF0_PORT1,
30 #endif
31 #if GMAC_AT_LEAST_3PORT
32 GSF1_PORT0,
33 #endif
34 MAX_PORT_NUM,
35 } port_id_t;
36
37 static int mac_iobase[MAX_PORT_NUM] = {
38 HIGMAC0_IOBASE,
39 #if GMAC_AT_LEAST_2PORT
40 HIGMAC1_IOBASE,
41 #endif
42 #if GMAC_AT_LEAST_3PORT
43 HIGMAC2_IOBASE,
44 #endif
45 };
46
47 /* this driver only support GMAC_NUMS = 2 or 1 */
48 #define MDIO_BUS_NUMS 2
49 struct higmac_board_info g_higmac_board_info[CONFIG_GMAC_NUMS] = {
50 {
51 {
52 .index = GSF0_PORT0,
53 .iobase = HIGMAC0_IOBASE,
54 .iobase_phys = HIGMAC0_IOBASE,
55 },
56 .mii_name = "mdio0",
57 .phy_intf = CONFIG_HIGMAC_PHY0_INTERFACE_MODE,
58 .phy_addr = CONFIG_HIGMAC_PHY0_ADDR,
59 },
60 #if GMAC_AT_LEAST_2PORT
61 {
62 {
63 .index = GSF0_PORT1,
64 .iobase = HIGMAC1_IOBASE,
65 .iobase_phys = HIGMAC1_IOBASE,
66 },
67 .mii_name = "mdio1",
68 .phy_intf = CONFIG_HIGMAC_PHY1_INTERFACE_MODE,
69 .phy_addr = CONFIG_HIGMAC_PHY1_ADDR,
70 }
71 #endif
72 };
73
74 static int g_phy_link_times;
75 static int g_gmac_debug;
76
77 static char *phy_intf_str[INTERFACE_MODE_BUTT] = {
78 "mii",
79 "rmii",
80 "rgmii",
81 };
82 static char *mdio_bus[CONFIG_GMAC_NUMS] = {
83 "mdio0",
84 #if GMAC_AT_LEAST_2PORT
85 "mdio1",
86 #endif
87 #if GMAC_AT_LEAST_3PORT
88 "mdio2"
89 #endif
90 };
91
92 #if defined(CONFIG_MACH_GODEYES)
93 /*
94 * 3516(godeyes) port mode def.
95 * PORT_MODE_BUTT means not support this mode.
96 */
97 static int g_speed_portmode_table[SPEED_MODE_BUTT][INTERFACE_MODE_BUTT] = {
98 {PORT_MODE_10_MII, PORT_MODE_BUTT, PORT_MODE_10_RGMII},
99 {PORT_MODE_100_MII, PORT_MODE_BUTT, PORT_MODE_100_RGMII},
100 {PORT_MODE_BUTT, PORT_MODE_BUTT, PORT_MODE_1000_RGMII}
101 };
102 #else
103 static int g_speed_portmode_table[SPEED_MODE_BUTT][INTERFACE_MODE_BUTT] = {
104 {PORT_MODE_10_MII, PORT_MODE_10_RMII, PORT_MODE_10_RGMII},
105 {PORT_MODE_100_MII, PORT_MODE_100_RMII, PORT_MODE_100_RGMII},
106 {PORT_MODE_BUTT, PORT_MODE_BUTT, PORT_MODE_1000_RGMII}
107 };
108 #endif
109
calculate_port_mode(enum speed_mode speed,enum if_mode if_mode,int is_duplex_half)110 static int calculate_port_mode(enum speed_mode speed, enum if_mode if_mode,
111 int is_duplex_half)
112 {
113 if (speed < SPEED_MODE_BUTT && if_mode < INTERFACE_MODE_BUTT) {
114 int ret = g_speed_portmode_table[speed][if_mode];
115
116 if (is_duplex_half)
117 ret = ((unsigned int)ret) & (~bit(4)) ; /* bit 4 see mac_if reg */
118 return ret;
119 }
120
121 printf("Invalid speed=%d & interface=%d mode.\n", speed, if_mode);
122 printf("Please assign which mode our eth will correctly work at.\n"
123 "It may support 10M/100M MII, 10M/100M RMII, "
124 "10M/100M/1000M RGMII interface.\n"
125 "eg. if your board have two NICs, connecting each phy using "
126 "mii and rgmii interface, you can use the module param "
127 "'port_mode=mii,rgmii' to tell the driver.\n");
128 BUG();
129
130 /* can't reach here */
131 return -1;
132 }
133
set_gmac_debug_switch(void)134 static void set_gmac_debug_switch(void)
135 {
136 char *s = NULL;
137 char *e = NULL;
138 char evn_buf[ENV_BUF_LEN] = {0};
139 int i = 0;
140
141 s = env_get("gmac_debug");
142 if (s != NULL) {
143 while (*s != '\0' && i < sizeof(evn_buf) - 1)
144 evn_buf[i++] = *s++;
145 evn_buf[i] = '\0';
146 g_gmac_debug = (int)simple_strtoul(evn_buf, &e, 10); /* Base 10 */
147 } else {
148 g_gmac_debug = 0;
149 }
150 }
151
set_phy_link_times(void)152 static void set_phy_link_times(void)
153 {
154 char *s = NULL;
155 char *e = NULL;
156 char evn_buf[ENV_BUF_LEN] = {0};
157 int i = 0;
158
159 s = env_get("phy_link_times");
160 if (s != NULL) {
161 while (*s != '\0' && i < sizeof(evn_buf) - 1)
162 evn_buf[i++] = *s++;
163 evn_buf[i] = '\0';
164 g_phy_link_times = (int)simple_strtoul(evn_buf, &e, 10); /* Base 10 */
165 } else {
166 g_phy_link_times = DEFAULT_PHY_LINK_TIMES;
167 }
168 }
169
set_mdio_intf(void)170 static void set_mdio_intf(void)
171 {
172 int gmac = 0;
173 char *s = NULL;
174 char evn_buf[ENV_BUF_LEN] = {0};
175 int i = 0;
176
177 s = env_get("mdio_intf");
178 if (s != NULL) {
179 while (*s != '\0' && i < sizeof(evn_buf) - 1)
180 evn_buf[i++] = *s++;
181 evn_buf[i] = '\0';
182 s = evn_buf;
183 }
184 next_mii:
185 if (s != NULL) {
186 enum if_mode if_mode;
187
188 while (*s == ' ' || *s == ',')
189 s++;
190
191 if (!strncmp(s, "mii", strlen("mii"))) {
192 if_mode = INTERFACE_MODE_MII;
193 } else if (!strncmp(s, "rmii", strlen("rmii"))) {
194 if_mode = INTERFACE_MODE_RMII;
195 } else if (!strncmp(s, "rgmii", strlen("rgmii"))) {
196 if_mode = INTERFACE_MODE_RGMII;
197 } else {
198 printf("Invalid phy_intf(mii, rmii, or rgmii), " \
199 "Set ETH%d default to mii\n", gmac);
200 if_mode = INTERFACE_MODE_MII;
201 }
202
203 if (!gmac) { /* first time */
204 gmac = 1;
205 g_higmac_board_info[0].phy_intf = if_mode;
206 /* in case phy_intf=mii */
207 #if GMAC_AT_LEAST_2PORT
208 g_higmac_board_info[1].phy_intf = if_mode;
209 #endif
210 s = strchr(s, ',');
211 goto next_mii;
212 } else {
213 #if GMAC_AT_LEAST_2PORT
214 g_higmac_board_info[1].phy_intf = if_mode;
215 #else
216 ;
217 #endif
218 }
219 }
220 }
221
222 #if GMAC_AT_LEAST_2PORT
set_use_mdio(void)223 static void set_use_mdio(void)
224 {
225 int gmac = 0;
226 unsigned long tmp;
227 char *s = NULL;
228 char *e = NULL;
229
230 /* use_mdio=0 or use_mdio=1 or use_mdio=0,1 or ... */
231 s = env_get("use_mdio");
232 next_mdio:
233 if (s && gmac < CONFIG_GMAC_NUMS) {
234 while (*s == ' ' || *s == ',')
235 s++;
236
237 tmp = simple_strtoul(s, &e, 10); /* Base 10 */
238 if (tmp >= MDIO_BUS_NUMS) {
239 printf("Invalid use_mdio, Set GMAC%d use mdio%d.\n",
240 gmac, gmac);
241 tmp = gmac;
242 }
243
244 if (gmac == 0) { /* first time */
245 g_higmac_board_info[0].mii_name = mdio_bus[tmp];
246 g_higmac_board_info[1].mii_name = mdio_bus[tmp];
247 gmac++;
248 s = e;
249 s = strchr(s, ',');
250 goto next_mdio;
251 } else {
252 g_higmac_board_info[1].mii_name = mdio_bus[tmp];
253 }
254 }
255 }
256 #endif
257
set_phy_addr(void)258 static void set_phy_addr(void)
259 {
260 int gmac = 0;
261 unsigned long tmp;
262 char *s = NULL;
263 char *e = NULL;
264
265 /* get phy addr */
266 s = env_get("phy_addr");
267 next_phyaddr:
268 if (s && gmac < CONFIG_GMAC_NUMS) {
269 while (*s == ' ' || *s == ',')
270 s++;
271
272 tmp = simple_strtoul(s, &e, 10); /* Base 10 */
273 if (tmp == 0) {
274 printf("Dectected gmac%d phyaddr set to 0, " \
275 "is it right?\n", gmac);
276 } else if (tmp >= 32) { /* must less than 32 */
277 printf("Dectected gmac%d phyaddr " \
278 "set to val(%lu) >= 32, " \
279 "This may not correct, " \
280 "use default phyaddr=%d\n",
281 gmac, tmp,
282 g_higmac_board_info[gmac].phy_addr);
283
284 tmp = g_higmac_board_info[gmac].phy_addr;
285 }
286 if (gmac == 0) { /* gmac0 */
287 g_higmac_board_info[gmac].phy_addr = tmp;
288 gmac++;
289 s = e;
290 s = strchr(s, ',');
291 goto next_phyaddr;
292 } else { /* gmac1 */
293 #if GMAC_AT_LEAST_2PORT
294 g_higmac_board_info[gmac].phy_addr = tmp;
295 #else
296 ;
297 #endif
298 }
299 }
300 }
301
302 /* module parameter
303 * 1) phy_intf=mii,rgmii if eth0=mii, eth1=rgmii
304 * phy_intf=mii if eth0=mii, eth1=mii;
305 * 2) use_internal_phy=1 if eth1 use internal phy;
306 * 3) phy0_addr=1, phy1_addr=2
307 * 4) g_gmac_debug=1
308 */
parse_module_parameters(void)309 static void parse_module_parameters(void)
310 {
311 int gmac;
312
313 set_gmac_debug_switch();
314 set_phy_link_times();
315
316 /* phy_intf = {mii | rgmii | rmii} [,{mii | rgmii | rmii}] */
317 set_mdio_intf();
318
319 #if GMAC_AT_LEAST_2PORT
320 set_use_mdio();
321 #endif
322 set_phy_addr();
323 if (g_gmac_debug) {
324 printf("phy_link_times=%d\n", g_phy_link_times);
325 for (gmac = 0; gmac < CONFIG_GMAC_NUMS; gmac++)
326 printf("ETH%d: port_mode=%s, " \
327 "mii_name=%s, phy_addr=%d\n",
328 gmac,
329 phy_intf_str[g_higmac_board_info[gmac].phy_intf],
330 g_higmac_board_info[gmac].mii_name,
331 g_higmac_board_info[gmac].phy_addr);
332 printf("\n");
333 }
334 }
335
higmac_net_set_mac_address(struct eth_device * dev)336 static int higmac_net_set_mac_address(struct eth_device *dev)
337 {
338 struct higmac_netdev_local *ld = (struct higmac_netdev_local *)dev->priv;
339 unsigned char mac[MAC_LEN] = {0};
340 int ret;
341
342 ret = eth_env_get_enetaddr("ethaddr", mac);
343 if (ret == 0) {
344 printf("MAC address invalid!\n");
345 #ifdef CONFIG_NET_RANDOM_ETHADDR
346 net_random_ethaddr(mac);
347 printf("Set Random MAC address!\n");
348 eth_setenv_enetaddr("ethaddr", mac);
349 #endif
350 }
351
352 higmac_hw_set_macaddress(ld, mac, MAC_LEN);
353 memcpy(dev->enetaddr, mac, MAC_LEN);
354
355 return 0;
356 }
357
higmac_memalign_queue_addr(unsigned int queue_count)358 static higmac_desc* higmac_memalign_queue_addr(unsigned int queue_count)
359 {
360 unsigned int size = queue_count * sizeof(higmac_desc);
361 higmac_desc *queue_phy_addr = NULL;
362 queue_phy_addr = (higmac_desc *)memalign(ARCH_DMA_MINALIGN, size);
363 if (queue_phy_addr == NULL)
364 return NULL;
365
366 memset((void *)queue_phy_addr, 0, size);
367 #ifndef CONFIG_SYS_DCACHE_OFF
368 flush_cache((uintptr_t)queue_phy_addr, ALIGN(size, ARCH_DMA_MINALIGN));
369 #endif
370 return queue_phy_addr;
371 }
372
higmac_init_hw_desc_queue(struct higmac_netdev_local * ld)373 static int higmac_init_hw_desc_queue(struct higmac_netdev_local *ld)
374 {
375 higmac_desc *queue_phy_addr = NULL;
376
377 /* init rx fq */
378 queue_phy_addr = higmac_memalign_queue_addr(HIGMAC_HWQ_RX_FQ_DEPTH);
379 if (queue_phy_addr == NULL) {
380 printf("alloc rx fq error!\n");
381 goto _error_alloc_rx_fq;
382 }
383
384 ld->rx_fq_addr = queue_phy_addr;
385 higmac_set_rx_fq_hwq_addr(ld, (phys_addr_t)(uintptr_t)queue_phy_addr);
386
387 /* init rx bq */
388 queue_phy_addr = higmac_memalign_queue_addr(HIGMAC_HWQ_RX_BQ_DEPTH);
389 if (queue_phy_addr == NULL) {
390 printf("alloc rx bq error!\n");
391 goto _error_alloc_rx_bq;
392 }
393
394 ld->rx_bq_addr = queue_phy_addr;
395 higmac_set_rx_bq_hwq_addr(ld, (phys_addr_t)(uintptr_t)queue_phy_addr);
396
397 /* init tx bq */
398 queue_phy_addr = higmac_memalign_queue_addr(HIGMAC_HWQ_TX_BQ_DEPTH);
399 if (queue_phy_addr == NULL) {
400 printf("alloc tx bq error!\n");
401 goto _error_alloc_tx_bq;
402 }
403
404 ld->tx_bq_addr = queue_phy_addr;
405 higmac_set_tx_bq_hwq_addr(ld, (phys_addr_t)(uintptr_t)queue_phy_addr);
406
407 /* init tx rq */
408 queue_phy_addr = higmac_memalign_queue_addr(HIGMAC_HWQ_TX_RQ_DEPTH);
409 if (queue_phy_addr == NULL) {
410 printf("alloc tx rq error!\n");
411 goto _error_alloc_tx_rq;
412 }
413
414 ld->tx_rq_addr = queue_phy_addr;
415 higmac_set_tx_rq_hwq_addr(ld, (phys_addr_t)(uintptr_t)queue_phy_addr);
416
417 return 0;
418
419 _error_alloc_tx_rq:
420 free(ld->tx_bq_addr);
421 ld->tx_bq_addr = NULL;
422
423 _error_alloc_tx_bq:
424 free(ld->rx_bq_addr);
425 ld->rx_bq_addr = NULL;
426
427 _error_alloc_rx_bq:
428 free(ld->rx_fq_addr);
429 ld->rx_fq_addr = NULL;
430
431 _error_alloc_rx_fq:
432 return -1;
433 }
434
435 #define PHY_ID_KSZ8051 0x00221550
436 #define PHY_ID_KSZ8081 0x00221560
437 #define PHY_ID_KSZ9031 0x00221620
438 #define PHY_ID_MASK 0xFFFFFFF0
439
440 /* MMD: MDIO Manageable Device */
441 #define MACR 0x0D
442 #define MAADR 0x0E
phy_mmd_read(const char * devname,u32 phyaddr,u32 mmd_device,u32 regnum,u32 * val)443 static void phy_mmd_read(const char *devname, u32 phyaddr,
444 u32 mmd_device, u32 regnum, u32 *val)
445 {
446 int ret;
447
448 miiphy_write(devname, phyaddr, MACR, mmd_device);
449 miiphy_write(devname, phyaddr, MAADR, regnum);
450 miiphy_write(devname, phyaddr, MACR, 0x4000 | mmd_device);
451
452 ret = miiphy_read(devname, phyaddr, MAADR, (unsigned short *)val);
453 if (ret != 0)
454 printf("%s mmd read phy %d dev %d reg 0x%x failed\n",
455 devname, phyaddr, mmd_device, regnum);
456 }
457
phy_mmd_write(const char * devname,u32 phyaddr,u32 mmd_device,u32 regnum,u32 val)458 static void phy_mmd_write(const char *devname, u32 phyaddr,
459 u32 mmd_device, u32 regnum, u32 val)
460 {
461 miiphy_write(devname, phyaddr, MACR, mmd_device);
462 miiphy_write(devname, phyaddr, MAADR, regnum);
463 miiphy_write(devname, phyaddr, MACR, 0x4000 | mmd_device);
464
465 miiphy_write(devname, phyaddr, MAADR, val);
466 }
467
phy_detected(const char * devname,unsigned int phyaddr,u32 * phy_id)468 static int phy_detected(const char *devname, unsigned int phyaddr, u32* phy_id)
469 {
470 u16 id1 = 0;
471 u16 id2 = 0;
472
473 if (miiphy_read(devname, phyaddr, MII_PHYSID1, &id1) != 0) {
474 printf("PHY IDR1 read failed\n");
475 return 0;
476 };
477 if (miiphy_read(devname, phyaddr, MII_PHYSID2, &id2) != 0) {
478 printf("PHY IDR2 read failed\n");
479 return 0;
480 };
481
482 *phy_id = (id1 & 0xffff) << 16; /* shift 16 bit */
483 *phy_id |= (id2 & 0xffff);
484
485 /* If the phy_id is all Fs, there is no device there */
486 if (*phy_id == 0xffffffff || *phy_id == 0 ||
487 *phy_id == 0xFFFF || *phy_id == 0xFFFF0000)
488 return 0;
489
490 return 1;
491 }
492
phy_fixup(const char * devname,unsigned int phyaddr,enum if_mode phymode)493 static int phy_fixup(const char *devname, unsigned int phyaddr, enum if_mode phymode)
494 {
495 u32 phy_id = 0;
496
497 if (!phy_detected(devname, phyaddr, &phy_id))
498 return -1;
499
500 /* PHY-KSZ8051 */
501 if (((phy_id & PHY_ID_MASK) == PHY_ID_KSZ8051) &&
502 (phymode == INTERFACE_MODE_RMII)) {
503 unsigned int val = 0;
504
505 if (miiphy_read(devname, phyaddr, 0x1F,
506 (unsigned short *)&val) != 0) {
507 printf("PHY reg read failed\n");
508 return -1;
509 };
510 val |= bit(7); /* set (bit7) phy RMII 50MHz clk; */
511 if (miiphy_write(devname, phyaddr, 0x1F, val) != 0)
512 return -1;
513
514 if (miiphy_read(devname, phyaddr, 0x16,
515 (unsigned short *)&val) != 0) {
516 printf("PHY reg read failed\n");
517 return -1;
518 };
519 val |= bit(1); /* set phy RMII override; */
520 if (miiphy_write(devname, phyaddr, 0x16, val) != 0)
521 return -1;
522 }
523
524 /* PHY-KSZ8081 */
525 if (((phy_id & PHY_ID_MASK) == PHY_ID_KSZ8081) &&
526 (phymode == INTERFACE_MODE_RMII)) {
527 unsigned int val = 0;
528
529 if (miiphy_read(devname, phyaddr, 0x1F,
530 (unsigned short *)&val) != 0) {
531 printf("PHY IDR1 read failed\n");
532 return -1;
533 };
534 val |= bit(7); /* set (bit7) phy RMII 50MHz clk; */
535 if (miiphy_write(devname, phyaddr, 0x1F, val) != 0)
536 return -1;
537 }
538
539 /* PHY-KSZ9031 */
540 if ((phy_id & PHY_ID_MASK) == PHY_ID_KSZ9031) {
541 unsigned int val = 0;
542
543 /* RX_CLK Pad Skew: 1_1101(+0.84) */
544 phy_mmd_read(devname, phyaddr, 0x2, 0x8, &val);
545 val = (val & ~0x1F) | 0x1D;
546 phy_mmd_write(devname, phyaddr, 0x2, 0x8, val);
547 }
548
549 return 0;
550 }
551
higmac_net_adjust_speed(struct higmac_netdev_local * ld,unsigned int * link_stat,int is_duplex_half)552 static void higmac_net_adjust_speed(struct higmac_netdev_local *ld,
553 unsigned int *link_stat, int is_duplex_half)
554 {
555 char *mii_name = g_higmac_board_info[ld->index].mii_name;
556 int phy_addr = g_higmac_board_info[ld->index].phy_addr;
557 int speed, port_mode;
558 unsigned int stat = *link_stat;
559 enum speed_mode speed_mode = SPEED_MODE_100M;
560
561 speed = miiphy_speed(mii_name, phy_addr);
562 switch (speed) {
563 case _10BASET:
564 stat |= HIGMAC_SPD_10M;
565 speed_mode = SPEED_MODE_10M;
566 break;
567 case _100BASET:
568 stat |= HIGMAC_SPD_100M;
569 speed_mode = SPEED_MODE_100M;
570 break;
571 case _1000BASET:
572 stat |= HIGMAC_SPD_1000M;
573 speed_mode = SPEED_MODE_1000M;
574 break;
575 default:
576 printf("wired, phy speed!\n");
577 break;
578 }
579
580 if (ld->link_stat != stat) {
581 if (stat & HIGMAC_LINKED) {
582 port_mode = calculate_port_mode(speed_mode,
583 g_higmac_board_info[ld->index].phy_intf, is_duplex_half);
584
585 higmac_set_macif(ld, port_mode, speed_mode);
586
587 higmac_writel(ld, is_duplex_half ? 0x0 : 0x1,
588 MAC_DUPLEX_HALF_CTRL);
589 }
590 ld->link_stat = stat;
591 }
592 *link_stat = stat;
593 }
594
higmac_net_adjust_link(struct higmac_netdev_local * ld)595 static int higmac_net_adjust_link(struct higmac_netdev_local *ld)
596 {
597 char *mii_name = g_higmac_board_info[ld->index].mii_name;
598 int phy_addr = g_higmac_board_info[ld->index].phy_addr;
599 enum if_mode phy_mode = g_higmac_board_info[ld->index].phy_intf;
600 unsigned int stat = INVALID_LINK_STATUS;
601 int phy_duplex;
602 int is_duplex_half = 1;
603 u32 phy_id = 0;
604
605 if (phy_addr == INVALID_PHY_ADDR)
606 return stat;
607
608 phy_fixup(mii_name, phy_addr, phy_mode);
609
610 if (!phy_detected(mii_name, phy_addr, &phy_id))
611 return stat;
612
613 stat |= miiphy_link(mii_name, phy_addr) ? HIGMAC_LINKED : 0;
614
615 phy_duplex = miiphy_duplex(mii_name, phy_addr);
616 if (phy_duplex == FULL) {
617 stat |= HIGMAC_DUP_FULL;
618 is_duplex_half = 0;
619 }
620
621 higmac_net_adjust_speed(ld, &stat, is_duplex_half);
622
623 return stat;
624 }
625
select_current_linked_phy(struct higmac_netdev_local * ld)626 static int select_current_linked_phy(struct higmac_netdev_local *ld)
627 {
628 int count = g_phy_link_times ? : DEFAULT_PHY_LINK_TIMES;
629 unsigned int status;
630
631 for (; count > 0; count--) {
632 if (ctrlc()) {
633 puts("\nAbort\n");
634 goto link_failed;
635 }
636
637 status = (unsigned int)higmac_net_adjust_link(ld);
638 if (status & HIGMAC_LINKED)
639 goto link_on;
640 mdelay(100); /* wait 100ms */
641 }
642
643 link_failed:
644 printf("ETH%d: PHY(%s, phyaddr=%d, %s) not link!\n",
645 ld->index, g_higmac_board_info[ld->index].mii_name,
646 g_higmac_board_info[ld->index].phy_addr,
647 phy_intf_str[g_higmac_board_info[ld->index].phy_intf]);
648
649 return -1;
650
651 link_on:
652 printf("ETH%d: PHY(phyaddr=%d, %s) link UP: DUPLEX=%s : SPEED=%s\n",
653 ld->index, g_higmac_board_info[ld->index].phy_addr,
654 phy_intf_str[g_higmac_board_info[ld->index].phy_intf],
655 (status & HIGMAC_DUP_FULL) ? "FULL" : "HALF",
656 (status & HIGMAC_SPD_100M) ? "100M" :
657 ((status & HIGMAC_SPD_10M) ? "10M" : "1000M"));
658
659 miiphy_set_current_dev(g_higmac_board_info[ld->index].mii_name);
660
661 return 0;
662 }
663
get_wr_rd_dist(u32 rx_fq_wr_offset,u32 rx_fq_rd_offset)664 static unsigned int get_wr_rd_dist(u32 rx_fq_wr_offset, u32 rx_fq_rd_offset)
665 {
666 unsigned int wr_rd_dist;
667 if (rx_fq_wr_offset >= rx_fq_rd_offset)
668 wr_rd_dist = (HIGMAC_HWQ_RX_FQ_DEPTH << DESC_BYTE_SHIFT)
669 - (rx_fq_wr_offset - rx_fq_rd_offset);
670 else
671 wr_rd_dist = rx_fq_rd_offset - rx_fq_wr_offset;
672
673 /* offset was counted on bytes, desc size = 2^5 */
674 wr_rd_dist >>= DESC_BYTE_SHIFT;
675 return wr_rd_dist;
676 }
677
show_gmac_recv_msg(const char * addr,int len)678 static void show_gmac_recv_msg(const char *addr, int len)
679 {
680 if (g_gmac_debug) {
681 int i;
682 printf("got packet!\n");
683 printf("[%s:%d]Packet length = %#4x\n", __FUNCTION__, __LINE__, len);
684 for (i = 0; i < len; i++) {
685 if (i % 16 == 0) printf("%#4.4x", i); /* Each 16 print i */
686 if (i % 2 == 0) printf(" "); /* Each 2 print space */
687 printf("%2.2x", ((unsigned char *)addr)[i]);
688 if (i % 16 == 15) printf("\n"); /* 15 is last line of 16 */
689 }
690 printf("\n\n\n\n");
691 }
692 }
693
694 #define NET_IP_ALIGN 2
higmac_recv_rx_fq(struct higmac_netdev_local * ld)695 static void higmac_recv_rx_fq(struct higmac_netdev_local *ld)
696 {
697 higmac_desc *rx_fq_desc = ld->rx_fq_addr;
698 u32 rx_fq_wr_offset, rx_fq_rd_offset;
699 unsigned int wr_rd_dist;
700 phys_addr_t addr;
701 int i;
702
703 rx_fq_wr_offset = higmac_readl_bits(ld, RX_FQ_WR_ADDR, BITS_RX_FQ_WR_ADDR);
704 rx_fq_rd_offset = higmac_readl_bits(ld, RX_FQ_RD_ADDR, BITS_RX_FQ_RD_ADDR);
705
706 wr_rd_dist = get_wr_rd_dist(rx_fq_wr_offset, rx_fq_rd_offset);
707
708 /* wr_rd_dist - 1 for logic reason.
709 * Logic think the desc pool is full filled, ...?
710 */
711 for (i = 0; i < wr_rd_dist - 1; i++) {
712 rx_fq_desc = ld->rx_fq_addr + (rx_fq_wr_offset >> DESC_BYTE_SHIFT);
713 addr = (phys_addr_t)(uintptr_t)memalign(ARCH_DMA_MINALIGN,
714 HIETH_BUFFER_SIZE);
715 if (!addr)
716 break;
717 #ifndef CONFIG_SYS_DCACHE_OFF
718 invalidate_dcache_range(addr,
719 ALIGN(addr + HIETH_BUFFER_SIZE, ARCH_DMA_MINALIGN));
720 #endif
721 addr += NET_IP_ALIGN;
722 rx_fq_desc->data_buff_addr = (u32)addr;
723 #if defined(CONFIG_64BIT)
724 rx_fq_desc->reserve4 = ((u64)addr >> REG_BIT_WIDTH) << Q_ADDR_HI8_OFFSET;
725 #endif
726 rx_fq_desc->descvid = DESC_VLD_FREE;
727 rx_fq_desc->buffer_len = (HIETH_MAX_FRAME_SIZE - 1);
728 rx_fq_desc->data_len = 8; /* data length 8 */
729 #ifndef CONFIG_SYS_DCACHE_OFF
730 flush_cache((uintptr_t)rx_fq_desc & ~(ARCH_DMA_MINALIGN - 1),
731 ALIGN(sizeof(*rx_fq_desc), ARCH_DMA_MINALIGN));
732 #endif
733
734 rx_fq_wr_offset += DESC_SIZE;
735 if (rx_fq_wr_offset >= (HIGMAC_HWQ_RX_FQ_DEPTH << DESC_BYTE_SHIFT))
736 rx_fq_wr_offset = 0;
737 higmac_writel_bits(ld, rx_fq_wr_offset, RX_FQ_WR_ADDR,
738 BITS_RX_FQ_WR_ADDR);
739 }
740 }
741
higmac_recv(struct eth_device * dev)742 static int higmac_recv(struct eth_device *dev)
743 {
744 struct higmac_netdev_local *ld = (struct higmac_netdev_local *)dev->priv;
745 higmac_desc *rx_bq_desc = ld->rx_bq_addr;
746 u32 rx_bq_wr_offset, rx_bq_rd_offset;
747 int timeout_us = 100000;
748 phys_addr_t addr;
749 int len;
750
751 higmac_recv_rx_fq(ld);
752
753 rx_bq_wr_offset = higmac_readl_bits(ld, RX_BQ_WR_ADDR, BITS_RX_BQ_WR_ADDR);
754 rx_bq_rd_offset = higmac_readl_bits(ld, RX_BQ_RD_ADDR, BITS_RX_BQ_RD_ADDR);
755 rx_bq_desc += (rx_bq_rd_offset >> DESC_BYTE_SHIFT);
756
757 while (--timeout_us && (rx_bq_wr_offset == rx_bq_rd_offset)) {
758 udelay(1);
759 rx_bq_wr_offset = higmac_readl_bits(ld, RX_BQ_WR_ADDR, BITS_RX_BQ_WR_ADDR);
760 }
761 if (!timeout_us)
762 return -1;
763
764 rx_bq_rd_offset += DESC_SIZE;
765 if (rx_bq_rd_offset >= (HIGMAC_HWQ_RX_BQ_DEPTH << DESC_BYTE_SHIFT))
766 rx_bq_rd_offset = 0;
767
768 #ifndef CONFIG_SYS_DCACHE_OFF
769 invalidate_dcache_range((uintptr_t)rx_bq_desc & ~(ARCH_DMA_MINALIGN - 1),
770 ALIGN((uintptr_t)rx_bq_desc + sizeof(*rx_bq_desc), ARCH_DMA_MINALIGN));
771 #endif
772 addr = rx_bq_desc->data_buff_addr;
773 #if defined(CONFIG_64BIT)
774 addr |= (u64)(rx_bq_desc->reserve4 >> Q_ADDR_HI8_OFFSET) << REG_BIT_WIDTH;
775 #endif
776 len = rx_bq_desc->data_len;
777 if (higmac_invalid_rxpkg_len(len)) {
778 higmac_writel_bits(ld, rx_bq_rd_offset, RX_BQ_RD_ADDR, BITS_RX_BQ_RD_ADDR);
779 addr -= NET_IP_ALIGN;
780 free((void *)(uintptr_t)addr);
781 addr = 0;
782 return -1;
783 }
784
785 show_gmac_recv_msg((char *)(uintptr_t)addr, len);
786
787 #ifndef CONFIG_SYS_DCACHE_OFF
788 invalidate_dcache_range(addr - NET_IP_ALIGN,
789 ALIGN((unsigned int)(addr + len), ARCH_DMA_MINALIGN));
790 #endif
791 memcpy((void *)net_rx_packets[0], (const void *)(uintptr_t)addr, len);
792 addr -= NET_IP_ALIGN;
793 free((void *)(uintptr_t)addr);
794 addr = 0;
795
796 higmac_writel_bits(ld, rx_bq_rd_offset, RX_BQ_RD_ADDR, BITS_RX_BQ_RD_ADDR);
797
798 /* NetRecive */
799 net_process_received_packet(net_rx_packets[0], len);
800
801 return 0;
802 }
803
higmac_wait_tx_rq_wr(struct higmac_netdev_local * ld)804 static int higmac_wait_tx_rq_wr(struct higmac_netdev_local *ld)
805 {
806 u32 tx_rq_wr_offset;
807 u32 tx_rq_rd_offset;
808 int timeout_us = 1000;
809
810 tx_rq_wr_offset = higmac_readl_bits(ld,
811 TX_RQ_WR_ADDR, BITS_TX_RQ_WR_ADDR);
812 tx_rq_rd_offset = higmac_readl_bits(ld,
813 TX_RQ_RD_ADDR, BITS_TX_RQ_RD_ADDR);
814
815 tx_rq_rd_offset += DESC_SIZE;
816 if (tx_rq_rd_offset >= (HIGMAC_HWQ_TX_RQ_DEPTH << DESC_BYTE_SHIFT))
817 tx_rq_rd_offset = 0;
818
819 while (--timeout_us && (tx_rq_rd_offset != tx_rq_wr_offset)) {
820 udelay(1);
821 tx_rq_wr_offset = higmac_readl_bits(ld,
822 TX_RQ_WR_ADDR, BITS_TX_RQ_WR_ADDR);
823 }
824
825 if (!timeout_us)
826 return -1;
827
828 higmac_writel_bits(ld, tx_rq_rd_offset, TX_RQ_RD_ADDR, BITS_TX_RQ_RD_ADDR);
829 if (g_gmac_debug)
830 printf("send packet!\n");
831
832 return 0;
833 }
834
higmac_send(struct eth_device * dev,void * packet,int length)835 static int higmac_send(struct eth_device *dev, void *packet, int length)
836 {
837 struct higmac_netdev_local *ld = (struct higmac_netdev_local *)dev->priv;
838 u32 tx_bq_wr_offset, tx_bq_rd_offset;
839 unsigned int tso_ver;
840 higmac_desc *tx_bq_desc = ld->tx_bq_addr;
841 phys_addr_t addr;
842
843 tx_bq_wr_offset = higmac_readl_bits(ld, TX_BQ_WR_ADDR, BITS_TX_BQ_WR_ADDR);
844 tx_bq_rd_offset = higmac_readl_bits(ld, TX_BQ_RD_ADDR, BITS_TX_BQ_RD_ADDR);
845 if (tx_bq_rd_offset != tx_bq_wr_offset) {
846 higmac_writel_bits(ld, tx_bq_rd_offset,
847 TX_BQ_WR_ADDR, BITS_TX_BQ_WR_ADDR);
848 return -1;
849 }
850
851 tso_ver = higmac_readl_bits(ld, CRF_MIN_PACKET, BIT_TSO_VERSION);
852
853 tx_bq_desc += (tx_bq_wr_offset >> DESC_BYTE_SHIFT);
854 addr = (phys_addr_t)(uintptr_t)packet;
855 tx_bq_desc->data_buff_addr = (u32)addr;
856 #if defined(CONFIG_64BIT)
857 tx_bq_desc->reserve3 = ((u64)addr >> REG_BIT_WIDTH) & TX_DESC_HI8_MASK;
858 #endif
859 tx_bq_desc->descvid = DESC_VLD_BUSY;
860
861 tx_bq_desc->fl = tso_ver ? 0 : DESC_FL_FULL;
862
863 tx_bq_desc->reserve1 = 0;
864 tx_bq_desc->data_len = length;
865 tx_bq_desc->buffer_len = HIETH_MAX_FRAME_SIZE - 1;
866 #ifndef CONFIG_SYS_DCACHE_OFF
867 flush_cache((uintptr_t)packet, ALIGN((u32)length, ARCH_DMA_MINALIGN));
868 flush_cache((uintptr_t)tx_bq_desc & ~(ARCH_DMA_MINALIGN - 1),
869 ALIGN(sizeof(*tx_bq_desc), ARCH_DMA_MINALIGN));
870 #endif
871
872 tx_bq_wr_offset += DESC_SIZE;
873 if (tx_bq_wr_offset >= (HIGMAC_HWQ_TX_BQ_DEPTH << DESC_BYTE_SHIFT))
874 tx_bq_wr_offset = 0;
875
876 higmac_writel_bits(ld, tx_bq_wr_offset,
877 TX_BQ_WR_ADDR, BITS_TX_BQ_WR_ADDR);
878
879 return higmac_wait_tx_rq_wr(ld);
880 }
881
882 #ifdef CFG_NET_PINCTRL
higmac_config_rgmii0(void)883 static void higmac_config_rgmii0(void)
884 {
885 writel(VALUE_MDCK0, PHY_ADDR_MDCK0);
886 writel(VALUE_MDIO0, PHY_ADDR_MDIO0);
887 writel(VALUE_EPHY0_CLK, PHY_ADDR_EPHY0_CLK);
888 writel(VALUE_EPHY0_RSTN, PHY_ADDR_EPHY0_RSTN);
889 writel(VALUE_RGMII0_TXCKOUT, PHY_ADDR_RGMII0_TXCKOUT);
890 writel(VALUE_RGMII0_TXD0, PHY_ADDR_RGMII0_TXD0);
891 writel(VALUE_RGMII0_TXD1, PHY_ADDR_RGMII0_TXD1);
892 writel(VALUE_RGMII0_TXD2, PHY_ADDR_RGMII0_TXD2);
893 writel(VALUE_RGMII0_TXD3, PHY_ADDR_RGMII0_TXD3);
894 writel(VALUE_RGMII0_TXEN, PHY_ADDR_RGMII0_TXEN);
895 writel(VALUE_RGMII0_RXCK, PHY_ADDR_RGMII0_RXCK);
896 writel(VALUE_RGMII0_RXD0, PHY_ADDR_RGMII0_RXD0);
897 writel(VALUE_RGMII0_RXD1, PHY_ADDR_RGMII0_RXD1);
898 writel(VALUE_RGMII0_RXD2, PHY_ADDR_RGMII0_RXD2);
899 writel(VALUE_RGMII0_RXD3, PHY_ADDR_RGMII0_RXD3);
900 writel(VALUE_RGMII0_RXDV, PHY_ADDR_RGMII0_RXDV);
901 }
902
higmac_config_rmii0(void)903 static void higmac_config_rmii0(void)
904 {
905 writel(VALUE_MDCK0, PHY_ADDR_MDCK0);
906 writel(VALUE_MDIO0, PHY_ADDR_MDIO0);
907 writel(VALUE_EPHY0_CLK, PHY_ADDR_EPHY0_CLK);
908 writel(VALUE_EPHY0_RSTN, PHY_ADDR_EPHY0_RSTN);
909 writel(VALUE_RMII0_CLK, PHY_ADDR_RMII0_CLK);
910 writel(VALUE_RMII0_TXD0, PHY_ADDR_RMII0_TXD0);
911 writel(VALUE_RMII0_TXD1, PHY_ADDR_RMII0_TXD1);
912 writel(VALUE_RMII0_TXEN, PHY_ADDR_RMII0_TXEN);
913 writel(VALUE_RMII0_RXD0, PHY_ADDR_RMII0_RXD0);
914 writel(VALUE_RMII0_RXD1, PHY_ADDR_RMII0_RXD1);
915 writel(VALUE_RMII0_RXDV, PHY_ADDR_RMII0_RXDV);
916 }
917
918 #if GMAC_AT_LEAST_2PORT
higmac_config_rgmii1(void)919 static void higmac_config_rgmii1(void)
920 {
921 writel(VALUE_MDCK1, PHY_ADDR_MDCK1);
922 writel(VALUE_MDIO1, PHY_ADDR_MDIO1);
923 writel(VALUE_EPHY1_CLK, PHY_ADDR_EPHY1_CLK);
924 writel(VALUE_EPHY1_RSTN, PHY_ADDR_EPHY1_RSTN);
925 writel(VALUE_RGMII1_TXCKOUT, PHY_ADDR_RGMII1_TXCKOUT);
926 writel(VALUE_RGMII1_TXD0, PHY_ADDR_RGMII1_TXD0);
927 writel(VALUE_RGMII1_TXD1, PHY_ADDR_RGMII1_TXD1);
928 writel(VALUE_RGMII1_TXD2, PHY_ADDR_RGMII1_TXD2);
929 writel(VALUE_RGMII1_TXD3, PHY_ADDR_RGMII1_TXD3);
930 writel(VALUE_RGMII1_TXEN, PHY_ADDR_RGMII1_TXEN);
931 writel(VALUE_RGMII1_RXCK, PHY_ADDR_RGMII1_RXCK);
932 writel(VALUE_RGMII1_RXD0, PHY_ADDR_RGMII1_RXD0);
933 writel(VALUE_RGMII1_RXD1, PHY_ADDR_RGMII1_RXD1);
934 writel(VALUE_RGMII1_RXD2, PHY_ADDR_RGMII1_RXD2);
935 writel(VALUE_RGMII1_RXD3, PHY_ADDR_RGMII1_RXD3);
936 writel(VALUE_RGMII1_RXDV, PHY_ADDR_RGMII1_RXDV);
937 }
938
higmac_config_rmii1(void)939 static void higmac_config_rmii1(void)
940 {
941 writel(VALUE_MDCK1, PHY_ADDR_MDCK1);
942 writel(VALUE_MDIO1, PHY_ADDR_MDIO1);
943 writel(VALUE_EPHY1_CLK, PHY_ADDR_EPHY1_CLK);
944 writel(VALUE_EPHY1_RSTN, PHY_ADDR_EPHY1_RSTN);
945 writel(VALUE_RMII1_CLK, PHY_ADDR_RMII1_CLK);
946 writel(VALUE_RMII1_TXD0, PHY_ADDR_RMII1_TXD0);
947 writel(VALUE_RMII1_TXD1, PHY_ADDR_RMII1_TXD1);
948 writel(VALUE_RMII1_TXEN, PHY_ADDR_RMII1_TXEN);
949 writel(VALUE_RMII1_RXD0, PHY_ADDR_RMII1_RXD0);
950 writel(VALUE_RMII1_RXD1, PHY_ADDR_RMII1_RXD1);
951 writel(VALUE_RMII1_RXDV, PHY_ADDR_RMII1_RXDV);
952 }
953 #endif
954
higmac_pinctrl_config(void)955 static void higmac_pinctrl_config(void)
956 {
957 if (g_higmac_board_info[0].phy_intf == INTERFACE_MODE_RMII) // 0:mac0
958 higmac_config_rmii0();
959 else if (g_higmac_board_info[0].phy_intf == INTERFACE_MODE_RGMII) // 0:mac0
960 higmac_config_rgmii0();
961
962 #if GMAC_AT_LEAST_2PORT
963 if (g_higmac_board_info[1].phy_intf == INTERFACE_MODE_RMII) // 1:mac1
964 higmac_config_rmii1();
965 else if (g_higmac_board_info[1].phy_intf == INTERFACE_MODE_RGMII) // 1:mac1
966 higmac_config_rgmii1();
967 #endif
968 }
969 #endif
970 static int g_gmac_hw_inited = 0;
higmac_hw_init(void)971 static void higmac_hw_init(void)
972 {
973 /* init once to save time */
974 if (!g_gmac_hw_inited) {
975 higmac_sys_init();
976
977 g_gmac_hw_inited = 1;
978 }
979 }
980
higmac_init(struct eth_device * dev,bd_t * bd)981 static int higmac_init(struct eth_device *dev, bd_t *bd)
982 {
983 struct higmac_netdev_local *ld = (struct higmac_netdev_local *)dev->priv;
984 char *mii_devname = g_higmac_board_info[ld->index].mii_name;
985 int phy_addr = g_higmac_board_info[ld->index].phy_addr;
986 enum if_mode phy_intf = g_higmac_board_info[ld->index].phy_intf;
987 u32 phy_id = 0;
988 int ret;
989
990 higmac_hw_init();
991
992 /* init once to save time */
993 if (!ld->initalized) {
994 if (!phy_detected(mii_devname, phy_addr, &phy_id))
995 return -1;
996
997 miiphy_reset(mii_devname, phy_addr);
998
999 if (phy_intf != INTERFACE_MODE_RGMII) {
1000 unsigned short val = 0;
1001 if (!miiphy_read(mii_devname, phy_addr, MII_CTRL1000, &val)) {
1002 val &= ~(PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD);
1003 miiphy_write(mii_devname, phy_addr, MII_CTRL1000, val);
1004 }
1005 }
1006
1007 higmac_glb_preinit_dummy(ld);
1008
1009 ret = higmac_set_hwq_depth(ld);
1010 if (ret) {
1011 printf("init eth%d hw desc queue depth fail!\n", ld->index);
1012 return ret;
1013 }
1014
1015 ret = higmac_init_hw_desc_queue(ld);
1016 if (ret) {
1017 printf("init eth%d hw desc queue fail!\n", ld->index);
1018 return ret;
1019 }
1020 ld->initalized = 1;
1021 }
1022
1023 ret = select_current_linked_phy(ld);
1024 if (ret)
1025 return ret;
1026
1027 higmac_net_set_mac_address(dev);
1028 higmac_desc_enable(ld, RX_OUTCFF_WR_DESC_ENA | RX_CFF_RD_DESC_ENA);
1029 higmac_writel_bits(ld, 1, PORT_EN, BITS_RX_EN);
1030
1031 higmac_writel_bits(ld, 1, PORT_EN, BITS_TX_EN);
1032 higmac_desc_enable(ld, TX_OUTCFF_WR_DESC_ENA | TX_CFF_RD_DESC_ENA);
1033
1034 return 0;
1035 }
1036
higmac_halt(struct eth_device * dev)1037 static void higmac_halt(struct eth_device *dev)
1038 {
1039 struct higmac_netdev_local *ld = (struct higmac_netdev_local *)dev->priv;
1040
1041 higmac_writel_bits(ld, 0, PORT_EN, BITS_RX_EN);
1042 higmac_desc_disable(ld, RX_OUTCFF_WR_DESC_ENA | RX_CFF_RD_DESC_ENA);
1043
1044 higmac_desc_disable(ld, TX_OUTCFF_WR_DESC_ENA | TX_CFF_RD_DESC_ENA);
1045 higmac_writel_bits(ld, 0, PORT_EN, BITS_TX_EN);
1046 }
1047
higmac_register_dev(port_id_t port_id)1048 static int higmac_register_dev(port_id_t port_id)
1049 {
1050 struct eth_device *dev;
1051
1052 dev = malloc(sizeof(*dev));
1053 if (dev == NULL)
1054 return -1;
1055 memset(dev, 0, sizeof(*dev));
1056
1057 dev->iobase = mac_iobase[port_id];
1058 dev->init = higmac_init;
1059 dev->halt = higmac_halt;
1060 dev->send = higmac_send;
1061 dev->recv = higmac_recv;
1062 dev->priv = &g_higmac_board_info[port_id].higmac_ld;
1063 snprintf(dev->name, sizeof(dev->name) - 1, "gmac%d", port_id);
1064
1065 eth_register(dev);
1066
1067 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
1068 struct mii_dev *bus = mdio_alloc();
1069
1070 if (!bus) {
1071 free(dev);
1072 debug("Failed to allocate MDIO bus\n");
1073 return -ENOMEM;
1074 }
1075
1076 bus->read = higmac_mdiobus_read;
1077 bus->write = higmac_mdiobus_write;
1078 snprintf(bus->name, sizeof(bus->name), mdio_bus[port_id]);
1079
1080 if (mdio_register(bus)) {
1081 mdio_free(bus);
1082 free(dev);
1083 return -1;
1084 }
1085 #endif
1086
1087 return 0;
1088 }
1089
higmac_initialize(bd_t * bis)1090 int higmac_initialize(bd_t *bis)
1091 {
1092 int ret;
1093
1094 parse_module_parameters();
1095
1096 #ifdef CFG_NET_PINCTRL
1097 /* Configure higmac pinctrl parameters in software */
1098 higmac_pinctrl_config();
1099 #endif
1100
1101 ret = higmac_register_dev(GSF0_PORT0);
1102 if (ret)
1103 return ret;
1104
1105 #if GMAC_AT_LEAST_2PORT
1106 ret = higmac_register_dev(GSF0_PORT1);
1107 if (ret)
1108 return ret;
1109 #endif
1110
1111 #if GMAC_AT_LEAST_3PORT
1112 ret = higmac_register_dev(GSF1_PORT0);
1113 if (ret)
1114 return ret;
1115 #endif
1116
1117 return 0;
1118 }
1119