📄 ekii-led.c
字号:
/*
* linux/deriver/led/ekii-led.c
* led driver for Embest EduKit II
* Copyright (C) 2005 Embest <www.embedinfo.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h> // error codes
#include <linux/types.h> // size_t
#include <linux/delay.h> // mdelay
#include <asm/uaccess.h>
#include <asm/arch-S3C44B0X/s3c44b0x.h>
#undef DEBUG
#ifdef DEBUG
#define TRACE(str, args...) printk("led: " str, ## args)
#else
#define TRACE(str, args...)
#endif
#define LED_MAJOR 60
#define LED_DEVNAME "led"
#define GPB_MASK (3<<4)
#define GPF_MASK (3<<3)
#define GET_DATA(b, f) ((u8)( ((~b&0x20)>>5) | ((~b&0x10)>>2) | ((~f&0x08)>>2) | ((~f&0x10)>>1) ))
#define SET_DATA(t, b, f) ( b = (((~t&0x01)<<5) | ((~t&0x04)<<2)), f = (((~t&0x02)<<2) | ((~t&0x08)<<1)) )
#define LED_LOCK(u) down(&u->lock);
#define LED_UNLOCK(u) up(&u->lock);
struct unit {
struct semaphore lock;
u32 *PCONB; /* PCONB register */
u32 *PDATB; /* PDATB register */
u32 *PCONF; /* PCONF register */
u32 *PDATF; /* PDATF register */
u32 *PUPF; /* PUPF register */
u32 b; /* store LED 1 and LED 2 value */
u32 f; /* store LED 3 and LED 4 value */
};
static char *version = "Embest Edukit-II led driver version 1.0 (2005-04-18) <www.embedinfo.com>\n";
static struct unit led_unit = {
.PCONB = (u32 *)S3C44B0X_PCONB,
.PDATB = (u32 *)S3C44B0X_PDATB,
.PCONF = (u32 *)S3C44B0X_PCONF,
.PDATF = (u32 *)S3C44B0X_PDATF,
.PUPF = (u32 *)S3C44B0X_PUPF,
};
static void led_set_value(struct unit *unit, u8 val)
{
u32 temp;
SET_DATA(val, unit->b, unit->f);
temp = *unit->PDATB;
temp &= ~GPB_MASK;
temp |= unit->b;
*unit->PDATB = temp;
temp = *unit->PDATF;
temp &= ~GPF_MASK;
temp |= unit->f;
*unit->PDATF = temp;
}
static u8 led_get_value(struct unit *unit)
{
u8 temp = GET_DATA(unit->b, unit->f);
return temp;
}
static int led_open(struct inode *inode, struct file *file)
{
TRACE("open\n");
file->private_data = &led_unit;
MOD_INC_USE_COUNT;
return 0;
}
static int led_release(struct inode *inode, struct file *file)
{
TRACE("release\n");
MOD_DEC_USE_COUNT;
return 0;
}
static ssize_t led_read(struct file *file, char *buf, size_t count, loff_t *offset)
{
u8 temp;
int ret;
struct unit *unit = (struct unit *)file->private_data;
TRACE("read\n");
if(count > 1)
count = 1;
LED_LOCK(unit);
temp = led_get_value(unit);
ret = copy_to_user(buf, &temp, count) ? -EFAULT : count;
LED_UNLOCK(unit);
return ret;
}
static ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *offset)
{
u8 temp;
int ret;
struct unit *unit = (struct unit *)file->private_data;
TRACE("write\n");
if(count > 1)
count = 1;
LED_LOCK(unit);
ret = copy_from_user(&temp, buf, count) ? -EFAULT : count;
if(ret)
led_set_value(unit, temp);
LED_UNLOCK(unit);
return ret;
}
static struct file_operations led_ops = {
owner: THIS_MODULE,
read: led_read,
write: led_write,
open: led_open,
release: led_release,
};
/*
* led device init
*/
static void __init led_init(struct unit *unit)
{
u32 temp;
/* init device lock */
init_MUTEX(&unit->lock);
/* init io port */
temp = *unit->PCONB;
temp &= ~(3<<4);
*unit->PCONB = temp;
temp = *unit->PCONF;
temp &= ~((3<<8) | (3<<6));
temp |= ((1<<8) | (1<<6));
*unit->PCONF = temp;
temp = *unit->PUPF;
temp |= (3<<3);
*unit->PUPF = temp;
/* init data and turn on led*/
led_set_value(unit, 0x0f);
/* delay some time */
mdelay(100);
/* turn off led */
led_set_value(unit, 0x00);
}
/*
* module init
*/
int __init led_init_module(void)
{
int res;
TRACE("init_module\n");
/* print version information */
printk(KERN_INFO "%s", version);
/* register led device */
res = register_chrdev(LED_MAJOR, LED_DEVNAME, &led_ops);
if(res < 0) {
printk("ekii-led.o: unable to get major %d for led device.\n", LED_MAJOR);
return res;
}
/* then call led_init() */
led_init(&led_unit);
return 0;
}
/*
* module cleanup
*/
void __exit led_cleanup(void)
{
int res;
TRACE("cleanup\n");
/* unregister led device */
res = unregister_chrdev(LED_MAJOR, LED_DEVNAME);
if(res < 0)
printk("ekii-led.o: unable to release major %d for led device.\n", LED_MAJOR);
}
module_init(led_init_module);
module_exit(led_cleanup);
MODULE_DESCRIPTION("EduKit-II led driver");
MODULE_AUTHOR("Embest tech&info Co.,Ltd. <www.embedinfo.com>");
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -