博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux设备驱动剖析之IIC(二)
阅读量:7303 次
发布时间:2019-06-30

本文共 12299 字,大约阅读时间需要 40 分钟。

953行,适配器的编号大于MAX_ID_MASK是不行的,MAX_ID_MASK是一个宏,展开后的值为61。

957至968行,关于管理小整形ID数的,没怎么了解,略过。

974行,调用i2c_register_adapter函数注册IIC适配器,下面是它的定义:

00000837 static int i2c_register_adapter(struct i2c_adapter *adap)00000838 {00000839     int res = 0;00000840 00000841     /* Can't register until after driver model init */00000842     if (unlikely(WARN_ON(!i2c_bus_type.p))) {00000843         res = -EAGAIN;00000844         goto out_list;00000845     }00000846 00000847     rt_mutex_init(&adap->bus_lock);00000848     mutex_init(&adap->userspace_clients_lock);00000849     INIT_LIST_HEAD(&adap->userspace_clients);00000850 00000851     /* Set default timeout to 1 second if not already set */00000852     if (adap->timeout == 0)00000853         adap->timeout = HZ;00000854 00000855     dev_set_name(&adap->dev, "i2c-%d", adap->nr);00000856     adap->dev.bus = &i2c_bus_type;00000857     adap->dev.type = &i2c_adapter_type;00000858     res = device_register(&adap->dev);00000859     if (res)00000860         goto out_list;00000861 00000862     dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);00000863 00000864 #ifdef CONFIG_I2C_COMPAT00000865     res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,00000866                        adap->dev.parent);00000867     if (res)00000868         dev_warn(&adap->dev,00000869              "Failed to create compatibility class link\n");00000870 #endif00000871 00000872     /* create pre-declared device nodes */00000873     if (adap->nr < __i2c_first_dynamic_bus_num)00000874         i2c_scan_static_board_info(adap);00000875 00000876     /* Notify drivers */00000877     mutex_lock(&core_lock);00000878     bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);00000879     mutex_unlock(&core_lock);00000880 00000881     return 0;00000882 00000883 out_list:00000884     mutex_lock(&core_lock);00000885     idr_remove(&i2c_adapter_idr, adap->nr);00000886     mutex_unlock(&core_lock);00000887     return res;00000888 }

842至845行,i2c_bus_type的私有成员p在IIC子系统初始化时在bus_register函数里已经被初始化了,因此if条件不会成立,可以继续往下走。

848、849行,之前说struct i2c_adapter时被略过的最后两个成员在这里被初始化。

852、853行,如果timeout没有设置,那么就给它个默认值HZ。一路走来可以发现,timeout在这里会被设置成HZ。

858行,注册适配器这个设备。

864至870行,兼容性方面的,略过。

874行,调用i2c_scan_static_board_info函数注册所有在板文件里定义的设备,下面看它的定义:

00000802 static void i2c_scan_static_board_info(struct i2c_adapter *adapter)00000803 {00000804     struct i2c_devinfo    *devinfo;00000805 00000806     down_read(&__i2c_board_lock);00000807     list_for_each_entry(devinfo, &__i2c_board_list, list) {00000808         if (devinfo->busnum == adapter->nr00000809                 && !i2c_new_device(adapter,00000810                         &devinfo->board_info))00000811             dev_err(&adapter->dev,00000812                 "Can't create device at 0x%02x\n",00000813                 devinfo->board_info.addr);00000814     }00000815     up_read(&__i2c_board_lock);00000816 }

807行,遍历__i2c_board_list链表,每找到一个成员就调用i2c_new_device函数创建一个IIC从机设备,下面是i2c_new_device函数的定义:

