• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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