VxWorks 设备树API函数和分析

风河驱动在7.0后,也引入了设备树,和linux一样,通过设备树来设置驱动的相关参数信息。通过vxwroks源码分析设备树相关源码。

例1:设备树部分代码:

nandflash@0x30000000

        {

        compatible  = "ti,emif16-nand";

        clocks      = <&internaldiv_6>;

        clock-names = "internaldiv_6";

        chip-select = <0>;

        ale-offset  = <0x2000>;

        cle-offset  = <0x4000>;

        reg = <0x21000a00 0x0000100>,       /@ emif16 control @/

              <0x30000000 0x4000000>;       /@ chip access window @/

        /@ below timing values are in nanoseconds @/

        acr-wsetup  = <8>;        

        acr-wstrobe = <23>;           

        acr-whold   = <8>;

        acr-rsetup  = <9>;   

        acr-rstrobe = <23>;           

        acr-rhold   = <6>;

        acr-ta      = <12>;           

        };

1.1 数据结构

typedef struct vxbFdtDev

    {

    char    name[FDT_NODE_NAME_LEN + 1];

    int     offset;

    } VXB_FDT_DEV;

typedef struct vxbDevList {

    SL_LIST     list;

} VXB_RESOURCE_LIST;

1.2 API函数

1.2.1 vxbFdtDevMatch

函数功能:

此函数将FDT类型的设备与其驱动程序匹配。FDT用“compatible”字符串描述设备。驱动程序有列出支持的设备的表。这个例程将兼容字符串与驱动表进行比较,并返回匹配的兼容字符串的个数。

函数原型:

STATUS vxbFdtDevMatch

    (

       VXB_DEV_ID                  pDev,           /* device to do match */

    const VXB_FDT_DEV_MATCH_ENTRY * pMatchTbl,  /* pointer to match table */

    VXB_FDT_DEV_MATCH_ENTRY ** pMatchedEntry    /* best matched entry */

    )

例2:

LOCAL const VXB_FDT_DEV_MATCH_ENTRY vxbEmif16Match[] =

    {

        {

        "ti,emif16-nand",               /* compatible */

        (void *)NULL

        },

        {}

    };

LOCAL STATUS vxbEmif16Probe    (    VXB_DEV_ID pDev    )

    {

//调用此函数vxbEmif16Match和设备树中compatible  = "ti,emif16-nand";是否匹配

    return vxbFdtDevMatch (pDev, vxbEmif16Match, NULL);

    }

1.2.2 vxbFdtDevGet

函数功能: 获取FDT总线设备信息

函数原型:VXB_FDT_DEV * vxbFdtDevGet

    (

    VXB_DEV_ID pDev                       /* device identifier */

    )

1.2.3 vxbFdtDevSetup

函数功能: 设置FDT总线设备名称和偏移量

函数原型:void vxbFdtDevSetup

    (

    int offset,                     /* device offset */

    VXB_FDT_DEV * pFdtDev           /* pointer to FDT device structure */

    )

1.2.4 vxbFdtIntGet

函数功能:获取设备中断信息,为设备创建中断资源。

函数原型:STATUS vxbFdtIntGet

    (

    VXB_RESOURCE_LIST  * pResList,           /* resource list */

    VXB_FDT_DEV * pFdtDev                    /* FDT device */

    )

1.2.5 vxbFdtIntParentOffsetGetByDev

函数功能: 获取父中断控制器偏移量

函数原型:int vxbFdtIntParentOffsetGetByDev

    (

    VXB_FDT_DEV * pFdtDev

)

1.2.6 vxbFdtIoGet

函数功能: 此函数获取设备I/O信息,并为设备创建IO类型资源。

函数原型: STATUS vxbFdtIoGet

    (

    VXB_RESOURCE_LIST  * pResList,

    VXB_FDT_DEV * pFdtDev

    )

1.2.7 vxbFdtRegGet

函数功能: 这个函数获取设备注册信息,并为设备创建内存/IO类型资源。注意:这个函数只被简单总线用来创建内存/IO资源,fdtBus不应该调用这个例程。

