A40I led driver

news/2024/11/30 0:53:06/

LDE DRIVER 亲试有效
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>

#define DTS_PLATFROM_LED_CNT 1
#define DTS_PLATFROM_LED_NAME “led-wqw”

#define GPIO_DEVICE_NUM 3

struct gpioled_dev
{
dev_t devid; /* 设备号 /
int major; /
主设备号 /
int minor; /
次设备号 /
struct cdev cdev; /
字符设备 */
struct class class; / 类 */
struct device_node nd; / 设备节点 */
struct device device; / 设备 */
int led_gpio[GPIO_DEVICE_NUM];
};

struct gpioled_dev gpioled;
/*
static ssize_t gpioled_read(struct file *pfile,
char __user *buf, size_t cnt, loff_t *ppos){
int ret = 0,i;
unsigned char databuf[8]={0},val;

struct gpioled_dev *dev = pfile->private_data;printk("-----------%s-%d-----\n", __FUNCTION__,__LINE__);
printk("copy_to_user minor=%d!\r\n",minor);
for(i=0;i<GPIO_DEVICE_NUM;i++){val=gpio_get_value(dev->led_gpio[i]);databuf[0]=(databuf[0]<<(8-i))
}
ret = copy_to_user(databuf, databuf, 1);
if(ret < 0) {printk("copy_to_user failed!\r\n");return -EINVAL;
}
return ret;

}
*/
static ssize_t gpioled_write(struct file *pfile,
const char __user *buf, size_t cnt, loff_t *ppos){

int ret = 0,led_num,led_val;
unsigned char databuf[32]={0};
struct gpioled_dev *dev = pfile->private_data;ret = copy_from_user(databuf, buf, cnt);
if(ret < 0) {printk("copy_from_user failed!\r\n");return -EINVAL;
}led_num = databuf[0]-48;
led_val = databuf[1]-48;
printk("wqw copy_from_user led_num =%d----led_val=%d\r\n",led_num,led_val);gpio_set_value(dev->led_gpio[led_num], led_val);
return ret;

}

static int gpioled_open(struct inode *inode, struct file *pfile){
pfile->private_data = &gpioled;
return 0;
}

int gpioled_release(struct inode *pinode, struct file *pfile){
return 0;
}

static const struct file_operations gpioled_fops= {
.owner = THIS_MODULE,
.write = gpioled_write,
.open = gpioled_open,
.release = gpioled_release,
};

static int led_init(void){
int ret = 0,i;
enum of_gpio_flags flag;
/* 获取设备节点 /
gpioled.nd = of_find_node_by_path("/wqw-gpioled");
if (gpioled.nd == NULL) { /
失败 */
ret = -EINVAL;
}
printk(“find dts node successful!\r\n”);

for(i = 0;i < GPIO_DEVICE_NUM;i++)
{gpioled.led_gpio[i] = of_get_named_gpio_flags(gpioled.nd, "gpios", i, &flag);printk("<%s,%d>\r\n",__FUNCTION__,__LINE__);printk("LINE =%d  debug:invalid gpio,gpio=%d\n", __LINE__,gpioled.led_gpio[i]);if(!gpio_is_valid(gpioled.led_gpio[i])){printk("LINE =%d  debug:invalid gpio,gpio=%d\n", __LINE__,gpioled.led_gpio[i]);}gpio_direction_output(gpioled.led_gpio[i],1);if(gpio_request(gpioled.led_gpio[i], "led-gpio")){printk("<%s,%d>\r\n",__FUNCTION__,__LINE__);printk("debug:error pwm_gpio_init--%d\n",i);}
}
return ret;

}

/*
/{
wqw-gpioled {
compatible = “wqw-gpioled”;
gpios = <&msm_gpio 90 0x0>,
<&msm_gpio 92 0x0>,
<&msm_gpio 93 0x0>;
status = “okay”;
};
};
*/
static int gpioled_probe(struct platform_device *pla_dev){
int ret = 0;

printk("led driver and device was matched!\r\n");
/* 1,申请设备号 */
gpioled.major = 0;   /* 设备号由内核分配 */
if(gpioled.major) {  /* 定义了设备号 */gpioled.devid = MKDEV(gpioled.major, 0);ret = register_chrdev_region(gpioled.devid, DTS_PLATFROM_LED_CNT, DTS_PLATFROM_LED_NAME);
} else {            /* 没有给定设备号 */ret = alloc_chrdev_region(&gpioled.devid, 0, DTS_PLATFROM_LED_CNT, DTS_PLATFROM_LED_NAME);gpioled.major = MAJOR(gpioled.devid);gpioled.minor = MINOR(gpioled.devid);
}   
if(ret < 0) {goto fail_devid;
}
printk("gpioled_devid = %d\r\n", gpioled.devid);
printk("gpioled_major = %d\r\n", gpioled.major);
printk("gpioled_minor = %d\r\n", gpioled.minor);/* 2,添加字符设备 */
gpioled.cdev.owner = THIS_MODULE;
cdev_init(&gpioled.cdev, &gpioled_fops);
ret = cdev_add(&gpioled.cdev, gpioled.devid, DTS_PLATFROM_LED_CNT);
if(ret < 0) goto fail_cdev;
printk("cdev_add successful!\r\n");/* 3,自动创建设备节点 */
gpioled.class =  class_create(THIS_MODULE, DTS_PLATFROM_LED_NAME);
if (IS_ERR(gpioled.class)) {ret = PTR_ERR(gpioled.class);goto fail_class;
}
printk("class_create successful!\r\n");gpioled.device = device_create(gpioled.class, NULL, gpioled.devid, NULL, DTS_PLATFROM_LED_NAME);
if (IS_ERR(gpioled.device)) {ret = PTR_ERR(gpioled.device);goto fail_device;
}
printk("device_create successful!\r\n");
led_init();return 0;

fail_device:
class_destroy(gpioled.class);
fail_class:
cdev_del(&gpioled.cdev);
fail_cdev:
unregister_chrdev_region(gpioled.devid, DTS_PLATFROM_LED_CNT);
fail_devid:
return ret;
}

