如果bus和driver同时具备probe方法,则优先调用总线的probe函数。否则调用device_driver的probe函数,此 probe 函数是经过各种类型的driver重载的函数,这就实现了利用基类的统一方法来实现不同的功能。对于platform_driver来说,其就是:
394static int platform_drv_probe(struct device *_dev)
395{
396 struct platform_driver *drv = to_platform_driver(_dev->driver);
397 struct platform_device *dev = to_platform_device(_dev);
398
399 return drv->probe(dev);
400}
然后调用特定platform_driver所定义的操作方法,这个是在定义某个platform_driver时静态指定的操作接口。
至此,platform_driver成功挂接到platform bus上了,并与特定的设备实现了绑定,并对设备进行了probe处理。
6 bus、device及driver三者之间的关系
在数据结构设计上,总线、设备及驱动三者相互关联。
platform device包含device,根据device可以获得相应的bus及driver。
设备添加到总线上后形成一个双向循环链表,根据总线可以获得其上挂接的所有device,进而获得了 platform device。根据device也可以获得驱动该总线上所有设备的相关driver。
platform driver包含driver,根据driver可以获得相应的bus,进而获得bus上所有的device,进一步获得platform device,根据name对driver与platform device进行匹配,匹配成功后将device与相应的driver关联起来,即实现了platform device和platform driver的关联。
匹配成功后调用driver的probe进而调用platform driver的probe,在probe里实现驱动特定的功能。
7 哪些适用于plarform驱动?
platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过platform device提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,这样拥有更好的可移植性。platform机制的本身使用并不复杂,由两 部分组成:platform_device和platfrom_driver。Platform driver通过platform bus获取platform_device。
通常情况下只要和内核本身运行依赖性不大的外围设备,相对独立的,拥有各自独立的资源(地址总线和IRQs),都可以用 platform_driver来管理,而timer,irq等小系统之内的设备则最好不用platfrom_driver机制。
platform_device最大的特定是CPU直接寻址设备的寄存器空间,即使对于其他总线设备,设备本身的寄存器无法通过CPU总线访问,但总线的controller仍然需要通过platform bus来管理。
总之,platfrom_driver的根本目的是为了统一管理系统的外设资源,为驱动程序提供统一的接口来访问系统资源,将驱动和资源分离,提高程序的可移植性。
8 基于platform总线的驱动开发流程
基于Platform总线的驱动开发流程如下:
• 定义初始化platform bus
• 定义各种platform devices
• 注册各种platform devices
• 定义相关platform driver
• 注册相关platform driver
• 操作相关设备
以S3C24xx平台为例,来简单讲述下platform驱动的实现流程。
8.1 初始化platform_bus
Platform总线的初始化是在platform_bus_init()完成的,代码如下:
26struct device platform_bus = {
27 .bus_id = "platform",
28};
29EXPORT_SYMBOL_GPL(platform_bus);
621int __init platform_bus_init(void)
622{
623 int error;
624
625 error = device_register(&platform_bus);
626 if (error)
627 return error;
628 error = bus_register(&platform_bus_type);
629 if (error)
630 device_unregister(&platform_bus);
631 return error;
632}