NotePublic/Software/Development/OperatingSystem/Linux/Kernel/Modules/DeviceTree/DeviceTree.md

29 KiB
Raw Blame History

Device Tree

设备树的起源

linux 2.6 及之前,大量板级信息被硬编码到内核里,十分庞大,大量代码冗余。

linux 2.6 之后,引入了设备树。设备树源于 OpenFirmware描述硬件的数据结构。由一些列节点node和属性property组成通常包括下列信息

  • CPU 数量和类别
  • 内存基地址和大小
  • 总线和桥
  • 外设连接
  • 中断控制器和中断使用情况
  • GPIO 控制器和 GPIO 使用情况
  • 时钟控制器和时钟使用情况

本质上是画一棵 CPU、总线、设备组成的树Linux 内核会把设备树展开成 platform_device、i2c_client、spi_device 等设备,而这些设备用到的内存、中断等资源,也会传递个内核,内核会将这些资源绑定给展开的相应设备。

DTSI/DTS/DTC/DTB

dtsi可被 #include 的设备树源文件;

dts设备树源文件

dtc编译 dts 和 dtsi 后得到的设备树文件dts 及 dtsi 中的内容被组合或覆盖该文件为源码形式Linux 内核无法识别;

dtb编译 dtc 后得到的二进制设备树文件Linux 内核可加载和识别其中的内容。

如果谋 dts 文件引用了谋 dtsi 文件,可以在 dts 中覆盖 dtsi 中的部分内容。

DTS 语法

设备树包含一个根节点和多个子节点,如果在 dts/dtsi 文件中写了多个根节点,则在编译后被组合成一个根节点。子节点可嵌套。 节点会被展开为 device其 compatible 属性用于与 driver 的 compatible 属性项匹配,如果匹配成功则调用该 driver 的 probe 函数。

DTS 中使用“//”进行行注释或“/**/”进行块注释。

节点

节点使用:

[label]:<name>[@<unit-address>] {}

的格式来定义。挂到内存空间的设备,其 unit-address 一般是内存地址。别的地方可以通过“&label”来引用该节点。

属性

属性必须包含在节点中,使用:

<property-name>=<value>

来定义。属性值可以为整数或字符串。如果为整数则用“<>”括起来,“<>”中可以有多个单元,称为 cellcell 间使用空格隔开,不同的 cell 可以有不同的含义。字符串使用英文双引号括起来。同一属性的多个值可以使用英文“,”进行分割,例如:

reg = <0 0x00000000 0x04000000>,
      <1 0x00000000 0x04000000>;

标准属性

compatible

“compatible”属性通常用来 device 和 driver 的适配推荐的格式为”manufacturer,model”。

Value type: stringlist

Example:

compatible = "fsl,mpc8641", "ns16550";

model

“model”属性只是简单的表示型号root 节点用其来传递值给 machine_desc_str。

Value type: stringlist

Example:

model = "fsl,MPC8349EMITX";

phandle

“phandle”属性通用一个唯一的 id 来标识一个 Node在 property 可以使用这个 id 来引用 Node。

Value type: u32

Example:

pic@10000000 {
    phandle = <1>;
    interrupt-controller;
};

another-device-node {
    interrupt-parent = <1>;
};

在 DeviceTree 中通过另一种方式进行 phandle 的定义和引用更加常见:

  • 定义一个“label”来引用Node在编译是系统会自动为node生成一个phandle属性。
  • 使用”&”来引用“label”即是引用phandle。

ranges

“ranges”属性用来做当前 node 和父 node 之间的地址映射,格式为(child-bus-address, parentbus-address, length)。其中 child-bus-address 的解析长度受当前 node 的 #address-cells 属性控制parentbus-address 的解析长度受父 node 的 #address-cells 属性控制 length 的解析长度受当前 node 的 #size-cells 属性控制。

Value type: empty or prop-encoded-array encoded as an arbitrary number of (child-bus-address, parentbus-address, length) triplets.

Example:

soc {
    compatible = "simple-bus";
    #address-cells = <1>;
    #size-cells = <1>;
    ranges = <0x0 0xe0000000 0x00100000>;
    serial {
        device_type = "serial";
        compatible = "ns16550";
        reg = <0x4600 0x100>;
        clock-frequency = <0>;
        interrupts = <0xA 0x8>;
        interrupt-parent = <&ipic>;
    };
};

The soc node specifies a ranges property of <0x0 0xe0000000 0x00100000>;