函数原型:STATUS vxbFdtRegGet

    (

    VXB_RESOURCE_LIST  * pResList,           /* resource list */

    VXB_FDT_DEV * pFdtDev                    /* FDT device */

    )

1.2.8 vxbFdtResFree

函数功能: 从资源列表中释放所有资源。

函数原型:void vxbFdtResFree

    (

    VXB_RESOURCE_LIST  * pResList            /* resource list */

    )

1.2.9 vxbFdtUnitAddrGet

函数功能: 返回FDT节点的单位地址字符串;

这个助手函数从FDT设备节点名中获取单元地址字段。设备节点名称可以指定为name@unit-address,其中@字符后面的部分是16进制值。这个函数将解析节点名以找到单元地址字段的开头,以便它可以用作设备路径元素。注意,在VxWorks .dts文件中,单位地址字段的使用有些不一致。理想情况下,这个值应该始终存在,但有时却不是。而且,当它出现时,格式有时会不同。为了避免混淆,尽量返回一个统一的值。

VxWorks对单位地址字段的使用不一致。这些值通常是十六进制的,但格式不同。可以有以下任何一种: device@a000

device@0xa000

device@0000a000

device@0x0000a000

device@0

希望保持一致。最简单的事情是采用使用十六进制值的惯例,没有前导0和0x前缀,因此我们去掉这些字符。

函数原型:char * vxbFdtUnitAddrGet

    (

    UINT32 offset,

    char * name,

    UINT32 len

    )

1.2.10 vxbFdtDevAcquireByOffset

函数功能: 使用VxBus节点的DTB偏移量查找VxBus节点。这个函数在VxBus树中搜索指定DTB 值对应的节点。这个偏移量必须是扁平设备树blob中的设备定义的位置,FDT总线代码使用它在VxBus设备树中创建一个节点。这个函数在核心vxbLib库之外实现,因为FDT在技术上是特定于总线的。(核心VxBus库包含可应用于任何VxBus句柄的泛型例程。这个函数只具有FDT总线的子设备的意义。)使用此函数获取的句柄必须通过vxbDevRelease()释放,以减少其引用计数。

函数原型:VXB_DEV_ID vxbFdtDevAcquireByOffset

    (

    int offset

    )

1.2.11 vxbFdtDevAcquireByPhandle

函数功能: 在VxBus树中查找设备节点的phandle < >指定的设备,它获取对该设备的引用以防止被从树中移除。获得设备节点后,应该使用vxbDevRelease()例程释放对设备节点的引用。

注意:这个API应该只用于这样的情况:一个VxBus节点依赖于树中的另一个节点,而这个节点不容易通过仔细安排设备层次结构来解决。例如,在一些目标上,访问以太网PHY芯片的管理寄存器需要结合MDIO和GPIO寄存器访问。这意味着MDIO驱动程序可能需要向GPIO驱动程序发出请求,为此它需要GPIO设备的句柄。然而,MDIO和GPIO设备通常是兄弟节点,而不是父/子节点,因此,如果没有使用此API,就没有一种简单的方法来引用另一种。

应用程序代码应该避免使用这个API。理想情况下,设备驱动程序应该在附加阶段向应用程序库注册自己(例如,END驱动程序应该调用muxDevLoad()将自己绑定到MUX),而不是库代码试图将自己附加到设备上。

函数原型:VXB_DEV_ID vxbFdtDevAcquireByPhandle

    (

    UINT32      pHandle         /* node property handle (phandle) */

    )

1.2.12 vxbFdtMsiParentParse

函数功能: 为指定的VxBus设备查找MSI父节点,使用MSI -parent属性。msi-parent可以与任何类型的FDT设备一起使用。这个属性的应用方式有一些变化:一个单一的MSI -parent属性可以指定多个phandle,一个给定的MSI -parent模式可以有一个# MSI -cells属性,允许MSI -parent属性包含额外的包含MSI指定符数据的单元格。如果# MSI -cells是0或者不包含,那么MSI -parent属性只包含作为设备的MSI父节点的phandle。同样,任何作为MSI父节点的节点必须包含MSI -controller属性。

这意味着我们必须能够处理以下场景:

