#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");#i