00000523 struct i2c_client *00000524 i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)00000525 {00000526     struct i2c_client    *client;00000527     int            status;00000528 00000529     client = kzalloc(sizeof *client, GFP_KERNEL);00000530     if (!client)00000531         return NULL;00000532 00000533     client->adapter = adap;00000534 00000535     client->dev.platform_data = info->platform_data;00000536 00000537     if (info->archdata)00000538         client->dev.archdata = *info->archdata;00000539 00000540     client->flags = info->flags;00000541     client->addr = info->addr;00000542     client->irq = info->irq;00000543 00000544     strlcpy(client->name, info->type, sizeof(client->name));00000545 00000546     /* Check for address validity */00000547     status = i2c_check_client_addr_validity(client);00000548     if (status) {00000549         dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",00000550             client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);00000551         goto out_err_silent;00000552     }00000553 00000554     /* Check for address business */00000555     status = i2c_check_addr_busy(adap, client->addr);00000556     if (status)00000557         goto out_err;00000558 00000559     client->dev.parent = &client->adapter->dev;00000560     client->dev.bus = &i2c_bus_type;00000561     client->dev.type = &i2c_client_type;00000562 #ifdef CONFIG_OF00000563     client->dev.of_node = info->of_node;00000564 #endif00000565 00000566     dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),00000567              client->addr);00000568     status = device_register(&client->dev);00000569     if (status)00000570         goto out_err;00000571 00000572     dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",00000573         client->name, dev_name(&client->dev));00000574 00000575     return client;00000576 00000577 out_err:00000578     dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "00000579         "(%d)\n", client->name, client->addr, status);00000580 out_err_silent:00000581     kfree(client);00000582     return NULL;00000583 }

529行,为IIC从机设备结构体申请内存。

533至542行,一些赋值。

544行,为client的name成员赋值,IIC总线的match函数能否匹配成功就要看这里了。从这里也可以知道如何让板文件里定义的设备与驱动匹配起来。

547行,检查IIC从机设备地址的合法性,怎样才合法?如果从机使用十位地址的话,那么地址的最大值不能大于0x3ff;如果使用的是七位地址,那么地址的最大值不能大于0x7f,也不能为0。

555行,检查当前IIC从机设备的地址有没有被使用,一条IIC总线或者一个IIC适配器上可以挂多个从机设备,靠设备的地址来识别不同的设备,因此一条总线上不能有两个同样地址的设备。

561行,设备的类型,IIC从机设备在IIC子系统里属于client类型。

568行,将IIC从机设备注册进系统。

      回到i2c_register_adapter函数,878行,遍历IIC总线上的所有已经注册了的驱动,每找到一个就调用__process_new_adapter函数进行处理,__process_new_adapter函数的定义如下:

00000832 static int __process_new_adapter(struct device_driver *d, void *data)00000833 {00000834     return i2c_do_add_adapter(to_i2c_driver(d), data);00000835 }

里面就是调用i2c_do_add_adapter函数:

00000818 static int i2c_do_add_adapter(struct i2c_driver *driver,00000819                   struct i2c_adapter *adap)00000820 {00000821     /* Detect supported devices on that bus, and instantiate them */00000822     i2c_detect(adap, driver);00000823 00000824     /* Let legacy drivers scan this bus for matching devices */00000825     if (driver->attach_adapter) {00000826         /* We ignore the return code; if it fails, too bad */00000827         driver->attach_adapter(adap);00000828     }00000829     return 0;00000830 }

822行,检查驱动是否能够与该适配器所在总线上的设备匹配。

825行,如果驱动的attach_adapter函数有定义就调用之,这主要针对旧的驱动,像i2c-dev.c就是使用这种方式来驱动IIC适配器的,这个函数指针在将来可能会被移除。

      到这里,说完了s3c6410的IIC控制器驱动的初始化过程。下面开始说drivers/i2c/i2c-dev.c这个通用的i2c驱动,首先看它的初始化函数i2c_dev_init:

00000595 static int __init i2c_dev_init(void)00000596 {00000597     int res;00000598 00000599     printk(KERN_INFO "i2c /dev entries driver\n");00000600 00000601     res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);00000602     if (res)00000603         goto out;00000604 00000605     i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");00000606     if (IS_ERR(i2c_dev_class)) {00000607         res = PTR_ERR(i2c_dev_class);00000608         goto out_unreg_chrdev;00000609     }00000610 00000611     res = i2c_add_driver(&i2cdev_driver);00000612     if (res)00000613         goto out_unreg_class;00000614 00000615     return 0;00000616 00000617 out_unreg_class:00000618     class_destroy(i2c_dev_class);00000619 out_unreg_chrdev:00000620     unregister_chrdev(I2C_MAJOR, "i2c");00000621 out:00000622     printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);00000623     return res;00000624 }

601行,注册IIC设备,主设备号为I2C_MAJOR,它的值为89,文件操作结构体对象是i2cdev_fops,定义为:

00000514 static const struct file_operations i2cdev_fops = {00000515     .owner        = THIS_MODULE,00000516     .llseek        = no_llseek,00000517     .read        = i2cdev_read,00000518     .write        = i2cdev_write,00000519     .unlocked_ioctl    = i2cdev_ioctl,00000520     .open        = i2cdev_open,00000521     .release    = i2cdev_release,00000522 };

后面会以i2cdev_ioctl为例说说它的工作过程。

605至609行,创建IIC设备类,是后面自动创建设备节点的基础。

611行,添加IIC驱动,起始里面是对i2c_register_driver函数的包装,在include/linux/i2c.h里定义:

00000434 static inline int i2c_add_driver(struct i2c_driver *driver)00000435 {00000436     return i2c_register_driver(THIS_MODULE, driver);00000437 }

这样就可以省去写THIS_MODULE,也可以避免忘记写THIS_MODULE。下面看i2c_register_driver函数的定义,在drivers/i2c/i2c-core.c中:

00001108 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)00001109 {00001110     int res;00001111 00001112     /* Can't register until after driver model init */00001113     if (unlikely(WARN_ON(!i2c_bus_type.p)))00001114         return -EAGAIN;00001115 00001116     /* add the driver to the list of i2c drivers in the driver core */00001117     driver->driver.owner = owner;00001118     driver->driver.bus = &i2c_bus_type;00001119 00001120     /* When registration returns, the driver core00001121      * will have called probe() for all matching-but-unbound devices.00001122      */00001123     res = driver_register(&driver->driver);00001124     if (res)00001125         return res;00001126 00001127     pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);00001128 00001129     INIT_LIST_HEAD(&driver->clients);00001130     /* Walk the adapters that are already present */00001131     mutex_lock(&core_lock);00001132     bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);00001133     mutex_unlock(&core_lock);00001134 00001135     return 0;00001136 }