This property value specifies that for an 1024KB range of address space, a child node addressed at physical 0x0 maps to a parent address of physical 0xe0000000. With this mapping, the serial device node can be addressed by a load or store at address 0xe0004600, an offset of 0x4600 (specified in reg) plus the 0xe0000000 mapping specified in ranges.

reg 属性和 address-cells、size-cells

子节点的“reg”属性用于标记 iomem由“address”字段和“size”字段构成

reg = <address1 size1 [address2 size2] [address3 size3]...>;

属性“#address-cells”描述了子节点的“reg”属性的“address”字段为几个 32bit 的整型数据。

属性“#size-cells”描述了子节点的“reg”属性的“size”字段为几个 32bit 整型数据,如果为 0则没有 lenth 字段。

interrupt

  • interrutt-controller属性为空表明“我是中断控制器”
  • #interrupt-cells表明连接此中断控制器的设备的中断属性的 cell 大小,也就是 interrupt = <> 属性的 cell 大小;
  • interrupt-parent设备节点通过这个关键字指定其依附的中断控制器 phandle如果没有指定则继承父节点的 interrupt-parent 配置;
  • interrupt设备节点里使用一般包含中断号、触发方法等。具体有多少个 cell由 #interrupt-cells 决定,每个 cell 的具体含义,一般由驱动决定。

多个中断可以用 interrupts 描述。interrupts 属性后面,会有不同的参数,有时是两个,有时是三个。

两个的时候一般是这样出现:

interrupt-parent = <&gpio2>;
interrupts = <29 0>;

一般这样表明:中断控制器是 GPIO2然后使用它的 29 号中断。(这里的 29 号,就是指 29 号引脚)0 是指触发的方式(上升沿、下降沿等)。

三个的时候一般是这样出现:

interrupts = <0 37 1>;
interrupts = <GIC_SPI 37 1>;
interrupts = <GIC_PPI 37 1>;

第一个参数表示是 IPI、PPI、SPI、SGI 其中的一个。第二个参数表示:是第一个参数里面的第几个。第三个参数表示:中断触发的类型(上升沿、下降沿等)。

IPI、PPI、SPI、SGI 是 ARM 规范的中断,含义如下:

  • IPIinter-processer interrupt 中断号015
  • PPIper processor interrupts 中断号1631
  • SPIshared processor interrupts 中断号 32 32+224
  • SGIsoftware generated interrupts (SGI).

中断类型的值如下:

#define IRQ_TYPE_NONE           0
#define IRQ_TYPE_EDGE_RISING    1
#define IRQ_TYPE_EDGE_FALLING   2
#define IRQ_TYPE_EDGE_BOTH      (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH     4
#define IRQ_TYPE_LEVEL_LOW      8

标准节点

Root

aliases

memory

chosen

cpus

// TODO: http://kernel.meizu.com/device-tree.htmlhttps://blog.csdn.net/21cnbao/article/details/8457546https://www.jianshu.com/p/923b380366bb

DTS 示例

一个简单的 dts 文件示例如下:

/ {
     compatible = "acme,coyotes-rev"
     #address-cells = <1>;  // 描述下一级子节点的数据属性
     #size-cells = <1>;
     interrupt-parent = <&intc>;

     cpus {
       #address-cells = <1>;
       #size-cells = <0>;
       cpu@0 {
         compatible = "arm,cortex-a9";   // device兼容性用于与driver匹配
         reg = <0>;
       };
       cpu@1 {
         compatible = "arm,cortex-a9";
         reg = <1>;
       };
    };

    serial@101f0000 {        // 地址
      compatible = "arm,pl011";
       reg = <0x101f0000 0x1000 >;
      interrupts = < 1 0 >;
     };

    serial@101f2000 {
      compatible = "arm,pl011";
       reg = <0x101f2000 0x1000 >;
      interrupts = < 2 0 >;
    };

    gpio@101f3000 {
      compatible = "arm,pl061";
      reg = <0x101f3000 0x1000
      0x101f4000 0x0010>;
      interrupts = < 3 0 >;
    };

     intc: interrupt-controller@10140000 {
      compatible = "arm,pl190";
       reg = <0x10140000 0x1000 >;
      interrupt-controller;
      #interrupt-cells = <2>;
    };

    spi@10115000 {
      compatible = "arm,pl022";
      reg = <0x10115000 0x1000 >;
      interrupts = < 4 0 >;50
    };

    external-bus {
      #address-cells = <2>
      #size-cells = <1>;
      ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
            1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
            2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash

      ethernet@0,0 {
        compatible = "smc,smc91c111";
        reg = <0 0 0x1000>;
        interrupts = < 5 2 >;
      };

      i2c@1,0 {
        compatible = "acme,a1234-i2c-bus";
        #address-cells = <1>;
        #size-cells = <0>;
        reg = <1 0 0x1000>;
        interrupts = < 6 2 >;
        rtc@58 {
          compatible = "maxim,ds1338";
          reg = <58>;
          interrupts = < 7 3 >;
        };
     };

     flash@2,0 {
       compatible = "samsung,k8f1315ebm", "cfi-flash";
       reg = <2 0 0x4000000>;
     };
   };// end of external-bus
};

