我是靠谱客的博主 靓丽长颈鹿,最近开发中收集的这篇文章主要介绍linux下的gpio转串口驱动,X-026-KERNEL-Linux gpio driver的移植之gpio range,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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。c6a6308114f401be7df747ae46f2b4db.png

评论:

bigpillow

2017-11-10 10:54

刚写完一套GPIO driver.

当时考虑到不同chip通用性使用了gpiochip_add_pin_range function

现在看看在DTS里面原来这么方便。

发表评论:

昵称

邮件地址 (选填)

个人主页 (选填)

d4e3789769c8ad44c7e403863bfc3822.png

最后

以上就是靓丽长颈鹿为你收集整理的linux下的gpio转串口驱动,X-026-KERNEL-Linux gpio driver的移植之gpio range的全部内容,希望文章能够帮你解决linux下的gpio转串口驱动,X-026-KERNEL-Linux gpio driver的移植之gpio range所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部