设备树

Linux_for_Tegra/source/public/hardware/nvidia/platform/t19x/galen/kernel-dts/tegra194-p2888-0001-p2822-0000.dts

#include "common/tegra194-p2888-0001-p2822-0000-common.dtsi"
#include "common/tegra194-p2822-camera-modules.dtsi"
#include "t19x-common-modules/tegra194-camera-plugin-manager.dtsi"
#include "user/user-gpio.dtsi"

Linux_for_Tegra/source/public/hardware/nvidia/platform/t19x/galen/kernel-dts/user/user-gpio.dtsi

#include <dt-bindings/gpio/tegra194-gpio.h>/ {user-gpios {compatible = "user,user-init-gpio";status = "okay";out-gpios-num = <2>;out-1-gpios = <&tegra_main_gpio TEGRA194_MAIN_GPIO(N, 1) GPIO_ACTIVE_HIGH>;out-2-gpios = <&tegra_main_gpio TEGRA194_MAIN_GPIO(H, 7) GPIO_ACTIVE_LOW>;input-gpios-num = <1>;in-1-gpios = <&tegra_main_gpio TEGRA194_MAIN_GPIO(H, 0) GPIO_ACTIVE_HIGH>;};
};

驱动

Linux_for_Tegra/source/public/kernel/kernel-4.9/drivers/gpio/gpio-user.c