Device Tree 的解析

device 包含 “of_node” 属性其类型为“struct device_node*”,通过 dev_of_node(device) 可获得该 of_node。of_node 代表了该设备在设备树中所对应的节点。各 driver 可以使用内核 API 结合 of_node 属性自行解析设备树中对应的资源。

device_node 结构体

Linux 内核中使用 device_node 结构体来描述一个节点,此结构体定义在文件 include/linux/of.h 中,定义如下:

struct device_node {
    const char *name;           /* 节点名字 */
    const char *type;           /* 设备类型 */
    phandle phandle;
    const char *full_name;      /* 节点全名 */
    struct fwnode_handle fnode;

    struct property *properties; /* 属性 */
    struct property *deadprops;  /* removes 属性 */
    struct device_node *parend;  /* 父节点 */
    struct device_node *child;   /* 子节点 */
    struct device_node *sibling;
    struct kobject kobj;
    ...
};

property 结构体

Linux 内核中使用 struct property 结构体来表示属性,定义如下:

struct property {
    char *name; //属性名字
    int length; //属性长度
    void *value; //属性值
    struct property *next;//下一个属性
    unsigned long _flags;
    unsigned int unique_id;
    struct bin_attribute attr;
};

常用 OF 函数

of_find_node_by_name 函数

头文件:

#include <linux/of.h>

函数原型:

struct device_node *of_find_node_by_name(struct device_node *from, const char *name);

说明:

通过节点名字查找指定的节点。

参数:

from开始查找的节点如果为 NULL 表示从根节点开始查找整个设备树;

name要查找的节点名字。

返回值:

成功则返回找到的节点,失败返回 NULL。

of_find_node_by_type 函数

头文件:

#include <linux/of.h>

函数原型:

struct device_node *of_find_node_by_type(struct device_node *from, const char *type);

说明:

通过 device_type 属性查找指定的节点。

参数:

from开始查找的节点如果为 NULL 表示从根节点开始查找整个设备树;

type要查找的节点对应的字符串也就是 device_type 属性值。

返回值:

成功则返回找到的节点,失败返回 NULL。

of_find_compatible_node 函数

头文件:

#include <linux/of.h>

函数原型:

struct device_node *of_find_compatible_node(struct device_node *from, const struct of_device_id *matches, const struct of_device_id **match);

说明:

根据 device_type 和 compatible 这两个属性查找指定的节点。

参数:

from开始查找的节点如果为 NULL 表示从根节点开始查找整个设备树;

matchesof_device_id 匹配表,也就是在此匹配表里面查找节点;

match找到的匹配的 of_device_id。

返回值:

成功则返回找到的节点,失败返回 NULL。

of_find_matching_node 函数

头文件:

#include <linux/of.h>

函数原型:

struct device_node *of_find_matching_node(struct device_node *from, const struct of_device_id *matches);

说明:

通过 compatible 属性查找指定节点。

参数:

from指向开始路径的节点如果为NULL则从根节点开始 matches指向设备ID表注意ID表必须以NULL结束。

返回值:

成功:得到节点的首地址;

失败NULL。

of_find_node_by_path 函数

头文件:

#include <linux/of.h>

函数原型:

inline struct device_node *of_find_node_by_path(const char *path);

说明:

通过路径来查找指定的节点。

参数:

path带有全路径的节点名。

返回值:

成功则返回找到的节点,失败返回 NULL。

of_get_parent 函数

头文件:

#include <linux/of.h>

函数原型:

struct device_node *of_get_parent(const struct device_node *node);

说明:

用于获取指定节点的父节点(如果有父节点的话)。

参数:

node子节点。

返回值:

成功则返回找到的父节点,失败返回 NULL。

of_get_next_child 函数

头文件:

#include <linux/of.h>

函数原型:

struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev);

说明:

查找谋节点的子节点。

参数:

node父节点

prev前一个子节点也就是从哪一个子节点开始的下一个子节点如果为 NULL 表示从第一个子节点开始。

返回值:

成功则返回找到的下一个子节点,失败返回 NULL。

of_find_property 函数

头文件:

