dts的关键字 linux_linux dts关键字 - CSDN
  • linux 设备驱动文件在与 dts 中的设备板级硬件信息匹配的关键字是 compatible 属性。即比较驱动文件中 of_device_id 结构体元素的 .compatible 成员变量和 dts 文件中 node 中 compatible 属性两个字符串。...

    linux 设备驱动文件在与 dts 中的设备板级硬件信息匹配的关键字是 compatible 属性。即比较驱动文件中 of_device_id 结构体元素的 .compatible 成员变量和 dts 文件中 node 中 compatible 属性两个字符串。

    Rationale:

    linux 启动从 lk jump 到 kernel 之后

        函数调用的深度比较深所以图比较长,其中细节部分省略,可以打开具体源码去看。

    可以看到最后调用的函数

    static inline int of_driver_match_device(struct device *dev,const struct device_driver *drv)
    	--->of_match_device(drv->of_match_table, dev) != NULL;
    		--->of_match_node(matches, dev->of_node)
    			--->__of_match_node(matches, node)
    				--->static const struct of_device_id *__of_match_node(const struct             
                           of_device_id *matches,
    					   const struct device_node *node)
    					{
    						const struct of_device_id *best_match = NULL;
    						int score, best_score = 0;
    
    						if (!matches)
    							return NULL;
    
    						for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
                      //此函数将driver的of_match_table->compatible和node中的compatible比较
    							score = __of_device_is_compatible(node, matches->compatible,
    											  matches->type, matches->name); 
    							if (score > best_score) {
    								best_match = matches;
    								best_score = score;
    							}    
    						}
    
    						return best_match;
    					}

    传递到最后__of_device_is_compatible函数将driver的of_match_table->compatible和node中的compatible比较,这个比较不是单纯的比较,是一种加分制。

    匹配成功之后会进行probe,如果driver 的 probe 执行不成功(比如硬件问题,或者没有挂载设备),会调用sys系列函数进行驱动卸载。

    展开全文
  • 摘自:... http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf =======================================

    摘自:http://blog.csdn.net/xiaojiezuo123/article/details/49890471

    http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf
    =============================================
    问题一:以前的Linux Kernel如何描述硬件,现在又如何描述呢?

    在以前的内核版本中:
    1)内核包含了对硬件的全部描述;
    2)bootloader会加载一个二进制的内核镜像,并执行它,比如uImage或者zImage;
    3)bootloader会提供一些额外的信息,成为ATAGS,它的地址会通过r2寄存器传给内核;
        ATAGS包含了内存大小和地址,kernel command line等等;
    4)bootloader会告诉内核加载哪一款board,通过r1寄存器存放的machine type integer;
    5)U-Boot的内核启动命令:bootm 

    6)Barebox变量:bootm.image (?)

    screenshot from 2014-10-14 09:48:32.jpg


    现今的内核版本使用了Device Tree:
    1)内核不再包含对硬件的描述,它以二进制的形式单独存储在另外的位置:the device tree blob
    2)bootloader需要加载两个二进制文件:内核镜像和DTB
        内核镜像仍然是uImage或者zImage;
        DTB文件在arch/arm/boot/dts中,每一个board对应一个dts文件;
    3)bootloader通过r2寄存器来传递DTB地址,通过修改DTB可以修改内存信息,kernel command line,以及潜在的其它信息;
    4)不再有machine type;
    5)U-Boot的内核启动命令:bootm 

    6)Barebox变量:bootm.image,bootm.oftree
    screenshot from 2014-10-14 09:58:16.jpg


    有些bootloader不支持Device Tree,或者有些专门给特定设备写的版本太老了,也不包含。为了解决这个问题,CONFIG_ARM_APPENDED_DTB被引进。
        它告诉内核,在紧跟着内核的地址里查找DTB文件;
        由于没有built-in Makefile rule来产生这样的内核,因此需要手动操作:
            cat arch/arm/boot/zImage arch/arm/boot/dts/myboard.dtb > my-zImage
            mkimage ... -d my-zImage my-uImage
        (cat这个命令,还能够直接合并两个mp3文件哦!so easy!)
    另外,CONFIG_ARM_ATAG_DTB_COMPAT选项告诉内核去bootloader里面读取ATAGS,并使用它们升级DT。

    =============================================
    问题二:现在Linux Kernel使用的Device Tree到底是个什么东东?

    引用the Power.org Standard for Embedded Power Architecture Platform Requirements (ePAPR)的定义:
    1)ePAPR使用device tree的概念描述硬件。boot程序会加载device tree到client program's memory中,并将device tree的指针传递给client;
    2)device tree是一个树形数据结构with nodes,用来描述系统的physical devices;
    3)一个ePAPR-complient device tree描述的设备信息不能被client program读取;
    screenshot from 2014-10-14 11:13:22.jpg


    From Source to binary
    1)在ARM系统中,所有的DTS文件放置在arch/arm/boot/dts中:
        .dts文件为板级定义
        .dtsi文件为SoC级定义
    2)Device Tree Compiler工具,将源代码编译成二进制形式;
        它的源代码放置在scripts/dtc中
    3)编译器会产生DTB文件,bootloader会加载这个DTB文件,内核在boot时去解析它;
    4)arch/arm/boot/dts/Makefile会指定产生哪个DTB文件;
    screenshot from 2014-10-14 11:45:24.jpg


    上图是pdf里面自带的例子,我再从arch/arm/boot/dts/am33xxx.dtsi中摘录了两个:
                   
                    uart0: serial@44e09000 {
                            compatible = "ti,omap3-uart";
                            ti,hwmods = "uart1";
                            clock-frequency = <48000000>;
                            reg = <0x44e09000 0x2000>;
                            interrupts = <72>;
                            status = "disabled";
                    };

                    uart1: serial@48022000 {
                            compatible = "ti,omap3-uart";
                            ti,hwmods = "uart2";
                            clock-frequency = <48000000>;
                            reg = <0x48022000 0x2000>;
                            interrupts = <73>;
                            status = "disabled";
                    };

    对比图片中的注释,就能够知道对于uart0这个外设:
    Node name: serial
    Unit Address: 0x44e09000
    compatible: 定义了设备的programming model,允许操作系统识别对应的程序驱动;
    clock-frequency: 48000000,晶振频率为24MHz,这应该是PLL倍频后的输出(?);
    reg: 寄存器的地址和寄存器长度,uart0的地址起始为0x44e09000,长度为0x2000;
    interrupts: 中断号;
    status: 状态值,初始的时候为disabled,即禁用它;

    =============================================
    问题三:Device Tree的编写规则是怎样的?

    1)Device Tree inclusion不一定要做成monolithic,它们可以分散在不同的文件中,互相包含;
    2).dtsi文件是被包含的,.dts文件才是最终的Device Trees;
    3).dts文件包含了板级信息;
    4)including工作主要是将including file覆盖到included file上面;
    5)inclusion使用DT操作符/include/,或者在某些少量的内核发布版中,由于DTS是使用了C preprocessor,因此推荐#include。
    screenshot from 2014-10-15 14:10:47.jpg


    由这张图可见,如果included file中的某项,被including file文件定义了,则会使用后者的定义,也就是使用更上层更新的定义;如果没有被定义,则添加进入。

    1)bindings是device tree里面可已包含的specific types and classes of devices。
    2)compatible特征描述了节点编译的specific binding;
    3)当为一个设备创建新的device tree时,应该创建a binding来描述设备的全部细节。

    =============================================
    问题四:在哪里可以找到Device Tree的文档呢?

    1)所有可被内核识别的Device Tree bindings在文档Documentation/devicetree/bindings里面;
    2)每个binding文档描述了哪些properties可以被接受,可以使用哪些值,哪些特征是必须的,哪些是可选的;
    3)所有新的Device Tree bindings必须让代码维护者审核,提交到devicetree@vger.kernel.org上。这用来保证它们的正确性和一致性。

    =============================================
    问题五:Device Tree中的常见关键字含义是什么?

    Device Tree organization: top-level nodes
    在设备的最顶层节点上,一般可以发现如下这些:
    cpus:描述了系统的CPU
    memory:定义了RAM的地址和大小
    chosen:定义了boot时被系统固件选择或定义的参数;可用来传递kernel command line;
    aliases:定义了certain nodes的shotcuts;
    一个或多个总线定义;
    一个或多个板上设备定义;

    下面是am33xx.dtsi中的定义:

    / {
            compatible = "ti,am33xx";
            interrupt-parent = <&intc>;

            aliases {
                    i2c0 = &i2c0;
                    i2c1 = &i2c1;
                    i2c2 = &i2c2;
                    serial0 = &uart0;
                    serial1 = &uart1;
                    serial2 = &uart2;
                    serial3 = &uart3;
                    serial4 = &uart4;
                    serial5 = &uart5;
                    d_can0 = &dcan0;
                    d_can1 = &dcan1;
                    usb0 = &usb0;
                    usb1 = &usb1;
                    phy0 = &usb0_phy;
                    phy1 = &usb1_phy;
                    ethernet0 = &cpsw_emac0;
                    ethernet1 = &cpsw_emac1;
            };

            cpus {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    cpu@0 {
                            compatible = "arm,cortex-a8";
                            device_type = "cpu";
                            reg = <0>;
                            
                            /*
                             * To consider voltage drop between PMIC and SoC,
                             * tolerance value is reduced to 2% from 4% and
                             * voltage value is increased as a precaution.
                             */
                            operating-points = <
                                    /* kHz    uV */
                                    720000  1285000
                                    600000  1225000
                                    500000  1125000
                                    275000  1125000
                            >;
                            voltage-tolerance = <2>; /* 2 percentage */

                            clocks = <&dpll_mpu_ck>;
                            clock-names = "cpu";
                            
                            clock-latency = <300000>; /* From omap-cpufreq driver */
                    };
            };

            pmu {
                    compatible = "arm,cortex-a8-pmu";
                    interrupts = <3>;
            };

            /*
             * The soc node represents the soc top level view. It is used for IPs
             * that are not memory mapped in the MPU view or for the MPU itself.
             */
            soc {
                    compatible = "ti,omap-infra";
                    mpu {
                            compatible = "ti,omap3-mpu";
                            ti,hwmods = "mpu";
                    };
            };


        /* ...... */

    };

    从上面的代码里面可以找出四个compatible,分别是:
    top: compatible = "ti,am33xx";
    cpu0: compatible = "arm,cortex-a8";
    pmu: compatible = "arm,cortex-a8-pmu";
    soc: compatible = "ti,omap-infra";

    怎样使用compatible呢?
    方法一是用来匹配DT_MACHINE结构体中的dt_compat域,方法二是使用of_machine_is_compatible函数。

    在总线中,一般要定义compatile、#address-cells、#size-cells、ranges,比如:

           i2c0: i2c@44e0b000 {
                    compatible = "ti,omap4-i2c";
                    #address-cells = <1>;
                    #size-cells = <0>;
                    ti,hwmods = "i2c1";
                    reg = <0x44e0b000 0x1000>;
                    interrupts = <70>;
                    status = "disabled";
            };

    =============================================
    问题六:有关DT的策略,你应该了解的~

    DT是一种硬件描述,而不是一种配置。
    它应该描述硬件的构成,和硬件工作的方式;
    它不应该描述那种硬件配置你更加喜欢;
    例如:
        你可以在DT中描述是否硬件配置支持DMA;
        但是你不要在DT中描述你是否想要DMA。

    1)DT独立于OS,它也需要非常稳定;
    2)最初的设想是,DTBs由生产厂家烧写进芯片中,用户直接安装系统就好了;
    3)当Device Tree binding被定义,并且在DTBs使用之后,它就不能再改变,但可以扩展;
    4)这意味着Device Tree binding是内核的二进制程序接口(ABI),它需要same care;
    5)但是内核开发者意识到了这个很难达到,并且会减慢驱动程序的集成:
        ARM Kernel Mini-submit discussions放松了这些限制;
        未来在Kernel Summit时会有additional discussion;

    Basic guidelines for binding design:
    1) A precise compatible string is better than a vague one.
    2) Do not encode too much hardware details in the DT.
    展开全文
  • linux内核主线了解dts

    2019-06-04 18:28:32
    http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf ...原版在上面的地址上,这个是转载别人翻译好的,dts的用法说的很详细,还有2个疑问 第一,bootloader 在R2...

    http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf
    =============================================

    原版在上面的地址上,这个是转载别人翻译好的,dts的用法说的很详细,还有2个疑问

    第一,bootloader 在R2寄存器里把dtb的地址传给kernel这部分如何实现的

    第二,kernel拿到dtb文件的存放地址后,如何使用这个dtb文件的。

    下面先看看大神翻译好的内容!

     

    问题一:以前的Linux Kernel如何描述硬件,现在又如何描述呢?

    在以前的内核版本中:
    1)内核包含了对硬件的全部描述;
    2)bootloader会加载一个二进制的内核镜像,并执行它,比如uImage或者zImage;
    3)bootloader会提供一些额外的信息,成为ATAGS,它的地址会通过r2寄存器传给内核;
        ATAGS包含了内存大小和地址,kernel command line等等;
    4)bootloader会告诉内核加载哪一款board,通过r1寄存器存放的machine type integer;
    5)U-Boot的内核启动命令:bootm 
    6)Barebox变量:bootm.image (?)

    screenshot from 2014-10-14 09:48:32.jpg



    现今的内核版本使用了Device Tree:
    1)内核不再包含对硬件的描述,它以二进制的形式单独存储在另外的位置:the device tree blob
    2)bootloader需要加载两个二进制文件:内核镜像和DTB
        内核镜像仍然是uImage或者zImage;
        DTB文件在arch/arm/boot/dts中,每一个board对应一个dts文件;
    3)bootloader通过r2寄存器来传递DTB地址,通过修改DTB可以修改内存信息,kernel command line,以及潜在的其它信息;
    4)不再有machine type;
    5)U-Boot的内核启动命令:bootm - 
    6)Barebox变量:bootm.image,bootm.oftree

    screenshot from 2014-10-14 09:58:16.jpg



    有些bootloader不支持Device Tree,或者有些专门给特定设备写的版本太老了,也不包含。为了解决这个问题,CONFIG_ARM_APPENDED_DTB被引进。
        它告诉内核,在紧跟着内核的地址里查找DTB文件;
        由于没有built-in Makefile rule来产生这样的内核,因此需要手动操作:
            cat arch/arm/boot/zImage arch/arm/boot/dts/myboard.dtb > my-zImage
            mkimage ... -d my-zImage my-uImage
        (cat这个命令,还能够直接合并两个mp3文件哦!so easy!)
    另外,CONFIG_ARM_ATAG_DTB_COMPAT选项告诉内核去bootloader里面读取ATAGS,并使用它们升级DT。

    =============================================
    问题二:现在Linux Kernel使用的Device Tree到底是个什么东东?

    引用the Power.org Standard for Embedded Power Architecture Platform Requirements (ePAPR)的定义:
    1)ePAPR使用device tree的概念描述硬件。boot程序会加载device tree到client program's memory中,并将device tree的指针传递给client;
    2)device tree是一个树形数据结构with nodes,用来描述系统的physical devices;
    3)一个ePAPR-complient device tree描述的设备信息不能被client program读取;

    screenshot from 2014-10-14 11:13:22.jpg



    From Source to binary
    1)在ARM系统中,所有的DTS文件放置在arch/arm/boot/dts中:
        .dts文件为板级定义
        .dtsi文件为SoC级定义
    2)Device Tree Compiler工具,将源代码编译成二进制形式;
        它的源代码放置在scripts/dtc中
    3)编译器会产生DTB文件,bootloader会加载这个DTB文件,内核在boot时去解析它;
    4)arch/arm/boot/dts/Makefile会指定产生哪个DTB文件;

    screenshot from 2014-10-14 11:45:24.jpg



    上图是pdf里面自带的例子,我再从arch/arm/boot/dts/am33xxx.dtsi中摘录了两个:
                   
                    uart0: serial@44e09000 {
                            compatible = "ti,omap3-uart";
                            ti,hwmods = "uart1";
                            clock-frequency = <48000000>;
                            reg = <0x44e09000 0x2000>;
                            interrupts = <72>;
                            status = "disabled";
                    };

                    uart1: serial@48022000 {
                            compatible = "ti,omap3-uart";
                            ti,hwmods = "uart2";
                            clock-frequency = <48000000>;
                            reg = <0x48022000 0x2000>;
                            interrupts = <73>;
                            status = "disabled";
                    };

    对比图片中的注释,就能够知道对于uart0这个外设:
    Node name: serial
    Unit Address: 0x44e09000
    compatible: 定义了设备的programming model,允许操作系统识别对应的程序驱动;
    clock-frequency: 48000000,晶振频率为24MHz,这应该是PLL倍频后的输出(?);
    reg: 寄存器的地址和寄存器长度,uart0的地址起始为0x44e09000,长度为0x2000;
    interrupts: 中断号;
    status: 状态值,初始的时候为disabled,即禁用它;

    =============================================
    问题三:Device Tree的编写规则是怎样的?

    1)Device Tree inclusion不一定要做成monolithic,它们可以分散在不同的文件中,互相包含;
    2).dtsi文件是被包含的,.dts文件才是最终的Device Trees;
    3).dts文件包含了板级信息;
    4)including工作主要是将including file覆盖到included file上面;
    5)inclusion使用DT操作符/include/,或者在某些少量的内核发布版中,由于DTS是使用了C preprocessor,因此推荐#include。

    screenshot from 2014-10-15 14:10:47.jpg



    由这张图可见,如果included file中的某项,被including file文件定义了,则会使用后者的定义,也就是使用更上层更新的定义;如果没有被定义,则添加进入。

    1)bindings是device tree里面可已包含的specific types and classes of devices。
    2)compatible特征描述了节点编译的specific binding;
    3)当为一个设备创建新的device tree时,应该创建a binding来描述设备的全部细节。

    =============================================
    问题四:在哪里可以找到Device Tree的文档呢?

    1)所有可被内核识别的Device Tree bindings在文档Documentation/devicetree/bindings里面;
    2)每个binding文档描述了哪些properties可以被接受,可以使用哪些值,哪些特征是必须的,哪些是可选的;
    3)所有新的Device Tree bindings必须让代码维护者审核,提交到devicetree@vger.kernel.org上。这用来保证它们的正确性和一致性。

    =============================================
    问题五:Device Tree中的常见关键字含义是什么?

    Device Tree organization: top-level nodes
    在设备的最顶层节点上,一般可以发现如下这些:
    cpus:描述了系统的CPU
    memory:定义了RAM的地址和大小
    chosen:定义了boot时被系统固件选择或定义的参数;可用来传递kernel command line;
    aliases:定义了certain nodes的shotcuts;
    一个或多个总线定义;
    一个或多个板上设备定义;

    下面是am33xx.dtsi中的定义:

    / {
            compatible = "ti,am33xx";
            interrupt-parent = <&intc>;

            aliases {
                    i2c0 = &i2c0;
                    i2c1 = &i2c1;
                    i2c2 = &i2c2;
                    serial0 = &uart0;
                    serial1 = &uart1;
                    serial2 = &uart2;
                    serial3 = &uart3;
                    serial4 = &uart4;
                    serial5 = &uart5;
                    d_can0 = &dcan0;
                    d_can1 = &dcan1;
                    usb0 = &usb0;
                    usb1 = &usb1;
                    phy0 = &usb0_phy;
                    phy1 = &usb1_phy;
                    ethernet0 = &cpsw_emac0;
                    ethernet1 = &cpsw_emac1;
            };

            cpus {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    cpu@0 {
                            compatible = "arm,cortex-a8";
                            device_type = "cpu";
                            reg = <0>;
                            
                            /*
                             * To consider voltage drop between PMIC and SoC,
                             * tolerance value is reduced to 2% from 4% and
                             * voltage value is increased as a precaution.
                             */
                            operating-points = <
                                    /* kHz    uV */
                                    720000  1285000
                                    600000  1225000
                                    500000  1125000
                                    275000  1125000
                            >;
                            voltage-tolerance = <2>; /* 2 percentage */

                            clocks = <&dpll_mpu_ck>;
                            clock-names = "cpu";
                            
                            clock-latency = <300000>; /* From omap-cpufreq driver */
                    };
            };

            pmu {
                    compatible = "arm,cortex-a8-pmu";
                    interrupts = <3>;
            };

            /*
             * The soc node represents the soc top level view. It is used for IPs
             * that are not memory mapped in the MPU view or for the MPU itself.
             */
            soc {
                    compatible = "ti,omap-infra";
                    mpu {
                            compatible = "ti,omap3-mpu";
                            ti,hwmods = "mpu";
                    };
            };


        /* ...... */

    };

    从上面的代码里面可以找出四个compatible,分别是:
    top: compatible = "ti,am33xx";
    cpu0: compatible = "arm,cortex-a8";
    pmu: compatible = "arm,cortex-a8-pmu";
    soc: compatible = "ti,omap-infra";

    怎样使用compatible呢?
    方法一是用来匹配DT_MACHINE结构体中的dt_compat域,方法二是使用of_machine_is_compatible函数。

    在总线中,一般要定义compatile、#address-cells、#size-cells、ranges,比如:

           i2c0: i2c@44e0b000 {
                    compatible = "ti,omap4-i2c";
                    #address-cells = <1>;
                    #size-cells = <0>;
                    ti,hwmods = "i2c1";
                    reg = <0x44e0b000 0x1000>;
                    interrupts = <70>;
                    status = "disabled";
            };

    =============================================
    问题六:有关DT的策略,你应该了解的~

    DT是一种硬件描述,而不是一种配置。
    它应该描述硬件的构成,和硬件工作的方式;
    它不应该描述那种硬件配置你更加喜欢;
    例如:
        你可以在DT中描述是否硬件配置支持DMA;
        但是你不要在DT中描述你是否想要DMA。

    1)DT独立于OS,它也需要非常稳定;
    2)最初的设想是,DTBs由生产厂家烧写进芯片中,用户直接安装系统就好了;
    3)当Device Tree binding被定义,并且在DTBs使用之后,它就不能再改变,但可以扩展;
    4)这意味着Device Tree binding是内核的二进制程序接口(ABI),它需要same care;
    5)但是内核开发者意识到了这个很难达到,并且会减慢驱动程序的集成:
        ARM Kernel Mini-submit discussions放松了这些限制;
        未来在Kernel Summit时会有additional discussion;

    Basic guidelines for binding design:
    1) A precise compatible string is better than a vague one.
    2) Do not encode too much hardware details in the DT.

    展开全文
  • Linux 内核驱动里面 EMMC 默认是 4 线模式的,4 线模式肯定没有 8 线模式的速度快,所以将 EMMC 的驱动修改为 8 线模式。修改方法很简单,直接修改设备树即可,打开文件 imx6ull-mybsp-emmc.dts,找到如下所示内容:...

    使能 8 线 EMMC 驱动

    在这里插入图片描述

    Linux 内核驱动里面 EMMC 默认是 4 线模式的,4 线模式肯定没有 8 线模式的速度快,所以将 EMMC 的驱动修改为 8 线模式。修改方法很简单,直接修改设备树即可,打开文件 imx6ull-mybsp-emmc.dts,找到如下所示内容:

    gedit arch/arm/boot/dts/imx6ull-mybsp-emmc.dts

    关键字:&usdhc2
    在这里插入图片描述

    只需要将其改为如下代码即可:

    &usdhc2 {
    	pinctrl-names = "default", "state_100mhz", "state_200mhz";
    	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
    	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
    	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
    	bus-width = <8>;
    	non-removable;
    	status = "okay";
    };
    

    修改完成以后保存一下 imx6ull-mybsp-emmc.dts,然后使用命令“make dtbs”重新编译一下设备树,编译完成以后使用新的设备树重新烧录 Linux 系统即可。
    下载烧录参考:https://blog.csdn.net/qq_29246181/article/details/106297810

    修改网络驱动

    1. 修改 LAN8720 的复位以及网络时钟引脚驱动

    ENET1 复位引脚 ENET1_RST 连接在 I.M6ULL 的 SNVS_TAMPER7 这个引脚上。ENET2的复位引脚 ENET2_RST 连接在 I.MX6ULL 的 SNVS_TAMPER8 上。
    打开设备树文件 imx6ull-mybsp-emmc.dts,找到如下代码:

    gedit arch/arm/boot/dts/imx6ull-mybsp-emmc.dts

    关键词:pinctrl_spi4:
    在这里插入图片描述
    第 588 和 589 行就是初始化 SNVS_TAMPER7 和 SNVS_TAMPER8 这两个引脚的,但是它们作为了 SPI4 的 IO口。所以我们要删除SPI4的IO口掉重新定义。
    修改后:
    在这里插入图片描述

    关键词:spi4 {
    在这里插入图片描述

    第 129 行,设置 GPIO5_IO08 为 SPI4 的一个功能引脚,而GPIO5_IO08 就是 SNVS_TAMPER8 的 GPIO 功能引脚。

    第 133 行, 设置 GPIO5_IO07 作为 SPI4 的片选引脚, 而 GPIO5_IO07 就是 SNVS_TAMPER7的 GPIO 功能引脚。

    现在我们需要 GPIO5_IO07 和 GPIO5_IO08 分别作为 ENET1 和 ENET2 的复位引脚,而不是 SPI4 的什么功能引脚, 因此将示例代码中的第 129 行和第 133 行处的代码删除掉! !否则会干扰到网络复位引脚!
    修改后:
    在这里插入图片描述

    关键词:iomuxc_snvs
    然后在此节点下添加网络复位引脚信息,内容如下:

    		/*enet1 reset*/
    		pinctrl_enet1_reset:enet1resetgrp {
    			fsl,pins = <
    			/* used for enet1  reset */
    			MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07      0x10B0      /* ENET1 RESET */
    			>;
    		};
    
    		/*enet2 reset*/
    		pinctrl_enet2_reset:enet2resetgrp {
    			fsl,pins = <
    			/* used for enet2  reset */
    			MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08      0x10B0     /* ENET2 RESET */
    			>;
    		};
    

    在这里插入图片描述
    **关键词:pinctrl_enet1: **
    添加如下内容:

    MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009
    MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009

    修改前:
    在这里插入图片描述
    修改后:
    在这里插入图片描述

    至此网络复位以及时钟引脚驱动就修改完成。

    1. 修改 fec1 和 fec2 节点的 pinctrl-0 属性

    gedit arch/arm/boot/dts/imx6ull-mybsp-emmc.dts

    先看下修改前,和修改后。
    在这里插入图片描述
    在这里插入图片描述
    第一部分:
    //添加了 ENET1 网络复位引脚所使用的 IO 为 GPIO5_IO07, 低电平有效。复位低电平信号持续时间为 200ms。
    //添加了 ENET2 网络复位引脚所使用的 IO 为 GPIO5_IO08, 低电平有效,持续时间同样为 200ms。

    	pinctrl-0 = <&pinctrl_enet1
    	&pinctrl_enet1_reset>;
    
    	pinctrl-0 = <&pinctrl_enet2
    	&pinctrl_enet2_reset>;
    
    	phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
    	phy-reset-duration = <200>;
    
    	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
    	phy-reset-duration = <200>;
    
    
    

    第二部分:
    ①“smsc,disable-energy-detect” 表明 PHY 芯片是 SMSC 公司的, 这样 Linux内核就会找到 SMSC 公司的 PHY 芯片驱动来驱动 LAN8720A。
    ②ethernet-phy@”后面的数字是 PHY 的地址,ENET1 的 PHY 地址为 0,所以“@”后面是 0(默认为 2)。
    reg 的值也表示 PHY 地址,ENET1 的 PHY 地址为 0,所以 reg=0。
    ENET1 的 LAN8720A 地址为 0x0,ENET2 的 LAN8720A地址为 0x1。

    		ethphy0: ethernet-phy@0 {
    		compatible = "ethernet-phy-ieee802.3-c22";
    		smsc,disable-energy-detect;
    		reg = <0>;
    		};
     
    		ethphy1: ethernet-phy@1 {
            	compatible = "ethernet-phy-ieee802.3-c22";
    		smsc,disable-energy-detect;
            	reg = <1>;
    		};
    
    &fec1 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_enet1
    			&pinctrl_enet1_reset>;
    	phy-mode = "rmii";
    	phy-handle = <&ethphy0>;
    	phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
    	phy-reset-duration = <200>;
    	status = "okay";
    };
    
    &fec2 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_enet2
    				&pinctrl_enet2_reset>;
    	phy-mode = "rmii";
    	phy-handle = <&ethphy1>;
    	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
    	phy-reset-duration = <200>;
    	status = "okay";
    
    	mdio {
    		#address-cells = <1>;
    		#size-cells = <0>;
    
    		ethphy0: ethernet-phy@0 {
    		compatible = "ethernet-phy-ieee802.3-c22";
    		smsc,disable-energy-detect;
    		reg = <0>;
    		};
     
    		ethphy1: ethernet-phy@1 {
            	compatible = "ethernet-phy-ieee802.3-c22";
    		smsc,disable-energy-detect;
            	reg = <1>;
    		};
    	};
    };
    

    重新编译一下设备树,终端输入:make dtbs
    在这里插入图片描述

    1. 修改 fec_main.c 文件

    要 在 I.MX6ULL 上 使 用 LAN8720A , 需 要 修 改 一 下 Linux 内 核 源 码 , 打 开drivers/net/ethernet/freescale/fec_main.c。

    gedit drivers/net/ethernet/freescale/fec_main.c

    关键词: fec_probe
    fec_probe 中加入如下代码:
    在这里插入图片描述
    在这里插入图片描述

       	/* 设置MX6UL_PAD_ENET1_TX_CLK和MX6UL_PAD_ENET2_TX_CLK
    	   这两个IO的复用寄存器的SION位为1。
        */
        void __iomem *IMX6U_ENET1_TX_CLK;
        void __iomem *IMX6U_ENET2_TX_CLK;
    
        IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
        writel(0X14, IMX6U_ENET1_TX_CLK);
     
        IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
        writel(0X14, IMX6U_ENET2_TX_CLK);
    
    1. 配置 Linux 内核,使能 LAN8720 驱动

    终端输入命令:make menuconfig
    步骤:
    ①-> Device Drivers
    ② -> Network device support
    ③ -> PHY Device support and infrastructure
    ④ -> Drivers for SMSC PHYs
    在这里插入图片描述
    保存完毕了,选择Exit,一路退出。

    1. 修改 smsc.c 文件

    首先需要找到 LAN8720A 的驱动文件,LAN8720A 的驱动文件是 drivers/net/phy/smsc.c,在此文件中有个叫做 smsc_phy_reset 的函数。

    gedit drivers/net/phy/smsc.c

    ①添加头文件

    #include <linux/of_gpio.h>
    #include <linux/io.h>
    

    在这里插入图片描述
    ② 修改复位函数:smsc_phy_reset
    在这里插入图片描述
    在这里插入图片描述

    static int smsc_phy_reset(struct phy_device *phydev)
    {
    	int err, phy_reset;
    	int msec = 1;
    	struct device_node *np;
    
    	if(phydev->addr == 0) /* FEC1  */ {
    		np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");//获取 FEC1 网卡对应的设备节点
    		if(np == NULL) {
    			return -EINVAL;
    		}
    	}
    
    	if(phydev->addr == 1) /* FEC2  */ {
    		np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");//获取 FEC2 网卡对应的设备节点
    		if(np == NULL) {
    			return -EINVAL;
    		}
    	}
    
    	err = of_property_read_u32(np, "phy-reset-duration", &msec);//从设备树中获取“phy-reset-duration”属性信息,也就是复位时间
    	/* A sane reset duration should not be longer than 1s */
    	if (!err && msec > 1000)
    		msec = 1;
    	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);//从设备树中获取“phy-reset-gpios”属性信息,也就是复位 IO
    	if (!gpio_is_valid(phy_reset))
    		return;
        /*设置 PHY 的复位 IO,复位 LAN8720A*/
    	gpio_direction_output(phy_reset, 0);
    	gpio_set_value(phy_reset, 0);
    	msleep(msec);
    	gpio_set_value(phy_reset, 1);
    
    	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
    	if (rc < 0)
    		return rc;
    
    	/* 设置为全功能模式*/
    	if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
    
    		/* 设置“所有功能”模式并重置phy */
    		rc |= MII_LAN83C185_MODE_ALL;
    		phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
    	}
    
    	phy_write(phydev, MII_BMCR, BMCR_RESET);
    	/* 复位等待结束 (max 500 ms) */
    	int timeout = 50000;
    	do {
    		udelay(10);
    		if (timeout-- == 0)
    			return -1;
    		rc = phy_read(phydev, MII_BMCR);
    	} while (rc & BMCR_RESET);
    	return 0;
    }
    

    然后保存重新编译

    (不要用shell,因为会清除配置文件)。

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_mybsp_emmc_defconfig
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

    下载烧录:

    编译完成以后就会在目录 arch/arm/boot 下生成 zImage 镜像文件。在 arch/arm/boot/dts 目录下生成 imx6ull-alientek-emmc.dtb 文件。

    设置uboot环境变量:https://blog.csdn.net/qq_29246181/article/details/106265362

    setenv bootargs ‘console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw’
    saveenv

    将zImage烧录到开发板中(参考 4、tftp 命令):https://blog.csdn.net/qq_29246181/article/details/106272766

    cp arch/arm/boot/zImage …/…/tftpboot/ -f
    cp arch/arm/boot/dts/imx6ull-mybsp-emmc.dtb …/…/tftpboot/ -f

    将这两个文件拷贝到 tftp 目录下,然后重启开发板,在uboot 命令模式中使用 tftp 命令下载这两个文件并启动,命令如下:

    tftp 80800000 zImage
    tftp 83000000 imx6ull-mybsp-emmc.dtb
    bootz 80800000 - 83000000

    在这里插入图片描述

    网络驱动测试

    修改好设备树和 Linux 内核以后重新编译一下,得到新的 zImage 镜像文件和 imx6ull-mybsp-emmc.dtb 设备树文件, 使用网线将 I.MX6U-ALPHA 开发板的两个网口与路由器或者电脑连接起来,最后使用新的文件启动 Linux 内核。
    输入命令“ifconfig -a”来查看一下开发板中存在的所有网卡:
    在这里插入图片描述
    使用如下命令依次打开 eth0 和 eth1 这两个网卡:

    ifconfig eth0 up
    ifconfig eth1 up

    在这里插入图片描述

    输入“ifconfig”命令来查看一下当前活动的网卡
    在这里插入图片描述
    可以看出,此时 eth0 和 eth1 两个网卡都已经打开,并且工作正常,但是这两个网卡都还没有 IP 地址,所以不能进行 ping 等操作。使用如下命令给两个网卡配置 IP 地址:

    ifconfig eth0 192.168.1.251、
    ifconfig eth1 192.168.1.252

    使用“ping”命令来 ping 一下自己的主机。

    ping 192.168.1.250

    在这里插入图片描述

    配置文件另存为

    因为使用shell,因为会清除配置文件,所有我们需要把配置文件另存为。
    操作如下:

    终端输入:make menuconfig

    在这里插入图片描述

    输入:arch/arm/configs/imx_mybsp_emmc_defconfig
    在这里插入图片描述

    这样就可以使用shell,因为另存为后,就不会被清除。
    运行脚本:

    chmod 777 imx6ull_mybsp_emmc.sh
    //给予可执行权限
    ./imx6ull_mybsp_emmc.sh
    //执行 shell 脚本编译内核

    展开全文
  • linux下写驱动是站在巨人的肩膀上做开发,不用完全从头做起,甚至你不需要懂SPI时序,照样能写出可用的驱动,原因是:控制器驱动一般芯片商早已写好(linux4.9中针对imx系列cpu是 drivers/spi/spi-imx.c),怎么发、...
  • 设备树(一)linux内核主线了解dts http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf ============================================= 问题一:以前的Linux Kernel...
  • 问题一:以前的Linux Kernel如何描述硬件,现在又如何描述呢? 在以前的内核版本中: 1)内核包含了对硬件的全部描述; 2)bootloader会加载一个二进制的内核镜像,并执行它,比如uImage或者zImage; 3)...
  • 关键字linux内核、GPIO、中断系统、内核抢占 之前参与过一个项目,用TCA6424芯片通过I2C扩展GPIO资源,AP侧GPIO资源不够,在开发过程中遇到很多在当时看来许多奇葩的问题,无意中搜到一个蜗窝科技论坛,对我理解...
  • 关键字 dtsi、gpio、key、input子系统、event解析、长按按键检测 ### gpio_keys说明 key是嵌入式开发中常用到的东西,linux内核中也早已为我们做了一套成熟的机制。 linux内核下的 drivers/input/keyboard/gpio...
  • 14.DTS配置

    2017-12-13 15:02:38
    一、dts学习(注:pin 包括但不属于 gpio) 1.gpio0 node编写方法: gpio0: gpio@0 { pins_cmd_dat { pins = ; //模式 slew-rate = ;
  • 最近在移植linux,用到kernel版本为3.14.28,在高版本的内核源码中用到了设备树(device-tree),设备树中用到pinctrl的配置,记录一下。 1、普通设置 在配置串口时,pinctrl的配置信息如下所示:
  • 今天接着移植Linux 3.4.2内核,接着上一篇文章(点击查看:上一篇文章)我们完成了内核的串口启动打印输出,但是无法挂载根文件系统,我们看看启动后显示的是什么: 从打印结构可以看出,我们的分区不对,在U-...
  • 【全志平台】dts内容如何最快导入到机器中 方法四:编译kernel,pack,烧录工具不选择任何分区是最快的方法。 文章目录【全志平台】dts内容如何最快导入到机器中方法一:全编译整包烧录方法二:编译kernel ,dd...
  • provider的角度,介绍了Linux kernel怎么管理系统的clock资源,以及device driver怎么使用clock资源。本文将深入到clock framework的内部,分析相关的实现逻辑。 注:本文使用的kernel版本为linux-3.10.29。虽然
  • 关键字linux驱动、杂项设备、GPIO  此驱动程序控制了外接的两个二极管,二极管是低电平有效。 上一篇博客中已经介绍了linux驱动程序的编写流程,这篇博客算是前一篇的提高篇,也是下一篇博客(JNI)的底层程序 ...
  • 本文转载自:... http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf =========================================
  • 转载时请注明出处和作者联系方式:http://blog.csdn.net/mimepp作者联系方式:YU TAO 关键字: Dolby TrueHD,DTS-HD Master Audio, DTS-HDMA ,AC-3,DD, DD+,Dolby Digital Plus,次世代 在这里列一下输出的...
  • 为了能够更好的学习嵌入式Linux内核,本文基于qemu-system-arm工具模拟ARM公司的VersatileExpress硬件环境,基于buildroot工具制作rootfs,并且扩展了buildroot,增加内核配置管理,定制rootfs等功能。 我的上一篇...
1 2 3 4 5 ... 20
收藏数 426
精华内容 170
关键字:

dts的关键字 linux