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<