配置和定义

        gpio_power_detect {
                compatible = "quectel,gpio_power_detect";
                pinctrl-names = "default";
                pinctrl-0 = <&gpio_power_detect_active>;
                gpio_power_gpio = <&tlmm 95 0x00>;
                //otg-power-gpios = <&tlmm 18 0>;
                usb-sel-gpios = <&tlmm 66 0>;
                debounce = <15>;
                linux,code = <172>;

        };
 struct gpio_power_detect {
        struct device *dev;
        struct input_dev *p_inputdev;

        unsigned int gpio_power_gpio;
        unsigned int gpio_power_irq_num;

//      struct work_struct power_detect;
        struct workqueue_struct *gpio_power_detect_wq;
        struct work_struct      work;

        unsigned int gpio_usb_sel_gpio;
        atomic_t state;
        unsigned int code;

};

driver 和 dts 块之间的绑定

driver 中的 struct of_device_id 中的 compatible 会和 dts 中的 compatible 进行匹配,吻合的情况下, driver 就能从这个 dts 块中读取相应的数据了。 本文的 dts 是 qm215-qrd.dtsi

static struct of_device_id of_device_sc20_gpio_match_table[] =
{
        {.compatible = "quectel,gpio_power_detect"},
        {},
};
        gpio_power_detect {
                compatible = "quectel,gpio_power_detect";
                ...

        };

driver 配置输入引脚

输入引脚一般需要配置: 引脚方向,中断,上下拉。

  1. 获取 gpio, driver 中通过 dts 中的相同名称,获取到 gpio,然后申请相应的结构体
dev_struct->gpio_power_gpio = of_get_named_gpio(dev_struct->dev->of_node, "gpio_power_gpio", 0);
gpio_request(dev_struct->gpio_power_gpio, "gpio_power_gpio");
        gpio_power_detect {
                ...
                gpio_power_gpio = <&tlmm 95 0x00>;
                ...

        };
  1. 获取中断

    dev_struct->gpio_power_irq_num = gpio_to_irq(dev_struct->gpio_power_gpio);
  2. 设置方向

    gpio_direction_input(dev_struct->gpio_power_gpio);
  3. 设置上下拉,是通过 dts 来配置的,本文实在 msm8917-pinctrl.dtsi 中配置的,然后在 qm215-qrd.dtsi 中进行引用。
                tlmm_gpio_power_detect {
                        gpio_power_detect_active: gpio_power_detect_active {
                                mux {
                                        pins = "gpio95";
                                        drive-strength = <2>;
                                        bias-pull-up;
                                };
                        };
                };
        gpio_power_detect {
                ...
                pinctrl-names = "default";
                pinctrl-0 = <&gpio_power_detect_active>;
                ...

        };
···

# 配置输出引脚
输出引脚配置比较简单,只要获取 gpio 后,配置方向和初始值即可。
1. 获取 gpio
    dev_struct->gpio_usb_sel_gpio = of_get_named_gpio(dev_struct->dev->of_node, "usb-sel-gpios", 0);
    if (dev_struct->gpio_usb_sel_gpio < 0){
            pr_err("%s: get usb_sel_gpio failed\n", __func__);
    return -EINVAL;
    }
    ret = gpio_request(dev_struct->gpio_usb_sel_gpio, "usb-sel-gpios");
    if (ret) {
            pr_err("%s: Unable to request usb_sel_spio [%d]\n", __func__, dev_struct->gpio_usb_sel_gpio);
            return ret;
    }
    gpio_power_detect {
            ...
            usb-sel-gpios = <&tlmm 66 0>;
            ...

    };

2. 配置位输出
    ret = gpio_direction_output(dev_struct->gpio_usb_sel_gpio, 1);
    if (ret) {
            pr_err("%s: Unable to set direction for usb-sel-gpios [%d]\n", __func__, dev_struct->gpio_usb_sel_gpio);
            gpio_free(dev_struct->gpio_usb_sel_gpio);
    }

# 配置按键值上报
1. 获取按键值
    if(of_property_read_u32(dev_struct->dev->of_node, "linux,code", &dev_struct->code)) {
            dev_err(dev_struct->dev, "fail to get linux code\n");
            return (-EINVAL);
    }
    printk("gpio_power_detect probe get key code %d\n", dev_struct->code);

    state = gpio_get_value(dev_struct->gpio_power_gpio);
    if(state < 0) {
            dev_err(dev_struct->dev, "fail to init base_detect state %d\n", state);
            return (-EINVAL);
    }
    atomic_set(&dev_struct->state, state);
    gpio_power_detect {
            ...
            linux,code = <172>;

    };

2. 工作时上报键值
    old_state = atomic_read(&dev_struct->state);
    new_state = gpio_get_value(dev_struct->gpio_power_gpio);
    if (new_state < 0) {
            dev_err(dev_struct->dev,
                    "failed to get bd-gpio state: %d\n", new_state);
            return;
    }

    if(new_state != old_state){
            dev_err(dev_struct->dev, "base_detect update state %d", new_state);
            atomic_set(&dev_struct->state, new_state);
            gpio_set_value(dev_struct->gpio_usb_sel_gpio, new_state);
            input_report_key(dev_struct->p_inputdev, dev_struct->code, new_state);
            input_sync(dev_struct->p_inputdev);
    }


