Linux Kernel 中,对于 GPIO 功能用 Gpiolib 来管理,作为中间层的 Gpiolib ,对上(其他 Drivers)提供一套统一的 操作 GPIO 的软件API,屏蔽了不同芯片的具体实现,对下(硬件)针对不同的芯片提供对应的一套 framework 用以物理实现功能(怎样增加 framework :需先实现 Specific Chip Driver ,再用 Gpiolib 提供的注册函数将其挂接到 Gpiolib 上即可)
一个 gpio_device 结构体表示一个 GPIO 控制器(Bank),多个结构体在内核中用 gpio_devices 链表存储。
// Linux内核/drivers/gpio/gpiolib.h
struct gpio_device {
int id; //它是系统中第几个gpio controller
struct device dev;
struct cdev chrdev;
struct device *mockdev;
struct module *owner;
struct gpio_chip *chip; //含有各类操作函数
struct gpio_desc *descs; //用来描述引脚,每个引脚对应一个gpio_desc
int base; //每个 Bank 的起始编号,加偏移量成为每个引脚的编号
u16 ngpio; //这个 Bank 有多少个引脚
char *label; //标签、名字
void *data;
struct list_head list;
#ifdef CONFIG_PINCTRL
/*
* If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
* describe the actual pin range which they serve in an SoC. This
* information would be used by pinctrl subsystem to configure
* corresponding pins for gpio usage.
*/
struct list_head pin_ranges;
#endif
};
一个 GPIO 控制器(Bank)包含多个 GPIO 功能引脚,每个引脚用一个 gpio_desc 结构体表示
struct gpio_desc {
struct gpio_device *gdev; //属于哪个 Bank
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_ACTIVE_LOW 6 /* 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 FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
#define FLAG_SLEEP_MAY_LOOSE_VALUE 12 /* GPIO may loose value in sleep */
/* Connection label */
const char *label; //一般等于gpio_chip的label,标签,名称
/* Name of the GPIO */
const char *name; //引脚名
};
gpio_chip 是操作方法结构体,抽象出所有 GPIO 操作,向上提供统一接口,适配不同的芯片,注意它是以一个 GPIO 控制器(Bank)为单位,该结构体抽象的是一个控制器(Bank)的操作方法,而不是一个引脚的,定义在 include/linux/gpio/driver.h 中,每个 GPIO Bank 都有 N 个寄存器来表示不同的操作。如:
SoC 将 I/O 分为了 2 个 Bank:
Bank 1:GPIOA ~ GPIOB
Bank 2:GPIOC ~ GPIOD