1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2020 NXP
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <net.h>
9 #include <dm/device-internal.h>
10 #include <dm/uclass-internal.h>
11 #include <dm/lists.h>
12 
13 struct eth_phy_device_priv {
14 	struct mii_dev *mdio_bus;
15 };
16 
eth_phy_binds_nodes(struct udevice * eth_dev)17 int eth_phy_binds_nodes(struct udevice *eth_dev)
18 {
19 	ofnode mdio_node, phy_node;
20 	const char *node_name;
21 	int ret;
22 
23 	mdio_node = dev_read_subnode(eth_dev, "mdio");
24 	if (!ofnode_valid(mdio_node)) {
25 		debug("%s: %s mdio subnode not found!", __func__,
26 		      eth_dev->name);
27 		return -ENXIO;
28 	}
29 
30 	ofnode_for_each_subnode(phy_node, mdio_node) {
31 		node_name = ofnode_get_name(phy_node);
32 
33 		debug("* Found child node: '%s'\n", node_name);
34 
35 		ret = device_bind_driver_to_node(eth_dev,
36 						 "eth_phy_generic_drv",
37 						 node_name, phy_node, NULL);
38 		if (ret) {
39 			debug("  - Eth phy binding error: %d\n", ret);
40 			continue;
41 		}
42 
43 		debug("  - bound phy device: '%s'\n", node_name);
44 	}
45 
46 	return 0;
47 }
48 
eth_phy_set_mdio_bus(struct udevice * eth_dev,struct mii_dev * mdio_bus)49 int eth_phy_set_mdio_bus(struct udevice *eth_dev, struct mii_dev *mdio_bus)
50 {
51 	struct udevice *dev;
52 	struct eth_phy_device_priv *uc_priv;
53 
54 	for (uclass_first_device(UCLASS_ETH_PHY, &dev); dev;
55 	     uclass_next_device(&dev)) {
56 		if (dev->parent == eth_dev) {
57 			uc_priv = (struct eth_phy_device_priv *)(dev_get_uclass_priv(dev));
58 
59 			if (!uc_priv->mdio_bus)
60 				uc_priv->mdio_bus = mdio_bus;
61 		}
62 	}
63 
64 	return 0;
65 }
66 
eth_phy_get_mdio_bus(struct udevice * eth_dev)67 struct mii_dev *eth_phy_get_mdio_bus(struct udevice *eth_dev)
68 {
69 	int ret;
70 	struct udevice *phy_dev;
71 	struct eth_phy_device_priv *uc_priv;
72 
73 	/* Will probe the parent of phy device, then phy device */
74 	ret = uclass_get_device_by_phandle(UCLASS_ETH_PHY, eth_dev,
75 					   "phy-handle", &phy_dev);
76 	if (!ret) {
77 		if (eth_dev != phy_dev->parent) {
78 			/*
79 			 * phy_dev is shared and controlled by
80 			 * other eth controller
81 			 */
82 			uc_priv = (struct eth_phy_device_priv *)(dev_get_uclass_priv(phy_dev));
83 			if (uc_priv->mdio_bus)
84 				printf("Get shared mii bus on %s\n", eth_dev->name);
85 			else
86 				printf("Can't get shared mii bus on %s\n", eth_dev->name);
87 
88 			return uc_priv->mdio_bus;
89 		}
90 	} else {
91 		printf("FEC: can't find phy-handle\n");
92 	}
93 
94 	return NULL;
95 }
96 
eth_phy_get_addr(struct udevice * dev)97 int eth_phy_get_addr(struct udevice *dev)
98 {
99 	struct ofnode_phandle_args phandle_args;
100 	int reg;
101 
102 	if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
103 				       &phandle_args)) {
104 		debug("Failed to find phy-handle");
105 		return -ENODEV;
106 	}
107 
108 	reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
109 
110 	return reg;
111 }
112 
113 UCLASS_DRIVER(eth_phy_generic) = {
114 	.id		= UCLASS_ETH_PHY,
115 	.name		= "eth_phy_generic",
116 	.per_device_auto	= sizeof(struct eth_phy_device_priv),
117 };
118 
119 U_BOOT_DRIVER(eth_phy_generic_drv) = {
120 	.name		= "eth_phy_generic_drv",
121 	.id		= UCLASS_ETH_PHY,
122 };
123