linux gpio接口 .

一.相关结构体

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->base,chip->base+chip->ngpio-1,chip->label?:"generic");
	return status;
}
EXPORT_SYMBOL_GPL(gpiochip_add);

2.清空gpio_chip管理的全局gpio_desc数组项

int gpiochip_remove(struct gpio_chip *chip)
{
	unsigned long	flags;
	int	status = 0;
	unsigned	id;

	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	of_gpiochip_remove(chip);
	for (id = chip->base; id < chip->base + chip->ngpio; id++) {	//查找对应全局gpio_desc数组项
		if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {	//判断是否存在标志含FLAG_REQUESTED的gpio口
			status = -EBUSY;
			break;
		}
	}
	if (status == 0) {
		for (id = chip->base; id < chip->base + chip->ngpio; id++)	//清空对应全局gpio_desc数组项
			gpio_desc[id].chip = NULL;
	}
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	if (status == 0)
		gpiochip_unexport(chip);	//gpio_chip移除用户接口
	return status;
}
EXPORT_SYMBOL_GPL(gpiochip_remove);

3.查找获取gpio_chip

struct gpio_chip *gpiochip_find(void *data,int (*match)(struct gpio_chip *chip, void *data))
{
	struct gpio_chip *chip = NULL;
	unsigned long flags;
	int i;

	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	for (i = 0; i < ARCH_NR_GPIOS; i++) {	//遍历整个全局gpio_desc数组
		if (!gpio_desc[i].chip)	//若没被某个gpio_chip管理,则跳过继续
			continue;
		if (match(gpio_desc[i].chip, data)) {	//调用传递进来的匹配函数
			chip = gpio_desc[i].chip;	//匹配则获取其gpio_chip
			break;
		}
	}
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	return chip;	//返回查找到的gpio_chip指针
}

4.验证gpio号是否正确

static inline int gpio_is_valid(int number)
{
	return ((unsigned)number) < ARCH_NR_GPIOS;
}

5.请求gpio资源

int gpio_request(unsigned gpio, const char *label)
{
	struct gpio_desc	*desc;
	struct gpio_chip	*chip;
	int	status = -EINVAL;
	unsigned long	flags;

	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	if (!gpio_is_valid(gpio))	//验证gpio号是否正确
		goto done;
	desc = &gpio_desc[gpio];	//获取gpio描述符
	chip = desc->chip;	//获取gpio_chip
	if (chip == NULL)	//获取gpio_chip失败
		goto done;
	if (!try_module_get(chip->owner))	//增加模块引用计数
		goto done;
	if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {	//测试并设置gpio_desc的FLAG_REQUESTED标志
		desc_set_label(desc, label ? : "?");	//设置gpio_desc的label
		status = 0;
	} 
	else {
		status = -EBUSY;
		module_put(chip->owner);	//减少模块引用计数
		goto done;
	}
	if (chip->request) {	//gpio_chip存在request方法
		spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
		status = chip->request(chip, gpio - chip->base);	//调用gpio_chip的request方法
		spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
		if (status < 0) {
			desc_set_label(desc, NULL);	//清除gpio_desc的label
			module_put(chip->owner);	//减少模块引用计数
			clear_bit(FLAG_REQUESTED, &desc->flags);	//清除gpio_chip的FLAG_REQUESTED标志
		}
	}
done:
	if (status)
		pr_debug("gpio_request: gpio-%d (%s) status %d\n",gpio, label ? : "?", status);
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	return status;
}
EXPORT_SYMBOL_GPL(gpio_request);

6.释放gpio资源

void gpio_free(unsigned gpio)	
{
	unsigned long		flags;
	struct gpio_desc	*desc;
	struct gpio_chip	*chip;

	might_sleep();
	if (!gpio_is_valid(gpio)) {	//验证gpio号
		WARN_ON(extra_checks);
		return;
	}
	gpio_unexport(gpio);	//gpio移除用户接口
	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	desc = &gpio_desc[gpio];	//获取gpio_desc
	chip = desc->chip;			//获取gpio_chip
	if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {	//测试gpio_desc的FLAG_REQUESTED标志
		if (chip->free) {	//gpio_chip存在free方法
			spin_unlock_irqrestore(&gpio_lock, flags);	//上自旋锁
			might_sleep_if(chip->can_sleep);
			chip->free(chip, gpio - chip->base);	//调用gpio_chip的free方法
			spin_lock_irqsave(&gpio_lock, flags);	//解自旋锁
		}
		desc_set_label(desc, NULL);	//清除gpio_desc的label信息
		module_put(desc->chip->owner);	//减少模块引用计数
		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);	//清除FLAG_ACTIVE_LOW的标志
		clear_bit(FLAG_REQUESTED, &desc->flags);	//清除FLAG_REQUESTED的标志
	} 
	else
		WARN_ON(extra_checks);
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
}
EXPORT_SYMBOL_GPL(gpio_free);

