blob: 950a48d520db93a63b152cb07cd113f97e92b22c [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassdb9391e2016-01-17 14:52:00 -07002/*
3 * (C) Copyright 2001-2015
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * Joe Hershberger, National Instruments
Simon Glassdb9391e2016-01-17 14:52:00 -07006 */
7
8#include <common.h>
9#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060010#include <env.h>
Simon Glassdb9391e2016-01-17 14:52:00 -070011#include <net.h>
12#include <dm/device-internal.h>
13#include <dm/uclass-internal.h>
Ramon Fried3eaac632019-07-18 21:43:30 +030014#include <net/pcap.h>
Simon Glassdb9391e2016-01-17 14:52:00 -070015#include "eth_internal.h"
16
Simon Glassa7c45ec2016-01-30 15:45:14 -070017DECLARE_GLOBAL_DATA_PTR;
18
Simon Glassdb9391e2016-01-17 14:52:00 -070019/**
20 * struct eth_device_priv - private structure for each Ethernet device
21 *
22 * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
23 */
24struct eth_device_priv {
25 enum eth_state_t state;
26};
27
28/**
29 * struct eth_uclass_priv - The structure attached to the uclass itself
30 *
31 * @current: The Ethernet device that the network functions are using
32 */
33struct eth_uclass_priv {
34 struct udevice *current;
35};
36
37/* eth_errno - This stores the most recent failure code from DM functions */
38static int eth_errno;
39
40static struct eth_uclass_priv *eth_get_uclass_priv(void)
41{
42 struct uclass *uc;
Peng Fand2b70202020-05-03 22:41:13 +080043 int ret;
Simon Glassdb9391e2016-01-17 14:52:00 -070044
Peng Fand2b70202020-05-03 22:41:13 +080045 ret = uclass_get(UCLASS_ETH, &uc);
46 if (ret)
47 return NULL;
48
Simon Glassdb9391e2016-01-17 14:52:00 -070049 assert(uc);
50 return uc->priv;
51}
52
53void eth_set_current_to_next(void)
54{
55 struct eth_uclass_priv *uc_priv;
56
57 uc_priv = eth_get_uclass_priv();
58 if (uc_priv->current)
59 uclass_next_device(&uc_priv->current);
60 if (!uc_priv->current)
61 uclass_first_device(UCLASS_ETH, &uc_priv->current);
62}
63
64/*
65 * Typically this will simply return the active device.
66 * In the case where the most recent active device was unset, this will attempt
67 * to return the first device. If that device doesn't exist or fails to probe,
68 * this function will return NULL.
69 */
70struct udevice *eth_get_dev(void)
71{
72 struct eth_uclass_priv *uc_priv;
73
74 uc_priv = eth_get_uclass_priv();
75 if (!uc_priv->current)
76 eth_errno = uclass_first_device(UCLASS_ETH,
77 &uc_priv->current);
78 return uc_priv->current;
79}
80
81/*
82 * Typically this will just store a device pointer.
83 * In case it was not probed, we will attempt to do so.
84 * dev may be NULL to unset the active device.
85 */
86void eth_set_dev(struct udevice *dev)
87{
88 if (dev && !device_active(dev)) {
89 eth_errno = device_probe(dev);
90 if (eth_errno)
91 dev = NULL;
92 }
93
94 eth_get_uclass_priv()->current = dev;
95}
96
97/*
98 * Find the udevice that either has the name passed in as devname or has an
99 * alias named devname.
100 */
101struct udevice *eth_get_dev_by_name(const char *devname)
102{
103 int seq = -1;
104 char *endp = NULL;
105 const char *startp = NULL;
106 struct udevice *it;
107 struct uclass *uc;
108 int len = strlen("eth");
Peng Fand2b70202020-05-03 22:41:13 +0800109 int ret;
Simon Glassdb9391e2016-01-17 14:52:00 -0700110
111 /* Must be longer than 3 to be an alias */
112 if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
113 startp = devname + len;
114 seq = simple_strtoul(startp, &endp, 10);
115 }
116
Peng Fand2b70202020-05-03 22:41:13 +0800117 ret = uclass_get(UCLASS_ETH, &uc);
118 if (ret)
119 return NULL;
120
Simon Glassdb9391e2016-01-17 14:52:00 -0700121 uclass_foreach_dev(it, uc) {
122 /*
123 * We need the seq to be valid, so try to probe it.
124 * If the probe fails, the seq will not match since it will be
125 * -1 instead of what we are looking for.
126 * We don't care about errors from probe here. Either they won't
127 * match an alias or it will match a literal name and we'll pick
128 * up the error when we try to probe again in eth_set_dev().
129 */
130 if (device_probe(it))
131 continue;
132 /* Check for the name or the sequence number to match */
133 if (strcmp(it->name, devname) == 0 ||
134 (endp > startp && it->seq == seq))
135 return it;
136 }
137
138 return NULL;
139}
140
141unsigned char *eth_get_ethaddr(void)
142{
143 struct eth_pdata *pdata;
144
145 if (eth_get_dev()) {
146 pdata = eth_get_dev()->platdata;
147 return pdata->enetaddr;
148 }
149
150 return NULL;
151}
152
153/* Set active state without calling start on the driver */
154int eth_init_state_only(void)
155{
156 struct udevice *current;
157 struct eth_device_priv *priv;
158
159 current = eth_get_dev();
160 if (!current || !device_active(current))
161 return -EINVAL;
162
163 priv = current->uclass_priv;
164 priv->state = ETH_STATE_ACTIVE;
165
166 return 0;
167}
168
169/* Set passive state without calling stop on the driver */
170void eth_halt_state_only(void)
171{
172 struct udevice *current;
173 struct eth_device_priv *priv;
174
175 current = eth_get_dev();
176 if (!current || !device_active(current))
177 return;
178
179 priv = current->uclass_priv;
180 priv->state = ETH_STATE_PASSIVE;
181}
182
183int eth_get_dev_index(void)
184{
185 if (eth_get_dev())
186 return eth_get_dev()->seq;
187 return -1;
188}
189
190static int eth_write_hwaddr(struct udevice *dev)
191{
xypron.glpk@gmx.dec08248d2017-05-16 05:07:01 +0200192 struct eth_pdata *pdata;
Simon Glassdb9391e2016-01-17 14:52:00 -0700193 int ret = 0;
194
195 if (!dev || !device_active(dev))
196 return -EINVAL;
197
198 /* seq is valid since the device is active */
199 if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
xypron.glpk@gmx.dec08248d2017-05-16 05:07:01 +0200200 pdata = dev->platdata;
Simon Glassdb9391e2016-01-17 14:52:00 -0700201 if (!is_valid_ethaddr(pdata->enetaddr)) {
202 printf("\nError: %s address %pM illegal value\n",
203 dev->name, pdata->enetaddr);
204 return -EINVAL;
205 }
206
207 /*
208 * Drivers are allowed to decide not to implement this at
209 * run-time. E.g. Some devices may use it and some may not.
210 */
211 ret = eth_get_ops(dev)->write_hwaddr(dev);
212 if (ret == -ENOSYS)
213 ret = 0;
214 if (ret)
215 printf("\nWarning: %s failed to set MAC address\n",
216 dev->name);
217 }
218
219 return ret;
220}
221
222static int on_ethaddr(const char *name, const char *value, enum env_op op,
223 int flags)
224{
225 int index;
226 int retval;
227 struct udevice *dev;
228
229 /* look for an index after "eth" */
230 index = simple_strtoul(name + 3, NULL, 10);
231
232 retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev);
233 if (!retval) {
234 struct eth_pdata *pdata = dev->platdata;
235 switch (op) {
236 case env_op_create:
237 case env_op_overwrite:
Joe Hershbergerfb8977c2019-09-13 19:21:16 -0500238 string_to_enetaddr(value, pdata->enetaddr);
Hannes Schmelzerc86ff7f2016-09-02 14:48:17 +0200239 eth_write_hwaddr(dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700240 break;
241 case env_op_delete:
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100242 memset(pdata->enetaddr, 0, ARP_HLEN);
Simon Glassdb9391e2016-01-17 14:52:00 -0700243 }
244 }
245
246 return 0;
247}
248U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
249
250int eth_init(void)
251{
Simon Glass00caae62017-08-03 12:22:12 -0600252 char *ethact = env_get("ethact");
253 char *ethrotate = env_get("ethrotate");
Simon Glassdb9391e2016-01-17 14:52:00 -0700254 struct udevice *current = NULL;
255 struct udevice *old_current;
256 int ret = -ENODEV;
257
258 /*
259 * When 'ethrotate' variable is set to 'no' and 'ethact' variable
260 * is already set to an ethernet device, we should stick to 'ethact'.
261 */
262 if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) {
263 if (ethact) {
264 current = eth_get_dev_by_name(ethact);
265 if (!current)
266 return -EINVAL;
267 }
268 }
269
270 if (!current) {
271 current = eth_get_dev();
272 if (!current) {
273 printf("No ethernet found.\n");
274 return -ENODEV;
275 }
276 }
277
278 old_current = current;
279 do {
280 if (current) {
281 debug("Trying %s\n", current->name);
282
283 if (device_active(current)) {
284 ret = eth_get_ops(current)->start(current);
285 if (ret >= 0) {
286 struct eth_device_priv *priv =
287 current->uclass_priv;
288
289 priv->state = ETH_STATE_ACTIVE;
290 return 0;
291 }
292 } else {
293 ret = eth_errno;
294 }
295
296 debug("FAIL\n");
297 } else {
298 debug("PROBE FAIL\n");
299 }
300
301 /*
302 * If ethrotate is enabled, this will change "current",
303 * otherwise we will drop out of this while loop immediately
304 */
305 eth_try_another(0);
306 /* This will ensure the new "current" attempted to probe */
307 current = eth_get_dev();
308 } while (old_current != current);
309
310 return ret;
311}
312
313void eth_halt(void)
314{
315 struct udevice *current;
316 struct eth_device_priv *priv;
317
318 current = eth_get_dev();
Joe Hershberger68acb512018-07-02 14:47:46 -0500319 if (!current || !eth_is_active(current))
Simon Glassdb9391e2016-01-17 14:52:00 -0700320 return;
321
322 eth_get_ops(current)->stop(current);
323 priv = current->uclass_priv;
Jean-Jacques Hiblotc3211702018-08-09 16:17:41 +0200324 if (priv)
325 priv->state = ETH_STATE_PASSIVE;
Simon Glassdb9391e2016-01-17 14:52:00 -0700326}
327
328int eth_is_active(struct udevice *dev)
329{
330 struct eth_device_priv *priv;
331
332 if (!dev || !device_active(dev))
333 return 0;
334
335 priv = dev_get_uclass_priv(dev);
336 return priv->state == ETH_STATE_ACTIVE;
337}
338
339int eth_send(void *packet, int length)
340{
341 struct udevice *current;
342 int ret;
343
344 current = eth_get_dev();
345 if (!current)
346 return -ENODEV;
347
Alexander Grafa532e2f2018-03-15 15:07:09 +0100348 if (!eth_is_active(current))
Simon Glassdb9391e2016-01-17 14:52:00 -0700349 return -EINVAL;
350
351 ret = eth_get_ops(current)->send(current, packet, length);
352 if (ret < 0) {
353 /* We cannot completely return the error at present */
354 debug("%s: send() returned error %d\n", __func__, ret);
355 }
Ramon Fried3eaac632019-07-18 21:43:30 +0300356#if defined(CONFIG_CMD_PCAP)
357 if (ret >= 0)
358 pcap_post(packet, length, true);
359#endif
Simon Glassdb9391e2016-01-17 14:52:00 -0700360 return ret;
361}
362
363int eth_rx(void)
364{
365 struct udevice *current;
366 uchar *packet;
367 int flags;
368 int ret;
369 int i;
370
371 current = eth_get_dev();
372 if (!current)
373 return -ENODEV;
374
Alexander Grafa532e2f2018-03-15 15:07:09 +0100375 if (!eth_is_active(current))
Simon Glassdb9391e2016-01-17 14:52:00 -0700376 return -EINVAL;
377
378 /* Process up to 32 packets at one time */
379 flags = ETH_RECV_CHECK_DEVICE;
380 for (i = 0; i < 32; i++) {
381 ret = eth_get_ops(current)->recv(current, flags, &packet);
382 flags = 0;
383 if (ret > 0)
384 net_process_received_packet(packet, ret);
385 if (ret >= 0 && eth_get_ops(current)->free_pkt)
386 eth_get_ops(current)->free_pkt(current, packet, ret);
387 if (ret <= 0)
388 break;
389 }
390 if (ret == -EAGAIN)
391 ret = 0;
392 if (ret < 0) {
393 /* We cannot completely return the error at present */
394 debug("%s: recv() returned error %d\n", __func__, ret);
395 }
396 return ret;
397}
398
399int eth_initialize(void)
400{
401 int num_devices = 0;
402 struct udevice *dev;
403
404 eth_common_init();
405
406 /*
407 * Devices need to write the hwaddr even if not started so that Linux
408 * will have access to the hwaddr that u-boot stored for the device.
409 * This is accomplished by attempting to probe each device and calling
410 * their write_hwaddr() operation.
411 */
Mario Six3ce43042018-04-27 14:52:56 +0200412 uclass_first_device_check(UCLASS_ETH, &dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700413 if (!dev) {
414 printf("No ethernet found.\n");
415 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
416 } else {
Simon Glass00caae62017-08-03 12:22:12 -0600417 char *ethprime = env_get("ethprime");
Simon Glassdb9391e2016-01-17 14:52:00 -0700418 struct udevice *prime_dev = NULL;
419
420 if (ethprime)
421 prime_dev = eth_get_dev_by_name(ethprime);
422 if (prime_dev) {
423 eth_set_dev(prime_dev);
424 eth_current_changed();
425 } else {
426 eth_set_dev(NULL);
427 }
428
429 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
430 do {
Michael Walle19820db2019-10-22 01:03:10 +0200431 if (dev->seq != -1) {
432 if (num_devices)
433 printf(", ");
Simon Glassdb9391e2016-01-17 14:52:00 -0700434
Michael Walle19820db2019-10-22 01:03:10 +0200435 printf("eth%d: %s", dev->seq, dev->name);
Simon Glassdb9391e2016-01-17 14:52:00 -0700436
Michael Walle19820db2019-10-22 01:03:10 +0200437 if (ethprime && dev == prime_dev)
438 printf(" [PRIME]");
439 }
Simon Glassdb9391e2016-01-17 14:52:00 -0700440
441 eth_write_hwaddr(dev);
442
Michael Walle19820db2019-10-22 01:03:10 +0200443 if (dev->seq != -1)
444 num_devices++;
Mario Six3ce43042018-04-27 14:52:56 +0200445 uclass_next_device_check(&dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700446 } while (dev);
447
Michael Walle19820db2019-10-22 01:03:10 +0200448 if (!num_devices)
449 printf("No ethernet found.\n");
Simon Glassdb9391e2016-01-17 14:52:00 -0700450 putc('\n');
451 }
452
453 return num_devices;
454}
455
456static int eth_post_bind(struct udevice *dev)
457{
458 if (strchr(dev->name, ' ')) {
459 printf("\nError: eth device name \"%s\" has a space!\n",
460 dev->name);
461 return -EINVAL;
462 }
463
464 return 0;
465}
466
467static int eth_pre_unbind(struct udevice *dev)
468{
469 /* Don't hang onto a pointer that is going away */
470 if (dev == eth_get_uclass_priv()->current)
471 eth_set_dev(NULL);
472
473 return 0;
474}
475
Thierry Reding379af672019-05-20 17:59:57 +0200476static bool eth_dev_get_mac_address(struct udevice *dev, u8 mac[ARP_HLEN])
477{
478#if IS_ENABLED(CONFIG_OF_CONTROL)
479 const uint8_t *p;
480
481 p = dev_read_u8_array_ptr(dev, "mac-address", ARP_HLEN);
482 if (!p)
483 p = dev_read_u8_array_ptr(dev, "local-mac-address", ARP_HLEN);
484
485 if (!p)
486 return false;
487
488 memcpy(mac, p, ARP_HLEN);
489
490 return true;
491#else
492 return false;
493#endif
494}
495
Simon Glassdb9391e2016-01-17 14:52:00 -0700496static int eth_post_probe(struct udevice *dev)
497{
498 struct eth_device_priv *priv = dev->uclass_priv;
499 struct eth_pdata *pdata = dev->platdata;
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100500 unsigned char env_enetaddr[ARP_HLEN];
Michal Simekd4172c92020-03-16 11:36:17 +0100501 char *source = "DT";
Simon Glassdb9391e2016-01-17 14:52:00 -0700502
503#if defined(CONFIG_NEEDS_MANUAL_RELOC)
504 struct eth_ops *ops = eth_get_ops(dev);
505 static int reloc_done;
506
507 if (!reloc_done) {
508 if (ops->start)
509 ops->start += gd->reloc_off;
510 if (ops->send)
511 ops->send += gd->reloc_off;
512 if (ops->recv)
513 ops->recv += gd->reloc_off;
514 if (ops->free_pkt)
515 ops->free_pkt += gd->reloc_off;
516 if (ops->stop)
517 ops->stop += gd->reloc_off;
Simon Glassdb9391e2016-01-17 14:52:00 -0700518 if (ops->mcast)
519 ops->mcast += gd->reloc_off;
Simon Glassdb9391e2016-01-17 14:52:00 -0700520 if (ops->write_hwaddr)
521 ops->write_hwaddr += gd->reloc_off;
522 if (ops->read_rom_hwaddr)
523 ops->read_rom_hwaddr += gd->reloc_off;
524
525 reloc_done++;
526 }
527#endif
528
529 priv->state = ETH_STATE_INIT;
530
Thierry Reding379af672019-05-20 17:59:57 +0200531 /* Check if the device has a valid MAC address in device tree */
532 if (!eth_dev_get_mac_address(dev, pdata->enetaddr) ||
533 !is_valid_ethaddr(pdata->enetaddr)) {
Michal Simekd4172c92020-03-16 11:36:17 +0100534 source = "ROM";
Thierry Reding379af672019-05-20 17:59:57 +0200535 /* Check if the device has a MAC address in ROM */
536 if (eth_get_ops(dev)->read_rom_hwaddr)
537 eth_get_ops(dev)->read_rom_hwaddr(dev);
538 }
Simon Glassdb9391e2016-01-17 14:52:00 -0700539
Simon Glass35affd72017-08-03 12:22:14 -0600540 eth_env_get_enetaddr_by_index("eth", dev->seq, env_enetaddr);
Simon Glassdb9391e2016-01-17 14:52:00 -0700541 if (!is_zero_ethaddr(env_enetaddr)) {
542 if (!is_zero_ethaddr(pdata->enetaddr) &&
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100543 memcmp(pdata->enetaddr, env_enetaddr, ARP_HLEN)) {
Simon Glassdb9391e2016-01-17 14:52:00 -0700544 printf("\nWarning: %s MAC addresses don't match:\n",
545 dev->name);
Michal Simekd4172c92020-03-16 11:36:17 +0100546 printf("Address in %s is\t\t%pM\n",
547 source, pdata->enetaddr);
548 printf("Address in environment is\t%pM\n",
Simon Glassdb9391e2016-01-17 14:52:00 -0700549 env_enetaddr);
550 }
551
552 /* Override the ROM MAC address */
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100553 memcpy(pdata->enetaddr, env_enetaddr, ARP_HLEN);
Simon Glassdb9391e2016-01-17 14:52:00 -0700554 } else if (is_valid_ethaddr(pdata->enetaddr)) {
Simon Glassfd1e9592017-08-03 12:22:11 -0600555 eth_env_set_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
Michal Simekd4172c92020-03-16 11:36:17 +0100556 printf("\nWarning: %s using MAC address from %s\n",
557 dev->name, source);
Siva Durga Prasad Paladuguaa555fe2016-11-02 12:52:13 +0100558 } else if (is_zero_ethaddr(pdata->enetaddr) ||
559 !is_valid_ethaddr(pdata->enetaddr)) {
Simon Glassdb9391e2016-01-17 14:52:00 -0700560#ifdef CONFIG_NET_RANDOM_ETHADDR
561 net_random_ethaddr(pdata->enetaddr);
562 printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
563 dev->name, dev->seq, pdata->enetaddr);
564#else
565 printf("\nError: %s address not set.\n",
566 dev->name);
567 return -EINVAL;
568#endif
569 }
570
Thierry Redingb743bbd2019-05-20 17:59:56 +0200571 eth_write_hwaddr(dev);
572
Simon Glassdb9391e2016-01-17 14:52:00 -0700573 return 0;
574}
575
576static int eth_pre_remove(struct udevice *dev)
577{
578 struct eth_pdata *pdata = dev->platdata;
579
580 eth_get_ops(dev)->stop(dev);
581
582 /* clear the MAC address */
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100583 memset(pdata->enetaddr, 0, ARP_HLEN);
Simon Glassdb9391e2016-01-17 14:52:00 -0700584
585 return 0;
586}
587
588UCLASS_DRIVER(eth) = {
589 .name = "eth",
590 .id = UCLASS_ETH,
591 .post_bind = eth_post_bind,
592 .pre_unbind = eth_pre_unbind,
593 .post_probe = eth_post_probe,
594 .pre_remove = eth_pre_remove,
595 .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
596 .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
597 .flags = DM_UC_FLAG_SEQ_ALIAS,
598};