#include <linux/of.h>

函数原型:

struct property *of_find_property(const struct device_node *np, const char *name, int *lenp);

说明:

通过属性名称查找指定的属性

参数:

np设备节点

name属性名字

lenp返回属性值的字节数。

返回值:

成功则返回找到的属性,失败返回 NULL。

of_get_property 函数

头文件:

#include <linux/of.h>

函数原型:

const void *of_get_property(const struct device_node *np, const char *name, int *lenp);

说明:

是 of_find_property 函数的扩展,直接返回 property 的 value 属性。

参数:

np设备节点

name属性名字

lenp返回属性值的字节数。

返回值:

成功则返回找到的 value失败返回 NULL。

of_property_count_elems_of_size 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_count_elems_of_size(const struct device_node *np, const char *propname int elem_size);

说明:

用于获取属性中元素的数量,比如 reg 属性值是一个数组,那么使用此函数可以获取到这个数组的大小。

参数:

np设备节点

proname需要统计元素数量的属性名字

elem_size元素长度。

返回值:

得到的属性元素数量。

of_property_read_u32_index 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u32_index(const struct device_node *np,
                               const char *propname,
                               u32 index,
                               u32 *out_value);

说明:

用于从属性中获取指定标号的 u32 类型数据值(无符号 32 位),比如某个属性有多个 u32 类型的值,那么就可以使用此函数来获取指定标号的数据值。

参数:

np设备节点

proname要读取的属性名字

index要读取的值标号

out_value读取到的值。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u8 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u8(const struct device_node *np,
                        const char *propname,
                        u8 *out_value);

说明:

用于读取属性只有一个 u8 数据的值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u16 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u16(const struct device_node *np,
                        const char *propname,
                        u16 *out_value);

说明:

用于读取属性只有一个 u16 数据的值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u32 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u32(const struct device_node *np,
                        const char *propname,
                        u32 *out_value);

说明:

用于读取属性只有一个 u32 数据的值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u64 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u64(const struct device_node *np,
                        const char *propname,
                        u64 *out_value);

说明:

用于读取属性只有一个 u64 数据的值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u8_array 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u8_array(const struct device_node *np,
                                const char *propname,
                                u8 *out_values,
                                size_t sz);

说明:

以 u8 数组形式读取属性值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值

sz要读取的数组元素数量。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u16_array 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u16_array(const struct device_node *np,
                                const char *propname,
                                u16 *out_values,
                                size_t sz);

说明:

以 u16 数组形式读取属性值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值

sz要读取的数组元素数量。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u32_array 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u32_array(const struct device_node *np,
                                const char *propname,
                                u32 *out_values,
                                size_t sz);

说明:

以 u32 数组形式读取属性值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值

sz要读取的数组元素数量。

返回值:

0读取成功

负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_u64_array 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_u64_array(const struct device_node *np,
                                const char *propname,
                                u64 *out_values,
                                size_t sz);

说明:

以 u64 数组形式读取属性值。

参数:

np设备节点

proname要读取的属性名字

out_value读取到的数组值

sz要读取的数组元素数量。

返回值:

0读取成功

负值:读取失败,-EINVAL 表示属性不存在。-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。

of_property_read_string 函数

头文件:

#include <linux/of.h>

函数原型:

int of_property_read_string(struct device_node *np,
                            const char *propname,
                            const char **out_string);

说明:

用于读取属性中字符串值。

参数:

np设备节点

proname要读取的属性名字

out_string读取到的字符串值。

返回值:

0读取成功

负值:读取失败。

of_property_read_bool 函数

头文件:

#include <linux/of.h>

函数原型:

static inline bool of_property_read_bool(const struct device_node *np,
                                         const char *propname);

说明:

用于读取属性中布尔类型数据的值。

参数:

np设备节点

proname要读取的属性名字。

返回值:

属性存在则返回 true否则返回 false。

of_n_addr_cells 函数

头文件:

#include <linux/of.h>

函数原型:

int of_n_addr_cells(struct device_node *np);

说明:

用于获取“#address-cells“属性值。

参数:

np设备节点。

返回值:

获取到的“#address-cells”属性值。

of_n_size_cells 函数

头文件:

#include <linux/of.h>

函数原型:

int of_n_size_cells(struct device_node *np);

说明:

用于获取“#size-cells“属性值。

参数:

np设备节点。

返回值:

获取到的“#size-cells”属性值。

of_device_is_compatible 函数

头文件:

#include <linux/of.h>

函数原型:

int of_device_is_compatible(const struct device_node *device,
                            const char *compat);

说明:

