linux platfrom驱动
一、linux驱动的分离和分层
为提高linux驱动可重用性和可移植性。下图以i2c驱动为例说明linux驱动的分离和分层思想。由于不同芯片的i2c控制器不同,所以不同厂家会提供自己的i2c控制器驱动,不同设备它们的i2c接口驱动也不一样,所以不同设备厂家也会提供各自的设备驱动,linux则提供统一的api接口,使i2c驱动和设备驱动联通。
为了实现这种分层和分离的思想,linux提出设备、总线、驱动的方法。linux内核中,用struct device、struct bus_type、struct device_driver这三个结构体分别表示设备、总线、驱动。
二、driver和device注册过程
driver注册过程
->driver_register //注册驱动, linux_kernel/drivers/base/drivers.c
->bus_add_driver //将驱动添加到总线中, linux_kernel/drivers/base/bus.c
->driver_attach //查找总线下的所有设备,并将该驱动与所有设备相匹配
->bus_for_each_dev //查找总线下的所有设备,并将该驱动与所有设备相匹配
->fn //fn即__driver_attach函数,为总线下的每个设备与该驱动执行fn函数
->driver_match_device //检查驱动与设备是否匹配
->driver_probe_device //如果匹配值执行这个函数
->really_probe
->drv->probe //最终执行device_driver 中的probe函数
device注册过程
->device_register //注册device, linux_kernel/drivers/base/core.c
->device_initialize //初始化设备
->device_add //添加设备
->bus_add_device //向总线添加设备
->bus_probe_device
->device_initial_probe
->__device_attach
->bus_for_each_drv //查找总线下的所有驱动
->fn ///fn即__device_attach_driver函数,为总线下的每个驱动与该设备执行fn函数
->driver_match_device //检测驱动和设备是否匹配
->driver_probe_device //如果设备与驱动匹配,则执行该函数
->really_probe
->drv->probe //最终执行device_driver 中的probe函数
综上,当注册驱动时,总线上的所有设备会与该驱动匹配,若匹配上,则执行驱动的prob函数。当注册设备时,总线上的所有驱动会与改设备匹配,当匹配时,也会执行驱动的prob函数。
三、platform、platform_device、platform_driver注册过程
3.1 platform注册过程
->platform_bus_init //patform总线初始化, linux_kernel/drivers/base/platform.c
->device_register
->bus_register
3.2 platform_driver注册过程
->__platform_driver_probe //注册platform_driver,用于替代platform_driver_register函数, linux_kernel/drivers/base/platform.c
->__platform_driver_register //初始化platform_driver中的device_driver结构体,最后调用driver_register注册platform_driver中的device_driver
->driver_register //注册platform_driver中的device_driver,后续过程跟上面的注册driver一致
__platform_driver_registery源码分析
int __platform_driver_register(struct platform_driver *drv,
struct module *owner)
{
drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
drv->driver.probe = platform_drv_probe; //将platform_driver中的device_driver指定为platform_drv_probe
drv->driver.remove = platform_drv_remove;
drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver); //注册device_driver时最后会调用probe函数,而上面又将device_driver的probe指定为platform_drv_probe,
//platform_drv_probe函数中调用了struct platform_driver中的probe函数,所以最终还是调用了struct platform_driver中的prob函数
}
注册platform_driver将最终调用struct platform_driver中的prob函数
3.3 platform_device 注册
->platform_device_register //注册platform_device, linux_kernel/drivers/base/platform.c
->platform_device_add
->device_add //向内核添加platform_device中的device,后续跟上面注册device中的的添加device一致
四、platform驱动和设备匹配过程
如下图所示,paltform的匹配函数是platform_match,有三种匹配方式,分别是设备树匹配、acpi匹配、id匹配、name匹配。
.
设备树的匹配方式。
->of_driver_match_device //linux_kernel/drivers/base/platform.c
->of_match_device
->of_match_node
->__of_match_node
->__of_device_is_compatible //这个函数会去读取设备树中的compatible值来匹配