设备树节点转换为设备节点device_node、和平台设备资源platform_device

1、_dtb转换为device_node

在dts文件里,每个大括号{ }代表一个节点,比如根节点里有个大括号,对应一个device_node结构体;

memory也有一个大括号,也对应一个device_node结构体。

节点里面有各种属性,也可能里面还有子节点,所以它们还有一些父子关系。

根节点下的memory、chosen、led等节点是并列关系,兄弟关系。对于父子关系、兄弟关系,在device_node结构体里面肯定有成员来描述这些关系


struct device_node {
            const char *name;  // 来自节点中的name属性, 如果没有该属性, 则设为"NULL"
            const char *type;  // 来自节点中的device_type属性, 如果没有该属性, 则设为"NULL"
            phandle phandle;
            const char *full_name;  // 节点的名字, node-name[@unit-address]
            struct fwnode_handle fwnode;

            struct  property *properties;  // 节点的属性
            struct  property *deadprops;    /* removed properties */
            struct  device_node *parent;   // 节点的父亲
            struct  device_node *child;    // 节点的孩子(子节点)

            struct  device_node *sibling;  // 节点的兄弟(同级节点)
        #if defined(CONFIG_OF_KOBJ)
            struct  kobject kobj;
        #endif
            unsigned long _flags;
            void    *data;
        #if defined(CONFIG_SPARC)
            const char *path_component_name;
            unsigned int unique_id;
            struct of_irq_controller *irq_trans;
        #endif
        };


device_node结构体表示一个节点,property结构体表示节点的具体属性。


properties结构体的定义如下:
```c
        struct property {
            char    *name;    // 属性名字, 指向dtb文件中的字符串 例如reg  interrupts
            int length;       // 属性值的长度
            void    *value;   // 属性值, 指向dtb文件中value所在位置, 数据仍以big endian存储
            struct property *next;
        #if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
            unsigned long _flags;
        #endif
        #if defined(CONFIG_OF_PROMTREE)
            unsigned int unique_id;
        #endif
        #if defined(CONFIG_OF_KOBJ)
            struct bin_attribute attr;
        #endif
        };


2、_device_node转换为platform_device

a. 内核函数of_platform_default_populate_init, 遍历device_node树, 生成platform_device
b. 并非所有的device_node都会转换为platform_device只有以下的device_node会转换:

  • 该节点必须含有compatible属性
  • 根节点的子节点(节点必须含有compatible属性)
  • 含有特殊compatible属性的节点的子节点(子节点必须含有compatible属性)这些特殊的compatilbe属性为: “simple-bus”,“simple-  mfd”,“isa”,"arm,amba-bus "
  • 根节点是例外的,生成platfrom_device时,即使有compatible属性也不会处理

注意:i2c, spi等总线节点会转换为platform_device,但是,spi、i2c下的子节点无论compatilbe是否为: “simple-bus”,“simple-  mfd”,“isa”,"arm,amba-bus "都应该交给对应的总线驱动程序来处理而不会被转换为platform_device

举例:

/ {
          mytest {  //根节点下的子节点并且包含compatile,因此可以转换为platform_device

              compatile = "mytest", "simple-bus";

              mytest@0 {  //该节点不属于根节点的子节点,因此不会转换为platform_device
                    compatile = "mytest_0";  
              };
          };
          
          i2c { //根节点下的子节点并且包含compatile,因此可以转换为platform_device
              compatile = "samsung,i2c";

              at24c02 {   //不属于根节点的子节点,并且还是i2c的子节点,一般交给i2c驱动转换为i2c_client
                    compatile = "at24c02";                      
              };
          };

          spi {  //根节点下的子节点并且包含compatile,因此可以转换为platform_device
              compatile = "samsung,spi";     
         
              flash@0 {   //不属于根节点的子节点,并且还是spi的子节点,一般交给spi驱动转换为spi_device
                    compatible = "winbond,w25q32dw";
                    spi-max-frequency = <25000000>;
                    reg = <0>;
                  };
          };
      };
  1. platform_device中含有resource数组, 它来自device_node的reg, interrupts属性; 可以通过platform_get_resource等平台API获取资源
  2. platform_device.dev.of_node指向device_node, 可以通过它获得其他属性

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`of_device_id`结构体中的`data`字段是一个指向与设备相关的数据的指针,通常用于在驱动程序中访问设备树节点属性。在设备树中,每个节点都有一个属性列表,驱动程序可以使用`of_device`结构体中的`dev.of_node`成员指针来获取该节点的属性,然后进行相应的操作。 例如,假设我们有一个名为`my-device`的设备节点,其属性列表中包含一个名为`my-property`的属性,我们可以先在`of_device_id`结构体中定义一个与之对应的数据结构: ```c struct my_device_data { int my_property; }; ``` 然后,在驱动程序初始化时,我们可以将这个数据结构指定为`of_device_id`结构体的`data`字段: ```c static const struct of_device_id my_driver_of_match[] = { { .compatible = "my-device", .data = &my_device_data }, { /* end of list */ }, }; ``` 接着,在驱动程序的`probe()`函数中,我们可以通过`of_device`结构体中的`dev.of_node`成员指针获取设备节点的属性,并将其保存到之前定义的数据结构中: ```c static int my_driver_probe(struct platform_device *pdev) { struct my_device_data *data; struct device_node *np = pdev->dev.of_node; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; of_property_read_u32(np, "my-property", &data->my_property); /* do something with my-property value */ return 0; } ``` 在上面的例子中,`of_property_read_u32()`函数用于从设备节点的属性列表中读取`my-property`属性,并将其保存到`my_device_data`结构体中的`my_property`字段中。这样,我们就可以在驱动程序中访问设备树中的节点属性,并按需进行相应的操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值