简单的si-parent情况:

   msi-parent = <&mii>;

 -简单的msi-parent情况,但带有#msi-cells > 0:

   msi-parent = <&mii 0x1234>;

 -复杂的msi-parent案例中有多个实例:

   msi-parent = <&mii0>, <&mii1>, <&mii2>;

 -复杂的msi-parent情况,带有#msi-cells > 0:  

msi-parent = <&mii0 0x1234>, <&mii1 0x5678>, <&mii2 0x9abc>;

需要注意的是,复杂情况也可以表示为:

   msi-parent = <&mii0 0x1234>;

   msi-parent = <&mii1 0x5678>;

   msi-parent = <&mii2 0x9abc>;

尽管这在语法上是不同的,但它们在功能上是等价的,因为它们在设备树blob中以相同的方式编码。还要注意,该语法允许每个MSI父节点为# MSI -cells定义不同的值。这意味着你可以有这样的东西:

msi-parent = <&mii0 0x1234>;

msi-parent = <&mii1 0x5678 0x9abc>;

在有多个phandl的复杂的si-parent情况下,调用者可以使用参数来选择返回哪个条目(index == 0是第一个)。如果指定了一个不存在的表项(例如index == 1,但只有一个表项),那么将返回一个NULL指针。

函数原型:STATUS vxbFdtMsiParentParse

    (

    VXB_DEV_ID pDev,

    int index,

    VXB_DEV_ID * pMsiParent,

    int * pArgCnt,

    UINT32 ** ppArgs

    )

1.2.13 vxbFdtRidMap

函数功能: FdtRidMap——在VxBus节点上执行RID转换

这是一个helper函数,用于在VxBus设备节点上使用MSI -map或IOMMU -map属性执行请求者ID翻译和IOMMU/MSI父查询。在设备树,某些节点可能包含以下属性:

msi-map / msi-map-mask

iommu-map / iommu-map-mask

由于这两组属性以相同的方式格式化并使用相同的解码规则,所以我们可以使用一个函数来解析它们,尽管结果调用者可能会根据不同的情况进行不同的解析。

总线控制器使用IOMMU -map属性将设备的请求者ID转换为IOMMU隔离说明符,IOMMU隔离说明符用于限制设备执行DMA传输的方式,并提供到树中关联IOMMU设备的链接(通过phandle)。

msi-map属性定义专门为PCI控制器,用于设备的请求ID转化为MSI边带说明符用于限制设备如何实现动态的中断,并提供相关的链接(通过phandle)到一个MSI中断控制器装置内的树。

在一些例子中,总线控制器同时在IOMMU隔离和MSI边带转换中使用IOMMU -map属性。然而,同时使用IOMMU隔离和MSI边带数据的PCI控制器必须同时使用IOMMU -map和MSI -map属性,即使值在很大程度上相同。在这两种情况下,map属性包含4个单元:

- A base requester ID

- A parent phandle

- A base specifier ID (MSI specifier or IOMMU specifier)

- A length (which defines the translation range)

PCI总线的请求者ID是一个16位的字,它对PCI总线进行编码,给定设备的设备和函数号。一个示例msi-map条目看起来像:

Msi-map = <0x0 &msi0 0x110000 0x10000>;

其效果是将前缀0x110000添加到设备的16位中请求ID。

iommu-map属性的rid将取决于应用它的总线。

可以有多个msi-map或iommu-map条目,每个条目仅为总线上的设备子集提供转换。也可能有重叠的地图规则,尽管只有在可能的情况下,两个MSI或IOMMU父母可能服务于同一设备。换句话说,单个节点可以有这样的规则:

Msi-map = <0x0000 &msi_a 0x8000 0x08000>,

<0x8000 &msi_a 0x0000 0x08000>

<0x0000 &msi_b 0x0000 0x10000>;

可以包含一个附加的iommu-map-mask/msi-map-mask属性,以屏蔽指示符值中ORing之前的请求者ID中的位。请注意,虽然可以有多个映射属性,但只能有一个map-mask属性。因此,相同的map-mask值应用于所有map条目。

