device_node转换为platform_device

Posted -glb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了device_node转换为platform_device相关的知识,希望对你有一定的参考价值。

以前在写驱动程序的时候,需要把驱动分为平台device和平台driver两部分。在平台device中会放入硬件所使用的资源,使用C代码来指定platform_device,当需要修改硬件资源时,比如说想去修改led的引脚时,需要重新修改C文件,重新编译内核。再后来我们使用了设备树,可以在设备树中指定硬件资源。设备树是dts文件,它会转换成dtb文件,最终给内核使用。内核会来解析dtb文件得到一系列的device_node,现在终于来到了最后一步,将device_node转换成platform_device.

在分析如何转换之前,先来看下面的两个问题。

1、哪些device_node可以转换成platform_device?

根节点也会对应一个device_node,它并不对应什么设备,也就是说不对应什么硬件,因此根节点对应的device_node应该不会转换成platform_device。

再看一下memory,它虽然是一个硬件,但是我们并不需要什么驱动程序。内存所对应的device_node应该不会转换成platform_device

再看一些chosen,它只是用来设置一些运行时的信息,它并不对应真实的硬件,它也不应该转换成platform_device.

因此,并非所有的device_node都会转换为platform_device。 只有以下的device_node会转换:

1.1 该节点必须含有compatible属性

1.2 根节点的子节点(节点必须含有compatible属性)

1.3 含有特殊compatible属性的节点的子节点(子节点必须含有compatible属性):

  这些特殊的compatilbe属性为: "simple-bus","simple-mfd","isa","arm,amba-bus"

1.4 比如以下的节点,
/mytest会被转换为platform_device,
因为它兼容"simple-bus", 它的子节点/mytest/mytest@0 也会被转换为platform_device

/i2c节点一般表示i2c控制器, 它会被转换为platform_device, 在内核中有对应的platform_driver;
/i2c/at24c02节点不会被转换为platform_device, 它被如何处理完全由父节点的platform_driver决定, 一般是被创建为一个i2c_client。

类似的也有/spi节点, 它一般也是用来表示SPI控制器, 它会被转换为platform_device, 在内核中有对应的platform_driver;
/spi/flash@0节点不会被转换为platform_device, 它被如何处理完全由父节点的platform_driver决定, 一般是被创建为一个spi_device。

/ {
          mytest {
              compatile = "mytest", "simple-bus";
              mytest@0 {
                    compatile = "mytest_0";
              };
          };
          
          i2c {
              compatile = "samsung,i2c";
              at24c02 {
                    compatile = "at24c02";                      
              };
          };

          spi {
              compatile = "samsung,spi";              
              flash@0 {
                    compatible = "winbond,w25q32dw";
                    spi-max-frequency = <25000000>;
                    reg = <0>;
                  };
          };
      };

对于根目录下的第一级子节点,比如说I2c,它应该转换成platform_device,它会对应有一个platform_driver,当匹配时,driver中的probe函数就会被调用,对于I2c下面的这些子节点,比如说AT24C02应该交给probe函数来处理。如果仍然把这些子节点转成platfrom_device的话,就不太合适了。
2. device_node如何转换成platform_device

首先来看一下,platform_device结构体的定义:

struct platform_device {
    const char    *name;
    int        id;
    bool        id_auto;
    struct device    dev;
    u32        num_resources;
    struct resource    *resource;   //指向一个动态生成的数组,数组的大小由num_resources决定。意味着平台设备中可以有0项,或1项,或多项资源。
                                 //这些资源来自设备树中的reg属性,如果设备树中设有reg属性,那么在对应的platform_device中就会有一项资源,
                                 //用来表示它所占用的内存空间。还可以指定一些中断属性,那么在platform_device就会表示它占据哪个中断号。
                                 //资源的类别:I/O资源,内存资源,中断资源,这3中资源都可以在设备树中指定。这些资源会从device_node转换得到。
                                 
    const struct platform_device_id    *id_entry;
    char *driver_override; /* Driver name to force a match */
    /* MFD cell pointer */
    struct mfd_cell *mfd_cell;
    /* arch specific additions */
    struct pdev_archdata    archdata;
};

platform_device中含有resource数组, 它来自device_node的reg, interrupts属性;
platform_device.dev.of_node指向device_node, 可以通过它获得其他属性

以上是关于device_node转换为platform_device的主要内容,如果未能解决你的问题,请参考以下文章

RK3399平台开发系列讲解(内核设备树篇)4.22设备树dtb信息转化为device_node结构

device node结构体转换成platform_device结构体

dtb展开成device_node

RK3399平台开发系列讲解(内核设备树篇)3.6device_node与device绑定流程

RK3399平台开发系列讲解(内核设备树篇)3.6device_node与device绑定流程

Linux内核 设备树操作常用API