1113行,检查IIC总线的私有数据p是否已经初始化,前面已经说过了,在IIC子系统初始化的时候p就已经被初始化了。

1117、1118行,没什么好说的吧。

1123行,将该驱动注册进系统,经过一层层调用后会调用IIC总线的match函数。

1132行,遍历IIC总线上的所有设备,每找到一个就调用__process_new_driver函数进行处理,__process_new_driver函数的定义:

00001096 static int __process_new_driver(struct device *dev, void *data)00001097 {00001098     if (dev->type != &i2c_adapter_type)00001099         return 0;00001100     return i2c_do_add_adapter(data, to_i2c_adapter(dev));00001101 }

1098行,如果设备不是适配器类型,就表示不是要找的设备,直接返回0。否则调用1100行的i2c_do_add_adapter函数,这个函数前面已经说过了,这里就不重复了。

我们知道,此驱动注册进系统后会导致i2cdev_attach_adapter函数被调用,下面看它的定义:

00000534 static int i2cdev_attach_adapter(struct i2c_adapter *adap)00000535 {00000536     struct i2c_dev *i2c_dev;00000537     int res;00000538 00000539     i2c_dev = get_free_i2c_dev(adap);00000540     if (IS_ERR(i2c_dev))00000541         return PTR_ERR(i2c_dev);00000542 00000543     /* register this i2c device with the driver core */00000544     i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,00000545                      MKDEV(I2C_MAJOR, adap->nr), NULL,00000546                      "i2c-%d", adap->nr);00000547     if (IS_ERR(i2c_dev->dev)) {00000548         res = PTR_ERR(i2c_dev->dev);00000549         goto error;00000550     }00000551     res = device_create_file(i2c_dev->dev, &dev_attr_name);00000552     if (res)00000553         goto error_destroy;00000554 00000555     pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",00000556          adap->name, adap->nr);00000557     return 0;00000558 error_destroy:00000559     device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));00000560 error:00000561     return_i2c_dev(i2c_dev);00000562     return res;00000563 }