函数原型:STATUS vxbFdtRidMap

    (

    VXB_DEV_ID pDev,

    int index,

    VXB_DEV_ID * pMsiParent,

    char * pPropName,

    char * pPropMaskName,

    UINT32 ridIn,

    UINT32 * ridOut

    )

1.2.14 vxbFdtBusIoctl

函数功能: fdtBus设备的ioctl方法

函数原型:STATUS vxbFdtBusIoctl

    (

    VXB_DEV_ID  pDev, /* FDT bus device */

    int cmd,          /* ioctl commands for FDT bus device */

    void * pArg       /* command parameter for FDT bus device */

    )

1.2.15 vxbFdtChildScan

函数功能: 扫描子设备

函数原型:STATUS vxbFdtChildScan

    (

    VXB_DEV_ID pDev              /* device to scan */

    )

1.2.16 vxFdtPropGet

函数功能: 获取给定属性的值;在offset nodeoffset处获取一个指向节点名为'pPropName'属性值的指针。

函数原型:const void * vxFdtPropGet

    (

    int     offset,     /* node offset */

    char *  pPropName,  /* contains property name */

    int *   pLen        /* on return, contains length, in bytes, */

                        /* of property value */

    )

pVal = vxFdtPropGet (pFdtDev->offset, "data-scl-frequency", NULL);

1.2.17 vxFdtFirstPropGet

函数功能: 获取节点的第一个属性及其名称。

函数原型:const void * vxFdtFirstPropGet

    (

    int             offset,     /* node offset */

    char **         pPropName,  /* property name */

    int *           pLen,       /* length of property value */

    int *           propOffset  /* new property offset */

    )

1.2.18 vxFdtNextPropGet

函数功能: 根据当前提供的节点获取指向节点下一个属性的指针。

函数原型:const void * vxFdtNextPropGet

    (

    int             offset,     /* property offset */

    char **         pPropName,  /* property name */

    int *           pLen,       /* length of property value */

    int *           propOffset  /* new property offset */

    )

1.2.19 vxFdtGetName

函数功能: 返回一个指向结构块offset 处的设备树节点的名称(包括unit地址)的指针。如果非null,则通过更新所指向的整数值来返回该名称的长度。

函数原型:const void * vxFdtGetName

    (

    int    offset, /* node offset */

    int *  pLen    /* location to update length, in bytes, of name */

    )

1.2.20 vxFdtIsEnabled

函数功能: 当节点被启用或“status”属性不存在时,这个函数将FDT节点状态返回TRUE,否则返回FALSE。

函数原型:BOOL vxFdtIsEnabled

    (

    int offset     /* node offset */

    )

主要判断status=“okay”还是“disabled”

if (vxFdtIsEnabled (offset) == FALSE) go err;

1.2.21 vxFdtNodeOffsetByPhandle

函数功能: 获取具有给定值的节点的偏移量。如果在给定(无效树)的树中有多个节点,则结果是未定义的。

函数原型:int vxFdtNodeOffsetByPhandle

    (

    UINT32  phandle  / node property handle (phandle) /

    )

phyOffset = vxFdtNodeOffsetByPhandle (phandle);

1.2.22 vxFdtNodeOffsetByCompatible

函数功能: 查找具有给定'compatible'值的节点; 例程返回之后第一个节点的偏移量,该节点有一个名为'compatible'的属性,其值匹配给定的字符串;或者如果 = -1,表示树中第一个匹配的节点。

如果成功,返回结构块偏移量。

-FDT_ERR_BADOFFSET如果没有找到或兼容是NULL

-FDT_ERR_INTERNAL如果FDT库内部错误

函数原型:int vxFdtNodeOffsetByCompatible

    (

    int startoffset,  /* starting node offset */

    char *compatible  /* node compatibility string */

    )

  offset = vxFdtNodeOffsetByCompatible (0, "fsl,ls2-isc");

isc: isc@1f70000

      {

            compatible = "fsl,ls2-isc";

            reg = <0x0 0x1f70000 0x0 0x10000>;

            };

1.2.23 vxFdtNodeCheckCompatible

