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