xref: /OK3568_Linux_fs/u-boot/net/eth_common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2001-2015
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  * Joe Hershberger, National Instruments
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <dm.h>
11*4882a593Smuzhiyun #include <miiphy.h>
12*4882a593Smuzhiyun #include <net.h>
13*4882a593Smuzhiyun #include "eth_internal.h"
14*4882a593Smuzhiyun 
eth_parse_enetaddr(const char * addr,uchar * enetaddr)15*4882a593Smuzhiyun void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	char *end;
18*4882a593Smuzhiyun 	int i;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	for (i = 0; i < 6; ++i) {
21*4882a593Smuzhiyun 		enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
22*4882a593Smuzhiyun 		if (addr)
23*4882a593Smuzhiyun 			addr = (*end) ? end + 1 : end;
24*4882a593Smuzhiyun 	}
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
eth_env_get_enetaddr(const char * name,uchar * enetaddr)27*4882a593Smuzhiyun int eth_env_get_enetaddr(const char *name, uchar *enetaddr)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	eth_parse_enetaddr(env_get(name), enetaddr);
30*4882a593Smuzhiyun 	return is_valid_ethaddr(enetaddr);
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
eth_env_set_enetaddr(const char * name,const uchar * enetaddr)33*4882a593Smuzhiyun int eth_env_set_enetaddr(const char *name, const uchar *enetaddr)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	char buf[ARP_HLEN_ASCII + 1];
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	if (eth_env_get_enetaddr(name, (uchar *)buf))
38*4882a593Smuzhiyun 		return -EEXIST;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	sprintf(buf, "%pM", enetaddr);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	return env_set(name, buf);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun 
eth_env_get_enetaddr_by_index(const char * base_name,int index,uchar * enetaddr)45*4882a593Smuzhiyun int eth_env_get_enetaddr_by_index(const char *base_name, int index,
46*4882a593Smuzhiyun 				 uchar *enetaddr)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	char enetvar[32];
49*4882a593Smuzhiyun 	sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
50*4882a593Smuzhiyun 	return eth_env_get_enetaddr(enetvar, enetaddr);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
eth_env_set_enetaddr_by_index(const char * base_name,int index,uchar * enetaddr)53*4882a593Smuzhiyun int eth_env_set_enetaddr_by_index(const char *base_name, int index,
54*4882a593Smuzhiyun 				 uchar *enetaddr)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	char enetvar[32];
57*4882a593Smuzhiyun 	sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
58*4882a593Smuzhiyun 	return eth_env_set_enetaddr(enetvar, enetaddr);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
eth_common_init(void)61*4882a593Smuzhiyun void eth_common_init(void)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
64*4882a593Smuzhiyun #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
65*4882a593Smuzhiyun 	miiphy_init();
66*4882a593Smuzhiyun #endif
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun #ifdef CONFIG_PHYLIB
69*4882a593Smuzhiyun 	phy_init();
70*4882a593Smuzhiyun #endif
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
eth_mac_skip(int index)73*4882a593Smuzhiyun int eth_mac_skip(int index)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	char enetvar[15];
76*4882a593Smuzhiyun 	char *skip_state;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
79*4882a593Smuzhiyun 	skip_state = env_get(enetvar);
80*4882a593Smuzhiyun 	return skip_state != NULL;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
eth_current_changed(void)83*4882a593Smuzhiyun void eth_current_changed(void)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	char *act = env_get("ethact");
86*4882a593Smuzhiyun 	char *ethrotate;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/*
89*4882a593Smuzhiyun 	 * The call to eth_get_dev() below has a side effect of rotating
90*4882a593Smuzhiyun 	 * ethernet device if uc_priv->current == NULL. This is not what
91*4882a593Smuzhiyun 	 * we want when 'ethrotate' variable is 'no'.
92*4882a593Smuzhiyun 	 */
93*4882a593Smuzhiyun 	ethrotate = env_get("ethrotate");
94*4882a593Smuzhiyun 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
95*4882a593Smuzhiyun 		return;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	/* update current ethernet name */
98*4882a593Smuzhiyun 	if (eth_get_dev()) {
99*4882a593Smuzhiyun 		if (act == NULL || strcmp(act, eth_get_name()) != 0)
100*4882a593Smuzhiyun 			env_set("ethact", eth_get_name());
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 	/*
103*4882a593Smuzhiyun 	 * remove the variable completely if there is no active
104*4882a593Smuzhiyun 	 * interface
105*4882a593Smuzhiyun 	 */
106*4882a593Smuzhiyun 	else if (act != NULL)
107*4882a593Smuzhiyun 		env_set("ethact", NULL);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
eth_try_another(int first_restart)110*4882a593Smuzhiyun void eth_try_another(int first_restart)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	static void *first_failed;
113*4882a593Smuzhiyun 	char *ethrotate;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/*
116*4882a593Smuzhiyun 	 * Do not rotate between network interfaces when
117*4882a593Smuzhiyun 	 * 'ethrotate' variable is set to 'no'.
118*4882a593Smuzhiyun 	 */
119*4882a593Smuzhiyun 	ethrotate = env_get("ethrotate");
120*4882a593Smuzhiyun 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
121*4882a593Smuzhiyun 		return;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	if (!eth_get_dev())
124*4882a593Smuzhiyun 		return;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	if (first_restart)
127*4882a593Smuzhiyun 		first_failed = eth_get_dev();
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	eth_set_current_to_next();
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	eth_current_changed();
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	if (first_failed == eth_get_dev())
134*4882a593Smuzhiyun 		net_restart_wrap = 1;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
eth_set_current(void)137*4882a593Smuzhiyun void eth_set_current(void)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	static char *act;
140*4882a593Smuzhiyun 	static int  env_changed_id;
141*4882a593Smuzhiyun 	int	env_id;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	env_id = get_env_id();
144*4882a593Smuzhiyun 	if ((act == NULL) || (env_changed_id != env_id)) {
145*4882a593Smuzhiyun 		act = env_get("ethact");
146*4882a593Smuzhiyun 		env_changed_id = env_id;
147*4882a593Smuzhiyun 	}
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	if (act == NULL) {
150*4882a593Smuzhiyun 		char *ethprime = env_get("ethprime");
151*4882a593Smuzhiyun 		void *dev = NULL;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		if (ethprime)
154*4882a593Smuzhiyun 			dev = eth_get_dev_by_name(ethprime);
155*4882a593Smuzhiyun 		if (dev)
156*4882a593Smuzhiyun 			eth_set_dev(dev);
157*4882a593Smuzhiyun 		else
158*4882a593Smuzhiyun 			eth_set_dev(NULL);
159*4882a593Smuzhiyun 	} else {
160*4882a593Smuzhiyun 		eth_set_dev(eth_get_dev_by_name(act));
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	eth_current_changed();
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
eth_get_name(void)166*4882a593Smuzhiyun const char *eth_get_name(void)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	return eth_get_dev() ? eth_get_dev()->name : "unknown";
169*4882a593Smuzhiyun }
170