Commit | Line | Data |
---|---|---|
a2443fd1 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
02d320c3 | 2 | /* MDIO Bus interface |
00db8189 AF |
3 | * |
4 | * Author: Andy Fleming | |
5 | * | |
6 | * Copyright (c) 2004 Freescale Semiconductor, Inc. | |
00db8189 | 7 | */ |
8d242488 JP |
8 | |
9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | ||
00db8189 | 11 | #include <linux/delay.h> |
3d1e4db2 | 12 | #include <linux/device.h> |
54e80ded BG |
13 | #include <linux/errno.h> |
14 | #include <linux/etherdevice.h> | |
15 | #include <linux/ethtool.h> | |
69226896 RQ |
16 | #include <linux/gpio.h> |
17 | #include <linux/gpio/consumer.h> | |
54e80ded BG |
18 | #include <linux/init.h> |
19 | #include <linux/interrupt.h> | |
20 | #include <linux/io.h> | |
21 | #include <linux/kernel.h> | |
34865933 | 22 | #include <linux/micrel_phy.h> |
54e80ded BG |
23 | #include <linux/mii.h> |
24 | #include <linux/mm.h> | |
25 | #include <linux/module.h> | |
26 | #include <linux/netdevice.h> | |
a30e2c18 | 27 | #include <linux/of_device.h> |
69226896 | 28 | #include <linux/of_gpio.h> |
54e80ded BG |
29 | #include <linux/of_mdio.h> |
30 | #include <linux/phy.h> | |
71dd6c0d | 31 | #include <linux/reset.h> |
00db8189 | 32 | #include <linux/skbuff.h> |
54e80ded | 33 | #include <linux/slab.h> |
00db8189 | 34 | #include <linux/spinlock.h> |
54e80ded | 35 | #include <linux/string.h> |
02d320c3 | 36 | #include <linux/uaccess.h> |
54e80ded | 37 | #include <linux/unistd.h> |
00db8189 | 38 | |
e22e996b UKK |
39 | #define CREATE_TRACE_POINTS |
40 | #include <trace/events/mdio.h> | |
41 | ||
648ea013 FF |
42 | #include "mdio-boardinfo.h" |
43 | ||
ee7e16b6 | 44 | static int mdiobus_register_gpiod(struct mdio_device *mdiodev) |
7f854420 | 45 | { |
bafbdd52 | 46 | /* Deassert the optional reset signal */ |
40ba6a12 DT |
47 | mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev, |
48 | "reset", GPIOD_OUT_LOW); | |
d0f0c55e TB |
49 | if (IS_ERR(mdiodev->reset_gpio)) |
50 | return PTR_ERR(mdiodev->reset_gpio); | |
40ba6a12 DT |
51 | |
52 | if (mdiodev->reset_gpio) | |
53 | gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset"); | |
bafbdd52 | 54 | |
71dd6c0d DB |
55 | return 0; |
56 | } | |
57 | ||
58 | static int mdiobus_register_reset(struct mdio_device *mdiodev) | |
59 | { | |
62140036 GU |
60 | struct reset_control *reset; |
61 | ||
62 | reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy"); | |
63 | if (IS_ERR(reset)) | |
64 | return PTR_ERR(reset); | |
71dd6c0d DB |
65 | |
66 | mdiodev->reset_ctrl = reset; | |
bafbdd52 | 67 | |
ee7e16b6 AL |
68 | return 0; |
69 | } | |
70 | ||
71 | int mdiobus_register_device(struct mdio_device *mdiodev) | |
72 | { | |
73 | int err; | |
74 | ||
75 | if (mdiodev->bus->mdio_map[mdiodev->addr]) | |
76 | return -EBUSY; | |
77 | ||
78 | if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) { | |
79 | err = mdiobus_register_gpiod(mdiodev); | |
80 | if (err) | |
81 | return err; | |
71dd6c0d DB |
82 | |
83 | err = mdiobus_register_reset(mdiodev); | |
84 | if (err) | |
85 | return err; | |
86 | ||
87 | /* Assert the reset signal */ | |
88 | mdio_device_reset(mdiodev, 1); | |
ee7e16b6 AL |
89 | } |
90 | ||
7f854420 AL |
91 | mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev; |
92 | ||
93 | return 0; | |
94 | } | |
95 | EXPORT_SYMBOL(mdiobus_register_device); | |
96 | ||
97 | int mdiobus_unregister_device(struct mdio_device *mdiodev) | |
98 | { | |
99 | if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev) | |
100 | return -EINVAL; | |
101 | ||
32085f25 DB |
102 | reset_control_put(mdiodev->reset_ctrl); |
103 | ||
7f854420 AL |
104 | mdiodev->bus->mdio_map[mdiodev->addr] = NULL; |
105 | ||
106 | return 0; | |
107 | } | |
108 | EXPORT_SYMBOL(mdiobus_unregister_device); | |
109 | ||
09bd2d7d | 110 | static struct mdio_device *mdiobus_find_device(struct mii_bus *bus, int addr) |
7f854420 | 111 | { |
8a8b70b3 | 112 | bool addr_valid = addr >= 0 && addr < ARRAY_SIZE(bus->mdio_map); |
867dbe78 | 113 | |
8a8b70b3 | 114 | if (WARN_ONCE(!addr_valid, "addr %d out of range\n", addr)) |
867dbe78 HK |
115 | return NULL; |
116 | ||
09bd2d7d RKO |
117 | return bus->mdio_map[addr]; |
118 | } | |
7f854420 | 119 | |
09bd2d7d RKO |
120 | struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) |
121 | { | |
122 | struct mdio_device *mdiodev; | |
123 | ||
124 | mdiodev = mdiobus_find_device(bus, addr); | |
7f854420 AL |
125 | if (!mdiodev) |
126 | return NULL; | |
127 | ||
128 | if (!(mdiodev->flags & MDIO_DEVICE_FLAG_PHY)) | |
129 | return NULL; | |
130 | ||
131 | return container_of(mdiodev, struct phy_device, mdio); | |
132 | } | |
133 | EXPORT_SYMBOL(mdiobus_get_phy); | |
134 | ||
135 | bool mdiobus_is_registered_device(struct mii_bus *bus, int addr) | |
136 | { | |
09bd2d7d | 137 | return mdiobus_find_device(bus, addr) != NULL; |
7f854420 AL |
138 | } |
139 | EXPORT_SYMBOL(mdiobus_is_registered_device); | |
140 | ||
298cf9be | 141 | /** |
eb8a54a7 | 142 | * mdiobus_alloc_size - allocate a mii_bus structure |
af58f1d6 RD |
143 | * @size: extra amount of memory to allocate for private storage. |
144 | * If non-zero, then bus->priv is points to that memory. | |
298cf9be LB |
145 | * |
146 | * Description: called by a bus driver to allocate an mii_bus | |
147 | * structure to fill in. | |
148 | */ | |
eb8a54a7 | 149 | struct mii_bus *mdiobus_alloc_size(size_t size) |
298cf9be | 150 | { |
46abc021 | 151 | struct mii_bus *bus; |
eb8a54a7 TT |
152 | size_t aligned_size = ALIGN(sizeof(*bus), NETDEV_ALIGN); |
153 | size_t alloc_size; | |
e7f4dc35 | 154 | int i; |
eb8a54a7 TT |
155 | |
156 | /* If we alloc extra space, it should be aligned */ | |
157 | if (size) | |
158 | alloc_size = aligned_size + size; | |
159 | else | |
160 | alloc_size = sizeof(*bus); | |
46abc021 | 161 | |
eb8a54a7 | 162 | bus = kzalloc(alloc_size, GFP_KERNEL); |
db9107b4 DC |
163 | if (!bus) |
164 | return NULL; | |
165 | ||
166 | bus->state = MDIOBUS_ALLOCATED; | |
167 | if (size) | |
168 | bus->priv = (void *)bus + aligned_size; | |
46abc021 | 169 | |
080bb352 FF |
170 | /* Initialise the interrupts to polling and 64-bit seqcounts */ |
171 | for (i = 0; i < PHY_MAX_ADDR; i++) { | |
e7f4dc35 | 172 | bus->irq[i] = PHY_POLL; |
080bb352 FF |
173 | u64_stats_init(&bus->stats[i].syncp); |
174 | } | |
e7f4dc35 | 175 | |
46abc021 | 176 | return bus; |
298cf9be | 177 | } |
eb8a54a7 | 178 | EXPORT_SYMBOL(mdiobus_alloc_size); |
298cf9be | 179 | |
46abc021 LB |
180 | /** |
181 | * mdiobus_release - mii_bus device release callback | |
78c36b15 | 182 | * @d: the target struct device that contains the mii_bus |
46abc021 LB |
183 | * |
184 | * Description: called when the last reference to an mii_bus is | |
185 | * dropped, to free the underlying memory. | |
186 | */ | |
187 | static void mdiobus_release(struct device *d) | |
188 | { | |
189 | struct mii_bus *bus = to_mii_bus(d); | |
775f2547 | 190 | |
867ae8a7 FF |
191 | WARN(bus->state != MDIOBUS_RELEASED && |
192 | /* for compatibility with error handling in drivers */ | |
193 | bus->state != MDIOBUS_ALLOCATED, | |
194 | "%s: not in RELEASED or ALLOCATED state\n", | |
195 | bus->id); | |
46abc021 LB |
196 | kfree(bus); |
197 | } | |
198 | ||
080bb352 FF |
199 | struct mdio_bus_stat_attr { |
200 | int addr; | |
201 | unsigned int field_offset; | |
202 | }; | |
203 | ||
204 | static u64 mdio_bus_get_stat(struct mdio_bus_stats *s, unsigned int offset) | |
205 | { | |
206 | const char *p = (const char *)s + offset; | |
207 | unsigned int start; | |
208 | u64 val = 0; | |
209 | ||
210 | do { | |
211 | start = u64_stats_fetch_begin(&s->syncp); | |
212 | val = u64_stats_read((const u64_stats_t *)p); | |
213 | } while (u64_stats_fetch_retry(&s->syncp, start)); | |
214 | ||
215 | return val; | |
216 | } | |
217 | ||
218 | static u64 mdio_bus_get_global_stat(struct mii_bus *bus, unsigned int offset) | |
219 | { | |
220 | unsigned int i; | |
221 | u64 val = 0; | |
222 | ||
223 | for (i = 0; i < PHY_MAX_ADDR; i++) | |
224 | val += mdio_bus_get_stat(&bus->stats[i], offset); | |
225 | ||
226 | return val; | |
227 | } | |
228 | ||
229 | static ssize_t mdio_bus_stat_field_show(struct device *dev, | |
230 | struct device_attribute *attr, | |
231 | char *buf) | |
232 | { | |
233 | struct mii_bus *bus = to_mii_bus(dev); | |
234 | struct mdio_bus_stat_attr *sattr; | |
235 | struct dev_ext_attribute *eattr; | |
236 | u64 val; | |
237 | ||
238 | eattr = container_of(attr, struct dev_ext_attribute, attr); | |
239 | sattr = eattr->var; | |
240 | ||
241 | if (sattr->addr < 0) | |
242 | val = mdio_bus_get_global_stat(bus, sattr->field_offset); | |
243 | else | |
244 | val = mdio_bus_get_stat(&bus->stats[sattr->addr], | |
245 | sattr->field_offset); | |
246 | ||
b5155ddd | 247 | return sysfs_emit(buf, "%llu\n", val); |
080bb352 FF |
248 | } |
249 | ||
250 | static ssize_t mdio_bus_device_stat_field_show(struct device *dev, | |
251 | struct device_attribute *attr, | |
252 | char *buf) | |
253 | { | |
254 | struct mdio_device *mdiodev = to_mdio_device(dev); | |
255 | struct mii_bus *bus = mdiodev->bus; | |
256 | struct mdio_bus_stat_attr *sattr; | |
257 | struct dev_ext_attribute *eattr; | |
258 | int addr = mdiodev->addr; | |
259 | u64 val; | |
260 | ||
261 | eattr = container_of(attr, struct dev_ext_attribute, attr); | |
262 | sattr = eattr->var; | |
263 | ||
264 | val = mdio_bus_get_stat(&bus->stats[addr], sattr->field_offset); | |
265 | ||
b5155ddd | 266 | return sysfs_emit(buf, "%llu\n", val); |
080bb352 FF |
267 | } |
268 | ||
269 | #define MDIO_BUS_STATS_ATTR_DECL(field, file) \ | |
270 | static struct dev_ext_attribute dev_attr_mdio_bus_##field = { \ | |
271 | .attr = { .attr = { .name = file, .mode = 0444 }, \ | |
272 | .show = mdio_bus_stat_field_show, \ | |
273 | }, \ | |
274 | .var = &((struct mdio_bus_stat_attr) { \ | |
275 | -1, offsetof(struct mdio_bus_stats, field) \ | |
276 | }), \ | |
277 | }; \ | |
278 | static struct dev_ext_attribute dev_attr_mdio_bus_device_##field = { \ | |
279 | .attr = { .attr = { .name = file, .mode = 0444 }, \ | |
280 | .show = mdio_bus_device_stat_field_show, \ | |
281 | }, \ | |
282 | .var = &((struct mdio_bus_stat_attr) { \ | |
283 | -1, offsetof(struct mdio_bus_stats, field) \ | |
284 | }), \ | |
285 | }; | |
286 | ||
287 | #define MDIO_BUS_STATS_ATTR(field) \ | |
288 | MDIO_BUS_STATS_ATTR_DECL(field, __stringify(field)) | |
289 | ||
290 | MDIO_BUS_STATS_ATTR(transfers); | |
291 | MDIO_BUS_STATS_ATTR(errors); | |
292 | MDIO_BUS_STATS_ATTR(writes); | |
293 | MDIO_BUS_STATS_ATTR(reads); | |
294 | ||
295 | #define MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, file) \ | |
296 | static struct dev_ext_attribute dev_attr_mdio_bus_addr_##field##_##addr = { \ | |
297 | .attr = { .attr = { .name = file, .mode = 0444 }, \ | |
298 | .show = mdio_bus_stat_field_show, \ | |
299 | }, \ | |
300 | .var = &((struct mdio_bus_stat_attr) { \ | |
301 | addr, offsetof(struct mdio_bus_stats, field) \ | |
302 | }), \ | |
303 | } | |
304 | ||
305 | #define MDIO_BUS_STATS_ADDR_ATTR(field, addr) \ | |
306 | MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, \ | |
307 | __stringify(field) "_" __stringify(addr)) | |
308 | ||
309 | #define MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(addr) \ | |
310 | MDIO_BUS_STATS_ADDR_ATTR(transfers, addr); \ | |
311 | MDIO_BUS_STATS_ADDR_ATTR(errors, addr); \ | |
312 | MDIO_BUS_STATS_ADDR_ATTR(writes, addr); \ | |
313 | MDIO_BUS_STATS_ADDR_ATTR(reads, addr) \ | |
314 | ||
315 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(0); | |
316 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(1); | |
317 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(2); | |
318 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(3); | |
319 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(4); | |
320 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(5); | |
321 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(6); | |
322 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(7); | |
323 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(8); | |
324 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(9); | |
325 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(10); | |
326 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(11); | |
327 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(12); | |
328 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(13); | |
329 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(14); | |
330 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(15); | |
331 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(16); | |
332 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(17); | |
333 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(18); | |
334 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(19); | |
335 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(20); | |
336 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(21); | |
337 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(22); | |
338 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(23); | |
339 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(24); | |
340 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(25); | |
341 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(26); | |
342 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(27); | |
343 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(28); | |
344 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(29); | |
345 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(30); | |
346 | MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(31); | |
347 | ||
348 | #define MDIO_BUS_STATS_ADDR_ATTR_GROUP(addr) \ | |
349 | &dev_attr_mdio_bus_addr_transfers_##addr.attr.attr, \ | |
350 | &dev_attr_mdio_bus_addr_errors_##addr.attr.attr, \ | |
351 | &dev_attr_mdio_bus_addr_writes_##addr.attr.attr, \ | |
352 | &dev_attr_mdio_bus_addr_reads_##addr.attr.attr \ | |
353 | ||
354 | static struct attribute *mdio_bus_statistics_attrs[] = { | |
355 | &dev_attr_mdio_bus_transfers.attr.attr, | |
356 | &dev_attr_mdio_bus_errors.attr.attr, | |
357 | &dev_attr_mdio_bus_writes.attr.attr, | |
358 | &dev_attr_mdio_bus_reads.attr.attr, | |
359 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(0), | |
360 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(1), | |
361 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(2), | |
362 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(3), | |
363 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(4), | |
364 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(5), | |
365 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(6), | |
366 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(7), | |
367 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(8), | |
368 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(9), | |
369 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(10), | |
370 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(11), | |
371 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(12), | |
372 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(13), | |
373 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(14), | |
374 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(15), | |
375 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(16), | |
376 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(17), | |
377 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(18), | |
378 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(19), | |
379 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(20), | |
380 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(21), | |
381 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(22), | |
382 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(23), | |
383 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(24), | |
384 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(25), | |
385 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(26), | |
386 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(27), | |
387 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(28), | |
388 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(29), | |
389 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(30), | |
390 | MDIO_BUS_STATS_ADDR_ATTR_GROUP(31), | |
391 | NULL, | |
392 | }; | |
393 | ||
394 | static const struct attribute_group mdio_bus_statistics_group = { | |
395 | .name = "statistics", | |
396 | .attrs = mdio_bus_statistics_attrs, | |
397 | }; | |
398 | ||
399 | static const struct attribute_group *mdio_bus_groups[] = { | |
400 | &mdio_bus_statistics_group, | |
401 | NULL, | |
402 | }; | |
403 | ||
46abc021 LB |
404 | static struct class mdio_bus_class = { |
405 | .name = "mdio_bus", | |
406 | .dev_release = mdiobus_release, | |
080bb352 | 407 | .dev_groups = mdio_bus_groups, |
46abc021 LB |
408 | }; |
409 | ||
ce69e216 JL |
410 | /** |
411 | * mdio_find_bus - Given the name of a mdiobus, find the mii_bus. | |
ab741102 | 412 | * @mdio_name: The name of a mdiobus. |
ce69e216 JL |
413 | * |
414 | * Returns a reference to the mii_bus, or NULL if none found. The | |
415 | * embedded struct device will have its reference count incremented, | |
416 | * and this must be put_deviced'ed once the bus is finished with. | |
417 | */ | |
418 | struct mii_bus *mdio_find_bus(const char *mdio_name) | |
419 | { | |
420 | struct device *d; | |
421 | ||
422 | d = class_find_device_by_name(&mdio_bus_class, mdio_name); | |
423 | return d ? to_mii_bus(d) : NULL; | |
424 | } | |
425 | EXPORT_SYMBOL(mdio_find_bus); | |
426 | ||
b943fbb0 | 427 | #if IS_ENABLED(CONFIG_OF_MDIO) |
25106022 DD |
428 | /** |
429 | * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. | |
f41ef2e7 | 430 | * @mdio_bus_np: Pointer to the mii_bus. |
25106022 | 431 | * |
a1364421 RK |
432 | * Returns a reference to the mii_bus, or NULL if none found. The |
433 | * embedded struct device will have its reference count incremented, | |
434 | * and this must be put once the bus is finished with. | |
25106022 DD |
435 | * |
436 | * Because the association of a device_node and mii_bus is made via | |
437 | * of_mdiobus_register(), the mii_bus cannot be found before it is | |
438 | * registered with of_mdiobus_register(). | |
439 | * | |
440 | */ | |
441 | struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np) | |
442 | { | |
443 | struct device *d; | |
444 | ||
445 | if (!mdio_bus_np) | |
446 | return NULL; | |
447 | ||
cfba5de9 | 448 | d = class_find_device_by_of_node(&mdio_bus_class, mdio_bus_np); |
25106022 DD |
449 | return d ? to_mii_bus(d) : NULL; |
450 | } | |
451 | EXPORT_SYMBOL(of_mdio_find_bus); | |
d9daa247 | 452 | |
f03bc4ae AL |
453 | /* Walk the list of subnodes of a mdio bus and look for a node that |
454 | * matches the mdio device's address with its 'reg' property. If | |
455 | * found, set the of_node pointer for the mdio device. This allows | |
456 | * auto-probed phy devices to be supplied with information passed in | |
457 | * via DT. | |
d9daa247 | 458 | */ |
f03bc4ae AL |
459 | static void of_mdiobus_link_mdiodev(struct mii_bus *bus, |
460 | struct mdio_device *mdiodev) | |
d9daa247 | 461 | { |
f03bc4ae | 462 | struct device *dev = &mdiodev->dev; |
d9daa247 DM |
463 | struct device_node *child; |
464 | ||
e5a03bfd | 465 | if (dev->of_node || !bus->dev.of_node) |
d9daa247 DM |
466 | return; |
467 | ||
e5a03bfd | 468 | for_each_available_child_of_node(bus->dev.of_node, child) { |
d9daa247 | 469 | int addr; |
d9daa247 | 470 | |
d0a65400 JM |
471 | addr = of_mdio_parse_addr(dev, child); |
472 | if (addr < 0) | |
d9daa247 | 473 | continue; |
d9daa247 | 474 | |
f03bc4ae | 475 | if (addr == mdiodev->addr) { |
7e33d84d | 476 | device_set_node(dev, of_fwnode_handle(child)); |
d33dae51 RKO |
477 | /* The refcount on "child" is passed to the mdio |
478 | * device. Do _not_ use of_node_put(child) here. | |
479 | */ | |
d9daa247 DM |
480 | return; |
481 | } | |
482 | } | |
483 | } | |
484 | #else /* !IS_ENABLED(CONFIG_OF_MDIO) */ | |
f03bc4ae AL |
485 | static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio, |
486 | struct mdio_device *mdiodev) | |
d9daa247 DM |
487 | { |
488 | } | |
25106022 DD |
489 | #endif |
490 | ||
d0281a56 | 491 | /** |
69280228 | 492 | * mdiobus_create_device - create a full MDIO device given |
d0281a56 FF |
493 | * a mdio_board_info structure |
494 | * @bus: MDIO bus to create the devices on | |
495 | * @bi: mdio_board_info structure describing the devices | |
496 | * | |
497 | * Returns 0 on success or < 0 on error. | |
498 | */ | |
499 | static int mdiobus_create_device(struct mii_bus *bus, | |
500 | struct mdio_board_info *bi) | |
501 | { | |
502 | struct mdio_device *mdiodev; | |
503 | int ret = 0; | |
504 | ||
505 | mdiodev = mdio_device_create(bus, bi->mdio_addr); | |
506 | if (IS_ERR(mdiodev)) | |
507 | return -ENODEV; | |
508 | ||
509 | strncpy(mdiodev->modalias, bi->modalias, | |
510 | sizeof(mdiodev->modalias)); | |
511 | mdiodev->bus_match = mdio_device_bus_match; | |
512 | mdiodev->dev.platform_data = (void *)bi->platform_data; | |
513 | ||
514 | ret = mdio_device_register(mdiodev); | |
515 | if (ret) | |
516 | mdio_device_free(mdiodev); | |
517 | ||
518 | return ret; | |
519 | } | |
520 | ||
d41e1277 | 521 | static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45) |
81d874e7 AL |
522 | { |
523 | struct phy_device *phydev = ERR_PTR(-ENODEV); | |
524 | int err; | |
525 | ||
d41e1277 | 526 | phydev = get_phy_device(bus, addr, c45); |
81d874e7 AL |
527 | if (IS_ERR(phydev)) |
528 | return phydev; | |
529 | ||
530 | /* For DT, see if the auto-probed phy has a corresponding child | |
531 | * in the bus node, and set the of_node pointer in this case. | |
532 | */ | |
533 | of_mdiobus_link_mdiodev(bus, &phydev->mdio); | |
534 | ||
535 | err = phy_device_register(phydev); | |
536 | if (err) { | |
537 | phy_device_free(phydev); | |
538 | return ERR_PTR(-ENODEV); | |
539 | } | |
540 | ||
541 | return phydev; | |
542 | } | |
d41e1277 AL |
543 | |
544 | /** | |
545 | * mdiobus_scan_c22 - scan one address on a bus for C22 MDIO devices. | |
546 | * @bus: mii_bus to scan | |
547 | * @addr: address on bus to scan | |
548 | * | |
549 | * This function scans one address on the MDIO bus, looking for | |
550 | * devices which can be identified using a vendor/product ID in | |
551 | * registers 2 and 3. Not all MDIO devices have such registers, but | |
552 | * PHY devices typically do. Hence this function assumes anything | |
553 | * found is a PHY, or can be treated as a PHY. Other MDIO devices, | |
554 | * such as switches, will probably not be found during the scan. | |
555 | */ | |
556 | struct phy_device *mdiobus_scan_c22(struct mii_bus *bus, int addr) | |
557 | { | |
558 | return mdiobus_scan(bus, addr, false); | |
559 | } | |
560 | EXPORT_SYMBOL(mdiobus_scan_c22); | |
561 | ||
562 | /** | |
563 | * mdiobus_scan_c45 - scan one address on a bus for C45 MDIO devices. | |
564 | * @bus: mii_bus to scan | |
565 | * @addr: address on bus to scan | |
566 | * | |
567 | * This function scans one address on the MDIO bus, looking for | |
568 | * devices which can be identified using a vendor/product ID in | |
569 | * registers 2 and 3. Not all MDIO devices have such registers, but | |
570 | * PHY devices typically do. Hence this function assumes anything | |
571 | * found is a PHY, or can be treated as a PHY. Other MDIO devices, | |
572 | * such as switches, will probably not be found during the scan. | |
573 | */ | |
574 | static struct phy_device *mdiobus_scan_c45(struct mii_bus *bus, int addr) | |
575 | { | |
576 | return mdiobus_scan(bus, addr, true); | |
577 | } | |
578 | ||
579 | static int mdiobus_scan_bus_c22(struct mii_bus *bus) | |
580 | { | |
581 | int i; | |
582 | ||
583 | for (i = 0; i < PHY_MAX_ADDR; i++) { | |
584 | if ((bus->phy_mask & BIT(i)) == 0) { | |
585 | struct phy_device *phydev; | |
586 | ||
587 | phydev = mdiobus_scan_c22(bus, i); | |
588 | if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV)) | |
589 | return PTR_ERR(phydev); | |
590 | } | |
591 | } | |
592 | return 0; | |
593 | } | |
594 | ||
595 | static int mdiobus_scan_bus_c45(struct mii_bus *bus) | |
596 | { | |
597 | int i; | |
598 | ||
599 | for (i = 0; i < PHY_MAX_ADDR; i++) { | |
600 | if ((bus->phy_mask & BIT(i)) == 0) { | |
601 | struct phy_device *phydev; | |
602 | ||
603 | /* Don't scan C45 if we already have a C22 device */ | |
604 | if (bus->mdio_map[i]) | |
605 | continue; | |
606 | ||
607 | phydev = mdiobus_scan_c45(bus, i); | |
608 | if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV)) | |
609 | return PTR_ERR(phydev); | |
610 | } | |
611 | } | |
612 | return 0; | |
613 | } | |
81d874e7 | 614 | |
34865933 AL |
615 | /* There are some C22 PHYs which do bad things when where is a C45 |
616 | * transaction on the bus, like accepting a read themselves, and | |
617 | * stomping over the true devices reply, to performing a write to | |
618 | * themselves which was intended for another device. Now that C22 | |
619 | * devices have been found, see if any of them are bad for C45, and if we | |
620 | * should skip the C45 scan. | |
621 | */ | |
622 | static bool mdiobus_prevent_c45_scan(struct mii_bus *bus) | |
623 | { | |
624 | int i; | |
625 | ||
626 | for (i = 0; i < PHY_MAX_ADDR; i++) { | |
627 | struct phy_device *phydev; | |
628 | u32 oui; | |
629 | ||
630 | phydev = mdiobus_get_phy(bus, i); | |
631 | if (!phydev) | |
632 | continue; | |
633 | oui = phydev->phy_id >> 10; | |
634 | ||
635 | if (oui == MICREL_OUI) | |
636 | return true; | |
637 | } | |
638 | return false; | |
639 | } | |
640 | ||
b3df0da8 | 641 | /** |
59f06978 | 642 | * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus |
b3df0da8 | 643 | * @bus: target mii_bus |
59f06978 | 644 | * @owner: module containing bus accessor functions |
e1393456 | 645 | * |
b3df0da8 | 646 | * Description: Called by a bus driver to bring up all the PHYs |
59f06978 RK |
647 | * on a given bus, and attach them to the bus. Drivers should use |
648 | * mdiobus_register() rather than __mdiobus_register() unless they | |
f89df3f3 | 649 | * need to pass a specific owner module. MDIO devices which are not |
fec76125 | 650 | * PHYs will not be brought up by this function. They are expected |
f89df3f3 | 651 | * to be explicitly listed in DT and instantiated by of_mdiobus_register(). |
b3df0da8 RD |
652 | * |
653 | * Returns 0 on success or < 0 on error. | |
e1393456 | 654 | */ |
3e3aaf64 | 655 | int __mdiobus_register(struct mii_bus *bus, struct module *owner) |
e1393456 | 656 | { |
711fdba3 | 657 | struct mdio_device *mdiodev; |
69226896 | 658 | struct gpio_desc *gpiod; |
34865933 AL |
659 | bool prevent_c45_scan; |
660 | int i, err; | |
e1393456 | 661 | |
555d64c6 AL |
662 | if (!bus || !bus->name) |
663 | return -EINVAL; | |
664 | ||
665 | /* An access method always needs both read and write operations */ | |
666 | if (!!bus->read != !!bus->write || !!bus->read_c45 != !!bus->write_c45) | |
667 | return -EINVAL; | |
668 | ||
669 | /* At least one method is mandatory */ | |
670 | if (!bus->read && !bus->read_c45) | |
e1393456 AF |
671 | return -EINVAL; |
672 | ||
04f41c68 SK |
673 | if (bus->parent && bus->parent->of_node) |
674 | bus->parent->of_node->fwnode.flags |= | |
675 | FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD; | |
676 | ||
867ae8a7 FF |
677 | WARN(bus->state != MDIOBUS_ALLOCATED && |
678 | bus->state != MDIOBUS_UNREGISTERED, | |
679 | "%s: not in ALLOCATED or UNREGISTERED state\n", bus->id); | |
46abc021 | 680 | |
3e3aaf64 | 681 | bus->owner = owner; |
46abc021 LB |
682 | bus->dev.parent = bus->parent; |
683 | bus->dev.class = &mdio_bus_class; | |
684 | bus->dev.groups = NULL; | |
036b6687 | 685 | dev_set_name(&bus->dev, "%s", bus->id); |
46abc021 | 686 | |
ca6e11c3 PS |
687 | /* We need to set state to MDIOBUS_UNREGISTERED to correctly release |
688 | * the device in mdiobus_free() | |
689 | * | |
690 | * State will be updated later in this function in case of success | |
691 | */ | |
692 | bus->state = MDIOBUS_UNREGISTERED; | |
693 | ||
46abc021 LB |
694 | err = device_register(&bus->dev); |
695 | if (err) { | |
8d242488 | 696 | pr_err("mii_bus %s failed to register\n", bus->id); |
46abc021 LB |
697 | return -EINVAL; |
698 | } | |
699 | ||
d1e7fe4d | 700 | mutex_init(&bus->mdio_lock); |
63490847 | 701 | mutex_init(&bus->shared_lock); |
d1e7fe4d | 702 | |
e0183b97 ML |
703 | /* assert bus level PHY GPIO reset */ |
704 | gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_HIGH); | |
d396e84c | 705 | if (IS_ERR(gpiod)) { |
0a12ad59 GS |
706 | err = dev_err_probe(&bus->dev, PTR_ERR(gpiod), |
707 | "mii_bus %s couldn't get reset GPIO\n", | |
708 | bus->id); | |
e40e2a2e | 709 | device_del(&bus->dev); |
0a12ad59 | 710 | return err; |
fe0e4052 | 711 | } else if (gpiod) { |
d396e84c | 712 | bus->reset_gpiod = gpiod; |
6259e0f5 | 713 | fsleep(bus->reset_delay_us); |
d396e84c | 714 | gpiod_set_value_cansleep(gpiod, 0); |
bb383129 BT |
715 | if (bus->reset_post_delay_us > 0) |
716 | fsleep(bus->reset_post_delay_us); | |
69226896 RQ |
717 | } |
718 | ||
c290d1ab FF |
719 | if (bus->reset) { |
720 | err = bus->reset(bus); | |
721 | if (err) | |
722 | goto error_reset_gpiod; | |
723 | } | |
df0c8d91 | 724 | |
1a136ca2 | 725 | if (bus->read) { |
d41e1277 AL |
726 | err = mdiobus_scan_bus_c22(bus); |
727 | if (err) | |
728 | goto error; | |
729 | } | |
e1393456 | 730 | |
34865933 AL |
731 | prevent_c45_scan = mdiobus_prevent_c45_scan(bus); |
732 | ||
1a136ca2 | 733 | if (!prevent_c45_scan && bus->read_c45) { |
d41e1277 AL |
734 | err = mdiobus_scan_bus_c45(bus); |
735 | if (err) | |
736 | goto error; | |
e1393456 AF |
737 | } |
738 | ||
d0281a56 | 739 | mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device); |
648ea013 | 740 | |
161c8d2f | 741 | bus->state = MDIOBUS_REGISTERED; |
7590fc6f | 742 | dev_dbg(&bus->dev, "probed\n"); |
161c8d2f | 743 | return 0; |
e1393456 | 744 | |
161c8d2f | 745 | error: |
d41e1277 | 746 | for (i = 0; i < PHY_MAX_ADDR; i++) { |
711fdba3 AL |
747 | mdiodev = bus->mdio_map[i]; |
748 | if (!mdiodev) | |
749 | continue; | |
750 | ||
751 | mdiodev->device_remove(mdiodev); | |
752 | mdiodev->device_free(mdiodev); | |
161c8d2f | 753 | } |
c290d1ab | 754 | error_reset_gpiod: |
69226896 | 755 | /* Put PHYs in RESET to save power */ |
a010a2f6 FF |
756 | if (bus->reset_gpiod) |
757 | gpiod_set_value_cansleep(bus->reset_gpiod, 1); | |
69226896 | 758 | |
161c8d2f | 759 | device_del(&bus->dev); |
e1393456 AF |
760 | return err; |
761 | } | |
3e3aaf64 | 762 | EXPORT_SYMBOL(__mdiobus_register); |
e1393456 AF |
763 | |
764 | void mdiobus_unregister(struct mii_bus *bus) | |
765 | { | |
a9049e0c | 766 | struct mdio_device *mdiodev; |
e1393456 AF |
767 | int i; |
768 | ||
1dde47a6 DC |
769 | if (WARN_ON_ONCE(bus->state != MDIOBUS_REGISTERED)) |
770 | return; | |
46abc021 LB |
771 | bus->state = MDIOBUS_UNREGISTERED; |
772 | ||
e1393456 | 773 | for (i = 0; i < PHY_MAX_ADDR; i++) { |
a9049e0c AL |
774 | mdiodev = bus->mdio_map[i]; |
775 | if (!mdiodev) | |
776 | continue; | |
777 | ||
6110ed2d DB |
778 | if (mdiodev->reset_gpio) |
779 | gpiod_put(mdiodev->reset_gpio); | |
bafbdd52 | 780 | |
711fdba3 AL |
781 | mdiodev->device_remove(mdiodev); |
782 | mdiodev->device_free(mdiodev); | |
e1393456 | 783 | } |
69226896 RQ |
784 | |
785 | /* Put PHYs in RESET to save power */ | |
a010a2f6 FF |
786 | if (bus->reset_gpiod) |
787 | gpiod_set_value_cansleep(bus->reset_gpiod, 1); | |
69226896 | 788 | |
b6c6aedc | 789 | device_del(&bus->dev); |
e1393456 AF |
790 | } |
791 | EXPORT_SYMBOL(mdiobus_unregister); | |
792 | ||
298cf9be LB |
793 | /** |
794 | * mdiobus_free - free a struct mii_bus | |
795 | * @bus: mii_bus to free | |
796 | * | |
46abc021 LB |
797 | * This function releases the reference to the underlying device |
798 | * object in the mii_bus. If this is the last reference, the mii_bus | |
799 | * will be freed. | |
298cf9be LB |
800 | */ |
801 | void mdiobus_free(struct mii_bus *bus) | |
802 | { | |
02d320c3 | 803 | /* For compatibility with error handling in drivers. */ |
46abc021 LB |
804 | if (bus->state == MDIOBUS_ALLOCATED) { |
805 | kfree(bus); | |
806 | return; | |
807 | } | |
808 | ||
867ae8a7 FF |
809 | WARN(bus->state != MDIOBUS_UNREGISTERED, |
810 | "%s: not in UNREGISTERED state\n", bus->id); | |
46abc021 LB |
811 | bus->state = MDIOBUS_RELEASED; |
812 | ||
813 | put_device(&bus->dev); | |
298cf9be LB |
814 | } |
815 | EXPORT_SYMBOL(mdiobus_free); | |
816 | ||
080bb352 FF |
817 | static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret) |
818 | { | |
c7e261d8 | 819 | preempt_disable(); |
080bb352 FF |
820 | u64_stats_update_begin(&stats->syncp); |
821 | ||
822 | u64_stats_inc(&stats->transfers); | |
823 | if (ret < 0) { | |
824 | u64_stats_inc(&stats->errors); | |
825 | goto out; | |
826 | } | |
827 | ||
828 | if (op) | |
829 | u64_stats_inc(&stats->reads); | |
830 | else | |
831 | u64_stats_inc(&stats->writes); | |
832 | out: | |
833 | u64_stats_update_end(&stats->syncp); | |
c7e261d8 | 834 | preempt_enable(); |
080bb352 FF |
835 | } |
836 | ||
34dc08e4 RK |
837 | /** |
838 | * __mdiobus_read - Unlocked version of the mdiobus_read function | |
839 | * @bus: the mii_bus struct | |
840 | * @addr: the phy address | |
841 | * @regnum: register number to read | |
842 | * | |
843 | * Read a MDIO bus register. Caller must hold the mdio bus lock. | |
844 | * | |
845 | * NOTE: MUST NOT be called from interrupt context. | |
846 | */ | |
847 | int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) | |
848 | { | |
849 | int retval; | |
850 | ||
e6e918d4 | 851 | lockdep_assert_held_once(&bus->mdio_lock); |
34dc08e4 | 852 | |
b063b192 AL |
853 | if (bus->read) |
854 | retval = bus->read(bus, addr, regnum); | |
855 | else | |
856 | retval = -EOPNOTSUPP; | |
34dc08e4 RK |
857 | |
858 | trace_mdio_access(bus, 1, addr, regnum, retval, retval); | |
080bb352 | 859 | mdiobus_stats_acct(&bus->stats[addr], true, retval); |
34dc08e4 RK |
860 | |
861 | return retval; | |
862 | } | |
863 | EXPORT_SYMBOL(__mdiobus_read); | |
864 | ||
865 | /** | |
866 | * __mdiobus_write - Unlocked version of the mdiobus_write function | |
867 | * @bus: the mii_bus struct | |
868 | * @addr: the phy address | |
869 | * @regnum: register number to write | |
870 | * @val: value to write to @regnum | |
871 | * | |
872 | * Write a MDIO bus register. Caller must hold the mdio bus lock. | |
873 | * | |
874 | * NOTE: MUST NOT be called from interrupt context. | |
875 | */ | |
876 | int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) | |
877 | { | |
878 | int err; | |
879 | ||
e6e918d4 | 880 | lockdep_assert_held_once(&bus->mdio_lock); |
34dc08e4 | 881 | |
b063b192 AL |
882 | if (bus->write) |
883 | err = bus->write(bus, addr, regnum, val); | |
884 | else | |
885 | err = -EOPNOTSUPP; | |
34dc08e4 RK |
886 | |
887 | trace_mdio_access(bus, 0, addr, regnum, val, err); | |
080bb352 | 888 | mdiobus_stats_acct(&bus->stats[addr], false, err); |
34dc08e4 RK |
889 | |
890 | return err; | |
891 | } | |
892 | EXPORT_SYMBOL(__mdiobus_write); | |
893 | ||
6cc7cf81 RK |
894 | /** |
895 | * __mdiobus_modify_changed - Unlocked version of the mdiobus_modify function | |
896 | * @bus: the mii_bus struct | |
897 | * @addr: the phy address | |
898 | * @regnum: register number to modify | |
899 | * @mask: bit mask of bits to clear | |
900 | * @set: bit mask of bits to set | |
901 | * | |
902 | * Read, modify, and if any change, write the register value back to the | |
903 | * device. Any error returns a negative number. | |
904 | * | |
905 | * NOTE: MUST NOT be called from interrupt context. | |
906 | */ | |
907 | int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, | |
908 | u16 mask, u16 set) | |
909 | { | |
910 | int new, ret; | |
911 | ||
912 | ret = __mdiobus_read(bus, addr, regnum); | |
913 | if (ret < 0) | |
914 | return ret; | |
915 | ||
916 | new = (ret & ~mask) | set; | |
917 | if (new == ret) | |
918 | return 0; | |
919 | ||
920 | ret = __mdiobus_write(bus, addr, regnum, new); | |
921 | ||
922 | return ret < 0 ? ret : 1; | |
923 | } | |
924 | EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); | |
925 | ||
4e4aafcd AL |
926 | /** |
927 | * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function | |
928 | * @bus: the mii_bus struct | |
929 | * @addr: the phy address | |
930 | * @devad: device address to read | |
931 | * @regnum: register number to read | |
932 | * | |
933 | * Read a MDIO bus register. Caller must hold the mdio bus lock. | |
934 | * | |
935 | * NOTE: MUST NOT be called from interrupt context. | |
936 | */ | |
937 | int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) | |
938 | { | |
939 | int retval; | |
940 | ||
941 | lockdep_assert_held_once(&bus->mdio_lock); | |
942 | ||
943 | if (bus->read_c45) | |
944 | retval = bus->read_c45(bus, addr, devad, regnum); | |
945 | else | |
db1a63ae | 946 | retval = -EOPNOTSUPP; |
4e4aafcd AL |
947 | |
948 | trace_mdio_access(bus, 1, addr, regnum, retval, retval); | |
949 | mdiobus_stats_acct(&bus->stats[addr], true, retval); | |
950 | ||
951 | return retval; | |
952 | } | |
953 | EXPORT_SYMBOL(__mdiobus_c45_read); | |
954 | ||
955 | /** | |
956 | * __mdiobus_c45_write - Unlocked version of the mdiobus_write function | |
957 | * @bus: the mii_bus struct | |
958 | * @addr: the phy address | |
959 | * @devad: device address to read | |
960 | * @regnum: register number to write | |
961 | * @val: value to write to @regnum | |
962 | * | |
963 | * Write a MDIO bus register. Caller must hold the mdio bus lock. | |
964 | * | |
965 | * NOTE: MUST NOT be called from interrupt context. | |
966 | */ | |
967 | int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, | |
968 | u16 val) | |
969 | { | |
970 | int err; | |
971 | ||
972 | lockdep_assert_held_once(&bus->mdio_lock); | |
973 | ||
974 | if (bus->write_c45) | |
975 | err = bus->write_c45(bus, addr, devad, regnum, val); | |
976 | else | |
db1a63ae | 977 | err = -EOPNOTSUPP; |
4e4aafcd AL |
978 | |
979 | trace_mdio_access(bus, 0, addr, regnum, val, err); | |
980 | mdiobus_stats_acct(&bus->stats[addr], false, err); | |
981 | ||
982 | return err; | |
983 | } | |
984 | EXPORT_SYMBOL(__mdiobus_c45_write); | |
985 | ||
986 | /** | |
987 | * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function | |
988 | * @bus: the mii_bus struct | |
989 | * @addr: the phy address | |
990 | * @devad: device address to read | |
991 | * @regnum: register number to modify | |
992 | * @mask: bit mask of bits to clear | |
993 | * @set: bit mask of bits to set | |
994 | * | |
995 | * Read, modify, and if any change, write the register value back to the | |
996 | * device. Any error returns a negative number. | |
997 | * | |
998 | * NOTE: MUST NOT be called from interrupt context. | |
999 | */ | |
1000 | static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, | |
1001 | int devad, u32 regnum, u16 mask, | |
1002 | u16 set) | |
1003 | { | |
1004 | int new, ret; | |
1005 | ||
1006 | ret = __mdiobus_c45_read(bus, addr, devad, regnum); | |
1007 | if (ret < 0) | |
1008 | return ret; | |
1009 | ||
1010 | new = (ret & ~mask) | set; | |
1011 | if (new == ret) | |
1012 | return 0; | |
1013 | ||
1014 | ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); | |
1015 | ||
1016 | return ret < 0 ? ret : 1; | |
1017 | } | |
1018 | ||
21dd19fe NA |
1019 | /** |
1020 | * mdiobus_read_nested - Nested version of the mdiobus_read function | |
1021 | * @bus: the mii_bus struct | |
1022 | * @addr: the phy address | |
1023 | * @regnum: register number to read | |
1024 | * | |
1025 | * In case of nested MDIO bus access avoid lockdep false positives by | |
1026 | * using mutex_lock_nested(). | |
1027 | * | |
1028 | * NOTE: MUST NOT be called from interrupt context, | |
1029 | * because the bus read/write functions may wait for an interrupt | |
1030 | * to conclude the operation. | |
1031 | */ | |
1032 | int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum) | |
1033 | { | |
1034 | int retval; | |
1035 | ||
9a6f2b01 | 1036 | mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); |
34dc08e4 | 1037 | retval = __mdiobus_read(bus, addr, regnum); |
21dd19fe NA |
1038 | mutex_unlock(&bus->mdio_lock); |
1039 | ||
1040 | return retval; | |
1041 | } | |
1042 | EXPORT_SYMBOL(mdiobus_read_nested); | |
1043 | ||
2e888103 LB |
1044 | /** |
1045 | * mdiobus_read - Convenience function for reading a given MII mgmt register | |
1046 | * @bus: the mii_bus struct | |
1047 | * @addr: the phy address | |
1048 | * @regnum: register number to read | |
1049 | * | |
1050 | * NOTE: MUST NOT be called from interrupt context, | |
1051 | * because the bus read/write functions may wait for an interrupt | |
1052 | * to conclude the operation. | |
1053 | */ | |
abf35df2 | 1054 | int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) |
2e888103 LB |
1055 | { |
1056 | int retval; | |
1057 | ||
2e888103 | 1058 | mutex_lock(&bus->mdio_lock); |
34dc08e4 | 1059 | retval = __mdiobus_read(bus, addr, regnum); |
2e888103 LB |
1060 | mutex_unlock(&bus->mdio_lock); |
1061 | ||
1062 | return retval; | |
1063 | } | |
1064 | EXPORT_SYMBOL(mdiobus_read); | |
1065 | ||
4e4aafcd AL |
1066 | /** |
1067 | * mdiobus_c45_read - Convenience function for reading a given MII mgmt register | |
1068 | * @bus: the mii_bus struct | |
1069 | * @addr: the phy address | |
1070 | * @devad: device address to read | |
1071 | * @regnum: register number to read | |
1072 | * | |
1073 | * NOTE: MUST NOT be called from interrupt context, | |
1074 | * because the bus read/write functions may wait for an interrupt | |
1075 | * to conclude the operation. | |
1076 | */ | |
1077 | int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) | |
1078 | { | |
1079 | int retval; | |
1080 | ||
1081 | mutex_lock(&bus->mdio_lock); | |
1082 | retval = __mdiobus_c45_read(bus, addr, devad, regnum); | |
1083 | mutex_unlock(&bus->mdio_lock); | |
1084 | ||
1085 | return retval; | |
1086 | } | |
1087 | EXPORT_SYMBOL(mdiobus_c45_read); | |
1088 | ||
1d914d51 AL |
1089 | /** |
1090 | * mdiobus_c45_read_nested - Nested version of the mdiobus_c45_read function | |
1091 | * @bus: the mii_bus struct | |
1092 | * @addr: the phy address | |
1093 | * @devad: device address to read | |
1094 | * @regnum: register number to read | |
1095 | * | |
1096 | * In case of nested MDIO bus access avoid lockdep false positives by | |
1097 | * using mutex_lock_nested(). | |
1098 | * | |
1099 | * NOTE: MUST NOT be called from interrupt context, | |
1100 | * because the bus read/write functions may wait for an interrupt | |
1101 | * to conclude the operation. | |
1102 | */ | |
1103 | int mdiobus_c45_read_nested(struct mii_bus *bus, int addr, int devad, | |
1104 | u32 regnum) | |
1105 | { | |
1106 | int retval; | |
1107 | ||
1108 | mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); | |
1109 | retval = __mdiobus_c45_read(bus, addr, devad, regnum); | |
1110 | mutex_unlock(&bus->mdio_lock); | |
1111 | ||
1112 | return retval; | |
1113 | } | |
1114 | EXPORT_SYMBOL(mdiobus_c45_read_nested); | |
1115 | ||
21dd19fe NA |
1116 | /** |
1117 | * mdiobus_write_nested - Nested version of the mdiobus_write function | |
1118 | * @bus: the mii_bus struct | |
1119 | * @addr: the phy address | |
1120 | * @regnum: register number to write | |
1121 | * @val: value to write to @regnum | |
1122 | * | |
1123 | * In case of nested MDIO bus access avoid lockdep false positives by | |
1124 | * using mutex_lock_nested(). | |
1125 | * | |
1126 | * NOTE: MUST NOT be called from interrupt context, | |
1127 | * because the bus read/write functions may wait for an interrupt | |
1128 | * to conclude the operation. | |
1129 | */ | |
1130 | int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val) | |
1131 | { | |
1132 | int err; | |
1133 | ||
9a6f2b01 | 1134 | mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); |
34dc08e4 | 1135 | err = __mdiobus_write(bus, addr, regnum, val); |
21dd19fe NA |
1136 | mutex_unlock(&bus->mdio_lock); |
1137 | ||
1138 | return err; | |
1139 | } | |
1140 | EXPORT_SYMBOL(mdiobus_write_nested); | |
1141 | ||
2e888103 LB |
1142 | /** |
1143 | * mdiobus_write - Convenience function for writing a given MII mgmt register | |
1144 | * @bus: the mii_bus struct | |
1145 | * @addr: the phy address | |
1146 | * @regnum: register number to write | |
1147 | * @val: value to write to @regnum | |
1148 | * | |
1149 | * NOTE: MUST NOT be called from interrupt context, | |
1150 | * because the bus read/write functions may wait for an interrupt | |
1151 | * to conclude the operation. | |
1152 | */ | |
abf35df2 | 1153 | int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) |
2e888103 LB |
1154 | { |
1155 | int err; | |
1156 | ||
2e888103 | 1157 | mutex_lock(&bus->mdio_lock); |
34dc08e4 | 1158 | err = __mdiobus_write(bus, addr, regnum, val); |
2e888103 LB |
1159 | mutex_unlock(&bus->mdio_lock); |
1160 | ||
1161 | return err; | |
1162 | } | |
1163 | EXPORT_SYMBOL(mdiobus_write); | |
1164 | ||
4e4aafcd AL |
1165 | /** |
1166 | * mdiobus_c45_write - Convenience function for writing a given MII mgmt register | |
1167 | * @bus: the mii_bus struct | |
1168 | * @addr: the phy address | |
1169 | * @devad: device address to read | |
1170 | * @regnum: register number to write | |
1171 | * @val: value to write to @regnum | |
1172 | * | |
1173 | * NOTE: MUST NOT be called from interrupt context, | |
1174 | * because the bus read/write functions may wait for an interrupt | |
1175 | * to conclude the operation. | |
1176 | */ | |
1177 | int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, | |
1178 | u16 val) | |
1179 | { | |
1180 | int err; | |
1181 | ||
1182 | mutex_lock(&bus->mdio_lock); | |
1183 | err = __mdiobus_c45_write(bus, addr, devad, regnum, val); | |
1184 | mutex_unlock(&bus->mdio_lock); | |
1185 | ||
1186 | return err; | |
1187 | } | |
1188 | EXPORT_SYMBOL(mdiobus_c45_write); | |
1189 | ||
1d914d51 AL |
1190 | /** |
1191 | * mdiobus_c45_write_nested - Nested version of the mdiobus_c45_write function | |
1192 | * @bus: the mii_bus struct | |
1193 | * @addr: the phy address | |
1194 | * @devad: device address to read | |
1195 | * @regnum: register number to write | |
1196 | * @val: value to write to @regnum | |
1197 | * | |
1198 | * In case of nested MDIO bus access avoid lockdep false positives by | |
1199 | * using mutex_lock_nested(). | |
1200 | * | |
1201 | * NOTE: MUST NOT be called from interrupt context, | |
1202 | * because the bus read/write functions may wait for an interrupt | |
1203 | * to conclude the operation. | |
1204 | */ | |
1205 | int mdiobus_c45_write_nested(struct mii_bus *bus, int addr, int devad, | |
1206 | u32 regnum, u16 val) | |
1207 | { | |
1208 | int err; | |
1209 | ||
1210 | mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); | |
1211 | err = __mdiobus_c45_write(bus, addr, devad, regnum, val); | |
1212 | mutex_unlock(&bus->mdio_lock); | |
1213 | ||
1214 | return err; | |
1215 | } | |
1216 | EXPORT_SYMBOL(mdiobus_c45_write_nested); | |
1217 | ||
e6a45700 RKO |
1218 | /* |
1219 | * __mdiobus_modify - Convenience function for modifying a given mdio device | |
1220 | * register | |
1221 | * @bus: the mii_bus struct | |
1222 | * @addr: the phy address | |
1223 | * @regnum: register number to write | |
1224 | * @mask: bit mask of bits to clear | |
1225 | * @set: bit mask of bits to set | |
1226 | */ | |
1227 | int __mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, | |
1228 | u16 set) | |
1229 | { | |
1230 | int err; | |
1231 | ||
1232 | err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); | |
1233 | ||
1234 | return err < 0 ? err : 0; | |
1235 | } | |
1236 | EXPORT_SYMBOL_GPL(__mdiobus_modify); | |
1237 | ||
6cc7cf81 RK |
1238 | /** |
1239 | * mdiobus_modify - Convenience function for modifying a given mdio device | |
1240 | * register | |
1241 | * @bus: the mii_bus struct | |
1242 | * @addr: the phy address | |
1243 | * @regnum: register number to write | |
1244 | * @mask: bit mask of bits to clear | |
1245 | * @set: bit mask of bits to set | |
1246 | */ | |
1247 | int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set) | |
1248 | { | |
1249 | int err; | |
1250 | ||
6cc7cf81 | 1251 | mutex_lock(&bus->mdio_lock); |
e6a45700 | 1252 | err = __mdiobus_modify(bus, addr, regnum, mask, set); |
6cc7cf81 RK |
1253 | mutex_unlock(&bus->mdio_lock); |
1254 | ||
e6a45700 | 1255 | return err; |
6cc7cf81 RK |
1256 | } |
1257 | EXPORT_SYMBOL_GPL(mdiobus_modify); | |
1258 | ||
4e4aafcd AL |
1259 | /** |
1260 | * mdiobus_c45_modify - Convenience function for modifying a given mdio device | |
1261 | * register | |
1262 | * @bus: the mii_bus struct | |
1263 | * @addr: the phy address | |
1264 | * @devad: device address to read | |
1265 | * @regnum: register number to write | |
1266 | * @mask: bit mask of bits to clear | |
1267 | * @set: bit mask of bits to set | |
1268 | */ | |
1269 | int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, | |
1270 | u16 mask, u16 set) | |
1271 | { | |
1272 | int err; | |
1273 | ||
1274 | mutex_lock(&bus->mdio_lock); | |
1275 | err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, | |
1276 | mask, set); | |
1277 | mutex_unlock(&bus->mdio_lock); | |
1278 | ||
1279 | return err < 0 ? err : 0; | |
1280 | } | |
1281 | EXPORT_SYMBOL_GPL(mdiobus_c45_modify); | |
1282 | ||
79365f36 RKO |
1283 | /** |
1284 | * mdiobus_modify_changed - Convenience function for modifying a given mdio | |
1285 | * device register and returning if it changed | |
1286 | * @bus: the mii_bus struct | |
1287 | * @addr: the phy address | |
1288 | * @regnum: register number to write | |
1289 | * @mask: bit mask of bits to clear | |
1290 | * @set: bit mask of bits to set | |
1291 | */ | |
1292 | int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, | |
1293 | u16 mask, u16 set) | |
1294 | { | |
1295 | int err; | |
1296 | ||
1297 | mutex_lock(&bus->mdio_lock); | |
1298 | err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); | |
1299 | mutex_unlock(&bus->mdio_lock); | |
1300 | ||
1301 | return err; | |
1302 | } | |
1303 | EXPORT_SYMBOL_GPL(mdiobus_modify_changed); | |
1304 | ||
4e4aafcd AL |
1305 | /** |
1306 | * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio | |
1307 | * device register and returning if it changed | |
1308 | * @bus: the mii_bus struct | |
1309 | * @addr: the phy address | |
1310 | * @devad: device address to read | |
1311 | * @regnum: register number to write | |
1312 | * @mask: bit mask of bits to clear | |
1313 | * @set: bit mask of bits to set | |
1314 | */ | |
408c0900 | 1315 | int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, |
4e4aafcd AL |
1316 | u32 regnum, u16 mask, u16 set) |
1317 | { | |
1318 | int err; | |
1319 | ||
1320 | mutex_lock(&bus->mdio_lock); | |
1321 | err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); | |
1322 | mutex_unlock(&bus->mdio_lock); | |
1323 | ||
1324 | return err; | |
1325 | } | |
1326 | EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); | |
1327 | ||
b3df0da8 | 1328 | /** |
e76a4957 AL |
1329 | * mdio_bus_match - determine if given MDIO driver supports the given |
1330 | * MDIO device | |
1331 | * @dev: target MDIO device | |
1332 | * @drv: given MDIO driver | |
00db8189 | 1333 | * |
e76a4957 AL |
1334 | * Description: Given a MDIO device, and a MDIO driver, return 1 if |
1335 | * the driver supports the device. Otherwise, return 0. This may | |
1336 | * require calling the devices own match function, since different classes | |
1337 | * of MDIO devices have different match criteria. | |
00db8189 AF |
1338 | */ |
1339 | static int mdio_bus_match(struct device *dev, struct device_driver *drv) | |
1340 | { | |
94114d90 | 1341 | struct mdio_driver *mdiodrv = to_mdio_driver(drv); |
e76a4957 | 1342 | struct mdio_device *mdio = to_mdio_device(dev); |
00db8189 | 1343 | |
94114d90 RKO |
1344 | /* Both the driver and device must type-match */ |
1345 | if (!(mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY) != | |
1346 | !(mdio->flags & MDIO_DEVICE_FLAG_PHY)) | |
1347 | return 0; | |
1348 | ||
a30e2c18 DD |
1349 | if (of_driver_match_device(dev, drv)) |
1350 | return 1; | |
1351 | ||
e76a4957 AL |
1352 | if (mdio->bus_match) |
1353 | return mdio->bus_match(dev, drv); | |
a30e2c18 | 1354 | |
e76a4957 | 1355 | return 0; |
00db8189 AF |
1356 | } |
1357 | ||
2a81ada3 | 1358 | static int mdio_uevent(const struct device *dev, struct kobj_uevent_env *env) |
1b8f8694 RK |
1359 | { |
1360 | int rc; | |
1361 | ||
1362 | /* Some devices have extra OF data and an OF-style MODALIAS */ | |
1363 | rc = of_device_uevent_modalias(dev, env); | |
1364 | if (rc != -ENODEV) | |
1365 | return rc; | |
1366 | ||
1367 | return 0; | |
1368 | } | |
1369 | ||
080bb352 FF |
1370 | static struct attribute *mdio_bus_device_statistics_attrs[] = { |
1371 | &dev_attr_mdio_bus_device_transfers.attr.attr, | |
1372 | &dev_attr_mdio_bus_device_errors.attr.attr, | |
1373 | &dev_attr_mdio_bus_device_writes.attr.attr, | |
1374 | &dev_attr_mdio_bus_device_reads.attr.attr, | |
1375 | NULL, | |
1376 | }; | |
1377 | ||
1378 | static const struct attribute_group mdio_bus_device_statistics_group = { | |
1379 | .name = "statistics", | |
1380 | .attrs = mdio_bus_device_statistics_attrs, | |
1381 | }; | |
1382 | ||
1383 | static const struct attribute_group *mdio_bus_dev_groups[] = { | |
1384 | &mdio_bus_device_statistics_group, | |
1385 | NULL, | |
1386 | }; | |
1387 | ||
00db8189 AF |
1388 | struct bus_type mdio_bus_type = { |
1389 | .name = "mdio_bus", | |
080bb352 | 1390 | .dev_groups = mdio_bus_dev_groups, |
00db8189 | 1391 | .match = mdio_bus_match, |
1b8f8694 | 1392 | .uevent = mdio_uevent, |
00db8189 | 1393 | }; |
11b0bacd | 1394 | EXPORT_SYMBOL(mdio_bus_type); |
00db8189 | 1395 | |
67c4f3fa | 1396 | int __init mdio_bus_init(void) |
00db8189 | 1397 | { |
46abc021 LB |
1398 | int ret; |
1399 | ||
1400 | ret = class_register(&mdio_bus_class); | |
1401 | if (!ret) { | |
1402 | ret = bus_register(&mdio_bus_type); | |
1403 | if (ret) | |
1404 | class_unregister(&mdio_bus_class); | |
1405 | } | |
1406 | ||
1407 | return ret; | |
00db8189 AF |
1408 | } |
1409 | ||
90eff909 | 1410 | #if IS_ENABLED(CONFIG_PHYLIB) |
dc85dec6 | 1411 | void mdio_bus_exit(void) |
e1393456 | 1412 | { |
46abc021 | 1413 | class_unregister(&mdio_bus_class); |
e1393456 AF |
1414 | bus_unregister(&mdio_bus_type); |
1415 | } | |
90eff909 FF |
1416 | EXPORT_SYMBOL_GPL(mdio_bus_exit); |
1417 | #else | |
1418 | module_init(mdio_bus_init); | |
1419 | /* no module_exit, intentional */ | |
1420 | MODULE_LICENSE("GPL"); | |
1421 | MODULE_DESCRIPTION("MDIO bus/device layer"); | |
1422 | #endif |