功能: 通過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");