Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * i2c-boardinfo.c - collect pre-declarations of I2C devices 4 : : */ 5 : : 6 : : #include <linux/export.h> 7 : : #include <linux/i2c.h> 8 : : #include <linux/kernel.h> 9 : : #include <linux/property.h> 10 : : #include <linux/rwsem.h> 11 : : #include <linux/slab.h> 12 : : 13 : : #include "i2c-core.h" 14 : : 15 : : 16 : : /* These symbols are exported ONLY FOR the i2c core. 17 : : * No other users will be supported. 18 : : */ 19 : : DECLARE_RWSEM(__i2c_board_lock); 20 : : EXPORT_SYMBOL_GPL(__i2c_board_lock); 21 : : 22 : : LIST_HEAD(__i2c_board_list); 23 : : EXPORT_SYMBOL_GPL(__i2c_board_list); 24 : : 25 : : int __i2c_first_dynamic_bus_num; 26 : : EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num); 27 : : 28 : : 29 : : /** 30 : : * i2c_register_board_info - statically declare I2C devices 31 : : * @busnum: identifies the bus to which these devices belong 32 : : * @info: vector of i2c device descriptors 33 : : * @len: how many descriptors in the vector; may be zero to reserve 34 : : * the specified bus number. 35 : : * 36 : : * Systems using the Linux I2C driver stack can declare tables of board info 37 : : * while they initialize. This should be done in board-specific init code 38 : : * near arch_initcall() time, or equivalent, before any I2C adapter driver is 39 : : * registered. For example, mainboard init code could define several devices, 40 : : * as could the init code for each daughtercard in a board stack. 41 : : * 42 : : * The I2C devices will be created later, after the adapter for the relevant 43 : : * bus has been registered. After that moment, standard driver model tools 44 : : * are used to bind "new style" I2C drivers to the devices. The bus number 45 : : * for any device declared using this routine is not available for dynamic 46 : : * allocation. 47 : : * 48 : : * The board info passed can safely be __initdata, but be careful of embedded 49 : : * pointers (for platform_data, functions, etc) since that won't be copied. 50 : : * Device properties are deep-copied though. 51 : : */ 52 : 0 : int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len) 53 : : { 54 : 0 : int status; 55 : : 56 : 0 : down_write(&__i2c_board_lock); 57 : : 58 : : /* dynamic bus numbers will be assigned after the last static one */ 59 [ # # ]: 0 : if (busnum >= __i2c_first_dynamic_bus_num) 60 : 0 : __i2c_first_dynamic_bus_num = busnum + 1; 61 : : 62 [ # # ]: 0 : for (status = 0; len; len--, info++) { 63 : 0 : struct i2c_devinfo *devinfo; 64 : : 65 : 0 : devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); 66 [ # # ]: 0 : if (!devinfo) { 67 : : pr_debug("i2c-core: can't register boardinfo!\n"); 68 : : status = -ENOMEM; 69 : : break; 70 : : } 71 : : 72 : 0 : devinfo->busnum = busnum; 73 : 0 : devinfo->board_info = *info; 74 : : 75 [ # # ]: 0 : if (info->properties) { 76 : 0 : devinfo->board_info.properties = 77 : 0 : property_entries_dup(info->properties); 78 [ # # ]: 0 : if (IS_ERR(devinfo->board_info.properties)) { 79 : 0 : status = PTR_ERR(devinfo->board_info.properties); 80 : 0 : kfree(devinfo); 81 : 0 : break; 82 : : } 83 : : } 84 : : 85 [ # # ]: 0 : if (info->resources) { 86 : 0 : devinfo->board_info.resources = 87 : 0 : kmemdup(info->resources, 88 : 0 : info->num_resources * 89 : : sizeof(*info->resources), 90 : : GFP_KERNEL); 91 [ # # ]: 0 : if (!devinfo->board_info.resources) { 92 : 0 : status = -ENOMEM; 93 : 0 : kfree(devinfo); 94 : 0 : break; 95 : : } 96 : : } 97 : : 98 : 0 : list_add_tail(&devinfo->list, &__i2c_board_list); 99 : : } 100 : : 101 : 0 : up_write(&__i2c_board_lock); 102 : : 103 : 0 : return status; 104 : : }