static int gpioled_remove(struct platform_device *pla_dev){
int i = 0;

for(i = 0;i < GPIO_DEVICE_NUM;i++)
{/* 关灯 */gpio_set_value(gpioled.led_gpio[i], 1);/* 释放IO */gpio_free(gpioled.led_gpio[i]);
}/* 删除字符设备 */
cdev_del(&gpioled.cdev);
printk("cdev_del successful!\r\n");/* 释放设备号 */
unregister_chrdev_region(gpioled.devid, DTS_PLATFROM_LED_CNT);
printk("unregister chrdev successful!\r\n");/* 摧毁设备*/
device_destroy(gpioled.class, gpioled.devid);
printk("device_destroy successful!\r\n");/* 摧毁类 */
class_destroy(gpioled.class);
printk("class_destroy successful!\r\n");
return 0;

}

/* 匹配列表 /
static const struct of_device_id led_of_match[] = {
{ .compatible = “wqw-gpioled” },
{ /
Sentinel */ }
};

struct platform_driver dts_led_platfrom = {
.driver = {
.name = “wqw-gpioled”, /* 驱动名字,用于和设备匹配 /
.of_match_table = led_of_match, /
设备树匹配表 */
},
.probe = gpioled_probe,
.remove = gpioled_remove,
};

static int __init gpioled_init(void){
return platform_driver_register(&dts_led_platfrom);
}

static void __exit gpioled_exit(void){
platform_driver_unregister(&dts_led_platfrom);
}

module_init(gpioled_init);
module_exit(gpioled_exit);
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“wqw”);


http://www.ppmy.cn/news/141002.html

相关文章

ati hd 6470m驱动

ati hd 6470m驱动是官方提供的一款显卡驱动&#xff0c;本站收集提供高速下载&#xff0c;用于解决显卡不能正常运行&#xff0c;无法正常使用的问题&#xff0c;本动适用于&#xff1a;Windows XP / Windows 7 / Windows 8 / Windows 10 32/64位操作系统。有需要的朋友可以来本…

Linux-2440下的DMA驱动(详解)

DMA(Direct Memory Access) 即直接存储器访问&#xff0c; DMA 传输方式无需 CPU 直接控制传输&#xff0c;通过硬件为 RAM 、I/O 设备开辟一条直接传送数据的通路&#xff0c;能使 CPU 的效率大为提高。 学了这么多驱动&#xff0c;不难推出DMA的编写套路: 1)注册DMA中断,分…

DALSA Xtium系列MX4采集卡和AVAL GLOBAL APX-3324A采集卡参数对比

DALSA Xtium系列MX4采集卡和AVAL GLOBAL APX-3324A采集卡参数对比 DALSA Xtium系列采集卡Xtium-CL MX4 Teledyne DALSA公司已正式发布Xtium CL MX4采集卡&#xff0c;它采用了工业级PCI Express™ Gen 2.0标准&#xff0c;是Xtium采集卡系列中的新成员。Xtium-CLMX4采集卡基于…

PCF8574AT驱动LCD1602

STM32用IIC驱动LCD1602 介绍PCF8574AT选址芯片接线图 LCD1602显示问题乱码问题 实现代码 介绍 网上寻遍了资料发现驱动LCD1602液晶屏的程序几乎都是4线或8线数据线。基本思路都是直接操作I/O&#xff0c;但是缺点是接线太多&#xff0c;十分麻烦。PCF8574和PCF8574AT这两种芯片…

TI 2640 Quick start

&#xff08;1&#xff09;下载ccs 并且安装 &#xff08;2&#xff09;下载对应版本的SDK&#xff0c;并且安装 SDK对应版本下载可以通过搜索的方式&#xff1a;simplelink_cc2640r2_sdk_5_30_00_03 &#xff08;3&#xff09;导入对应的工程文件 此篇文档可以作为参考&#x…

[其他] ATI HD6630M 显卡在Win10下终于有救了(DEll 14R N4120)

重要提示&#xff01;&#xff01;&#xff01; 以前没有仔细的研究&#xff0c;今天重装了一遍Win10。然后重新安装了显卡驱动&#xff0c;现更新一些信息 0. 本教程不适用于索尼AMD双卡本&#xff0c;索尼双卡在AMD驱动下有Intel显卡信息&#xff0c;公版没有。&#xff08;…

Java程序猿搬砖笔记(十三)

文章目录 MySQL数据库生成自动增长序号MySQL修改密码SpringBoot定时任务解决Mybatis出现的各种Parameter not found. Available parameters are [ , ]Mybatis的foreach标签遍历mapSpringBoot项目打包SpringBoot Async使用注意事项Spring Cloud Config bootstrap文件&#xff…

【已解决】vue/react .env.development 中读取不到变量:undefined

文章目录 一、问题二、解决三、拓展学习 一、问题 react 项目中&#xff0c;通过 process.env. 在 .env 或 .env.development 中读取不到变量&#xff0c;undefined 二、解决 首先&#xff0c;确保 .env 和 .env.development 文件放在项目根目录&#xff08;和 package.json…