7.设置去抖动时间

int gpio_set_debounce(unsigned gpio, unsigned debounce)	
{
	unsigned long		flags;
	struct gpio_chip	*chip;
	struct gpio_desc	*desc = &gpio_desc[gpio];	//获取gpio_desc项
	int	status = -EINVAL;

	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	if (!gpio_is_valid(gpio))	//验证gpio号
		goto fail;
	chip = desc->chip;	//获取gpio_chip
	if (!chip || !chip->set || !chip->set_debounce)	//判断gpio_chip是否存在且是否存在set和set_debounce方法
		goto fail;
	gpio -= chip->base;	//计算gpio在该gpio_chip的偏移量
	if (gpio >= chip->ngpio)	//超过该gpio_chip的gpio数范围
		goto fail;
	status = gpio_ensure_requested(desc, gpio);	//确保gpio是request请求过了的
	if (status < 0)
		goto fail;
	/* now we know the gpio is valid and chip won't vanish */
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	might_sleep_if(chip->can_sleep);
	return chip->set_debounce(chip, gpio, debounce);	//调用gpio_chip的set_debounce方法
fail:
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	if (status)
		pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);
	return status;
}
EXPORT_SYMBOL_GPL(gpio_set_debounce);

8.设置gpio为输入io

int gpio_direction_input(unsigned gpio)
{
	unsigned long	flags;
	struct gpio_chip	*chip;
	struct gpio_desc	*desc = &gpio_desc[gpio];	//获取gpio_desc项
	int	status = -EINVAL;

	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	if (!gpio_is_valid(gpio))
		goto fail;
	chip = desc->chip;	//获取gpio_chip
	if (!chip || !chip->get || !chip->direction_input)	//判断gpio_chip是否存在且存在get和directon_input方法
		goto fail;
	gpio -= chip->base;	//计算gpio在该gpio_chip的偏移量
	if (gpio >= chip->ngpio)	//超过该gpio_chip的gpio数范围
		goto fail;
	status = gpio_ensure_requested(desc, gpio);	//确保gpio是request请求过了的
	if (status < 0)
		goto fail;
	/* now we know the gpio is valid and chip won't vanish */
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	might_sleep_if(chip->can_sleep);
	if (status) {
		status = chip->request(chip, gpio);	//调用chip_gpio的request方法
		if (status < 0) {
			pr_debug("GPIO-%d: chip request fail, %d\n",chip->base + gpio, status);
			goto lose;
		}
	}
	status = chip->direction_input(chip, gpio);	//调用chip_gpio的direction_input方法
	if (status == 0)
		clear_bit(FLAG_IS_OUT, &desc->flags);
lose:
	return status;
fail:
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	if (status)
		pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);
	return status;
}
EXPORT_SYMBOL_GPL(gpio_direction_input);

9.设备gpio为输出io

int gpio_direction_output(unsigned gpio, int value)
{
	unsigned long	flags;
	struct gpio_chip	*chip;
	struct gpio_desc	*desc = &gpio_desc[gpio];	//获取gpio_desc项
	int	status = -EINVAL;

	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	if (!gpio_is_valid(gpio))
		goto fail;
	chip = desc->chip;	//获取gpio_chip
	if (!chip || !chip->set || !chip->direction_output)	//判断gpio_chip是否存在且存在set和direction_output方法
		goto fail;
	gpio -= chip->base;	//计算gpio在该gpio_chip的偏移量
	if (gpio >= chip->ngpio)	//超过该gpio_chip的gpio数范围
		goto fail;
	status = gpio_ensure_requested(desc, gpio);	//确保gpio是request请求过了的
	if (status < 0)
		goto fail;
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	might_sleep_if(chip->can_sleep);
	if (status) {
		status = chip->request(chip, gpio);	//调用gpio_chip的request方法
		if (status < 0) {
			pr_debug("GPIO-%d: chip request fail, %d\n",chip->base + gpio, status);
			goto lose;
		}
	}
	status = chip->direction_output(chip, gpio, value);	//调用gpio_chip的direction_output方法
	if (status == 0)
		set_bit(FLAG_IS_OUT, &desc->flags);
lose:
	return status;
fail:
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	if (status)
		pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);
	return status;
}
EXPORT_SYMBOL_GPL(gpio_direction_output);

