About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / zh_CN / gpio.txt




Custom Search

Based on kernel version 3.13. Page generated on 2014-01-20 22:05 EST.

1	Chinese translated version of Documentation/gpio.txt
2	
3	If you have any comment or update to the content, please contact the
4	original document maintainer directly.  However, if you have a problem
5	communicating in English you can also ask the Chinese maintainer for
6	help.  Contact the Chinese maintainer if this translation is outdated
7	or if there is a problem with the translation.
8	
9	Maintainer: Grant Likely <grant.likely@secretlab.ca>
10			Linus Walleij <linus.walleij@linaro.org>
11	Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
12	---------------------------------------------------------------------
13	Documentation/gpio.txt 的中文翻译
14	
15	如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
16	交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
17	译存在问题,请联系中文版维护者。
18	英文版维护者: Grant Likely <grant.likely@secretlab.ca>
19			Linus Walleij <linus.walleij@linaro.org>
20	中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
21	中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
22	中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
23	
24	
25	以下为正文
26	---------------------------------------------------------------------
27	GPIO 接口
28	
29	本文档提供了一个在Linux下访问GPIO的公约概述。
30	
31	这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的
32	__gpio_* 前缀。
33	
34	
35	什么是GPIO?
36	==========
37	"通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可
38	由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是
39	比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中
40	“球珠”的一个位。电路板原理图显示了 GPIO 与外部硬件的连接关系。
41	驱动可以编写成通用代码,以使板级启动代码可传递引脚配置数据给驱动。
42	
43	片上系统 (SOC) 处理器对 GPIO 有很大的依赖。在某些情况下,每个
44	非专用引脚都可配置为 GPIO,且大多数芯片都最少有一些 GPIO。
45	可编程逻辑器件(类似 FPGA) 可以方便地提供 GPIO。像电源管理和
46	音频编解码器这样的多功能芯片经常留有一些这样的引脚来帮助那些引脚
47	匮乏的 SOC。同时还有通过 I2C 或 SPI 串行总线连接的“GPIO扩展器”
48	芯片。大多数 PC 的南桥有一些拥有 GPIO 能力的引脚 (只有BIOS
49	固件才知道如何使用他们)。
50	
51	GPIO 的实际功能因系统而异。通常用法有:
52	
53	  - 输出值可写 (高电平=1,低电平=0)。一些芯片也有如何驱动这些值的选项,
54	    例如只允许输出一个值、支持“线与”及其他取值类似的模式(值得注意的是
55	    “开漏”信号)
56	
57	  - 输入值可读(1、0)。一些芯片支持引脚在配置为“输出”时回读,这对于类似
58	    “线与”的情况(以支持双向信号)是非常有用的。GPIO 控制器可能有输入
59	    去毛刺/消抖逻辑,这有时需要软件控制。
60	
61	  - 输入通常可作为 IRQ 信号,一般是沿触发,但有时是电平触发。这样的 IRQ
62	    可能配置为系统唤醒事件,以将系统从低功耗状态下唤醒。
63	
64	  - 通常一个 GPIO 根据不同产品电路板的需求,可以配置为输入或输出,也有仅
65	    支持单向的。
66	
67	  - 大部分 GPIO 可以在持有自旋锁时访问,但是通常由串行总线扩展的 GPIO
68	    不允许持有自旋锁。但某些系统也支持这种类型。
69	
70	对于给定的电路板,每个 GPIO 都用于某个特定的目的,如监控 MMC/SD 卡的
71	插入/移除、检测卡的写保护状态、驱动 LED、配置收发器、模拟串行总线、
72	复位硬件看门狗、感知开关状态等等。
73	
74	
75	GPIO 公约
76	=========
77	注意,这个叫做“公约”,因为这不是强制性的,不遵循这个公约是无伤大雅的,
78	因为此时可移植性并不重要。GPIO 常用于板级特定的电路逻辑,甚至可能
79	随着电路板的版本而改变,且不可能在不同走线的电路板上使用。仅有在少数
80	功能上才具有可移植性,其他功能是平台特定。这也是由于“胶合”的逻辑造成的。
81	
82	此外,这不需要任何的执行框架,只是一个接口。某个平台可能通过一个简单地
83	访问芯片寄存器的内联函数来实现它,其他平台可能通过委托一系列不同的GPIO
84	控制器的抽象函数来实现它。(有一些可选的代码能支持这种策略的实现,本文档
85	后面会介绍,但作为 GPIO 接口的客户端驱动程序必须与它的实现无关。)
86	
87	也就是说,如果在他们的平台上支持这个公约,驱动应尽可能的使用它。同时,平台
88	必须在 Kconfig 中选择 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB
89	选项。那些调用标准 GPIO 函数的驱动应该在 Kconfig 入口中声明依赖GENERIC_GPIO。
90	当驱动包含文件:
91	
92		#include <linux/gpio.h>
93	
94	则 GPIO 函数是可用,无论是“真实代码”还是经优化过的语句。如果你遵守
95	这个公约,当你的代码完成后,对其他的开发者来说会更容易看懂和维护。
96	
97	注意,这些操作包含所用平台的 I/O 屏障代码,驱动无须显式地调用他们。
98	
99	
100	标识 GPIO
101	---------
102	GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数
103	用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层
104	硬件的代码会忽略这些整数。
105	
106	平台会定义这些整数的用法,且通常使用 #define 来定义 GPIO,这样
107	板级特定的启动代码可以直接关联相应的原理图。相对来说,驱动应该仅使用
108	启动代码传递过来的 GPIO 编号,使用 platform_data 保存板级特定
109	引脚配置数据 (同时还有其他须要的板级特定数据),避免可能出现的问题。
110	
111	例如一个平台使用编号 32-159 来标识 GPIO,而在另一个平台使用编号0-63
112	标识一组 GPIO 控制器,64-79标识另一类 GPIO 控制器,且在一个含有
113	FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中,也可以
114	使用编号2000-2063来标识一个 I2C 接口的 GPIO 扩展器中的 GPIO。
115	
116	如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码
117	(如"-EINVAL"),那将使其永远不会是有效。来测试这样一个结构体中的编号
118	是否关联一个 GPIO,你可使用以下断言:
119	
120		int gpio_is_valid(int number);
121	
122	如果编号不存在,则请求和释放 GPIO 的函数将拒绝执行相关操作(见下文)。
123	其他编号也可能被拒绝,比如一个编号可能存在,但暂时在给定的电路上不可用。
124	
125	一个平台是否支持多个 GPIO 控制器为平台特定的实现问题,就像是否可以
126	在 GPIO 编号空间中有“空洞”和是否可以在运行时添加新的控制器一样。
127	这些问题会影响其他事情,包括相邻的 GPIO 编号是否存在等。
128	
129	使用 GPIO
130	---------
131	对于一个 GPIO,系统应该做的第一件事情就是通过 gpio_request()
132	函数分配它,见下文。
133	
134	接下来是设置I/O方向,这通常是在板级启动代码中为所使用的 GPIO 设置
135	platform_device 时完成。
136	
137		/* 设置为输入或输出, 返回 0 或负的错误代码 */
138		int gpio_direction_input(unsigned gpio);
139		int gpio_direction_output(unsigned gpio, int value);
140	
141	返回值为零代表成功,否则返回一个负的错误代码。这个返回值需要检查,因为
142	get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误。通常,
143	你应该在进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子
144	启动的早期、进程启动前使用他们也是可以的。
145	
146	对于作为输出的 GPIO,为其提供初始输出值,对于避免在系统启动期间出现
147	信号毛刺是很有帮助的。
148	
149	为了与传统的 GPIO 接口兼容, 在设置一个 GPIO 方向时,如果它还未被申请,
150	则隐含了申请那个 GPIO 的操作(见下文)。这种兼容性正在从可选的 gpiolib
151	框架中移除。
152	
153	如果这个 GPIO 编码不存在,或者特定的 GPIO 不能用于那种模式,则方向
154	设置可能失败。依赖启动固件来正确地设置方向通常是一个坏主意,因为它可能
155	除了启动Linux,并没有做更多的验证工作。(同理, 板子的启动代码可能需要
156	将这个复用的引脚设置为 GPIO,并正确地配置上拉/下拉电阻。)
157	
158	
159	访问自旋锁安全的 GPIO
160	-------------------
161	大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以
162	安全地在硬(非线程)中断例程和类似的上下文中完成。
163	
164	对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文),使用
165	以下的函数访问:
166	
167		/* GPIO 输入:返回零或非零 */
168		int gpio_get_value(unsigned gpio);
169	
170		/* GPIO 输出 */
171		void gpio_set_value(unsigned gpio, int value);
172	
173	GPIO值是布尔值,零表示低电平,非零表示高电平。当读取一个输出引脚的值时,
174	返回值应该是引脚上的值。这个值不总是和输出值相符,因为存在开漏输出信号和
175	输出延迟问题。
176	
177	以上的 get/set 函数无错误返回值,因为之前 gpio_direction_*()应已检查过
178	其是否为“无效GPIO”。此外,还需要注意的是并不是所有平台都可以从输出引脚
179	中读取数据,对于不能读取的引脚应总返回零。另外,对那些在原子上下文中无法
180	安全访问的 GPIO (译者注:因为访问可能导致休眠)使用这些函数是不合适的
181	(见下文)。
182	
183	在 GPIO 编号(还有输出、值)为常数的情况下,鼓励通过平台特定的实现来优化
184	这两个函数来访问 GPIO 值。这种情况(读写一个硬件寄存器)下只需要几条指令
185	是很正常的,且无须自旋锁。这种优化函数比起那些在子程序上花费许多指令的
186	函数可以使得模拟接口(译者注:例如 GPIO 模拟 I2C、1-wire 或 SPI)的
187	应用(在空间和时间上都)更具效率。
188	
189	
190	访问可能休眠的 GPIO
191	-----------------
192	某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些
193	GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其反馈。期间需要
194	休眠,这不能在 IRQ 例程(中断上下文)中执行。
195	
196	支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要
197	一个之前通过 gpio_request 分配到的有效 GPIO 编号):
198	
199		int gpio_cansleep(unsigned gpio);
200	
201	为了访问这种 GPIO,内核定义了一套不同的函数:
202	
203		/* GPIO 输入:返回零或非零 ,可能会休眠 */
204		int gpio_get_value_cansleep(unsigned gpio);
205	
206		/* GPIO 输出,可能会休眠 */
207		void gpio_set_value_cansleep(unsigned gpio, int value);
208	
209	
210	访问这样的 GPIO 需要一个允许休眠的上下文,例如线程 IRQ 处理例程,并用以上的
211	访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。
212	
213	除了这些访问函数可能休眠,且它们操作的 GPIO 不能在硬件 IRQ 处理例程中访问的
214	事实,这些处理例程实际上和自旋锁安全的函数是一样的。
215	
216	** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中,
217	因为它们可能也需要访问 GPIO 控制器芯片: (这些设置函数通常在板级启动代码或者
218	驱动探测/断开代码中,所以这是一个容易满足的约束条件。)
219	
220		gpio_direction_input()
221		gpio_direction_output()
222		gpio_request()
223	
224	## 	gpio_request_one()
225	##	gpio_request_array()
226	## 	gpio_free_array()
227	
228		gpio_free()
229		gpio_set_debounce()
230	
231	
232	
233	声明和释放 GPIO
234	----------------------------
235	为了有助于捕获系统配置错误,定义了两个函数。
236	
237		/* 申请 GPIO, 返回 0 或负的错误代码.
238		 * 非空标签可能有助于诊断.
239		 */
240		int gpio_request(unsigned gpio, const char *label);
241	
242		/* 释放之前声明的 GPIO */
243		void gpio_free(unsigned gpio);
244	
245	将无效的 GPIO 编码传递给 gpio_request()会导致失败,申请一个已使用这个
246	函数声明过的 GPIO 也会失败。gpio_request()的返回值必须检查。你应该在
247	进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子启动的早期、
248	进入进程之前是可以申请的。
249	
250	这个函数完成两个基本的目标。一是标识那些实际上已作为 GPIO 使用的信号线,
251	这样便于更好地诊断;系统可能需要服务几百个可用的 GPIO,但是对于任何一个
252	给定的电路板通常只有一些被使用。另一个目的是捕获冲突,查明错误:如两个或
253	更多驱动错误地认为他们已经独占了某个信号线,或是错误地认为移除一个管理着
254	某个已激活信号的驱动是安全的。也就是说,申请 GPIO 的作用类似一种锁机制。
255	
256	某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和
257	简单地关闭未使用时钟)。
258	
259	对于 GPIO 使用 pinctrl 子系统已知的引脚,子系统应该被告知其使用情况;
260	一个 gpiolib 驱动的 .request()操作应调用 pinctrl_request_gpio(),
261	而 gpiolib 驱动的 .free()操作应调用 pinctrl_free_gpio()。pinctrl
262	子系统允许 pinctrl_request_gpio()在某个引脚或引脚组以复用形式“属于”
263	一个设备时都成功返回。
264	
265	任何须将 GPIO 信号导向适当引脚的引脚复用硬件的编程应该发生在 GPIO
266	驱动的 .direction_input()或 .direction_output()函数中,以及
267	任何输出 GPIO 值的设置之后。这样可使从引脚特殊功能到 GPIO 的转换
268	不会在引脚产生毛刺波形。有时当用一个 GPIO 实现其信号驱动一个非 GPIO
269	硬件模块的解决方案时,就需要这种机制。
270	
271	某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的,GPIO 或引脚的
272	其他方面也需要配置,如上拉/下拉。平台软件应该在对这些 GPIO 调用
273	gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映射表,
274	使得 GPIO 的用户无须关注这些细节。
275	
276	还有一个值得注意的是在释放 GPIO 前,你必须停止使用它。
277	
278	
279	注意:申请一个 GPIO 并没有以任何方式配置它,只不过标识那个 GPIO 处于使用
280	状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。
281	考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数:
282	
283		/* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置,
284		 * 其他和 gpio_request()的参数和返回值相同
285		 *
286		 */
287		int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
288	
289		/* 在单个函数中申请多个 GPIO
290		 */
291		int gpio_request_array(struct gpio *array, size_t num);
292	
293		/* 在单个函数中释放多个 GPIO
294		 */
295		void gpio_free_array(struct gpio *array, size_t num);
296	
297	这里 'flags' 当前定义可指定以下属性:
298	
299		* GPIOF_DIR_IN		- 配置方向为输入
300		* GPIOF_DIR_OUT		- 配置方向为输出
301	
302		* GPIOF_INIT_LOW	- 在作为输出时,初始值为低电平
303		* GPIOF_INIT_HIGH	- 在作为输出时,初始值为高电平
304		* GPIOF_OPEN_DRAIN	- gpio引脚为开漏信号
305		* GPIOF_OPEN_SOURCE	- gpio引脚为源极开路信号
306	
307		* GPIOF_EXPORT_DIR_FIXED	- 将 gpio 导出到 sysfs,并保持方向
308		* GPIOF_EXPORT_DIR_CHANGEABLE	- 同样是导出, 但允许改变方向
309	
310	因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为:
311	
312		* GPIOF_IN		- 配置为输入
313		* GPIOF_OUT_INIT_LOW	- 配置为输出,并初始化为低电平
314		* GPIOF_OUT_INIT_HIGH	- 配置为输出,并初始化为高电平
315	
316	当设置 flag 为 GPIOF_OPEN_DRAIN 时,则假设引脚是开漏信号。这样的引脚
317	将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志,gpio库
318	将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下
319	通过置0使其输出低电平。
320	
321	当设置 flag 为 GPIOF_OPEN_SOURCE 时,则假设引脚为源极开路信号。这样的引脚
322	将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志,gpio库
323	将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下
324	通过置1使其输出高电平。
325	
326	将来这些标志可能扩展到支持更多的属性。
327	
328	更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有
329	这三个领域:
330	
331		struct gpio {
332			unsigned	gpio;
333			unsigned long	flags;
334			const char	*label;
335		};
336	
337	一个典型的用例:
338	
339		static struct gpio leds_gpios[] = {
340			{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */
341			{ 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* 默认关闭 */
342			{ 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* 默认关闭 */
343			{ 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* 默认关闭 */
344			{ ... },
345		};
346	
347		err = gpio_request_one(31, GPIOF_IN, "Reset Button");
348		if (err)
349			...
350	
351		err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
352		if (err)
353			...
354	
355		gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
356	
357	
358	GPIO 映射到 IRQ
359	--------------------
360	GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间
361	(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射:
362	
363		/* 映射 GPIO 编号到 IRQ 编号 */
364		int gpio_to_irq(unsigned gpio);
365	
366		/* 映射 IRQ 编号到 GPIO 编号 (尽量避免使用) */
367		int irq_to_gpio(unsigned irq);
368	
369	它们的返回值为对应命名空间的相关编号,或是负的错误代码(如果无法映射)。
370	(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的:使用一个
371	未通过 gpio_direction_input()配置为输入的 GPIO 编号,或者使用一个
372	并非来源于gpio_to_irq()的 IRQ 编号。
373	
374	这两个映射函数可能会在信号编号的加减计算过程上花些时间。它们不可休眠。
375	
376	gpio_to_irq()返回的非错误值可以传递给 request_irq()或者 free_irq()。
377	它们通常通过板级特定的初始化代码存放到平台设备的 IRQ 资源中。注意:IRQ
378	触发选项是 IRQ 接口的一部分,如 IRQF_TRIGGER_FALLING,系统唤醒能力
379	也是如此。
380	
381	irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所使用,
382	比如在 IRQ 是沿触发时初始化或更新驱动状态。注意某些平台不支持反映射,所以
383	你应该尽量避免使用它。
384	
385	
386	模拟开漏信号
387	----------------------------
388	有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点,逻辑电平
389	结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语
390	适用于 CMOS 管;而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这
391	有时被称为“线与”。实际上,从负逻辑(低电平为真)的角度来看,这是一个“线或”。
392	
393	一个开漏信号的常见例子是共享的低电平使能 IRQ 信号线。此外,有时双向数据总线
394	信号也使用漏极开路信号。
395	
396	某些 GPIO 控制器直接支持开漏输出,还有许多不支持。当你需要开漏信号,但
397	硬件又不直接支持的时候,一个常用的方法是用任何即可作输入也可作输出的 GPIO
398	引脚来模拟:
399	
400	 LOW:	gpio_direction_output(gpio, 0) ... 这代码驱动信号并覆盖
401		上拉配置。
402	
403	 HIGH:	gpio_direction_input(gpio) ... 这代码关闭输出,所以上拉电阻
404		(或其他的一些器件)控制了信号。
405	
406	如果你将信号线“驱动”为高电平,但是 gpio_get_value(gpio)报告了一个
407	低电平(在适当的上升时间后),你就可以知道是其他的一些组件将共享信号线拉低了。
408	这不一定是错误的。一个常见的例子就是 I2C 时钟的延长:一个需要较慢时钟的
409	从设备延迟 SCK 的上升沿,而 I2C 主设备相应地调整其信号传输速率。
410	
411	
412	这些公约忽略了什么?
413	================
414	这些公约忽略的最大一件事就是引脚复用,因为这属于高度芯片特定的属性且
415	没有可移植性。某个平台可能不需要明确的复用信息;有的对于任意给定的引脚
416	可能只有两个功能选项;有的可能每个引脚有八个功能选项;有的可能可以将
417	几个引脚中的任何一个作为给定的 GPIO。(是的,这些例子都来自于当前运行
418	Linux 的系统。)
419	
420	在某些系统中,与引脚复用相关的是配置和使能集成的上、下拉模式。并不是所有
421	平台都支持这种模式,或者不会以相同的方式来支持这种模式;且任何给定的电路板
422	可能使用外置的上拉(或下拉)电阻,这时芯片上的就不应该使用。(当一个电路需要
423	5kOhm 的拉动电阻,芯片上的 100 kOhm 电阻就不能做到。)同样的,驱动能力
424	(2 mA vs 20 mA)和电压(1.8V vs 3.3V)是平台特定问题,就像模型一样在
425	可配置引脚和 GPIO 之间(没)有一一对应的关系。
426	
427	还有其他一些系统特定的机制没有在这里指出,例如上述的输入去毛刺和线与输出
428	选项。硬件可能支持批量读或写 GPIO,但是那一般是配置相关的:对于处于同一
429	块区(bank)的GPIO。(GPIO 通常以 16 或 32 个组成一个区块,一个给定的
430	片上系统一般有几个这样的区块。)某些系统可以通过输出 GPIO 触发 IRQ,
431	或者从并非以 GPIO 管理的引脚取值。这些机制的相关代码没有必要具有可移植性。
432	
433	当前,动态定义 GPIO 并不是标准的,例如作为配置一个带有某些 GPIO 扩展器的
434	附加电路板的副作用。
435	
436	GPIO 实现者的框架 (可选)
437	=====================
438	前面提到了,有一个可选的实现框架,让平台使用相同的编程接口,更加简单地支持
439	不同种类的 GPIO 控制器。这个框架称为"gpiolib"。
440	
441	作为一个辅助调试功能,如果 debugfs 可用,就会有一个 /sys/kernel/debug/gpio
442	文件。通过这个框架,它可以列出所有注册的控制器,以及当前正在使用中的 GPIO
443	的状态。
444	
445	
446	控制器驱动: gpio_chip
447	-------------------
448	在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip",他包含了
449	该类型的每个控制器的常用信息:
450	
451	 - 设置 GPIO 方向的方法
452	 - 用于访问 GPIO 值的方法
453	 - 告知调用其方法是否可能休眠的标志
454	 - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
455	 - 诊断标签
456	
457	也包含了来自 device.platform_data 的每个实例的数据:它第一个 GPIO 的
458	编号和它可用的 GPIO 的数量。
459	
460	实现 gpio_chip 的代码应支持多控制器实例,这可能使用驱动模型。那些代码要
461	配置每个 gpio_chip,并发起gpiochip_add()。卸载一个 GPIO 控制器很少见,
462	但在必要的时候可以使用 gpiochip_remove()。
463	
464	大部分 gpio_chip 是一个实例特定结构体的一部分,而并不将 GPIO 接口单独
465	暴露出来,比如编址、电源管理等。类似编解码器这样的芯片会有复杂的非 GPIO
466	状态。
467	
468	任何一个 debugfs 信息导出方法通常应该忽略还未申请作为 GPIO 的信号线。
469	他们可以使用 gpiochip_is_requested()测试,当这个 GPIO 已经申请过了
470	就返回相关的标签,否则返回 NULL。
471	
472	
473	平台支持
474	-------
475	为了支持这个框架,一个平台的 Kconfig 文件将会 "select"(选择)
476	ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,并让它的
477	<asm/gpio.h> 包含 <asm-generic/gpio.h>,同时定义三个方法:
478	gpio_get_value()、gpio_set_value()和 gpio_cansleep()。
479	
480	它也应提供一个 ARCH_NR_GPIOS 的定义值,这样可以更好地反映该平台 GPIO
481	的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和
482	GPIO 扩展器中的数据。)
483	
484	ARCH_REQUIRE_GPIOLIB 意味着 gpiolib 核心在这个构架中将总是编译进内核。
485	
486	ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以
487	使能它,并将其编译进内核(可选)。
488	
489	如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以
490	被用户使能。
491	
492	以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度:
493	
494	  #define gpio_get_value	__gpio_get_value
495	  #define gpio_set_value	__gpio_set_value
496	  #define gpio_cansleep		__gpio_cansleep
497	
498	这些定义可以用更理想的实现方法替代,那就是使用经过逻辑优化的内联函数来访问
499	基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”,
500	读取或设置它可能只需少则两或三个指令,且不会休眠。当这样的优化无法实现时,
501	那些函数必须使用框架提供的代码,那就至少要几十条指令才可以实现。对于用 GPIO
502	模拟的 I/O 接口, 如此精简指令是很有意义的。
503	
504	对于片上系统,平台特定代码为片上 GPIO 每个区(bank)定义并注册 gpio_chip
505	实例。那些 GPIO 应该根据芯片厂商的文档进行编码/标签,并直接和电路板原理图
506	对应。他们应该开始于零并终止于平台特定的限制。这些 GPIO(代码)通常从
507	arch_initcall()或者更早的地方集成进平台初始化代码,使这些 GPIO 总是可用,
508	且他们通常可以作为 IRQ 使用。
509	
510	板级支持
511	-------
512	对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA
513	或 CPLD),大多数常用板级特定代码都可以注册控制器设备,并保证他们的驱动知道
514	gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO
515	编号之后。
516	
517	例如板级启动代码应该创建结构体指明芯片公开的 GPIO 范围,并使用 platform_data
518	将其传递给每个 GPIO 扩展器芯片。然后芯片驱动中的 probe()例程可以将这个
519	数据传递给 gpiochip_add()。
520	
521	初始化顺序很重要。例如,如果一个设备依赖基于 I2C 的(扩展)GPIO,那么它的
522	probe()例程就应该在那个 GPIO 有效以后才可以被调用。这意味着设备应该在
523	GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是让这种 gpio_chip
524	控制器向板级特定代码提供 setup()和 teardown()回调函数。一旦所有必须的
525	资源可用之后,这些板级特定的回调函数将会注册设备,并可以在这些 GPIO 控制器
526	设备变成无效时移除它们。
527	
528	
529	用户空间的 Sysfs 接口(可选)
530	========================
531	使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。
532	这不同于 debugfs 接口,因为它提供的是对 GPIO方向和值的控制,而不只显示
533	一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。
534	
535	例如,通过适当的系统硬件文档,用户空间可以知道 GIOP #23 控制 Flash
536	存储器的写保护(用于保护其中 Bootloader 分区)。产品的系统升级可能需要
537	临时解除这个保护:首先导入一个 GPIO,改变其输出状态,然后在重新使能写保护
538	前升级代码。通常情况下,GPIO #23 是不会被触及的,并且内核也不需要知道他。
539	
540	根据适当的硬件文档,某些系统的用户空间 GPIO 可以用于确定系统配置数据,
541	这些数据是标准内核不知道的。在某些任务中,简单的用户空间 GPIO 驱动可能是
542	系统真正需要的。
543	
544	注意:标准内核驱动中已经存在通用的“LED 和按键”GPIO 任务,分别是:
545	"leds-gpio" 和 "gpio_keys"。请使用这些来替代直接访问 GPIO,因为集成在
546	内核框架中的这类驱动比你在用户空间的代码更好。
547	
548	
549	Sysfs 中的路径
550	--------------
551	在/sys/class/gpio 中有 3 类入口:
552	
553	   -	用于在用户空间控制 GPIO 的控制接口;
554	
555	   -	GPIOs 本身;以及
556	
557	   -	GPIO 控制器 ("gpio_chip" 实例)。
558	
559	除了这些标准的文件,还包含“device”符号链接。
560	
561	控制接口是只写的:
562	
563	    /sys/class/gpio/
564	
565	    	"export" ... 用户空间可以通过写其编号到这个文件,要求内核导出
566			一个 GPIO 的控制到用户空间。
567	
568			例如: 如果内核代码没有申请 GPIO #19,"echo 19 > export"
569			将会为 GPIO #19 创建一个 "gpio19" 节点。
570	
571	    	"unexport" ... 导出到用户空间的逆操作。
572	
573			例如: "echo 19 > unexport" 将会移除使用"export"文件导出的
574			"gpio19" 节点。
575	
576	GPIO 信号的路径类似 /sys/class/gpio/gpio42/ (对于 GPIO #42 来说),
577	并有如下的读/写属性:
578	
579	    /sys/class/gpio/gpioN/
580	
581		"direction" ... 读取得到 "in" 或 "out"。这个值通常运行写入。
582			写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行,
583			"low" 或 "high" 的电平值应该写入 GPIO 的配置,作为初始输出值。
584	
585			注意:如果内核不支持改变 GPIO 的方向,或者在导出时内核代码没有
586			明确允许用户空间可以重新配置 GPIO 方向,那么这个属性将不存在。
587	
588		"value" ... 读取得到 0 (低电平) 或 1 (高电平)。如果 GPIO 配置为
589			输出,这个值允许写操作。任何非零值都以高电平看待。
590	
591			如果引脚可以配置为中断信号,且如果已经配置了产生中断的模式
592			(见"edge"的描述),你可以对这个文件使用轮询操作(poll(2)),
593			且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2)),
594			请在 events 中设置 POLLPRI 和 POLLERR。如果你使用轮询操作
595			(select(2)),请在 exceptfds 设置你期望的文件描述符。在
596			轮询操作(poll(2))返回之后,既可以通过 lseek(2)操作读取
597			sysfs 文件的开始部分,也可以关闭这个文件并重新打开它来读取数据。
598	
599		"edge" ... 读取得到“none”、“rising”、“falling”或者“both”。
600			将这些字符串写入这个文件可以选择沿触发模式,会使得轮询操作
601			(select(2))在"value"文件中返回。
602	
603			这个文件仅有在这个引脚可以配置为可产生中断输入引脚时,才存在。
604	
605		"active_low" ... 读取得到 0 (假) 或 1 (真)。写入任何非零值可以
606			翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising"
607			和 "falling" 沿触发模式的轮询操作(poll(2))将会遵循这个设置。
608	
609	GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
610	开始实现控制的控制器),并有着以下只读属性:
611	
612	    /sys/class/gpio/gpiochipN/
613	
614	    	"base" ... 与以上的 N 相同,代表此芯片管理的第一个 GPIO 的编号
615	
616	    	"label" ... 用于诊断 (并不总是只有唯一值)
617	
618	    	"ngpio" ... 此控制器所管理的 GPIO 数量(而 GPIO 编号从 N 到
619	    		N + ngpio - 1)
620	
621	大多数情况下,电路板的文档应当标明每个 GPIO 的使用目的。但是那些编号并不总是
622	固定的,例如在扩展卡上的 GPIO会根据所使用的主板或所在堆叠架构中其他的板子而
623	有所不同。在这种情况下,你可能需要使用 gpiochip 节点(尽可能地结合电路图)来
624	确定给定信号所用的 GPIO 编号。
625	
626	
627	从内核代码中导出
628	-------------
629	内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出:
630	
631		/* 导出 GPIO 到用户空间 */
632		int gpio_export(unsigned gpio, bool direction_may_change);
633	
634		/* gpio_export()的逆操作 */
635		void gpio_unexport();
636	
637		/* 创建一个 sysfs 连接到已导出的 GPIO 节点 */
638		int gpio_export_link(struct device *dev, const char *name,
639			unsigned gpio)
640	
641		/* 改变 sysfs 中的一个 GPIO 节点的极性 */
642		int gpio_sysfs_set_active_low(unsigned gpio, int value);
643	
644	在一个内核驱动申请一个 GPIO 之后,它可以通过 gpio_export()使其在 sysfs
645	接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间
646	破坏重要的系统状态。
647	
648	这个明确的导出有助于(通过使某些实验更容易来)调试,也可以提供一个始终存在的接口,
649	与文档配合作为板级支持包的一部分。
650	
651	在 GPIO 被导出之后,gpio_export_link()允许在 sysfs 文件系统的任何地方
652	创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的
653	名字,在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。
654	
655	驱动可以使用 gpio_sysfs_set_active_low() 来在用户空间隐藏电路板之间
656	GPIO 线的极性差异。这个仅对 sysfs 接口起作用。极性的改变可以在 gpio_export()
657	前后进行,且之前使能的轮询操作(poll(2))支持(上升或下降沿)将会被重新配置来遵循
658	这个设置。
Hide Line Numbers
About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Information is copyright its respective author. All material is available from the Linux Kernel Source distributed under a GPL License. This page is provided as a free service by mjmwired.net.