1.platform device是怎么"自动"关联到platform driver上的?
转向linux driver有些时间了,前段时间碰到个问题,在Linux kernel 3.10的drivers/tty/serial/imx.c中,注册driver的时候调用platform_driver_register(&serial_imx_driver),serial_imx_driver类型为platform_driver, serial_imx_driver中有个成员变量probe,在driver注册时会调用这个函数,但是这个函数的参数是platform_device,而在imx.c中没有出现platform_device类型的任何变量,问题就此产生了。
2.设备、总线、驱动三者如何关联起来?
后来查阅了相关资料,大体上的意思是,在linux2.6内核以后,设备和驱动的结构划分为设备、总线、驱动,设备和驱动分别挂在总线上,而他们通过name来进行匹配,二者绑定有两种方式:一种是先安装driver,后挂载设备;另一种则是先挂载设备,然后安装driver。但二者都是后面动作的会在总线上搜索与自己name项相同的设备或者driver进行匹配,也即完成绑定。
3.代码中的实现
在imx.c中,由于平台是3.10,所以使用DTS,设备都是预先挂载了如串口0/1/2/3...,后面安装驱动时,会调用上述说到的platform_driver_register(&serial_imx_driver),在驱动注册过程中会对进行匹配设备,一旦匹配到某个device,就会调用probe进行初始化,这个probe的参量也就有源了。具体可以参考下面的调用过程:
do_basic_setup()->driver_init()->platform_bus_init()->...初始化platform bus(虚拟总线)
设备向内核注册的时候platform_device_register()->platform_device_add()->...内核把设备挂在虚拟的platform bus下
驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev()对每个挂在虚拟的platform bus的设备作__driver_attach()->driver_probe_device()->drv->bus->match()==platform_match()->比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用platform_drv_probe()->driver->probe(),如果probe成功则绑定该设备到该驱动.
代码如下:在执行到driver_attach的时候platform_device还没出现:
int driver_attach(struct device_driver *drv) { return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); } EXPORT_SYMBOL_GPL(driver_attach);
这一步开始出现了,县初始化device list,然后通过next_device来遍历节点的属性,调用fn也即__driver_attach,dev也是从next_device中获取device指针。
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)) { struct klist_iter i; struct device *dev; int error = 0; if (!bus || !bus->p) return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); return error; } EXPORT_SYMBOL_GPL(bus_for_each_dev);
以上只是简单理解,还是没有深入进去,所以很多原理说不清楚,希望能有时间静下心好好研究研究,如:
1. 设备、驱动、总线三者设计理念,结构模式
2. 设备、驱动先后挂到总线上的机制
3. linux2.6之前、linux2.6、linux2.6之后,驱动、设备在这些版本中的变迁,如platform的出现,dts的出现等