一.相关结构体
1.gpio_chip代表一个芯片的一个gpio bank
struct gpio_chip { //gpio bank
const char *label; //bank名
struct device *dev; //设备文件
struct module *owner; //模块所有者
int (*request)(struct gpio_chip *chip,unsigned offset);
void (*free)(struct gpio_chip *chip,unsigned offset);
int (*direction_input)(struct gpio_chip *chip,unsigned offset); //配置gpio为输入
int (*get)(struct gpio_chip *chip,unsigned offset); //获取值
int (*direction_output)(struct gpio_chip *chip,unsigned offset, int value); //配置gpio为输出
int (*direction_output_array)(struct gpio_chip*chip, unsigned value, unsigned mask);
int (*set_debounce)(struct gpio_chip *chip,unsigned offset, unsigned debounce); //去抖动时间
void (*set)(struct gpio_chip *chip,unsigned offset, int value); //设置gpio值
int (*to_irq)(struct gpio_chip *chip,unsigned offset); //中断
void (*dbg_show)(struct seq_file *s,struct gpio_chip *chip);
int base; //gpio基数
u16 ngpio; //gpio个数
const char *const *names;
unsigned can_sleep:1; //能否睡眠
unsigned exported:1;
#if defined(CONFIG_OF_GPIO)
struct device_node *of_node;
int of_gpio_n_cells;
int (*of_xlate)(struct gpio_chip *gc, struct device_node *np,const void *gpio_spec, u32 *flags);
#endif
};
2.gpio_desc 代表一个gpio口
struct gpio_desc { //GPIO描述符
struct gpio_chip *chip; //所属gpio_chip
unsigned long flags; //gpio标志
#ifdef CONFIG_DEBUG_FS
const char *label;
#endif
};
2.1 gpio_desc flags标志
#define FLAG_REQUESTED 0 //已请求资源
#define FLAG_IS_OUT 1 //输出io
#define FLAG_RESERVED 2 //保留
#define FLAG_EXPORT 3 /* protected by sysfs_lock */
#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
2.2 全局gpio_desc数组
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
3.gpio类
static struct class gpio_class = {
.name = "gpio",
.owner = THIS_MODULE,
.class_attrs = gpio_class_attrs,
};
二.api接口
int gpiochip_add(struct gpio_chip *chip) //添加初始化gpio_chip管理的gpio_desc
int gpiochip_remove(struct gpio_chip *chip) //清空gpio_chip管理的全局gpio_desc数组项
struct gpio_chip *gpiochip_find(void *data,int (*match)(struct gpio_chip *chip, void *data)) //查找获取gpio_chip
int gpio_request(unsigned gpio, const char *label) //请求gpio资源
void gpio_free(unsigned gpio) //释放gpio资源
int gpio_set_debounce(unsigned gpio, unsigned debounce) //设置去抖动时间
int gpio_direction_input(unsigned gpio) //设置gpio为输入io
int gpio_direction_output(unsigned gpio, int value) //设置gpio为输出io
int gpio_cansleep(unsigned gpio) //判断gpio可否睡眠
int gpio_get_value_cansleep(unsigned gpio) //获取gpio值(gpio可睡眠)
void gpio_set_value_cansleep(unsigned gpio, int value) //设置gpio值(gpio可睡眠)
int gpio_get_value(unsigned gpio) //获取gpio值(gpio不可睡眠)
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) //请求一个gpio资源
int gpio_request_array(struct gpio *array, size_t num) //请求一组gpio资源
void gpio_free_array(struct gpio *array, size_t num) //释放一组gpio资源
int gpio_to_irq(unsigned gpio) //根据gpio号获取对应的中断号
int gpio_export(unsigned gpio, bool direction_may_change) //gpio创建用户接口
void gpio_unexport(unsigned gpio) //gpio移除用户接口
三.api及调用到的相关函数解析
1.设置gpio_chip管理的全局gpio_desc数组项
int gpiochip_add(struct gpio_chip *chip)
{
unsigned long flags;
int status = 0;
unsigned id;
int base = chip->base; //获取gpio_chip基数
//验证gpio的基数,gpio的最后一个io的编号正确性
if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))&& base >= 0) {
status = -EINVAL;
goto fail;
}
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
if (base < 0) { //若gpio的基数小于0
base = gpiochip_find_base(chip->ngpio); //根据gpio个数分配新的基数
if (base < 0) {
status = base;
goto unlock;
}
chip->base = base; //设置新的基数
}
for (id = base; id < base + chip->ngpio; id++) {
if (gpio_desc[id].chip != NULL) { //判断gpio_desc是否给其他gpio_chip管理
status = -EBUSY;
break;
}
}
if (status == 0) {
for (id = base; id < base + chip->ngpio; id++) { //填充对应的全局gpio_desc数组项
gpio_desc[id].chip = chip; //gpio_chip
gpio_desc[id].flags = !chip->direction_input?(1 << FLAG_IS_OUT):0; //设置输入输出标志位
}
}
of_gpiochip_add(chip);
unlock:
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (status)
goto fail;
status = gpiochip_export(chip); //gpio_chip创建用户接口
if (status)
goto fail;
return 0;
fail:
pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",chip->