xref: /OK3568_Linux_fs/u-boot/net/mdio-uclass.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright 2019
4*4882a593Smuzhiyun  * Alex Marginean, NXP
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <miiphy.h>
10*4882a593Smuzhiyun #include <dm/device-internal.h>
11*4882a593Smuzhiyun #include <dm/uclass-internal.h>
12*4882a593Smuzhiyun 
dm_mdio_probe_devices(void)13*4882a593Smuzhiyun void dm_mdio_probe_devices(void)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct udevice *it;
16*4882a593Smuzhiyun 	struct uclass *uc;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	uclass_get(UCLASS_MDIO, &uc);
19*4882a593Smuzhiyun 	uclass_foreach_dev(it, uc) {
20*4882a593Smuzhiyun 		device_probe(it);
21*4882a593Smuzhiyun 	}
22*4882a593Smuzhiyun }
23*4882a593Smuzhiyun 
dm_mdio_post_bind(struct udevice * dev)24*4882a593Smuzhiyun static int dm_mdio_post_bind(struct udevice *dev)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	/*
27*4882a593Smuzhiyun 	 * MDIO command doesn't like spaces in names, don't allow them to keep
28*4882a593Smuzhiyun 	 * it happy
29*4882a593Smuzhiyun 	 */
30*4882a593Smuzhiyun 	if (strchr(dev->name, ' ')) {
31*4882a593Smuzhiyun 		debug("\nError: MDIO device name \"%s\" has a space!\n",
32*4882a593Smuzhiyun 		      dev->name);
33*4882a593Smuzhiyun 		return -EINVAL;
34*4882a593Smuzhiyun 	}
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	return 0;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun  * Following read/write/reset functions are registered with legacy MII code.
41*4882a593Smuzhiyun  * These are called for PHY operations by upper layers and we further call the
42*4882a593Smuzhiyun  * DM MDIO driver functions.
43*4882a593Smuzhiyun  */
mdio_read(struct mii_dev * mii_bus,int addr,int devad,int reg)44*4882a593Smuzhiyun static int mdio_read(struct mii_dev *mii_bus, int addr, int devad, int reg)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct udevice *dev = mii_bus->priv;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	return mdio_get_ops(dev)->read(dev, addr, devad, reg);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
mdio_write(struct mii_dev * mii_bus,int addr,int devad,int reg,u16 val)51*4882a593Smuzhiyun static int mdio_write(struct mii_dev *mii_bus, int addr, int devad, int reg,
52*4882a593Smuzhiyun 		      u16 val)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	struct udevice *dev = mii_bus->priv;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	return mdio_get_ops(dev)->write(dev, addr, devad, reg, val);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
mdio_reset(struct mii_dev * mii_bus)59*4882a593Smuzhiyun static int mdio_reset(struct mii_dev *mii_bus)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct udevice *dev = mii_bus->priv;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (mdio_get_ops(dev)->reset)
64*4882a593Smuzhiyun 		return mdio_get_ops(dev)->reset(dev);
65*4882a593Smuzhiyun 	else
66*4882a593Smuzhiyun 		return 0;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
dm_mdio_post_probe(struct udevice * dev)69*4882a593Smuzhiyun static int dm_mdio_post_probe(struct udevice *dev)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	pdata->mii_bus = mdio_alloc();
74*4882a593Smuzhiyun 	pdata->mii_bus->read = mdio_read;
75*4882a593Smuzhiyun 	pdata->mii_bus->write = mdio_write;
76*4882a593Smuzhiyun 	pdata->mii_bus->reset = mdio_reset;
77*4882a593Smuzhiyun 	pdata->mii_bus->priv = dev;
78*4882a593Smuzhiyun 	strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return mdio_register(pdata->mii_bus);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
dm_mdio_pre_remove(struct udevice * dev)83*4882a593Smuzhiyun static int dm_mdio_pre_remove(struct udevice *dev)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
86*4882a593Smuzhiyun 	struct mdio_ops *ops = mdio_get_ops(dev);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	if (ops->reset)
89*4882a593Smuzhiyun 		ops->reset(dev);
90*4882a593Smuzhiyun 	mdio_unregister(pdata->mii_bus);
91*4882a593Smuzhiyun 	mdio_free(pdata->mii_bus);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	return 0;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
dm_mdio_phy_connect(struct udevice * dev,int addr,struct udevice * ethdev,phy_interface_t interface)96*4882a593Smuzhiyun struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
97*4882a593Smuzhiyun 				       struct udevice *ethdev,
98*4882a593Smuzhiyun 				       phy_interface_t interface)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	if (device_probe(dev))
103*4882a593Smuzhiyun 		return 0;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	return phy_connect(pdata->mii_bus, addr, ethdev, interface);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun UCLASS_DRIVER(mdio) = {
109*4882a593Smuzhiyun 	.id = UCLASS_MDIO,
110*4882a593Smuzhiyun 	.name = "mdio",
111*4882a593Smuzhiyun 	.post_bind  = dm_mdio_post_bind,
112*4882a593Smuzhiyun 	.post_probe = dm_mdio_post_probe,
113*4882a593Smuzhiyun 	.pre_remove = dm_mdio_pre_remove,
114*4882a593Smuzhiyun 	.per_device_auto_alloc_size = sizeof(struct mdio_perdev_priv),
115*4882a593Smuzhiyun };
116