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 { 29 struct mdio_board_entry *be; 30 struct mdio_device *mdiodev; 31 struct mdio_board_info *bi; 32 int ret; 33 34 mutex_lock(&mdio_board_lock); 35 list_for_each_entry(be, &mdio_board_list, list) { 36 bi = &be->board_info; 37 38 if (strcmp(bus->id, bi->bus_id)) 39 continue; 40 41 mdiodev = mdio_device_create(bus, bi->mdio_addr); 42 if (IS_ERR(mdiodev)) 43 continue; 44 45 strncpy(mdiodev->modalias, bi->modalias, 46 sizeof(mdiodev->modalias)); 47 mdiodev->bus_match = mdio_device_bus_match; 48 mdiodev->dev.platform_data = (void *)bi->platform_data; 49 50 ret = mdio_device_register(mdiodev); 51 if (ret) { 52 mdio_device_free(mdiodev); 53 continue; 54 } 55 } 56 mutex_unlock(&mdio_board_lock); 57 } 58 59 /** 60 * mdio_register_board_info - register MDIO devices for a given board 61 * @info: array of devices descriptors 62 * @n: number of descriptors provided 63 * Context: can sleep 64 * 65 * The board info passed can be marked with __initdata but be pointers 66 * such as platform_data etc. are copied as-is 67 */ 68 int mdiobus_register_board_info(const struct mdio_board_info *info, 69 unsigned int n) 70 { 71 struct mdio_board_entry *be; 72 unsigned int i; 73 74 be = kcalloc(n, sizeof(*be), GFP_KERNEL); 75 if (!be) 76 return -ENOMEM; 77 78 for (i = 0; i < n; i++, be++, info++) { 79 memcpy(&be->board_info, info, sizeof(*info)); 80 mutex_lock(&mdio_board_lock); 81 list_add_tail(&be->list, &mdio_board_list); 82 mutex_unlock(&mdio_board_lock); 83 } 84 85 return 0; 86 } 87 EXPORT_SYMBOL(mdiobus_register_board_info); 88