7.10.2.GPIO子系统概念
也来问4个问题:
1什么是GPIO子系统?配置GPIO引脚电气特性的系统;
2如何表现?找到gpio.txt看下,
1) gpios property
需要用"[
gpio1: gpio1 { //名字
gpio-controller
#gpio-cells = <2>;
};
data-gpios = <&gpio1 12 0>,
<&gpio1 13 0>,
通常定义GPIO的标志位都是用include/dt-bindings/gpio/gpio.h中的宏来定义,看下这个文件:
/*
* 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
/*
* Open Drain/Collector is the combination of single-ended active low,
* Open Source/Emitter is the combination of single-ended active high.
*/
#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW) //开漏
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH)
#endif
Example of a node using GPIOs:
node {
enable-gpios = <&qe_pio_e 18 GPIO_ACTIVE_HIGH>; //18是引脚数
};
GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
Example:
gpio-controller@00000000 {
compatible = "foo";
reg = <0x00000000 0x1000>;
gpio-controller; //必须有
#gpio-cells = <2>; //必须有
ngpios = <18>;
gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R",
"LED G", "LED B", "Col A", "Col B", "Col C", "Col D",
"Row A", "Row B", "Row C", "Row D", "NMI button",
"poweroff", "reset";
}
2.1) gpio- and pin-controller interaction
Gpio-和pin controller的关联:Some or all of the GPIOs provided by a GPIO controller may be routed to pins on the package via a pin controller. This allows muxing those pins between GPIO and other functions.
基本概念已经理清楚了,小结:
3如何使用?分为设备树中使用和代码中使用;
3.1设备树中使用
//client device
leds {
compatible = "gpio-leds";
pinctrl-names = "default"; //1种状态,default
pinctrl-0 = <&pinctrl_leds>; //引脚defaul状态在pinctrl_leds定义
};
************************************************************************
//pin controller
&iomuxc_snvs {
pinctrl-names = "default_snvs";
imx6ul-evk {
pinctrl_leds: ledgrp {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x000110A0
>; //0x000110A0代表什么意思???
};
};
};
搜索参考手册并没有找到这个变量,MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03,google一下找到https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/dts/imx6ull-pinfunc-snvs.h提到了这个变量的定义在linux-xlnx/arch/arm/boot/dts/imx6ull-pinfunc-snvs.h中,好吧和.dts在一个文件夹中,看下它的具体内容:
#ifndef __DTS_IMX6ULL_PINFUNC_SNVS_H
#define __DTS_IMX6ULL_PINFUNC_SNVS_H
/*
* The pin function ID is a tuple of
*
*/
#define MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x0014 0x0058 0x0000 0x5 0x0//后面这一串是什么意思???
#endif /* __DTS_IMX6ULL_PINFUNC_SNVS_H */
根据ZDYZ的手册分析下:PAD_SNVS_TAMPER3的复用功能就是GPIO5_IO03,后面5个配置值分别对应
0x0014:mux_reg寄存器偏移地址,设备树中的 iomuxc_snvs节点就是 iomuxc_snvs外设对应的节点,根 据 其 reg 属 性 可 知 iomuxc_snvs外 设 寄 存 器 起 始 地 址 为 0x02290000。因此0x02290000+0x0014 = 0x02290014,即IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3的地址。
iomuxc_snvs: iomuxc-snvs@02290000 {
compatible = "fsl,imx6ull-iomuxc-snvs";
reg = <0x02290000 0x10000>;
};
0x0058:conf_reg 寄存器偏移地址,和 mux_reg 一样, 0x02290000+0x0058=0x02290058,即IOMUXC_SNVS_SW_PAD_CTL_PAD_SNVS_TAMPER3的地址。
0x0000:input_reg 寄存器偏移地址,有些外设有 input_reg 寄存器,有 input_reg 寄存器的外设需要配置 input_reg 寄存器。没有的话就不需要设置。
0x5:mux_reg 寄 存 器 值 , 在 这 里 就 相 当 于 设 置IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 寄存器为 0x5,也即是设置 PAD_SNVS_TAMPER3这个 PIN 复用为 GPIO5_IO03。
0x0:input_reg 寄存器值,在这里无效。
这就是对宏分析,发现并没有conf_reg寄存器的值, config_reg 寄存器是设置一个PIN 的电气特性的,这么重要的寄存器怎么没有值呢?回到示例代码中, 0x000110A0 就是 conf_reg 寄存器值!此值由用户自行设置,通过此值来设置一个 IO 的上 /下拉、驱动能力和速度等。在这里就相当于设置寄存器IOMUXC_SNVS_SW_PAD_CTL_PAD_SNVS_TAMPER3的值为 0x000110A0 ,即0b0001,0001,0000,1010,0000,具体代表什么意思看下参考手册。
3.2驱动代码中使用
也就是 GPIO 子系统的接口函数是什么?GPIO 子系统有两套接口: 基于描述符的(descriptor-based)、老的(legacy)。前者的函数都有前缀“gpiod_”,它使用 gpio_desc 结构体来表示一个引脚;后者的函数都有前缀“gpio_”,它使用一个整数来表示一个引脚。要操作一个引脚,首先要 get 引脚,然后设置方向,读值、写值。
“在 GPIO 子系统中,每注册一个 GPIO Controller 时会确定它的“base number”,那么这个控制器里的第 n 号引脚的号码就是: base number + n。但是如果硬件有变化、设备树有变化,这个 base number 并不能保证是固定的,应该查看 sysfs 来确定 base number。”
3.3sysfs 中的访问方法
这一块内容再补充。