函数功能: 检查节点的compatible属性;返回一个指示,表明对于指定的节点,存在一个名为'compatible'的属性,其值与给定的字符串匹配。返回:0当兼容性匹配,1当不匹配,和-FDT_ERR_INTERNAL如果FDT库内部错误。

函数原型:int vxFdtNodeCheckCompatible

    (

    int   offset,          /* node's offset */

    char *compatible       /* compatibility string */

    )

   if ((vxFdtNodeCheckCompatible (pFdtDev->offset, "vxsim,intc")) == 0)
intc: interrupt-controller@0 {

       compatible = "vxsim,intc";

       interrupt-controller;

        #interrupt-cells = <1>;

       };

1.2.24 vxFdtCellGet

函数功能: 获取寄存器cell大小

函数原型:STATUS vxFdtCellGet

    (

    int  offset,     /* node offset */

    int *pAdrsCell,  /* on return, contains register address cell */

    int *pSizeCell   /* on return, contains register size cell */

    )

ret = vxFdtCellGet (parOffset, &addressCells, &sizeCells);

  DEBUG_MSG ("vxFdtCellGet addressCells = %d, sizeCells = %d\n",   addressCells, sizeCells);

1.2.25 vxFdtDefRegGet

函数功能: 找到DTB的注册bar

函数原型:STATUS vxFdtDefRegGet

    (

    int          offset,      /* start node offset */

    UINT32       barIndx,     /* bar index */

    PHYS_ADDR *  pRegBarAddr, /* on return, contains register address */

    size_t *     pRegBarSize  /* on return, contains register size, in bytes */

    )

if (vxFdtDefRegGet (offset, 0, &phyAddr, &len) != OK)

   {

    phyAddr = (PHYS_ADDR)NULL;

    DEBUG_MSG ("%s: get fsl,kinetis-sio BAR failed.\n",__FUNCTION__);

    }

1.2.26 vxFdtStdoutGet

函数功能: 获取stdout节点ID

函数原型:int vxFdtStdoutGet(void)

//主要判断stdout-path属性

prop = (char *) fdt_getprop (gpDtb, offset, "stdout-path", &propLen);

chosen

 {

 stdout-path = "serial0";

   };

1.2.27 vxFdtPhysMemInfoGet

函数功能: 从DTB获取物理内存信息;获取物理内存信息,并使用不超过的物理内存描述符初始化表。

注意:1. 每个物理内存的起始地址必须与ARCH所需的TLB页大小对齐;

2. 内核映像必须位于第一个物理内存描述符中;注意,这个例程只能在EarlyInit()中使用。

函数原型:int vxFdtPhysMemInfoGet

    (

    PHYS_MEM_DESC * pPhysMemDesc, /* address contains mem descriptor on return */

    int   physMemDescNum,  /* maximum number of memory descriptors to get */

    UINT  uState           /* memory attributes (state) */

    )

regNum = vxFdtPhysMemInfoGet (pPhysMemDesc, physMemDescNum, uState);

memory@80000000

        {

        device_type = "memory";

        reg = <0x0 0x80000000 0x0 0x7be00000>,

              <0x20 0x80000000 0x0 0x80000000>;

        };

    };

1.2.28 vxFdtBootargsGet

函数功能: 从DTB获取boottargs

函数原型:STATUS vxFdtBootargsGet

    (

    char   pString,     / where to copy bootargs /

    int     strLen       / maximum number of bytes to copy /

    )

if (vxFdtBootargsGet ((char *)BOOT_LINE_ADRS, BOOT_LINE_SIZE) != OK)

chosen

{

bootargs = "enet(0,0)host:vxWorks h=192.168.0.2 e=192.168.0.3:ffffff00 g=192.168.0.1 u=target pw=vxTarget";

 };

1.2.29 vxFdtDtbAddressGet

函数功能: 返回全局DTB虚拟地址

函数原型:void  vxFdtDtbAddressGet(void)

gpDtb = vxFdtDtbAddressGet();

 offset = fdt_path_offset (gpDtb, "/chosen/i8253Config");

1.2.30 vxFdtCtrlNumGet

函数功能: 返回DTS中启用的控制器的编号

函数原型:int vxFdtCtrlNumGet(char  compatName)

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值