Linux driver —— led

@linux version: 2.6.32

@board: mini2440


将IO口寄存器映射为IO内存。



#include <linux/fs.h>

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <linux/moduleparam.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/device.h>

#define GPB 0x56000010
#define GPBCON 0x00
#define GPBDAT 0x04


#define LED_NAME "myled"

#define LED_MAJOR 225

#define LED_ON 1
#define LED_OFF 0

static led_major = LED_AMJOR;

struct led_dev 
{
struct cdev cdev;
struct class *led_class;
void __iomem *GPB_BASE;
};

struct led_dev *led_devp;

static int led_open(struct inode *inode, struct file *filp)
{
filp->private_data = led_devp;
return 0;
}

static int led_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned int arg)
{
int dat;
struct led_dev *dev = file->private_data;

printk(KERN_NOTICE"Using driver written by Jeremy Shen^_^\n");

if(arg<0 || arg>3)
{
return -EINVAL;
}

switch(cmd)
{
case LED_ON:
dat = ioread16(dev->GPB_BASE+GPBDAT);
dat &= ~(1<<(5+arg));
iowrite16(dat,dev->GPB_BASE+GPBDAT);
return 0;
case LED_OFF:
dat = ioread16(dev->GPB_BASE+GPBDAT);
dat |= 1<<(5+arg);
iowrite16(dat,dev->GPB_BASE+GPBDAT);
return 0;
default:
return -EINVAL;
}

}

static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.ioctl = led_ioctl,
};

static void led_setup_cdev(struct led_dev *dev, int index)
{
int err,devno = MKDEV(led_major,index);

cdev_init(&dev->cdev,&led_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &led_fops;
err = cdev_add(&dev->cdev,devno,1);
if(err)
printk(KERN_ERR"Error %d adding LED%d",err,index);
}

static __init int led_init(void)
{
int con,dat,ret;
dev_t devno = MKDEV(led_major,0);

if(led_major)
ret = register_chrdev_region(devno,1,LED_NAME);
else
{
ret = alloc_chrdev_region(&devno,0,1,LED_NAME);
led_major = MAJOR(devno);
}
if(ret<0)
{
printk(KERN_WARNING"Led: cannot get major %d\n",led_major);
return ret;
}

led_devp = kmalloc(sizeof(struct led_dev),GFP_KERNEL);
if(!led_devp)
{
ret = -ENOMEM;
goto fail_malloc;
}
memset(led_devp,0,sizeof(struct led_devp));

led_devp->GPB_BASE = ioremap(GPB,16);
if(!(led_devp->GPB_BASE))
{
printk(KERN_ERR"Iomap fail!\n");
ret = -ENOMEM;
goto fail_ioremap;
}

led_devp->led_class = class_create(THIS_MODULE,"led_class");
if(IS_ERR(led_devp->led_class))
{
printk(KERN_NOTICE"Err: failed in creating class\n");
ret = -1;
goto fail_class;
}
device_create(led_devp->led_class,NULL,devno,NULL,LED_NAME"%d",0);

con = ioread32(led_devp->GPB_BASE+GPBCON);
con &= ~(3<<10|3<<12|3<<14|3<<16);
con |= (1<<10|1<<12|1<<14|1<<16);
iowrite32(con,led_devp->GPB_BASE+GPBCON);

dat = ioread16(led_devp->GPB_BASE+GPBDAT);
dat |= (15<<5); 
iowrite16(dat,led_devp->GPB_BASE+GPBDAT);

led_setup_cdev(led_devp,0);

printk(KERN_NOTICE"Led driver is loaded!\n");
return 0;

fail_class:
iounmap(led_devp->GPB_BASE);
fail_ioremap:
kfree(led_devp);
fail_malloc:
unregister_chrdev_region(devno,1);

return ret;

}

static __exit void led_exit(void)
{
iounmap(led_devp->GPB_BASE);
device_destroy(led_devp->led_class,MKDEV(led_major,0));
class_destroy(led_devp->led_class);
cdev_del(led_devp->cdev);
kfree(led_devp);
unregister_chrdev_region(MKDEV(led_major,0),1);
//unregister_chrdev(LED_MAJOR,LED_NAME);
printk(KERN_NOTICE"Led driver is removed!\n");
}

module_init(led_init);
module_exit(led_exit);
module_param(led_major,int,S_IRUGO);

MODULE_AUTHOR("Jeremy shen");
MODULE_LICENSE("GPL");

你可能感兴趣的:(Linux driver —— led)