i2c drivers
转载于:http://blog.csdn.net/liuhaoyutz
内核版本:3.10.1
编写一个I2C设备驱动程序的工作可分为两部分,一是定义和注册I2C设备,即i2c_client;二是定义和注册I2C设备驱动,即i2c_driver。下面我们就以mini2440的I2C设备at24c08 EEPROM为例,介绍如何完成这两个工作。
一、定义和注册I2C设备
步骤1:用i2c_board_info保存I2C设备相关信息
在Linux中,struct i2c_client代表一个I2C设备,该结构体定义在include/linux/i2c.h文件中:
- 200/**
- 201 * struct i2c_client - represent an I2Cslave device
- 202 * @flags: I2C_CLIENT_TEN indicates thedevice uses a ten bit chip address;
- 203 * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
- 204 * @addr: Address used on the I2C busconnected to the parent adapter.
- 205 * @name: Indicates the type of thedevice, usually a chip name that's
- 206 * generic enough to hide second-sourcing and compatible revisions.
- 207 * @adapter: manages the bus segmenthosting this I2C device
- 208 * @driver: device's driver, hencepointer to access routines
- 209 * @dev: Driver model device node forthe slave.
- 210 * @irq: indicates the IRQ generated bythis device (if any)
- 211 * @detected: member of ani2c_driver.clients list or i2c-core's
- 212 * userspace_devices list
- 213 *
- 214 * An i2c_client identifies a singledevice (i.e. chip) connected to an
- 215 * i2c bus. The behaviour exposed to Linuxis defined by the driver
- 216 * managing the device.
- 217 */
- 218struct i2c_client {
- 219 unsigned short flags; /*div., see below */
- 220 unsigned short addr; /*chip address - NOTE: 7bit */
- 221 /* addresses are stored inthe */
- 222 /* _LOWER_ 7 bits */
- 223 char name[I2C_NAME_SIZE];
- 224 struct i2c_adapter *adapter; /*the adapter we sit on */
- 225 struct i2c_driver *driver; /* andour access routines */
- 226 struct device dev; /* thedevice structure */
- 227 int irq; /* irq issuedby device */
- 228 struct list_head detected;
- 229};
我们不用直接定义一个i2c_client结构,Linux会根据I2C设备的相关信息自动创建i2c_client。所以,我们需要提供I2C设备的相关信息。对于Mini2440的I2C设备at24c08 EEPROM,其相关信息保存在arch/arm/mach-s3c24xx/mach-mini2440.c文件中:
- 485/*
- 486 * I2C devices
- 487 */
- 488static struct at24_platform_data at24c08= {
- 489 .byte_len = SZ_8K / 8,
- 490 .page_size = 16,
- 491};
- 492
- 493static struct i2c_board_infomini2440_i2c_devs[] __initdata = {
- 494 {
- 495 I2C_BOARD_INFO("24c08", 0x50),
- 496 .platform_data = &at24c08,
- 497 },
- 498};
struct i2c_board_info是创建i2c设备的模板,该结构体定义在include/linux/i2c.h文件中:
- 251/**
- 252 * struct i2c_board_info - template fordevice creation
- 253 * @type: chip type, to initializei2c_client.name
- 254 * @flags: to initializei2c_client.flags
- 255 * @addr: stored in i2c_client.addr
- 256 * @platform_data: stored ini2c_client.dev.platform_data
- 257 * @archdata: copied intoi2c_client.dev.archdata
- 258 * @of_node: pointer to OpenFirmwaredevice node
- 259 * @acpi_node: ACPI device node
- 260 * @irq: stored in i2c_client.irq
- 261 *
- 262 * I2C doesn't actually support hardwareprobing, although controllers and
- 263 * devices may be able to useI2C_SMBUS_QUICK to tell whether or not there's
- 264 * a device at a given address. Drivers commonly need more information than
- 265 * that, such as chip type,configuration, associated IRQ, and so on.
- 266 *
- 267 * i2c_board_info is used to buildtables of information listing I2C devices
- 268 * that are present. This information is used to grow the drivermodel tree.
- 269 * For mainboards this is donestatically using i2c_register_board_info();
- 270 * bus numbers identify adapters thataren't yet available. For add-on boards,
- 271 * i2c_new_device() does thisdynamically with the adapter already known.
- 272 */
- 273struct i2c_board_info {
- 274 char type[I2C_NAME_SIZE];
- 275 unsigned short flags;
- 276 unsigned short addr;
- 277 void *platform_data;
- 278 struct dev_archdata *archdata;
- 279 struct device_node *of_node;
- 280 struct acpi_dev_node acpi_node;
- 281 int irq;
- 282};
从注释可以看到,i2c_board_info结构体用来保存I2C设备的相关信息,Linux根据这些信息创建I2C设备相关的设备模型树。对于mainboards,通过调用i2c_register_board_info()静态完成。对于add-on boards,通过调用i2c_new_device()动态完成。
i2c_board_info结构体有两个成员必须初始化,一个是type,用来初始化i2c_client.name;另一个是addr,用来初始化i2c_client.addr。其它i2c_board_info结构体成员根据需要赋值或保持为空。
宏I2C_BOARD_INFO定义在include/linux/i2c.h文件中,其内容如下:
- 284/**
- 285 * I2C_BOARD_INFO - macro used to listan i2c device and its address
- 286 * @dev_type: identifies the device type
- 287 * @dev_addr: the device's address onthe bus.
- 288 *
- 289 * This macro initializes essentialfields of a struct i2c_board_info,
- 290 * declaring what has been provided on aparticular board. Optional
- 291 * fields (such as associated irq, ordevice-specific platform_data)
- 292 * are provided using conventionalsyntax.
- 293 */
- 294#define I2C_BOARD_INFO(dev_type,dev_addr) \
- 295 .type = dev_type, .addr = (dev_addr)
从注释可以看到,I2C_BOARD_INFO宏用来初始化i2c_board_info结构体的两个必须初始化的成员变量type和addr。i2c_board_info结构体的其它成员变量使用常规的初始化语法。
struct at24_platform_data定义在include/linux/i2c/at24.h文件中:
1
- 4/**
- 15 * struct at24_platform_data - data toset up at24 (generic eeprom) driver
- 16 * @byte_len: size of eeprom in byte
- 17 * @page_size: number of byte which canbe written in one go
- 18 * @flags: tunable options, checkAT24_FLAG_* defines
- 19 * @setup: an optional callback invokedafter eeprom is probed; enables kernel
- 20 code to access eeprom via memory_accessor, see example
- 21 * @context: optional parameter passed tosetup()
- 22 *
- 23 * If you set up a custom eeprom type,please double-check the parameters.
- 24 * Especially page_size needs extra care,as you risk data loss if your value
- 25 * is bigger than what the chip actuallysupports!
- 26 *
- 27 * An example in pseudo code for asetup() callback:
- 28 *
- 29 * void get_mac_addr(structmemory_accessor *mem_acc, void *context)
- 30 * {
- 31 * u8 *mac_addr = ethernet_pdata->mac_addr;
- 32 * off_t offset = context;
- 33 *
- 34 * // Read MAC addr from EEPROM
- 35 * if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
- 36 * pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
- 37 * }
- 38 *
- 39 * This function pointer and context cannow be set up in at24_platform_data.
- 40 */
- 41
- 42struct at24_platform_data {
- 43 u32 byte_len; /* size (sum of all addr) */
- 44 u16 page_size; /* for writes */
- 45 u8 flags;
- 46#define AT24_FLAG_ADDR16 0x80 /* address pointer is 16 bit */
- 47#define AT24_FLAG_READONLY 0x40 /* sysfs-entry will be read-only */
- 48#define AT24_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */
- 49#define AT24_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */
- 50
- 51 void (*setup)(structmemory_accessor *, void *context);
- 52 void *context;
- 53};
该结构体用来保存at24系列EEPROM的platform data。byte_len成员变量保存EEPROM的大小,以byte为单位。page_size成员变量用来指定一次最多能写多少个byte。对于Mini2440,定义at24_platform_data结构体变量at24c08:
- 488static struct at24_platform_data at24c08= {
- 489 .byte_len = SZ_8K / 8,
- 490 .page_size = 16,
- 491};
SZ_8K宏即8K,定义在include/linux/sizes.h文件中:
- 25#define SZ_8K 0x00002000
步骤2:调用i2c_register_board_info注册i2c设备相关信息
对于Mini2440的I2C设备at24c08 EEPROM,由arch/arm/mach-s3c24xx/mach-mini2440.c文件中的mini2440_init函数调用i2c_register_board_info注册i2c设备相关信息,mini2440_init函数内容如下:
- 622static void __init mini2440_init(void)
- 623{
- 624 struct mini2440_features_t features = { 0 };
- 625 int i;
- 626
- 627 printk(KERN_INFO "MINI2440: Option string mini2440=%s\n",
- 628 mini2440_features_str);
- 629
- 630 /* Parse the feature string */
- 631 mini2440_parse_features(&features, mini2440_features_str);
- 632
- 633 /* turn LCD on */
- 634 s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
- 635
- 636 /* Turn the backlight early on */
- 637 WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL));
- 638 gpio_free(S3C2410_GPG(4));
- 639
- 640 /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s*/
- 641 gpio_request_one(S3C2410_GPB(1), GPIOF_IN, NULL);
- 642 s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
- 643 gpio_free(S3C2410_GPB(1));
- 644
- 645 /* mark the key as input, without pullups (there is one on the board) */
- 646 for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
- 647 s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);
- 648 s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT);
- 649 }
- 650 if (features.lcd_index != -1) {
- 651 int li;
- 652
- 653 mini2440_fb_info.displays =
- 654 &mini2440_lcd_cfg[features.lcd_index];
- 655
- 656 printk(KERN_INFO "MINI2440: LCD");
- 657 for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)
- 658 if (li == features.lcd_index)
- 659 printk(" [%d:%dx%d]",li,
- 660 mini2440_lcd_cfg[li].width,
- 661 mini2440_lcd_cfg[li].height);
- 662 else
- 663 printk(" %d:%dx%d",li,
- 664 mini2440_lcd_cfg[li].width,
- 665 mini2440_lcd_cfg[li].height);
- 666 printk("\n");
- 667 s3c24xx_fb_set_platdata(&mini2440_fb_info);
- 668 }
- 669
- 670 s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
- 671 s3c24xx_mci_set_platdata(&mini2440_mmc_cfg);
- 672 s3c_nand_set_platdata(&mini2440_nand_info);
- 673 s3c_i2c0_set_platdata(NULL);
- 674
- 675 i2c_register_board_info(0, mini2440_i2c_devs,
- 676 ARRAY_SIZE(mini2440_i2c_devs));
- 677
- 678 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
- 679
- 680 if (features.count) /* the optional features */
- 681 platform_add_devices(features.optional, features.count);
- 682
- 683}
这个函数我们这里只需要关注675行,调用i2c_register_board_info注册mini2440_i2c_devs。mini2440_i2c_devs就是上面定义的i2c_board_info结构体数组,其中定义了at24c08相关信息。
i2c_register_board_info函数定义在drivers/i2c/i2c-boardinfo.c文件中,其内容如下:
- 42/**
- 43 * i2c_register_board_info - staticallydeclare I2C devices
- 44 * @busnum: identifies the bus to whichthese devices belong
- 45 * @info: vector of i2c devicedescriptors
- 46 * @len: how many descriptors in the vector;may be zero to reserve
- 47 * the specified bus number.
- 48 *
- 49 * Systems using the Linux I2C driverstack can declare tables of board info
- 50 * while they initialize. This should be done in board-specific initcode
- 51 * near arch_initcall() time, orequivalent, before any I2C adapter driver is
- 52 * registered. For example, mainboard init code could defineseveral devices,
- 53 * as could the init code for eachdaughtercard in a board stack.
- 54 *
- 55 * The I2C devices will be created later,after the adapter for the relevant
- 56 * bus has been registered. After that moment, standard driver modeltools
- 57 * are used to bind "new style"I2C drivers to the devices. The busnumber
- 58 * for any device declared using thisroutine is not available for dynamic
- 59 * allocation.
- 60 *
- 61 * The board info passed can safely be__initdata, but be careful of embedded
- 62 * pointers (for platform_data,functions, etc) since that won't be copied.
- 63 */
- 64int __init
- 65i2c_register_board_info(int busnum,
- 66 struct i2c_board_info const *info, unsigned len)
- 67{
- 68 int status;
- 69
- 70 down_write(&__i2c_board_lock);
- 71
- 72 /* dynamic bus numbers will be assigned after the last static one */
- 73 if (busnum >= __i2c_first_dynamic_bus_num)
- 74 __i2c_first_dynamic_bus_num = busnum + 1;
- 75
- 76 for (status = 0; len; len--, info++) {
- 77 struct i2c_devinfo *devinfo;
- 78
- 79 devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
- 80 if (!devinfo) {
- 81 pr_debug("i2c-core: can'tregister boardinfo!\n");
- 82 status = -ENOMEM;
- 83 break;
- 84 }
- 85
- 86 devinfo->busnum = busnum;
- 87 devinfo->board_info = *info;
- 88 list_add_tail(&devinfo->list, &__i2c_board_list);
- 89 }
- 90
- 91 up_write(&__i2c_board_lock);
- 92
- 93 return status;
- 94}
第一个参数busnum表明I2C设备所依附的I2C总线的总线号。
72-74行,如果参数传递进来的busnum 大于等于__i2c_first_dynamic_bus_num,则将__i2c_first_dynamic_bus_num设置为busnum+1。__i2c_first_dynamic_bus_num代表第一个动态分配的I2C总线号,所以,动态分配的I2C总线号总是大于静态分配的I2C总线号。
__i2c_first_dynamic_bus_num定义在drivers/i2c/i2c-boardinfo.c文件中:
- 38int __i2c_first_dynamic_bus_num;
因为__i2c_first_dynamic_bus_num是一个全局变量,所以其值被自动初始化为0。所以73行的if判断是成立的。
76-89行,循环遍历info数组,用i2c_board_info变量初始化structi2c_devinfo指针变量devinfo,然后将devinfo放入__i2c_board_list链表中。
i2c_devinfo变量定义在drivers/i2c/i2c-core.h文件中:
- 22struct i2c_devinfo {
- 23 struct list_head list;
- 24 int busnum;
- 25 struct i2c_board_info board_info;
- 26};
可以看到i2c_devinfo结构体只有三个成员变量,busnum用来保存I2C设备所依附的I2C总线号。board_info用来保存I2C设备相关信息。list用于链接到全局链表__i2c_board_list中。
__i2c_board_list 链表定义在drivers/i2c/i2c-boardinfo.c文件中:
- 35LIST_HEAD(__i2c_board_list);
- 36EXPORT_SYMBOL_GPL(__i2c_board_list);
全局变量__i2c_board_list上挂载着所有的I2C设备的信息,包括I2C设备所在的I2C总线的总线号。
所以,i2c_register_board_info函数并没有创建i2c_client,只是将i2c_devinfo变量放入__i2c_board_list链表中。那么,什么时候才会创建i2c_client呢?这个就与创建I2C设备驱动程序无关了,而是跟I2C adapter驱动程序有关:
注册一个I2C adapter有两种方法,一是调用i2c_add_adapter函数,二是调用i2c_add_numbered_adapter函数。
先来看i2c_add_adapter函数,它定义在drivers/i2c/i2c-core.c文件中:
- 1099/**
- 1100 * i2c_add_adapter - declare i2cadapter, use dynamic bus number
- 1101 * @adapter: the adapter to add
- 1102 * Context: can sleep
- 1103 *
- 1104 * This routine is used to declare anI2C adapter when its bus number
- 1105 * doesn't matter or when its busnumber is specified by an dt alias.
- 1106 * Examples of bases when the busnumber doesn't matter: I2C adapters
- 1107 * dynamically added by USB links orPCI plugin cards.
- 1108 *
- 1109 * When this returns zero, a new busnumber was allocated and stored
- 1110 * in adap->nr, and the specifiedadapter became available for clients.
- 1111 * Otherwise, a negative errno value isreturned.
- 1112 */
- 1113int i2c_add_adapter(struct i2c_adapter*adapter)
- 1114{
- 1115 struct device *dev = &adapter->dev;
- 1116 int id;
- 1117
- 1118 if (dev->of_node) {
- 1119 id = of_alias_get_id(dev->of_node, "i2c");
- 1120 if (id >= 0) {
- 1121 adapter->nr = id;
- 1122 return__i2c_add_numbered_adapter(adapter);
- 1123 }
- 1124 }
- 1125
- 1126 mutex_lock(&core_lock);
- 1127 id = idr_alloc(&i2c_adapter_idr, adapter,
- 1128 __i2c_first_dynamic_bus_num, 0,GFP_KERNEL);
- 1129 mutex_unlock(&core_lock);
- 1130 if (id < 0)
- 1131 return id;
- 1132
- 1133 adapter->nr = id;
- 1134
- 1135 return i2c_register_adapter(adapter);
- 1136}
该函数为参数指定的i2c_adapter动态分配的个I2C总线号,并注册该i2c_adapter。
1118-1124行,忽略。
1127-1133行,调用idr_alloc,动态分配一个id号,并将该id号做为i2c_adapter的I2C总线号。
关于idr机制,我们不详细分析,只需要知道它是一种快速索引机制,它将一个整数ID与一个需要被索引的指针建立联系,方便进行查找。例如,这里idr_alloc返回的id与i2c_adapter建立了索引。idr_alloc的第三个参数指定返回ID的最小值(闭区间),第四个参数指定返回ID的最大值(开区间),即idr_alloc返回的ID大于等于第三个参数,而且必须小于第四个参数。在这个函数中,第三个参数为__i2c_first_dynamic_bus_num,所以返回的id必然是大于等于__i2c_first_dynamic_bus_num的,即动态分配的I2C总线号必然大于__i2c_first_dynamic_bus_num。
1135行,调用i2c_register_adapter注册i2c_adapter。
下面我们来看i2c_add_numbered_adapter,该函数定义在drivers/i2c/i2c-core.c文件中:
- 1139/**
- 1140 * i2c_add_numbered_adapter - declarei2c adapter, use static bus number
- 1141 * @adap: the adapter to register (withadap->nr initialized)
- 1142 * Context: can sleep
- 1143 *
- 1144 * This routine is used to declare anI2C adapter when its bus number
- 1145 * matters. For example, use it for I2C adapters fromsystem-on-chip CPUs,
- 1146 * or otherwise built in to thesystem's mainboard, and where i2c_board_info
- 1147 * is used to properly configure I2Cdevices.
- 1148 *
- 1149 * If the requested bus number is setto -1, then this function will behave
- 1150 * identically to i2c_add_adapter, andwill dynamically assign a bus number.
- 1151 *
- 1152 * If no devices have pre-been declaredfor this bus, then be sure to
- 1153 * register the adapter before anydynamically allocated ones. Otherwise
- 1154 * the required bus ID may not beavailable.
- 1155 *
- 1156 * When this returns zero, thespecified adapter became available for
- 1157 * clients using the bus numberprovided in adap->nr. Also, the table
- 1158 * of I2C devices pre-declared usingi2c_register_board_info() is scanned,
- 1159 * and the appropriate driver modeldevice nodes are created. Otherwise, a
- 1160 * negative errno value is returned.
- 1161 */
- 1162int i2c_add_numbered_adapter(structi2c_adapter *adap)
- 1163{
- 1164 if (adap->nr == -1) /* -1 means dynamically assign bus id */
- 1165 return i2c_add_adapter(adap);
- 1166
- 1167 return __i2c_add_numbered_adapter(adap);
- 1168}
该函数用于注册参数指定的i2c_adapter,该i2c_adapter的I2C总线号即i2c_adapter.nr必须已经静态设置好了。如果adap->nr为-1,则调用i2c_add_adapter动态分配I2C总线号,再注册。否则,调用__i2c_add_numbered_adapter函数。
__i2c_add_numbered_adapter函数定义在drivers/i2c/i2c-core.c文件中:
- 1078/**
- 1079 * __i2c_add_numbered_adapter -i2c_add_numbered_adapter where nr is never -1
- 1080 * @adap: the adapter to register (withadap->nr initialized)
- 1081 * Context: can sleep
- 1082 *
- 1083 * See i2c_add_numbered_adapter() fordetails.
- 1084 */
- 1085static int__i2c_add_numbered_adapter(struct i2c_adapter *adap)
- 1086{
- 1087 int id;
- 1088
- 1089 mutex_lock(&core_lock);
- 1090 id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1,
- 1091 GFP_KERNEL);
- 1092 mutex_unlock(&core_lock);
- 1093 if (id < 0)
- 1094 return id == -ENOSPC ? -EBUSY : id;
- 1095
- 1096 return i2c_register_adapter(adap);
- 1097}
1090-1091行,调用idr_alloc函数,建立idr索引关系。返回的id必须大于等于第三个参数adap->nr,同时必须小于第四个参数adap->nr+1,所以返回的id必然等于adap->nr,即静态指定的I2C总线号。
1096行,调用i2c_register_adapter注册i2c_adapter。
到这里,我们就知道了注册一个i2c_adapter可以调用i2c_add_numbered_adapter函数静态指定一个I2C总线号,也可以调用i2c_add_adapter函数动态分配一个I2C总线号。但是不论哪种方法,最后的注册工作都必须通过调用i2c_register_adapter函数完成。
i2c_register_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 980staticint i2c_register_adapter(struct i2c_adapter *adap)
- 981{
- 982 int res = 0;
- 983
- 984 /* Can't register until after driver model init */
- 985 if (unlikely(WARN_ON(!i2c_bus_type.p))) {
- 986 res = -EAGAIN;
- 987 goto out_list;
- 988 }
- 989
- 990 /* Sanity checks */
- 991 if (unlikely(adap->name[0] == '\0')) {
- 992 pr_err("i2c-core: Attempt to register an adapter with "
- 993 "no name!\n");
- 994 return -EINVAL;
- 995 }
- 996 if (unlikely(!adap->algo)) {
- 997 pr_err("i2c-core: Attempt to register adapter '%s' with "
- 998 "no algo!\n",adap->name);
- 999 return -EINVAL;
- 1000 }
- 1001
- 1002 rt_mutex_init(&adap->bus_lock);
- 1003 mutex_init(&adap->userspace_clients_lock);
- 1004 INIT_LIST_HEAD(&adap->userspace_clients);
- 1005
- 1006 /* Set default timeout to 1 second if not already set */
- 1007 if (adap->timeout == 0)
- 1008 adap->timeout = HZ;
- 1009
- 1010 dev_set_name(&adap->dev, "i2c-%d", adap->nr);
- 1011 adap->dev.bus = &i2c_bus_type;
- 1012 adap->dev.type = &i2c_adapter_type;
- 1013 res = device_register(&adap->dev);
- 1014 if (res)
- 1015 goto out_list;
- 1016
- 1017 dev_dbg(&adap->dev, "adapter [%s] registered\n",adap->name);
- 1018
- 1019#ifdef CONFIG_I2C_COMPAT
- 1020 res = class_compat_create_link(i2c_adapter_compat_class,&adap->dev,
- 1021 adap->dev.parent);
- 1022 if (res)
- 1023 dev_warn(&adap->dev,
- 1024 "Failed to createcompatibility class link\n");
- 1025#endif
- 1026
- 1027 /* bus recovery specific initialization */
- 1028 if (adap->bus_recovery_info) {
- 1029 struct i2c_bus_recovery_info*bri = adap->bus_recovery_info;
- 1030
- 1031 if (!bri->recover_bus) {
- 1032 dev_err(&adap->dev, "Norecover_bus() found, not using recovery\n");
- 1033 adap->bus_recovery_info = NULL;
- 1034 goto exit_recovery;
- 1035 }
- 1036
- 1037 /* Generic GPIO recovery */
- 1038 if (bri->recover_bus == i2c_generic_gpio_recovery) {
- 1039 if(!gpio_is_valid(bri->scl_gpio)) {
- 1040 dev_err(&adap->dev,"Invalid SCL gpio, not using recovery\n");
- 1041 adap->bus_recovery_info =NULL;
- 1042 goto exit_recovery;
- 1043 }
- 1044
- 1045 if(gpio_is_valid(bri->sda_gpio))
- 1046 bri->get_sda =get_sda_gpio_value;
- 1047 else
- 1048 bri->get_sda = NULL;
- 1049
- 1050 bri->get_scl =get_scl_gpio_value;
- 1051 bri->set_scl =set_scl_gpio_value;
- 1052 } else if (!bri->set_scl || !bri->get_scl) {
- 1053 /* Generic SCL recovery */
- 1054 dev_err(&adap->dev, "No{get|set}_gpio() found, not using recovery\n");
- 1055 adap->bus_recovery_info = NULL;
- 1056 }
- 1057 }
- 1058
- 1059exit_recovery:
- 1060 /* create pre-declared device nodes */
- 1061 if (adap->nr < __i2c_first_dynamic_bus_num)
- 1062 i2c_scan_static_board_info(adap);
- 1063
- 1064 /* Notify drivers */
- 1065 mutex_lock(&core_lock);
- 1066 bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
- 1067 mutex_unlock(&core_lock);
- 1068
- 1069 return 0;
- 1070
- 1071out_list:
- 1072 mutex_lock(&core_lock);
- 1073 idr_remove(&i2c_adapter_idr, adap->nr);
- 1074 mutex_unlock(&core_lock);
- 1075 return res;
- 1076}
984-1000行,做一些必要的检查工作。
1002-1008行,做一些简单的i2c_adapter成员变量初始化工作。
1010-1013行,初始化i2c_adapter.dev,并调用device_register注册i2c_adapter.dev。
1028-1057行,I2C总线恢复时相关的初始化工作。
1060-1062行,因为动态分析的I2C总线号必须大于或等于__i2c_first_dynamic_bus_num,所以,如果adap->nr< __i2c_first_dynamic_bus_num,说明是静态指定的I2C总线号,此时,要调用i2c_scan_static_board_info函数探测I2C总线上静态注册的I2C设备。
i2c_scan_static_board_info函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 941staticvoid i2c_scan_static_board_info(struct i2c_adapter *adapter)
- 942{
- 943 struct i2c_devinfo *devinfo;
- 944
- 945 down_read(&__i2c_board_lock);
- 946 list_for_each_entry(devinfo, &__i2c_board_list, list) {
- 947 if (devinfo->busnum == adapter->nr
- 948 &&!i2c_new_device(adapter,
- 949 &devinfo->board_info))
- 950 dev_err(&adapter->dev,
- 951 "Can't create device at0x%02x\n",
- 952 devinfo->board_info.addr);
- 953 }
- 954 up_read(&__i2c_board_lock);
- 955}
946-953行,遍历__i2c_board_list链表,如果devinfo->busnum等于adapter->nr,即链表节点所代表的I2C设备的I2C总线号等于i2c_adapter的I2C总线号,则调用i2c_new_device创建并注册I2C设备对应的i2c_client结构体。
到这里,就和我们在本文开始部分介绍的静态注册的i2c_board_info信息联系起来了。回忆一下我们通过调用i2c_register_board_info函数将将包含所有I2C设备的i2c_board_info信息的i2c_devinfo变量加入到__i2c_board_list链表中。现在在注册i2c_adater时,又通过调用i2c_scan_static_board_info函数遍历__i2c_board_list链表,查找属于对应i2c_adapter的I2C设备,如果找到,调用i2c_new_device创建对应的i2c_client结构体。
i2c_new_device函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 612/**
- 613* i2c_new_device - instantiate an i2c device
- 614* @adap: the adapter managing the device
- 615* @info: describes one I2C device; bus_num is ignored
- 616* Context: can sleep
- 617*
- 618* Create an i2c device. Binding is handled through driver model
- 619* probe()/remove() methods. A driver maybe bound to this device when we
- 620* return from this function, or any later moment (e.g. maybe hotplugging will
- 621* load the driver module). This call isnot appropriate for use by mainboard
- 622* initialization logic, which usually runs during an arch_initcall() long
- 623* before any i2c_adapter could exist.
- 624*
- 625* This returns the new i2c client, which may be saved for later use with
- 626* i2c_unregister_device(); or NULL to indicate an error.
- 627*/
- 628struct i2c_client *
- 629i2c_new_device(struct i2c_adapter *adap,struct i2c_board_info const *info)
- 630{
- 631 struct i2c_client *client;
- 632 int status;
- 633
- 634 client = kzalloc(sizeof *client, GFP_KERNEL);
- 635 if (!client)
- 636 return NULL;
- 637
- 638 client->adapter = adap;
- 639
- 640 client->dev.platform_data = info->platform_data;
- 641
- 642 if (info->archdata)
- 643 client->dev.archdata = *info->archdata;
- 644
- 645 client->flags = info->flags;
- 646 client->addr = info->addr;
- 647 client->irq = info->irq;
- 648
- 649 strlcpy(client->name, info->type, sizeof(client->name));
- 650
- 651 /* Check for address validity */
- 652 status = i2c_check_client_addr_validity(client);
- 653 if (status) {
- 654 dev_err(&adap->dev,"Invalid %d-bit I2C address 0x%02hx\n",
- 655 client->flags & I2C_CLIENT_TEN ?10 : 7, client->addr);
- 656 goto out_err_silent;
- 657 }
- 658
- 659 /* Check for address business */
- 660 status = i2c_check_addr_busy(adap, client->addr);
- 661 if (status)
- 662 goto out_err;
- 663
- 664 client->dev.parent = &client->adapter->dev;
- 665 client->dev.bus = &i2c_bus_type;
- 666 client->dev.type = &i2c_client_type;
- 667 client->dev.of_node = info->of_node;
- 668 ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle);
- 669
- 670 /* For 10-bit clients, add an arbitrary offset to avoid collisions */
- 671 dev_set_name(&client->dev, "%d-%04x",i2c_adapter_id(adap),
- 672 client->addr | ((client->flags & I2C_CLIENT_TEN)
- 673 ? 0xa000 : 0));
- 674 status =device_register(&client->dev);
- 675 if (status)
- 676 goto out_err;
- 677
- 678 dev_dbg(&adap->dev, "client [%s] registered with bus id%s\n",
- 679 client->name, dev_name(&client->dev));
- 680
- 681 return client;
- 682
- 683out_err:
- 684 dev_err(&adap->dev, "Failed to register i2c client %s at0x%02x "
- 685 "(%d)\n", client->name, client->addr, status);
- 686out_err_silent:
- 687 kfree(client);
- 688 return NULL;
- 689}
这个函数根据参数传递进来的信息,创建并注册i2c_client。
634行,为i2c_client变量分配内存空间。
638行,将i2c_client.adapter设置为参数传递进来的i2c_adapter。
640 行,将i2c_client.dev.platform_data设置为 info->platform_data;
645行,将i2c_client.flags设置为info->flags;
646行,将i2c_client.addr设置为info->addr;
647行,将i2c_client.irq设置为info->irq;
649行,将i2c_client.name设置为info->type;
651-657行,检查指定的I2C设备地址是否有效。
660-662行,检查指定的I2C设备地址是否忙。
664-674行,初始化i2c_client.dev,并调用device_register注册i2c_client.dev。
i2c_register_adapter函数我们还有一点内容没有分析完,回到i2c_register_adapter函数,上面我们分析到了1062行的i2c_scan_static_board_info(adap),只有在adap->nr小于__i2c_first_dynamic_bus_num即静态指定了i2c_adapter的I2C总线号的情况下,才会调用这个函数。对于动态分配I2C总线号的情况,直接跳过。这就说明,只有在静态指定i2c_adapter的I2C总线号的情况下,才会扫描静态注册的I2C设备,如果动态指定i2c_adapter的I2C总线号,不会扫描静态注册的I2C设备。对于I2C驱动程序,这种静态注册的方式,称为new-style driver;而动态探测的方式,称为legacy driver。
下面我们继续分析i2c_register_adapter函数,前面调用i2c_scan_static_board_info实例化了静态注册的I2C设备,下面要完成对I2C设备的动态探测和实例化:
不论是静态指定还是动态分配I2C总线号,都会调用到1066行的bus_for_each_drv函数。
1066行,调用bus_for_each_drv函数,该函数定义在drivers/base/bus.c文件中,其内容如下:
- 417/**
- 418 * bus_for_each_drv - driver iterator
- 419 * @bus: bus we're dealing with.
- 420 * @start: driver to start iterating on.
- 421 * @data: data to pass to the callback.
- 422 * @fn: function to call for each driver.
- 423 *
- 424 * This is nearly identical to the device iterator above.
- 425 * We iterate over each driver that belongs to @bus, and call
- 426 * @fn for each. If @fn returns anything but 0, we break out
- 427 * and return it. If @start is not NULL, we use it as the head
- 428 * of the list.
- 429 *
- 430 * NOTE: we don't return the driver that returns a non-zero
- 431 * value, nor do we leave the reference count incremented for that
- 432 * driver. If the caller needs to know that info, it must set it
- 433 * in the callback. It must also be sure to increment the refcount
- 434 * so it doesn't disappear before returning to the caller.
- 435 */
- 436int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
- 437 void *data, int (*fn)(struct device_driver *, void *))
- 438{
- 439 struct klist_iter i;
- 440 struct device_driver *drv;
- 441 int error = 0;
- 442
- 443 if (!bus)
- 444 return -EINVAL;
- 445
- 446 klist_iter_init_node(&bus->p->klist_drivers, &i,
- 447 start ? &start->p->knode_bus : NULL);
- 448 while ((drv = next_driver(&i)) && !error)
- 449 error = fn(drv, data);
- 450 klist_iter_exit(&i);
- 451 return error;
- 452}
这个函数我们在《Linux设备模型分析之device(基于3.10.1内核)》一文中已经分析过了。448-449行,这个while循环依次遍历bus->p->klist_drivers中的所有device_driver,对于每个device_driver,调用fn(drv,data)函数。这里,传递过来的fn参数是__process_new_adapter,data参数是adap。这个循环是一个关键点,注册一个新的i2c_adapter后,要为该i2c_adapter上的i2c设备匹配驱动程序,这个匹配过程就是通过这个循环调用__process_new_adapter函数完成的。
__process_new_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 975static int __process_new_adapter(struct device_driver *d, void *data)
- 976{
- 977 return i2c_do_add_adapter(to_i2c_driver(d), data);
- 978}
注意i2c_do_add_adapter函数的第一个参数,从device_driver转换为i2c_driver。
i2c_do_add_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 957static int i2c_do_add_adapter(struct i2c_driver *driver,
- 958 struct i2c_adapter *adap)
- 959{
- 960 /* Detect supported devices on that bus, and instantiate them */
- 961 i2c_detect(adap, driver);
- 962
- 963 /* Let legacy drivers scan this bus for matching devices */
- 964 if (driver->attach_adapter) {
- 965 dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
- 966 driver->driver.name);
- 967 dev_warn(&adap->dev, "Please use another way to instantiate "
- 968 "your i2c_client\n");
- 969 /* We ignore the return code; if it fails, too bad */
- 970 driver->attach_adapter(adap);
- 971 }
- 972 return 0;
- 973}
961行,调用i2c_detect函数,探测并初始化该i2c总线上的i2c设备。该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 1730static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
- 1731{
- 1732 const unsigned short *address_list;
- 1733 struct i2c_client *temp_client;
- 1734 int i, err = 0;
- 1735 int adap_id = i2c_adapter_id(adapter);
- 1736
- 1737 address_list = driver->address_list;
- 1738 if (!driver->detect || !address_list)
- 1739 return 0;
- 1740
- 1741 /* Stop here if the classes do not match */
- 1742 if (!(adapter->class & driver->class))
- 1743 return 0;
- 1744
- 1745 /* Set up a temporary client to help detect callback */
- 1746 temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- 1747 if (!temp_client)
- 1748 return -ENOMEM;
- 1749 temp_client->adapter = adapter;
- 1750
- 1751 for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
- 1752 dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
- 1753 "addr 0x%02x\n", adap_id, address_list[i]);
- 1754 temp_client->addr = address_list[i];
- 1755 err = i2c_detect_address(temp_client, driver);
- 1756 if (unlikely(err))
- 1757 break;
- 1758 }
- 1759
- 1760 kfree(temp_client);
- 1761 return err;
- 1762}
1755行,调用i2c_detect_address,探测指定的地址上的I2C设备是否存在,如果存在,注册该i2c设备。i2c_detect_address函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 1675static int i2c_detect_address(struct i2c_client *temp_client,
- 1676 struct i2c_driver *driver)
- 1677{
- 1678 struct i2c_board_info info;
- 1679 struct i2c_adapter *adapter = temp_client->adapter;
- 1680 int addr = temp_client->addr;
- 1681 int err;
- 1682
- 1683 /* Make sure the address is valid */
- 1684 err = i2c_check_addr_validity(addr);
- 1685 if (err) {
- 1686 dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
- 1687 addr);
- 1688 return err;
- 1689 }
- 1690
- 1691 /* Skip if already in use */
- 1692 if (i2c_check_addr_busy(adapter, addr))
- 1693 return 0;
- 1694
- 1695 /* Make sure there is something at this address */
- 1696 if (!i2c_default_probe(adapter, addr))
- 1697 return 0;
- 1698
- 1699 /* Finally call the custom detection function */
- 1700 memset(&info, 0, sizeof(struct i2c_board_info));
- 1701 info.addr = addr;
- 1702 err = driver->detect(temp_client, &info);
- 1703 if (err) {
- 1704 /* -ENODEV is returned if the detection fails. We catch it
- 1705 here as this isn't an error. */
- 1706 return err == -ENODEV ? 0 : err;
- 1707 }
- 1708
- 1709 /* Consistency check */
- 1710 if (info.type[0] == '\0') {
- 1711 dev_err(&adapter->dev, "%s detection function provided "
- 1712 "no name for 0x%x\n", driver->driver.name,
- 1713 addr);
- 1714 } else {
- 1715 struct i2c_client *client;
- 1716
- 1717 /* Detection succeeded, instantiate the device */
- 1718 dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
- 1719 info.type, info.addr);
- 1720 client = i2c_new_device(adapter, &info);
- 1721 if (client)
- 1722 list_add_tail(&client->detected, &driver->clients);
- 1723 else
- 1724 dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
- 1725 info.type, info.addr);
- 1726 }
- 1727 return 0;
- 1728}
1702行,调用driver->detect。
1720行,如果探测到i2c设备确实存在,调用i2c_new_device函数初始化对应的i2c_client结构体并注册。i2c_new_device函数我们在前面已经分析过。
至此,i2c_adapter的注册过程我们就清楚了。同时,我们对I2C设备的注册定义和注册也就完全清楚了。
二、定义和注册I2C设备驱动
步骤1:定义i2c_driver结构体变量。
Linux I2C设备驱动程序对应的结构体是structi2c_driver,定义在include/linux/i2c.h文件中:
- 124/**
- 125 * struct i2c_driver - represent an I2Cdevice driver
- 126 * @class: What kind of i2c device weinstantiate (for detect)
- 127 * @attach_adapter: Callback for busaddition (deprecated)
- 128 * @probe: Callback for device binding
- 129 * @remove: Callback for deviceunbinding
- 130 * @shutdown: Callback for deviceshutdown
- 131 * @suspend: Callback for device suspend
- 132 * @resume: Callback for device resume
- 133 * @alert: Alert callback, for examplefor the SMBus alert protocol
- 134 * @command: Callback for bus-wide signaling(optional)
- 135 * @driver: Device driver model driver
- 136 * @id_table: List of I2C devicessupported by this driver
- 137 * @detect: Callback for devicedetection
- 138 * @address_list: The I2C addresses toprobe (for detect)
- 139 * @clients: List of detected clients wecreated (for i2c-core use only)
- 140 *
- 141 * The driver.owner field should be setto the module owner of this driver.
- 142 * The driver.name field should be setto the name of this driver.
- 143 *
- 144 * For automatic device detection, both @detectand @address_list must
- 145 * be defined. @class should also beset, otherwise only devices forced
- 146 * with module parameters will becreated. The detect function must
- 147 * fill at least the name field of thei2c_board_info structure it is
- 148 * handed upon successful detection, andpossibly also the flags field.
- 149 *
- 150 * If @detect is missing, the driverwill still work fine for enumerated
- 151 * devices. Detected devices simplywon't be supported. This is expected
- 152 * for the many I2C/SMBus devices whichcan't be detected reliably, and
- 153 * the ones which can always beenumerated in practice.
- 154 *
- 155 * The i2c_client structure which ishanded to the @detect callback is
- 156 * not a real i2c_client. It isinitialized just enough so that you can
- 157 * call i2c_smbus_read_byte_data andfriends on it. Don't do anything
- 158 * else with it. In particular, callingdev_dbg and friends on it is
- 159 * not allowed.
- 160 */
- 161struct i2c_driver {
- 162 unsigned int class;
- 163
- 164 /* Notifies the driver that a new bus has appeared. You should avoid
- 165 * using this, it will be removed in a near future.
- 166 */
- 167 int (*attach_adapter)(struct i2c_adapter *) __deprecated;
- 168
- 169 /* Standard driver model interfaces */
- 170 int (*probe)(struct i2c_client *, const struct i2c_device_id *);
- 171 int (*remove)(struct i2c_client *);
- 172
- 173 /* driver model interfaces that don't relate to enumeration */
- 174 void (*shutdown)(struct i2c_client *);
- 175 int (*suspend)(struct i2c_client *, pm_message_t mesg);
- 176 int (*resume)(struct i2c_client *);
- 177
- 178 /* Alert callback, for example for the SMBus alert protocol.
- 179 * The format and meaning of the data value depends on the protocol.
- 180 * For the SMBus alert protocol, there is a single bit of data passed
- 181 * as the alert response's low bit ("event flag").
- 182 */
- 183 void (*alert)(struct i2c_client *, unsigned int data);
- 184
- 185 /* a ioctl like command that can be used to perform specific functions
- 186 * with the device.
- 187 */
- 188 int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
- 189
- 190 struct device_driver driver;
- 191 const struct i2c_device_id *id_table;
- 192
- 193 /* Device detection callback for automatic device creation */
- 194 int (*detect)(struct i2c_client *, struct i2c_board_info *);
- 195 const unsigned short *address_list;
- 196 struct list_head clients;
- 197};
注意注释中的说明,driver.name和driver.owner必须初始化。
id_table成员变量是i2c_device_id结构体指针,它用来保存该i2c_driver支持的I2C设备列表。
struct i2c_device_id定义在include/linux/mod_devicetable.h文件中,其内容如下:
- 419struct i2c_device_id {
- 420 char name[I2C_NAME_SIZE];
- 421 kernel_ulong_t driver_data; /* Data private to the driver */
- 422};
对于Mini2440的I2C设备at24c08 EEPROM,其对应的i2c_driver结构体变量实现在drivers/misc/eeprom/at24.c文件中:
- 677static struct i2c_driver at24_driver = {
- 678 .driver = {
- 679 .name = "at24",
- 680 .owner = THIS_MODULE,
- 681 },
- 682 .probe = at24_probe,
- 683 .remove = at24_remove,
- 684 .id_table = at24_ids,
- 685};
678-681行,初始化了要求必须初始化的i2c_driver.driver.name和i2c_driver.driver.owner。
682行,指定i2c_driver.probe函数为at24_probe。
683行,指定i2c_driver.remove函数为at24_remove。
684行,指定i2c_driver.id_table为at24_ids。
at24_ids定义在drivers/misc/eeprom/at24.c文件中,其内容如下:
- 99#define AT24_SIZE_BYTELEN 5
- 100#define AT24_SIZE_FLAGS 8
- 101
- 102#define AT24_BITMASK(x) (BIT(x) - 1)
- 103
- 104/* create non-zero magic value for giveneeprom parameters */
- 105#define AT24_DEVICE_MAGIC(_len,_flags) \
- 106 ((1 << AT24_SIZE_FLAGS | (_flags)) \
- 107 << AT24_SIZE_BYTELEN | ilog2(_len))
- 108
- 109static const struct i2c_device_idat24_ids[] = {
- 110 /* needs 8 addresses as A0-A2 are ignored */
- 111 { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
- 112 /* old variants can't be handled with this generic entry! */
- 113 { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
- 114 { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
- 115 /* spd is a 24c02 in memory DIMMs */
- 116 { "spd", AT24_DEVICE_MAGIC(2048 / 8,
- 117 AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
- 118 { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
- 119 /* 24rf08 quirk is handled at i2c-core */
- 120 { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },
- 121 { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },
- 122 { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },
- 123 { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },
- 124 { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },
- 125 { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },
- 126 { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },
- 127 { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16)},
- 128 { "at24", 0 },
- 129 { /* END OF LIST */ }
- 130};
可以看到,at24_driver支持很多设备,其中包括Mini2440使用的24c08 EEPROM。
步骤2:调用i2c_add_driver注册i2c_driver结构体变量。
对于Mini2440的I2C设备at24c08 EEPROM,这一步工作是在drivers/misc/eeprom/at24.c文件中的at24_init函数中完成的:
- 687static int __init at24_init(void)
- 688{
- 689 if (!io_limit) {
- 690 pr_err("at24: io_limit must not be 0!\n");
- 691 return -EINVAL;
- 692 }
- 693
- 694 io_limit = rounddown_pow_of_two(io_limit);
- 695 return i2c_add_driver(&at24_driver);
- 696}
695行,调用i2c_add_driver注册上面定义的at24_driver。
i2c_add_driver是一个宏,定义在include/linux/i2c.h文件中:
- 497/* use a define to avoid include chaining to get THIS_MODULE */
- 498#define i2c_add_driver(driver) \
- 499 i2c_register_driver(THIS_MODULE, driver)
i2c_register_driver函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 1307/*
- 1308 * An i2c_driver is used with one or more i2c_client (device) nodes to access
- 1309 * i2c slave chips, on a bus instance associated with some i2c_adapter.
- 1310 */
- 1311
- 1312int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
- 1313{
- 1314 int res;
- 1315
- 1316 /* Can't register until after driver model init */
- 1317 if (unlikely(WARN_ON(!i2c_bus_type.p)))
- 1318 return -EAGAIN;
- 1319
- 1320 /* add the driver to the list of i2c drivers in the driver core */
- 1321 driver->driver.owner = owner;
- 1322 driver->driver.bus = &i2c_bus_type;
- 1323
- 1324 /* When registration returns, the driver core
- 1325 * will have called probe() for all matching-but-unbound devices.
- 1326 */
- 1327 res = driver_register(&driver->driver);
- 1328 if (res)
- 1329 return res;
- 1330
- 1331 /* Drivers should switch to dev_pm_ops instead. */
- 1332 if (driver->suspend)
- 1333 pr_warn("i2c-core: driver [%s] using legacy suspend method\n",
- 1334 driver->driver.name);
- 1335 if (driver->resume)
- 1336 pr_warn("i2c-core: driver [%s] using legacy resume method\n",
- 1337 driver->driver.name);
- 1338
- 1339 pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
- 1340
- 1341 INIT_LIST_HEAD(&driver->clients);
- 1342 /* Walk the adapters that are already present */
- 1343 i2c_for_each_dev(driver, __process_new_driver);
- 1344
- 1345 return 0;
- 1346}
1327行,调用driver_register注册i2c_driver.driver。参考《 Linux设备模型分析之device_driver(基于3.10.1内核)》对Linux设备模型的分析,在driver_register执行过程中,如果I2C总线上找到了与该驱动匹配的I2C设备,则i2c_driver.probe函数会被调用执行。
1343行,调用i2c_for_each_dev遍历所有已存在的i2c_adapter。该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 1288int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
- 1289{
- 1290 int res;
- 1291
- 1292 mutex_lock(&core_lock);
- 1293 res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
- 1294 mutex_unlock(&core_lock);
- 1295
- 1296 return res;
- 1297}
1293行,调用bus_for_each_dev,这个函数定义在drivers/base/bus.c文件中,其内容如下:
- 286intbus_for_each_dev(struct bus_type *bus, struct device *start,
- 287 void *data, int (*fn)(struct device *, void *))
- 288{
- 289 struct klist_iter i;
- 290 struct device *dev;
- 291 int error = 0;
- 292
- 293 if (!bus || !bus->p)
- 294 return -EINVAL;
- 295
- 296 klist_iter_init_node(&bus->p->klist_devices, &i,
- 297 (start ?&start->p->knode_bus : NULL));
- 298 while ((dev = next_device(&i)) && !error)
- 299 error = fn(dev, data);
- 300 klist_iter_exit(&i);
- 301 return error;
- 302}
我们在《 Linux设备模型分析之device_driver(基于3.10.1内核)》一文中已经分析过这个函数。这里,传递过来的data参数是要注册的i2c_driver,fn参数是__process_new_driver函数,所以我们来看__process_new_driver函数,该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 1300static int __process_new_driver(structdevice *dev, void *data)
- 1301{
- 1302 if (dev->type != &i2c_adapter_type)
- 1303 return 0;
- 1304 return i2c_do_add_adapter(data, to_i2c_adapter(dev));
- 1305}
i2c_do_add_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
- 957static int i2c_do_add_adapter(structi2c_driver *driver,
- 958 struct i2c_adapter *adap)
- 959{
- 960 /* Detect supported devices on that bus, and instantiate them */
- 961 i2c_detect(adap, driver);
- 962
- 963 /* Let legacy drivers scan this bus for matching devices */
- 964 if (driver->attach_adapter) {
- 965 dev_warn(&adap->dev, "%s: attach_adapter method isdeprecated\n",
- 966 driver->driver.name);
- 967 dev_warn(&adap->dev, "Please use another way to instantiate"
- 968 "your i2c_client\n");
- 969 /* We ignore the return code; if it fails, too bad */
- 970 driver->attach_adapter(adap);
- 971 }
- 972 return 0;
- 973}
这个函数我们在分析i2c_adapter的注册过程时已经分析过了,它主要完成i2c_driver与i2c_adapter上的i2c设备的匹配工作,如果匹配成功,初始化并注册对应的i2c_client。
至此,i2c_driver的注册过程我们就清楚了。
步骤3:实现i2c_driver中要示实现的函数
对于Mini2440的I2C设备at24c08 EEPROM,at24_driver要求实现的是i2c_driver.probe和i2c_driver.remove函数。
i2c drivers的更多相关文章
- i2c总线,设备,驱动之间的关系
------ 总线上先添加好所有具体驱动,i2c.c遍历i2c_boardinfo链表,依次建立i2c_client, 并对每一个i2c_client与所有这个线上的驱动匹配,匹配上,就调用这个驱动的 ...
- Linux设备驱动模型之I2C总线
一.I2C子系统总体架构 1.三大组成部分 (1)I2C核心(i2c-core):I2C核心提供了I2C总线驱动(适配器)和设备驱动的注册.注销方法,提供了与具体硬件无关的I2C读写函数. (2)I2 ...
- Linux+I2C总线分析(主要是probe的方式)
Linux I2C 总线浅析 ㈠ Overview Linux的I2C体系结构分为3个组成部分: ·I2C核心: I2C核心提供了I2C总线驱动和设备驱动的注册.注销方法,I2C通信方法(即“algo ...
- linux驱动之I2C
include/linux/i2c.h struct i2c_msg;struct i2c_algorithm;struct i2c_adapter;struct i2c_client;struct ...
- Linux I2C设备驱动编写(二)
在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c_client.三者的关系也在上一节进行了描述.应该已经算是对Linux I2C子系统有了初步 ...
- 【转】Linux I2C设备驱动编写(二)
原文网址:http://www.cnblogs.com/biglucky/p/4059582.html 在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_drive ...
- i2c sub system __i2c_board_list/klist_devices/klist_drivers
i2c_devinfo全局链表: __i2c_board_list 用来挂接 i2c_board_info,这个信息用来生成 i2c_client i2c_client 链表: i2c_bus_typ ...
- I2C(二) linux2.6
目录 I2C(二) linux2.6 总线驱动 关键结构 入口 i2c_add_adapter 硬件操作 设备驱动 入口 注册 attach_adapter eeprom_detect i2c_att ...
- I2C(三) linux3.4(内核分析)
目录 I2C(三) linux3.4(内核分析) (一)总线流程 bus.probe match i2c_device_probe (二)client注册 方式(一)静态加载 方式(二)指定设备 方式 ...
随机推荐
- 044 Wildcard Matching 通配符匹配
实现一个支持 '?' 和 '*' 的通配符匹配.'?' 匹配任何单个字符.'*' 匹配任何数量的字符 (包括0个).匹配应覆盖 整个 输入字符串(而不是部分).这个函数原型为:bool isMatch ...
- 第十七章 提升用户体验 之 使用MVC扩展功能控制程序行为
1. 概述 ASP.NET MVC具有很好的扩展性,每一个核心功能都可以被扩展.重写 和 定制. 本章内容包括:实现MVC过滤器和controller工厂.使用 action results,view ...
- 开源项目android-uitableview介绍
在iOS应用中,UITableView应该是使用率最高的视图之一了.iPod.时钟.日历.备忘录.Mail.天气.照片.电话.短信. Safari.App Store.iTunes.Game Cent ...
- JavaScirpt 的垃圾(garbage collection)回收机制
一.垃圾回收机制—GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存. 原理:垃圾收集器会定期(周期性 ...
- JS移动端浏览器取消右划后退的几种方法
在开发过程中,发现我们公司所使用的APP有点BUG,在APP中打开网页.H5应用之后,处于首页时,轻微的右划触发了后退事件,导致直接退出网页或者H5应用的页面,这样使得很多需要交互的手势没办法使用.本 ...
- ios 利用runtime任性跳转
在开发项目中,会有这样变态的需求: 推送:根据服务端推送过来的数据规则,跳转到对应的控制器 feeds列表:不同类似的cell,可能跳转不同的控制器(嘘!产品经理是这样要求:我也不确定会跳转哪个界面哦 ...
- android配置android studio not found target android-*.的问题
列:not found target android-25, 打开下载android SDK的工具栏,找到android-25版本下载到你本地的sdk路径下就OK了.
- js操作文档对象的节点
好吧,为了能让大家不至于睡着,我们先回顾先前面的东东吧~ 1.首先我们写了javaScriput的是一门弱类型的解释性的脚本语言:弱类型:我们的变量不用申明其具体的数据类型,在使用的时候浏览器根据其存 ...
- UVA 1442 Cave 洞穴 (贪心+扫描)
题意:有一个洞穴,每个位置有一个底的高度p[i],和对应顶的高度s[i],要往里面尽量放燃料,要求燃料不能碰到顶,可以无限接近. 题解:制约燃料储放的就是顶的高度了,分别求出设当前储放位置的向两边的延 ...
- vue 文件流下载xlsx 功能实现
downLoadFile (url, name) { this.xhr = new XMLHttpRequest() this.xhr.open('GET', url, true) this.xhr. ...