DTS中如何配置设备相关的pinctrl

本文详细解析了嵌入式Linux环境下DTS中pinctrl子系统的配置方法,重点介绍了如何定义和管理设备驱动中的pin功能,包括pin的选择、配置及驱动程序的引用。通过实例展示了Freescale IOMUX的pin配置过程。

进行嵌入式Linux驱动开发时,不可避免的会涉及到DTS相关的编写工作,而其中,最为重要的一项工作就是pinctrl相关的配置,这包括pins的功能选择(作为普通IO,还是作为外围控制器的pins)以及pins的配置(pull-up/pull-down、驱动能力、三态等)。
内核中的pinctrl子系统抽象了不同SoC中关于pins的管理方式,Linux内核之pinctrl子系统对于pinctrl子系统进行了简要的概述,如果想要了解pinctrl子系统,可以参考这篇博文。

本文主要讲解对于一个具体的设备驱动,如何在DTS中基于pinctrl实现关于pins的管理,这包括:

  • 如何定义pin功能
  • 驱动程序如何引用pin

如何定义pin功能

利用内核文档

市面上存在很多的SoC,一般情况下,不同的SoC在DTS中关于pin的管理方式会有一些不同。SoC厂商在发布时,会编写相关的pinctrl驱动程序,同时,会在内核目录Documentation/devicetree/bindings/pinctrl下,编写相关的配置说明,比如,fsl,imx-pinctrl.txt
里面说明了 Freescale IOMUX Controller (IOMUXC) for I.MX相关的配置说明;rockchipi, pinctrl.txt里面说面了Rockchip Pinmux Controller相关的配置说明。

所以,当我们拿到一块电路板时,首先,需要确定其使用的SoC,然后,去Documentation/devicetree/bindings/pinctrl目录下,找到关于该款SoC相关的pinctrl的配置说明。这里需要注意的时,某个厂商的SoC一般遵循相同的pinctrl配置方式,所以,在未找到具体SoC的
pinctrl使用说明时,可以直接查看这个SoC厂商的说明文档,比如,我们如果使用的是s3c6410,可以看到该目录下,没有s3c6410相关的说明,但是,我们可以找到samsung-pinctrl.txt,参照这个文档,同样可以在DTS中配置pinctrl。

pin配置举例

下面拿一个例子,说明一下如何在DTS中定义pin的功能。

Freescale IOMUX

关于Freescale SoC的pinctrl配置,主要完成一下两项内容:

  • 确定SoC的pinctrl控制器的兼容性: compatible: “fsl,-iomuxc”,关于SoC的IOMUX的兼容性,需要到fsl,-pinctrl.txt中获得。
  • 配置具体的pins: fsl,pins/</>,该字段定义了pin的功能,其一般定义一组pins的功能,这一组pins服务于同一function,比如spi控制器。每个配置项包括6字段分别是:前5个字段分别是<mux_reg conf_reg input_reg mux_val input_val>,可以到/arch/arm/boot/dts的imx*-pinfunc.h中找到他们的定义,
    比如,imx6ul-pinfunc.h定义imx6ul这款SoC的所有pins。6个字段是pin的配置参数,比如:pull-up/pull-down等。

下面是sd卡所用到的pin的功能配置定义:

usdhc@219c000 { /* uSDHC4 */
    non-removable;
    vmmc-supply = <&reg_3p3v>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_usdhc4_1>;
};         
           
