Linux驱动设备树-GPIO分析

了解、熟悉 设备树中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 获取

区别与联系

特性gpiosreset-gpios
用途通用GPIO 功能
语义明确性无特定语义,取决于驱动明确表示复位引脚
典型使用场景电源使能、中断、数据线等硬件复位控制
内核 APIgpiod_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 中断关联的设备树,有相似之处
  • 为后面设备树的应用打一个基础
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

野火少年

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

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

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

打赏作者

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

抵扣说明:

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

余额充值