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