在《Linux设备模型分析之基本数据结构》一文中我分析了kobject,kset,device,device_driver等构成Linux设备模型的重要数据结构。但在分析Linux内核代码时这些原始数据结构大多被platform_device和platform_driver所封装代替,下文采用at91sam9260开发板提供的Linux2.6.19内核,剖析platform_device和platform_driver的使用。首先来看这两个结构体的定义,都在/include/linux/platform_device.h中被定义:
- struct platform_device {
- const char * name;
- u32 id;
- struct device dev;
- u32 num_resources;
- struct resource * resource;
- };
- struct platform_driver {
- int (*probe)(struct platform_device *);
- int (*remove)(struct platform_device *);
- void (*shutdown)(struct platform_device *);
- int (*suspend)(struct platform_device *, pm_message_t state);
- int (*suspend_late)(struct platform_device *, pm_message_t state);
- int (*resume_early)(struct platform_device *);
- int (*resume)(struct platform_device *);
- struct device_driver driver;
- };
可见上文提到的device结构体被封装在platform_device中,而device_driver结构体被封装在platform_driver中。 其中,resource结构体在/include/linux/ioport.h中定义,该结构体指明了设备的地址范围,名称,设备类型(flags字段:存储,IO,中断等,在/include/linux/ioport.h中定义),已经指向父兄子节点的指针(不常用)。
- struct resource {
- resource_size_t start;
- resource_size_t end;
- const char *name;
- unsigned long flags;
- struct resource *parent, *sibling, *child;
- };
下面以at91sam9260中的I2C总线驱动为例对platform设备注册过程进行分析。 在/arch/arm/mach-at91rm9200/at91sam9260_devices.c中定义如下:
- static struct resource twi_resources[] = {
- [0] = {
- .start = AT91SAM9260_BASE_TWI,
- .end = AT91SAM9260_BASE_TWI + SZ_16K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = AT91SAM9260_ID_TWI,
- .end = AT91SAM9260_ID_TWI,
- .flags = IORESOURCE_IRQ,
- },
- };
-
- static struct platform_device at91sam9260_twi_device = {
- .name = "at91_i2c",
- .id = -1,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
- }
-
- 在/drivers/i2c/buses中
- static struct platform_driver at91_i2c_driver = {
- .probe = at91_i2c_probe,
- .remove = __devexit_p(at91_i2c_remove),
- .suspend = at91_i2c_suspend,
- .resume = at91_i2c_resume,
- .driver = {
- .name = "at91_i2c",
- .owner = THIS_MODULE,
- },
- };
twi_resource中定义了两个资源:一个是作为存储的资源(IORESOURCE_MEM),定义了I2C的地址,这里注意用的是物理地址;另一个是I2C中断,使用的是at91sam9260的peripheral identifier designator。at91sam9260_twi_device即描述了TWI这个具体设备的资源,这里没有对其中的device结构进行初始化。at91_i2c_driver则是具体的驱动封装,指向了具体的操作函数,并对platform_driver结构体中的name和owner域进行了赋值,注意name的值要要一致。