10.判断gpio可否睡眠

#define gpio_cansleep	  __gpio_cansleep
int __gpio_cansleep(unsigned gpio)
{
	struct gpio_chip	*chip;
	chip = gpio_to_chip(gpio);	//获取gpio_chip
	return chip->can_sleep;		//调用gpio_chip的can_sleep方法
}
EXPORT_SYMBOL_GPL(__gpio_cansleep);

11.获取gpio值(gpio可睡眠)

int gpio_get_value_cansleep(unsigned gpio)
{
	struct gpio_chip	*chip;
	might_sleep_if(extra_checks);
	chip = gpio_to_chip(gpio);	//获取gpio_chip
	return chip->get ? chip->get(chip, gpio - chip->base) : 0;	//若存在gpio_chip的get方法则调用该方法
}
EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);

12.设置gpio值(gpio可睡眠)

void gpio_set_value_cansleep(unsigned gpio, int value)
{
	struct gpio_chip	*chip;
	might_sleep_if(extra_checks);
	chip = gpio_to_chip(gpio);	//获取gpio_chip
	chip->set(chip, gpio - chip->base, value);	//调用gpio_chip的set方法
}
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);

13.获取gpio值(gpio不可睡眠)

#define gpio_get_value	  __gpio_get_value	
int __gpio_get_value(unsigned gpio)
{
	struct gpio_chip	*chip;
	chip = gpio_to_chip(gpio);	//获取gpio_chip
	WARN_ON(chip->can_sleep);
	return chip->get ? chip->get(chip, gpio - chip->base) : 0;	//若存在gpio_chip的get方法则调用该方法
}
EXPORT_SYMBOL_GPL(__gpio_get_value);

14.设置gpio值(gpio不可睡眠)

#define gpio_set_value	  __gpio_set_value	
void __gpio_set_value(unsigned gpio, int value)
{
	struct gpio_chip	*chip;
	chip = gpio_to_chip(gpio);	//获取gpio_chip
	WARN_ON(chip->can_sleep);
	chip->set(chip, gpio - chip->base, value);	//调用gpio_chip的set方法
}
EXPORT_SYMBOL_GPL(__gpio_set_value);

15.请求一个gpio资源

int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
{
	int err;
	err = gpio_request(gpio, label);	//请求gpio资源
	if (err)
		return err;
	if (flags & GPIOF_DIR_IN)	//输入gpio
		err = gpio_direction_input(gpio);	//设置gpio为输入
	else						//输出gpio
		err = gpio_direction_output(gpio,(flags & GPIOF_INIT_HIGH) ? 1 : 0);	//设置gpio为输出
	if (err)	//出错
		gpio_free(gpio);	//释放gpio资源
	return err;
}
EXPORT_SYMBOL_GPL(gpio_request_one);

16.请求一组gpio资源

int gpio_request_array(struct gpio *array, size_t num)
{
	int i, err;
	for (i = 0; i < num; i++, array++) {	//批量请求gpio资源
		err = gpio_request_one(array->gpio, array->flags, array->label);
		if (err)
			goto err_free;
	}
	return 0;
err_free:
	while (i--)
		gpio_free((--array)->gpio);	//释放gpio资源
	return err;
}
EXPORT_SYMBOL_GPL(gpio_request_array);

17.释放一组gpio资源

void gpio_free_array(struct gpio *array, size_t num)
{
	while (num--)
		gpio_free((array++)->gpio);	//批量是否gpio资源
}
EXPORT_SYMBOL_GPL(gpio_free_array);

18.根据gpio号获取对应的中断号

int __gpio_to_irq(unsigned gpio)
{
	struct gpio_chip	*chip;
	chip = gpio_to_chip(gpio);	//获取gpio_chip
	return chip->to_irq?chip->to_irq(chip,gpio-chip->base):-ENXIO;	//若gpio_chip的to_irq方法存在则调用其方法
}
EXPORT_SYMBOL_GPL(__gpio_to_irq);

19.gpio_chip创建用户接口

