Linux驱动设备树-pinctrl篇

熟悉设备树中pinctrl 机制
学会配置pinctrl


参考资料

Linux驱动开发—设备树描述引脚复用 Pinmux 与Pinctrl
设备树-第61章 实例分析:pinctrl
正点原子嵌入式linux驱动开发——pinctrl和gpio子系统

一、 pinmux 介绍

  • Pinmux(引脚复用)
    是指在系统中配置和管理引脚功能的过程。在许多现代集成电路中,单个引脚可以具有多个功能,例如作为 GPIO、UART、SPI 或 I2C 等。通过使用引脚复用功能,可以在这些不同的功能之间切换
    比如如下原理图:
    在这里插入图片描述

从右边往左边看,USB_HOST_PWREN_H_GPIO0_A6 这个引脚,它可以有四个功能预选项吧,看你自己怎么配置。 可以作为 左边:
GPU_PWREN、SATA_CP_POO、PCIE30X2_CLKREQn_MO、GPIO0_A6_d 中其中一个功能的脚,这;里USB_HOST_PWREN_H_GPIO0_A6 不就是复用的嘛,但是只能4选一。

  • AG25 是什么? 它就是一个坐标系,把芯片上面的引脚标注出来,用坐标表示。
    在 BGA(Ball Grid Array,球栅阵列)封装中,引脚标号是用于唯一标识每个引脚的标识符。这些标号通常由芯片制造商定义,并在芯片的规格文档或数据手册中提供。
    BGA 芯片的引脚标号通常由字母和数字的组合构成。它们用于在芯片的封装底部的焊盘上进行标记。每个引脚标号都与芯片内部的功能或信号相对应,以便正确连接到印刷电路板(PCB)上的目标位置。RK3568 的引脚标号图如下(图 61-2)所示
    在这里插入图片描述
    可以看到纵向为 A-AH 的 28 个字母类型标号,横向为 1-28 的 28 个字母类型标号,瑞芯微也在对应的 3568 数据手册中加入了根据 BGA 位置制作的复用功能图,部分内容如下图
    在这里插入图片描述
    其中黑色框代表被保留的引脚,其他有颜色的框一般为电源和地,白色的框代表有具体复用功能的引脚;那为什么电源脚那么多? 如果一个芯片上面电源就一根线的话,那不就是等着烧嘛…

我自己看驱动同事开发时候,经常看这个数据手册,这个理解下,蛮重要的。

小结:
pinmux 解决了什么问题,解决了功能引脚复用的问题,一个引脚支持多个功能,开发工程师自行配置需要的那个支持的功能。

PinMux 解决的问题

  • 现代微控制器集成了大量外设(UART、SPI、I2C、PWM等)
  • 物理引脚数量有限
  • 需要灵活地将外设功能映射到物理引脚

工作原理

  • 功能选择寄存器:决定引脚当前的功能(GPIO、UART、SPI等)
  • 电气特性配置:上拉/下拉电阻、驱动强度、施密特触发等
  • 输入/输出方向控制

典型应用场景

  • 开发板设计:允许灵活的外设布局
  • 产品定制:同一芯片可适应不同硬件设计
  • 功能切换:运行时动态改变引脚功能

配置方式

  • 寄存器直接操作
  • 厂商提供的配置工具(如TI的PinMux工具、NXP的MCUXpresso等)
  • 设备树配置(Linux嵌入式系统)

这里我们了解 、掌握的就是设备树

二、 pinctrl 语法

pinctrl 的语法可以看成两部分构成,一部分是客户端client,一部分是服务端 service.
client 端语法基本固定,服务端service端根据各个芯片平台厂商不同,会有一定的区别。

Client 端

在设备树中声明 pinctrl 引用,如下:

device_node {
    pinctrl-names = "default", "sleep", "active";
    pinctrl-0 = <&pin_config_default>;
    pinctrl-1 = <&pin_config_sleep>;
    pinctrl-2 = <&pin_config_active>;
};
  • pinctrl-names: 定义状态名称

  • pinctrl-N: 引用具体的引脚配置,指向 pinctrl 节点

注意点: 这个 pinctrl-N 属性值对应的是service 端的某个节点值,一一对应的关系。 举例如下图:
在这里插入图片描述

Service 服务端 -主流厂商语法

几大主流厂商语法结构

NXP i.MX 系列

iomuxc: iomuxc@20e0000 {
    compatible = "fsl,imx6ul-iomuxc";
    reg = <0x20e0000 0x4000>;
    
    uart1grp: uart1grp {
        fsl,pins = <
            MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
            MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
        >;
    };
};

分析:
给人感觉 fsl,pins 写法固定,里面的值大概分为三部分来解析:

  • MX6UL_PAD 厂家固定写死
  • UART1_TX_DATA、UART1_RX_DATA 引脚的名字
  • UART1_DCE_TX、UART1_DCE_RX 被设置的功能
    上面结合起来就是 把UART1_TX_DATA 引脚设置为UART1_DCE_TX功能;把UART1_RX_DATA引脚设置为UART1_DCE_RX
  • 0x1b0b1、0x1b0b1 电气属性,这个寄存器地址需要查芯片的数据手册,看看是什么电气属性功能

