/*********************************************
* *GEC2410-BOX
* *date: created at 2007-09-18 by baibj
* led驱动
*********************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef MYDEBUG
#include
#include
#include
#include
#endif
#define DEVICE_NAME "led" //驱动名
#define LEDRAW_MINOR 1 //子设备号
#define CMD_OFF 0 //关led命令
#define CMD_ON 1 //开led命令
static int ledMajor = 0;
static int ledMinor = 0;
//led驱动结构
struct led_dev{
struct cdev cdev ;
char data[1] ;
};
static struct led_dev *myled ;
module_param(ledMajor,int,S_IRUGO) ;
MODULE_LICENSE("Dual BSD/GPL") ;
void __exit led_driver_exit(void) ;
void s3c2410_led_gpio_init(void)
{
__raw_writel((__raw_readl(S3C2410_GPFCON)|0xFF00)&0xFFFF55FF,S3C2410_GPFCON) ;
__raw_writel(__raw_readl(S3C2410_GPFUP)|0xF0,S3C2410_GPFUP);
__raw_writel((__raw_readl(S3C2410_GPFDAT)|0xF0)&0xAF,S3C2410_GPFDAT);
}
void s3c2410_led_light(char c)
{
__raw_writel((__raw_readl(S3C2410_GPFDAT)|0xF0)&(c|0xF),S3C2410_GPFDAT) ;
}
int s3c2410_led_open(struct inode *inode, struct file *filp)
{
//GPE11,GPE12---output
//__raw_writel(__raw_readl(S3C2410_GPECON) & (~(0x0f<<22)) | (0x05<<22), S3C2410_GPECON);
//__raw_writel(__raw_readl(S3C2410_GPEDAT) | (0x03<<11), S3C2410_GPEDAT); //output--H
struct led_dev *dev ;
printk(KERN_INFO DEVICE_NAME ": opened.\n");
dev=container_of(inode->i_cdev,struct led_dev,cdev) ;
filp->private_data=dev;
return 0;
}
int s3c2410_led_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret=0 ;
int v=0 ;
struct led_dev *dev=(struct led_dev*)file->private_data ;
switch(cmd){
case CMD_OFF:
v=0 ;
dev->data[0]=__raw_readl(S3C2410_GPFDAT)&~(1<
break ;
case CMD_ON :
v=1 ;
dev->data[0]=__raw_readl(S3C2410_GPFDAT)|(1< break ;
default:
printk(KERN_INFO" command %d is not support!\n",cmd) ;
return -EFAULT ;
break ;
}
s3c2410_led_light(dev->data[0]) ;
return 0 ;
}
ssize_t s3c2410_led_read(struct file *filp,char __user *buf,size_t count,
loff_t *f_pos)
{
ssize_t retval = 0 ;
struct led_dev *dev=(struct led_dev*)filp->private_data ;
if(copy_to_user(buf,(void*)(dev->data),count))
return -EFAULT ;
return retval ;
}
ssize_t s3c2410_led_write(struct file *filp,const char __user *buf,size_t count,
loff_t *f_pos)
{
ssize_t retval = 0 ;
struct led_dev *dev=filp->private_data ;
if(copy_from_user((void*)(dev->data),buf,count))
return -EFAULT ;
s3c2410_led_light(dev->data[0]) ;
return retval ;
}
int s3c2410_led_release(struct inode *inode, struct file *filp)
{
printk(KERN_INFO DEVICE_NAME ": released.\n");
return 0;
}
struct file_operations s3c2410_fops = {
owner: THIS_MODULE,
open: s3c2410_led_open,
ioctl: s3c2410_led_ioctl,
release: s3c2410_led_release,
read: s3c2410_led_read ,
write: s3c2410_led_write,
};
int led_setup_cdev(struct led_dev *dev,int index)
{
int err,devno=MKDEV(ledMajor,ledMinor) ;
cdev_init(&dev->cdev,&s3c2410_fops) ;
dev->cdev.owner = THIS_MODULE ;
err = cdev_add(&dev->cdev,devno,1) ;
if(err)
printk(KERN_INFO"Error:add cdev fail:%d\n",err) ;
return err ;
}
int __init led_driver_init(void)
{
int ret;
dev_t dev = 0 ;
if(ledMajor){
dev=MKDEV(ledMajor,ledMinor) ;
ret=register_chrdev_region(dev,1,DEVICE_NAME) ;
}else{
ret=alloc_chrdev_region(&dev,ledMinor,1,DEVICE_NAME) ;
ledMajor=MAJOR(dev) ;
}
if(ret<0){
printk(KERN_INFO DEVICE_NAME " can't get major number\n") ;
return ret ;
}
myled=kmalloc(sizeof (struct led_dev),GFP_KERNEL) ;
if(!myled){
ret =-ENOMEM ;
goto fail ;
}
memset(myled,0,sizeof(struct led_dev)) ;
led_setup_cdev(myled,0) ;
s3c2410_led_gpio_init() ;
return 0 ;
fail:
led_driver_exit() ;
return ret ;
}
void __exit led_driver_exit(void)
{
dev_t devno=MKDEV(ledMajor,ledMinor) ;
cdev_del(&myled->cdev) ;
kfree(myled) ;
unregister_chrdev_region(devno,1) ;
}
//模块加载
module_init(led_driver_init);
//模块卸载
module_exit(led_driver_exit);
阅读(1409) | 评论(0) | 转发(0) |