GPIO子系统架构分析(一)
GPIO子系统架构分析(二)
通过sysf操作gpio
GPIO子系统架构
在设备驱动中对GPIO的操作是非常普遍的,linux内核提供了GPIO子系统,方便用户使用,它为用户提供了GPIO的统一操作接口,用户不需要关心底层实现,因为这是芯片厂商需要关心的,芯片厂商会去做这一部分工作。
如下图即为GPIO子系统的软件架构。
最底层的是gpio控制器。gpio控制器驱动是硬件相关的模组,主要工作是调用gpio lib提供的接口注册驱动。gpio lib模块是一个硬件无关模块,提供了gpio控制器驱动的注册、注销方法,从用户角度给出了操作gpio的接口,这样,各个driver不需要关注gpio控制器的底层硬件相关的内容。
主要的数据结构
gpio_desc结构体,描述一个gpio,定义如下:
struct gpio_desc {
//后面解析
struct gpio_device *gdev;
//标志位
unsigned long flags;
/* 一些标志位含义如下: */
//该gpio是否已经申请
#define FLAG_REQUESTED 0
//gpio是否为输出
#define FLAG_IS_OUT 1
//若通过sysfs文件export一个gpio,则设置FLAG_EXPORT、FLAG_SYSFS、FLAG_REQUESTED
#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 */
//gpio是否被占用
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
/* Connection label */
const char *label;
/* Name of the GPIO */
const char *name;
};
gpio_chip结构体,描述一个gpio控制器,定义如下:
struct gpio_chip {
......
//后面解析
struct gpio_device *gpiodev;
......
//申请gpio,使用gpio之前需申请
int (*request)(struct gpio_chip *chip,
unsigned offset);
//释放gpio
void (*free)(struct gpio_chip *chip,
unsigned offset);
//获取gpio当前配置方向,返回0,输出模式,返回1,输入模式
int (*get_direction)(struct gpio_chip *chip,
unsigned offset);
//配置gpio为输入模式
int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
//配置gpio为输出模式
int (*direction_output)(struct gpio_chip *chip,
unsigned offset, int value);
//获取gpio的输出电平,返回0,低电平, 返回1,高电平
int (*get)(struct gpio_chip *chip,
unsigned offset);
//设置gpio的输出电平
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
......
//把GPIO number转换为irq
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
......
//起始的GPIO number
int base;
//该gpio控制器包含的gpio数目
u16 ngpio;
......
#if defined(CONFIG_OF_GPIO)
struct device_node *of_node;
int of_gpio_n_cells;
int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags);
#endif
};
一个gpio控制器,包含一个或多个gpio,所以在gpio_chip结构体里有一成员gpiodev,包含gpio控制器所有的gpio对应的gpio_desc等信息。该成员结构体定义如下:
struct gpio_device {
//gpiochip编号
int id;
struct device dev;
//字符设备,用于每个gpio控制器提供设备文件功能
struct cdev chrdev;
struct device *mockdev;
struct module *owner;
//指向所属控制器
struct gpio_chip *chip;
//gpio_desc数组
struct gpio_desc *descs;
//起始gpio号
int base;
//gpio个数
u16 ngpio;
char *label;
void *data;
struct list_head list;
#ifdef CONFIG_PINCTRL
struct list_head pin_ranges;
#endif
};
系统中所有gpio_device都会插入到一个全局链表gpio_devices里,以后通过gpio号,可以在该链表上找到对应的gpio_desc以及所属gpio_chip。
系统中,所有的gpio号都是不可重复的,如某款soc有三组gpio,每组gpio有32个引脚,如下图:
gpio_devices链表的顺序按照gpio号从小到大排序,如下图: