blob: debe8ca3909cc068c25f92046f0a4bbd5aee8f03 [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
Patrick Delaunay79d191e2021-07-20 20:15:30 +02008#define LOG_CATEGORY UCLASS_ETH
9
Simon Glassdb9391e2016-01-17 14:52:00 -070010#include <common.h>
Simon Glass4fd8d072022-04-24 23:31:15 -060011#include <bootdev.h>
Simon Glass52f24232020-05-10 11:40:00 -060012#include <bootstage.h>
Simon Glassdb9391e2016-01-17 14:52:00 -070013#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060014#include <env.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060015#include <log.h>
Simon Glassdb9391e2016-01-17 14:52:00 -070016#include <net.h>
Sean Anderson97d0f9b2022-05-05 13:11:41 -040017#include <nvmem.h>
Simon Glass401d1c42020-10-30 21:38:53 -060018#include <asm/global_data.h>
Simon Glassdb9391e2016-01-17 14:52:00 -070019#include <dm/device-internal.h>
20#include <dm/uclass-internal.h>
Ramon Fried3eaac632019-07-18 21:43:30 +030021#include <net/pcap.h>
Simon Glassdb9391e2016-01-17 14:52:00 -070022#include "eth_internal.h"
Ye Li5fe419e2020-05-03 22:41:14 +080023#include <eth_phy.h>
Zhuo Wang4c88a342023-02-20 07:16:26 +000024#if defined(CONFIG_AMLOGIC_ETH)
25#include <amlogic/keyunify.h>
26#if defined MAC_ADDR_NEW
27#include <asm/amlogic/arch/register.h>
28#endif
29#endif
Simon Glassa7c45ec2016-01-30 15:45:14 -070030DECLARE_GLOBAL_DATA_PTR;
31
Simon Glassdb9391e2016-01-17 14:52:00 -070032/**
33 * struct eth_device_priv - private structure for each Ethernet device
34 *
35 * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
36 */
37struct eth_device_priv {
38 enum eth_state_t state;
Matthias Schifferfa795f42020-11-04 14:45:14 +010039 bool running;
Simon Glassdb9391e2016-01-17 14:52:00 -070040};
41
42/**
43 * struct eth_uclass_priv - The structure attached to the uclass itself
44 *
45 * @current: The Ethernet device that the network functions are using
46 */
47struct eth_uclass_priv {
48 struct udevice *current;
49};
50
51/* eth_errno - This stores the most recent failure code from DM functions */
52static int eth_errno;
53
54static struct eth_uclass_priv *eth_get_uclass_priv(void)
55{
56 struct uclass *uc;
Peng Fand2b70202020-05-03 22:41:13 +080057 int ret;
Simon Glassdb9391e2016-01-17 14:52:00 -070058
Peng Fand2b70202020-05-03 22:41:13 +080059 ret = uclass_get(UCLASS_ETH, &uc);
60 if (ret)
61 return NULL;
62
Simon Glassdb9391e2016-01-17 14:52:00 -070063 assert(uc);
Simon Glass0fd3d912020-12-22 19:30:28 -070064 return uclass_get_priv(uc);
Simon Glassdb9391e2016-01-17 14:52:00 -070065}
66
67void eth_set_current_to_next(void)
68{
69 struct eth_uclass_priv *uc_priv;
70
71 uc_priv = eth_get_uclass_priv();
72 if (uc_priv->current)
73 uclass_next_device(&uc_priv->current);
74 if (!uc_priv->current)
75 uclass_first_device(UCLASS_ETH, &uc_priv->current);
76}
77
78/*
79 * Typically this will simply return the active device.
80 * In the case where the most recent active device was unset, this will attempt
Michael Walle6e424b42021-02-24 17:30:44 +010081 * to return the device with sequence id 0 (which can be configured by the
82 * device tree). If this fails, fall back to just getting the first device.
83 * The latter is non-deterministic and depends on the order of the probing.
84 * If that device doesn't exist or fails to probe, this function will return
85 * NULL.
Simon Glassdb9391e2016-01-17 14:52:00 -070086 */
87struct udevice *eth_get_dev(void)
88{
89 struct eth_uclass_priv *uc_priv;
90
91 uc_priv = eth_get_uclass_priv();
Sean Andersonc3f02782020-09-12 17:45:43 -040092 if (!uc_priv)
93 return NULL;
94
Michael Walle6e424b42021-02-24 17:30:44 +010095 if (!uc_priv->current) {
96 eth_errno = uclass_get_device_by_seq(UCLASS_ETH, 0,
97 &uc_priv->current);
98 if (eth_errno)
Michal Suchanekc726fc02022-10-12 21:57:59 +020099 eth_errno = uclass_first_device_err(UCLASS_ETH,
100 &uc_priv->current);
Michal Suchanek0736f7a2022-10-12 21:58:02 +0200101 if (eth_errno)
102 uc_priv->current = NULL;
Michael Walle6e424b42021-02-24 17:30:44 +0100103 }
Simon Glassdb9391e2016-01-17 14:52:00 -0700104 return uc_priv->current;
105}
106
107/*
108 * Typically this will just store a device pointer.
109 * In case it was not probed, we will attempt to do so.
110 * dev may be NULL to unset the active device.
111 */
112void eth_set_dev(struct udevice *dev)
113{
114 if (dev && !device_active(dev)) {
115 eth_errno = device_probe(dev);
116 if (eth_errno)
117 dev = NULL;
118 }
119
120 eth_get_uclass_priv()->current = dev;
121}
122
123/*
124 * Find the udevice that either has the name passed in as devname or has an
125 * alias named devname.
126 */
127struct udevice *eth_get_dev_by_name(const char *devname)
128{
129 int seq = -1;
130 char *endp = NULL;
131 const char *startp = NULL;
132 struct udevice *it;
133 struct uclass *uc;
134 int len = strlen("eth");
Peng Fand2b70202020-05-03 22:41:13 +0800135 int ret;
Simon Glassdb9391e2016-01-17 14:52:00 -0700136
137 /* Must be longer than 3 to be an alias */
138 if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
139 startp = devname + len;
Simon Glass0b1284e2021-07-24 09:03:30 -0600140 seq = dectoul(startp, &endp);
Simon Glassdb9391e2016-01-17 14:52:00 -0700141 }
142
Peng Fand2b70202020-05-03 22:41:13 +0800143 ret = uclass_get(UCLASS_ETH, &uc);
144 if (ret)
145 return NULL;
146
Simon Glassdb9391e2016-01-17 14:52:00 -0700147 uclass_foreach_dev(it, uc) {
148 /*
Simon Glassdb9391e2016-01-17 14:52:00 -0700149 * We don't care about errors from probe here. Either they won't
150 * match an alias or it will match a literal name and we'll pick
151 * up the error when we try to probe again in eth_set_dev().
152 */
153 if (device_probe(it))
154 continue;
155 /* Check for the name or the sequence number to match */
156 if (strcmp(it->name, devname) == 0 ||
Simon Glass8b85dfc2020-12-16 21:20:07 -0700157 (endp > startp && dev_seq(it) == seq))
Simon Glassdb9391e2016-01-17 14:52:00 -0700158 return it;
159 }
160
161 return NULL;
162}
163
164unsigned char *eth_get_ethaddr(void)
165{
166 struct eth_pdata *pdata;
167
168 if (eth_get_dev()) {
Simon Glass0fd3d912020-12-22 19:30:28 -0700169 pdata = dev_get_plat(eth_get_dev());
Simon Glassdb9391e2016-01-17 14:52:00 -0700170 return pdata->enetaddr;
171 }
172
173 return NULL;
174}
175
176/* Set active state without calling start on the driver */
177int eth_init_state_only(void)
178{
179 struct udevice *current;
180 struct eth_device_priv *priv;
181
182 current = eth_get_dev();
183 if (!current || !device_active(current))
184 return -EINVAL;
185
Simon Glass0fd3d912020-12-22 19:30:28 -0700186 priv = dev_get_uclass_priv(current);
Simon Glassdb9391e2016-01-17 14:52:00 -0700187 priv->state = ETH_STATE_ACTIVE;
188
189 return 0;
190}
191
192/* Set passive state without calling stop on the driver */
193void eth_halt_state_only(void)
194{
195 struct udevice *current;
196 struct eth_device_priv *priv;
197
198 current = eth_get_dev();
199 if (!current || !device_active(current))
200 return;
201
Simon Glass0fd3d912020-12-22 19:30:28 -0700202 priv = dev_get_uclass_priv(current);
Simon Glassdb9391e2016-01-17 14:52:00 -0700203 priv->state = ETH_STATE_PASSIVE;
204}
205
206int eth_get_dev_index(void)
207{
208 if (eth_get_dev())
Simon Glass8b85dfc2020-12-16 21:20:07 -0700209 return dev_seq(eth_get_dev());
Simon Glassdb9391e2016-01-17 14:52:00 -0700210 return -1;
211}
212
213static int eth_write_hwaddr(struct udevice *dev)
214{
xypron.glpk@gmx.dec08248d2017-05-16 05:07:01 +0200215 struct eth_pdata *pdata;
Simon Glassdb9391e2016-01-17 14:52:00 -0700216 int ret = 0;
217
218 if (!dev || !device_active(dev))
219 return -EINVAL;
220
221 /* seq is valid since the device is active */
Simon Glass8b85dfc2020-12-16 21:20:07 -0700222 if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev_seq(dev))) {
Simon Glass0fd3d912020-12-22 19:30:28 -0700223 pdata = dev_get_plat(dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700224 if (!is_valid_ethaddr(pdata->enetaddr)) {
225 printf("\nError: %s address %pM illegal value\n",
226 dev->name, pdata->enetaddr);
227 return -EINVAL;
228 }
229
230 /*
231 * Drivers are allowed to decide not to implement this at
232 * run-time. E.g. Some devices may use it and some may not.
233 */
234 ret = eth_get_ops(dev)->write_hwaddr(dev);
235 if (ret == -ENOSYS)
236 ret = 0;
237 if (ret)
238 printf("\nWarning: %s failed to set MAC address\n",
239 dev->name);
240 }
241
242 return ret;
243}
244
245static int on_ethaddr(const char *name, const char *value, enum env_op op,
246 int flags)
247{
248 int index;
249 int retval;
250 struct udevice *dev;
251
252 /* look for an index after "eth" */
Simon Glass0b1284e2021-07-24 09:03:30 -0600253 index = dectoul(name + 3, NULL);
Simon Glassdb9391e2016-01-17 14:52:00 -0700254
Simon Glass99175912020-12-16 21:20:29 -0700255 retval = uclass_find_device_by_seq(UCLASS_ETH, index, &dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700256 if (!retval) {
Simon Glass0fd3d912020-12-22 19:30:28 -0700257 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700258 switch (op) {
259 case env_op_create:
260 case env_op_overwrite:
Joe Hershbergerfb8977c2019-09-13 19:21:16 -0500261 string_to_enetaddr(value, pdata->enetaddr);
Hannes Schmelzerc86ff7f2016-09-02 14:48:17 +0200262 eth_write_hwaddr(dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700263 break;
264 case env_op_delete:
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100265 memset(pdata->enetaddr, 0, ARP_HLEN);
Simon Glassdb9391e2016-01-17 14:52:00 -0700266 }
267 }
268
269 return 0;
270}
271U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
272
273int eth_init(void)
274{
Simon Glass00caae62017-08-03 12:22:12 -0600275 char *ethact = env_get("ethact");
276 char *ethrotate = env_get("ethrotate");
Simon Glassdb9391e2016-01-17 14:52:00 -0700277 struct udevice *current = NULL;
278 struct udevice *old_current;
279 int ret = -ENODEV;
280
281 /*
282 * When 'ethrotate' variable is set to 'no' and 'ethact' variable
283 * is already set to an ethernet device, we should stick to 'ethact'.
284 */
285 if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) {
286 if (ethact) {
287 current = eth_get_dev_by_name(ethact);
288 if (!current)
289 return -EINVAL;
290 }
291 }
292
293 if (!current) {
294 current = eth_get_dev();
295 if (!current) {
Heinrich Schuchardtad895912020-09-14 11:00:18 +0200296 log_err("No ethernet found.\n");
Simon Glassdb9391e2016-01-17 14:52:00 -0700297 return -ENODEV;
298 }
299 }
300
301 old_current = current;
302 do {
303 if (current) {
304 debug("Trying %s\n", current->name);
305
306 if (device_active(current)) {
307 ret = eth_get_ops(current)->start(current);
308 if (ret >= 0) {
309 struct eth_device_priv *priv =
Simon Glass0fd3d912020-12-22 19:30:28 -0700310 dev_get_uclass_priv(current);
Simon Glassdb9391e2016-01-17 14:52:00 -0700311
312 priv->state = ETH_STATE_ACTIVE;
Matthias Schifferfa795f42020-11-04 14:45:14 +0100313 priv->running = true;
Simon Glassdb9391e2016-01-17 14:52:00 -0700314 return 0;
315 }
316 } else {
317 ret = eth_errno;
318 }
319
320 debug("FAIL\n");
321 } else {
322 debug("PROBE FAIL\n");
323 }
324
325 /*
326 * If ethrotate is enabled, this will change "current",
327 * otherwise we will drop out of this while loop immediately
328 */
329 eth_try_another(0);
330 /* This will ensure the new "current" attempted to probe */
331 current = eth_get_dev();
332 } while (old_current != current);
333
334 return ret;
335}
336
337void eth_halt(void)
338{
339 struct udevice *current;
340 struct eth_device_priv *priv;
341
342 current = eth_get_dev();
Matthias Schifferfa795f42020-11-04 14:45:14 +0100343 if (!current)
344 return;
345
346 priv = dev_get_uclass_priv(current);
347 if (!priv || !priv->running)
Simon Glassdb9391e2016-01-17 14:52:00 -0700348 return;
349
350 eth_get_ops(current)->stop(current);
Matthias Schifferfa795f42020-11-04 14:45:14 +0100351 priv->state = ETH_STATE_PASSIVE;
352 priv->running = false;
Simon Glassdb9391e2016-01-17 14:52:00 -0700353}
354
355int eth_is_active(struct udevice *dev)
356{
357 struct eth_device_priv *priv;
358
359 if (!dev || !device_active(dev))
360 return 0;
361
362 priv = dev_get_uclass_priv(dev);
363 return priv->state == ETH_STATE_ACTIVE;
364}
365
366int eth_send(void *packet, int length)
367{
368 struct udevice *current;
369 int ret;
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 ret = eth_get_ops(current)->send(current, packet, length);
379 if (ret < 0) {
380 /* We cannot completely return the error at present */
381 debug("%s: send() returned error %d\n", __func__, ret);
382 }
Ramon Fried3eaac632019-07-18 21:43:30 +0300383#if defined(CONFIG_CMD_PCAP)
384 if (ret >= 0)
385 pcap_post(packet, length, true);
386#endif
Simon Glassdb9391e2016-01-17 14:52:00 -0700387 return ret;
388}
389
390int eth_rx(void)
391{
392 struct udevice *current;
393 uchar *packet;
394 int flags;
395 int ret;
396 int i;
397
398 current = eth_get_dev();
399 if (!current)
400 return -ENODEV;
401
Alexander Grafa532e2f2018-03-15 15:07:09 +0100402 if (!eth_is_active(current))
Simon Glassdb9391e2016-01-17 14:52:00 -0700403 return -EINVAL;
404
405 /* Process up to 32 packets at one time */
406 flags = ETH_RECV_CHECK_DEVICE;
Patrick Wildt36ea0ca2020-10-07 11:03:30 +0200407 for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
Simon Glassdb9391e2016-01-17 14:52:00 -0700408 ret = eth_get_ops(current)->recv(current, flags, &packet);
409 flags = 0;
410 if (ret > 0)
411 net_process_received_packet(packet, ret);
412 if (ret >= 0 && eth_get_ops(current)->free_pkt)
413 eth_get_ops(current)->free_pkt(current, packet, ret);
414 if (ret <= 0)
415 break;
416 }
417 if (ret == -EAGAIN)
418 ret = 0;
419 if (ret < 0) {
420 /* We cannot completely return the error at present */
421 debug("%s: recv() returned error %d\n", __func__, ret);
422 }
423 return ret;
424}
425
426int eth_initialize(void)
427{
428 int num_devices = 0;
429 struct udevice *dev;
430
431 eth_common_init();
432
433 /*
434 * Devices need to write the hwaddr even if not started so that Linux
435 * will have access to the hwaddr that u-boot stored for the device.
436 * This is accomplished by attempting to probe each device and calling
437 * their write_hwaddr() operation.
438 */
Mario Six3ce43042018-04-27 14:52:56 +0200439 uclass_first_device_check(UCLASS_ETH, &dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700440 if (!dev) {
Heinrich Schuchardtad895912020-09-14 11:00:18 +0200441 log_err("No ethernet found.\n");
Simon Glassdb9391e2016-01-17 14:52:00 -0700442 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
443 } else {
Simon Glass00caae62017-08-03 12:22:12 -0600444 char *ethprime = env_get("ethprime");
Simon Glassdb9391e2016-01-17 14:52:00 -0700445 struct udevice *prime_dev = NULL;
446
447 if (ethprime)
448 prime_dev = eth_get_dev_by_name(ethprime);
449 if (prime_dev) {
450 eth_set_dev(prime_dev);
451 eth_current_changed();
452 } else {
453 eth_set_dev(NULL);
454 }
455
456 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
457 do {
Simon Glass552da332020-12-16 21:20:16 -0700458 if (device_active(dev)) {
Michael Walle19820db2019-10-22 01:03:10 +0200459 if (num_devices)
460 printf(", ");
Simon Glassdb9391e2016-01-17 14:52:00 -0700461
Simon Glass8b85dfc2020-12-16 21:20:07 -0700462 printf("eth%d: %s", dev_seq(dev), dev->name);
Simon Glassdb9391e2016-01-17 14:52:00 -0700463
Michael Walle19820db2019-10-22 01:03:10 +0200464 if (ethprime && dev == prime_dev)
465 printf(" [PRIME]");
466 }
Simon Glassdb9391e2016-01-17 14:52:00 -0700467
468 eth_write_hwaddr(dev);
469
Simon Glass552da332020-12-16 21:20:16 -0700470 if (device_active(dev))
Michael Walle19820db2019-10-22 01:03:10 +0200471 num_devices++;
Mario Six3ce43042018-04-27 14:52:56 +0200472 uclass_next_device_check(&dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700473 } while (dev);
474
Michael Walle19820db2019-10-22 01:03:10 +0200475 if (!num_devices)
Heinrich Schuchardtad895912020-09-14 11:00:18 +0200476 log_err("No ethernet found.\n");
Simon Glassdb9391e2016-01-17 14:52:00 -0700477 putc('\n');
478 }
479
480 return num_devices;
481}
482
483static int eth_post_bind(struct udevice *dev)
484{
Simon Glass4fd8d072022-04-24 23:31:15 -0600485 int ret;
486
Simon Glassdb9391e2016-01-17 14:52:00 -0700487 if (strchr(dev->name, ' ')) {
488 printf("\nError: eth device name \"%s\" has a space!\n",
489 dev->name);
490 return -EINVAL;
491 }
492
Ye Li5fe419e2020-05-03 22:41:14 +0800493#ifdef CONFIG_DM_ETH_PHY
494 eth_phy_binds_nodes(dev);
495#endif
Simon Glass4fd8d072022-04-24 23:31:15 -0600496 if (CONFIG_IS_ENABLED(BOOTDEV_ETH)) {
497 ret = bootdev_setup_for_dev(dev, "eth_bootdev");
498 if (ret)
499 return log_msg_ret("bootdev", ret);
500 }
Ye Li5fe419e2020-05-03 22:41:14 +0800501
Simon Glassdb9391e2016-01-17 14:52:00 -0700502 return 0;
503}
504
505static int eth_pre_unbind(struct udevice *dev)
506{
507 /* Don't hang onto a pointer that is going away */
508 if (dev == eth_get_uclass_priv()->current)
509 eth_set_dev(NULL);
510
511 return 0;
512}
513
Thierry Reding379af672019-05-20 17:59:57 +0200514static bool eth_dev_get_mac_address(struct udevice *dev, u8 mac[ARP_HLEN])
515{
Simon Glass177e7f92021-01-13 20:29:47 -0700516#if CONFIG_IS_ENABLED(OF_CONTROL)
Thierry Reding379af672019-05-20 17:59:57 +0200517 const uint8_t *p;
Sean Anderson97d0f9b2022-05-05 13:11:41 -0400518 struct nvmem_cell mac_cell;
Thierry Reding379af672019-05-20 17:59:57 +0200519
520 p = dev_read_u8_array_ptr(dev, "mac-address", ARP_HLEN);
521 if (!p)
522 p = dev_read_u8_array_ptr(dev, "local-mac-address", ARP_HLEN);
523
Sean Anderson97d0f9b2022-05-05 13:11:41 -0400524 if (p) {
525 memcpy(mac, p, ARP_HLEN);
526 return true;
527 }
528
529 if (nvmem_cell_get_by_name(dev, "mac-address", &mac_cell))
Thierry Reding379af672019-05-20 17:59:57 +0200530 return false;
531
Sean Anderson97d0f9b2022-05-05 13:11:41 -0400532 return !nvmem_cell_read(&mac_cell, mac, ARP_HLEN);
Thierry Reding379af672019-05-20 17:59:57 +0200533#else
534 return false;
535#endif
536}
Zhuo Wang4c88a342023-02-20 07:16:26 +0000537#if defined(CONFIG_AMLOGIC_ETH)
YoungSoo Shinf0489792025-02-13 10:48:13 +0900538__weak int eth_get_efuse_mac(struct udevice *dev)
Zhuo Wang4c88a342023-02-20 07:16:26 +0000539{
540#ifndef CONFIG_UNIFY_KEY_MANAGE
541 debug("\nWarning: %s MAC addresses is not from dtb\n",
542 dev->name);
543 return -1;
544#else
545#define MAC_MAX_LEN 17
546 int i = 0;
547 int err = 0, exist = 0;
548 ssize_t keysize = 0;
549 const char* seedNum = "0x1234";
550 unsigned char buf[MAC_MAX_LEN+1] = {0};
551 struct eth_pdata *pdata = dev_get_plat(dev);
Thierry Reding379af672019-05-20 17:59:57 +0200552
Zhuo Wang4c88a342023-02-20 07:16:26 +0000553 err = key_unify_init(seedNum, NULL);
554 if (err)
555 return err;
556
557 err = key_unify_query_exist("mac", &exist);
558 if (err || (!exist))
559 return -EEXIST;
560
561 err = key_unify_query_size("mac", &keysize);
562 if (err)
563 return err;
564
565 if (keysize != MAC_MAX_LEN) {
566 return -EINVAL;
567 }
568
569 err = key_unify_read("mac", buf, keysize);
570 if (err)
571 return err;
572
573 for (i=0; i<6; i++) {
574 buf[i*3 + 2] = '\0';
575 pdata->enetaddr[i] = simple_strtoul((char *)&buf[i*3], NULL, 16);
576 }
577
578 return key_unify_uninit();
579#endif
580}
581static char env_str[32];
582#endif
Simon Glassdb9391e2016-01-17 14:52:00 -0700583static int eth_post_probe(struct udevice *dev)
584{
Simon Glass0fd3d912020-12-22 19:30:28 -0700585 struct eth_device_priv *priv = dev_get_uclass_priv(dev);
586 struct eth_pdata *pdata = dev_get_plat(dev);
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100587 unsigned char env_enetaddr[ARP_HLEN];
Michal Simekd4172c92020-03-16 11:36:17 +0100588 char *source = "DT";
Simon Glassdb9391e2016-01-17 14:52:00 -0700589
590#if defined(CONFIG_NEEDS_MANUAL_RELOC)
591 struct eth_ops *ops = eth_get_ops(dev);
592 static int reloc_done;
593
594 if (!reloc_done) {
595 if (ops->start)
596 ops->start += gd->reloc_off;
597 if (ops->send)
598 ops->send += gd->reloc_off;
599 if (ops->recv)
600 ops->recv += gd->reloc_off;
601 if (ops->free_pkt)
602 ops->free_pkt += gd->reloc_off;
603 if (ops->stop)
604 ops->stop += gd->reloc_off;
Simon Glassdb9391e2016-01-17 14:52:00 -0700605 if (ops->mcast)
606 ops->mcast += gd->reloc_off;
Simon Glassdb9391e2016-01-17 14:52:00 -0700607 if (ops->write_hwaddr)
608 ops->write_hwaddr += gd->reloc_off;
609 if (ops->read_rom_hwaddr)
610 ops->read_rom_hwaddr += gd->reloc_off;
611
612 reloc_done++;
613 }
614#endif
615
616 priv->state = ETH_STATE_INIT;
Matthias Schifferfa795f42020-11-04 14:45:14 +0100617 priv->running = false;
Simon Glassdb9391e2016-01-17 14:52:00 -0700618
Thierry Reding379af672019-05-20 17:59:57 +0200619 /* Check if the device has a valid MAC address in device tree */
620 if (!eth_dev_get_mac_address(dev, pdata->enetaddr) ||
621 !is_valid_ethaddr(pdata->enetaddr)) {
Michal Simekd4172c92020-03-16 11:36:17 +0100622 source = "ROM";
Thierry Reding379af672019-05-20 17:59:57 +0200623 /* Check if the device has a MAC address in ROM */
624 if (eth_get_ops(dev)->read_rom_hwaddr)
625 eth_get_ops(dev)->read_rom_hwaddr(dev);
626 }
Zhuo Wang4c88a342023-02-20 07:16:26 +0000627#if defined(CONFIG_AMLOGIC_ETH)
628 eth_get_efuse_mac(dev);
629 if (is_valid_ethaddr(pdata->enetaddr)) {
630 sprintf((char *)env_str, "%02x:%02x:%02x:%02x:%02x:%02x", pdata->enetaddr[0],
631 pdata->enetaddr[1], pdata->enetaddr[2], pdata->enetaddr[3],
632 pdata->enetaddr[4], pdata->enetaddr[5]);
633 env_set("ethaddr", (const char *)env_str);
634 eth_env_set_enetaddr_by_index("eth", dev_seq(dev),
635 pdata->enetaddr);
636 } else {
637#if defined MAC_ADDR_NEW
638 unsigned int reg18;
639 reg18 = *(unsigned int *)SYSCTRL_SEC_STATUS_REG18;
640 sprintf((char *)env_str,"02:ad:%02x:01:%02x:%02x", ((reg18 >> 24) & 0xff),
641 ((reg18 >> 8) & 0xff), (reg18 & 0xff));
642 printf("MACADDR:%s(from sec_reg)\n", env_str);
643 env_set("ethaddr", (const char *)env_str);
644#else
645 uint8_t buff[16];
646 if (get_chip_id(&buff[0], sizeof(buff)) == 0) {
647 sprintf((char *)env_str,"02:%02x:%02x:%02x:%02x:%02x", buff[8],
648 buff[7], buff[6], buff[5], buff[4]);
649 printf("MACADDR:%s(from chipid)\n", env_str);
650 env_set("ethaddr", (const char *)env_str);
651 }
652#endif
653#endif
654 eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
655 if (!is_zero_ethaddr(env_enetaddr)) {
656 if (!is_zero_ethaddr(pdata->enetaddr) &&
657 memcmp(pdata->enetaddr, env_enetaddr, ARP_HLEN)) {
658 printf("\nWarning: %s MAC addresses don't match:\n",
659 dev->name);
660 printf("Address in %s is\t\t%pM\n",
661 source, pdata->enetaddr);
662 printf("Address in environment is\t%pM\n",
663 env_enetaddr);
664 }
Simon Glassdb9391e2016-01-17 14:52:00 -0700665
Zhuo Wang4c88a342023-02-20 07:16:26 +0000666 /* Override the ROM MAC address */
667 memcpy(pdata->enetaddr, env_enetaddr, ARP_HLEN);
668 } else if (is_valid_ethaddr(pdata->enetaddr)) {
669 eth_env_set_enetaddr_by_index("eth", dev_seq(dev),
670 pdata->enetaddr);
671 } else if (is_zero_ethaddr(pdata->enetaddr) ||
672 !is_valid_ethaddr(pdata->enetaddr)) {
673#ifdef CONFIG_NET_RANDOM_ETHADDR
674 net_random_ethaddr(pdata->enetaddr);
675 printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
676 dev->name, dev_seq(dev), pdata->enetaddr);
677 eth_env_set_enetaddr_by_index("eth", dev_seq(dev),
678 pdata->enetaddr);
679#else
680 printf("\nError: %s address not set.\n",
Simon Glassdb9391e2016-01-17 14:52:00 -0700681 dev->name);
Zhuo Wang4c88a342023-02-20 07:16:26 +0000682 return -EINVAL;
683#endif
Simon Glassdb9391e2016-01-17 14:52:00 -0700684 }
685
Zhuo Wang4c88a342023-02-20 07:16:26 +0000686 eth_write_hwaddr(dev);
687#if defined(CONFIG_AMLOGIC_ETH)
Simon Glassdb9391e2016-01-17 14:52:00 -0700688 }
Zhuo Wang4c88a342023-02-20 07:16:26 +0000689#endif
Simon Glassdb9391e2016-01-17 14:52:00 -0700690 return 0;
691}
692
693static int eth_pre_remove(struct udevice *dev)
694{
Simon Glass0fd3d912020-12-22 19:30:28 -0700695 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glassdb9391e2016-01-17 14:52:00 -0700696
697 eth_get_ops(dev)->stop(dev);
698
699 /* clear the MAC address */
oliver@schinagl.nla40db6d2016-11-25 16:30:19 +0100700 memset(pdata->enetaddr, 0, ARP_HLEN);
Simon Glassdb9391e2016-01-17 14:52:00 -0700701
702 return 0;
703}
704
Michael Walle82a3c9e2021-02-25 16:51:11 +0100705UCLASS_DRIVER(ethernet) = {
706 .name = "ethernet",
Simon Glassdb9391e2016-01-17 14:52:00 -0700707 .id = UCLASS_ETH,
708 .post_bind = eth_post_bind,
709 .pre_unbind = eth_pre_unbind,
710 .post_probe = eth_post_probe,
711 .pre_remove = eth_pre_remove,
Simon Glass41575d82020-12-03 16:55:17 -0700712 .priv_auto = sizeof(struct eth_uclass_priv),
713 .per_device_auto = sizeof(struct eth_device_priv),
Simon Glassdb9391e2016-01-17 14:52:00 -0700714 .flags = DM_UC_FLAG_SEQ_ALIAS,
715};