request_mem_region 實踐

功能:  通過request_mem_region 和  ioremap,實現 led 驅動,led功能如前面《字符設備註冊實例》

 

代碼示例

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <mach/gpio-bank.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <asm/io.h>

//#define GPJ0CON    S5PV210_GPJ0CON
//#define GPJ0DAT    S5PV210_GPJ0DAT

#define  GPJ0BASE    (0XE0200240)

//#define rGPJ0CON   *((volatile unsigned int *)GPJ0CON)
//#define rGPJ0DAT   *((volatile unsigned int *)GPJ0DAT)

#define LED1_OFF    (1 << 3)
#define LED2_OFF    (1 << 4)
#define LED3_OFF    (1 << 5)

unsigned int  major_led1,major_led2; 
struct cdev led1;
struct cdev led2;
struct class *cla_led1;
struct resource *GPJ0RES ;
unsigned int *led_addr;


struct gpj0_register
{
	unsigned int con;
	unsigned int data;
	
};

struct gpj0_register *led_reg;




static int led_01_open(struct inode *inode, struct file *file)
{
    led_reg->data &= ~(LED1_OFF | LED2_OFF);

	return 0;
}
static int led_01_release(struct inode *inode, struct file *file)
{
	led_reg->data |= (LED1_OFF | LED2_OFF);
	return 0;
}

struct file_operations led_01_fops = {
	.open    = led_01_open,
	.release = led_01_release, 
};

static int lll_open(struct inode *inode, struct file *file)
{
    led_reg->data &= ~LED3_OFF;

	return 0;
}
static int lll_release(struct inode *inode, struct file *file)
{
	 led_reg->data |= LED3_OFF;
	return 0;
}

struct file_operations lll_fops = {
	.open    = lll_open,
	.release = lll_release, 
};


int led_gpio_init(void)
{
	led_reg->con &= ~((0xff << 12) | (0xff << 16) | (0xff << 20)); //clear 
	led_reg->con |= ((1 << 12) | (1 << 16) | (1 << 20));           // set as output

	led_reg->data |= (LED1_OFF | LED2_OFF | LED3_OFF);     //set all leds off

	return 0;
}


int led_register(struct cdev *led, unsigned int *major, unsigned count,const char *name,struct file_operations *led_fops)
{
	int err;

	err = alloc_chrdev_region(major, 0, count, name);
	if (err)
		goto err1;
	
	cdev_init(led, led_fops);
	err = cdev_add(led, *major, count);
	if (err)
		goto err2;


	return 0;

err2:
    cdev_del(&led1);
	unregister_chrdev_region(major_led1, 2);
err1:
	return err;

}


int __init hello_init(void)
{
	int ret;

	GPJ0RES = request_mem_region(GPJ0BASE, 8, "gpj0base");
	if(!GPJ0RES)
		return -1;
    
    led_reg = ioremap(GPJ0BASE, 8);



	led_gpio_init();    
	ret = led_register(&led1, &major_led1, 2,"led_01",&led_01_fops);
	if (ret)
		return ret;    
	ret = led_register(&led2, &major_led2, 1,"led_03",&lll_fops) ;  
	if (ret)
		return ret; 

	cla_led1 = class_create(THIS_MODULE, "led_pompey");
	if(IS_ERR(cla_led1))
		printk(KERN_ERR"Can not create class\n");
	device_create(cla_led1, NULL, major_led2, NULL, "led3");



	return ret;     

}

void __exit hello_exit(void)
{
	printk("hello exit\n");
	iounmap(led_reg);
	release_mem_region(GPJ0BASE, 8);
	

	cdev_del(&led1);
	cdev_del(&led2);

	unregister_chrdev_region(major_led2, 1);
	unregister_chrdev_region(major_led1, 2);
	device_destroy(cla_led1,major_led2);
	class_destroy(cla_led1);
	
}

module_init(hello_init);
module_exit(hello_exit);


MODULE_LICENSE("GPL");

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章