jetson agx xavier gpio-user驱动
设备树
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驱动相关推荐
- AGX Xavier GPIO
NVIDIA Jetson AGX Xavier GPIO Header Pinout 要使120Ω电阻串联的开关元件受Xavier的GPIO控制. 可以做开关的元器件有MOS管.三极管.二极管. 二 ...
- Nvidia Jetson AGX Xavier 硬件相关
文章目录 前言 载板PCB层叠与阻抗 699-Pin连接器 以太网 M.2 PCIE 40-Pin扩展口 风扇接口 自动控制接口 电源域 按键和指示灯 音频接口 eSATA / USB 3.1 Typ ...
- 评测Jetson AGX Xavier性能
NVIDIA Jetson AGX Xavier的GPU有512个核,是Jetson TX2的两倍,并且搭载了深度学习加速器,以及视觉加速器.Xavier的CPU表现也有了提升,从原来的6核提升到了8 ...
- NVIDIA Jetson AGX Xavier 安装 JetPack 注意事项
NVIDIA Jetson AGX Xavier 安装 JetPack 注意事项 本文主要记录了我第一次接触Linux和为NVIDIA Jetson AGX Xavier安装JetPack时遇到的一些 ...
- Nvidia Jetson Agx Xavier 在Ros中调用GMSL2相机
一.背景 在ros中调用GMSL2摄像头,刚开始是通过修改官方驱动包ros-meloidc-usb-cam,可能是修改的地方不对,一直报错,调用失败,要是有大佬修改成功,希望能交流一下. 后来借鉴了一 ...
- 玩转NVIDIA Jetson AGX Xavier
最近项目应用需要部署到边缘模块,所以就玩起了Xavier.感觉网上的资料不多,所以从头记录一下笔记,方便大家一起学习应用. 玩转NVIDIA Jetson AGX Xavier 1.刷机(安装sdkm ...
- Jetson AGX Xavier 设置 CAN,打开pllaon时钟,jetpack5.1
更新:jetpack5.1,可以直接用官方自带的jeston-io py脚本配置,40pin上的can,spi,i2c等功能. sudo /opt/nvidia/jetson-io/jetson-io ...
- ZED2代相机+nvidia jetson AGX xavier踩坑记录
ZED2代相机+nvidia jetson AGX xavier踩坑记录 项目描述 nvidia jetson AGX xavier就不详细介绍了,jetson系列嵌入式开发板比一般的arrch64开 ...
- Jetson Xavier NX and Jetson AGX Xavier Series启动流程
文章目录 BootROM BootLoader Components加载程序组成 通用驱动程序框架 Microboot1, MB1 TegraBoot TegraBoot BPMP TegraBoot ...
- 让NVIDIA Jetson AGX Xavier火力全开的秘密
之前我们写过让Jetson TX2火力全开的秘密,让大家知道命令行工具nvpmodel能够定义一组参数,从而有效地定义给定功率的性能. Jetson Tegra系统涵盖了广泛的性能和功率需求.平衡性能 ...
最新文章
- Camera ISP技术
- 从原理到实现,详解基于朴素ML思想的协同过滤推荐算法
- 利用RGB-D数据进行人体检测 带dataset
- Flyweight 享元模式
- 洛谷P2057 【SHOI2007】善意的投票
- 通过apt自动生成建造者模式单线程版代码(二)
- 中国楼宇自控系统发展规划现状及未来前景预测报告2022-2028年版
- POJ 2386 Lake Counting DFS水水
- html怎么设计自己的网页,求一份自己设计的简单网页 HTML格式
- 1.1.0-简介-P4-一致性、2PC和3PC
- ORACLE多表查询优化
- 编程语言python怎么读-Python入门学习的计算机程序设计语言是怎样的?
- ct与x光的哪个辐射大_胸片、CT、PET/CT哪个辐射大?结果你很难猜到
- Spark.reducer.maxSizeInFlight 参数
- 挑战程序设计竞赛第一章 笔记
- 分布式系统的经典基础理论
- linux公社_又一个Linux发行版宣告死亡!曾经是最好的桌面版BSD操作系统
- J2ME 2D小游戏入门之旅(五) 实现爆炸效果、并加入道具导弹(转)
- iphone刷基带_揭秘:iPhone6S开机白苹果维修、安卓机刷基带分享
- Word2Vec之Skip-Gram与CBOW模型
热门文章
- Windows11卸载亚信端点安全管理系统和亚信安全软件
- 专题-子项-1-mysqlf-Explain-执行计划-详解--索引--调优实践
- 关于win7便笺无法使用qq拼音输入法
- CE使用指南(入门教程)
- DeDeCMS常用标签代码整理汇总
- 51单片机:独立按键控制LED灯
- PostgreSQL中函数json_populate_recordset的参数null::myrowtype如何使用
- 国内外低代码开发平台优劣势一览
- 从“弄潮儿”到“追风者”,康师傅还能引领市场吗?
- flink-1.11 Application 模式