贴上一个s3c24402440的GPIO驱动源代码。可以实现对几个IO口的读写操作。写操作中,可以使用已经移植好的API接口函数如s3c2410_gpio_cfgpin等,可是读取函数使用s3c2410_gpio_getpin却不能正确读回IO的状态。后来改用了直接读取寄存器的方式,解决了这个问题。 /* gpio.c EPC's gpio driver. GUANGZHOU ZHIYUAN Copyright (c) 2006 GUANGZHOU ZHIYUAN ELECTRONICS CO.LTD By Chenxibing */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gpiodrv.h" #define DEV_NAME "gpio01" static struct semaphore gpio01_sem; static unsigned int GPIO01[4] = {S3C2410_GPG8, S3C2410_GPG9, S3C2410_GPG10, S3C2410_GPG11}; static unsigned int GPIO01_OUTP[4]= {S3C2410_GPG8_OUTP, S3C2410_GPG9_OUTP, \ S3C2410_GPG10_OUTP, S3C2410_GPG11_OUTP}; static unsigned int GPIO01_INP[4] = {S3C2410_GPG8_INP, S3C2410_GPG9_INP, \ S3C2410_GPG10_INP, S3C2410_GPG11_INP}; static int tp_gpio01_open(struct inode *inode, struct file *filp) { try_module_get(THIS_MODULE); printk( KERN_INFO DEV_NAME " opened!\n"); return 0; } static int tp_gpio01_release(struct inode *inode, struct file *filp) { module_put(THIS_MODULE); printk(KERN_INFO DEV_NAME " released!\n"); return 0; } static ssize_t tp_gpio01_read(struct file *filp, const char __user *buff, size_t count, loff_t *ppos) { unsigned char status=0; unsigned int temp, i; void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPG8); //unsigned long offs = S3C2410_GPIO_OFFSET(pin); if (count > 1) { return -EFBIG; } if (down_interruptible(&gpio01_sem)) return -ERESTARTSYS; #if 1//NOT OK for(i=0; i<4; i++) { s3c2410_gpio_cfgpin(GPIO01[i], GPIO01_INP[i]); s3c2410_gpio_pullup(GPIO01[i], 0); //enable pullup // status |= (s3c2410_gpio_getpin(GPIO01[i])< mdelay(10); } #endif status = (__raw_readl(base + 0x04)&0x0F00)>>8; printk("read data status = 0x%0x\n", status); put_user(status, (u8 *)buff); up(&gpio01_sem); return count; } static ssize_t tp_gpio01_write(struct file *filp, const char __user *buff, size_t count, loff_t *ppos) { int i; unsigned char ctrl=0; unsigned int set, clear; if (count > 1) { return -EFBIG; } if (down_interruptible(&gpio01_sem)) return -ERESTARTSYS; get_user(ctrl, (u8 *)buff); printk("write date ctrl=0x%0x\n", ctrl); for(i=0; i<4; i++) { s3c2410_gpio_cfgpin(GPIO01[i], GPIO01_OUTP[i]); s3c2410_gpio_pullup(GPIO01[i], 0); //enable pullup s3c2410_gpio_setpin(GPIO01[i], ((ctrl)>>i)&0x01); // printk("write %d %d\n", i, (((ctrl)>>i)&0x01)); mdelay(10); } up(&gpio01_sem); return count; } static int tp_gpio01_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int level; if (_IOC_TYPE(cmd) != GPIO_IOC_MAGIC) { return -ENOTTY; } if (_IOC_NR(cmd) >= GPIO_IOC_MAXNR) { return -ENOTTY; } if (arg > 7) { return -ENODEV; } // printk("arg=0x%x\n", arg); switch (cmd) { case GPIO_RESET_ALL: case GPIO_CLEAR_ALL: //tp_gpio01_reset(); break; case GPIO_SET_PIN_LOW: // GPCR(GPO[arg]) = GPIO_bit(GPO[arg]); break; case GPIO_SET_PIN_HIGH: // GPSR(GPO[arg]) = GPIO_bit(GPO[arg]); break; default: //tp_gpio01_reset(); break; } return 0; } static struct file_operations tp_gpio01_fops = { .owner = THIS_MODULE, .read = tp_gpio01_read, .write = tp_gpio01_write, .ioctl = tp_gpio01_ioctl, .open = tp_gpio01_open, .release = tp_gpio01_release, }; static struct miscdevice tp_gpio01_miscdev = { .minor = MISC_DYNAMIC_MINOR, .name = DEV_NAME, .fops = &tp_gpio01_fops, }; static int tp_gpio01_probe(struct device *dev) { int ret; printk(KERN_INFO DEV_NAME " probing...\n"); ret = misc_register(&tp_gpio01_miscdev); if (ret) printk(KERN_ERR "Failed to register miscdev.\n"); return ret; } static int tp_gpio01_remove(struct device *dev) { misc_deregister(&tp_gpio01_miscdev); printk(KERN_INFO DEV_NAME " removed!\n"); return 0; } struct platform_device *tp_gpio01_device; static struct device_driver tp_gpio01_driver = { .name = DEV_NAME, .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = tp_gpio01_probe, .remove = tp_gpio01_remove, }; static int __init tp_gpio01_init(void) { int rc = 0; int i; printk(KERN_INFO DEV_NAME " init...\n"); for(i=0; i<4; i++) { s3c2410_gpio_cfgpin(GPIO01[i], GPIO01_OUTP[i]); s3c2410_gpio_pullup(GPIO01[i], 0); //enable pullup s3c2410_gpio_setpin(GPIO01[i], 1); //default all HIGH } tp_gpio01_device = platform_device_register_simple(DEV_NAME, -1, NULL, 0); if(IS_ERR(tp_gpio01_device)) { goto out; } rc = driver_register(&tp_gpio01_driver); if (rc < 0) { platform_device_unregister(tp_gpio01_device); } sema_init(&gpio01_sem, 1); out: return rc; } static void __exit tp_gpio01_exit(void) { printk(KERN_INFO DEV_NAME " init...\n"); driver_unregister(&tp_gpio01_driver); platform_device_unregister(tp_gpio01_device); printk(KERN_INFO "tp_gpio01 exit!\n"); } module_init(tp_gpio01_init); module_exit(tp_gpio01_exit); MODULE_AUTHOR("Abing MODULE_DESCRIPTION("ZHIYUAN epc-gpio Driver"); MODULE_LICENSE("GPL"); |