gpio 子系统都是通过sysfs 访问方法

GPIO一般都分为几组,每组中有若干个引脚。所以在使用GPIO子系统之前,就要先确定它所在的组以及在组中的哪一个。在设备树中,“GPIO组” 就是一个 GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它的名字,比如“gpio1”,然后指定要用它里面的哪个引脚,比如 <&gpio1 0>。

“gpio-controller”表示这个节点是一个GPIO Controller,它下面有很多引脚。
“#gpio-cells = <2>”表示这个控制器下每一个引脚要用2个32位的数(cell)来描述。用第1个cell来表示哪一个引脚,用第2个cell来表示有效电平:GPIO_ACTIVE_HIGH(高电平有效),GPIO_ACTIVE_LOW(低电平有效)。
怎么引用某个引脚呢?在自己的设备节点中使用属性"[name]-gpios",示例如下usb驱动otg和host模式:

驱动代码位于kernel\drivers\gpio\gpio-xxx.c专门的结构体封装contoller。

这里发现一个container_of宏。

每个 GPIO 控制器用一个 gpio_device 来表示:
struct gpio_device {//它是系统中第几个GPIO控制器int id;struct device dev;struct cdev chrdev;struct device *mockdev;struct module *owner;//含有各类操作函数struct gpio_chip *chip;//每一个gpio引脚用一个gpio_desc来表示struct gpio_desc *descs;//这些GPIO的号码基值int base;//这个GPIO控制器支持多少个GPIOu16 ngpio;//标签,名字char *label;void *data;struct list_head list;......};
用 gpio_chip 来定义控制引脚和中断相关的函数:

每一个 gpio 引脚用一个 gpio_desc 来表示:
struct gpio_desc {struct gpio_chip *chip;unsigned long flags;/* flag symbols are bit numbers */#define FLAG_REQUESTED 0#define FLAG_IS_OUT 1#define FLAG_EXPORT 2 /* protected by sysfs_lock */#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */#define FLAG_TRIG_FALL 4 /* trigger on falling edge */#define FLAG_TRIG_RISE 5 /* trigger on rising edge */#define FLAG_ACTIVE_LOW 6 /* sysfs value has active low */#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */#define ID_SHIFT 16 /* add new flags before this one */#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))#ifdef CONFIG_DEBUG_FSconst char *label;#endif};

在Linux中,会在gpiolib.c中定义一个 ARCH_NR_GPIOS 大小的数组static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];。每个元素对应于当前CPU上各个GPIO接口的信息,记录各个GPIO的描述符,即对应struct gpio_desc结构体。struct gpio_desc内的成员gpio_chip又指向了一系列关于GPIO的操作。具体的操作在 driver/gpio/gpio_xxx.c中实现。
GPIO 子系统有两套接口:基于描述符的(descriptor-based)、老的(legacy)。前者的函数都有前缀 “gpiod_”,它使用 gpio_desc 结构体来表示一个引脚;后者的函数都有前缀 “gpio_”,它使用一个整数来表示一个引脚。
要操作一个引脚,首先要 get 引脚,然后设置方向,读值、写值。

建议使用“devm_”版本的相关函数。有前缀“devm_”的含义是“设备资源管理”(Managed Device Resource),这是一种自动释放资源的机制。它的思想是“资源是属于设备的,设备不存在时资源就可以自动释放”。
比如在 Linux 开发过程中,先申请了GPIO,再申请内存;如果内存申请失败,那么在返回之前就需要先释放GPIO资源。如果使用devm的相关函数,在内存申请失败时可以直接返回:设备的销毁函数会自动地释放已经申请了的GPIO资源。
例如

先确定某个GPIO Controller的基准引脚号(base number),再计算出某个引脚的号码。

然后进入某个gpiochip目录,查看文件label的内容,根据 label 的内容对比设备树,就可以知道这对应哪一个 GPIO Controller。比如用上面的例子,通过对比设备树可知 gpiochip448 对应 gpio1。

因为 pin number = base + offset,所以 GPIO1_27 的号码是 448 + 27 = 475,那么通过 sys 可以做如下操作。
echo 475 > /sys/class/gpio/exportecho in > /sys/class/gpio/gpio475/directioncat /sys/class/gpio/gpio475/valueecho 475 > /sys/class/gpio/unexport
当 pin 使用为 GPIO 功能时候,请先确保该 pin 脚没有被其他模块复用为其他功能使用。

其实