再举例如下:
在这里插入图片描述

三星(Samsung)平台设备树pinctrl配置

三星平台(如Exynos系列)的设备树pinctrl配置有其特定的语法格式,主要使用samsung,pins和samsung,pin-function等属性。

&pinctrl_0 {
    // UART配置示例
    uart0_data: uart0-data {
        samsung,pins = "gpa0-0", "gpa0-1";
        samsung,pin-function = <2>;  // 功能选择
        samsung,pin-pud = <0>;       // 上拉/下拉设置
        samsung,pin-drv = <0>;      // 驱动强度
    };
    
    // I2C配置示例
    i2c2_bus: i2c2-bus {
        samsung,pins = "gpa0-6", "gpa0-7";
        samsung,pin-function = <3>;
        samsung,pin-pud = <3>;
        samsung,pin-drv = <0>;
    };
    
    // GPIO配置示例
    sleep1: sleep-state {
        samsung,pins = "gpa0-0", "gpa0-1", "gpa0-2";
        samsung,pin-con-pdn = <2>;  // 睡眠状态配置
        samsung,pin-pud-pdn = <1>;
    };
};
关键属性说明
  • samsung,pins: 指定要配置的引脚列表,格式为"bank-num"(如"gpa0-0")
  • samsung,pin-function: 引脚复用功能选择
数值对应芯片手册中的ALT功能编号

例如0=GPIO, 1=ALT1, 2=ALT2等
  • samsung,pin-pud: 上拉/下拉电阻配置
0: 无上拉/下拉

1: 下拉

2: 上拉

3: 保留(通常表示不改变)
  • samsung,pin-drv: 驱动强度设置
数值越大驱动能力越强(具体级别参考芯片手册)
  • samsung,pin-val: 引脚初始输出值(用于输出配置)
  • 睡眠状态相关属性
samsung,pin-con-pdn: 睡眠状态下的引脚功能配置

samsung,pin-pud-pdn: 睡眠状态下的上拉/下拉配置

Rockchip 系列

pinctrl: pinctrl {
    compatible = "rockchip,rk3399-pinctrl";
    
    uart0 {
        uart0_xfer: uart0-xfer {
            rockchip,pins = <
                RK_GPIO1 16 RK_FUNC_1 &pcfg_pull_up
                RK_GPIO1 17 RK_FUNC_1 &pcfg_pull_none
            >;
        };
    };
};

上面的熟悉了,这里其实一样的道理:GPIO1 里面的16 和 17 引脚设置为 FUCN_1功能

下面给出其它教程里面的案例分析,可以看看参考下:
在这里插入图片描述

三、pinctrl 实例编写-将 led 的控制引脚复用为 GPIO 模式

去掉系统默认的led的节点

去掉RK3568 Linux源码中的led灯的节点,然后自己写一个。
路径:kernel/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
可以看到系统配置好的led 的设备数如下:
在这里插入图片描述

 leds: leds {
                compatible = "gpio-leds";
                work_led: work {
                        lable = "user1";
                        gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                        default-state = "on";
                };
        };

这里做如下修改,屏蔽掉 work_led 设备树配置:

在这里插入图片描述

发下问题

上面led灯 系统也没有通过配置pinctrl 配置gpio复用 ,为什么这个led灯还可以用?

底板原理图找gpio编号

在公开资料 topeet_rk3568_main_v1_7.pdf 底板原理图中找到gpio 是哪一个? 就是 GPIO0_B7
在这里插入图片描述

芯片数据手册中找到控制如上gpio的复用寄存器(引脚)

芯片手册:Rockchip RK3568 TRM Part2 V1.1-20210301.pdf
在这里插入图片描述
通过Name 查看它的描述怎样的:搜索PMU_GRF_GPIO0B_IOMUX_H

在这里插入图片描述
继续看寄存器PMU_GRF_GPIO0B_IOMUX_H 寄存器复位值 多少
在这里插入图片描述

在这里插入图片描述
所以,开发板启动的时候,默认的功能就是gpio功能:led灯对应的gpio默认就是gpio功能,所以不需要设置复用,而且软件其它位置也没有设置。

在rk平台开发板使用的设备树节点中添加自己的led gpio复用引脚功能

编辑 路径:kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v1.dts
在这里插入图片描述

引入了两个ditsi 文件,那么就打开其中一个,路径:vim rk3568-evb1-ddr4-v10.dtsi

写自己的client 端 led 设备树内容:

my_led: led {
compatible = "topeet,led";
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&rk_led_gpio>;
};

在这里插入图片描述

在这个文件中继续写Service 端代码,参考rk_485_ctl 对应的service 端,写led 相关的。
在这里插入图片描述

如下,我们写led 相关设备树 pinctrl 配置:
在这里插入图片描述

总结

  • 了解pinctrl 机制,设备树中的配置
  • 会手写pingctrl 设备树
  • 会查芯片数据手册,会看原理图
  • 因为不懂地方太多,所以磕磕绊绊,写到最后 才发下就是一个映射功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野火少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值