#include <linux/config.h>
#include <linux/init.h>
//#include <kernel.h>
#include <asm/hardware.h>
#include <asm/leds.h>
#include <asm/system.h>
#include <asm/arch/smdk.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#include <asm/arch/smdk.h>
#include <asm/arch/S3C2440.h>
#define LED0 (1 << 0)
#define LED1 (1 << 1)
#define LED2 (1 << 2)
#define LED3 (1 << 3)
#define __NO_VERSION__
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif
#define DEVICE_NAME "gpio_driv"
#define IOPORT_MAJOR 100 //定义主设备号,和前面的mknod/dev/gpiotestc 220 0匹配
#define GPIO_A_CON 0x56000000
#define GPIO_A_DAT 0x56000004
#define GPIO_B_CON 0x56000010
#define GPIO_B_DAT 0x56000014
#define GPIO_B_PUP 0x56000018
#define GPIO_C_CON 0x56000020
#define GPIO_C_DAT 0x56000024
#define GPIO_C_PUP 0x56000028
#define GPIO_D_CON 0x56000030
#define GPIO_D_DAT 0x56000034
#define GPIO_D_PUP 0x56000038
#define GPIO_E_CON 0x56000040
#define GPIO_E_DAT 0x56000044
#define GPIO_E_PUP 0x56000048
#define GPIO_F_CON 0x56000050
#define GPIO_F_DAT 0x56000054
#define GPIO_F_PUP 0x56000058
#define GPIO_G_CON 0x56000060
#define GPIO_G_DAT 0x56000064
#define GPIO_G_PUP 0x56000068
#define GPIO_H_CON 0x56000070
#define GPIO_H_DAT 0x56000074
#define GPIO_H_PUP 0x56000078
#define GPIO_J_CON 0x56000080
#define GPIO_J_DAT 0x56000084
#define GPIO_J_PUP 0x56000088
static int gpio_open(struct inode*, struct file *);
static int gpio_release(struct inode*, struct file *);
static int gpio_ioctl(struct inode *, struct file *, unsigned int intcommand, unsigned long arg);
static int gpio_read(struct file *file,
char *buffer, /* The buffer to fill with data
*/ size_t length, /* The length of the buffer */
loff_t * offset); /* Our offset in the file */
static int gpio_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what);
char kernel_version [] = UTS_RELEASE;
static struct file_operations gpio_ctl_fops=
{ ioctl: gpio_ioctl,
read: gpio_read,
write:gpio_write,
open: gpio_open,
release: gpio_release,
};
static int gpio_open(struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
printk ("device_open(%p,%p)\n", inode, file);
/*
* Get major / minor numbers when needed
*/
printk ("Device: %d.%d\n", inode->i_rdev >> 8, inode->i_rdev & 0xFF);
return 0;
}
static int gpio_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int gpio_ioctl(struct inode*inode,struct file *flip,unsigned intcommand,unsigned long arg)
{
return 0;
}
static int gpio_read(struct file *file,
char *buffer, /*buffer[0-3]=addr buffer[4-7]= bit */
size_t length,
loff_t * offset)
{
unsigned long templong,tempcon,tmpold;
unsigned char i;
int bit,GPIOAddr,GPIOData,temp_gdata[8];
for(i=0;i<8;i++)
temp_gdata[i]=(int)buffer[i];
GPIOAddr=temp_gdata[0]+temp_gdata[1]*256+temp_gdata[2]*256*256+temp_gdata[3]*256*256*256;
GPIOData=temp_gdata[4]+temp_gdata[5]*256+temp_gdata[6]*256*256+temp_gdata[7]*256*256*256;
// printk("\n GPIOAddr=%x GPIOData=%x", GPIOAddr,GPIOData);
tempcon=*((volatile unsigned long *)io_p2v(GPIOAddr ));
tmpold=tempcon;
if (length&0x8)
{
printk("CON is %x,DAT is %x, PULL is %x\n",
*((volatile unsigned long *)io_p2v( GPIOAddr )),
*((volatile unsigned long *)io_p2v( GPIOAddr+4)),
*((volatile unsigned long *)io_p2v( GPIOAddr+8)));
return 0;
}
if (length&0x2) //about set pullup, 1 set, 0 disable
{
switch(length&0x1)
{
case 1:
templong= *((volatile unsigned long *)io_p2v( GPIOAddr+8));
*((volatile unsigned long *)io_p2v(GPIOAddr+8 ))=templong|(1<<GPIOData); //GP DAT =1
break;
case 0:
templong= *((volatile unsigned long *)io_p2v(GPIOAddr+8 ));
*((volatile unsigned long *)io_p2v(GPIOAddr+8 ))=templong&(~(1<<GPIOData)); //GP DAT = 0
break;
default: break;
}
return 0;
}
*((volatile unsigned long *)io_p2v(GPIOAddr))=tempcon&(~(3<<(GPIOData*2))); // GP CON = 00 as input
templong= *((volatile unsigned long *)io_p2v( GPIOAddr+4));
if((templong&(1<<GPIOData))!=0)
bit=1;
else
bit=0;
// printk("\nGPIOData=%x GPIO con=%x", GPIOData,*((volatile unsigned long *)io_p2v(GPIOAddr)));
if (length&0x4)
*((volatile unsigned long *)io_p2v(GPIOAddr))=tmpold; // Keep CON IO as before
return bit;
}
static int gpio_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what)
{
unsigned long templong,tempcon,tmpold;
unsigned char i;
int GPIOAddr,GPIOData,temp_gdata[8];
for(i=0;i<8;i++)
temp_gdata[i]=(int)gdata[i];
GPIOAddr=temp_gdata[0]+temp_gdata[1]*256+temp_gdata[2]*256*256+temp_gdata[3]*256*256*256;
GPIOData=temp_gdata[4]+temp_gdata[5]*256+temp_gdata[6]*256*256+temp_gdata[7]*256*256*256;
// printk("\n GPIOAddr=%x GPIOData=%x", GPIOAddr,GPIOData);
tempcon=*((volatile unsigned long *)io_p2v(GPIOAddr ));
tmpold=tempcon;
if (length&0x4) //about set function11
{
*((volatile unsigned long *)io_p2v(GPIOAddr))=tempcon|((3<<(GPIOData*2))); // GP CON = 11 as FUNCTION2
return 0;
}
if (length&0x2) //about set function10
{
*((volatile unsigned long *)io_p2v(GPIOAddr))=tempcon&(~(1<<(GPIOData*2))); // GP CON = 10 as FUNCTION1
tempcon=*((volatile unsigned long *)io_p2v(GPIOAddr ));
*((volatile unsigned long *)io_p2v(GPIOAddr))=tempcon|((1<<(GPIOData*2+1))); // GP CON = 10 as FUNCTION1
return 0;
}
*((volatile unsigned long *)io_p2v(GPIOAddr))=tempcon&(~(1<<(GPIOData*2+1))); // GP CON = 01 as output
tempcon=*((volatile unsigned long *)io_p2v(GPIOAddr ));
*((volatile unsigned long *)io_p2v(GPIOAddr))=tempcon|((1<<(GPIOData*2))); // GP CON = 01 as output
switch(length&0x1)
{
case 1:
templong= *((volatile unsigned long *)io_p2v( GPIOAddr+4));
*((volatile unsigned long *)io_p2v(GPIOAddr+4 ))=templong|(1<<GPIOData); //GP DAT =1
// printk("Write gpio %d\n",length);
break;
case 0:
templong= *((volatile unsigned long *)io_p2v(GPIOAddr+4 ));
*((volatile unsigned long *)io_p2v(GPIOAddr+4 ))=templong&(~(1<<GPIOData)); //GP DAT = 0
// printk(" Write gpio %d\n",length);
break;
default: break;
}
// if (length&0x4)
// *((volatile unsigned long *)io_p2v(GPIOAddr))=tmpold; // Keep CON IO as before
return 0;
}