www.pudn.com > s3c2440_gpio.c.rar > s3c2440_gpio.c



 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  
#include 
#include 	//定义/proc下模块版本信息相关变量

#define DEBUG
#ifdef DEBUG
#define DBG(arg... )	printk( "\t" ##arg )
#else
#define DBG(args...)
#endif

#define DRIVER_VERSION 		"0.02"
#define DRIVER_AUTHOR 		"Siki "
#define STELCOM_DEV_DIR 		"ee100"
#define DRIVER_DESC			" GPIO control Driver"
#define DEVICE_NAME			"gpio"
#define DEVICE_MAJOR 		0

#ifdef CONFIG_PROC_MODVERSION
static int stel_proc_read(char *buf, char **start, off_t off,
			    int count, int *eof, void *data);
static struct stelproc_entry stel = {
	"stel_gpio",	stel_proc_read , DRIVER_VERSION
};
static char 	proc_name[50];
#endif	/* CONFIG_PROC_MODVERSION */

/* ioctl number, NR */
/* ioctl contain 4 bytes.The content from lower to higer bit is:
 *   Nr(8 bits), Type(8 bits), Size(14 bits), Direction(2 bits) for arm architeture
 * In this source, Nr decides the GPIO to be controled in ioctl,Type=GPIO_IOC_MAGIC, 
 *   Size=1, Direction shows whether to read data from userspace or to write data
 *   to userspace.
 * Nr must only be one of below:
 *   GPA0~GPA24:0-24
 *   GPB0~GPB15:25-40
 *   GPC0~GPC15:41-56
 *   GPD0~GPD15:57-72
 *   GPE0~GPE15:73-88
 *   GPF0~GPF15:89-104
 *   GPG0~GPG15:105-120
 *   GPH0~GPH15:121-136
 *   GPJ0~GPJ15:137-152
 *
 * Attention: change the GPIO output may result in crash of the system.Be careful!!!!
 */
#define GPIO_IOC_MAGIC		0xB4
#define GPIO_IOC_MAXNR 		152

static int 	gpio_major, gpio_opened = 0;
static 	devfs_handle_t 	devfs_handle, devfs_dir_handle;

static int gpio_open(struct inode *inode, struct file *file)
{	
	DBG("Open the gpio driver...\n");

	MOD_INC_USE_COUNT;
	gpio_opened = 1;
	
	return 0;
}

static int gpio_close(struct inode *inode, struct file *filp)
{
	DBG("Close the gpio driver...\n");

	if( gpio_opened == 0 ) {
		printk("The gpio driver hasn't opened!\n");
		return 0;
	}	
	MOD_DEC_USE_COUNT;
	gpio_opened = 0;
	
	return 0;
}

static int gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	int 	err = 0, dir, tmp, port, nr;//port and nr to specify the GPIO.for example, GPA2:port=0,nr=2
	u32		tmp2, value = 0;
	char	from, to;
	int 	retval = 0;
    
	/*
	 * extract the type and number bitfields, and don't decode
	 * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
	 */
	if (_IOC_TYPE(cmd) != GPIO_IOC_MAGIC) return -ENOTTY;
	if (_IOC_NR(cmd) > GPIO_IOC_MAXNR) return -ENOTTY;

	/*
	 * the direction is a bitmask, and VERIFY_WRITE catches R/W
	 * transfers. `Type' is user-oriented, while
	 * access_ok is kernel-oriented, so the concept of "read" and
	 * "write" is reversed
	 */
	if (_IOC_DIR(cmd) & _IOC_READ)
		err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
	else if (_IOC_DIR(cmd) & _IOC_WRITE)
		err =  !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
	if (err) return -EFAULT;

    	dir = _IOC_DIR(cmd);
	tmp = _IOC_NR(cmd);
	if(tmp < 25) {
		port = 0;
		nr = tmp;
	}
	else {
		port = (tmp-25)/16 + 1;
		nr = (tmp-25) % 16;
	}	
	DBG("cmd is 0x%x.\n",cmd);
	DBG("dir is %d.\n",dir);
	DBG("port is %d.\n",port);
	DBG("nr is %d.\n",nr);
	switch(dir) {
	  case _IOC_READ:
	  	DBG("Enter the IOC_READ.\n");
	  	if(port == 0) {	//GPA
			DBG("sikinzen1.\n");			
			GPACON &= (0xffffffff^(0x00000001<>= nr;	
			DBG("GPA:value is 0x%x.\n", value);
	  	}
		else if(port == 8) {	//GPJ
		    	tmp2 = GPJCON;
			tmp2 |= (0x00000003<<(2*nr));
			tmp2 &= (0xffffffff^(0x00000002<<(2*nr)));
			GPJCON = tmp2;
			value = GPJDAT & (0x00000001<>= nr;	
			DBG("GPJ:value is 0x%x.\n", value);
		}
		else { //GPB ~ GPH
			tmp = port*0x10;
			tmp2 = bGPIO(tmp);
			tmp2 |= (0x00000003<<(2*nr));
			tmp2 &= (0xffffffff^(0x00000002<<(2*nr)));
			bGPIO(tmp) = tmp2;
			value = bGPIO(tmp+4) & (0x00000001<>= nr;
			DBG("GPB ~ GPH:value is 0x%x.\n", value);
		}
		from = value;		
		DBG("Data read is %d.\n", from);
		put_user(from, (char *)arg);
		break;		
				
	  case _IOC_WRITE:
	  	DBG("Enter the IOC_WRITE.\n");
	  	get_user(to, (char *)arg);
		value = to;
		DBG("Data to be write is 0x%x.\n", value);
		if((value != 0) &&(value != 1)) {
			printk("The data write to I/O is wrong!\n");
			return -1;
    		}
		value <<= nr;
		DBG("Value is:0x%x.\n", value);
		if(port == 0) {	//GPA
			DBG("sikinzen1.\n");			
			GPACON &= (0xffffffff^(0x00000001<