从Linux2.6起,引入了一套新的驱动管理和注册机制:Platform_device和Platform_driver。Linux中大部分的设备驱动,都可以使用这套机制,设备用platform_device表示,驱动用platform_driver进行注册。
和传统的驱动一样,platform机制也分为三个步骤:
1 总线注册阶段:
内核启动初始化时的main.c文件中的
kernel_init()
-->do_basic_setup()
-->driver_init()
-->platform_bus_init()
-->bus_register(&platform_bus_type),注册了一条platform总线(虚拟总线)。
2 添加设备时:
设备注册的时候(对于展讯8830 设备的在kernel/arch/arm/mach-sc/Board_sp8830ec.c中的sc8830_init_machine()中有platform_add_devices(devices,ARRAY_SIZE(devices)))注册的。其中devices是platform_device类型的数组。
Platform_device_register()
-->platform_device_add()
-->device_add(),就这样把设备给挂到虚拟的总线上。
3 驱动注册时:
-->driver_register()
-->bus_add_driver()
-->driver_attach()
-->bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
对在每个挂在虚拟的platformbus的设备作__driver_attach()-->driver_probe_device(),判断drvàbusàmatch()是否执行成功,此时通过指针执行platform_match-->strncmp(pdev->name ,drv->name ,BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行相应设备的platform_driver->probe(platform_device)。)开始真正的探测,如果probe成功,则绑定设备到该驱动。
下面看几个结构体:
struct platform_device
{
};
该结构体中最重要的就是resource结构,这也是之所以引入platform机制的原因。
struct resource
{
};
struct platform_driver
{
};
Platform_driver结构体描述了一个platform结构的驱动。其中除了一些函数指针外,还有一个一般驱动的device_driver结构。
名字要一致的原因:
上面说的驱动在注册的时候会调用函数bus_for_each_dev(),对在每个挂在虚拟的platformbus的设备作__driver_attach()àdriver_probe_device(),在此函数中会对dev和drv做初步的匹配,调用的是drv->bus->match所指向的函数。platform_driver_register函数中drv->driver.bus=&platform_bus_type,所以drv->bus->match就为platform_bus_typeàmatch,为platform_match函数,该函数如下:
static int platform_match(struct device * dev, structdevice_driver * drv)
{
}
是比较dev和drv的name,相同则会进入really_probe()函数,从而进入自己写的probe函数做进一步的匹配。所以devàname和driveràdrvàname在初始化时一定要填一样的。
不同类型的驱动,其match函数是不一样的,这个platform的驱动,比较的是dev和drv的名字,还记得usb类驱动里的match吗?它比较的是ProductID和VendorID。