了解、熟悉 设备树中GPIO的配置,基本属性掌握
对后续开发打基础
文章目录
参考资料
设备树解析:gpio
RK3568驱动指南|第七期-设备树-第60章 实例分析:GPIO
Linux-驱动-设备树实案例分析-中断 对比设备树中中断相关属性配置来看,其中是有一些相似的配置之处。
一、基本属性
在Linux设备树(Device Tree)中,GPIO(通用输入输出)的配置是通过一系列标准属性来描述的。以下GPIO相关的关键属性及其用法:
属性gpio-controller
gpio-controller属性用于标识一个节点是GPIO控制器。这是一个布尔属性,不需要值。
gpio1: gpio@e0008000 {
compatible = "vendor,gpio-controller";
reg = <0xe0008000 0x1000>;
#gpio-cells = <2>;
gpio-controller;
};
属性#gpio-cells
#gpio-cells属性指定了使用该GPIO控制器时需要多少个cell来描述一个GPIO引脚。通常为2或3:
- 2 cells: <引脚号 标志>
- 3 cells: <bank 引脚号 标志>
#gpio-cells = <2>; // 最常见的配置
这个配合和中断 interrupt 里面的属性是不是特别像,几乎一致:
所以 这里直接给结论:
- #interrupt-cell 中断属性,对应的中断一个引脚描述是 interrupts
- #gpio-cells gpio属性,对应的gpio一个一个引脚描述是reset-gpios
属性reset-gpios
reset-gpios 是一个常用的设备属性,用于指定连接到设备复位引脚的GPIO。
reset-gpios = <&gpio_controller phandle flags>;
参数说明:
- &gpio_controller:指向GPIO控制器的phandle
- phandle:GPIO引脚号
- flags:GPIO标志(与#gpio-cells定义一致)
常用flags:
- GPIO_ACTIVE_HIGH (0):高电平有效
- GPIO_ACTIVE_LOW (1):低电平有效
- GPIO_OPEN_DRAIN (2):开漏输出
- GPIO_OPEN_SOURCE (4):开源输出
完整实例
gpio0: gpio@e000a000 {
compatible = "xlnx,zynq-gpio-1.0";
#gpio-cells = <2>;
gpio-controller;
reg = <0xe000a000 0x1000>;
};
ethernet@e000b000 {
compatible = "cdns,zynq-gem";
reg = <0xe000b000 0x1000>;
reset-gpios = <&gpio0 47 GPIO_ACTIVE_LOW>;
};
属性 gpio-ranges
gpio-ranges属性定义了GPIO控制器与引脚控制器(pinctrl)之间的映射关系。格式通常为:
gpio-ranges = <&pinctrl_controller offset gpio_offset count>;
例如:
gpio-ranges = <&pinctrl 0 0 32>; // 映射32个GPIO // 将GPIO 0-31映射到pinctrl的0-31
自己之前总是很难理解这个到底是什么意思,后来自己理解了,发现很简单的。
属性描述已经说了GPIO控制器 和 引脚控制器pinctrl 之间的映射关系。 为什么需要映射一次,那是因为 gpio 自己有自己的引脚编号,pinctrl 也有自己的引脚编号,如何联系起来。 就是通过这个属性映射过去。
比如,如上:表示 gpio 引脚标号从0 开始 总共有32个引脚编号,对应的是0到31编号映射到 pinctrl 引脚标号 0 -31 。
二、gpio设备数实例
我们首先用一下迅为rk3568 ,led 灯的原理图,如下:
分析:可以看到 GPIO0_B7
compatible 属性查找
Linux-驱动-设备树实案例分析-中断 这个篇章中我们写过中断的设备树, 在写一个设备树的基本结构当中,有几个参数是必须的,这个 compatible 就是必须的。
- 参考中断设备树实例编写
- 知道设备树中的参数值去那里找
led 的驱动文件, 然后找到 compatible 匹配值相关的部分:
路径:
“drivers/drivers/leds/leds-gpio.c”
static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", },
{},
};
所以,compatible 属性值为 gpio-leds
GPIO0_B7 RK 引脚名和 gpio 编号的宏定义查找
在引脚表述地方,会描述引脚名标号和宏定义,我们需要去找一下,去头文件中找,路径:
确认引脚编号查找
include/dt-bindings/pinctrl/rockchip.h
全文如下:
~/Linux/rk356x_linux/kernel/include/dt-bindings/pinctrl$ cat rockchip.h
/*
* Header providing constants for Rockchip pinctrl bindings.
*
* Copyright (c) 2013 MundoReader S.L.
* Author: Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
#define __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
#define RK_GPIO0 0
#define RK_GPIO1 1
#define RK_GPIO2 2
#define RK_GPIO3 3
#define RK_GPIO4 4
#define RK_GPIO6 6
#define RK_PA0 0
#define RK_PA1 1
#define RK_PA2 2
#define RK_PA3 3
#define RK_PA4 4
#define RK_PA5 5
#define RK_PA6 6
#define RK_PA7 7
#define RK_PB0 8
#define RK_PB1 9
#define RK_PB2 10
#define RK_PB3 11
#define RK_PB4 12
#define RK_PB5 13
#define RK_PB6 14
#define RK_PB7 15
#define RK_PC0 16
#define RK_PC1 17
#define RK_PC2 18
#define RK_PC3 19
#define RK_PC4 20
#define RK_PC5 21
#define RK_PC6 22
#define RK_PC7 23
#define RK_PD0 24
#define RK_PD1 25
#define RK_PD2 26
#define RK_PD3 27
#define RK_PD4 28
#define RK_PD5 29
#define RK_PD6 30
#define RK_PD7 31
#define RK_FUNC_GPIO 0
#define RK_FUNC_0 0
#define RK_FUNC_1 1
#define RK_FUNC_2 2
#define RK_FUNC_3 3
#define RK_FUNC_4 4
#define RK_FUNC_5 5
#define RK_FUNC_6 6
#define RK_FUNC_7 7
#define RK_FUNC_8 8
#define RK_FUNC_9 9
#define RK_FUNC_10 10
#define RK_FUNC_11 11
#define RK_FUNC_12 12
#define RK_FUNC_13 13
#define RK_FUNC_14 14
#define RK_FUNC_15 15
#endif
wfc123@ubuntu:~/Linux/rk356x_linux/kernel/include/dt-bindings/pinctrl$
确认gpio 极性
目录文件路径:
include/dt-bindings/gpio/gpio.h
wfc123@ubuntu:~/Linux/rk356x_linux/kernel/include/dt-bindings/gpio$ cat gpio.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This header provides constants for most GPIO bindings.
*
* Most GPIO bindings include a flags cell as part of the GPIO specifier.
* In most cases, the format of the flags cell uses the standard values
* defined in this header.
*/
#ifndef _DT_BINDINGS_GPIO_GPIO_H
#define _DT_BINDINGS_GPIO_GPIO_H
/* Bit 0 express polarity */
#define GPIO_ACTIVE_HIGH 0
#define GPIO_ACTIVE_LOW 1
/* Bit 1 express single-endedness */
#define GPIO_PUSH_PULL 0
#define GPIO_SINGLE_ENDED 2
/* Bit 2 express Open drain or open source */
#define GPIO_LINE_OPEN_SOURCE 0
#define GPIO_LINE_OPEN_DRAIN 4
/*
* Open Drain/Collector is the combination of single-ended open drain interface.
* Open Source/Emitter is the combination of single-ended open source interface.
*/
#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN)
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE)
/* Bit 3 express GPIO suspend/resume and reset persistence */
#define GPIO_PERSISTENT 0
#define GPIO_TRANSITORY 8
#endif
wfc123@ubuntu:~/Linux/rk356x_linux/kernel/include/dt-bindings/gpio$
我们要找的不就是这两个值吗:GPIO_ACTIVE_HIGH 、GPIO_ACTIVE_LOW
设备树编写
如上分析,设备树编写如下:
/dts-v1/;
#include "dt-bindings/pinctrl/rockchip.h"
#include "dt-bindings/gpio/gpio.h"
/{
model = "This is my devicetree!";
led led@1 {
compatible = "gpio-leds";
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>
};
};
三、知识扩展-gpios 和 reset-gpios
如上,我们分析了几个属性,没有提到过gpios 属性,但是实际我们写设备树的时候居然用到了这个属性。而且这个属性和reset-gpios 属性描述的一模一样,那我们看看gpios 是做什么的。
在设备树(Device Tree)中,gpios 和 reset-gpios 都是用于描述 GPIO(通用输入输出)引脚的属性,但它们的用途和语义有所不同
gpios 属性
- 用途:gpios 是一个通用的属性,用于表示设备使用的 GPIO 引脚。它通常用于设备的核心功能,比如控制电源、使能信号、数据线等。
- 语法示例:
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; // 使用 GPIO0 的第 12 脚,高电平有效
- 特点
通常由设备的驱动程序直接解析和使用。
可以用于任何 GPIO 相关的功能,没有特定的语义限制。
在 Linux 内核中,通常使用 gpiod_get() 或类似的 API 获取这个 GPIO
reset-gpios 属性
- 用途:reset-gpios 是一个具有明确语义的属性,专门用于描述设备的复位(Reset)信号线。它通常用于控制硬件复位(如拉低或拉高复位引脚)。
- 语法示例:
reset-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; // 使用 GPIO1 的第 5 脚,低电平有效
- 特点
语义明确,表示这是一个复位控制引脚。
通常由内核的复位框架(reset framework)或设备驱动在初始化时使用,用于复位设备。
在 Linux 内核中,可以使用 devm_gpiod_get(dev, “reset”, GPIOD_OUT_HIGH) 等 API 获取
区别与联系
特性 | gpios | reset-gpios |
---|---|---|
用途 | 通用 | GPIO 功能 |
语义明确性 | 无特定语义,取决于驱动 | 明确表示复位引脚 |
典型使用场景 | 电源使能、中断、数据线等 | 硬件复位控制 |
内核 API | gpiod_get() | devm_gpiod_get(…, “reset”, …) |
设备树绑定规范 | 通用,适用于大多数 GPIO | 特定功能,符合复位信号约定 |
为什么需要区分
- 码可读性:reset-gpios 让驱动和内核框架明确知道这是一个复位引脚,而不是普通的 GPIO。
- 标准化:内核的复位子系统(reset subsystem)可以自动处理这类引脚,比如在设备初始化或电源管理时进行复位操作。
- 避免冲突:某些硬件可能同时需要多个 GPIO,比如一个用于复位,另一个用于中断。使用专用属性(如 reset-gpios、interrupt-gpios)可以避免混淆。
示例
// 设备树片段
device {
// 通用 GPIO,用途由驱动决定
gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
// 专用于复位的 GPIO
reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
// 专用于中断的 GPIO
interrupt-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
};
总结
- 了解了gpio 在设备树中的几个属性,会写gpio相关的设备树
- 对比interrupt 中断关联的设备树,有相似之处
- 为后面设备树的应用打一个基础