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 = <&pinctrl1 19 52 1>;
};
其中黄色背景那一行的含义是:将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的改动。
patch:https://github.com/wowotechX/linux/commit/cf4d492855d0619772876bc8494b7e180c6a4232
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. 参考文档
[1] linux内核中的GPIO系统之(4):pinctrl驱动的理解和总结
[2] linux内核中的GPIO系统之(5):gpio subsysem和pinctrl subsystem之间的耦合
[3] X-025-KERNEL-Linux gpio driver的移植之基本功能
[4] X-023-KERNEL-Linux pinctrl driver的移植
[5] Schematics_Bubblegum96.pdf
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
标签: driver GPIO porting pinctrl range

评论:
功能
最新评论
- wangjing
写得太好了 - wangjing
写得太好了! - DRAM
圖面都沒辦法顯示出來好像掛點了。 - Simbr
bus至少是不是还有个subsystem? - troy
@testtest:只要ldrex-modify-strex... - gh
Linux 内核在 sparse 内存模型基础上实现了vme...
文章分类
随机文章
文章存档
- 2025年4月(5)
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2017-11-10 10:54
当时考虑到不同chip通用性使用了gpiochip_add_pin_range function
现在看看在DTS里面原来这么方便。