Linux 驱动i2c -- Gsenser(二)

对linux驱动模型有一点了解的兄弟知道,一个驱动,特别是挂上总线的驱动,
真正开始执行都是始于probe函数。我们这里的lis3lv02d_i2c驱动,是挂在系统的i2c总线上的,
因而也就会从probe开始执行。那么是谁来调用这个probe内?就好像驱动通过总线介绍,嫁给了设备,
那到底是哪个设备去掀起驱动的红盖头呢?我们从i2c_register_driver看开去。
代码在kernel/driver/i2c/i2c-core.c中:
872 /*
873  * An i2c_driver is used with one or more i2c_client (device) nodes to access
874  * i2c slave chips, on a bus instance associated with some i2c_adapter.
875  */
876
877 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
878 {
879   int res;
880
881   /* Can't register until after driver model init */
882   if (unlikely(WARN_ON(!i2c_bus_type.p)))
883     return -EAGAIN;
884
885   /* add the driver to the list of i2c drivers in the driver core */
886   driver->driver.owner = owner;
887   driver->driver.bus = &i2c_bus_type;
888
889   /* When registration returns, the driver core
890    * will have called probe() for all matching-but-unbound devices.
891    */
892   res = driver_register(&driver->driver);
893   if (res)
894     return res;
895
896   pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
897
898   INIT_LIST_HEAD(&driver->clients);
899   /* Walk the adapters that are already present */
900   mutex_lock(&core_lock);
901   bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
902   mutex_unlock(&core_lock);
903 ///WTT DEBUG
904 printk("***** WTT DEBUG i2c_register_driver to return 0\n");
905 ///WTT DEBUG
906   return 0;
907 }
908 EXPORT_SYMBOL(i2c_register_driver);
此函数中第887行,driver->driver.bus = &i2c_bus_type;
将i2c_driver->device_driver.bus 赋值为&i2c_bus_type
那么这个&i2c_bus_type是在哪里定义的呢?
代码在kernel/driver/i2c/i2c-core.c中:
233 struct bus_type i2c_bus_type = {
234   .name   = "i2c",
235   .match    = i2c_device_match,
236   .probe    = i2c_device_probe,
237   .remove   = i2c_device_remove,
238   .shutdown = i2c_device_shutdown,
239   .suspend  = i2c_device_suspend,
240   .resume   = i2c_device_resume,
241 };
242 EXPORT_SYMBOL_GPL(i2c_bus_type);
struct bus_type 是linux中定义的总线类型,所有的总线都需要定义这么一个结构体,
用来储存总线的名称以及一些相关的API。
从字面上看,可以看到相关的API有:
    设备匹配,主要是将驱动和设备进行匹配。
    设备移除、关闭、挂起、恢复。
    还有设备挂载(探测),是设备驱动probe的调用者,
也就是这节寻寻觅觅的掀起盖头的那位了。
那么这些函数都是怎么执行的呢?这个就跟伟大的Linux设备模型息息相关了。
具体的代码实现细节我没有跟读过,知识了解一些操作的结果和过程。
大致是这样的, 892   res = driver_register(&driver->driver);,我们把这个驱动,
注册到了i2c_bus_type总线上。当该总线上有新的设备添加i2c_add_device,
又或者有新的驱动注册i2c_add_driver,那么i2c_device_match就会被执行,我们来看这个函数:
也在i2c-core中
  66 static int i2c_device_match(struct device *dev, struct device_driver *drv)
  67 {
  68   struct i2c_client *client = i2c_verify_client(dev);
  69   struct i2c_driver *driver;
  70
  71   if (!client)
  72     return 0;
  73
  74   driver = to_i2c_driver(drv);
  75 ///WTT DEBUG
  76   printk("***** WTT DEBUG i2c_device_match : driver name=%s\n",driver->id_table->name);
  77 ///WTT DEBUG
  78   /* match on an id table if there is one */
  79   if (driver->id_table)
  80     return i2c_match_id(driver->id_table, client) != NULL;
  81
  82   return 0;
  83 }
我们看到,这个函数所要match的是驱动和设备的id—table。
我们跟着第80行,进入i2c_match_id:
  55 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
  56             const struct i2c_client *client)
  57 {
  58   while (id->name[0]) {
  59     if (strcmp(client->name, id->name) == 0)
  60       return id;
  61     id++;
  62   }
  63   return NULL;
  64 }
  这个函数应该没什么问题,大致意思就是比较从driver来的id中的name和client中的name。

  client哪里来?这里先留个悬念,下节再细说,我们先往下看。

