全志linux led驱动程序,芯灵思Sinlinx A64 linux通过设备树写LED驱动(附参考代码,未测试)...
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MY_DEVICE_NAME "my_LED_device"
// 獲取到設備樹中到節點
static int gpio = -1;
int get_irqno_from_node(void)
{
struct gpio_config config;
struct device_node *np = of_find_node_by_path("/leds");
IF(np){
printk("find node ok\n");
}
else{
printk("find node failed\n");
}
gpio = of_get_named_gpio_flags(nd, "gpios", i, (enum of_gpio_flags *)&config);// 從設備樹中讀取gpios的GPIO配置編號和標志
if(!gpio_is_valid(gpio)){
//判斷該 GPIO 編號是否有效,有效gpio_request 則申請占用該 GPIO。如果初始化過程出錯,需要調用 gpio_free 來釋放之前申請過且成功的 GPIO
printk("gpio isn't valid\n");
return -1;
}
if(gpio_request(gpio, "leds") < 0)
printk("gpio request failed %d\n", gpio);
gpio_direction_output(gpio, 1); //關燈
return 0;
}
static int my_open (struct inode *node, struct file *filp)
{
if(gpio)
{
printk("open ok\n");
}
else
{
return -EINVAL;
}
return 0;
}
static ssize_t my_write (struct file *filp, const char __user *buf, size_t size, loff_t *off)
{
unsigned char val;
copy_from_user(&val, buf, 1);
printk(" gpl_dat address? ?0x%x\n",gpl_dat);
if (val)
{
gpio_direction_output(gpio, 0); //關燈
printk("led on\n");
}
else
{
gpio_direction_output(gpio, 1); //關燈
printk("led off\n");
}
return 1;
}
static const struct file_operations my_led_fops = {
//step 1 :定義file_operations結構體
.open = my_open,
.write = my_write,
};
//step 1 :
static struct class *led_class;
static struct cdev *pcdev;? ?? ?//定義一個cdev指針
static dev_t n_dev;? ?? ?? ?? ?//第一個設備號(包含了主和次)
static int __init led_device_init(void)
{//step 2 :注冊
int ret = -1;
pcdev = cdev_alloc();//分配cdev結構空間
if(pcdev == NULL) {
printk(KERN_EMERG" cdev_alloc??error\n");
ret = -ENOMEM;? ?/* 分配失敗 */
return ret;
}
//2. 動態申請設備號
ret = alloc_chrdev_region(&n_dev, 0 , 2, MY_DEVICE_NAME);
if(ret < 0 ) {
//釋放前面成功的資源
kfree(pcdev);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?/*釋放cdev結構空間 */
printk(KERN_EMERG"alloc_chrdev_region??error\n");
return ret;
}
cdev_init(pcdev, &my_led_fops);? ???//初始化cdev結構? ?? ?? ???/* 建立cdev和file_operations之間的連接 */
/*
或這樣初始化cdev結構
pcdev->owner = THIS_MODULE;
pcdev->ops = &my_led_fops;
*/
ret = cdev_add(pcdev, n_dev, 2) ;// 向內核里面添加一個驅動,注冊驅動
if(ret < 0 ) {
//釋放前面成功的資源
unregister_chrdev_region(n_dev,??2);? ?? ? /*??釋放前面申請的調和號*/
kfree(pcdev);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? /* 釋放cdev結構空間 */
printk(KERN_EMERG"alloc_chrdev_region??error\n");
return ret;
}
/*自動創建設備節點/dev/SinlinxA64_LED*/
led_class = class_create(THIS_MODULE, "myled");
device_create(led_class, NULL, n_dev, NULL, "SinlinxA64_LED");
get_irqno_from_node();
printk(KERN_EMERG"cdev ok\n");
return 0;
}
static void __exit led_device_exit(void)
{? ? //step 2 :注銷
//注銷cdev結構
cdev_del(pcdev);
//釋放設備號
unregister_chrdev_region(n_dev, 2); /*起始設備號(主、次) 連續的次設備號數量*/
//釋放cdev結構空間
kfree(pcdev);
device_destroy(led_class, n_dev);
class_destroy(led_class);
gpio_free(gpio);
printk(KERN_EMERG"cdev_del ok\n");
}
module_init(led_device_init);
module_exit(led_device_exit);
MODULE_LICENSE("GPL");
總結
以上是生活随笔為你收集整理的全志linux led驱动程序,芯灵思Sinlinx A64 linux通过设备树写LED驱动(附参考代码,未测试)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux七个运行级如何设置,RHEL7
- 下一篇: linux 网卡丢弃多播包,rp_fil