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