539行,不要被它的名字所迷惑,看它的定义:

00000076 static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)00000077 {00000078     struct i2c_dev *i2c_dev;00000079 00000080     if (adap->nr >= I2C_MINORS) {00000081         printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",00000082                adap->nr);00000083         return ERR_PTR(-ENODEV);00000084     }00000085 00000086     i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);00000087     if (!i2c_dev)00000088         return ERR_PTR(-ENOMEM);00000089     i2c_dev->adap = adap;00000090 00000091     spin_lock(&i2c_dev_list_lock);00000092     list_add_tail(&i2c_dev->list, &i2c_dev_list);00000093     spin_unlock(&i2c_dev_list_lock);00000094     return i2c_dev;00000095 }

80至84行,如果适配器的编号大于最大的次设备号,那么就返回出错。I2C_MINORS的值为256。

86行,为i2c_dev对象申请内存。

92行,将i2c_dev对象加入到i2c_dev_list链表中。

      回到i2cdev_attach_adapter函数,544行,创建设备节点,主设备号为I2C_MAJOR,次设备号为适配器的编号,设备节点的名字为i2c-x,x的值就是适配器的编号。如果适配器的编号为0,那么就会在/dev下创建一个名为i2c-0的文件,即/dev/i2c-0,但在某些嵌入式Linux平台上没有看到这个文件,而是/dev/i2c/0这种形式,原因在于在启动文件里调用了mdev –s这条命令,导致/dev/i2c-0变成了/dev/i2c/0,不信?把i2c-x的-去掉,变成i2cx,重新编译后启动内核,看生成的是否是/dev/i2cx文件。之所以会造成那样是因为字符‘-’引起的。

551行,创建设备文件,关于设备模型的,不多说了。

     到此,i2c-dev.c的初始化过程也说完了。

     某某大侠说得对:“内核代码就像酒,有的苦有的烈,这样的滋味你我早晚要体会,请与我举起杯,与内核干杯。”多么形象的比喻!多么可爱的文字!

     不管多“苦”多“累”,既然认定了前方,路还是要走下去的。

 

转载地址:http://hkhnm.baihongyu.com/

你可能感兴趣的文章
HDU3790:最短路径问题(最短路+双权值)
查看>>
微积分学习笔记五:多元函数微积分
查看>>
C#关闭多线程程序
查看>>
测试jupyter notebook导出md格式的兼容性
查看>>
ABP官方文档翻译 7.1 后台Jobs和Workers
查看>>
keil c51 和keil mak(arm)如何安装在一起的问题
查看>>
springIOC、AOP的一些注解
查看>>
用为知笔记发博客
查看>>
Windows 8下完美使用Virtual PC 2007(virtual pc 2007 64 win8 兼容性)
查看>>
JavaScript中函数参数的值传递和引用传递
查看>>
面向对象高级编程(上)-- 第二周学习笔记(Boolan)
查看>>
主城地图1.0(4.7)
查看>>
其他数据类型转换成String
查看>>
SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表)
查看>>
AI历史和哲学基础浅谈
查看>>
java项目显示红叉,程序却没有错误
查看>>
angularJS遇到的坑
查看>>
异常处理汇总-数据库系列
查看>>
Linux安装 jdk&maven
查看>>
msxfs.dll函数加载代码
查看>>