led驱动

 

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/device.h>

#define LED_MAJOR 0    /*预设的LED_MAJOR的主设备号*/
static int led_major = LED_MAJOR;

static struct class *led_drv_class;
static struct class_device	*led_drv_class_dev;

volatile unsigned long *gpbcon = NULL ;
volatile unsigned long *gpbdat = NULL ;  
volatile unsigned long *gpbup = NULL ;

struct cdev cdev; /*cdev结构体*/ 
static int led_drv_open(struct inode *inode, struct file *file)
{
	//printk("first_drv_open\n");
	/* 配置GPF5,6,8,10为输出 */

    *gpbcon &= ~((0x3<<(5*2)) | (0x3<<(6*2)) | (0x3<<(8*2) | (0x3<<(10*2))));
    *gpbcon |= ((0x1<<(8*2)) | (0x1<<(5*2)) | (0x1<<(6*2)) | (0x1<<(10*2)));	
    *gpbup = 0x0;
    printk("first_drv_open\n");
    return 0;
}

static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
    int val;
    int ret;  
    copy_from_user(&val, buf, count) ; 
   
    if (val == 1)
    {
	// 点灯
	*gpbdat &= ~( (1<<5) | (1<<6) |(1<<8)| (1<<10));
        printk("first_drv_write 1111111\n");
    }
    else
    {
	// 灭灯
	*gpbdat |= ( (1<<5) | (1<<6) |(1<<8)| (1<<10));
        printk("first_drv_write 00000\n");
    }
    return 0;
}

static struct file_operations led_drv_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   led_drv_open,     
    .write	=	led_drv_write,	   
};
/*初始化并注册cdev*/
static void led_setup_cdev(void)
{
  int err, devno = MKDEV(led_major, 0);//index 为从设备号
  cdev_init(&cdev, &led_drv_fops);
  cdev.owner = THIS_MODULE;
  cdev.ops = &led_drv_fops;
  err = cdev_add(&cdev, devno, 1);//devno 为第一个设备号,1为数量
  if (err)
    printk(KERN_NOTICE "Error %d adding", err);
}

static int led_drv_init(void)
{
    int result;
    dev_t devno;
    devno=MKDEV(led_major,0);
    if(led_major)//静态申请设备号
        result=register_chrdev_region(devno,1,"led1_dev");
    else
    {
        result = alloc_chrdev_region(&devno,0,1,"led1_dev");//动态申请设备号
        led_major = MAJOR(devno);
    }
    if(result<0)
    {
        printk (KERN_WARNING "hello: can't get major number %d\n", led_major);
        return result;
    }        
    led_setup_cdev();    
    led_drv_class = class_create(THIS_MODULE, "leddrv");
    if(IS_ERR(led_drv_class)) 
    {
      printk("Err: failed in creating class.\n");
      return -1; 
    } 
    led_drv_class_dev = device_create(led_drv_class, NULL, MKDEV(led_major, 0),NULL,"xyz"); /* /dev/xyz */
 
    gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16);
    gpbdat = gpbcon + 1;
    gpbup = gpbcon + 2;
    return 0;	
}

static void led_drv_exit(void)
{
    cdev_del(&cdev); // 注销cdev
    unregister_chrdev_region(MKDEV(led_major,0),1);//释放设备号
    //device_destroy(led_drv_class_dev,MKDEV(led_major,0));
    device_unregister(led_drv_class_dev);
    class_destroy(led_drv_class);
    iounmap(gpbcon)
}

module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");

你可能感兴趣的:(led驱动)