Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1259895
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类:

2011-12-09 21:00:37

原文地址:GPIO驱动 作者:chenxibing008

GPIO Drivers



 贴上一个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");
阅读(455) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~