led字符设备驱动

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>	  //for MKDEV register_chrdev_region
#include <linux/cdev.h>  //字符设备头文件
#include <asm/io.h> 

#define LED_MA 500  //主设备号 用于区分不同种类的设备  
                    //某些主设备号已经静态地分配给了大部分公用设备。见Documentation/devices.txt 。
#define LED_MI 0    //次设备号 用于区分同一类型的多个设备
#define LED_NUM 1	//设备个数

    //注:  内核驱动里不能直接访问硬件地址,所以需要映射成内核虚地址,间接的访问
	//   *(unsigned int *)LED3_CON =0x01;
	//   *(unsigned int *)LED3_DAT =1;

struct cdev led; //定义字符设备
static struct mutex lock; //定义互斥体
/*LED实际的物理地址*/
#define LED2_CON	0x11000c40
#define LED2_DAT	0x11000c44

#define LED3_CON  	0X11000C20
#define LED3_DAT  	0X11000C24

#define LED4_CON  	0x114001E0
#define LED4_DAT  	0x114001E4  
/*ioremap映射后的地址*/
unsigned int  *led2con=NULL;
unsigned int  *led2dat=NULL;

unsigned int  *led3con=NULL;
unsigned int  *led3dat=NULL;

unsigned int  *led4con=NULL;
unsigned int  *led4dat=NULL;

/*实现文件的open操作*/
int  led_open(struct inode * inode, struct file *file)
{
	mutex_lock(&lock);  //加锁
    printk("led_open ok\n");
	return 0;
}
/*实现文件的release(close)操作*/
int led_release(struct inode * inode, struct file *file)
{
	mutex_unlock(&lock);  //解锁
    printk(" led release ok\n");
	return 0;
}
/*幻数*/
#define LED_MAGIC	'l'
#define LED2_ON 	_IOW(LED_MAGIC,0,int)
#define LED2_OFF 	_IOW(LED_MAGIC,1,int)
#define LED3_ON 	_IOW(LED_MAGIC,2,int)
#define LED3_OFF 	_IOW(LED_MAGIC,3,int)
#define LED4_ON 	_IOW(LED_MAGIC,4,int)
#define LED4_OFF 	_IOW(LED_MAGIC,5,int)


/*ioctl 实现定制个性化的命令*/
long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
   // printk(" led_ioctl go\n");

      switch(cmd)
      {
      case LED2_ON:  
		writel((readl(led2dat)& (~(0x1 << 7))) | (0x1<<7),led2dat);
        break;
      case LED2_OFF:  
		writel(readl(led2dat)&(~(0x1<<7)),led2dat);
        break; 
      case LED3_ON:  
		writel((readl(led3dat)& (~(0x1 << 0))) | (0x1<<0),led3dat);
        break;
      case LED3_OFF:  
		writel(readl(led3dat) &(~(0x1<<0)),led3dat);
        break;
	  case LED4_ON:  
		writel((readl(led4dat)& (~(0x1 << 4))) | (0x1<<4),led4dat);
        break;
      case LED4_OFF:  
		writel(readl(led4dat)&(~(0x1<<4)),led4dat);
        break; 
      default:
        printk(" no found cmd = %d\n",cmd);	  	
	  	break;
      }		
	return 0;
}
/*设备的文件操作函数指针结构体*/
struct file_operations   led_fps={ 
  .open = led_open, 
  .release = led_release,	
  .unlocked_ioctl = led_ioctl,
};

int led_init(void)
{

 //1.注册设备号
    dev_t devno = MKDEV(LED_MA, LED_MI);  //把主次设备号合并生成设备ID
   int ret=0; 
    ret =register_chrdev_region(devno, LED_NUM, "newled"); //注册设备号
    if(ret<0){
        printk("register cdev error\n");
	 return -1;	
    }

//2.初始化字符设备
   cdev_init(&led,&led_fps); 			//将设备和文件操作关联起来 	
   ret = cdev_add(&led, devno, LED_NUM); //添加字符设备到系统中
   if(ret<0){
         printk("cdev_add error\n");
	 return -1;	    
   }
   /*把物理地址映射为内核虚地址*/
   led2con =ioremap(LED2_CON,4); 
   if(led2con ==  NULL){
         printk("ioremap led2con  error\n");
	 return -1;
   }
   led2dat =ioremap(LED2_DAT,4); 
   if(led2dat ==  NULL){
         printk("ioremap led2dat  error\n");
	 return -1;
   }
   led3con =ioremap(LED3_CON,4); 
   if(led3con ==  NULL){
         printk("ioremap led3con  error\n");
	 return -1;
   } 
   led3dat =ioremap(LED3_DAT,4); 
   if(led3dat ==  NULL){
         printk("ioremap led3dat  error\n");
	 return -1;
   }
   led4con =ioremap(LED4_CON,4); 
   if(led4con ==  NULL){
         printk("ioremap led4con  error\n");
	 return -1;
   }   
   led4dat =ioremap(LED4_DAT,4); 
   if(led4dat ==  NULL){
         printk("ioremap led4dat  error\n");
	 return -1;
   }
   	/*设置寄存器初值,初始化寄存器*/
    writel((readl(led2con)& (~(0xf<<28))) | (0x1<<28),led2con);
    writel((readl(led3con)&  (~(0xf<<0))) | (0x1<<0),led3con);
	writel((readl(led4con)& (~(0xf<<16))) | (0x1<<16),led4con);

	mutex_init(&lock);//初始化互斥体
	printk("led init go mutex\n");
    return 0;
}

void led_exit(void)
{
  	//注意:  申请资源要与释放资源相配对
    dev_t devno = MKDEV(LED_MA, LED_MI);

    iounmap(led2con); 
    iounmap(led2dat); 
	iounmap(led3con); 
    iounmap(led3dat); 
	iounmap(led4con); 
    iounmap(led4dat);	//取消映射 
    cdev_del(&led);		//删除设备
    unregister_chrdev_region(devno, LED_NUM);  //取消注册
    printk("led exit go\n");

}

module_init(led_init);    			//模块加载入口声明
module_exit(led_exit);  			//模块卸载入口声明
MODULE_LICENSE("Dual BSD/GPL");    	//免费开源 许可声明
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值