从Linux 2.6开始,引入了新的驱动管理和注册机制:platform_device和platform_driver。Linux中的大多数设备驱动程序都可以使用这种机制。设备由platform_device表示,驱动程序由platform_driver注册。
与传统的设备驱动机制(通过driver_register函数注册)相比,Linux平台驱动机制有一个非常明显的优势,就是设备本身的资源注册在内核中,由内核管理,这些资源在驱动中使用时,通过平台设备提供的标准接口来申请和使用。这样提高了驱动和资源管理的独立性,具有良好的可移植性和安全性(这些标准接口是安全的)。平台机制本身的使用并不复杂,由platform_device和platfrom _ driver两部分组成。通过平台机制开发底层设备的流程是申请平台_设备,注册平台_设备,注册平台_驱动。
Platform_device结构用于描述设备的名称和资源信息。结构定义在include/Linux/platform _ device . h中,原型如下:
结构平台_设备{
const char * name//定义平台设备的名称。
int id
结构设备开发;
u32数量_资源;
结构资源*资源;//定义平台设备的资源。
};
我们来看看平台_设备结构中最重要的成员,struct resource * resource。在include/linux/ioport.h中定义了结构资源,原型如下:
结构资源{
resource_size_t开始;//定义资源的起始地址。
resource_size_t结束;//定义资源的结束地址。
const char * name//定义资源的名称。
无符号长标志;//定义资源的类型,如MEM、IO、IRQ和DMA类型。
结构资源*父级,*同级,*子级;//资源链表指针
};
通过调用函数platform_add_devices()将设备添加到系统中,该函数在内部调用platform_device_register()进行设备注册。需要注意的是,这里的platform_device设备的注册过程必须在加载相应的设备驱动之前,也就是在执行platform_driver_register()之前调用,因为驱动注册需要匹配内核中所有注册的设备名称。
接下来,看看platform_driver结构的原型定义。在include/Linux/platform _ device . h中,代码如下:
结构平台_驱动程序{
int (*probe)(结构平台_设备*);
int (*remove)(结构平台_设备*);
void (*shutdown)(结构平台_设备*);
int (*suspend)(结构平台_设备*,pm _消息_t状态);
int (*suspend_late)(结构平台_设备*,pm _消息_t状态);
int (*resume_early)(结构平台_设备*);
int (*resume)(结构平台_设备*);
结构设备驱动程序驱动程序;
};
内核提供的platform_driver结构的注册函数是platform_driver_register(),其原型定义在driver/base/platform.c文件中。具体实现代码如下:
int平台_驱动程序_寄存器(结构平台_驱动程序*drv)
{
drv-》driver . bus=platform _ bus _ type;
if (drv-》探针)
drv-》driver . probe=platform _ drv _ probe;
如果(drv-》删除)
drv-》driver . remove=platform _ drv _ remove;
如果(drv-》关闭)
drv-》driver . shut down=platform _ drv _ shut down;
如果(drv-》暂停)
drv-》driver . suspend=platform _ drv _ suspend;
if (drv-》简历)
drv-》driver . resume=platform _ drv _ resume;
返回driver _ register(drv-》driver);
}
这里有一个例子来说明:
在kernel/arch/arm/mach-pxa/pxa 27 x . c中定义。
静态结构资源pxa27x_ohci_resources[]={
[0]={。start=0x4C000000。end=0x4C00ff6f。flags=IORESOURCE_MEM,
},
[1]={。start=IRQ_USBH1。end=IRQ_USBH1。flags=IORESOURCE_IRQ,
},
};
这里,定义了两组资源,它们描述了usb主机设备的资源。第一组描述了这个usb主机设备占用的资源。
总线地址范围,IORESOURCE_MEM表示第一组描述内存类型的资源信息,第二组描述usb主机设备。
IORESOURCE_IRQ的中断号表示第二组描述了中断资源信息。设备驱动程序将根据标志获取相应的资源信息。
有了资源信息,您可以定义平台设备:
静态结构平台_设备ohci _设备={。name="pxa27x-ohci"。id=-1。dev={。dma_mask=pxa27x_dmamask。coherent_dma_mask=0xffffffff,
},num _ resources=ARRAY _ SIZE(pxa 27 x _ ohci _ resources)。resource=pxa27x_ohci_resources
};
使用platform_device,您可以调用函数platform_add_devices将设备添加到系统中。这里的实现如下
静态int __init pxa27x_init(void)
{
返回platform_add_devices(设备,ARRAY_SIZE(设备));
}
这里的pxa27x_init必须在加载设备驱动程序之前调用。你可以把它放在。
subsys _ init call(pxa 27 x _ init);
驱动需要实现struct platform_driver,参考内核/驱动/USB/主机/OHCI-pxa27.c
静态结构平台_驱动程序ohci_hcd_pxa27x_driver={。probe=ohci _ HCD _ pxa 27 x _ drv _ probe。remove=ohci _ HCD _ pxa 27 x _ drv _ remove,
#ifdef CONFIG_PM。suspend=ohci _ HCD _ pxa 27 x _ drv _ suspend。resume=ohci _ HCD _ pxa 27 x _ drv _ resume
#endif。驱动程序={。name="pxa27x-ohci",
},
};
调用驱动初始化函数中的函数platform_driver_register()来注册platform_driver。应该注意的是
ohci_device结构中的name元素和ohci_hcd_pxa27x_driver结构中的driver.name必须相同,以便。
在platform_driver_register()上注册时,将检查所有注册的platform_device中的名称和当前注释。
比较书的platform_driver的driver.name,只能注册同名的platfomr _ device。
成功,注册成功时会调用platform_driver结构元素probe函数指针,这里是ohci_hcd_pxa27x_drv_probe。
进入probe功能后,需要获取设备的资源信息。获取资源的功能有:
struct resource * platform _ get _ resource(struct platform _ device * dev,无符号int type,无符号int num);
根据参数type指定类型,如IORESOURCE_MEM。
struct int platform _ get _ IRQ(struct platform _ device * dev,无符号int num);
获取资源中的中断号。
struct resource * platform _ get _ resource _ byname(struct platform _ device * dev,unsigned int type,char * name);
根据参数名指定的名称获取指定的资源。
int platform _ get _ IRQ _ byname(struct platform _ device * dev,char * name);
根据参数名指定的名称获取资源中的中断号。
综上所述,一般来说,只要对内核本身运行依赖不大的外设相对独立,有自己的资源(地址总线和IRQ),都可以用platform_driver来实现。如:LCD、网卡、USB、UART等。都可以用platform _ driver编写,而timer、irq等小型系统中的设备最好不要使用platform _ driver机制。
标签:资源设备平台