/****************************************************************
Copyright(c) 2009-2010,Newkoom Net Tech.Co,.Ltd
模块名称(Filename): led_s3c2410.c
项目名称(Projectname): RPM(Remote Power Manager System)
版本号(Version): 1.0.0
创建日期(Date): 2009-8-22
作者(Author): ZMF(Zheng meifu)
功能描述(Description): led driver for linux2.6.14.1
其他说明(Others):
修改记录(History):
****************************************************************/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/hardware.h>
#include <linux/devfs_fs_kernel.h>
//#define CONFIG_TARGET_RPM // 注释掉则led 驱动程序为YL2410开发板。
// 此参数已在内核配置里定义了,此处为调试目的
//定义则为RPM实际目标板
#define DEVICE_NAME "ledrpm"
#define LEDRPM_MAJOR 223
#ifndef CONFIG_TARGET_RPM
#define LEDRPM_NUM 4 //ledrpm num
#else
#define LEDRPM_NUM 6 //ledrpm num
#endif
#define LEDRPM_ON 0
#define LEDRPM_OFF 1
#define LEDRPM_DELAYMS(X) (HZ/(1000/(X)))
//#define LEDRPM_DEBUG
#ifdef LEDRPM_DEBUG
#define PRINTK(arg...) printk(arg)
#else
#define PRINTK(arg...) do{}while(0)
#endif
typedef unsigned int LEDRPM_RET;
struct ledrpm_dev_t{
struct cdev cdev;
struct timer_list timer;
#ifdef CONFIG_DEVFS_FS
int devfs;
#endif
};
struct ledrpm_info{
unsigned int pin;//gpio port
unsigned int pin_setting;
int ledrpm_code;//ledrpm value
};
static dev_t ledrpm_major=LEDRPM_MAJOR;
struct ledrpm_dev_t ledrpm_dev;
static const struct ledrpm_info ledrpm_info_tab[] = {
#ifndef CONFIG_TARGET_RPM
{ S3C2410_GPF4,S3C2410_GPF4_OUTP,LEDRPM_ON},
{ S3C2410_GPF5,S3C2410_GPF5_OUTP,LEDRPM_OFF},
{ S3C2410_GPF6,S3C2410_GPF6_OUTP,LEDRPM_ON},
{ S3C2410_GPF7,S3C2410_GPF7_OUTP,LEDRPM_OFF},
#else
{ S3C2410_GPD0,S3C2410_GPD0_OUTP,LEDRPM_ON},
{ S3C2410_GPD1,S3C2410_GPD1_OUTP,LEDRPM_ON},
{ S3C2410_GPD2,S3C2410_GPD2_OUTP,LEDRPM_ON},
{ S3C2410_GPD3,S3C2410_GPD3_OUTP,LEDRPM_ON},
{ S3C2410_GPD4,S3C2410_GPD4_OUTP,LEDRPM_ON},
{ S3C2410_GPD5,S3C2410_GPD5_OUTP,LEDRPM_ON},
#endif
};
#ifndef CONFIG_TARGET_RPM
#define GPIO_LEDPOWER (S3C2410_GPB0)
#define GPIO_LEDPOWER_INP (S3C2410_GPB0_INP)
#define GPIO_LEDPOWER_OUTP (S3C2410_GPB0_OUTP)
#define GPIO_LED01 (S3C2410_GPF4)
#define GPIO_LED01IN (S3C2410_GPF4_INP)
#define GPIO_LED01OU (S3C2410_GPF4_OUTP)
#define GPIO_LED02 (S3C2410_GPF5)
#define GPIO_LED02IN (S3C2410_GPF5_INP)
#define GPIO_LED02OU (S3C2410_GPF5_OUTP)
#define GPIO_LED03 (S3C2410_GPF6)
#define GPIO_LED03IN (S3C2410_GPF6_INP)
#define GPIO_LED03OU (S3C2410_GPF6_OUTP)
#define GPIO_LED04 (S3C2410_GPF7)
#define GPIO_LED04IN (S3C2410_GPF7_INP)
#define GPIO_LED04OU (S3C2410_GPF7_OUTP)
#define GPIO_LED05 (S3C2410_GPB0)
#define GPIO_LED05IN (S3C2410_GPB0_INP)
#define GPIO_LED05OU (S3C2410_GPB0_OUTP)
#define GPIO_LED06 (S3C2410_GPB0)
#define GPIO_LED06IN (S3C2410_GPB0_INP)
#define GPIO_LED06OU (S3C2410_GPB0_OUTP)
#else
#define GPIO_LEDPOWER (S3C2410_GPG10)
#define GPIO_LEDPOWER_INP (S3C2410_GPG10_INP)
#define GPIO_LEDPOWER_OUTP (S3C2410_GPG10_OUTP)
#define GPIO_LED01 (S3C2410_GPD0)
#define GPIO_LED01IN (S3C2410_GPD0_INP)
#define GPIO_LED01OU (S3C2410_GPD0_OUTP)
#define GPIO_LED02 (S3C2410_GPD1)
#define GPIO_LED02IN (S3C2410_GPD1_INP)
#define GPIO_LED02OU (S3C2410_GPD1_OUTP)
#define GPIO_LED03 (S3C2410_GPD2)
#define GPIO_LED03IN (S3C2410_GPD2_INP)
#define GPIO_LED03OU (S3C2410_GPD2_OUTP)
#define GPIO_LED04 (S3C2410_GPD3)
#define GPIO_LED04IN (S3C2410_GPD3_INP)
#define GPIO_LED04OU (S3C2410_GPD3_OUTP)
#define GPIO_LED05 (S3C2410_GPD4)
#define GPIO_LED05IN (S3C2410_GPD4_INP)
#define GPIO_LED05OU (S3C2410_GPD4_OUTP)
#define GPIO_LED06 (S3C2410_GPD5)
#define GPIO_LED06IN (S3C2410_GPD5_INP)
#define GPIO_LED06OU (S3C2410_GPD5_OUTP)
#endif
static void ledrpm_timer_handler(unsigned long data);
static int ledrpm_control(u32 command, u8 data);
static int ledrpm_open(struct inode *inode, struct file *filp);
static int ledrpm_release(struct inode *inode, struct file *filp);
static ssize_t ledrpm_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
static ssize_t ledrpm_read(struct file *file,char __user *buffer, size_t count, loff_t *ppos);
static int ledrpm_ioctl(struct inode *inode, struct file *filp, unsigned int command, unsigned long arg);
static const struct file_operations ledrpm_fops ={
.owner = THIS_MODULE,
.read = ledrpm_read,
.write = ledrpm_write,
.open = ledrpm_open,
.release = ledrpm_release,
.ioctl = ledrpm_ioctl,
};
static int ledrpm_control(u32 command, u8 data){
int err = 0;
if(command==0x01) { // write
switch(data) {
case 0x01: s3c2410_gpio_setpin(GPIO_LED01, LEDRPM_ON); break;
case 0x81: s3c2410_gpio_setpin(GPIO_LED01, LEDRPM_OFF); break;
case 0x02: s3c2410_gpio_setpin(GPIO_LED02, LEDRPM_ON); break;
case 0x82: s3c2410_gpio_setpin(GPIO_LED02, LEDRPM_OFF); break;
case 0x03: s3c2410_gpio_setpin(GPIO_LED03, LEDRPM_ON); break;
case 0x83: s3c2410_gpio_setpin(GPIO_LED03, LEDRPM_OFF); break;
case 0x04: s3c2410_gpio_setpin(GPIO_LED04, LEDRPM_ON); break;
case 0x84: s3c2410_gpio_setpin(GPIO_LED04, LEDRPM_OFF); break;
case 0x05: s3c2410_gpio_setpin(GPIO_LED05, LEDRPM_ON); break;
case 0x85: s3c2410_gpio_setpin(GPIO_LED05, LEDRPM_OFF); break;
case 0x06: s3c2410_gpio_setpin(GPIO_LED06, LEDRPM_ON); break;
case 0x86: s3c2410_gpio_setpin(GPIO_LED06, LEDRPM_OFF); break;
default: err = -1; break;
}
}else if(command==0x00) { // read
switch(data) {
case 0x01: err=s3c2410_gpio_getpin(GPIO_LED01); break;
case 0x02: err=s3c2410_gpio_getpin(GPIO_LED02); break;
case 0x03: err=s3c2410_gpio_getpin(GPIO_LED03); break;
case 0x04: err=s3c2410_gpio_getpin(GPIO_LED04); break;
case 0x05: err=s3c2410_gpio_getpin(GPIO_LED05); break;
case 0x06: err=s3c2410_gpio_getpin(GPIO_LED06); break;
default: err = -1; break;
}
}
return err;
}
static int ledrpm_open(struct inode *inode, struct file *filp){
filp->private_data = &ledrpm_dev;
PRINTK(KERN_NOTICE "ledrpm opened/n");
return 0;
}
static int ledrpm_release(struct inode *inode, struct file *filp){
PRINTK(KERN_NOTICE "ledrpm released/n");
return 0;
}
// 写参数为:count要写的灯数量,ppos为从第几个灯(小于灯数)开始写,
// buffer:要写的灯的数据:01-06亮81-86灭
static ssize_t ledrpm_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos){
u8 ledrpm_ret[LEDRPM_NUM];
int ri;
if (count>LEDRPM_NUM)
return -1;
copy_from_user(ledrpm_ret, buffer, count);
PRINTK(KERN_NOTICE "ledrpm write data count:%d/n",count);
for(ri=0; ri<count; ri++){
if(ledrpm_control(1, ledrpm_ret[ri])==-1)
return -1;
}
return count;
}
// 读函数带入参数: count:为读灯个数,要为LEDRPM_NUM; buffer:读回数据
// ppos:为从第一个灯算起第几个灯开始读。要为0。
static ssize_t ledrpm_read(struct file *filp,char __user *buffer, size_t count, loff_t *ppos){
u8 ledrpm_ret[LEDRPM_NUM];
int ri,rj;
if (count>LEDRPM_NUM)
return -1;
for(ri=0; ri<count; ri++){
rj=ledrpm_control(0, ri+1);
if (rj==-1) return -1;
ledrpm_ret[ri]=(rj ? 1: 0);
}
copy_to_user(buffer,(char*)&ledrpm_ret,count);
PRINTK(KERN_NOTICE "ledrpm read data count:%d/n",count);
return count;
}
static int ledrpm_ioctl(struct inode *inode, struct file *filp, unsigned int command, unsigned long arg){
return ledrpm_control(arg, command);
}
static void ledrpm_timer_handler(unsigned long data){
mod_timer(&ledrpm_dev.timer, jiffies+ LEDRPM_DELAYMS(500));
s3c2410_gpio_setpin(GPIO_LEDPOWER, (s3c2410_gpio_getpin(GPIO_LEDPOWER))?0:1);
}
static void ledrpm_init_config(void)
{
int result;
for (result=0; result<LEDRPM_NUM; result++){
s3c2410_gpio_cfgpin(ledrpm_info_tab[result].pin, ledrpm_info_tab[result].pin_setting);
s3c2410_gpio_setpin(ledrpm_info_tab[result].pin, ledrpm_info_tab[result].ledrpm_code);
}
s3c2410_gpio_cfgpin(GPIO_LEDPOWER, GPIO_LEDPOWER_OUTP);
init_timer(&ledrpm_dev.timer);
ledrpm_dev.timer.expires = jiffies + LEDRPM_DELAYMS(500);
ledrpm_dev.timer.function = ledrpm_timer_handler;
ledrpm_dev.timer.data = 0x00;
add_timer(&ledrpm_dev.timer);
}
static int __init ledrpm_init(void)
{
int result,err;
dev_t devno = MKDEV(ledrpm_major,0);
if (ledrpm_major) {
result = register_chrdev_region(devno, 1, DEVICE_NAME);
}else {
result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
ledrpm_major = MAJOR(devno);
}
if (result < 0) {
printk("ledrpm can't get major number:%d/n",result);
return result;
}
devno = MKDEV(ledrpm_major,0);
cdev_init((struct cdev *)&(ledrpm_dev.cdev),(struct file_operations *)&ledrpm_fops);
ledrpm_dev.cdev.owner = THIS_MODULE;
ledrpm_dev.cdev.ops = (struct file_operations *)&ledrpm_fops;
err = cdev_add(&ledrpm_dev.cdev, devno, 1);
if (err) {
printk(KERN_NOTICE "Error %d adding ledrpm fail",err);
return -1;
}
ledrpm_init_config();
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(ledrpm_major, 0), S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, DEVICE_NAME);
ledrpm_dev.devfs = devfs_register_tape(DEVICE_NAME);
#endif
printk(KERN_NOTICE "/dev/ledrpm inited: newkoom company:zhengmeifu@sina.com/n");
return 0;
}
static void __exit ledrpm_exit(void)
{
cdev_del(&ledrpm_dev.cdev);
unregister_chrdev_region(MKDEV(ledrpm_major,0),1);
#ifdef CONFIG_DEVFS_FS
devfs_remove(DEVICE_NAME);
devfs_unregister_tape(ledrpm_dev.devfs);
#endif
del_timer(&ledrpm_dev.timer);
}
module_init(ledrpm_init);
module_exit(ledrpm_exit);
MODULE_AUTHOR("zhengmeifu@sina.com");
MODULE_DESCRIPTION("RPM or (yls3c2410 devlp board) led driver");
MODULE_LICENSE("Dual BSD/GPL");