#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/kthread.h>#include <dt-bindings/gpio/tegra194-gpio.h>#define GPIOX_MAX_NUM 30enum direction_type_t {GPIO_IN,GPIO_OUT,GPIO_IRQ
};struct gpiox_device_t {int gpio;struct device * dev;int active_low;int direction;int edge;int value;int irq_num;
};struct gpiox_class_t {struct class *gpio_class;struct gpiox_device_t gpio_devs[GPIOX_MAX_NUM];int gpio_cnt;
};static ssize_t gpiox_active_low_show(struct device * dev, struct device_attribute * attr, char * buf)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "active_low")){if(xdev->active_low == 0)return strlcpy(buf, "0\n", 3);elsereturn strlcpy(buf, "1\n", 3);}return strlcpy(buf, "0\n", 3);
}static ssize_t gpiox_active_low_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t count)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);unsigned long on = simple_strtoul(buf, NULL, 10);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "active_low")){}xdev->active_low = on ? 1 : 0;return count;
}static ssize_t gpiox_direction_show(struct device * dev, struct device_attribute * attr, char * buf)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "direction")){switch(xdev->direction){case GPIO_IN:return strlcpy(buf, "in\n", 4);break;case GPIO_OUT:return strlcpy(buf, "out\n", 5);break;case GPIO_IRQ:return strlcpy(buf,"irq\n", 5);break;}}return strlcpy(buf, "none\n", 6);
}static ssize_t gpiox_direction_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t count)
{int direction = 0;struct gpiox_device_t * xdev = dev_get_drvdata(dev);unsigned long on = simple_strtoul(buf, NULL, 10);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "direction")){direction = (on==1)? GPIO_OUT :(on==0)? GPIO_IN:GPIO_IRQ; /* not used */}return 0;
}static ssize_t gpiox_edge_show(struct device * dev, struct device_attribute * attr, char * buf)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "edge")){if(xdev->edge == 0)return strlcpy(buf, "0\n", 3);elsereturn strlcpy(buf, "1\n", 3);}return strlcpy(buf, "0\n", 3);
}static ssize_t gpiox_edge_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t count)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);unsigned long on = simple_strtoul(buf, NULL, 10);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "edge")){if(on)gpio_direction_output(xdev->gpio, 1);elsegpio_direction_output(xdev->gpio, 0);}xdev->edge = on ? 1 : 0;return count;
}static ssize_t gpiox_value_show(struct device * dev, struct device_attribute * attr, char * buf)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "value")){switch(xdev->direction){case GPIO_IN:xdev->value = gpio_get_value(xdev->gpio);case GPIO_OUT:if(xdev->value == 0)return strlcpy(buf, "0\n", 3);elsereturn strlcpy(buf, "1\n", 3);break;case GPIO_IRQ:break;}}return strlcpy(buf, "0\n", 3);
}static ssize_t gpiox_value_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t count)
{struct gpiox_device_t * xdev = dev_get_drvdata(dev);unsigned long on = simple_strtoul(buf, NULL, 10);if(xdev == NULL)return 0;if(!strcmp(attr->attr.name, "value")){if(on)gpio_direction_output(xdev->gpio, 1);elsegpio_direction_output(xdev->gpio, 0);}xdev->value = on ? 1 : 0;return count;
}static DEVICE_ATTR(value, 0664, gpiox_value_show, gpiox_value_store);
static DEVICE_ATTR(direction, 0664, gpiox_direction_show, gpiox_direction_store);
static DEVICE_ATTR(edge, 0664, gpiox_edge_show, gpiox_edge_store);
static DEVICE_ATTR(active_low, 0664, gpiox_active_low_show, gpiox_active_low_store);
static struct attribute * gpiox_attrs[] = {&dev_attr_value.attr,&dev_attr_direction.attr,&dev_attr_edge.attr,&dev_attr_active_low.attr,NULL
};static const struct attribute_group gpiox_group = {.attrs = gpiox_attrs,
};static int init_device_data(struct gpiox_device_t *dev,int gpio,int active,int direction,int edge,int value)
{int irq_num;if(dev == NULL)return -1;value =(value==0)?1:0;dev->gpio = gpio;dev->active_low = active;dev->direction = direction;dev->edge = edge;dev->value = value;switch(direction){ case GPIO_IN:printk("set gpio%d direction input \n",dev->gpio);gpio_direction_input(dev->gpio);break;case GPIO_OUT:printk("set gpio%d direction output[%d] \n",dev->gpio,value);gpio_direction_output(dev->gpio,value);break;case GPIO_IRQ:irq_num = gpio_to_irq(dev->gpio);dev->irq_num = (irq_num>0)?irq_num:-1;break;}return 0;
}static int create_device_nodes(struct gpiox_class_t *cls,int gpio_num,enum direction_type_t direction,int flag)
{int ret = 0;char name[10];if(cls == NULL)return -1;if(cls->gpio_cnt>=GPIOX_MAX_NUM)  return -2;memset(name,0,sizeof(name));sprintf(name,"gpio%d",gpio_num);cls->gpio_devs[cls->gpio_cnt].dev = device_create(cls->gpio_class, NULL,MKDEV(0, cls->gpio_cnt), NULL, "%s", name);ret = sysfs_create_group(&cls->gpio_devs[cls->gpio_cnt].dev->kobj,&gpiox_group);init_device_data(&cls->gpio_devs[cls->gpio_cnt],gpio_num,1,direction,0,flag);dev_set_drvdata(cls->gpio_devs[cls->gpio_cnt].dev, &cls->gpio_devs[cls->gpio_cnt]);cls->gpio_cnt++;return 0;
}static int user_gpio_probe(struct platform_device * pdev)
{struct device_node * node = pdev->dev.of_node;struct gpiox_class_t * gpiox_class;enum of_gpio_flags flags;int gpio;int ret,i;int cnt = 0;char gpio_name[32];if(!node)return -ENODEV;gpiox_class = kzalloc(sizeof(struct gpiox_class_t), GFP_KERNEL);if (!gpiox_class){printk("%s -ENOMEM\n",__func__);return -ENOMEM;}gpiox_class->gpio_cnt = 0;gpiox_class->gpio_class = class_create(THIS_MODULE, "gpio_usr");ret = of_property_read_u32(node, "out-gpios-num", &cnt);if (ret || !cnt) {pr_err("no gpio\n");goto INIT_ERR_FREE;}printk("get out-gpios-num:%d\n",cnt);for (i = 0; i < cnt; i++) {sprintf(gpio_name, "out-%d-gpios", i + 1);//gpio = of_get_named_gpio(node, gpio_name,0);gpio = of_get_named_gpio_flags(node, gpio_name,0,&flags);if (gpio_request(gpio, NULL)) {pr_err("out-%d-gpios(%d) gpio_request fail\n",i + 1,gpio);continue;}printk("out-%d-gpios(%d) gpio_is_valid\n", i + 1, gpio);create_device_nodes(gpiox_class,gpio,GPIO_OUT,flags);}ret = of_property_read_u32(node, "input-gpios-num", &cnt);if (ret || !cnt) {pr_err("no in gpio\n");cnt = 0;}printk("get input-gpios-num:%d\n",cnt);for (i = 0; i < cnt; i++) {sprintf(gpio_name, "in-%d-gpios", i + 1);gpio = of_get_named_gpio(node, gpio_name,0);if (gpio_request(gpio, NULL)) {pr_err("in-%d-gpios(%d) gpio_request fail\n",i + 1,gpio);continue;}printk("in-%d-gpios(%d) gpio_is_valid\n", i + 1, gpio);create_device_nodes(gpiox_class,gpio,GPIO_IN,flags);}dev_set_drvdata(&pdev->dev, gpiox_class);pr_info("gpio_init finish\n");return 0;INIT_ERR_FREE:pr_err("gpio_init err\n");kfree(gpiox_class);return -1;
}static int user_gpio_remove(struct platform_device *pdev)
{int i = 0;struct gpiox_class_t * xdev = dev_get_drvdata(&pdev->dev);if(xdev != NULL){for(i=0;i<xdev->gpio_cnt;i++){gpio_free(xdev->gpio_devs[i].gpio);printk("gpio%d free %d\n",i,xdev->gpio_devs[i].gpio);sysfs_remove_group(&xdev->gpio_devs[i].dev->kobj, &gpiox_group);device_destroy(xdev->gpio_class,MKDEV(0, i));}class_destroy(xdev->gpio_class);}return 0;
}#ifdef CONFIG_PM
static int user_gpio_suspend(struct device *dev)
{return 0;
}static int user_gpio_resume(struct device *dev)
{return 0;
}
#else
#define user_gpio_suspend NULL
#define user_gpio_resume NULL
#endifstatic const struct dev_pm_ops user_gpio_pm_ops = {.suspend = user_gpio_suspend,.resume = user_gpio_resume,
};static struct of_device_id user_gpio_of_match[] = {{ .compatible = "user,user-init-gpio" },{},
};
MODULE_DEVICE_TABLE(of, user_gpio_of_match);static struct platform_driver user_gpio_driver = {.driver      = {.name   = "user-gpio",.owner = THIS_MODULE,.pm  = &user_gpio_pm_ops,.of_match_table    = of_match_ptr(user_gpio_of_match),},.probe        = user_gpio_probe,.remove      = user_gpio_remove,
};
module_platform_driver(user_gpio_driver);MODULE_DESCRIPTION("user gpio driver");
MODULE_AUTHOR("zhengweiqing, 1548889230@qq.com");
MODULE_LICENSE("GPL");

