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”);

A40I led driver相关推荐

  1. 广芯模拟开关芯片,SWITCHING CHARGER,ANALOG SWITCH,LED DRIVER,LDO

    开关充电(switching CHARGER):            BCT24157,封装:WLCSP-20L BCT24296,封装:4X4 QFN-24L MIPI 开关(MIPI SWITC ...

  2. A40i使用笔记:GPIO操作方式(用于测试设备io驱动性能)(传统方式、设备树方式、寄存器方式操作GPIO)

    一.前言 前文介绍了文件io的驱动方式,可以用于led点灯灭灯或者一些简单的不需求时序控制的ic操作,但是用于功能类ic,如AD采集芯片等时序控制需求高的,就不行了,这时候就需求高速io去实现指定的芯 ...

  3. NanoPi NEO Air使用十:自己编写驱动来控制LED

    NanoPi NEO Air使用一:介绍 NanoPi NEO Air使用二:固件烧录 NanoPi NEO Air使用三:OverlayFS.CPU温度和频率.wifi.蓝牙.npi-config ...

  4. 驱动程序实例(一):LED设备驱动程序( platform + cdev)

    结合之前对Linux内核的platform总线 ,以及对字符设备的cdev接口的分析,本文将编写基于platform总线与cdev接口的LED设备的实例代码并对其进行分析. platform总线分析, ...

  5. linux字符驱动之点亮LED

    上一节中,我们讲解了如何自动创建设备节点,这一节我们在上一节的基础上,实现点亮LED. 上一节文章链接:https://blog.csdn.net/qq_37659294/article/detail ...

  6. 驱动框架7——使用gpiolib完成led驱动

    以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 十四.使用gpiolib完成led驱动 1.流程分析 (1)第1步:使用gpio_request申请要使用的一个G ...

  7. 驱动框架5——基于驱动框架写led驱动

    以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 五.基于驱动框架写led驱动1 1.分析 (1)参考哪里?  drivers/leds/leds-s3c24xx. ...

  8. 字符设备驱动程序——点亮、熄灭LED操作

    2019独角兽企业重金招聘Python工程师标准>>> 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流的设 ...

  9. Linux下实现流水灯等功能的LED驱动代码及测试实例

    驱动代码: #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> ...

最新文章

  1. (0058)iOS开发之iOS8新特性IBDesignable的使用
  2. 返回对象2(调用了拷贝构造函数)
  3. 2022-2028年中国石油焦行业运行现状与发展态势展望报告
  4. ROS学习之roslaunch的node标签
  5. 15:46 2009-8-2 sql2005客户端装不上,碎片不能整理,createthread
  6. readline安装
  7. linux下与windows下的换行符
  8. IIS7 经典模式和集成模式的区别分析(转载)
  9. 面试题: 大公司面试 !=!=未看
  10. 【转载】python中strip(),lstrip(),rstrip()函数的区别
  11. 试用期不合格通知单可以签吗?
  12. 舱机器人尾巴毛茸茸_并无卵用的毛茸茸机器人 如此呆萌 设计是为了爱
  13. mtk android 关机充电,MTK充电开机关机过程
  14. iOS上架详细通关教程(提交到AppStore)
  15. Aria2+motrix设置教程
  16. 微信小游戏开新手攻略
  17. java ee中ssh学后感_学习SSH,SSM框架有感
  18. svn设置 修改服务器,svn设置 修改服务器ip地址
  19. (渗透测试后期)Linux进程隐藏详解
  20. Spring定时器之翘楚-Quartz

热门文章

  1. 战火与秩序迁城显示服务器忙,战火与秩序迁城方法介绍
  2. 使用requests爬取实习僧网站数据
  3. [人工智能-深度学习-81]:视觉 - 视频换脸软件大全
  4. Lidar Object detection
  5. 乐符识别matlab,GitHub - Nuullll/music-synthesizer: Homework No.1 for summer course: MATLAB
  6. 深入学习Docker网络(看这篇就完全够了)
  7. shell技巧4 - nm命令解决AppStore2.5.2被拒问题
  8. 【亚马逊】AWS re:Invent 2022 创新不平衡
  9. c语言分苹果程序,小朋友学C语言(14):分苹果(小学奥数题)
  10. 某网站电商运营数据分析案例