static int gpiochip_export(struct gpio_chip *chip)
{
	int		status;
	struct device	*dev;

	if (!gpio_class.p)
		return 0;
	mutex_lock(&sysfs_lock);	//上互斥锁
	dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,"gpiochip%d", chip->base);	//创建设备
	if (!IS_ERR(dev)) {
		status = sysfs_create_group(&dev->kobj,&gpiochip_attr_group);
	} 
	else
		status = PTR_ERR(dev);
	chip->exported = (status == 0);	//设置gpio_chip的exported标志
	mutex_unlock(&sysfs_lock);	//解互斥锁

	if (status) {
		unsigned long	flags;
		unsigned	gpio;
		spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
		gpio = chip->base;	//获取gpio_chip的基数
		while (gpio_desc[gpio].chip == chip)	//遍历该gpio_chip管理的所有gpio_desc
			gpio_desc[gpio++].chip = NULL;		//清除该gpio_desc的chip成员
		spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
		pr_debug("%s: chip %s status %d\n", __func__,chip->label, status);
	}

	return status;
}

20.gpio_chip移除用户接口

static void gpiochip_unexport(struct gpio_chip *chip)
{
	int	status;
	struct device	*dev;

	mutex_lock(&sysfs_lock);	//上互斥锁
	dev = class_find_device(&gpio_class, NULL, chip, match_export);	//找到export的gpio_chip的设备文件
	if (dev) {
		put_device(dev);	//减少引用计数
		device_unregister(dev);	//注销设备文件
		chip->exported = 0;	//清除export标志
		status = 0;	//设置status
	} 
	else
		status = -ENODEV;
	mutex_unlock(&sysfs_lock);	//解互斥锁
	if (status)
		pr_debug("%s: chip %s status %d\n", __func__,chip->label, status);
}

21.gpio创建用户接口

int gpio_export(unsigned gpio, bool direction_may_change)
{
	unsigned long	flags;
	struct gpio_desc	*desc;
	int	status = -EINVAL;
	const char	*ioname = NULL;

	if (!gpio_class.p) {
		pr_debug("%s: called too early!\n", __func__);
		return -ENOENT;
	}
	if (!gpio_is_valid(gpio))	//验证gpio号的正确性
		goto done;
	mutex_lock(&sysfs_lock);	//上互斥锁
	spin_lock_irqsave(&gpio_lock, flags);	//上自旋锁
	desc = &gpio_desc[gpio];	//获取gpio_desc数组项
	if (test_bit(FLAG_REQUESTED, &desc->flags)&& !test_bit(FLAG_EXPORT, &desc->flags)) {	//已请求但没export
		status = 0;
		if (!desc->chip->direction_input|| !desc->chip->direction_output)	//gpio_chip不存在direction_input和direction_output方法
			direction_may_change = false;	//那么gpio的方向不可能会改变
	}
	spin_unlock_irqrestore(&gpio_lock, flags);	//解自旋锁
	if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])	//gpio_chip存在名字数组且存在对应数组项的名字
		ioname = desc->chip->names[gpio - desc->chip->base];	//设置gpio名
	if (status == 0) {
		struct device	*dev;
		dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),desc, ioname ? ioname : "gpio%u", gpio);	//创建设备文件
		if (!IS_ERR(dev)) {
			status = sysfs_create_group(&dev->kobj,&gpio_attr_group);	//创建属性
			if (!status && direction_may_change)	//gpio方向可能会改变
				status = device_create_file(dev,&dev_attr_direction);	//则创建跟方向相关的属性
			if (!status && gpio_to_irq(gpio) >= 0&& (direction_may_change|| !test_bit(FLAG_IS_OUT,&desc->flags)))	//可设置中断的引荐
				status = device_create_file(dev,&dev_attr_edge);	//则创建跟中断触发相关的属性
			if (status != 0)
				device_unregister(dev);	//注销设备
		} 
		else
			status = PTR_ERR(dev);
		if (status == 0)
			set_bit(FLAG_EXPORT, &desc->flags);	//设置export标志
	}
	mutex_unlock(&sysfs_lock);	//解互斥锁
done:
	if (status)
		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
	return status;
}
EXPORT_SYMBOL_GPL(gpio_export);

22.gpio移除用户接口