刚刚我们说完了i2c_device_match,接着来说说掀起盖头来的那位i2c_device_probe,
他是在什么时候被调用的呢?是在i2c_device_match调用完成后被调用的。
i2c-bus在检测到有新的设备和驱动后,会主动去调用i2c_device_match,将两者做匹配,
一旦匹配成功,就会去调用i2c_device_probe。
就好比男孩(device)和女孩(driver),去bus相亲,相中了(match),就步入婚姻殿堂,
而一般,掀盖头都是要用装备的,不是徒手去掀,用什么?用秤杆,所谓称心如意!
而这里的i2c_device_probe就好比是秤杆,去解开驱动的probe面纱。
把上述的match和probe加上调试语句,就可以看出相对关系:
[    3.416687] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d    client:tpo_touch
[    3.424652] ***** WTT DEBUG i2c_device_match : driver name=lis3lv02d
[ 3.431030] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d client:elan_touch
[    3.439056] ***** WTT DEBUG i2c_device_match : driver name=lis3lv02d
[    3.445434] ***** WTT DEBUG i2c_device_match : dismatch drv:lis3lv02d    client:lis3lv02d
[    3.453369] ***** WTT DEBUG i2c_device_probe : driver name=lis3lv02d
[    3.445434]王八绿豆对上眼了,那就去掀盖头吧,[    3.453369] ***** WTT DEBUG i2c_device_probe : driver name=lis3lv02d。
他们都是总线上的API,都是由总线去调用的,

When i2c_bus_type was registered in linux kernel,in kernel/driver/base/bus.c
__device_attach and __driver_attach

///these functions will be called when one driver want to bind with device .
And function driver_match_device will call bus_type.match
And driver_probe_device will call bus_type.probe


话说秤杆有了,去挑起盖头咯,挑起前,还有些事情需要做,
比如,夫妻双方做个婚前体检,再次核实身份,诸如此类。
见i2c_device_probe代码,也在i2c-core中:
102 static int i2c_device_probe_count = 0;
103 static int i2c_device_probe(struct device *dev)
104 {
105   struct i2c_client *client = i2c_verify_client(dev);
106   struct i2c_driver *driver;
107   int status;
108
109   if (!client)
110     return 0;
111
112   driver = to_i2c_driver(dev->driver);
113 ///WTT DEBUG
114   printk("***** WTT DEBUG i2c_device_probe : driver name=%s\n",driver->id_table->name);
115 ///WTT DEBUG
116   if (!driver->probe || !driver->id_table)
117     return -ENODEV;
118   client->driver = driver;
119   if (!device_can_wakeup(&client->dev))
120     device_init_wakeup(&client->dev,
121           client->flags & I2C_CLIENT_WAKE);
122   dev_dbg(dev, "probe\n");
123 ///WTT DEBUG
124   printk("***** WTT DEBUG i2c_device_probe_count = %d\n",i2c_device_probe_count);
125   i2c_device_probe_count++;
126   printk("***** WTT DEBUG device to probe is %s\n",client->name);
127 ///WTT DEBUG
128   status = driver->probe(client, i2c_match_id(driver->id_table, client));
129
130   if (status)
131     client->driver = NULL;
132   return status;
133 }
先看i2c_verify_client,
251 /**
252  * i2c_verify_client - return parameter as i2c_client, or NULL
253  * @dev: device, probably from some driver model iterator
254  *
255  * When traversing the driver model tree, perhaps using driver model
256  * iterators like @device_for_each_child(), you can't assume very much
257  * about the nodes you find.  Use this function to avoid oopses caused
258  * by wrongly treating some non-I2C device as an i2c_client.
259  */
260 struct i2c_client *i2c_verify_client(struct device *dev)
261 {
262   return (dev->type == &i2c_client_type)
263       ? to_i2c_client(dev)
264       : NULL;
265 }
266 EXPORT_SYMBOL(i2c_verify_client);
就是想检查一下,client是不是真的i2c_client_type类型。
就好比男孩(device)想找个女孩(driver),但是相亲时没注意,找了个人妖,
所以就要婚前检查一下,i2c_verify_client就是起这个作用的,核实一下是不是真的i2c_client_type。
中间部分都是一些简单的初始化。
再看128行,status = driver->probe(client, i2c_match_id(driver->id_table, client));
终于要先去驱动的盖头了,掀起前,还是再检查一下吧,看看我们到你配不配,乙方万一以后后悔,
linux里走到这一步,要是不匹配,顶多返回而已。现实中一旦选择,那就要一辈子不离不弃,相濡以沫。
走到这里,终于走到驱动的probe了,也就是第2节中的300行:lis3lv02d_i2c_probe
probe函数,在一般情况下,是一个驱动在挂上总线并被调用后最先执行的函数,旨在做一些初始化工作,比如申请中断,map内存地址,申请结构体等等。
到此为止,我们算是走完了这个驱动的挂载和启动,不过先不急着往下看,我们还有点小尾巴尚未解决:
他的参数是什么?一个是struct i2c_client *client,另一个是 const struct i2c_device_id *id。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值