日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

写一个公用的gpio口驱动

發布時間:2023/12/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 写一个公用的gpio口驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

因為項目需要控制的GPIO口比較多,如果每個GPIO口都寫一個驅動就顯得比驕麻煩,所以就寫了一個通用的GPIO口驅動。只要dts里面配置好設備GPIO相關信息就可以自動加載了。可以很充分的體現多個設備一個驅動的優良性。

dts文件

gpio_rs485: gpio_rs485 {status = "okay";compatible = "gpio,px30-gpio";cname = "rs485";en-gpio = <&gpio3 12 GPIO_ACTIVE_HIGH>;};

驅動源代碼

#include <dt-bindings/gpio/gpio.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/err.h> #include <linux/slab.h>struct gpio_dev_data {int en_pin;int en_val;int gpio_val; };static struct of_device_id gpio_of_match[] = {{ .compatible = "gpio,px30-gpio" },{ } };MODULE_DEVICE_TABLE(of, gpio_of_match);static ssize_t gpio_store_en(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) {struct gpio_dev_data *dev_data = dev_get_drvdata(dev);unsigned long value = 0;int ret;/*將echo進來的buf轉換成整型*/ret = kstrtoul(buf, 16, &value);if (ret < 0) {printk( "%s:kstrtoul failed, ret=%d\n", __func__, ret);return ret;}printk("%s: en value : %d\n", __func__, (int)value);if (value) {gpio_direction_output(dev_data->en_pin, dev_data->en_val);dev_data->gpio_val = 1;} else {gpio_direction_output(dev_data->en_pin, !dev_data->en_val);dev_data->gpio_val = 0;}return count; }static char mybuf[10]="123";/*cat命令時,將會調用該函數*/ static ssize_t gpio_show_en(struct device *dev,struct device_attribute *attr, char *buf) {struct gpio_dev_data *dev_data = dev_get_drvdata(dev);snprintf(mybuf,sizeof(mybuf),"%d",dev_data->gpio_val);return sprintf(buf, "%s\n", mybuf); }static DEVICE_ATTR(gpio_en, S_IWUSR, gpio_show_en, gpio_store_en);static int gpio_probe(struct platform_device *pdev) {struct device_node *node = pdev->dev.of_node;enum of_gpio_flags flags;int gpio;int ret;int en_value;struct class *dev_class;struct device *ctl_dev;struct gpio_dev_data *dev_data;int err;const char *class_name;printk("%s enter: %d\n", __func__, __LINE__);if (!node)return -ENODEV;/*獲取gpio口*/gpio = of_get_named_gpio_flags(node, "en-gpio", 0, &flags);en_value = (flags == GPIO_ACTIVE_HIGH) ? 1 : 0;if (!gpio_is_valid(gpio)) {dev_err(&pdev->dev, "invalid en gpio%d\n", gpio);}ret = devm_gpio_request(&pdev->dev, gpio, "onoff");if (ret) {dev_err(&pdev->dev,"failed to request GPIO%d for \n",gpio);return -EINVAL;}/*設置probe的默認電平*/gpio_direction_output(gpio, !en_value);dev_data = kzalloc(sizeof(struct gpio_dev_data), GFP_KERNEL);if (dev_data == NULL) {printk("Failed to malloc gpio_dev_data\n");return -ENOMEM;}if(en_value > 0)dev_data->gpio_val = 0;elsedev_data->gpio_val = 1;/*創建class節點*/err = of_property_read_string(node, "cname", &class_name);if(err){printk("%s get class name error %d\n",__FUNCTION__,__LINE__);return -EINVAL;}dev_class = class_create(THIS_MODULE, class_name);ctl_dev = device_create(dev_class, NULL, 0, NULL, "onoff");if (IS_ERR(ctl_dev)) {dev_err(ctl_dev, "Failed to create device\n");ret = PTR_ERR(ctl_dev);goto err_create_dev;}err = device_create_file(ctl_dev, &dev_attr_gpio_en);if (err)printk("driver_create_file = %d\n", err);/*獲取的gpio賦值全局變量*/dev_data->en_pin = gpio;dev_data->en_val = en_value;dev_info(ctl_dev, "%s: %d\n", __func__, __LINE__);dev_info(&pdev->dev, "%s: %d\n", __func__, __LINE__);dev_set_drvdata(ctl_dev, dev_data);dev_set_drvdata(&pdev->dev, dev_data);return 0;err_create_dev:kfree(dev_data);return ret; }static int gpio_remove(struct platform_device *pdev) {printk("%s: %d\n", __func__, __LINE__);return 0; }#ifdef CONFIG_PM_SLEEP static int gpio_suspend(struct device *dev) {struct gpio_dev_data *dev_data = dev_get_drvdata(dev);dev_info(dev, "%s: %d\n", __func__, __LINE__);gpio_direction_output(dev_data->en_pin, !dev_data->en_val);return 0; }static int gpio_resume(struct device *dev) {printk("%s: %d\n", __func__, __LINE__);return 0; } #endifstatic const struct dev_pm_ops gpio_pm_ops = { #ifdef CONFIG_PM_SLEEP.suspend = gpio_suspend,.resume = gpio_resume,.poweroff = gpio_suspend,.restore = gpio_resume, #endif };static struct platform_driver gpio_driver = {.driver = {.name = "gpio-en",.owner = THIS_MODULE,.pm = &gpio_pm_ops,.of_match_table = of_match_ptr(gpio_of_match),},.probe = gpio_probe,.remove = gpio_remove, };module_platform_driver(gpio_driver);MODULE_AUTHOR("Weiqifa <329410527@qq.com>"); MODULE_DESCRIPTION("simple gpio driver"); MODULE_LICENSE("GPL");

Makefile文件

obj-$(CONFIG_GPIO_CONTROL) += gpio_control.o

Kconfig

config GPIO_CONTROLtristate "GPIO control driver"default nhelpGPIO control driver.

? 回復「?籃球的大肚子」進入技術群聊

回復「1024」獲取1000G學習資料

總結

以上是生活随笔為你收集整理的写一个公用的gpio口驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。