`
isiqi
  • 浏览: 16353378 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

platform驱动管理机制

阅读更多

<!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/> <w:TrackFormatting/> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>EN-US</w:LidThemeOther> <w:LidThemeAsian>ZH-CN</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="--"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Priority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="0" Name="header"/> <w:LsdException Locked="false" Priority="0" Name="footer"/> <w:LsdException Locked="false" Priority="0" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="0" Name="page number"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="0" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/> <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/> <w:LsdException Locked="false" Priority="0" Name="Document Map"/> <w:LsdException Locked="false" Priority="0" Name="No List"/> <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/> <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 1"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/> <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/> <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/> <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 6"/> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/> <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/> <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/> <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/> <w:LsdException Locked="false" Priority="32" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/> <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/> <w:LsdException Locked="false" Priority="37" Name="Bibliography"/> <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/> </w:LatentStyles> </xml><![endif]--><!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman","serif";} </style> <![endif]-->

第1章 platform 驱动管理机制

Linux2.6 内核引入了一套新的驱动管理机制: Platform_device Platform_driver 。设备用 Platform_device 表示,驱动用 Platform_driver 表示,另外设备描述了使用的资源,驱动则负责电源管理和使用资源。由于驱动和资源之间的独立,使得程序的可移植性和可扩展性大大增强。

1.1 platform_device

1.1.1 数据结构

plarform 设备用 platform_device 来表示,如 程序清单 1 .1 所示。


程序清单 1 . 1 platform_device

/* include/linux/platform_device.h */

struct platform_device {

const char * name;

int id;

struct device dev;

u32 num_resources;

struct resource * resource;

};

各个成员的解释如下:

name 指向设备的名字字符串,这个名字用来和同名的 platform_driver 进行匹配。

id 是设备编号(如果有多个同类设备的话),如果只有一个则需设为 -1

设备模型用到的成员。

使用到的资源的数量。

资源数组头地址。

最后一个成员 resource 指向此设备用到的资源的数组, struct resource 的定义如 程序清单 1 .2 所示。


程序清单 1 . 2 struct resource

/* 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;

};

#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */

#define IORESOURCE_IO 0x00000100 /* Resource type */

#define IORESOURCE_MEM 0x00000200

#define IORESOURCE_IRQ 0x00000400

#define IORESOURCE_DMA 0x00000800

#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */

#define IORESOURCE_READONLY 0x00002000

#define IORESOURCE_CACHEABLE 0x00004000

#define IORESOURCE_RANGELENGTH 0x00008000

#define IORESOURCE_SHADOWABLE 0x00010000

#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */

#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */

#define IORESOURCE_DISABLED 0x10000000

#define IORESOURCE_UNSET 0x20000000

#define IORESOURCE_AUTO 0x40000000

#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */


各个成员的解释如下:

start 记录资源范围的起始值,比如一段内存空间的首地址。

end 记录资源范围的结束位置。

name 资源的名字。

flags 用来记录资源类型以及是否可写、忙碌等信息,各位的定义如 程序清单 1 .2 所示。

分别记录资源树的父节点、兄弟节点和子节点。

1.1.2 注册流程

注册 platform_device 有两个接口 platform_add_devices platform_device_register ,它们的代码如所示。


程序清单 1 . 3 platform_device 注册接口

/* drivers/base/platform.c */

int platform_add_devices(struct platform_device **devs, int num)

{

int i, ret = 0;

for (i = 0; i < num; i++) {

ret = platform_device_register(devs[i]);

if (ret) {

while (--i >= 0)

platform_device_unregister(devs[i]);

break;

}

}

return ret;

}

int platform_device_register(struct platform_device *pdev)

{

device_initialize(&pdev->dev);

return platform_device_add(pdev);

}

platform_add_devices 注册多个设备,循环调用了 platform_device_register platform_device_register 只有两步,第一步初始化 platform_device dev 成员,接下来调用 platform_device_add 函数,它的实现如 程序清单 1 .4 所示。


程序清单 1 . 4 platform_device_add

/* drivers/base/platform.c */

int platform_device_add(struct platform_device *pdev)

{

int i, ret = 0;

if (!pdev)

return -EINVAL;

if (!pdev->dev.parent)

pdev->dev.parent = &platform_bus;

pdev->dev.bus = &platform_bus_type;

if (pdev->id != -1)

snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,

pdev->id);

else

strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);

for (i = 0; i < pdev->num_resources; i++) {

struct resource *p, *r = &pdev->resource[i];

if (r->name == NULL)

r->name = pdev->dev.bus_id;

p = r->parent;

if (!p) {

if (r->flags & IORESOURCE_MEM)

p = &iomem_resource;

else if (r->flags & IORESOURCE_IO)

p = &ioport_resource;

}

if (p && insert_resource(p, r)) {

printk(KERN_ERR

"%s: failed to claim resource %d\n",

pdev->dev.bus_id, i);

ret = -EBUSY;

goto failed;

}

}

pr_debug("Registering platform device '%s'. Parent at %s\n",

pdev->dev.bus_id, pdev->dev.parent->bus_id);

ret = device_add(&pdev->dev);

if (ret == 0)

return ret;

failed:

while (--i >= 0)

if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))

release_resource(&pdev->resource[i]);

return ret;

}


代码的解释如下:

处初始化设备的父设备和总线类型。

处填写该设备在设备模型中的名字:如果编号不为 -1 则名字为设备名加编号,否则只包含设备名。

处循环处理设备的每一个资源。

如果父资源指针为空,则为 IO 端口和 IO 内存设置默认的父资源节点。这里看到,中断资源和 DMA 资源并不设置父节点,因为内核没有为这两类资源建立资源树,它们的使用情况使用另外的方式记录。

如果有父资源节点,则将资源注册进内核资源树(仅仅针对 IO 端口和 IO 内存)。

将本设备注册进内核的驱动模型中。

1.2 platform_driver

platform 驱动用 platform_driver 来表示,它的定义如 程序清单 1 .5 所示。


程序清单 1 . 5 platform_driver

/* include/linux/platform_device.h */

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 pm_ext_ops *pm;

struct device_driver driver;

};

platform_driver 的各个成员主要用来进行电源管理。其成员 driver.name 用来匹配支持的设备,它支持的 platfirm_device 必须使用这个名字。当有 platform_device 和该驱动名字匹配时, probe 成员会被调用,传入匹配的设备指针。解除绑定时 remove 被调用。

platform_driver 的注册较为简单,如 程序清单 1 .6 所示。


程序清单 1 . 6 platform_driver_register

/* drivers/base/platform.c */

int platform_driver_register(struct platform_driver *drv)

{

drv->driver.bus = &platform_bus_type;

if (drv->probe)

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;

if (drv->pm)

drv->driver.pm = &drv->pm->base;

return driver_register(&drv->driver);

}

注册过程就是将 platform_driver 的成员函数赋给 driver 成员的成员函数指针,然后注册进设备模型。

1.3 platform 使用例子

1.3.1 lpc32xx i2c

platform 提供了设备的资源视图,可以比较集中的管理资源的使用。在 Linux 内核硬件相关的文件当中, Linux 使用 platform 机制定义了很多驱动使用的资源,可以在一个文件中看到多个驱动的资源分配情况,有利于资源的规划和分配。对于 smartarm3250 来说,这个文件是 arch/arm/mach-lpc32xx/arch-lpc32xx.c ,这个文件定义了看门狗、 rtc i2c spi 等各种总线 / 设备用到的资源,定义了这些模块的驱动 platform_device ,对于 i2c 的定义如 程序清单 1 .7 所示。


程序清单 1 . 7 i2c platform_device

/* arch/arm/mach-lpc32xx/arch-lpc32xx.c */

#if defined (CONFIG_MACH_LPC32XX_I2C0_ENABLE)

static struct i2c_pnx_algo_data lpc32xx_algo_data0 = {

.base = I2C1_BASE,

.irq = IRQ_I2C_1,

};

static struct i2c_adapter lpc32xx_adapter0 = {

.name = I2C_CHIP_NAME "0",

.algo_data = &lpc32xx_algo_data0,

};

static struct i2c_pnx_data i2c0_data = {

.suspend = i2c_lpc32xx_suspend,

.resume = i2c_lpc32xx_resume,

.calculate_input_freq = calculate_input_freq,

.set_clock_run = set_clock_run,

.set_clock_stop = set_clock_stop,

.adapter = &lpc32xx_adapter0,

};

static struct platform_device i2c0_device = {

.name = "pnx-i2c",

.id = 0,

.dev = {

.platform_data = &i2c0_data,

},

};

#endif


这里资源的传递没有通过 struct resource 来传递,而是使用了 struct platform_device dev. platform_data 传递过去的,这种用法不多见,其它模块的资源通过 struct platform_device resource 成员来传递。可见这里已经定义好了设备的一切资源。

lpc32xx platform_device 是通过 phy3250_board_init()->lpc32xx_init()->platform_add_devices() 来注册的。而 phy3250_board_init 是在硬件架构的初始化时被调用的。

上面的内容是 platform_device 的定义,完整的驱动模型包含驱动和设备两部分。对应的 platform_driver 定义在 driver/i2c/busses/i2c-pnx.c ,如所示。


程序清单 1 . 8 lpc32xx platform_driver

/* driver/i2c/busses/i2c-pnx.c */

static struct platform_driver i2c_pnx_driver = {

.driver = {

.name = "pnx-i2c",

.owner = THIS_MODULE,

},

.probe = i2c_pnx_probe,

.remove = __devexit_p(i2c_pnx_remove),

.suspend = i2c_pnx_controller_suspend,

.resume = i2c_pnx_controller_resume,

};

static int __init i2c_adap_pnx_init(void)

{

return platform_driver_register(&i2c_pnx_driver);

}

static void __exit i2c_adap_pnx_exit(void)

{

platform_driver_unregister(&i2c_pnx_driver);

}

subsys_initcall(i2c_adap_pnx_init);

module_exit(i2c_adap_pnx_exit);


可以看到这个驱动的名字和 platform_device 的名字是一致的,因为名字是它们相互绑定的依据。在 Linux 设备模型中,当发现新注册的驱动和已经注册的设备符合绑定条件之后,驱动的 probe 函数将被调用, probe 的主要职能是申请设备定义的资源(比如中断和 IO 内存空间)并初始化设备的硬件,注册设备的其它子系统资源(比如 i2c 的适配器结构体)。

由于 i2c_adap_pnx_init 是在子系统初始化的时候被调用的,因此比 platform_device 的初始化要晚。

1.3.2 platform 驱动的使用总结

最典型的 platform 应用就是 1.3.1 节的所示的形式,在一个文件中定义设备的资源和数据结构,在另一个文件的驱动中进行申请和初始化。设备和驱动的绑定由 Linux 设备模型负责。驱动和设备的分离使得每个驱动可以对应多个同类的设备,资源独立之后可以在不修改设备资源配置的情况下升级驱动模块。

典型的应用是在内核编译之前就定义好了各种平台设备和它们的资源,如果想在驱动模块中定义 platform_device 并申请资源也是可以的。可以使用以下接口动态申请一个 platform_device:


struct platform_device *platform_device_alloc( const char *name, int id);


进行适当的初始化之后就可以使用 platform_device_register() 进行注册了。当然也可以直接动态构并注册:


struct platform_device *platform_device_register_simple(

const char *name, int id,

struct resource *res, unsigned int nres);


在模块当中定义 platform_devic platform_driver 并不是内核文档推荐的用法,因为 platform_devic 可能被其他模块或者子系统所依赖或引用。当本模块卸载时,其它模块可能还在使用。因此在驱动模块中定义设备是不合适的,因为驱动的职责不包含设备的定义,这违背了 Linux 设备模型的思想。但是如果保证不会和其它模块产生依赖,使用平台设备可以添加设备电源管理的接口,这对需要低功耗的嵌入式设备具有重大意义。因此如果对功耗没有要求,尽量不要用 platform ,如果有需求则需要小心使用,如果这个设备比较固定,最好将设备的定义添加到内核中。

1.4 Linux 资源树

我们看到 Linux 的平台设备使用了资源的概念,如 程序清单 1 .2 所示。如 程序清单 1 .4 所示, platform_device 注册过程中会将没有设置父节点的 IO 端口和 IO 内存资源的父节点指针指向默认的两个节点: ioport_resource iomem_resource ,内核会以倒置的兄弟节点树的形式来记录资源的使用情况。它们的定义如 程序清单 1 .9 所示。


程序清单 1 . 9 ioport_resource iomem_resource

/* kernel/resource.c */

struct resource ioport_resource = {

.name = "PCI IO",

.start = 0,

.end = IO_SPACE_LIMIT,

.flags = IORESOURCE_IO,

};

struct resource iomem_resource = {

.name = "PCI mem",

.start = 0,

.end = -1,

.flags = IORESOURCE_MEM,

};


对于中断和 DMA 类的资源,内核中并没有相应的资源树。

在使用 IO 端口和 IO 内存资源之前,首先要进行申请,也就是从资源树中申请。 IO 端口空间的申请接口如下所示:


/* include/linux/ioport.h */

#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name));

#define release_region(start,n) __release_region(&ioport_resource, (start), (n));

static inline int __deprecated check_region(resource_size_t s, resource_size_t n);

这三个接口分别用来申请一段 IO 端口资源、释放一段资源和检查一段资源是否被占用。但是最后一个接口是不安全的,不推荐使用,因为检查和申请资源并不是原子的。

IO 内存资源的管理接口如下:


#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name));

#define release_mem_region(start,n) __release_region(&iomem_resource, (start), (n));

#define check_mem_region(start,n) __check_region(&iomem_resource, (start), (n));


这三个接口的功能 分别用来申请一段 IO 内存资源、释放一段资源和检查一段资源是否被占用。同样 check_mem_region 也是不安全的。

资源树仅仅用来使用的记录,实际使用 IO 端口和 IO 内存之前还要进行物理地址到虚拟地址之间的映射。

分享到:
评论

相关推荐

    platform机制的驱动模型

    Platform驱动适用于那些没有独立物理总线,或者通过CPU内部接口直接访问的设备,例如SoC(System on Chip)中的各种控制器、定时器、中断控制器等。 6. **基于Platform总线的驱动开发流程** - **初始化Platform ...

    Linux嵌入式platform驱动模块modules_platform_dirver

    配合博客文章《Linux嵌入式platform驱动模块modules_platform_dirver》(https://blog.csdn.net/szm1234/article/details/113705050),你可以更深入地了解如何实际编写和使用这种驱动。 总之,`modules_platform_...

    linux platform机制详解

    Linux Platform 机制是 Linux 内核中的一种驱动管理和注册机制,从 Linux 2.6 起引入,用于描述SOC上的片上资源,如 S3C2410 上集成的控制器(LCD、Watchdog、RTC 等)。该机制由 Platform_device 和 Platform_...

    Linux设备管理机制PlatForm

    在Linux内核中,为了更好地管理和组织设备与对应的驱动程序,从2.6版本开始引入了一种新的管理机制——Platform Device和Platform Driver模型。这一机制极大地提高了系统的灵活性、可移植性和可扩展性。本文将通过...

    Linux中platform设备驱动全透析

    因此,Linux提出了一种虚拟的总线机制,即platform总线,以及相应的platform设备和platform驱动。 Platform总线是一种特殊的总线类型,为那些不依附于标准总线类型的设备提供了挂载点。一个典型例子是S3C6410处理器...

    plat_device.rar_platform 驱动_platform设备

    在Linux操作系统中,`platform`驱动是用于连接和管理基于平台特定硬件的接口。平台设备驱动是一种特殊的设备驱动,主要用于处理那些没有通用总线(如PCI、USB)的硬件,这些硬件通常直接与系统主板上的特定接口相连...

    Linux设备驱动+platform驱动框架示例代码

    本资源提供的"Linux设备驱动+platform驱动框架示例代码"旨在帮助开发者理解和学习如何编写针对这类设备的驱动程序。 平台驱动通常涉及以下关键知识点: 1. **平台设备(Platform Device)**:这是Linux内核中用于...

    linux platform 驱动程序模版

    在Linux操作系统中,平台驱动程序(Platform Driver)是一种特殊的设备驱动,主要负责与系统中的片上系统(SoC,...通过理解和利用这个模版,开发者可以更好地理解Linux驱动的工作机制,提升软件和硬件的协同效率。

    drv_dv_platform_gpio_a.rar_platform 驱动

    平台驱动是Linux内核的一部分,用于管理这些设备的初始化、操作和关闭。下面我们将深入探讨平台驱动的概念、结构以及如何分析其代码。 1. 平台驱动基础: - 平台驱动是针对特定硬件设计的,它们理解硬件的工作方式...

    安卓系统签名 需要的文件 platform.pk8 platform.x509.pem fastboot驱动

    安装这个驱动后,开发者可以在Windows设备管理器中识别并正常通信到处于fastboot模式的Android设备。通常,Google会定期发布这些驱动的更新,以兼容最新的设备和操作系统版本。 总结来说,`platform.pk8`和`...

    基于platform总线的驱动模型

    #### 七、哪些适用于Platform驱动? 平台驱动适用于那些需要在CPU内部处理的硬件资源,特别是那些与特定平台密切相关的资源。例如,在嵌入式系统中,很多处理器内部集成有各种各样的控制器(如I2C控制器、SPI控制器...

    platform设备驱动全透析

    平台总线是Linux内核中一种重要的设备管理机制,它为那些不依赖于传统总线的设备提供了一致的管理和接口。通过`platform_device`和`platform_driver`这两个核心结构体以及匹配机制,实现了设备和驱动的自动绑定,...

    imx6q平台platform的gpio驱动

    2. **Linux Platform框架**: Linux Platform框架是Linux内核中用于管理硬件平台的一种机制,它简化了设备驱动程序的编写,通过定义设备结构体和设备驱动模型,使得驱动可以更方便地与特定硬件平台交互。 3. **GPIO...

    Linux platform驱动架构的解析与应用.pdf

    Linux平台驱动架构是Linux操作系统中用于管理硬件设备的一种机制,主要在Linux内核2.6.31版本中被详细阐述和应用。该架构提供了一种抽象层,使得硬件设备的驱动程序能够与硬件平台独立,提高了驱动程序的可移植性和...

    Linux驱动修炼之道-platform

    平台(Platform)模型是Linux内核用于处理嵌入式系统中特定硬件的一种机制,它通过提供一种结构化的方式来连接设备驱动和硬件平台,简化了驱动的编写过程。 ### 平台模型概述 在Linux内核中,平台模型是一种基于...

    STM32MP135实现platform驱动【支持STM32MP1系列单片机_Linux驱动】.zip

    1. **平台设备驱动(Platform Driver)**:平台驱动是Linux内核中用于处理特定SoC(System on Chip)上的非标准外设的一种驱动模型。STM32MP135的平台驱动通常包括初始化、注册、注销等操作,它允许开发者针对STM32...

    linux platform tree下驱动模版

    在Linux操作系统中,平台树(platform tree)是设备驱动程序框架的一部分,用于描述硬件设备及其与系统的交互方式。平台驱动模型允许系统启动时自动探测和配置硬件,为开发者提供了一个标准化的方法来编写驱动代码。...

    Linux Platform Device and Driver

    - S3C2410-I2C的`platform_device`是在系统启动时通过`s3c_arch_init()`函数进行注册的,该函数的优先级高于`module_init`,确保在Platform驱动注册之前完成设备注册。 #### 六、总结 Linux Platform Device和...

    S5PV210-Key_Platform.zip

    Platform Bus驱动是Linux内核中用于设备驱动模型的一种机制,它简化了硬件设备与内核之间的交互。 在Linux内核中,设备驱动通常有多种类型,如PCI、SPI、I2C等,而Platform Bus驱动则是针对那些没有特定总线接口...

    linux platform tree下的led驱动程序

    10. **电源管理**:考虑电源效率,LED驱动程序可能需要实现电源管理功能,如在设备待机时关闭LED,以减少功耗。 以上是关于“Linux平台树下的LED驱动程序”涉及的主要知识点。编写这样的驱动程序需要深入理解Linux...

Global site tag (gtag.js) - Google Analytics