1f40a31e6SJoe Hershberger // SPDX-License-Identifier: GPL-2.0+
2f40a31e6SJoe Hershberger /*
3f40a31e6SJoe Hershberger  * Copyright (c) 2018 National Instruments
4f40a31e6SJoe Hershberger  * Copyright (c) 2018 Joe Hershberger <joe.hershberger@ni.com>
5f40a31e6SJoe Hershberger  */
6f40a31e6SJoe Hershberger 
7f40a31e6SJoe Hershberger #include <common.h>
8f40a31e6SJoe Hershberger #include <asm/eth-raw-os.h>
9f40a31e6SJoe Hershberger #include <dm.h>
10f40a31e6SJoe Hershberger #include <errno.h>
11f40a31e6SJoe Hershberger #include <dm/device-internal.h>
12f40a31e6SJoe Hershberger #include <dm/lists.h>
13f40a31e6SJoe Hershberger 
eth_raw_bus_post_bind(struct udevice * dev)14f40a31e6SJoe Hershberger static int eth_raw_bus_post_bind(struct udevice *dev)
15f40a31e6SJoe Hershberger {
16f40a31e6SJoe Hershberger 	struct sandbox_eth_raw_if_nameindex *ni, *i;
17f40a31e6SJoe Hershberger 	struct udevice *child;
18f40a31e6SJoe Hershberger 	struct eth_sandbox_raw_priv *priv;
19f40a31e6SJoe Hershberger 	char *ub_ifname;
20f40a31e6SJoe Hershberger 	static const char ub_ifname_pfx[] = "host_";
21f40a31e6SJoe Hershberger 	u32 skip_localhost = 0;
22f40a31e6SJoe Hershberger 
23f40a31e6SJoe Hershberger 	ni = sandbox_eth_raw_if_nameindex();
24f40a31e6SJoe Hershberger 	if (!ni)
25f40a31e6SJoe Hershberger 		return -EINVAL;
26f40a31e6SJoe Hershberger 
27f40a31e6SJoe Hershberger 	dev_read_u32(dev, "skip-localhost", &skip_localhost);
28f40a31e6SJoe Hershberger 	for (i = ni; !(i->if_index == 0 && !i->if_name); i++) {
29f40a31e6SJoe Hershberger 		int local = sandbox_eth_raw_os_is_local(i->if_name);
30f40a31e6SJoe Hershberger 
31f40a31e6SJoe Hershberger 		if (local < 0)
32f40a31e6SJoe Hershberger 			continue;
33f40a31e6SJoe Hershberger 		if (skip_localhost && local)
34f40a31e6SJoe Hershberger 			continue;
35f40a31e6SJoe Hershberger 
36f40a31e6SJoe Hershberger 		ub_ifname = calloc(IFNAMSIZ + sizeof(ub_ifname_pfx), 1);
37f40a31e6SJoe Hershberger 		strcpy(ub_ifname, ub_ifname_pfx);
38f40a31e6SJoe Hershberger 		strncat(ub_ifname, i->if_name, IFNAMSIZ);
39f40a31e6SJoe Hershberger 		device_bind_driver(dev, "eth_sandbox_raw", ub_ifname, &child);
40f40a31e6SJoe Hershberger 
41f40a31e6SJoe Hershberger 		device_set_name_alloced(child);
42f40a31e6SJoe Hershberger 		device_probe(child);
43f40a31e6SJoe Hershberger 		priv = dev_get_priv(child);
44f40a31e6SJoe Hershberger 		if (priv) {
45*e628bba7SSimon Glass 			strcpy(priv->host_ifname, i->if_name);
46f40a31e6SJoe Hershberger 			priv->host_ifindex = i->if_index;
47f40a31e6SJoe Hershberger 			priv->local = local;
48f40a31e6SJoe Hershberger 		}
49f40a31e6SJoe Hershberger 	}
50f40a31e6SJoe Hershberger 
51f40a31e6SJoe Hershberger 	sandbox_eth_raw_if_freenameindex(ni);
52f40a31e6SJoe Hershberger 
53f40a31e6SJoe Hershberger 	return 0;
54f40a31e6SJoe Hershberger }
55f40a31e6SJoe Hershberger 
56f40a31e6SJoe Hershberger static const struct udevice_id sandbox_eth_raw_bus_ids[] = {
57f40a31e6SJoe Hershberger 	{ .compatible = "sandbox,eth-raw-bus" },
58f40a31e6SJoe Hershberger 	{ }
59f40a31e6SJoe Hershberger };
60f40a31e6SJoe Hershberger 
61f40a31e6SJoe Hershberger U_BOOT_DRIVER(sandbox_eth_raw_bus) = {
62f40a31e6SJoe Hershberger 	.name       = "sb_eth_raw_bus",
63f40a31e6SJoe Hershberger 	.id         = UCLASS_SIMPLE_BUS,
64f40a31e6SJoe Hershberger 	.of_match   = sandbox_eth_raw_bus_ids,
65f40a31e6SJoe Hershberger 	.bind       = eth_raw_bus_post_bind,
66f40a31e6SJoe Hershberger };
67