用于查看节点的 compatible 属性是否有包含 compat 指定的字符串,也就是检查设备节点的兼容性。

参数:

device设备节点

compat要查看的字符串。

返回值:

0节点的 compatible 属性中不包含 compat 指定的字符串;

正数:节点的 compatible 属性中包含 compat 指定的字符串。

of_get_address 函数

头文件:

#include <linux/of_address.h>

函数原型:

const __be32 *of_get_address(struct device_node *dev,
                            int index,
                            u64 *size,
                            unsigned int *flags);

说明:

用于获取地址相关属性主要是“reg”或者“assigned-addresses”属性值。

参数:

dev设备节点

index要读取的地址标号

size地址长度

flags参数比如 IORESOURCE_IO、IORESOURCE_MEM 等。

返回值:

成功则返回读取到的地址数据首地址,失败返回 NULL。

of_translate_address 函数

头文件:

#include <linux/of_address.h>

函数原型:

u64 of_translate_address(struct device_node *dev,const __be32 *in_addr);

说明:

将从设备树读取到的地址转换为物理地址。

参数:

dev设备节点

in_addr要转换的地址。

返回值:

成功则返回转换得到的物理地址,失败返回 OF_BAD_ADDR。

of_address_to_resource 函数

头文件:

#include <linux/of_address.h>

函数原型:

int of_address_to_resource(struct device_node *dev,
                            int index,
                            struct resource *r);

说明:

根据索引号从设备树中获取“reg”这一类的地址资源。

参数:

dev设备节点

index地址资源索引号

r得到的 resource 类型的资源值。

返回值:

0成功

负值:失败。

of_iomap 函数

头文件:

#include <linux/of_address.h>

函数原型:

void __iomem *of_iomap(struct device_node *np, int index);

说明:

通过设备结点的“reg”字段直接进行设备内存区间的 ioremap()。

参数:

np设备节点

indexreg 属性中要完成内存映射的段,如果 reg 属性只有一段的话 index 就设置为 0。

返回值:

成功则返回经过内存映射后的虚拟内存首地址,失败返回 NULL。

of_io_request_and_map 函数

头文件:

#include <linux/of_address.h>

函数原型:

void __iomem *of_io_request_and_map(struct device_node *np, int index, const char *name);

说明:

提取 I/O 口地址并申请 I/O 资源及映射成虚拟地址。

参数:

np设备节点

indexreg 属性中要完成内存映射的段,如果 reg 属性只有一段的话 index 就设置为 0

name设备名申请 I/O 地址时使用。

返回值:

成功:映射好虚拟地址;

失败NULL

of_get_named_gpio 函数

头文件:

#include <linux/of_gpio.h>

函数原型:

int of_get_named_gpio(struct device_node *np, const char *propname, int index);

说明:

从设备树中提取gpio口。

参数:

dev设备节点

propname属性名

indexgpio 口引脚标号。

返回值:

成功:得到 GPIO 口编号;

失败:负数,绝对值是错误码。

irq_of_parse_and_map 函数

头文件:

#include <linux/of_irq.h>

函数原型:

unsigned int irq_of_parse_and_map(struct device_node *node, int index);

说明:

从设备树的 interrupt 字段解析出中断号,如果有多个中断则通过 index 来指定。

参数:

node设备节点

index用于指定要解析中断的段如果只有一段的话就设置为 0。

返回值:

成功则返回解析的中断号,失败返回 0。

of_irq_count 函数

头文件:

#include <linux/of_irq.h>

函数原型:

int of_irq_count(struct device_node *np);

说明:

从设备树中提取中断的数量。

参数:

np设备节点。

返回值:

成功大于等于0实际中断数量

0表示没有中断。

of_irq_get 函数

头文件:

#include <linux/of_irq.h>

函数原型:

int of_irq_get(struct device_node *np, int index);

说明:

从设备树中提取中断号。

参数:

np设备节点

index要提取的中断号的标号。

返回值:

成功:中断号;

失败:负数,其绝对值是错误码。

of_get_mac_address 函数

头文件:

#include <linux/of_net.h>

函数原型:

void *of_get_mac_address(struct device_node *np);

说明:

从设备树中提取 MAC 地址。

参数:

np设备节点

返回值:

成功MAC6字节的首地址

失败NULL。

of_find_device_by_node 函数

头文件:

#include <linux/of_platform.h>

函数原型:

struct platform_device *of_find_device_by_node(struct device_node *np);

说明:

获取与节点对应的 platform_device。

参数:

node设备节点。

返回值:

成功则返回 platform_device 指针,失败返回 NULL。