1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * mdio-boardinfo - Collect pre-declarations for MDIO devices |
4 | */ |
5 | |
6 | #include <linux/kernel.h> |
7 | #include <linux/slab.h> |
8 | #include <linux/export.h> |
9 | #include <linux/mutex.h> |
10 | #include <linux/list.h> |
11 | |
12 | #include "mdio-boardinfo.h" |
13 | |
14 | static LIST_HEAD(mdio_board_list); |
15 | static DEFINE_MUTEX(mdio_board_lock); |
16 | |
17 | /** |
18 | * mdiobus_setup_mdiodev_from_board_info - create and setup MDIO devices |
19 | * from pre-collected board specific MDIO information |
20 | * @bus: Bus the board_info belongs to |
21 | * @cb: Callback to create device on bus |
22 | * Context: can sleep |
23 | */ |
24 | void mdiobus_setup_mdiodev_from_board_info(struct mii_bus *bus, |
25 | int (*cb) |
26 | (struct mii_bus *bus, |
27 | struct mdio_board_info *bi)) |
28 | { |
29 | struct mdio_board_entry *be; |
30 | struct mdio_board_entry *tmp; |
31 | struct mdio_board_info *bi; |
32 | int ret; |
33 | |
34 | mutex_lock(&mdio_board_lock); |
35 | list_for_each_entry_safe(be, tmp, &mdio_board_list, list) { |
36 | bi = &be->board_info; |
37 | |
38 | if (strcmp(bus->id, bi->bus_id)) |
39 | continue; |
40 | |
41 | mutex_unlock(lock: &mdio_board_lock); |
42 | ret = cb(bus, bi); |
43 | mutex_lock(&mdio_board_lock); |
44 | if (ret) |
45 | continue; |
46 | |
47 | } |
48 | mutex_unlock(lock: &mdio_board_lock); |
49 | } |
50 | EXPORT_SYMBOL(mdiobus_setup_mdiodev_from_board_info); |
51 | |
52 | /** |
53 | * mdiobus_register_board_info - register MDIO devices for a given board |
54 | * @info: array of devices descriptors |
55 | * @n: number of descriptors provided |
56 | * Context: can sleep |
57 | * |
58 | * The board info passed can be marked with __initdata but be pointers |
59 | * such as platform_data etc. are copied as-is |
60 | */ |
61 | int mdiobus_register_board_info(const struct mdio_board_info *info, |
62 | unsigned int n) |
63 | { |
64 | struct mdio_board_entry *be; |
65 | unsigned int i; |
66 | |
67 | be = kcalloc(n, size: sizeof(*be), GFP_KERNEL); |
68 | if (!be) |
69 | return -ENOMEM; |
70 | |
71 | for (i = 0; i < n; i++, be++, info++) { |
72 | memcpy(&be->board_info, info, sizeof(*info)); |
73 | mutex_lock(&mdio_board_lock); |
74 | list_add_tail(new: &be->list, head: &mdio_board_list); |
75 | mutex_unlock(lock: &mdio_board_lock); |
76 | } |
77 | |
78 | return 0; |
79 | } |
80 | EXPORT_SYMBOL(mdiobus_register_board_info); |
81 | |