void gpio_unexport(unsigned gpio)
{
	struct gpio_desc	*desc;
	int			status = 0;
	
	if (!gpio_is_valid(gpio)) {	//验证gpio号的正确性
		status = -EINVAL;
		goto done;
	}
	mutex_lock(&sysfs_lock);	//上锁互斥锁
	desc = &gpio_desc[gpio];	//获取gpio_desc
	if (test_bit(FLAG_EXPORT, &desc->flags)) {	//判断是否export
		struct device	*dev = NULL;
		dev = class_find_device(&gpio_class, NULL, desc, match_export);	//获取设备文件
		if (dev) {
			gpio_setup_irq(desc, dev, 0);	//中断gpio的处理
			clear_bit(FLAG_EXPORT, &desc->flags);	//清除export标志
			put_device(dev);	//增加dev引用计数
			device_unregister(dev);	//注销设备
		} 
		else
			status = -ENODEV;
	}
	mutex_unlock(&sysfs_lock);	//解锁互斥锁
done:
	if (status)
		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
}
EXPORT_SYMBOL_GPL(gpio_unexport);

23.中断gpio处理

static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,unsigned long gpio_flags)
{
	struct sysfs_dirent	*value_sd;
	unsigned long	irq_flags;
	int	ret, irq, id;

	if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)	//有FLAG_TRIG_FALL或FLAG_TRIG_RISE标志
		return 0;
	irq = gpio_to_irq(desc - gpio_desc);	//根据gpio获取对应的中断号
	if (irq < 0)
		return -EIO;
	id = desc->flags >> ID_SHIFT;	//#define ID_SHIFT	16
	value_sd = idr_find(&dirent_idr, id);	//获取设备id
	if (value_sd)	//获取设备id成功,说明是申请过gpio中断的了
		free_irq(irq, value_sd);	//释放中断
	desc->flags &= ~GPIO_TRIGGER_MASK;	//屏蔽gpio_desc标志位FLAG_TRIG_FALL或FLAG_TRIG_RISE
	if (!gpio_flags) {	//gpio_unexport中的gpio_setup_irq跑到这里返回
		ret = 0;
		goto free_id;
	}
	irq_flags = IRQF_SHARED;	//设置为共享中断类型
	if (test_bit(FLAG_TRIG_FALL, &gpio_flags))	//FLAG_TRIG_FALL 下降沿触发
		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
	if (test_bit(FLAG_TRIG_RISE, &gpio_flags))	//FLAG_TRIG_RISE 上升沿触发
		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
	if (!value_sd) {	//获取设备id不成功
		value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");	//获取设备id
		if (!value_sd) {
			ret = -ENODEV;
			goto err_out;
		}
		do {
			ret = -ENOMEM;
			if (idr_pre_get(&dirent_idr, GFP_KERNEL))
				ret = idr_get_new_above(&dirent_idr, value_sd,1, &id);
		} while (ret == -EAGAIN);//id机制中获取新的id该id指向value_sd
		if (ret)
			goto free_sd;
		desc->flags &= GPIO_FLAGS_MASK;		//设置gpio_desc标志
		desc->flags |= (unsigned long)id << ID_SHIFT;	//或上idr机制获取的id
		if (desc->flags >> ID_SHIFT != id) {	//验证下是否id存放正确
			ret = -ERANGE;
			goto free_id;
		}
	}
	ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,"gpiolib", value_sd);	//申请中断
	if (ret < 0)
		goto free_id;
	desc->flags |= gpio_flags;	//gpio_desc设置传递进来的标志
	return 0;
free_id:
	idr_remove(&dirent_idr, id);
	desc->flags &= GPIO_FLAGS_MASK;
free_sd:
	if (value_sd)
		sysfs_put(value_sd);
err_out:
	return ret;
}


四.sysfs的初始化

static int __init gpiolib_sysfs_init(void)
{
	int	status;
	unsigned long	flags;
	unsigned	gpio;

	status = class_register(&gpio_class);	//注册gpio_class
	if (status < 0)
		return status;

	spin_lock_irqsave(&gpio_lock, flags);
	for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {	//遍历全局gpio_desc数组
		struct gpio_chip	*chip;

		chip = gpio_desc[gpio].chip;	//获取数组项的gpio_chip
		if (!chip || chip->exported)	//gpio_chip为空或已经exported了
			continue;

		spin_unlock_irqrestore(&gpio_lock, flags);	//上自旋锁
		status = gpiochip_export(chip);	//exported该项
		spin_lock_irqsave(&gpio_lock, flags);	//解自旋锁
	}
	spin_unlock_irqrestore(&gpio_lock, flags);


	return status;
}
postcore_initcall(gpiolib_sysfs_init);


























 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值