platformbus是一个虚拟总线,对应的设备是platform_device,驱动是platform_driver。在Linux2.6的设备驱动模型中,I2C、RTC、LCD等都归纳为platform_device。总线将设备和驱动绑定在一起,系统每注册一个设备,就会寻找匹配的驱动;相反,系统每注册一个驱动程序,就会去寻找匹配的设备,而匹配是由总线来完成的。Linux2.6系统中定义了bus_type的一个实例platform_bus_typestructbus_typeplatform_bus_type={.name="platform",.dev_attrs=platform_dev_attrs,.match=platform_match,//device和driver通过match函数判断是否匹配.uevent=platform_uevent,.pm=PLATFORM_PM_OPS_PTR,};/*platform_match函数用于匹配总线中的驱动和设备*/staticintplatform_match(structdevice*dev,structdevice_driver*drv){structplatform_device*pdev=to_platform_device(dev);structplatform_driver*pdrv=to_platform_driver/driver(drv)*matchaagainsttheidtablefirst*/if(pdrv->id_table)returnplatform_match_id(pdrv->id_table,pdev)!=NULL;/*fall-backtodrivernamematch*/return(strcmp(pdev->name,drv->name)==0);}platform_match函数首先判断是否使用了id_table,如果是,则使用id_table进行匹配,否则,判断platform_device和platform_driver成员中的name,如果两者的name字段相同则匹配,而如果匹配,则调用platform_driver的探测函数。platform_device结构的定义structplatform_device{constchar*name;/*name*/intid;structdevicedev;u32num_resources;/*totalresources*/structresource*resource;/*resources*/structplatform_device_id*id_entry;};其中一个重要的成员是resource,就是设备的资源信息,比如IO地址,中断号等。structresource{resource_size_tstart;//资源起始值resource_size_tend;//资源结束值constchar*name;unsignedlongflags;//资源类型,如IORESOURCE_IO,IORESOURCE_MEM,IORESOURCE_IRQ,IORESOURCE_DMAstructresource*parent,*sibling,*child;};有些设备可能有多个资源,通常使用platform_get_resource函数获取资源){inti;for(i=0;inum_resources;i++){structresource*r=&dev->resource[i];if(type==resource_type(r)&&num--==0)returnr;}returnNULL;}注册平台设备,使用platform_device_register函数平台设备。intplatform_device_add(structplatform_device*pdev){inti,ret=0;if(!pdev)/*如果pdev为空,则返回EINVAL*/return-EINVAL;/*如果pdev->dev.parent为空,则pdev->dev.parent设置为platform_bus*/if(!pdev->dev.parent)pdev->dev.parent=&platform_bus;pdev->dev.bus=&platform_bus_type;/*setbustype*/if(pdev->id!=-1)/*如果id=-1,则自动分配名称*/dev_set_name(&pdev->dev,"%s.%d",pdev->name,pdev->id);elsedev_set_name(&pdev->dev,pdev->name);for(i=0;inum_resources;i++){structresource*p,*r=&pdev->resource[i];/*获取资源*/if(r->name==NULL)r->name=dev_name(&pdev->dev);p=r->parent;if(!p){if(resource_type(r)==IORESOURCE_MEM)/*设置资源类型*/p=&iomem_resource;elseif(resource_type(r)==IORESOURCE_IO)p=&ioport_resource;}if(p&&insert_resource(p,r)){printk(KERN_ERR"%s:failedtoclaimresource%d\n",dev_name(&pdev->dev),i);ret=-EBUSY;gotofailed;}}pr_debug("Registeringplatformdevice'%s'.Parentat%s\n",dev_name(&pdev->dev),dev_name(pdev->dev.parent));/*向内核添加一个设备*/ret=device_add(&pdev->dev);if(ret==0)returnret;失败:while(--i>=0){structresource*r=&pdev->resource[i];unsignedlongtype=resource_type(r);if(type==IORESOURCE_MEM||type==IORESOURCE_IO)release_resource(r);}returnret;}platform_device_add最后调用device_add完成平台设备的注册反之,如果要注销平台设备,使用platform_device_unregister函数voidplatform_device_unregister(structplatform_device*pdev){platform_device_del(pdev);platform_device_put(pdev);}platform_device_unregister函数调用platform_device_del函数注销平台设备pdev){device_del(&pdev->dev);for(i=0;inum_resources;i++){structresource*r=&pdev->resource[i];unsignedlongtype=resource_type(r);if(type==IORESOURCE_MEM||type==IORESOURCE_IO)release_resource(r);}}}platform_device_del函数调用device_del函数删除平台设备。相应地,释放资源需要调用release_resource函数,前提是资源类型必须是IORESOURCE_MEM或IORESOURCE_IOplatform_driver的定义:structplatform_driver{int(*probe)(structplatform_device*);int(*remove)(structplatform_device*);void(*shutdown)(structplatform_device*);int(*suspend)(structplatform_device*,pm_message_tstate);int(*resume)(structplatform_device*);structdevice_driverdriver;conststructplatform_device_id*id_table;};device_driver的定义:structdevice_driver{constchar*name;structbus_type*bus;structmodule*owner;constchar*mod_name;/*用于内置模块*/boolsuppress_bind_attrs;/*disablesbind/unbindviasysfs*/conststructof_device_id*of_match_table;conststructacpi_device_id*acpi_match_table;int(*probe)();int(*remove)(structdevice*dev);void(*shutdown)(structdevice*dev);int(*suspend)(structdevice*dev,pm_message_tstate);int(*resume)(structdevice*dev);conststructattribute_group**groups;conststructdev_pm_ops*pm;structdriver_private*p;};platform_driver结构体有device_driver成员,其各自的字段如上所示,device_driver还有probe、remove、shutdown等函数,在注册platformdriver时初始化。前面提到,当系统中有平台设备,通过总线的匹配函数匹配到平台驱动时,会调用pl??atform_driver的probe函数,参数为platform_device,有时会通过id_table来判断是否是火柴。structplatform_device_id{charname[PLATFORM_NAME_SIZE];kernel_ulong_tdriver_data__attribute__((aligned(sizeof(kernel_ulong_t))));};平台驱动注册使用platform_driver_register函数intplatform_driver_register(structplatform_driver*drv){drv=&pliver.ifprobe)drv->driver.probe=platform_drv_probe;if(drv->remove)drv->driver.remove=platform_drv_remove;if(drv->shutdown)drv->driver.shutdown=platform_drv_shutdown;if(drv->suspend)drv->driver.suspend=platform_drv_suspend;if(drv->resume)drv->driver.resume=platform_drv_resume;returndriver_register(&drv->driver);}首先在platform_driver中初始化驱动,驱动的类型为device_driver,设置驱动setthedriver'sprobe为platform_drv_probe;将驱动程序的删除设置为platform_drv_remove;将驱动程序的关闭设置为platform_drv_shutdown;将驱动程序的挂起设置为platform_drv_suspend;将driver的resume设置为platform_drv_resume,最后调用driver_register函数注册platformdriver。相反,要取消注册平台驱动程序,请使用platform_driver_unregister函数voidplatform_driver_unregister(structplatform_driver*drv){driver_unregister(&drv->driver);}