X-026-KERNEL-Linux gpio driver的移植之gpio range
作者:wowo 发布于:2017-9-27 22:27
分类:X Project
1. 前言
我们在[1][2]中提到过,鉴于gpio的特殊性,pinctrl subsystem特意留了一个后门(gpio range),gpio driver可以通过这个后门直接向pinctrl subsystem申请将某个pin用作gpio功能。本文将根据一个简单的示例,介绍这个后门的使用方法,以加深对相关机制的理解。
注1:本文的测试方法和[3]中的一致,即:通过gpiolib sysfs api控制LED0(GPIOA19)的亮灭,因而不再罗列详细步骤。
2. 移植步骤
由[2]可知,gpio range的主要目的就是将gpio命名空间(gpio)转换为pinctrl命名空间(pin),并由pinctrl subsystem访问硬件实现gpio有关的功能控制。因此gpio range的移植步骤注要包括:
2.1 pinctrl命名空间和gpio命名空间的定义
参考”X-025-KERNEL-Linux gpio driver的移植之基本功能[3]”中有关gpiochip的实现,本例中的GPIOA19的gpio命名空间为:
gpiochip:gpioa
编号:19
同理,按照“X-023-KERNEL-Linux pinctrl driver的移植[4]”中的方法,结合bubblegum-96的原理图,我们可以把GPIOA19所在的管脚编号为"F3",它对应的pinctrl命名空间为:
pin controller:pinctrl@0xe01b0000
编号:52
@@ -68,6 +68,7 @@ static const struct pinctrl_pin_desc s900_pins[] = {
PINCTRL_PIN(15, "B6"),
PINCTRL_PIN(24, "C5"),
PINCTRL_PIN(37, "D8"),
+ PINCTRL_PIN(52, "F3"),
PINCTRL_PIN(60, "G1"),
PINCTRL_PIN(61, "G2"),
};
2.2 将gpio number转换为pin number
命名空间定义完成后,可以按照[2]中的步骤,在dts中定义一个gpio range,将gpio number转换为pin number,如下:
@@ -39,7 +39,7 @@
clock-frequency = <24000000>;
};
- pinctrl@0xe01b0000 {
+ pinctrl1: pinctrl@0xe01b0000 {
compatible = "actions,s900-pinctrl";
reg = <0 0="" 0xe01b0000="" 0x550="">;
@@ -56,6 +56,7 @@
gpioa: gpio@0xe01b0000 {
compatible = "actions,s900-gpio";
reg = <0 0="" 12="" 0xe01b0000="">;
base = <0>;
+ gpio-ranges = ;
};
其中黄色背景那一行的含义是:将gpioa中的19号gpio,和pinctrl1中的52号pin,对应。
2.3 修改gpio driver和pinctrl driver,二者配合,完成gpio的request、free、direction_input以及direction_output等操作
1)修改pinctrl driver,实现pinmux_ops中gpio_request_enable、gpio_disable_free、gpio_set_direction等回调函数
这三个API的输入参数都是range指针和offset(如下所示),通过它们可以找到这个GPIO所在的gpiochip、GPIO bank、GPIO number、对应pin所在的pin controller、pin number等信息。基于这些信息,可以获得相应的硬件信息(寄存器、bit偏移等)。
int (*gpio_request_enable) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset);
void (*gpio_disable_free) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset);
int (*gpio_set_direction) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset,
bool input);
2)修改gpio chip的.request、.free、.direction_input、.direction_output等回调函数,让它们调用pinctrl subsystem提供的相关API,如下:
int pinctrl_request_gpio(unsigned gpio) ;
void pinctrl_free_gpio(unsigned gpio) ;
int pinctrl_gpio_direction_input(unsigned gpio);
int pinctrl_gpio_direction_output(unsigned gpio);
注2:有些硬件平台,在完成上面步骤1)的时候,可能会遇到一些困扰,例如怎么根据gpio和pin的信息,找到对应的硬件控制信息(寄存器、bit偏移等),这时我们可以灵活处理。例如在本文例子所使用的bubblegum-96平台上,gpio的pinmux功能并没有单独的寄存器控制,而是通过gpio的in或者out功能的使能,覆盖其它的pinmux功能。此时我们可以把硬件配置的操作交给gpio driver,而pinctrl driver只处理管脚的互斥。具体可参考下面patch的改动。
3. 测试步骤
请参考[3]中的测试。测试结果如下(看到s900_gpio_request_enable中的打印,就说明我们的移植成功了):
/ # mkdir /sys
/ # mount -t sysfs /sys /sys
/ # echo 19 > /sys/class/gpio/export
[ 55.136218] owl_pinctrl e01b0000.pinctrl: s900_gpio_request_enable, range(19/52/1), offset 52
/ # echo out > /sys/class/gpio/gpio19/direction
[ 86.886343] owl_gpio e01b0000.gpio: offset 19, value 0
/ # echo 1 > /sys/class/gpio/gpio19/value
[ 100.223812] owl_gpio e01b0000.gpio: offset 19, value 1
/ # echo 0 > /sys/class/gpio/gpio19/value
[ 120.467468] owl_gpio e01b0000.gpio: offset 19, value 0
4. 参考文档
[5] Schematics_Bubblegum96.pdf
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
评论:
bigpillow
2017-11-10 10:54
刚写完一套GPIO driver.
当时考虑到不同chip通用性使用了gpiochip_add_pin_range function
现在看看在DTS里面原来这么方便。
发表评论:
昵称
邮件地址 (选填)
个人主页 (选填)