Linux下GPIO驱动(四) ----gpio_request();gpio_free();_kunkliu的博客-程序员秘密

技术标签: kernel-driver-gpio  

转载地址:http://www.cnblogs.com/hello2mhb/p/3279322.html
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); // gpio_lock是自旋锁,上锁,保存FLAG在flags变量
    if (!gpio_is_valid(gpio))
        goto done;
    desc = &gpio_desc[gpio];
    chip = desc->chip;
    if (chip == NULL)
        goto done;

    if (!try_module_get(chip->owner)) // 该函数用于增加模块使用计数;若返回为0,表示调用失败,希望使用的模块没有被加载或正在被卸载中       goto done;

    /* NOTE:  gpio_request() can be called in early boot,
     * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
     */

    if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { // 原子操作,将flags的第FLAG_REQUESTED位置1,并返回其原值        
    desc_set_label(desc, label ? : "?");// 如果原来的值是0, 执行desc_set_label, 对desc->chip.label赋值,如果label有定义,直接用定义,比如上面的“temporary”,否则用“?”      
    status = 0;
    } else {
        status = -EBUSY;
        module_put(chip->owner); // 该函数用于减少模块使用计数goto done;
    }

    if (chip->request) {
  // chip->request在linux初始化时是没有指向的       /* chip->request may sleep */
        spin_unlock_irqrestore(&gpio_lock, flags);// 如果chip->request不为0, 解锁,因为后面调用的chip->request有可能睡眠       
        status = chip->request(chip, gpio - chip->base);
        spin_lock_irqsave(&gpio_lock, flags);

        if (status < 0) {
            desc_set_label(desc, NULL);
            module_put(chip->owner);
            clear_bit(FLAG_REQUESTED, &desc->flags);
        }
    }

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);

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

    might_sleep();

    if (!gpio_is_valid(gpio)) {
        WARN_ON(extra_checks);
        return;
    }

    gpio_unexport(gpio);

    spin_lock_irqsave(&gpio_lock, flags);

    desc = &gpio_desc[gpio];
    chip = desc->chip;
    if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
        if (chip->free) {
            spin_unlock_irqrestore(&gpio_lock, flags);
            might_sleep_if(extra_checks && chip->can_sleep);
            chip->free(chip, gpio - chip->base);
            spin_lock_irqsave(&gpio_lock, flags);
        }
        desc_set_label(desc, NULL);
        module_put(desc->chip->owner);
        clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
        clear_bit(FLAG_REQUESTED, &desc->flags);
    } else
        WARN_ON(extra_checks);

    spin_unlock_irqrestore(&gpio_lock, flags);
}
EXPORT_SYMBOL_GPL(gpio_free);
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/kunkliu/article/details/78038655

智能推荐

ROS Navigation-----map_server包缺少Error: package 'map_server' not found_pd很不专业的博客-程序员秘密

出现找不到map_server时Error: package 'map_server' not found直接安装map_server包就行了。sudo apt-get install ros-indigo-map-server

linux将u盘文件拷贝到根目录,如何将U盘上的文件复制到linux目录下_曾杰律师的博客-程序员秘密

如何将U盘上的文件复制到linux目录下将U盘上的文件复制到linux目录下涉及到cp以及mount等命令,下面先讲一个各个命令1、 Linux 常用命令说明cp 该命令实现Linux下文件的拷贝功能,源地址为需要拷出文件的地址,目的地址为文件拷贝的目标地址。例1:拷贝/known/log目录中的文件名为log的文件到/mnt目录中cp /known/log/log /mnt例2:拷贝/...

C++核心入门-01内存分区模型_木头人学习的博客-程序员秘密

C++核心入门-01内存分区模型0、前言1、程序运行前1.1 代码区1.2 全局区本小节总结0、前言C++在执行时,将内存大方向划分为4个区域代码区:存放函数体的二进制代码,由操作系统进行管理。全局区:存放全局变量、静态变量以及常量。栈区:由编译器自动分配释放,存放函数的参数值,局部变量等。堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。内存分四个区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程。1、程序运行前在程序编译后,生成了exe可执行程

三分法问题个人总结&MS_活动中心问题_石头_奋斗的博客-程序员秘密

看了一下微软2014编程之美大赛的初赛第一阶段的题目:

解析OCR与Voting Disk以及其管理_weixin_33912246的博客-程序员秘密

Voting Disk和OCR是Oracle Clusterware的2部分。Voting Disk里面记录着节点成员的信息。如RAC数据库中有哪些节点成员,节点增加或者删除时也同样会将信息记录进来。Voting Disk必须存放在共享存储上,通常来说是存放在裸设备上。为了保证Voting Disk的安全,需要配置多个Voting Disk,Oracle建议Voting Di...

rk3288_lubuntu_img制作步骤_rk lubuntu_jiangdou88的博客-程序员秘密

1#刷Firefly-RK3288_Android4.4_201412290906.img启动后刷linux-boot-miniroot.img 写到 recovery 分区,misc.img 写到 misc 分区。2#建立TFa,插TF到rk3288,  fdisk  -lb,fdisk /dev/mmcblk1       d (选择d,w删除所有分区)       选

随便推点

计算机学测打多少字,速度测试,一分钟能打多少字?_weixin_39667626的博客-程序员秘密

六、速度测试——检验学习效果经过一段时间的练习,输入速度提高了不少吧,赶快来测试一下现在一分钟可以输入多少英文或汉字。金山打字通2010的“速度测试”功能不仅有基本的“屏幕对照”速度测试,还有“书本对照”测试及要求较高的“同声录入”测试。让用户可以用各种测试方法来测试自己的文字输入水平。图19 速度测试测试完毕,金山打字通2010会给出用户的输入曲线图,用户可以从中可以看到自己的输入水平评价、平均...

WordPress - 学习/实践_wordpress csdn_穿素白衫的中少年的博客-程序员秘密

学习使用wordpress进行快速建站,维护个人博客。

爱了!Intellij IDEA 自带的 Vim 插件真心不错_公众号:方志朋的博客-程序员秘密

点击上方“方志朋”,选择“设为星标”回复”666“获取新整理的面试文章来源:hsujee.com/2016/01/13/在 IDEA Intellij小技巧和插件 一文中简单介绍了一下Id...

关于left join 的连接条件和过滤条件的关系_买了否冷的博客-程序员秘密

参考文章:https://blog.csdn.net/weixin_39428938/article/details/77944939left join的困惑:一旦加上where条件,则显示的结果等于inner join将where 换成 and 用where 是先连接然后再筛选 用and 是先筛选再连接过滤条件放在:where后面:是先连接然生成临时查询结果,然后再筛选...

开源虚拟化平台解决方案oVirt 4.0尝鲜准备_virt4.0_DexterLien的博客-程序员秘密

最近准备给运行了3年多的RHEL更换存储设备,突然意识到RHEVM那台服务器貌似都没有可替代的容灾方案,毕竟当时就只买了一年的RHN订阅,如果哪天RHEVM服务器突然挂掉的话,还真就懵逼了,各种rpm包都得用yum安装,没有订阅就没法重新部署环境了,不能想象啊~赶紧找了下资料,果然不出所料,只要是红帽有的东西,都会有相应开源的项目可以替代,目前找到的方案是使用CentOS替换RHEL,oVirt替...

javascript 查看变量类型_sayyy的博客-程序员秘密

console.log(Object.prototype.toString.call(1));console.log(Object.prototype.toString.call(3.14));console.log(Object.prototype.toString.call('a'));console.log(Object.prototype.toString.call(true));console.log(Object.prototype.toString.call([1,2,3]));co

推荐文章

热门文章

相关标签