# 注意
本文中使用的 `gpio_request` 属于老的 api,新的 api 一般是 `gpiod` 开头,比如:`gpiod_direction_output`.

如果是按键,为了消抖,dts 中需要考虑 `debounce`,driver 中需要考虑 延迟工作 `struct delayed_work` 。

`DEVICE_ATTR` 可以在 `sys fs` 中添加文件,相关可以参考: https://blog.csdn.net/njuitjf/article/details/16849333

# 参考:
设备树详解  
https://blog.csdn.net/qq_28992301/article/details/53321610  
在Linux驱动中使用gpio子系统  
https://www.jianshu.com/p/f160209bd64b  
Linux内核中的GPIO驱动  
https://blog.csdn.net/vincent1995x/article/details/51581711  
1.1. GPIO设置   
http://developer.rokid.com/docs/7-bspguide/pinmuxji_gpio_she_zhi/gpioshe_zhi.html  
LinuxGPIO中文文档  
https://www.cnblogs.com/bforever/p/10528395.html  
一、初识linux输入子系统  
https://www.cnblogs.com/zhaobinyouth/p/6257662.html  
pm_stay_awake()和pm_relax()的意义  
https://blog.csdn.net/chizhang7815/article/details/100800761  
linux gpio_to_irq()源码分析  
https://blog.csdn.net/MACMACip/article/details/105549516  
of_property_read_u32  
https://biscuitos.github.io/blog/DTS-of_property_read_u32/  
如何在一份驱动中上报键值之理解input子系统设备  
https://blog.csdn.net/weixin_44158983/article/details/106872084?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242.1&utm_relevant_index=3  
INPUT子系统学习 evdev  
https://blog.csdn.net/xiaochuan110/article/details/82424237  
高通 gpio控制方式  
https://blog.csdn.net/qq_36781842/article/details/102625088?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link  
Android 5.1高通方案增加GPIO按键  
https://blog.csdn.net/tdstds/article/details/50920443?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.no_search_link  
Qualcomm MSM GPIO-KEY device tree  
https://blog.csdn.net/bolanlst/article/details/51385808?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link  
android7.1 msm8953通过寄存器拉高gpio电平  
https://blog.csdn.net/zjy764219923/article/details/106243794?spm=1001.2101.3001.6650.15&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-15.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-15.no_search_link  
msm8996的gpio和irq  
https://blog.csdn.net/lintwins/article/details/50203173?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-11.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-11.no_search_link  
Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇)  
https://radia.blog.csdn.net/article/details/70800076?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link  
高通msm8916 gpio笔记(基于设备树)  
https://blog.csdn.net/hm131415/article/details/54377549?spm=1001.2101.3001.6650.18&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-18.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-18.no_search_link  
msm8953 申请gpio失败,查看所有的gpio 申请情况。  
https://blog.csdn.net/jlgcumt/article/details/106614870?spm=1001.2101.3001.6650.14&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-14.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-14.no_search_link  
高通 gpio控制方式  
https://blog.csdn.net/qq_36781842/article/details/102625088?spm=1001.2101.3001.6650.9&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-9.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-9.no_search_link  
高通msm8916 gpio笔记(基于设备树)  
https://blog.csdn.net/hm131415/article/details/54377549?spm=1001.2101.3001.6650.16&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-16.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-16.no_search_link  
高通 msm平台GPIO相关的device tree设置  
https://blog.csdn.net/viewsky11/article/details/53402536?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link  
配置学习总结高通平台GPIO  
https://blog.csdn.net/Joymine/article/details/48161895?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link  
GPIO中断唤醒系统调试方法  
https://blog.csdn.net/jlgcumt/article/details/110480062?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.no_search_link  
Linux休眠后开启中断的方法及中断唤醒过程  
https://blog.csdn.net/mike8825/article/details/98473014  
Android系统下如何通过外设实现GPIO中断触发调用Android程序执行  
https://blog.csdn.net/a499957739/article/details/104425753  
配置学习总结高通平台GPIO  
https://blog.csdn.net/Joymine/article/details/48161895  
Android GPIO 控制方案  
https://blog.csdn.net/WXXGoodJob/article/details/90599925  
android 上层如何控制GPIO  
https://blog.csdn.net/prike/article/details/53216954   
[RK3288]LED亮灯GPIO驱动编写及dts文件架构介绍(基于android8.1使用android studio3.6开发)  
https://blog.csdn.net/a812417530/article/details/107004198  

Android(Linux)控制GPIO的方法及实时性分析  
https://www.cnblogs.com/we-hjb/p/5859479.html  
Android(Linux)控制GPIO方法二  
https://www.cnblogs.com/we-hjb/p/5903366.html  
Android 驱动 (一) GPIO  
https://www.cnblogs.com/tlnshuju/p/7028985.html  

标签: aosp

添加新评论