]> Git Repo - u-boot.git/blob - net/mdio-uclass.c
Merge commit 'f3f86fd1fe0fb288356bff78f8a6fa2edf89e3fc' as 'lib/lwip/lwip'
[u-boot.git] / net / mdio-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2019
4  * Alex Marginean, NXP
5  */
6
7 #include <dm.h>
8 #include <dm/lists.h>
9 #include <eth_phy.h>
10 #include <log.h>
11 #include <malloc.h>
12 #include <miiphy.h>
13 #include <dm/device-internal.h>
14 #include <dm/device_compat.h>
15 #include <dm/of_extra.h>
16 #include <dm/uclass-internal.h>
17 #include <linux/compat.h>
18 #include <linux/delay.h>
19
20 #define DEFAULT_GPIO_RESET_DELAY        10      /* in microseconds */
21
22 void dm_mdio_probe_devices(void)
23 {
24         struct udevice *it;
25         struct uclass *uc;
26
27         uclass_get(UCLASS_MDIO, &uc);
28         uclass_foreach_dev(it, uc) {
29                 device_probe(it);
30         }
31 }
32
33 static int dm_mdio_post_bind(struct udevice *dev)
34 {
35         const char *dt_name;
36
37         /* set a custom name for the MDIO device, if present in DT */
38         if (dev_has_ofnode(dev)) {
39                 dt_name = dev_read_string(dev, "device-name");
40                 if (dt_name) {
41                         debug("renaming dev %s to %s\n", dev->name, dt_name);
42                         device_set_name(dev, dt_name);
43                 }
44         }
45
46         /*
47          * MDIO command doesn't like spaces in names, don't allow them to keep
48          * it happy
49          */
50         if (strchr(dev->name, ' ')) {
51                 debug("\nError: MDIO device name \"%s\" has a space!\n",
52                       dev->name);
53                 return -EINVAL;
54         }
55
56 #if CONFIG_IS_ENABLED(OF_REAL)
57         return dm_scan_fdt_dev(dev);
58 #else
59         return 0;
60 #endif
61 }
62
63 int dm_mdio_read(struct udevice *mdio_dev, int addr, int devad, int reg)
64 {
65         struct mdio_ops *ops = mdio_get_ops(mdio_dev);
66
67         if (!ops->read)
68                 return -ENOSYS;
69
70         return ops->read(mdio_dev, addr, devad, reg);
71 }
72
73 int dm_mdio_write(struct udevice *mdio_dev, int addr, int devad, int reg,
74                   u16 val)
75 {
76         struct mdio_ops *ops = mdio_get_ops(mdio_dev);
77
78         if (!ops->write)
79                 return -ENOSYS;
80
81         return ops->write(mdio_dev, addr, devad, reg, val);
82 }
83
84 int dm_mdio_reset(struct udevice *mdio_dev)
85 {
86         struct mdio_ops *ops = mdio_get_ops(mdio_dev);
87         struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdio_dev);
88         struct mii_dev *mii_bus = pdata->mii_bus;
89
90         if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&mii_bus->reset_gpiod)) {
91                 dm_gpio_set_value(&mii_bus->reset_gpiod, 1);
92                 udelay(mii_bus->reset_delay_us);
93                 dm_gpio_set_value(&mii_bus->reset_gpiod, 0);
94                 if (mii_bus->reset_post_delay_us > 0)
95                         udelay(mii_bus->reset_post_delay_us);
96         }
97
98         if (!ops->reset)
99                 return 0;
100
101         return ops->reset(mdio_dev);
102 }
103
104 /*
105  * Following read/write/reset functions are registered with legacy MII code.
106  * These are called for PHY operations by upper layers and we further call the
107  * DM MDIO driver functions.
108  */
109 static int mdio_read(struct mii_dev *mii_bus, int addr, int devad, int reg)
110 {
111         return dm_mdio_read(mii_bus->priv, addr, devad, reg);
112 }
113
114 static int mdio_write(struct mii_dev *mii_bus, int addr, int devad, int reg,
115                       u16 val)
116 {
117         return dm_mdio_write(mii_bus->priv, addr, devad, reg, val);
118 }
119
120 static int mdio_reset(struct mii_dev *mii_bus)
121 {
122         return dm_mdio_reset(mii_bus->priv);
123 }
124
125 static int mdio_bind_phy_nodes(struct udevice *mdio_dev)
126 {
127         ofnode mdio_node, phy_node;
128         struct udevice *phy_dev;
129         const char *node_name;
130         int ret;
131
132         mdio_node = dev_ofnode(mdio_dev);
133         if (!ofnode_valid(mdio_node)) {
134                 dev_dbg(mdio_dev, "invalid ofnode for mdio_dev\n");
135                 return -ENXIO;
136         }
137
138         ofnode_for_each_subnode(phy_node, mdio_node) {
139                 node_name = ofnode_get_name(phy_node);
140                 dev_dbg(mdio_dev, "* Found child node: '%s'\n", node_name);
141                 ret = device_bind_driver_to_node(mdio_dev,
142                                                  "eth_phy_generic_drv",
143                                                  node_name, phy_node, &phy_dev);
144                 if (ret) {
145                         dev_dbg(mdio_dev, "  - Eth phy binding error: %d\n", ret);
146                         continue;
147                 }
148
149                 dev_dbg(mdio_dev, "  - bound phy device: '%s'\n", node_name);
150                 ret = device_probe(phy_dev);
151                 if (ret) {
152                         dev_dbg(mdio_dev, "Device '%s' probe failed\n", phy_dev->name);
153                         device_unbind(phy_dev);
154                         continue;
155                 }
156         }
157
158         return 0;
159 }
160
161 static int dm_mdio_post_probe(struct udevice *dev)
162 {
163         struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
164         struct mii_dev *mii_bus;
165         int ret;
166
167         mii_bus = mdio_alloc();
168         if (!mii_bus) {
169                 dev_err(dev, "couldn't allocate mii_bus\n");
170                 return -ENOMEM;
171         }
172         pdata->mii_bus = mii_bus;
173         pdata->mii_bus->read = mdio_read;
174         pdata->mii_bus->write = mdio_write;
175         pdata->mii_bus->reset = mdio_reset;
176         pdata->mii_bus->priv = dev;
177         strlcpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
178
179         if (IS_ENABLED(CONFIG_DM_GPIO)) {
180                 /* Get bus level PHY reset GPIO details */
181                 mii_bus->reset_delay_us = dev_read_u32_default(dev, "reset-delay-us",
182                                                                DEFAULT_GPIO_RESET_DELAY);
183                 mii_bus->reset_post_delay_us = dev_read_u32_default(dev,
184                                                                     "reset-post-delay-us",
185                                                                     0);
186                 ret = gpio_request_by_name(dev, "reset-gpios", 0, &mii_bus->reset_gpiod,
187                                            GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
188                 if (ret && ret != -ENOENT) {
189                         dev_err(dev, "couldn't get reset-gpios: %d\n", ret);
190                         return ret;
191                 }
192         }
193
194         if (CONFIG_IS_ENABLED(DM_ETH_PHY))
195                 mdio_bind_phy_nodes(dev);
196
197         return mdio_register(pdata->mii_bus);
198 }
199
200 static int dm_mdio_pre_remove(struct udevice *dev)
201 {
202         struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
203
204         dm_mdio_reset(dev);
205         mdio_unregister(pdata->mii_bus);
206         mdio_free(pdata->mii_bus);
207
208         return 0;
209 }
210
211 struct phy_device *dm_phy_find_by_ofnode(ofnode phynode)
212 {
213         struct mdio_perdev_priv *pdata;
214         struct udevice *mdiodev;
215         u32 phy_addr;
216
217         if (ofnode_read_u32(phynode, "reg", &phy_addr))
218                 return NULL;
219
220         if (uclass_get_device_by_ofnode(UCLASS_MDIO,
221                                         ofnode_get_parent(phynode),
222                                         &mdiodev))
223                 return NULL;
224
225         if (device_probe(mdiodev))
226                 return NULL;
227
228         pdata = dev_get_uclass_priv(mdiodev);
229
230         return phy_find_by_mask(pdata->mii_bus, BIT(phy_addr));
231 }
232
233 struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
234                                        struct udevice *ethdev,
235                                        phy_interface_t interface)
236 {
237         struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdiodev);
238
239         if (device_probe(mdiodev))
240                 return NULL;
241
242         return phy_connect(pdata->mii_bus, phyaddr, ethdev, interface);
243 }
244
245 static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
246                                                     phy_interface_t interface)
247 {
248         u32 phy_addr;
249         struct udevice *mdiodev;
250         struct phy_device *phy;
251         ofnode phynode;
252
253         if (IS_ENABLED(CONFIG_PHY_FIXED) &&
254             ofnode_phy_is_fixed_link(dev_ofnode(ethdev), &phynode)) {
255                 phy = phy_connect(NULL, 0, ethdev, interface);
256                 goto out;
257         }
258
259         phynode = dev_get_phy_node(ethdev);
260         if (!ofnode_valid(phynode)) {
261                 dev_dbg(ethdev, "can't find PHY node\n");
262                 return NULL;
263         }
264
265         /*
266          * reading 'reg' directly should be fine.  This is a PHY node, the
267          * address is always size 1 and requires no translation
268          */
269         if (ofnode_read_u32(phynode, "reg", &phy_addr)) {
270                 dev_dbg(ethdev, "missing reg property in phy node\n");
271                 return NULL;
272         }
273
274         if (uclass_get_device_by_ofnode(UCLASS_MDIO,
275                                         ofnode_get_parent(phynode),
276                                         &mdiodev)) {
277                 dev_dbg(ethdev, "can't find MDIO bus for node %s\n",
278                         ofnode_get_name(ofnode_get_parent(phynode)));
279                 return NULL;
280         }
281
282         phy = dm_mdio_phy_connect(mdiodev, phy_addr, ethdev, interface);
283
284 out:
285         if (phy)
286                 phy->node = phynode;
287
288         return phy;
289 }
290
291 /* Connect to a PHY linked in eth DT node */
292 struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
293 {
294         phy_interface_t interface;
295         struct phy_device *phy;
296
297         if (!dev_has_ofnode(ethdev)) {
298                 debug("%s: supplied eth dev has no DT node!\n", ethdev->name);
299                 return NULL;
300         }
301
302         interface = dev_read_phy_mode(ethdev);
303         if (interface == PHY_INTERFACE_MODE_NA)
304                 dev_dbg(ethdev, "can't find interface mode, default to NA\n");
305
306         phy = dm_eth_connect_phy_handle(ethdev, interface);
307
308         if (!phy)
309                 return NULL;
310
311         phy->interface = interface;
312
313         return phy;
314 }
315
316 UCLASS_DRIVER(mdio) = {
317         .id = UCLASS_MDIO,
318         .name = "mdio",
319         .post_bind  = dm_mdio_post_bind,
320         .post_probe = dm_mdio_post_probe,
321         .pre_remove = dm_mdio_pre_remove,
322         .per_device_auto        = sizeof(struct mdio_perdev_priv),
323 };
This page took 0.046111 seconds and 4 git commands to generate.