⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 led-edukit-s3c2410.c

📁 s3c2410 LED的驱动程序代码
💻 C
字号:
/*
* linux/derivers/led/led-edukit-s3c2410.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 <linux/proc_fs.h>
#include <asm/uaccess.h>	// to copy to/from userspace
#include <asm/hardware.h>#include <asm/arch-s3c2410/s3c2410.h>
#include <asm/leds.h>

#ifdef	LED_DEBUG	// if want to debug, define it while compile this function
#define DEBUG(str, args...)	printk("led: " str, ## args)
#else
#define DEBUG(str, args...)
#endif

#undef u32
#define u32	unsigned

static int nLedMajor = 0;						/* allow to alloc the major number for led*/
#define LED_DEVNAME "led"

#define GPF_MASK	(0xF<<4)					/* GPF4-7: LED1-LED4 */
#define GET_DATA(f) ((u8)(~f>>4))
#define SET_DATA(t, f) ( f = (~t&0x0F)<<4 )

#define LED_LOCK(u)		down(&u->lock);
#define LED_UNLOCK(u)	up(&u->lock);

#define GPF_CTL_BASE		  io_p2v(0x56000050)/* get the virtual address map to GPF */
#define S3C2410_GPFCON       (GPF_CTL_BASE + 0x0)
#define S3C2410_GPFDAT       (GPF_CTL_BASE + 0x4)
#define S3C2410_GPFUP        (GPF_CTL_BASE + 0x8)

unsigned long flags;
static char *version = "Embest EdukitII-2410 led driver version 1.0 (2005-06-18) <www.embedinfo.com>\n";

struct unit {
	struct semaphore lock;
	u32 *GPF_CON;	/* GPFCON register */
	u32 *GPF_DAT;	/* GPFDAT register */
	u32 *GPF_UP;	/* GPFUP register */
	u32 f;			/* LEDs value (bit4-7:LED1-LED4)*/
};
static struct unit led_unit = {
	.GPF_CON		= (u32 *)S3C2410_GPFCON,
	.GPF_DAT		= (u32 *)S3C2410_GPFDAT,
	.GPF_UP			= (u32 *)S3C2410_GPFUP,
	.f				= 0x00 // turn on all LEDs
};


#ifdef CONFIG_PROC_FS
static int led_proc(char *page, char **start, off_t off,
                         int count, int *eof, void *data)
{
	char *p = page;
	int len;
	struct unit led_u;
	
	len = led_u.f;
	
	p += sprintf(p, "%s\n LED1: %s LED2: %s LED3: %s LED4: %s \n", version,
				 len&(1<<4)?"ON":"OFF",
				 len&(1<<5)?"ON":"OFF",
				 len&(1<<6)?"ON":"OFF",
				 len&(1<<7)?"ON":"OFF"
		     );

	len = (p - page) - off;
	if (len < 0)
		len = 0;

	*eof = (len <= count) ? 1 : 0;
	*start = page + off;

	return len;
}
#endif


static void led_set_value(struct unit *unit, u8 val)
{
	u32 temp;

	SET_DATA(val, unit->f);
	
	temp = *unit->GPF_DAT;
	temp &= ~GPF_MASK;
	temp |= unit->f;
	*unit->GPF_DAT = temp;
	DEBUG("write to GPFDAT:0x%x.\n", temp);
}
static u8 led_get_value(struct unit *unit)
{
	u8 temp = GET_DATA(unit->f);

	return temp;
}


static int led_open(struct inode *inode, struct file *file)
{
	DEBUG("open\n");

	leds_event(led_stop);
	file->private_data = &led_unit;
	MOD_INC_USE_COUNT;

	return 0;
}

static int led_release_f(struct inode *inode, struct file *file)
{
	DEBUG("release\n");
	MOD_DEC_USE_COUNT;

	leds_event(led_start);
	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;

	DEBUG("read\n");
	if(count > 1)
		count = 1;
	LED_LOCK(unit);
	temp = led_get_value(unit);
	DEBUG("Read from unit value field:0x%x.\n", temp);
	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;
	char *tmp;
	struct unit *unit = (struct unit *)file->private_data;

	DEBUG("write\n");
	
	if(count > 1)
		count = 1;
	LED_LOCK(unit);
	ret = copy_from_user(&temp, buf, count) ? -EFAULT : count;
	DEBUG("led0 writing %d bytes:0x%x.\n", ret,temp);
	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_f,
};


/*
* 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->GPF_CON;
	temp &= ~(0xF<<4);
	temp |= ((1<<14) | (1<<12) | (1<<10) | (1<<8));// GPF4,5,6,7 as Output
	*unit->GPF_CON = temp;

	temp = *unit->GPF_UP;
	temp |= (0xF<<8);// pull up all GPF4,5,6,7
	*unit->GPF_UP = temp;
	
	/* init data and turn on led, bit0-3:LED1-4*/
	led_set_value(unit, 0x0f);

	/* delay some time */
	mdelay(100);

	/* turn off led */
	led_set_value(unit, 0x00);
}


/*
* module init
*/
static devfs_handle_t devfs_handle,devfs_led_dir;
#ifdef MODULE
int init_module(void)
#else
int __init led_init_module(void)
#endif
{
	int res;

	DEBUG("init_module\n");
	/* print version information */
	printk(KERN_INFO "%s", version);

	/* register led device, character device: /proc/devices*/
#ifdef CONFIG_DEVFS_FS
	res = devfs_register_chrdev(0, LED_DEVNAME, &led_ops);
	if(res < 0) {
		printk("led-edukit-s3c2410.o: unable to get major for led device.\n");
		return res;
	}

	/* create the devfs: /driver/led/0 */
	devfs_led_dir = devfs_mk_dir(NULL, LED_DEVNAME, NULL);
	devfs_handle = devfs_register(devfs_led_dir, "0", DEVFS_FL_DEFAULT,
				      res, 0,S_IFCHR | S_IRUSR | S_IWUSR,&led_ops, NULL);   
#else
	res = register_chrdev(nLedMajor, LED_DEVNAME, &led_ops);
#endif

	/* add a profile to /proc/driver/led */
#ifdef CONFIG_PROC_FS
	create_proc_read_entry ("driver/led", 0, 0, led_proc, NULL);
#endif

	/* get the major number */
	if( nLedMajor == 0 )
	{
		nLedMajor = res;
		printk("Led major number = %d\n",nLedMajor);
	}

	/* then call led_init() */
	led_init(&led_unit);

	return 0;
}


/*
* module cleanup
*/
#ifdef MODULE
void cleanup_module(void)
#else
void __exit led_cleanup(void)
#endif
{
	int res;

	DEBUG("cleanup\n");
	/* unregister led device */
	res = unregister_chrdev(nLedMajor, LED_DEVNAME);
	if(res < 0)
		printk("led-edukit-s3c2410.o: unable to release major %d for led device.\n", nLedMajor);

#ifdef CONFIG_DEVFS_FS	
	devfs_unregister(devfs_handle);
	devfs_unregister(devfs_led_dir);
#endif	

	/* remove the profile /proc/driver/led */
#ifdef CONFIG_PROC_FS
	remove_proc_entry("driver/led", NULL);
#endif	
}

#ifndef MODULE
/* declare a module init entry */
module_init(led_init_module);
/* declare a module exit entry */
module_exit(led_cleanup);
#endif

MODULE_DESCRIPTION("EduKitII-2410 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 + -