Makefile

Linux_for_Tegra/source/public/kernel/kernel-4.9/drivers/gpio/Makefile
最后添加:

obj-$(CONFIG_GPIO_USER)    += gpio-user.o

Kconfig

Linux_for_Tegra/source/public/kernel/kernel-4.9/drivers/gpio/Kconfig
增加GPIO_USER部分:

config GPIO_LOONGSON1tristate "Loongson1 GPIO support"depends on MACH_LOONGSON32select GPIO_GENERIChelpSay Y or M here to support GPIO on Loongson1 SoCs.config GPIO_USERtristate "USER GPIO support"depends on GPIOLIBdefault mhelpSay Y or M here to support USER GPIO .endmenumenu "Port-mapped I/O GPIO drivers"

tegra_defconfig

Linux_for_Tegra/source/public/kernel/kernel-4.9/arch/arm64/configs/tegra_defconfig
增加

CONFIG_GPIO_USER=m

编译

cd  Linux_for_Tegra/source/public/kernel/kernel-4.9
./build.sh

build.sh内容:

export CROSS_COMPILE=aarch64-linux-gnu-
make ARCH=arm64 tegra_defconfig
make ARCH=arm64 -j12#TOP_PATH=/home/z/nvidia/Linux_for_Tegra
TOP_PATH=`pwd`/../../../../
cp arch/arm64/boot/Image $TOP_PATH/kernel/Image
cp arch/arm64/boot/dts/* $TOP_PATH/kernel/dtb/sudo make ARCH=arm64 modules_install INSTALL_MOD_PATH=$TOP_PATH/rootfs/

更新设备树以及驱动上传

agx进入Recovery模式后,执行

cd  Linux_for_Tegra./flash.sh -k kernel-dtb jetson-agx-xavier-devkit mmcblk0p1

更新完成后,重启板子,将生成驱动文件 gpio-user.ko放到板子中加载。

测试

sudo insmod gpio-user.ko ls /sys/class/gpio_usr/
gpio344  gpio351  gpio393~$ cat /sys/class/gpio_usr/gpio351/direction
out
~$ cat /sys/class/gpio_usr/gpio393/direction
out
~$ cat /sys/class/gpio_usr/gpio344/direction
in~$ cat /sys/class/gpio_usr/gpio344/value
0

jetson agx xavier gpio-user驱动相关推荐

  1. AGX Xavier GPIO

    NVIDIA Jetson AGX Xavier GPIO Header Pinout 要使120Ω电阻串联的开关元件受Xavier的GPIO控制. 可以做开关的元器件有MOS管.三极管.二极管. 二 ...

  2. Nvidia Jetson AGX Xavier 硬件相关

    文章目录 前言 载板PCB层叠与阻抗 699-Pin连接器 以太网 M.2 PCIE 40-Pin扩展口 风扇接口 自动控制接口 电源域 按键和指示灯 音频接口 eSATA / USB 3.1 Typ ...

  3. 评测Jetson AGX Xavier性能

    NVIDIA Jetson AGX Xavier的GPU有512个核,是Jetson TX2的两倍,并且搭载了深度学习加速器,以及视觉加速器.Xavier的CPU表现也有了提升,从原来的6核提升到了8 ...

  4. NVIDIA Jetson AGX Xavier 安装 JetPack 注意事项

    NVIDIA Jetson AGX Xavier 安装 JetPack 注意事项 本文主要记录了我第一次接触Linux和为NVIDIA Jetson AGX Xavier安装JetPack时遇到的一些 ...

  5. Nvidia Jetson Agx Xavier 在Ros中调用GMSL2相机

    一.背景 在ros中调用GMSL2摄像头,刚开始是通过修改官方驱动包ros-meloidc-usb-cam,可能是修改的地方不对,一直报错,调用失败,要是有大佬修改成功,希望能交流一下. 后来借鉴了一 ...

  6. 玩转NVIDIA Jetson AGX Xavier

    最近项目应用需要部署到边缘模块,所以就玩起了Xavier.感觉网上的资料不多,所以从头记录一下笔记,方便大家一起学习应用. 玩转NVIDIA Jetson AGX Xavier 1.刷机(安装sdkm ...

  7. Jetson AGX Xavier 设置 CAN,打开pllaon时钟,jetpack5.1

    更新:jetpack5.1,可以直接用官方自带的jeston-io py脚本配置,40pin上的can,spi,i2c等功能. sudo /opt/nvidia/jetson-io/jetson-io ...

  8. ZED2代相机+nvidia jetson AGX xavier踩坑记录

    ZED2代相机+nvidia jetson AGX xavier踩坑记录 项目描述 nvidia jetson AGX xavier就不详细介绍了,jetson系列嵌入式开发板比一般的arrch64开 ...

  9. Jetson Xavier NX and Jetson AGX Xavier Series启动流程

    文章目录 BootROM BootLoader Components加载程序组成 通用驱动程序框架 Microboot1, MB1 TegraBoot TegraBoot BPMP TegraBoot ...

  10. 让NVIDIA Jetson AGX Xavier火力全开的秘密

    之前我们写过让Jetson TX2火力全开的秘密,让大家知道命令行工具nvpmodel能够定义一组参数,从而有效地定义给定功率的性能. Jetson Tegra系统涵盖了广泛的性能和功率需求.平衡性能 ...

最新文章

  1. Camera ISP技术
  2. 从原理到实现,详解基于朴素ML思想的协同过滤推荐算法
  3. 利用RGB-D数据进行人体检测 带dataset
  4. Flyweight 享元模式
  5. 洛谷P2057 【SHOI2007】善意的投票
  6. 通过apt自动生成建造者模式单线程版代码(二)
  7. 中国楼宇自控系统发展规划现状及未来前景预测报告2022-2028年版
  8. POJ 2386 Lake Counting DFS水水
  9. html怎么设计自己的网页,求一份自己设计的简单网页 HTML格式
  10. 1.1.0-简介-P4-一致性、2PC和3PC
  11. ORACLE多表查询优化
  12. 编程语言python怎么读-Python入门学习的计算机程序设计语言是怎样的?
  13. ct与x光的哪个辐射大_胸片、CT、PET/CT哪个辐射大?结果你很难猜到
  14. Spark.reducer.maxSizeInFlight 参数
  15. 挑战程序设计竞赛第一章 笔记
  16. 分布式系统的经典基础理论
  17. linux公社_又一个Linux发行版宣告死亡!曾经是最好的桌面版BSD操作系统
  18. J2ME 2D小游戏入门之旅(五) 实现爆炸效果、并加入道具导弹(转)
  19. iphone刷基带_揭秘:iPhone6S开机白苹果维修、安卓机刷基带分享
  20. Word2Vec之Skip-Gram与CBOW模型

热门文章

  1. Windows11卸载亚信端点安全管理系统和亚信安全软件
  2. 专题-子项-1-mysqlf-Explain-执行计划-详解--索引--调优实践
  3. 关于win7便笺无法使用qq拼音输入法
  4. CE使用指南(入门教程)
  5. DeDeCMS常用标签代码整理汇总
  6. 51单片机:独立按键控制LED灯
  7. PostgreSQL中函数json_populate_recordset的参数null::myrowtype如何使用
  8. 国内外低代码开发平台优劣势一览
  9. 从“弄潮儿”到“追风者”,康师傅还能引领市场吗?
  10. flink-1.11 Application 模式