iomuxc@20e0000 {
    compatible = "fsl,imx6q-iomuxc";
    reg = <0x020e0000 0x4000>;
           
    /* shared pinctrl settings */
    usdhc4 {
        pinctrl_usdhc4_1: usdhc4grp-1 {
            fsl,pins = <
                MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
                MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
                MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
                MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
                MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
                MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
                MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059                                                                                                                                                                                                                                    
                MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
                MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
                MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
            >;
    };  
    ....
};       
  • iomuxc的兼容性为"fsl,imx6q-iomuxc";
  • 节点pinctrl_usdhc4_1定义了设备uSDHC4所使用的pins功能。

驱动程序如何使用pins

对于普通的设备,如何定义其使用到的pin呢?上面关于Freescale IOMUX的举例,说明了uSDHC4这个设备如何定义pins的功能。文档pinctrl-bindings.txt中说明了一般情况下如何在DTS中定义一个设备驱动的pins功能。

如果一个设备使用到某些pins,那么,在其DTS节点中至少包含下面两项内容:

  • pinctrl-names:定义设备不同的工作状态,一般包括下面几个:default、init、sleep、idle。其中,sleep、idle用于系统的电源管理,以达到控制系统功耗的目的。
  • pinctrl-0:定义了一个phandles的列表,每个phandle指向一个pinctrl的节点。该配置项定义了该设备的一种工作状态,其对应于pinctrl-names中首个工作状态。

下面举例说明一下:
deviceA {
pinctrl-names = “defalut”, “idle”;
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};

deviceA节点,定义了"default","idle"两种工作状态,所以,下面依次定义了pinctrl-0和pinctrl-1两个pins列表,分别对应于上面两个状态。

上面内容,说明了一个设备如何在DTS中配置其所用到的pins,后面文章还具体分析pinctrl子系统在DTS中的配置方式。

关注公众号“奔跑的码仔”获取更多优质资源

<think>我们正在讨论如何在Linux设备树中为GPIO中断配置pinctrl状态。根据用户提供的引用和之前的讨论,我们需要将pinctrl配置与GPIO中断关联起来。引用[1]提到:pinctrl子系统用于设置PIN的复用和电气属性。如果将一个PIN复用为GPIO,那么就会涉及到gpio子系统。而gpio子系统则用于初始化GPIO并提供API,包括设置输入输出、读取值等。引用[5]中有一个关于button的设备树节点示例,其中涉及gpios属性和interrupts属性。在设备树中配置GPIO中断通常需要两个步骤:1.通过pinctrl子系统将引脚配置为GPIO功能,并设置电气属性(如上拉、下拉等)。2.在设备节点中指定使用的GPIO引脚,以及中断属性(包括中断号和触发方式)。以下是一个典型的设备树配置示例:首先,在pinctrl子节点中定义引脚的配置状态(例如,将某个引脚配置为GPIO功能,并设置上拉,以及配置为中断触发模式):```&iomuxc{pinctrl_mygpio_int:mygpio_int_grp{fsl,pins=<//使用宏来定义引脚,将其复用为GPIO,并设置电气属性(如上拉),以及中断触发模式MX6UL_PAD_GPIO1_IO03__GPIO1_IO030x17059//这里的0x17059是配置寄存器的值,具体含义参考芯片手册>;};};```上述配置中,我们将GPIO1_IO03这个引脚配置为GPIO功能,并设置电气属性(上拉、驱动能力等)。注意:在i.MX系列中,寄存器的配置值包括了上拉、下拉、速度、开漏等设置。然后,在设备节点中,我们需要:a.引用上面定义的pinctrl状态b.通过gpio属性指定使用的GPIOc.配置中断属性(中断父控制器、中断号、触发方式)例如:```mydevice{compatible="mydevice-driver";pinctrl-names="default";pinctrl-0=<&pinctrl_mygpio_int>;//引用pinctrl状态interrupt-parent=<&gpio1>;//指定中断控制器,这里使用gpio1控制器interrupts=<3IRQ_TYPE_EDGE_RISING>;//中断号为3(对应GPIO1_IO03),上升沿触发gpios=<&gpio13GPIO_ACTIVE_LOW>;//指定使用的GPIO引脚,并说明有效电平};```注意:1.在pinctrl配置中,我们通常只是将引脚复用为GPIO,并设置电气属性。而中断的触发方式(如上升沿、下降沿等)通常在设备节点的interrupts属性中设置。2.在设备节点中,我们需要指定中断的父控制器(interrupt-parent),对于GPIO中断,通常就是该GPIO所在的GPIO控制器(如gpio1)。3.中断号(interrupts属性中的第一个数字)一般是该GPIO在控制器内部的序号。例如,GPIO1_IO03对应的序号是3(从0开始)。引用[1]提到,pinctrl子系统将一个PIN复用为GPIO后,就交由gpio子系统管理。引用[5]中的示例也展示了在设备树中如何配置一个按钮(包括gpio和中断属性)。总结步骤:1.在pinctrl节点中配置引脚为GPIO功能,并设置电气属性(如上拉、下拉等)。2.在设备节点中:-通过pinctrl-0引用该配置-指定interrupt-parent为对应的GPIO控制器-指定interrupts属性(包括GPIO编号和触发类型)-可选:使用gpios属性(如果驱动需要通过gpio子系统操作这个引脚)需要特别注意的是:电气属性(如上拉、下拉、驱动能力)在pinctrl配置中设定,而中断触发类型(如上升沿、下降沿)在设备节点的interrupts属性中设定。参考文献:[^1]:pinctrl子系统和gpio子系统的关系[^5]:设备树中配置中断的示例相关问题:1.如何确定GPIO在设备树中的中断号?2.设备树中如何配置多个中断引脚?3.pinctrl配置中的电气属性值具体如何计算?4.GPIO中断在驱动程序中如何获取和使用?</think> ### Linux设备树中GPIO中断的pinctrl状态配置方法 在Linux设备树中为GPIO中断配置pinctrl状态需要结合**pinctrl子系统**和**gpio子系统**的功能,具体配置步骤如下: #### 1. **定义pinctrl状态组**(在SoC级别的节点中) 在SoC的引脚控制器节点中,定义GPIO中断的电气属性和复用配置: ```dts &iomuxc { my_gpio_intr_pins: gpio-intr-pins { fsl,pins = < // 配置为GPIO功能 + 电气属性 + 中断功能 MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x17059 >; }; }; ``` 关键参数解析: - `MX6UL_PAD_GPIO1_IO03__GPIO1_IO03`:指定引脚复用为GPIO功能[^1] - `0x17059`:电气属性值(包含上拉/下拉/驱动强度等),具体值需参考芯片手册: - 位0-3: 驱动强度 - 位4-5: 速率控制 - 位6-7: 上拉/下拉(0x40=100K上拉,0x80=100K下拉) #### 2. **在设备节点中引用pinctrl状态** 在具体的设备节点中引用预定义的引脚状态: ```dts button { compatible = "gpio-keys"; pinctrl-names = "default"; // 状态名称 pinctrl-0 = <&my_gpio_intr_pins>; // 引用上一步定义的pinctrl interrupt-parent = <&gpio1>; // GPIO控制器[^5] interrupts = <3 IRQ_TYPE_EDGE_RISING>; // 引脚号+触发方式 gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; // GPIO定义(可选) }; ``` 参数详解: - `interrupt-parent`:指定GPIO控制器[^3] - `interrupts`:`<引脚号 触发方式>` - 触发方式常量: - `IRQ_TYPE_NONE`:默认 - `IRQ_TYPE_EDGE_RISING`:上升沿 - `IRQ_TYPE_EDGE_FALLING`:下降沿 - `IRQ_TYPE_EDGE_BOTH`:双边沿 #### 3. **在驱动中处理中断** 在设备驱动代码中只需通过标准API获取中断号: ```c static int probe(struct platform_device *pdev) { int irq = platform_get_irq(pdev, 0); // 自动解析设备树的中断配置 request_irq(irq, handler, IRQF_TRIGGER_RISING, "my_irq", NULL); } ``` pinctrl子系统会自动完成: 1. 引脚复用设置(替代`HAL_GPIO_Init()`) 2. 电气属性配置(替代`GPIO_PULLUP`等) 3. 中断控制器注册[^2] #### 电气属性配置参考表 | 功能 | i.MX寄存器位 | 典型值 | |------|-------------|--------| | 上拉 | PUS[1:0]=10 | 0x40 | | 下拉 | PUS[1:0]=01 | 0x80 | | 高速 | SPEED=1 | 0x100 | | 开漏 | ODE=1 | 0x1000 | > 注:不同SoC寄存器定义不同,需参考具体芯片手册[^1] **关键优势**: 这种配置完全在设备树中实现硬件抽象,无需修改驱动代码即可适配不同硬件平台[^4]。 --- ### **相关问题** 1. 如何验证GPIO中断pinctrl配置是否正确生效? 2. 在设备树中配置双边沿触发(IRQ_TYPE_EDGE_BOTH)需要注意什么? 3. 多个GPIO中断共享同一中断线时如何配置设备树? 4. 如何为低功耗模式配置不同的pinctrl中断状态(如sleep状态)?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值